98 lines
2.4 KiB
Odin
98 lines
2.4 KiB
Odin
package main
|
|
|
|
|
|
import hm "core:container/handle_map"
|
|
import rl "vendor:raylib"
|
|
|
|
ent_handle :: hm.Handle32
|
|
|
|
Entity :: struct {
|
|
position: rl.Vector2,
|
|
hp: i32,
|
|
speed: f32,
|
|
walk_speed: f32,
|
|
col: f32,
|
|
}
|
|
|
|
Player :: struct {
|
|
using ent: Entity,
|
|
}
|
|
|
|
Enemy :: struct {
|
|
using ent: Entity,
|
|
handle: ent_handle,
|
|
}
|
|
|
|
|
|
update_player :: proc(player: ^Player, dt: f32) {
|
|
input: rl.Vector2
|
|
if rl.IsKeyDown(.W) {
|
|
input.y += -1
|
|
}
|
|
if rl.IsKeyDown(.D) {
|
|
input.x += 1
|
|
}
|
|
if rl.IsKeyDown(.S) {
|
|
input.y += 1
|
|
}
|
|
if rl.IsKeyDown(.A) {
|
|
input.x += -1
|
|
}
|
|
input = rl.Vector2Normalize(input)
|
|
|
|
player.position += input * player.speed * dt
|
|
}
|
|
|
|
calc_col_box :: proc(center: rl.Vector2, side: f32) -> rl.Rectangle {
|
|
return rl.Rectangle {
|
|
x = center.x - side / 2,
|
|
y = center.y - side / 2,
|
|
width = side,
|
|
height = side,
|
|
}
|
|
}
|
|
|
|
|
|
// разводит пересёкшиеся боксы: 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)
|
|
|
|
if !rl.CheckCollisionRecs(ra, rb) do return
|
|
|
|
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 {
|
|
dx = overlap_x if a.position.x < b.position.x else -overlap_x
|
|
} else {
|
|
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, hi in hm.iterate(&it) {
|
|
// пары симметричны: пушим обе стороны, поэтому каждую обрабатываем один раз
|
|
it2 := hm.iterator_make(&scene.enemies)
|
|
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) {
|
|
// «вес»: враг поддаётся на 80%, игрок на 20% — враг упирается в игрока,
|
|
// а игрок выдавливает врага перед собой
|
|
resolve_entity_overlap(&scene.player.ent, i, b_share = 0.6)
|
|
}
|
|
}
|