Setup basic enemy information and make enemy use flow field.
This commit is contained in:
+55
-4
@@ -16,7 +16,9 @@ Enemy :: struct {
|
||||
|
||||
// movement
|
||||
velocity: rl.Vector2,
|
||||
speed: f32,
|
||||
speed: f32, // max move speed
|
||||
accel: f32, // how fast to reach speed
|
||||
friction: f32, // how fast to stop
|
||||
|
||||
// collision
|
||||
collider_offset: rl.Vector2,
|
||||
@@ -27,10 +29,14 @@ Enemy :: struct {
|
||||
enemy_init :: proc(assets: ^Enemy_Assets, pos: [2]f32) -> Enemy {
|
||||
enemy := Enemy{}
|
||||
enemy.position = {pos.x, pos.y}
|
||||
enemy.speed = 100
|
||||
enemy.accel = 720
|
||||
enemy.friction = 640
|
||||
|
||||
enemy.state = .IDLE
|
||||
enemy.collider_offset = rl.Vector2{8, 15}
|
||||
enemy.collider_w = 16
|
||||
enemy.collider_h = 10
|
||||
enemy.collider_w = 12
|
||||
enemy.collider_h = 8
|
||||
animation_play(&enemy.animation, &assets.clips[.IDLE])
|
||||
|
||||
return enemy
|
||||
@@ -45,6 +51,13 @@ get_enemy_collider :: proc(enemy: Enemy, pos: rl.Vector2) -> rl.Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
get_enemy_center :: proc(enemy: Enemy, pos: rl.Vector2) -> rl.Vector2 {
|
||||
collider := get_enemy_collider(enemy, pos)
|
||||
return rl.Vector2{
|
||||
collider.x + collider.width * 0.5,
|
||||
collider.y + collider.height * 0.5,
|
||||
}
|
||||
}
|
||||
|
||||
get_spawn_rect :: proc(max_x, max_y: f32) -> rl.Rectangle {
|
||||
enemy_spawn_points: [4]rl.Rectangle = {
|
||||
@@ -63,6 +76,7 @@ get_spawn_rect :: proc(max_x, max_y: f32) -> rl.Rectangle {
|
||||
return rand_pos
|
||||
}
|
||||
|
||||
|
||||
// @TODO consider a self check, ie pass the enemy in question index and make sure to skip that
|
||||
spawn_enemy :: proc(enemy_array: ^[MAX_ENEMIES]Enemy, assets: ^Enemy_Assets, enemy_count: ^int, game_map: Game_Map) {
|
||||
max_x := game_map.width_px
|
||||
@@ -91,10 +105,47 @@ spawn_enemy :: proc(enemy_array: ^[MAX_ENEMIES]Enemy, assets: ^Enemy_Assets, ene
|
||||
}
|
||||
}
|
||||
|
||||
update_enemies :: proc(enemy_array: ^[MAX_ENEMIES]Enemy, assets: ^Enemy_Assets, enemy_cnt: int, dt: f32) {
|
||||
update_enemies :: proc(enemy_array: ^[MAX_ENEMIES]Enemy, assets: ^Enemy_Assets, enemy_cnt: int, game_map: Game_Map, dt: f32) {
|
||||
for idx in 0..<enemy_cnt {
|
||||
enemy := &enemy_array[idx]
|
||||
moving := false
|
||||
dir := rl.Vector2{}
|
||||
|
||||
enemy_center := get_enemy_center(enemy^, enemy.position)
|
||||
enemy_grid_pos := world_to_grid(enemy_center)
|
||||
enemy_grid_index := grid_to_index(enemy_grid_pos.x, enemy_grid_pos.y, game_map.width)
|
||||
|
||||
// already normalized
|
||||
flow_dir := game_map.flow_field[enemy_grid_index]
|
||||
|
||||
// wall avoidance steering
|
||||
|
||||
target_velocity := flow_dir * enemy.speed
|
||||
|
||||
enemy.velocity = rl.Vector2MoveTowards(enemy.velocity, target_velocity, enemy.accel * dt)
|
||||
// Check for collisions
|
||||
new_position := enemy.velocity * dt
|
||||
new_x_pos := rl.Vector2{enemy.position.x + new_position.x, enemy.position.y}
|
||||
if
|
||||
!check_map_collision(get_enemy_collider(enemy^, new_x_pos), game_map)
|
||||
{
|
||||
enemy.position.x = new_x_pos.x
|
||||
moving = true
|
||||
} else {
|
||||
enemy.velocity.x = 0
|
||||
moving = false
|
||||
}
|
||||
|
||||
new_y_pos := rl.Vector2{enemy.position.x, enemy.position.y + new_position.y}
|
||||
if
|
||||
!check_map_collision(get_enemy_collider(enemy^, new_y_pos), game_map)
|
||||
{
|
||||
enemy.position.y = new_y_pos.y
|
||||
moving = true
|
||||
} else {
|
||||
enemy.velocity.y = 0
|
||||
moving = false
|
||||
}
|
||||
|
||||
enemy.state = moving ? .WALK : .IDLE
|
||||
animation_play(&enemy.animation, &assets.clips[enemy.state])
|
||||
|
||||
Reference in New Issue
Block a user