fix: Поправил физику коллизий
This commit is contained in:
+24
-34
@@ -7,16 +7,15 @@ import rl "vendor:raylib"
|
|||||||
ent_handle :: hm.Handle32
|
ent_handle :: hm.Handle32
|
||||||
|
|
||||||
Entity :: struct {
|
Entity :: struct {
|
||||||
position: rl.Vector2,
|
position: rl.Vector2,
|
||||||
hp: i32,
|
hp: i32,
|
||||||
speed: f32,
|
speed: f32,
|
||||||
col: f32,
|
walk_speed: f32,
|
||||||
|
col: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
Player :: struct {
|
Player :: struct {
|
||||||
using ent: Entity,
|
using ent: Entity,
|
||||||
walk_speed: f32,
|
|
||||||
run_speed: f32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Enemy :: struct {
|
Enemy :: struct {
|
||||||
@@ -41,12 +40,6 @@ update_player :: proc(player: ^Player, dt: f32) {
|
|||||||
}
|
}
|
||||||
input = rl.Vector2Normalize(input)
|
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
|
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)
|
ra := calc_col_box(a.position, a.col)
|
||||||
rb := calc_col_box(b.position, b.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_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)
|
overlap_y := min(ra.y + ra.height - rb.y, rb.y + rb.height - ra.y)
|
||||||
|
|
||||||
|
dx, dy: f32
|
||||||
if overlap_x < overlap_y {
|
if overlap_x < overlap_y {
|
||||||
half := overlap_x / 2
|
dx = overlap_x if a.position.x < b.position.x else -overlap_x
|
||||||
if a.position.x < b.position.x {
|
|
||||||
a.position.x -= half
|
|
||||||
b.position.x += half
|
|
||||||
} else {
|
|
||||||
a.position.x += half
|
|
||||||
b.position.x -= half
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
half := overlap_y / 2
|
dy = overlap_y if a.position.y < b.position.y else -overlap_y
|
||||||
if a.position.y < b.position.y {
|
|
||||||
a.position.y -= half
|
|
||||||
b.position.y += half
|
|
||||||
} else {
|
|
||||||
a.position.y += half
|
|
||||||
b.position.y -= half
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
resolve_collisions :: proc(scene: ^Scene) {
|
||||||
it := hm.iterator_make(&scene.enemies)
|
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)
|
it2 := hm.iterator_make(&scene.enemies)
|
||||||
for j, _ in hm.iterate(&it2) {
|
for j, hj in hm.iterate(&it2) {
|
||||||
if i == j do continue
|
if hj.idx <= hi.idx do continue
|
||||||
resolve_entity_overlap(i, j)
|
resolve_entity_overlap(i, j)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it = hm.iterator_make(&scene.enemies)
|
it = hm.iterator_make(&scene.enemies)
|
||||||
for i, _ in hm.iterate(&it) {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ create_scene :: proc() -> Scene {
|
|||||||
position = rl.Vector2{100, 100},
|
position = rl.Vector2{100, 100},
|
||||||
hp = 100,
|
hp = 100,
|
||||||
walk_speed = 300,
|
walk_speed = 300,
|
||||||
run_speed = 500,
|
speed = 300,
|
||||||
col = 32,
|
col = 32,
|
||||||
},
|
},
|
||||||
camera = rl.Camera2D {
|
camera = rl.Camera2D {
|
||||||
@@ -38,24 +38,24 @@ create_scene :: proc() -> Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// _ = hm.add(
|
_ = hm.add(
|
||||||
// &scene.enemies,
|
&scene.enemies,
|
||||||
// Enemy {
|
Enemy {
|
||||||
// position = rl.Vector2{500, 500},
|
position = rl.Vector2{500, 500},
|
||||||
// hp = 100,
|
hp = 100,
|
||||||
// speed = 100,
|
speed = 100,
|
||||||
// col = 32,
|
col = 32,
|
||||||
// },
|
},
|
||||||
// )
|
)
|
||||||
// _ = hm.add(
|
_ = hm.add(
|
||||||
// &scene.enemies,
|
&scene.enemies,
|
||||||
// Enemy {
|
Enemy {
|
||||||
// position = rl.Vector2{600, 600},
|
position = rl.Vector2{600, 600},
|
||||||
// hp = 100,
|
hp = 100,
|
||||||
// speed = 100,
|
speed = 100,
|
||||||
// col = 32,
|
col = 32,
|
||||||
// },
|
},
|
||||||
// )
|
)
|
||||||
|
|
||||||
scene.atlas = load_atlas()
|
scene.atlas = load_atlas()
|
||||||
|
|
||||||
@@ -89,18 +89,12 @@ draw_scene :: proc(scene: ^Scene) {
|
|||||||
rl.WHITE,
|
rl.WHITE,
|
||||||
)
|
)
|
||||||
|
|
||||||
// for tile in scene.tiles {
|
|
||||||
// if tile.atlas == nil do continue
|
|
||||||
// draw_tile(tile)
|
|
||||||
// }
|
|
||||||
|
|
||||||
rl.DrawCircle(
|
rl.DrawCircle(
|
||||||
cast(i32)scene.player.position.x,
|
cast(i32)scene.player.position.x,
|
||||||
cast(i32)scene.player.position.y,
|
cast(i32)scene.player.position.y,
|
||||||
32,
|
32,
|
||||||
rl.GREEN,
|
rl.GREEN,
|
||||||
)
|
)
|
||||||
rl.DrawRectangle(300, 300, 100, 100, rl.BLUE)
|
|
||||||
|
|
||||||
it := hm.iterator_make(&scene.enemies)
|
it := hm.iterator_make(&scene.enemies)
|
||||||
for i, _ in hm.iterate(&it) {
|
for i, _ in hm.iterate(&it) {
|
||||||
@@ -121,7 +115,8 @@ render_map :: proc(atlas: ^Atlas, map_data: Map) -> rl.RenderTexture2D {
|
|||||||
rl.BeginTextureMode(tex)
|
rl.BeginTextureMode(tex)
|
||||||
for layer in map_data.layers {
|
for layer in map_data.layers {
|
||||||
for row_data, row in layer.data {
|
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 {
|
for tile_id, col in row_data {
|
||||||
offset, empty := get_offset(atlas, tile_id)
|
offset, empty := get_offset(atlas, tile_id)
|
||||||
if empty do continue
|
if empty do continue
|
||||||
|
|||||||
Reference in New Issue
Block a user