From 53cba1d004451f0782312cb203afb7da47a29c5f Mon Sep 17 00:00:00 2001 From: Xander Swan Date: Wed, 3 Dec 2025 09:52:13 -0500 Subject: update renderer structure a lil --- src/constants.odin | 4 +++ src/draw/default.glsl | 10 +++---- src/draw/draw.odin | 37 +++++++++++++------------ src/draw/sprite.odin | 30 +++++++++++++++----- src/input.odin | 6 ++-- src/main.odin | 28 ++++++++++++++++--- src/player.odin | 76 +++++++++++++++++++++++++++++++-------------------- 7 files changed, 124 insertions(+), 67 deletions(-) create mode 100644 src/constants.odin (limited to 'src') diff --git a/src/constants.odin b/src/constants.odin new file mode 100644 index 0000000..ae763d7 --- /dev/null +++ b/src/constants.odin @@ -0,0 +1,4 @@ +package demonchime + +GRAVITY :: 500 +TERMINAL_VELOCITY :: 500 diff --git a/src/draw/default.glsl b/src/draw/default.glsl index b45a1c9..15cb2e2 100644 --- a/src/draw/default.glsl +++ b/src/draw/default.glsl @@ -10,13 +10,13 @@ out vec4 fcolor; out vec2 fuv; layout (binding = 0) uniform default_vs_params { - mat4 projection; + mat4 projection; }; void main() { - gl_Position = projection * vec4(vposition, 0.0, 1.0); - fcolor = vcolor; - fuv = vuv; + gl_Position = projection * vec4(vposition, 0.0, 1.0); + fcolor = vcolor; + fuv = vuv; } @end @@ -31,7 +31,7 @@ layout (binding = 0) uniform sampler tex_samp; #define tex sampler2D(tex, tex_samp) void main() { - out_color = texture(tex, fuv) * fcolor; + out_color = texture(tex, fuv) * fcolor; } @end diff --git a/src/draw/draw.odin b/src/draw/draw.odin index 1bc24d1..d67e16c 100644 --- a/src/draw/draw.odin +++ b/src/draw/draw.odin @@ -10,23 +10,23 @@ import sglue "shared:sokol/glue" Vec2 :: [2]f32 Vec3 :: [3]f32 -Mat4 :: matrix[4, 4]f32 Rect :: struct { start: Vec2, size: Vec2, } +Mat4 :: matrix[4, 4]f32 + Color :: [4]f32 SCREEN_WIDTH :: 256 SCREEN_HEIGHT :: 256 Renderer :: struct { - screen: struct { - framebuffer: Framebuffer, - }, - display: struct { + screen: Framebuffer, + + window_pass: struct { pass_action: sg.Pass_Action, pipe: sg.Pipeline, }, @@ -52,7 +52,7 @@ Batch :: struct { } init :: proc(r: ^Renderer) { - r.display.pipe = sg.make_pipeline({ + r.window_pass.pipe = sg.make_pipeline({ shader = sg.make_shader(default_shader_desc(sg.query_backend())), layout = { attrs = { @@ -63,14 +63,14 @@ init :: proc(r: ^Renderer) { }, }) - r.display.pass_action = { + r.window_pass.pass_action = { colors = { 0 = {load_action = .CLEAR, clear_value = {0, 0, 0, 1}}, }, } init_framebuffer( - &r.screen.framebuffer, + &r.screen, SCREEN_WIDTH, SCREEN_HEIGHT, Color{0.2, 0.2, 0.2, 1.0}, ) @@ -84,17 +84,16 @@ init :: proc(r: ^Renderer) { deinit :: proc(r: ^Renderer) { delete_batch(&r.current_batch) - sg.destroy_pipeline(r.screen.framebuffer.pipe) - sg.destroy_pipeline(r.display.pipe) + sg.destroy_pipeline(r.window_pass.pipe) sg.destroy_view(r.view) sg.destroy_sampler(r.sampler) - destroy_framebuffer(&r.screen.framebuffer) + destroy_framebuffer(&r.screen) } new_frame :: proc(r: ^Renderer) { - framebuffer_draw_start(r.screen.framebuffer) + framebuffer_draw_start(r.screen) r.projection = linalg.matrix_ortho3d( 0, f32(SCREEN_WIDTH), f32(SCREEN_HEIGHT), 0, @@ -106,7 +105,7 @@ end_frame :: proc(r: ^Renderer) { flush_current_batch(r) clear(&r.current_batch.vertices) - framebuffer_draw_end(r.screen.framebuffer) + framebuffer_draw_end(r.screen) r.projection = linalg.matrix_ortho3d( 0, f32(sapp.width()), @@ -114,8 +113,8 @@ end_frame :: proc(r: ^Renderer) { 0.0, 1.0, ) - sg.begin_pass({action=r.display.pass_action, swapchain=sglue.swapchain()}) - sg.apply_pipeline(r.display.pipe) + 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) , @@ -128,7 +127,7 @@ end_frame :: proc(r: ^Renderer) { draw_texture( r, - r.screen.framebuffer.img, + r.screen.img, screen_start, scale = Vec2{scale, scale}, ) @@ -227,8 +226,8 @@ draw_texture_quad :: proc( assert(quad.size.x > 0 && quad.size.y > 0) batch := request_batch(r, img) - - top_left := pos - (offset * scale) + + top_left := pos + offset * scale bot_rght := top_left + quad.size * scale size := Vec2{ @@ -266,3 +265,5 @@ draw_texture_full :: proc( } draw_texture_quad(r, img, Rect{Vec2{0, 0}, size}, pos, offset, scale) } + + diff --git a/src/draw/sprite.odin b/src/draw/sprite.odin index e2f2639..ff8ce58 100644 --- a/src/draw/sprite.odin +++ b/src/draw/sprite.odin @@ -1,10 +1,12 @@ package draw import "core:log" +import "core:math" import "core:image" import "core:image/qoi" import sg "shared:sokol/gfx" +import stime "shared:sokol/time" Sprite :: struct { image: sg.Image, @@ -12,6 +14,13 @@ Sprite :: struct { active_anim: u32, frame_time: f32, current_frame: i32, + + width: i32, + height: i32, + + pos: Vec2, + offset: Vec2, + scale: Vec2, } init_sprite :: proc( @@ -37,7 +46,17 @@ init_sprite :: proc( }) sprite.anim = anim - log.debugf("loaded sprite '%v'", path) + sprite.width = i32(img.width / len(sprite.anim.frames)) + sprite.height = i32(img.height) + + sprite.scale = Vec2{1, 1} + + log.debugf( + "loaded sprite '%v' %vx%v (%vx%v)", + path, + sprite.width, sprite.height, + img.width, img.height, + ) return true } @@ -69,9 +88,6 @@ update_sprite :: proc(sprite: ^Sprite, dt: f32) { draw_sprite :: proc( r: ^Renderer, sprite: Sprite, - pos: Vec2, - offset := Vec2{0, 0}, - scale := Vec2{1, 1}, ) { frame := sprite.anim.frames[sprite.current_frame] @@ -82,8 +98,8 @@ draw_sprite :: proc( Vec2{f32(frame.rect.x), f32(frame.rect.y)}, Vec2{f32(frame.rect.w), f32(frame.rect.h)}, }, - pos, - offset, - scale, + sprite.pos, + sprite.offset, + sprite.scale, ) } diff --git a/src/input.odin b/src/input.odin index 0dad408..6c02349 100644 --- a/src/input.odin +++ b/src/input.odin @@ -14,10 +14,9 @@ Keybind :: struct { } Input :: struct { - move_up: Keybind, move_left: Keybind, - move_down: Keybind, move_right: Keybind, + jump: Keybind, key_down: [sapp.MAX_KEYCODES]bool, key_just_down: [sapp.MAX_KEYCODES]bool, @@ -26,10 +25,9 @@ Input :: struct { } init_keybinds :: proc(input: ^Input) { - input.move_up.input = sapp.Keycode.W input.move_left.input = sapp.Keycode.A - input.move_down.input = sapp.Keycode.S input.move_right.input = sapp.Keycode.D + input.jump.input = sapp.Keycode.SPACE } input_event :: proc(event: ^sapp.Event, input: ^Input) { diff --git a/src/main.odin b/src/main.odin index 41af6e3..95ddbcd 100644 --- a/src/main.odin +++ b/src/main.odin @@ -6,9 +6,12 @@ package demonchime import "base:runtime" +import "core:log" + 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 "draw" @@ -23,8 +26,18 @@ state: struct { input: Input, } +logger: log.Logger + +default_context :: proc "contextless" () -> runtime.Context { + ctx := runtime.default_context() + ctx.logger = logger + return ctx +} + init :: proc "c" () { - context = runtime.default_context() + context = default_context() + + stime.setup() sg.setup({ environment = sglue.environment(), @@ -39,7 +52,7 @@ init :: proc "c" () { } frame :: proc "c" () { - context = runtime.default_context() + context = default_context() update_player(&state.player, f32(sapp.frame_duration())) @@ -48,10 +61,12 @@ frame :: proc "c" () { draw_player(state.player) draw.end_frame(&state.renderer) + + free_all(context.temp_allocator) } event :: proc "c" (event: ^sapp.Event) { - context = runtime.default_context() + context = default_context() if event.type == .KEY_DOWN && event.key_code == .ESCAPE { sapp.quit() @@ -61,11 +76,14 @@ event :: proc "c" (event: ^sapp.Event) { } cleanup :: proc "c" () { - context = runtime.default_context() + context = default_context() sg.shutdown() } main :: proc() { + logger = log.create_console_logger() + context.logger = logger + sapp.run({ init_cb = init, frame_cb = frame, @@ -77,4 +95,6 @@ main :: proc() { icon = {sokol_default = true}, logger = {func=slog.func}, }) + + log.destroy_console_logger(logger) } diff --git a/src/player.odin b/src/player.odin index 01bc02b..e098167 100644 --- a/src/player.odin +++ b/src/player.odin @@ -10,59 +10,77 @@ import "draw" Player :: struct { pos: Vec2, + vel: Vec2, anim: draw.Animation, sprite: draw.Sprite, } -init_player :: proc(player: ^Player) { - anim_ok := draw.init_anim_data(&player.anim, "res/robot2.json") +PLAYER_SPEED :: 100 +PLAYER_ACCEL :: 10 +PLAYER_JUMP_FORCE :: 300 + +init_player :: proc(p: ^Player) { + p.pos = Vec2{50, 50} + + anim_ok := draw.init_anim_data(&p.anim, "res/robot2.json") if !anim_ok { fmt.println("coult not load animation") sapp.quit() return } - draw.init_sprite(&player.sprite, player.anim.image_path, player.anim) -} + draw.init_sprite(&p.sprite, p.anim.image_path, p.anim) -deinit_player :: proc(player: ^Player) { - draw.delete_anim_data(player.anim) + p.sprite.offset = Vec2{ + -math.floor(f32(p.sprite.width / 2)), + -f32(p.sprite.height) + } } -update_player :: proc(player: ^Player, dt: f32) { - SPEED :: 100 +deinit_player :: proc(p: ^Player) { + draw.delete_anim_data(p.anim) +} - input: Vec2 +update_player :: proc(p: ^Player, dt: f32) { + input: f32 - if is_keybind_down(state.input, state.input.move_up) { - input.y -= 1 - } if is_keybind_down(state.input, state.input.move_left) { - input.x -= 1 - } - if is_keybind_down(state.input, state.input.move_down) { - input.y += 1 + input -= 1 } if is_keybind_down(state.input, state.input.move_right) { - input.x += 1 + input += 1 } - if linalg.length2(input) > 0 { - input = linalg.normalize(input) - draw.set_sprite_active_tag(&player.sprite, "down_run") + if input != 0 { + draw.set_sprite_active_tag(&p.sprite, "down_run") + p.sprite.scale.x = math.sign(input) } else { - draw.set_sprite_active_tag(&player.sprite, "down_idle") + draw.set_sprite_active_tag(&p.sprite, "down_idle") } - player.pos += input * SPEED * dt + if is_keybind_down(state.input, state.input.jump) && p.pos.y >= 256 { + p.vel.y = -PLAYER_JUMP_FORCE + } + + p.vel.x = math.lerp( + p.vel.x, + input * PLAYER_SPEED, + math.pow(0.5, dt * PLAYER_ACCEL), + ) + p.vel.y = math.min(p.vel.y + GRAVITY * dt, TERMINAL_VELOCITY) - draw.update_sprite(&player.sprite, dt) + p.pos += p.vel * dt + + if p.pos.y > 256 { + p.pos.y = 256 + p.vel.y = 0 + } + + p.sprite.pos = p.pos + + draw.update_sprite(&p.sprite, dt) } -draw_player :: proc(player: Player) { - draw.draw_sprite( - &state.renderer, - player.sprite, - player.pos, - ) +draw_player :: proc(p: Player) { + draw.draw_sprite(&state.renderer, p.sprite) } -- cgit v1.3-2-g0d8e