first commit
This commit is contained in:
commit
c2142436b9
10 changed files with 174 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
converter*
|
||||
viewer*
|
2
build.bat
Normal file
2
build.bat
Normal file
|
@ -0,0 +1,2 @@
|
|||
odin build . -out:converter
|
||||
odin build . -out:viewer -define:MAKE_CONVERTER=false
|
2
build.sh
Executable file
2
build.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
odin build . -out:converter
|
||||
odin build . -out:viewer -define:MAKE_CONVERTER=false
|
BIN
kiva.sand
Normal file
BIN
kiva.sand
Normal file
Binary file not shown.
163
main.odin
Normal file
163
main.odin
Normal file
|
@ -0,0 +1,163 @@
|
|||
package main
|
||||
|
||||
import "core:encoding/cbor"
|
||||
import "core:fmt"
|
||||
import "core:image/png"
|
||||
import "core:math/rand"
|
||||
import "core:os"
|
||||
import "core:strings"
|
||||
import "core:time"
|
||||
import rl "vendor:raylib"
|
||||
|
||||
MAKE_CONVERTER :: #config(MAKE_CONVERTER, true)
|
||||
|
||||
Pixel :: struct {
|
||||
id: int,
|
||||
pos: rl.Vector2,
|
||||
already_moved: bool,
|
||||
color: rl.Color,
|
||||
}
|
||||
|
||||
State :: struct {
|
||||
seed: u64,
|
||||
colors: map[int]rl.Color,
|
||||
}
|
||||
state: State
|
||||
|
||||
SIZE :: 800
|
||||
SCALE :: 20
|
||||
DIVIDED :: SIZE / SCALE
|
||||
pixels: [dynamic]Pixel
|
||||
|
||||
get_pixel :: proc(pos: rl.Vector2) -> Maybe(^Pixel) {
|
||||
for &pixel in pixels {
|
||||
if pixel.pos == pos {
|
||||
return &pixel
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
is_finished :: proc() -> bool {
|
||||
return len(pixels) >= DIVIDED * DIVIDED
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
rl.SetTraceLogLevel(.ERROR)
|
||||
|
||||
when MAKE_CONVERTER {
|
||||
if len(os.args) < 3 {
|
||||
fmt.eprintln("Please provide input and output filenames!")
|
||||
return
|
||||
}
|
||||
|
||||
state.seed = u64(time.time_to_unix(time.now()))
|
||||
rand.reset(state.seed)
|
||||
rl.SetConfigFlags({.WINDOW_HIDDEN})
|
||||
fmt.println("Beginning conversion...")
|
||||
} else {
|
||||
if len(os.args) < 2 {
|
||||
fmt.eprintln("Please provide a sand image!")
|
||||
return
|
||||
}
|
||||
|
||||
bytes, err := os.read_entire_file_or_err(os.args[1])
|
||||
if err != nil {
|
||||
fmt.eprintln("Failed to read sand image:", err)
|
||||
return
|
||||
}
|
||||
unmarshal_err := cbor.unmarshal(string(bytes), &state)
|
||||
if unmarshal_err != nil {
|
||||
fmt.eprintln("Failed to unmarshal sand image:", unmarshal_err)
|
||||
}
|
||||
rand.reset(state.seed)
|
||||
}
|
||||
|
||||
rl.InitWindow(SIZE, SIZE, strings.clone_to_cstring(os.args[1]))
|
||||
when MAKE_CONVERTER {
|
||||
img := rl.LoadImage(strings.clone_to_cstring(os.args[1]))
|
||||
rl.ImageResize(&img, DIVIDED, DIVIDED)
|
||||
} else {
|
||||
rl.SetTargetFPS(120)
|
||||
}
|
||||
|
||||
for !rl.WindowShouldClose() {
|
||||
for &pixel in pixels {
|
||||
pixel.already_moved = false
|
||||
}
|
||||
|
||||
if !is_finished() {
|
||||
pos := rl.Vector2{f32(rand.int_max(DIVIDED)), 0}
|
||||
if _, found := get_pixel(pos).?; !found {
|
||||
color: rl.Color
|
||||
id := len(pixels)
|
||||
when !MAKE_CONVERTER {
|
||||
color = state.colors[id]
|
||||
}
|
||||
append(&pixels, Pixel{id = id, pos = pos, color = color})
|
||||
}
|
||||
}
|
||||
|
||||
when !MAKE_CONVERTER {
|
||||
rl.BeginDrawing()
|
||||
rl.ClearBackground(rl.BLACK)
|
||||
}
|
||||
for &pixel in pixels {
|
||||
when !MAKE_CONVERTER {
|
||||
rl.DrawRectangleV(pixel.pos * SCALE, {SCALE, SCALE}, pixel.color)
|
||||
}
|
||||
|
||||
if pixel.already_moved do continue
|
||||
if pixel.pos.y >= DIVIDED - 1 do continue
|
||||
|
||||
down := pixel.pos + {0, 1}
|
||||
left := pixel.pos + {-1, 1}
|
||||
right := pixel.pos + {1, 1}
|
||||
if _, found := get_pixel(down).?; !found {
|
||||
pixel.pos = down
|
||||
pixel.already_moved = true
|
||||
} else if _, found := get_pixel(left).?; !found {
|
||||
if pixel.pos.x > 0 {
|
||||
pixel.pos = left
|
||||
pixel.already_moved = true
|
||||
}
|
||||
}
|
||||
|
||||
if _, found := get_pixel(right).?; !found && !pixel.already_moved {
|
||||
if pixel.pos.x >= DIVIDED - 1 do continue
|
||||
pixel.pos = right
|
||||
}
|
||||
}
|
||||
when !MAKE_CONVERTER {
|
||||
rl.EndDrawing()
|
||||
}
|
||||
|
||||
when MAKE_CONVERTER {
|
||||
if is_finished() {
|
||||
for x in 0 ..< DIVIDED {
|
||||
for y in 0 ..< DIVIDED {
|
||||
pixel := get_pixel(rl.Vector2{f32(x), f32(y)}).?
|
||||
color := rl.GetImageColor(img, i32(x), i32(y))
|
||||
pixel.color = color
|
||||
state.colors[pixel.id] = color
|
||||
}
|
||||
}
|
||||
|
||||
bytes, err := cbor.marshal(state)
|
||||
if err != nil {
|
||||
fmt.eprintln("Failed to marshal sand image:", err)
|
||||
return
|
||||
}
|
||||
write_err := os.write_entire_file_or_err(os.args[2], bytes)
|
||||
if write_err != nil {
|
||||
fmt.eprintln("Failed to write sand image:", write_err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.println("Conversion complete")
|
||||
rl.CloseWindow()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
BIN
mathew.sand
Normal file
BIN
mathew.sand
Normal file
Binary file not shown.
5
odinfmt.json
Normal file
5
odinfmt.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"character_width": 110,
|
||||
"tabs": false,
|
||||
"tabs_width": 4
|
||||
}
|
BIN
out.sand
Normal file
BIN
out.sand
Normal file
Binary file not shown.
BIN
rose.sand
Normal file
BIN
rose.sand
Normal file
Binary file not shown.
BIN
sam.sand
Normal file
BIN
sam.sand
Normal file
Binary file not shown.
Loading…
Add table
Reference in a new issue