diff options
| author | Xander Swan <no email> | 2025-12-05 09:27:12 -0500 |
|---|---|---|
| committer | Xander Swan <no email> | 2025-12-05 09:27:12 -0500 |
| commit | 3375d712e40cce1d17198ba20839f58a2a77d202 (patch) | |
| tree | 856f517c9e9e59173b81b62a40bd4d2f1115d378 /src | |
| parent | 53cba1d004451f0782312cb203afb7da47a29c5f (diff) | |
add platforms and AABB collision
Diffstat (limited to 'src')
| -rw-r--r-- | src/aabb.odin | 13 | ||||
| -rw-r--r-- | src/constants.odin | 4 | ||||
| -rw-r--r-- | src/draw/draw.odin | 60 | ||||
| -rw-r--r-- | src/draw/sprite.odin | 6 | ||||
| -rw-r--r-- | src/entity_list.odin | 2 | ||||
| -rw-r--r-- | src/main.odin | 31 | ||||
| -rw-r--r-- | src/platform.odin | 21 | ||||
| -rw-r--r-- | src/player.odin | 52 |
8 files changed, 161 insertions, 28 deletions
diff --git a/src/aabb.odin b/src/aabb.odin new file mode 100644 index 0000000..9637ec9 --- /dev/null +++ b/src/aabb.odin @@ -0,0 +1,13 @@ +package demonchime + +aabb_hori :: proc(a: Rect, b: Rect) -> bool { + return a.start.x < b.start.x + b.size.x && b.start.x < a.start.x + a.size.x +} + +aabb_vert :: proc(a: Rect, b: Rect) -> bool { + return a.start.y < b.start.y + b.size.y && b.start.y < a.start.y + a.size.y +} + +aabb :: proc(a: Rect, b: Rect) -> bool { + return aabb_hori(a, b) && aabb_vert(a, b) +} diff --git a/src/constants.odin b/src/constants.odin index ae763d7..d415c3e 100644 --- a/src/constants.odin +++ b/src/constants.odin @@ -1,4 +1,4 @@ package demonchime -GRAVITY :: 500 -TERMINAL_VELOCITY :: 500 +GRAVITY :: 1000 +TERMINAL_VELOCITY :: 900 diff --git a/src/draw/draw.odin b/src/draw/draw.odin index d67e16c..1762b25 100644 --- a/src/draw/draw.odin +++ b/src/draw/draw.odin @@ -1,6 +1,5 @@ package draw -import "core:fmt" import "core:math/linalg" import "core:math" @@ -20,8 +19,8 @@ Mat4 :: matrix[4, 4]f32 Color :: [4]f32 -SCREEN_WIDTH :: 256 -SCREEN_HEIGHT :: 256 +SCREEN_WIDTH :: 480 +SCREEN_HEIGHT :: 360 Renderer :: struct { screen: Framebuffer, @@ -34,6 +33,8 @@ Renderer :: struct { view: sg.View, sampler: sg.Sampler, + white_1x1: sg.Image, + projection: Mat4, current_batch: Batch, @@ -69,6 +70,18 @@ init :: proc(r: ^Renderer) { }, } + 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, @@ -125,7 +138,7 @@ end_frame :: proc(r: ^Renderer) { (f32(sapp.height()) - (SCREEN_HEIGHT * scale)) / 2, } - draw_texture( + texture( r, r.screen.img, screen_start, @@ -210,12 +223,37 @@ batch_vertices :: proc( append(&b.vertices, ..vertices) } -draw_texture :: proc{ - draw_texture_full, - draw_texture_quad, +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[:]) +} + +texture :: proc{ + texture_full, + texture_quad, } -draw_texture_quad :: proc( +texture_quad :: proc( r: ^Renderer, img: sg.Image, quad: Rect, @@ -252,7 +290,7 @@ draw_texture_quad :: proc( batch_vertices(batch, vertices[:]) } -draw_texture_full :: proc( +texture_full :: proc( r: ^Renderer, img: sg.Image, pos: Vec2, @@ -263,7 +301,5 @@ draw_texture_full :: proc( f32(sg.query_image_width(img)), f32(sg.query_image_height(img)), } - draw_texture_quad(r, img, Rect{Vec2{0, 0}, size}, pos, offset, scale) + 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 ff8ce58..59d1c32 100644 --- a/src/draw/sprite.odin +++ b/src/draw/sprite.odin @@ -1,12 +1,10 @@ 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, @@ -85,13 +83,13 @@ update_sprite :: proc(sprite: ^Sprite, dt: f32) { } } -draw_sprite :: proc( +sprite :: proc( r: ^Renderer, sprite: Sprite, ) { frame := sprite.anim.frames[sprite.current_frame] - draw_texture( + texture( r, sprite.image, Rect { diff --git a/src/entity_list.odin b/src/entity_list.odin index 4890d2c..1f07ef9 100644 --- a/src/entity_list.odin +++ b/src/entity_list.odin @@ -1,6 +1,6 @@ package demonchime -// import "core:math" +import "core:math" Entity_Handle :: struct { idx: u32, diff --git a/src/main.odin b/src/main.odin index 95ddbcd..9a9c91c 100644 --- a/src/main.odin +++ b/src/main.odin @@ -18,9 +18,16 @@ import "draw" Vec2 :: [2]f32 +Rect :: struct { + start: Vec2, + size: Vec2, +} + state: struct { player: Player, + platform_list: Entity_List(Platform), + renderer: draw.Renderer, input: Input, @@ -49,6 +56,26 @@ init :: proc "c" () { draw.init(&state.renderer) init_player(&state.player) + + make_platform(Rect{ + start = {50, 50}, + size = {100, 20} + }) + + make_platform(Rect{ + start = {20, 340}, + size = {440, 20} + }) + + make_platform(Rect{ + start = {140, 320}, + size = {20, 20} + }) + + make_platform(Rect{ + start = {240, 280}, + size = {20, 20} + }) } frame :: proc "c" () { @@ -60,6 +87,8 @@ frame :: proc "c" () { draw_player(state.player) + draw_platforms() + draw.end_frame(&state.renderer) free_all(context.temp_allocator) @@ -78,6 +107,8 @@ event :: proc "c" (event: ^sapp.Event) { cleanup :: proc "c" () { context = default_context() sg.shutdown() + + delete_entity_list(state.platform_list) } main :: proc() { diff --git a/src/platform.odin b/src/platform.odin new file mode 100644 index 0000000..b837355 --- /dev/null +++ b/src/platform.odin @@ -0,0 +1,21 @@ +package demonchime + +import "draw" + +Platform :: struct { + handle: Entity_Handle, + rect: Rect, +} + +make_platform :: proc(rect: Rect) -> (Entity_Handle, ^Platform) { + return make_entity(&state.platform_list, Platform { + rect = rect, + }) +} + +draw_platforms :: proc() { + iter := iter_entity_list(state.platform_list) + for p in entity_list_iter(&iter) { + draw.rect(&state.renderer, cast(draw.Rect)p.rect) + } +} diff --git a/src/player.odin b/src/player.odin index e098167..1dd79ae 100644 --- a/src/player.odin +++ b/src/player.odin @@ -2,7 +2,6 @@ package demonchime import "core:fmt" import "core:math" -import "core:math/linalg" import sapp "shared:sokol/app" @@ -13,11 +12,12 @@ Player :: struct { vel: Vec2, anim: draw.Animation, sprite: draw.Sprite, + on_floor: bool } PLAYER_SPEED :: 100 PLAYER_ACCEL :: 10 -PLAYER_JUMP_FORCE :: 300 +PLAYER_JUMP_FORCE :: 350 init_player :: proc(p: ^Player) { p.pos = Vec2{50, 50} @@ -58,7 +58,7 @@ update_player :: proc(p: ^Player, dt: f32) { draw.set_sprite_active_tag(&p.sprite, "down_idle") } - if is_keybind_down(state.input, state.input.jump) && p.pos.y >= 256 { + if is_keybind_down(state.input, state.input.jump) && p.on_floor { p.vel.y = -PLAYER_JUMP_FORCE } @@ -69,18 +69,52 @@ update_player :: proc(p: ^Player, dt: f32) { ) p.vel.y = math.min(p.vel.y + GRAVITY * dt, TERMINAL_VELOCITY) - p.pos += p.vel * dt - - if p.pos.y > 256 { - p.pos.y = 256 - p.vel.y = 0 + res_pos := p.pos + p.vel * dt + + rect_size := Vec2{f32(p.sprite.width), f32(p.sprite.height)} + rect_offset := Vec2{-rect_size.x / 2, -rect_size.y} + + rect := Rect{ + res_pos + rect_offset, + rect_size, } + p.on_floor = false + + iter := iter_entity_list(state.platform_list) + for plat in entity_list_iter(&iter) { + if aabb(rect, plat.rect) { + prev_rect := Rect{ + p.pos + rect_offset, + rect_size, + } + if aabb_hori(prev_rect, plat.rect) { + if p.vel.y > 0 { + res_pos.y = plat.rect.start.y - rect.size.y - rect_offset.y + p.on_floor = true + } else { + res_pos.y = plat.rect.start.y + plat.rect.size.y - rect_offset.y + } + p.vel.y = 0 + } else if aabb_vert(prev_rect, plat.rect) { + if p.vel.x > 0 { + res_pos.x = plat.rect.start.x - rect.size.x - rect_offset.x + } else { + res_pos.x = plat.rect.start.x + plat.rect.size.x - rect_offset.x + } + p.vel.x = 0 + } + } + } + + p.pos = res_pos + p.sprite.pos = p.pos draw.update_sprite(&p.sprite, dt) } draw_player :: proc(p: Player) { - draw.draw_sprite(&state.renderer, p.sprite) + draw.sprite(&state.renderer, p.sprite) } + |
