[Odin] Odin Plotting with Raylib[Odin] Odin Plotting with Raylib

☠️

X Marks the Spot

Week 2, 2026

// - use "odin run ." to run the code // - input.txt should be nearby with the input data // - map.jpg should be nearby package main import "core:fmt" import "core:strconv" import "core:strings" import rl "vendor:raylib" input_txt_bytes := #load("input.txt") map_jpg_bytes := #load("map.jpg") main :: proc () { rl.SetTraceLogLevel(.WARNING) rl.SetConfigFlags({ .VSYNC_HINT }) map_img := rl.LoadImageFromMemory(".jpg", raw_data(map_jpg_bytes), i32(len(map_jpg_bytes))) rl.InitWindow(map_img.width, map_img.height, "week2") defer rl.CloseWindow() map_tex := rl.LoadTextureFromImage(map_img) rl.UnloadImage(map_img) defer rl.UnloadTexture(map_tex) path_tex, path_map_origin := plot() path_tex_center := [2] f32 { f32(path_tex.width/2), f32(path_tex.height/2) } defer rl.UnloadTexture(path_tex) path_tex_top_left: [2] f32 is_align_mode := true for !rl.WindowShouldClose() { if rl.IsMouseButtonPressed(.LEFT) do is_align_mode ~= true mouse_pos := rl.GetMousePosition() mouse_pos_map := [2] f32 { path_map_origin.x - path_tex_top_left.x + mouse_pos.x, path_map_origin.y + path_tex_top_left.y - mouse_pos.y, } if is_align_mode { path_tex_top_left = mouse_pos - path_tex_center } rl.BeginDrawing() rl.DrawTexture(map_tex, 0, 0, rl.WHITE) rl.DrawTextureV(path_tex, path_tex_top_left, rl.WHITE) hint_cstr := fmt.ctprintf( "1. Align start of the path with the ship\n" + "2. Click with LMB to toggle Align Mode [%s]\n" + "3. Mouse over the cross in the path to see coordinates %v of the treasure", is_align_mode ? "ON" : "OFF", mouse_pos_map, ) rl.DrawText(hint_cstr, 20+1, 20+2, 20, rl.BLACK) rl.DrawText(hint_cstr, 20, 20, 20, rl.YELLOW) rl.EndDrawing() free_all(context.temp_allocator) } } plot :: proc () -> (path_tex: rl.Texture, path_map_origin: [2] f32) { context.allocator = context.temp_allocator path_img := rl.GenImageColor(4000, 4000, {0,0,0,100}) path_off := [2] i32 { path_img.width/2, path_img.height/2 } path_pos := path_off path_box := struct { left, right, top, bottom: i32 } { left = path_pos.x, right = path_pos.x, top = path_pos.y, bottom = path_pos.y, } input := strings.trim(string(input_txt_bytes), "\n\t ") entries := strings.split(input, " ") last_pos: [2] i32 #reverse for entry in entries { values := strings.split(entry, ",") assert(len(values) == 2) v1_str, v2_str := values[0], values[1] if v1_str[0]!='N' && v1_str[0]!='S' { x, x_ok := strconv.parse_f32(v1_str) y, y_ok := strconv.parse_f32(v2_str) assert(x_ok && y_ok) assert(last_pos == {}, "last pos already set") last_pos = { i32(x), i32(y) } continue } for v in values { dist, dist_ok := strconv.parse_int(v[1:], base=10) assert(dist_ok) if dist != 0 { dir: [2] i32 switch v[0] { case 'N': dir = {0,+1} case 'S': dir = {0,-1} case 'W': dir = {+1,0} case 'E': dir = {-1,0} case : panic("unexpected direction") } path_pos += dir * i32(dist) } } assert(path_pos.x>=0 && path_pos.x=0 && path_pos.y