let () = Random.self_init () module Map = struct type background = | Grass | Water | Black let width = 1000 let height = 1000 let player_pos = ref (20, 3) let m = Array.init width (fun _x -> Array.init height (fun _y -> if Random.int 1000 <= 42 then Water else Grass ) ) let get_tile_kind ~x ~y = try m.(x).(y) with Invalid_argument _ -> Black end open Brr open Brr_canvas let get_el id = match Document.find_el_by_id G.document (Jstr.of_string id) with | None -> failwith (Format.sprintf {|Could not find element by id: "%s"|} id) | Some el -> el let tile_size = 40 let width = 835 let height = 635 let canvas = let el = get_el "canvas" in Canvas.of_el el let context = C2d.get_context canvas let init_bg () = Canvas.set_w canvas width; Canvas.set_h canvas height; C2d.set_fill_style context (C2d.color (Jstr.v "#FF1188")); C2d.fill_rect context ~x:0. ~y:0. ~w:(float_of_int width) ~h:(float_of_int height) let tiles_per_w = width / tile_size let tiles_per_h = height / tile_size let orig_x = (width - (tiles_per_w * tile_size)) / 2 let orig_y = (height - (tiles_per_h * tile_size)) / 2 let grass = C2d.image_src_of_el (get_el "grass") let papy_bottom = C2d.image_src_of_el (get_el "papy_bottom") let water = C2d.image_src_of_el (get_el "water") let draw_map _timestamp = let player_x, player_y = !Map.player_pos in Format.printf "player_x = %d@\nplayer_y = %d@\n" player_x player_y; for x = 0 to tiles_per_w - 1 do let mapx = x + player_x - (tiles_per_w / 2) in for y = 0 to tiles_per_h - 1 do let mapy = y + player_y - (tiles_per_h / 2) in let tile_img = match Map.get_tile_kind ~x:mapx ~y:mapy with | Grass -> grass | Water -> water | Black -> water in C2d.draw_image context tile_img ~x:(float_of_int (orig_x + (x * tile_size))) ~y:(float_of_int (orig_y + (y * tile_size))) done done; C2d.draw_image context papy_bottom ~x:(float_of_int (width / 2)) ~y:(float_of_int (height / 2)) let kb_handler ev = let x, y = !Map.player_pos in let x, y = match ev |> Ev.as_type |> Ev.Keyboard.code |> Jstr.to_string with | "KeyW" | "ArrowUp" -> (x, y - 1) | "KeyA" | "ArrowLeft" -> (x - 1, y) | "KeyS" | "ArrowDown" -> (x, y + 1) | "KeyD" | "ArrowRight" -> (x + 1, y) | _s -> (x, y) in let x = max 0 x in let x = min (Map.width - 1) x in let y = max 0 y in let y = min (Map.height - 1) y in Map.player_pos := (x, y); let _animation_frame_id = G.request_animation_frame draw_map in () let rec game_loop _timestamp = (* ... update state ... *) draw_map (); ignore @@ G.request_animation_frame game_loop let () = let on_window_load f x = ignore @@ Ev.listen Ev.load (fun _ev -> ignore @@ f x) (Window.as_target G.window) in let bind_keys () = ignore @@ Ev.listen Ev.keydown (fun ev -> kb_handler ev) (Window.as_target G.window) in on_window_load init_bg (); on_window_load bind_keys (); on_window_load G.request_animation_frame game_loop