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) } }