Skip to content

Commit

Permalink
enemy attack
Browse files Browse the repository at this point in the history
  • Loading branch information
tsukinoko-kun committed Jul 8, 2024
1 parent d890da7 commit c08cd86
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 19 deletions.
8 changes: 3 additions & 5 deletions src/anim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

use std::cmp;

use bevy::prelude::*;

#[derive(Component, Debug)]
Expand All @@ -42,10 +40,10 @@ fn animate_sprite(
for (indices, mut timer, mut atlas) in &mut query {
timer.tick(time.delta());
if timer.just_finished() {
atlas.index = if atlas.index == indices.last {
indices.first
atlas.index = if atlas.index >= indices.first && atlas.index < indices.last {
atlas.index + 1
} else {
cmp::min(atlas.index + 1, indices.last)
indices.first
};
}
}
Expand Down
90 changes: 77 additions & 13 deletions src/enemy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,40 @@ use crate::player::Player;
use crate::projectile::Projectile;

const ENEMY_SPEED: f32 = 40.0;
const ENEMY_THRESHOLD: f32 = ENEMY_SPEED;
const ENEMY_THRESHOLD: f32 = ENEMY_SPEED * 2.0;
const ENEMY_MAX_COUNT: usize = 10;

pub struct EnemyPlugin;

#[derive(Debug)]
enum EnemyState {
Hunting,
ReadyBlade,
SwingBlade,
}

#[derive(Debug)]
enum Face {
Left,
Right,
}

#[derive(Component, Debug)]
pub struct Enemy;
pub struct Enemy {
animation_state: EnemyState,
face: Face,
sword_hit_timer: Timer,
}

impl Default for Enemy {
fn default() -> Self {
Self {
animation_state: EnemyState::Hunting,
face: Face::Left,
sword_hit_timer: Timer::from_seconds(0.5, TimerMode::Repeating),
}
}
}

fn spawn_enemy(
mut commands: Commands,
Expand All @@ -58,10 +85,10 @@ fn spawn_enemy(

let radius = rng.next_u32() as f32 / u32::MAX as f32 * 2.0 * std::f32::consts::PI;
let distance =
rng.next_u32() as f32 / u32::MAX as f32 * ENEMY_SPEED * 20.0 + ENEMY_SPEED * 20.0;
rng.next_u32() as f32 / u32::MAX as f32 * ENEMY_SPEED * 10.0 + ENEMY_SPEED * 17.5;

commands.spawn((
Enemy,
Enemy::default(),
Health::new(1),
SpriteBundle {
texture,
Expand All @@ -85,6 +112,31 @@ fn spawn_enemy(
}
}

fn enemy_attack(
mut enemy_q: Query<(&mut Enemy, &GlobalTransform)>,
player_q: Query<&Transform, With<Player>>,
time: Res<Time>,
) {
for (mut enemy, enemy_transform) in enemy_q.iter_mut() {
enemy.sword_hit_timer.tick(time.delta());
if !enemy.sword_hit_timer.finished() {
continue;
}
for player_transform in player_q.iter() {
let direction = player_transform.translation - enemy_transform.translation();
if direction.length() <= ENEMY_THRESHOLD {
enemy.animation_state = match enemy.animation_state {
EnemyState::Hunting => EnemyState::ReadyBlade,
EnemyState::SwingBlade => EnemyState::ReadyBlade,
EnemyState::ReadyBlade => EnemyState::SwingBlade,
};
} else {
enemy.animation_state = EnemyState::Hunting;
}
}
}
}

fn projectile_hit_enemy(
mut commands: Commands,
mut enemy_q: Query<(Entity, &Transform, &mut Health), With<Enemy>>,
Expand Down Expand Up @@ -113,7 +165,7 @@ fn update_position(
if let Ok(player_transform) = player_transform_q.get_single() {
for (enemy_transform, mut enemy_vel) in &mut enemy_q.iter_mut() {
let direction = player_transform.translation - enemy_transform.translation;
if direction.length() > ENEMY_THRESHOLD {
if direction.length() >= ENEMY_THRESHOLD {
enemy_vel.direction = direction.normalize();
} else {
enemy_vel.direction = Vec3::ZERO;
Expand All @@ -122,24 +174,36 @@ fn update_position(
}
}

fn update_animation(mut enemy_q: Query<(&Velocity, &mut AnimationIndices), With<Enemy>>) {
for (velocity, mut indices) in &mut enemy_q {
fn update_animation(mut enemy_q: Query<(&mut Enemy, &Velocity, &mut AnimationIndices)>) {
for (mut enemy, velocity, mut animation_indices) in enemy_q.iter_mut() {
if velocity.direction.x < 0.0 {
indices.first = 0;
indices.last = 1;
enemy.face = Face::Left;
} else if velocity.direction.x > 0.0 {
indices.first = 2;
indices.last = 3;
} else {
indices.last = indices.first;
enemy.face = Face::Right;
}

animation_indices.first = match enemy.animation_state {
EnemyState::Hunting => 0,
EnemyState::ReadyBlade => 4,
EnemyState::SwingBlade => 8,
} + match enemy.face {
Face::Left => 0,
Face::Right => 2,
};

animation_indices.last = if velocity.direction.length() > 0.0 {
animation_indices.first + 1
} else {
animation_indices.first
};
}
}

impl Plugin for EnemyPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, spawn_enemy)
.add_systems(Update, update_position)
.add_systems(Update, enemy_attack)
.add_systems(Update, update_animation)
.add_systems(Update, projectile_hit_enemy);
}
Expand Down
2 changes: 1 addition & 1 deletion src/projectile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl ProjectileBundle {
timer: AnimationTimer(Timer::from_seconds(0.125, TimerMode::Repeating)),
},
moving_object: MovingObjectBundle {
velocity: Velocity::from_vec2(direction, 200.0),
velocity: Velocity::from_vec2(direction, 512.0),
},
}
}
Expand Down

0 comments on commit c08cd86

Please sign in to comment.