Enemy AI
This commit is contained in:
parent
9b1d780bf9
commit
abb0198a2b
3 changed files with 88 additions and 10 deletions
|
|
@ -3,22 +3,101 @@ use bevy::prelude::*;
|
|||
use crate::{
|
||||
collision::Collider,
|
||||
damagable::Damagable,
|
||||
ships::{Factions, gun::Gun},
|
||||
velocity::Velocity,
|
||||
ships::{Factions, gun::Gun, player::PlayerMovement},
|
||||
velocity::{self, Velocity},
|
||||
};
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Enemy;
|
||||
pub struct Enemy {
|
||||
state: EnemyState,
|
||||
return_radius: f32,
|
||||
search_arc: f32,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum EnemyState {
|
||||
Approaching,
|
||||
OriginalViolence,
|
||||
Distancing,
|
||||
}
|
||||
|
||||
pub fn spawn_enemy(commands: &mut Commands, sprite: Handle<Image>, at: Vec2) {
|
||||
commands.spawn((
|
||||
Enemy,
|
||||
Gun::new(5, f32::to_radians(15.), 0.2),
|
||||
Enemy {
|
||||
state: EnemyState::Approaching,
|
||||
return_radius: 128.0,
|
||||
search_arc: f32::to_radians(5.),
|
||||
},
|
||||
Gun::new(2, f32::to_radians(15.), 0.2),
|
||||
Collider::new(8.),
|
||||
Velocity::stopped(500., f32::to_radians(360.)),
|
||||
Velocity::moving(256., f32::to_radians(360.)),
|
||||
Sprite::from(sprite),
|
||||
Transform::from_xyz(at.x, at.y, 0.),
|
||||
Damagable::new(100),
|
||||
Factions::EnemyFaction,
|
||||
));
|
||||
}
|
||||
|
||||
pub fn enemy_ai_system(
|
||||
player_query: Single<&Transform, (With<PlayerMovement>, Without<Enemy>)>,
|
||||
enemies_query: Query<
|
||||
(&mut Velocity, &mut Enemy, &mut Gun, &Transform),
|
||||
Without<PlayerMovement>,
|
||||
>,
|
||||
) {
|
||||
let player_transform = player_query.into_inner();
|
||||
for (mut enemy_velocity, mut enemy, mut gun, enemy_transform) in enemies_query {
|
||||
let direction = enemy_transform.rotation * Vec3::X;
|
||||
let left_side = enemy_transform.rotation * Vec3::Y;
|
||||
let dir_to_player = player_transform.translation - enemy_transform.translation;
|
||||
let distance_to_player = enemy_transform
|
||||
.translation
|
||||
.distance_squared(player_transform.translation);
|
||||
match enemy.state {
|
||||
EnemyState::Approaching => {
|
||||
if direction.angle_between(dir_to_player) <= enemy.search_arc {
|
||||
enemy_velocity.rotation_speed = 0.;
|
||||
gun.shoot = true;
|
||||
enemy.state = EnemyState::OriginalViolence;
|
||||
enemy_velocity.linear_speed = enemy_velocity.max_linear_speed / 2.0;
|
||||
continue;
|
||||
}
|
||||
|
||||
enemy_velocity.rotation_speed =
|
||||
enemy_velocity.max_rotation_speed * (left_side.dot(dir_to_player)).signum();
|
||||
}
|
||||
EnemyState::OriginalViolence => {
|
||||
gun.shoot = true;
|
||||
if direction.angle_between(dir_to_player) > enemy.search_arc {
|
||||
enemy_velocity.linear_speed = enemy_velocity.max_linear_speed;
|
||||
enemy.state = EnemyState::Approaching;
|
||||
gun.shoot = false;
|
||||
continue;
|
||||
}
|
||||
if distance_to_player <= enemy.return_radius * enemy.return_radius {
|
||||
enemy_velocity.linear_speed = enemy_velocity.max_linear_speed;
|
||||
enemy.state = EnemyState::Distancing;
|
||||
gun.shoot = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
EnemyState::Distancing => {
|
||||
if distance_to_player > enemy.return_radius * enemy.return_radius {
|
||||
enemy.state = EnemyState::Approaching;
|
||||
continue;
|
||||
}
|
||||
if direction.angle_between(dir_to_player) > f32::to_radians(90.) {
|
||||
enemy_velocity.rotation_speed = 0.;
|
||||
continue;
|
||||
}
|
||||
|
||||
let angle_to_left = direction.angle_between(left_side);
|
||||
if angle_to_left <= f32::to_radians(90.) {
|
||||
enemy_velocity.rotation_speed = -enemy_velocity.max_rotation_speed
|
||||
} else {
|
||||
enemy_velocity.rotation_speed = enemy_velocity.max_rotation_speed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue