diff --git a/entity.odin b/entity.odin index 647627a..83187ff 100644 --- a/entity.odin +++ b/entity.odin @@ -7,16 +7,15 @@ import rl "vendor:raylib" ent_handle :: hm.Handle32 Entity :: struct { - position: rl.Vector2, - hp: i32, - speed: f32, - col: f32, + position: rl.Vector2, + hp: i32, + speed: f32, + walk_speed: f32, + col: f32, } Player :: struct { - using ent: Entity, - walk_speed: f32, - run_speed: f32, + using ent: Entity, } Enemy :: struct { @@ -41,12 +40,6 @@ update_player :: proc(player: ^Player, dt: f32) { } input = rl.Vector2Normalize(input) - if rl.IsKeyDown(.LEFT_SHIFT) { - player.speed = player.run_speed - } else { - player.speed = player.walk_speed - } - player.position += input * player.speed * dt } @@ -60,7 +53,9 @@ calc_col_box :: proc(center: rl.Vector2, side: f32) -> rl.Rectangle { } -resolve_entity_overlap :: proc(a, b: ^Entity) { +// разводит пересёкшиеся боксы: b получает долю b_share правки, a — остаток. +// Враг-враг: пополам. Игрок-враг: враг поддаётся слабо (доля мала) — «вес» +resolve_entity_overlap :: proc(a, b: ^Entity, b_share: f32 = 0.5) { ra := calc_col_box(a.position, a.col) rb := calc_col_box(b.position, b.col) @@ -69,39 +64,34 @@ resolve_entity_overlap :: proc(a, b: ^Entity) { overlap_x := min(ra.x + ra.width - rb.x, rb.x + rb.width - ra.x) overlap_y := min(ra.y + ra.height - rb.y, rb.y + rb.height - ra.y) + dx, dy: f32 if overlap_x < overlap_y { - half := overlap_x / 2 - if a.position.x < b.position.x { - a.position.x -= half - b.position.x += half - } else { - a.position.x += half - b.position.x -= half - } + dx = overlap_x if a.position.x < b.position.x else -overlap_x } else { - half := overlap_y / 2 - if a.position.y < b.position.y { - a.position.y -= half - b.position.y += half - } else { - a.position.y += half - b.position.y -= half - } + dy = overlap_y if a.position.y < b.position.y else -overlap_y } + + a.position.x -= dx * (1 - b_share) + a.position.y -= dy * (1 - b_share) + b.position.x += dx * b_share + b.position.y += dy * b_share } resolve_collisions :: proc(scene: ^Scene) { it := hm.iterator_make(&scene.enemies) - for i, _ in hm.iterate(&it) { + for i, hi in hm.iterate(&it) { + // пары симметричны: пушим обе стороны, поэтому каждую обрабатываем один раз it2 := hm.iterator_make(&scene.enemies) - for j, _ in hm.iterate(&it2) { - if i == j do continue + for j, hj in hm.iterate(&it2) { + if hj.idx <= hi.idx do continue resolve_entity_overlap(i, j) } } it = hm.iterator_make(&scene.enemies) for i, _ in hm.iterate(&it) { - resolve_entity_overlap(&scene.player.ent, i) + // «вес»: враг поддаётся на 80%, игрок на 20% — враг упирается в игрока, + // а игрок выдавливает врага перед собой + resolve_entity_overlap(&scene.player.ent, i, b_share = 0.6) } } diff --git a/main.odin b/main.odin index 8481c27..0b20ba1 100644 --- a/main.odin +++ b/main.odin @@ -28,7 +28,7 @@ create_scene :: proc() -> Scene { position = rl.Vector2{100, 100}, hp = 100, walk_speed = 300, - run_speed = 500, + speed = 300, col = 32, }, camera = rl.Camera2D { @@ -38,24 +38,24 @@ create_scene :: proc() -> Scene { } - // _ = hm.add( - // &scene.enemies, - // Enemy { - // position = rl.Vector2{500, 500}, - // hp = 100, - // speed = 100, - // col = 32, - // }, - // ) - // _ = hm.add( - // &scene.enemies, - // Enemy { - // position = rl.Vector2{600, 600}, - // hp = 100, - // speed = 100, - // col = 32, - // }, - // ) + _ = hm.add( + &scene.enemies, + Enemy { + position = rl.Vector2{500, 500}, + hp = 100, + speed = 100, + col = 32, + }, + ) + _ = hm.add( + &scene.enemies, + Enemy { + position = rl.Vector2{600, 600}, + hp = 100, + speed = 100, + col = 32, + }, + ) scene.atlas = load_atlas() @@ -89,18 +89,12 @@ draw_scene :: proc(scene: ^Scene) { rl.WHITE, ) - // for tile in scene.tiles { - // if tile.atlas == nil do continue - // draw_tile(tile) - // } - rl.DrawCircle( cast(i32)scene.player.position.x, cast(i32)scene.player.position.y, 32, rl.GREEN, ) - rl.DrawRectangle(300, 300, 100, 100, rl.BLUE) it := hm.iterator_make(&scene.enemies) for i, _ in hm.iterate(&it) { @@ -121,7 +115,8 @@ render_map :: proc(atlas: ^Atlas, map_data: Map) -> rl.RenderTexture2D { rl.BeginTextureMode(tex) for layer in map_data.layers { for row_data, row in layer.data { - dest_y := f32(i32(map_data.height) - 1 - i32(row)) * atlas.tile_size.y + dest_y := + f32(i32(map_data.height) - 1 - i32(row)) * atlas.tile_size.y for tile_id, col in row_data { offset, empty := get_offset(atlas, tile_id) if empty do continue