From ce4d64bd41937d7dff18ca607122188dc338d696 Mon Sep 17 00:00:00 2001 From: Xander Swan Date: Wed, 17 Dec 2025 18:38:21 -0500 Subject: switch to raylib, update some structure --- src/draw/draw.odin | 316 ++++++++++------------------------------------ src/draw/framebuffer.odin | 94 -------------- src/draw/sprite.odin | 46 +++---- src/input.odin | 52 ++++---- src/main.odin | 131 +++++-------------- src/phys/body.odin | 3 +- src/phys/world.odin | 77 ++++++----- src/platform.odin | 6 +- src/player.odin | 36 +++--- 9 files changed, 199 insertions(+), 562 deletions(-) delete mode 100644 src/draw/framebuffer.odin (limited to 'src') diff --git a/src/draw/draw.odin b/src/draw/draw.odin index 6c013de..6761b36 100644 --- a/src/draw/draw.odin +++ b/src/draw/draw.odin @@ -1,12 +1,9 @@ package draw -import "core:math/linalg" import "core:math" +import "core:c" -import sg "shared:sokol/gfx" -import sapp "shared:sokol/app" -import sdtxt "shared:sokol/debugtext" -import sglue "shared:sokol/glue" +import rl "vendor:raylib" Vec2 :: [2]f32 Vec3 :: [3]f32 @@ -23,238 +20,69 @@ Color :: [4]f32 SCREEN_WIDTH :: 480 SCREEN_HEIGHT :: 360 -Renderer :: struct { - screen: Framebuffer, - - window_pass: struct { - pass_action: sg.Pass_Action, - pipe: sg.Pipeline, - }, - - view: sg.View, - sampler: sg.Sampler, - - white_1x1: sg.Image, - - projection: Mat4, - current_batch: Batch, - +renderer: struct { + screen: rl.RenderTexture2D, tint: Color, } -Vertex :: struct { - pos: Vec2, - uv: Vec2, - color: Color, -} - -Batch :: struct { - img: sg.Image, - vertices: [dynamic]Vertex, -} - -init :: proc(r: ^Renderer) { - r.window_pass.pipe = sg.make_pipeline({ - shader = sg.make_shader(default_shader_desc(sg.query_backend())), - layout = { - attrs = { - ATTR_default_vposition = {format = .FLOAT2}, - ATTR_default_vuv = {format = .FLOAT2}, - ATTR_default_vcolor = {format = .FLOAT4}, - }, - }, - }) - - r.window_pass.pass_action = { - colors = { - 0 = {load_action = .CLEAR, clear_value = {0, 0, 0, 1}}, - }, +@(private) +color_to_rl :: proc(col: Color) -> rl.Color { + return rl.Color{ + u8(col.r * 255), + u8(col.g * 255), + u8(col.b * 255), + u8(col.a * 255), } - - white := [?]u8{255, 255, 255, 255} - - r.white_1x1 = sg.make_image({ - width = 1, - height = 1, - data = { - mip_levels = { - 0 = {ptr=&white, size=size_of(white)}, - }, - }, - }) - - init_framebuffer( - &r.screen, - SCREEN_WIDTH, SCREEN_HEIGHT, - Color{0.2, 0.2, 0.2, 1.0}, - ) - - r.view = sg.alloc_view() - r.sampler = sg.make_sampler({}) - - r.tint = {1, 1, 1, 1} - - sdtxt.set_context(sdtxt.make_context({ - color_format = .RGBA8, - depth_format = .NONE, - sample_count = 1, - })) -} - -deinit :: proc(r: ^Renderer) { - delete_batch(&r.current_batch) - - sg.destroy_pipeline(r.window_pass.pipe) - - sg.destroy_view(r.view) - sg.destroy_sampler(r.sampler) - - destroy_framebuffer(&r.screen) } -new_frame :: proc(r: ^Renderer) { - framebuffer_draw_start(r.screen) - r.projection = linalg.matrix_ortho3d( - 0, f32(SCREEN_WIDTH), - f32(SCREEN_HEIGHT), 0, - 0.0, 1.0, - ) +init :: proc() { + renderer.screen = rl.LoadRenderTexture(SCREEN_WIDTH, SCREEN_HEIGHT) + renderer.tint = Color{1, 1, 1, 1} } -end_frame :: proc(r: ^Renderer) { - flush_current_batch(r) - clear(&r.current_batch.vertices) - - sdtxt.draw() - - framebuffer_draw_end(r.screen) - - r.projection = linalg.matrix_ortho3d( - 0, f32(sapp.width()), - 0, f32(sapp.height()), - 0.0, 1.0, - ) - - sg.begin_pass({action=r.window_pass.pass_action, swapchain=sglue.swapchain()}) - sg.apply_pipeline(r.window_pass.pipe) - - scale := math.min( - f32(sapp.height()) / f32(SCREEN_HEIGHT) , - f32(sapp.width()) / f32(SCREEN_WIDTH), - ) - screen_start := Vec2{ - (f32(sapp.width()) - (SCREEN_WIDTH * scale)) / 2, - (f32(sapp.height()) - (SCREEN_HEIGHT * scale)) / 2, - } - - texture( - r, - r.screen.img, - screen_start, - scale = Vec2{scale, scale}, - ) - - flush_current_batch(r) - clear(&r.current_batch.vertices) - - sg.end_pass() - - sg.commit() +deinit :: proc() { + rl.UnloadRenderTexture(renderer.screen) } -@(private) -delete_batch :: proc(batch: ^Batch) { - delete(batch.vertices) +new_frame :: proc() { + rl.BeginTextureMode(renderer.screen) + rl.ClearBackground(color_to_rl(Color{0.2, 0.2, 0.2, 1})) } -flush_current_batch :: proc(r: ^Renderer) { - batch := r.current_batch - - if len(batch.vertices) == 0 { - return - } - - buffer := sg.make_buffer({ - data = { - ptr = &r.current_batch.vertices[0], - size = size_of(Vertex) * len(r.current_batch.vertices), - }, - }) - - sg.init_view(r.view, { - texture = { - image = r.current_batch.img, - }, - }) - - binds: sg.Bindings - - binds.vertex_buffers[0] = buffer - binds.views[VIEW_tex] = r.view - binds.samplers[SMP_tex_samp] = r.sampler +end_frame :: proc() { + rl.EndTextureMode() - uniforms := Default_Vs_Params { - projection = transmute([16]f32)r.projection, - } - - sg.apply_bindings(binds) - sg.apply_uniforms(UB_default_vs_params, {ptr=&uniforms, size=size_of(uniforms)}) - - sg.draw(0, len(r.current_batch.vertices), 1) - - sg.uninit_view(r.view) - - sg.destroy_buffer(buffer) -} + rl.BeginDrawing() + { + rl.ClearBackground(color_to_rl(Color{0, 0, 0, 1})) + scale := math.min( + f32(rl.GetScreenWidth()) / f32(SCREEN_WIDTH), + f32(rl.GetScreenHeight()) / f32(SCREEN_HEIGHT), + ) + screen_start := Vec2{ + (f32(rl.GetScreenWidth()) - (SCREEN_WIDTH * scale)) / 2, + (f32(rl.GetScreenHeight()) - (SCREEN_HEIGHT * scale)) / 2, + } -@(private) -new_batch :: proc(batch: ^Batch, img: sg.Image) { - clear(&batch.vertices) - batch.img = img -} - -request_batch :: proc(r: ^Renderer, img: sg.Image) -> ^Batch { - if len(r.current_batch.vertices) == 0 { - new_batch(&r.current_batch, img) - } else if img != r.current_batch.img { - flush_current_batch(r) - new_batch(&r.current_batch, img) + texture_full( + renderer.screen.texture, + screen_start, + scale = Vec2{scale, scale}, + ) } - - return &r.current_batch -} - -@(private) -batch_vertices :: proc( - b: ^Batch, - vertices: []Vertex, -) { - append(&b.vertices, ..vertices) + rl.EndDrawing() } rect :: proc( - r: ^Renderer, rect: Rect, - color := Color{1, 1, 1, 1}, ) { assert(rect.size.x > 0 && rect.size.y > 0) - batch := request_batch(r, r.white_1x1) - - start := rect.start - end := rect.start + rect.size - - vertices := [?]Vertex{ - {start, {0, 0}, r.tint}, - {{end.x, start.y}, {1, 0}, r.tint}, - {{start.x, end.y}, {0, 1}, r.tint}, - - {{end.x, start.y}, {1, 0}, r.tint}, - {{start.x, end.y}, {0, 1}, r.tint}, - {end, {1, 1}, r.tint}, - } - - batch_vertices(batch, vertices[:]) + rl.DrawRectangle( + c.int(rect.start.x), c.int(rect.start.y), + c.int(rect.size.x), c.int(rect.size.y), + color_to_rl(renderer.tint), + ) } texture :: proc{ @@ -263,52 +91,42 @@ texture :: proc{ } texture_quad :: proc( - r: ^Renderer, - img: sg.Image, + img: rl.Texture2D, quad: Rect, - pos: Vec2, + position: Vec2, offset := Vec2{0, 0}, + rotation: f32 = 0, scale := Vec2{1, 1}, ) { - assert(quad.size.x > 0 && quad.size.y > 0) + // assert(quad.size.x > 0 && quad.size.y > 0) - batch := request_batch(r, img) - - top_left := pos + offset * scale - bot_rght := top_left + quad.size * scale + quad := quad + quad.size *= scale - size := Vec2{ - f32(sg.query_image_width(img)), - f32(sg.query_image_height(img)), - } - - uv_start := quad.start / size - uv_end := (quad.start + quad.size) / size - - // |/| - vertices := [?]Vertex{ - {top_left, uv_start, r.tint}, - {{bot_rght.x, top_left.y}, {uv_end.x, uv_start.y}, r.tint}, - {{top_left.x, bot_rght.y}, {uv_start.x, uv_end.y }, r.tint}, - - {{bot_rght.x, top_left.y}, {uv_end.x, uv_start.y}, r.tint}, - {{top_left.x, bot_rght.y}, {uv_start.x, uv_end.y }, r.tint}, - {bot_rght, uv_end, r.tint}, - } - - batch_vertices(batch, vertices[:]) + rl.DrawTexturePro( + img, + transmute(rl.Rectangle)quad, + rl.Rectangle{ + position.x, position.y, + quad.size.x * scale.x, quad.size.y * scale.y, + }, + offset, + rotation, + color_to_rl(renderer.tint), + ) } texture_full :: proc( - r: ^Renderer, - img: sg.Image, - pos: Vec2, + img: rl.Texture2D, + position: Vec2, offset := Vec2{0, 0}, + rotation: f32 = 0, scale := Vec2{1, 1}, ) { size := Vec2{ - f32(sg.query_image_width(img)), - f32(sg.query_image_height(img)), + f32(img.width), + -f32(img.height), } - texture_quad(r, img, Rect{Vec2{0, 0}, size}, pos, offset, scale) + + texture_quad(img, Rect{Vec2{0, 0}, size}, position, offset, rotation, scale) } diff --git a/src/draw/framebuffer.odin b/src/draw/framebuffer.odin deleted file mode 100644 index cd7848b..0000000 --- a/src/draw/framebuffer.odin +++ /dev/null @@ -1,94 +0,0 @@ -package draw - -import sg "shared:sokol/gfx" - -Framebuffer :: struct { - img: sg.Image, - view: sg.View, - pipe: sg.Pipeline, - pass: sg.Pass, -} - -init_framebuffer :: proc( - fb: ^Framebuffer, - width: i32, - height: i32, - clear_color := Color{0, 0, 0, 0}, -) { - fb.pipe = sg.make_pipeline({ - shader = sg.make_shader(default_shader_desc(sg.query_backend())), - layout = { - attrs = { - ATTR_default_vposition = {format = .FLOAT2}, - ATTR_default_vuv = {format = .FLOAT2}, - ATTR_default_vcolor = {format = .FLOAT4}, - }, - }, - depth = { - pixel_format = .NONE, - }, - sample_count = 1, - colors = { - 0 = { - pixel_format = .RGBA8, - blend = { - enabled = true, - src_factor_rgb = .SRC_ALPHA, - dst_factor_rgb = .ONE_MINUS_SRC_ALPHA, - src_factor_alpha = .ONE, - dst_factor_alpha = .ZERO, - }, - }, - }, - }) - - fb.img = sg.make_image({ - usage = { - color_attachment = true, - }, - - width = width, - height = height, - - pixel_format = .RGBA8, - sample_count = 1, - }) - - fb.view = sg.make_view({ - texture = { - image = fb.img, - }, - }) - - fb.pass = { - attachments = { - colors = { - 0 = sg.make_view({ - color_attachment = { - image = fb.img, - }, - }), - }, - }, - action = { - colors = { - 0 = {load_action = .CLEAR, clear_value = transmute(sg.Color)clear_color}, - }, - }, - } -} - -destroy_framebuffer :: proc(fb: ^Framebuffer) { - sg.destroy_pipeline(fb.pipe) - sg.destroy_view(fb.view) - sg.destroy_image(fb.img) -} - -framebuffer_draw_start :: proc(fb: Framebuffer) { - sg.begin_pass(fb.pass) - sg.apply_pipeline(fb.pipe) -} - -framebuffer_draw_end :: proc(fb: Framebuffer) { - sg.end_pass() -} diff --git a/src/draw/sprite.odin b/src/draw/sprite.odin index 59d1c32..a6a109b 100644 --- a/src/draw/sprite.odin +++ b/src/draw/sprite.odin @@ -1,13 +1,14 @@ package draw import "core:log" -import "core:image" -import "core:image/qoi" +// import "core:image" +import "core:mem" +// import "core:image/qoi" -import sg "shared:sokol/gfx" +import rl "vendor:raylib" Sprite :: struct { - image: sg.Image, + image: rl.Texture2D, anim: Animation, active_anim: u32, frame_time: f32, @@ -18,6 +19,7 @@ Sprite :: struct { pos: Vec2, offset: Vec2, + rotation: f32, scale: Vec2, } @@ -26,26 +28,15 @@ init_sprite :: proc( path: string, anim: Animation = {}, ) -> bool { - img, img_err := qoi.load_from_file(path) - if img_err != nil { - log.error("could not load image") - return false - } - defer image.destroy(img) - - sprite.image = sg.make_image({ - width = i32(img.width), - height = i32(img.height), - data = { - mip_levels = { - 0 = {ptr=&img.pixels.buf[0], size=len(img.pixels.buf)}, - }, - }, - }) + byte_path := make([]u8, len(path) + 1, context.temp_allocator) + copy(byte_path, path) + byte_path[len(path)] = 0 + + sprite.image = rl.LoadTexture(transmute(cstring)&byte_path[0]) sprite.anim = anim - sprite.width = i32(img.width / len(sprite.anim.frames)) - sprite.height = i32(img.height) + sprite.width = i32(int(sprite.image.width) / len(sprite.anim.frames)) + sprite.height = i32(sprite.image.height) sprite.scale = Vec2{1, 1} @@ -53,12 +44,16 @@ init_sprite :: proc( "loaded sprite '%v' %vx%v (%vx%v)", path, sprite.width, sprite.height, - img.width, img.height, + sprite.image.width, sprite.image.height, ) return true } +destroy_sprite :: proc(sprite: Sprite) { + rl.UnloadTexture(sprite.image) +} + set_sprite_active_tag :: proc(sprite: ^Sprite, tag_name: string) { sprite.active_anim = sprite.anim.frame_tags_indices[tag_name] } @@ -84,13 +79,11 @@ update_sprite :: proc(sprite: ^Sprite, dt: f32) { } sprite :: proc( - r: ^Renderer, sprite: Sprite, ) { frame := sprite.anim.frames[sprite.current_frame] - texture( - r, + texture_quad( sprite.image, Rect { Vec2{f32(frame.rect.x), f32(frame.rect.y)}, @@ -98,6 +91,7 @@ sprite :: proc( }, sprite.pos, sprite.offset, + sprite.rotation, sprite.scale, ) } diff --git a/src/input.odin b/src/input.odin index 6c02349..de2af7e 100644 --- a/src/input.odin +++ b/src/input.odin @@ -1,10 +1,10 @@ package demonchime -import sapp "shared:sokol/app" +import rl "vendor:raylib" KeybindInput :: union { - sapp.Keycode, - sapp.Mousebutton, + rl.KeyboardKey, + rl.MouseButton, } Keybind :: struct { @@ -13,44 +13,36 @@ Keybind :: struct { just_pressed: bool, } -Input :: struct { +actions: struct { move_left: Keybind, move_right: Keybind, jump: Keybind, - - key_down: [sapp.MAX_KEYCODES]bool, - key_just_down: [sapp.MAX_KEYCODES]bool, - mouse_down: [sapp.MAX_MOUSEBUTTONS]bool, - mouse_just_down: [sapp.MAX_MOUSEBUTTONS]bool, } -init_keybinds :: proc(input: ^Input) { - input.move_left.input = sapp.Keycode.A - input.move_right.input = sapp.Keycode.D - input.jump.input = sapp.Keycode.SPACE +init_keybinds :: proc() { + actions.move_left.input = .A + actions.move_right.input = .D + actions.jump.input = .SPACE } -input_event :: proc(event: ^sapp.Event, input: ^Input) { - #partial switch event.type { - case .KEY_DOWN: - input.key_down[event.key_code] = true - input.key_just_down[event.key_code] = true - case .KEY_UP: - input.key_down[event.key_code] = false - case .MOUSE_DOWN: - input.mouse_down[event.key_code] = true - input.mouse_just_down[event.key_code] = true - case .MOUSE_UP: - input.mouse_down[event.key_code] = false +is_keybind_down :: proc(keybind: Keybind) -> bool { + switch val in keybind.input { + case rl.KeyboardKey: + return rl.IsKeyDown(val) + case rl.MouseButton: + return rl.IsMouseButtonDown(val) } + + assert(false) + return false } -is_keybind_down :: proc(input: Input, keybind: Keybind) -> bool { +is_keybind_just_down :: proc(keybind: Keybind) -> bool { switch val in keybind.input { - case sapp.Keycode: - return input.key_down[val] - case sapp.Mousebutton: - return input.mouse_down[val] + case rl.KeyboardKey: + return rl.IsKeyPressed(val) + case rl.MouseButton: + return rl.IsMouseButtonPressed(val) } assert(false) diff --git a/src/main.odin b/src/main.odin index 2ca3e7f..9a6c09a 100644 --- a/src/main.odin +++ b/src/main.odin @@ -7,13 +7,9 @@ package demonchime import "base:runtime" import "core:log" +import "core:fmt" -import sg "shared:sokol/gfx" -import sapp "shared:sokol/app" -import sglue "shared:sokol/glue" -import stime "shared:sokol/time" -import slog "shared:sokol/log" -import sdtxt "shared:sokol/debugtext" +import rl "vendor:raylib" import "draw" import "phys" @@ -27,47 +23,13 @@ Rect :: struct { state: struct { player: Player, - platform_list: Entity_List(Platform), - - renderer: draw.Renderer, - physics_world: phys.World, - - input: Input, - - fps: f32, - last_fps: f32, - frames_rendered: int, } -logger: log.Logger - -default_context :: proc "contextless" () -> runtime.Context { - ctx := runtime.default_context() - ctx.logger = logger - return ctx -} - -init :: proc "c" () { - context = default_context() - - stime.setup() - - sg.setup({ - environment = sglue.environment(), - logger = {func=slog.func}, - }) - - sdtxt.setup({ - fonts = { - 0 = sdtxt.font_kc853(), - }, - logger = {func=slog.func}, - }) +init :: proc() { + init_keybinds() - init_keybinds(&state.input) - - draw.init(&state.renderer) + draw.init() init_player(&state.player) @@ -89,17 +51,14 @@ init :: proc "c" () { start = {160, 320}, size = {20, 20} }) - make_platform(Rect{ start = {240, 280}, size = {40, 20} }) - make_platform(Rect{ start = {260, 260}, size = {20, 20} }) - make_platform(Rect{ start = {300, 220}, size = {40, 20} @@ -126,74 +85,44 @@ init :: proc "c" () { }) } -frame :: proc "c" () { - context = default_context() - - update_player(&state.player, f32(sapp.frame_duration())) - - // sdtxt.canvas(f32(sapp.width()), f32(sapp.height())) - sdtxt.canvas(draw.SCREEN_WIDTH, draw.SCREEN_HEIGHT) - sdtxt.origin(0.1, 0.1) - sdtxt.home() - sdtxt.font(0) +frame :: proc() { + update_player(&state.player, rl.GetFrameTime()) - stats := sg.query_frame_stats() - sdtxt.printf("FPS: %f\n", state.fps) - sdtxt.printf("Draw calls: %d\n", stats.num_draw) + draw.new_frame() - draw.new_frame(&state.renderer) - - draw_player(state.player) + fps_text := fmt.caprintf( + "FPS: %v", rl.GetFPS(), + allocator = context.temp_allocator, + ) + rl.DrawText(fps_text, 5, 5, 8, rl.GREEN) draw_platforms() + draw_player(state.player) - draw.end_frame(&state.renderer) - - free_all(context.temp_allocator) - - state.frames_rendered += 1 - now := f32(stime.sec(stime.now())) - if now - state.last_fps > 1 { - state.fps = f32(state.frames_rendered) / (now - state.last_fps) - state.last_fps = now - state.frames_rendered = 0 - } -} - -event :: proc "c" (event: ^sapp.Event) { - context = default_context() - - if event.type == .KEY_DOWN && event.key_code == .ESCAPE { - sapp.quit() - } - - input_event(event, &state.input) + draw.end_frame() } -cleanup :: proc "c" () { - context = default_context() - sg.shutdown() - sdtxt.shutdown() - +cleanup :: proc() { delete_entity_list(state.platform_list) } main :: proc() { - logger = log.create_console_logger() + logger := log.create_console_logger() context.logger = logger + defer log.destroy_console_logger(logger) - sapp.run({ - init_cb = init, - frame_cb = frame, - event_cb = event, - cleanup_cb = cleanup, - width = 800, - height = 600, - window_title = "Demonchime", - icon = {sokol_default = true}, - logger = {func=slog.func}, - }) + rl.InitWindow(480 * 2, 360 * 2, "Demonchime") + + rl.SetWindowState({.WINDOW_RESIZABLE}) + + init() + + for !rl.WindowShouldClose() { + frame() + + free_all(context.temp_allocator) + } - log.destroy_console_logger(logger) + cleanup() } diff --git a/src/phys/body.odin b/src/phys/body.odin index fcae697..0256dee 100644 --- a/src/phys/body.odin +++ b/src/phys/body.odin @@ -37,7 +37,6 @@ Body :: struct { } make_body :: proc( - w: ^World, rect: Rect, layers := bit_set[Layer; u16]{.DEFAULT}, mask := bit_set[Layer; u16]{.DEFAULT}, @@ -48,7 +47,7 @@ make_body :: proc( mask = mask, active = true, } - return add_body(w, b) + return add_body(b) } aabb_hori :: proc(a: Rect, b: Rect) -> bool { diff --git a/src/phys/world.odin b/src/phys/world.odin index eac3d5c..3154a0b 100644 --- a/src/phys/world.odin +++ b/src/phys/world.odin @@ -3,22 +3,22 @@ package phys import "core:log" import "core:math" -import sapp "shared:sokol/app" +import rl "vendor:raylib" BIN_COUNT :: 2056 BIN_SIZE :: 64 Body_Handle :: u32 -World :: struct { +world: struct { handles: [dynamic]u32, unused_handles: [dynamic]Body_Handle, bodies: [dynamic]Body, bins: [BIN_COUNT][dynamic]Body_Handle, } -destroy_world :: proc(w: World) { - for bin in w.bins { +destroy_world :: proc() { + for bin in world.bins { delete(bin) } } @@ -37,7 +37,6 @@ world_to_bin :: proc(point: Vec2) -> (i32, i32) { @(private="file") get_surrounding_bins :: proc( - w: ^World, pos: Vec2, allocator := context.temp_allocator, ) -> []^[dynamic]Body_Handle { @@ -50,7 +49,7 @@ get_surrounding_bins :: proc( for offset_x in -1..=1 { for offset_y in -1..=1 { bin_idx := hash_bin(center_x + i32(offset_x), center_y + i32(offset_y)) - bin := &w.bins[bin_idx % BIN_COUNT] + bin := &world.bins[bin_idx % BIN_COUNT] neighbors[idx] = bin idx += 1 } @@ -60,79 +59,79 @@ get_surrounding_bins :: proc( } @(private="file") -find_bin :: proc(w: ^World, b: Body) -> ^[dynamic]Body_Handle { +find_bin :: proc(b: Body) -> ^[dynamic]Body_Handle { bin_x, bin_y := world_to_bin(b.pos + b.rect.start) - return &w.bins[hash_bin(bin_x, bin_y) % BIN_COUNT] + return &world.bins[hash_bin(bin_x, bin_y) % BIN_COUNT] } @(private="file") -add_to_bins :: proc(w: ^World, b: Body) { - bin := find_bin(w, b) +add_to_bins :: proc(b: Body) { + bin := find_bin(b) idx := i32(len(bin)) append(bin, b.handle) - w.bodies[bin[idx]].bin_idx = idx + world.bodies[bin[idx]].bin_idx = idx } @(private="file") -remove_from_bins :: proc(w: ^World, b: Body) { - bin := find_bin(w, b) +remove_from_bins :: proc(b: Body) { + bin := find_bin(b) assert(bin[b.bin_idx] == b.handle) last := pop(bin) if last != b.handle { bin[b.bin_idx] = last - w.bodies[last].bin_idx = b.bin_idx + world.bodies[last].bin_idx = b.bin_idx } } -get_body :: proc(w: World, h: Body_Handle) -> ^Body { - return &w.bodies[w.handles[h]] +get_body :: proc(h: Body_Handle) -> ^Body { + return &world.bodies[world.handles[h]] } -add_body :: proc(w: ^World, b: Body) -> (Body_Handle, ^Body) { +add_body :: proc(b: Body) -> (Body_Handle, ^Body) { handle: Body_Handle if b.rect.size.x > BIN_SIZE || b.rect.size.y > BIN_SIZE { log.warnf("Body size is too big (%vx%v)", b.rect.size.x, b.rect.size.y) } - if len(w.unused_handles) > 0 { - handle = pop(&w.unused_handles) + if len(world.unused_handles) > 0 { + handle = pop(&world.unused_handles) } else { - handle = cast(Body_Handle)len(w.handles) - append(&w.handles, 0) + handle = cast(Body_Handle)len(world.handles) + append(&world.handles, 0) } - w.handles[handle] = u32(len(w.bodies)) - append(&w.bodies, b) + world.handles[handle] = u32(len(world.bodies)) + append(&world.bodies, b) - body := &w.bodies[w.handles[handle]] + body := &world.bodies[world.handles[handle]] body.handle = handle - add_to_bins(w, body^) + add_to_bins(body^) return handle, body } -remove_body :: proc(w: ^World, h: Body_Handle) { - b := get_body(w^, h) +remove_body :: proc(h: Body_Handle) { + b := get_body(h) - remove_from_bins(w, b^) + remove_from_bins(b^) - last := pop(&w.bodies) + last := pop(&world.bodies) if last.handle != h { - w.bodies[h] = last - w.handles[last.handle] = w.handles[h] + world.bodies[h] = last + world.handles[last.handle] = world.handles[h] } - append(&w.unused_handles, b.handle) + append(&world.unused_handles, b.handle) } -update_body :: proc(w: ^World, h: Body_Handle) { - dt := f32(sapp.frame_duration()) +update_body :: proc(h: Body_Handle) { + dt := rl.GetFrameTime() - b := get_body(w^, h) + b := get_body(h) res_pos := b.pos + b.vel * dt @@ -142,7 +141,7 @@ update_body :: proc(w: ^World, h: Body_Handle) { res_rect := b.rect res_rect.start += res_pos - bin_list := get_surrounding_bins(w, res_rect.start) + bin_list := get_surrounding_bins(res_rect.start) b.collisions = {} @@ -156,7 +155,7 @@ update_body :: proc(w: ^World, h: Body_Handle) { continue } - c := get_body(w^, c_h) + c := get_body(c_h) c_rect := c.rect c_rect.start += c.pos @@ -198,8 +197,8 @@ update_body :: proc(w: ^World, h: Body_Handle) { res_bin := hash_bin(world_to_bin(res_pos + b.rect.start)) if prev_bin != res_bin { - remove_from_bins(w, b^) - add_to_bins(w, b^) + remove_from_bins(b^) + add_to_bins(b^) } } diff --git a/src/platform.odin b/src/platform.odin index 150d96c..674e1a3 100644 --- a/src/platform.odin +++ b/src/platform.odin @@ -9,7 +9,7 @@ Platform :: struct { } make_platform :: proc(rect: Rect) -> (Entity_Handle, ^Platform) { - handle, body := phys.make_body(&state.physics_world, transmute(phys.Rect)rect) + handle, body := phys.make_body(transmute(phys.Rect)rect) return make_entity(&state.platform_list, Platform { body = handle, }) @@ -18,7 +18,7 @@ make_platform :: proc(rect: Rect) -> (Entity_Handle, ^Platform) { draw_platforms :: proc() { iter := iter_entity_list(state.platform_list) for p in entity_list_iter(&iter) { - body := phys.get_body(state.physics_world, p.body) - draw.rect(&state.renderer, cast(draw.Rect)body.rect) + body := phys.get_body(p.body) + draw.rect(cast(draw.Rect)body.rect) } } diff --git a/src/player.odin b/src/player.odin index 1fbbb0a..6c34d14 100644 --- a/src/player.odin +++ b/src/player.odin @@ -1,9 +1,9 @@ package demonchime -import "core:fmt" +import "core:log" import "core:math" -import sapp "shared:sokol/app" +import rl "vendor:raylib" import "draw" import "phys" @@ -25,20 +25,19 @@ Player :: struct { } init_player :: proc(p: ^Player) { - anim_ok := draw.init_anim_data(&p.anim, "res/robot2.json") + anim_ok := draw.init_anim_data(&p.anim, "res/player.json") if !anim_ok { - fmt.println("coult not load animation") - sapp.quit() + log.warn("could not load animation") + rl.CloseWindow() return } handle, body := phys.make_body( - &state.physics_world, - phys.Rect{{-8, -17}, {16, 16}}, + phys.Rect{{8, 17}, {16, 16}}, ) p.body_handle = handle - body.pos = Vec2{50, 50} + body.pos = Vec2{50, 0} draw.init_sprite(&p.sprite, p.anim.image_path, p.anim) @@ -49,33 +48,34 @@ init_player :: proc(p: ^Player) { } deinit_player :: proc(p: ^Player) { - phys.remove_body(&state.physics_world, p.body_handle) + phys.remove_body(p.body_handle) + draw.destroy_sprite(p.sprite) draw.delete_anim_data(p.anim) } update_player :: proc(p: ^Player, dt: f32) { input: f32 - if is_keybind_down(state.input, state.input.move_left) { + if is_keybind_down(actions.move_left) { input -= 1 } - if is_keybind_down(state.input, state.input.move_right) { + if is_keybind_down(actions.move_right) { input += 1 } - if is_keybind_down(state.input, state.input.jump) { + if is_keybind_just_down(actions.jump) { p.jump_buffer = JUMP_BUFFERING } if input != 0 { - draw.set_sprite_active_tag(&p.sprite, "down_run") + draw.set_sprite_active_tag(&p.sprite, "run") p.sprite.scale.x = math.sign(input) } else { - draw.set_sprite_active_tag(&p.sprite, "down_idle") + draw.set_sprite_active_tag(&p.sprite, "idle") } - body := phys.get_body(state.physics_world, p.body_handle) + body := phys.get_body(p.body_handle) if .DOWN in body.collisions { p.coyote_time = COYOTE_TIME @@ -88,7 +88,7 @@ update_player :: proc(p: ^Player, dt: f32) { } if .DOWN not_in body.collisions \ - && !is_keybind_down(state.input, state.input.jump) \ + && !is_keybind_down(actions.jump) \ && body.vel.y < JUMP_RELEASE_CUT { body.vel.y = JUMP_RELEASE_CUT } @@ -100,7 +100,7 @@ update_player :: proc(p: ^Player, dt: f32) { ) body.vel.y = math.min(body.vel.y + GRAVITY * dt, TERMINAL_VELOCITY) - phys.update_body(&state.physics_world, p.body_handle) + phys.update_body(p.body_handle) p.sprite.pos = body.pos draw.update_sprite(&p.sprite, dt) @@ -110,6 +110,6 @@ update_player :: proc(p: ^Player, dt: f32) { } draw_player :: proc(p: Player) { - draw.sprite(&state.renderer, p.sprite) + draw.sprite(p.sprite) } -- cgit v1.3-2-g0d8e