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::{
|
use crate::{
|
||||||
collision::Collider,
|
collision::Collider,
|
||||||
damagable::Damagable,
|
damagable::Damagable,
|
||||||
ships::{Factions, gun::Gun},
|
ships::{Factions, gun::Gun, player::PlayerMovement},
|
||||||
velocity::Velocity,
|
velocity::{self, Velocity},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Component)]
|
#[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) {
|
pub fn spawn_enemy(commands: &mut Commands, sprite: Handle<Image>, at: Vec2) {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
Enemy,
|
Enemy {
|
||||||
Gun::new(5, f32::to_radians(15.), 0.2),
|
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.),
|
Collider::new(8.),
|
||||||
Velocity::stopped(500., f32::to_radians(360.)),
|
Velocity::moving(256., f32::to_radians(360.)),
|
||||||
Sprite::from(sprite),
|
Sprite::from(sprite),
|
||||||
Transform::from_xyz(at.x, at.y, 0.),
|
Transform::from_xyz(at.x, at.y, 0.),
|
||||||
Damagable::new(100),
|
Damagable::new(100),
|
||||||
Factions::EnemyFaction,
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ impl Plugin for ShipsPlugin {
|
||||||
player::player_movement_system.run_if(in_state(GameState::Game)),
|
player::player_movement_system.run_if(in_state(GameState::Game)),
|
||||||
player::player_shooting_system.run_if(in_state(GameState::Game)),
|
player::player_shooting_system.run_if(in_state(GameState::Game)),
|
||||||
gun::gun_shooting_system.run_if(in_state(GameState::Game)),
|
gun::gun_shooting_system.run_if(in_state(GameState::Game)),
|
||||||
|
enemy::enemy_ai_system,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
collision::Collider,
|
collision::Collider,
|
||||||
damagable::Damagable,
|
damagable::Damagable,
|
||||||
projectile::ProjectileSprite,
|
ships::{Factions, enemy::Enemy, gun::Gun},
|
||||||
ships::{Factions, gun::Gun},
|
|
||||||
velocity::Velocity,
|
velocity::Velocity,
|
||||||
};
|
};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use rand::random_range;
|
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
#[require(Velocity)]
|
#[require(Velocity)]
|
||||||
|
|
@ -92,7 +90,7 @@ pub(super) fn player_movement_system(
|
||||||
|
|
||||||
pub fn player_shooting_system(
|
pub fn player_shooting_system(
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
query: Single<&mut Gun, With<PlayerMovement>>,
|
query: Single<&mut Gun, (With<PlayerMovement>, Without<Enemy>)>,
|
||||||
) {
|
) {
|
||||||
let mut gun = query.into_inner();
|
let mut gun = query.into_inner();
|
||||||
gun.shoot = keyboard_input.pressed(KeyCode::Space);
|
gun.shoot = keyboard_input.pressed(KeyCode::Space);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue