Add a bunch of stuff (kill stats)

This commit is contained in:
Paul Brinkmeier 2022-02-20 14:15:39 +01:00
parent ce070ce4be
commit ba8cc16782
3 changed files with 180 additions and 45 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
/target /target
*.DS_Store

Binary file not shown.

View File

@ -4,11 +4,9 @@ use bevy::core::{FixedTimestep, Time, Timer};
use bevy::input::system::exit_on_esc_system; use bevy::input::system::exit_on_esc_system;
use bevy::input::Input; use bevy::input::Input;
use bevy::math::Vec3; use bevy::math::Vec3;
use bevy::prelude::{ use bevy::prelude::*;
App, AssetServer, Commands, Component, Entity, KeyCode, OrthographicCameraBundle, Query, Res,
SystemSet, Transform, Without,
};
use bevy::sprite::{Sprite, SpriteBundle}; use bevy::sprite::{Sprite, SpriteBundle};
use bevy::text::Text;
use bevy::window::Windows; use bevy::window::Windows;
use bevy::DefaultPlugins; use bevy::DefaultPlugins;
use rand::Rng; use rand::Rng;
@ -16,6 +14,7 @@ use rand::Rng;
fn main() { fn main() {
App::new() App::new()
.add_plugins(DefaultPlugins) .add_plugins(DefaultPlugins)
.insert_resource(ArnoldStats::new())
.add_startup_system(setup) .add_startup_system(setup)
.add_system_set( .add_system_set(
SystemSet::new() SystemSet::new()
@ -26,7 +25,8 @@ fn main() {
.with_system(linear_movement_system) .with_system(linear_movement_system)
.with_system(expiration_date_system) .with_system(expiration_date_system)
.with_system(follow_arnold_system) .with_system(follow_arnold_system)
.with_system(enemy_spawner_system), .with_system(enemy_spawner_system)
.with_system(update_scoreboard_system),
) )
.add_system(exit_on_esc_system) .add_system(exit_on_esc_system)
.run(); .run();
@ -35,60 +35,162 @@ fn main() {
fn setup(mut commands: Commands, assets: Res<AssetServer>) { fn setup(mut commands: Commands, assets: Res<AssetServer>) {
let arnold_sh = assets.load("arno.png"); let arnold_sh = assets.load("arno.png");
// cameras
commands.spawn_bundle(OrthographicCameraBundle::new_2d()); commands.spawn_bundle(OrthographicCameraBundle::new_2d());
commands.spawn_bundle(UiCameraBundle::default());
// arnold himself
commands commands
.spawn_bundle(SpriteBundle { .spawn_bundle(SpriteBundle {
texture: arnold_sh, texture: arnold_sh,
..Default::default() ..Default::default()
}) })
.insert(EnemySpawner::new(Timer::from_seconds(3.0, true)))
.insert(Arnold::new()) .insert(Arnold::new())
.insert(Transform { .insert(Transform {
translation: Vec3::new(0.0, 0.0, 0.0), translation: Vec3::new(0.0, 0.0, 0.0),
..Default::default() ..Default::default()
}); });
// enemy spawner
commands
.spawn()
.insert(EnemySpawner::new(Timer::from_seconds(3.0, true)));
// scoreboard
commands
.spawn_bundle(TextBundle {
text: Text {
sections: vec![
TextSection {
style: TextStyle {
font: assets.load("fonts/PressStart2P-Regular.ttf"),
font_size: 15.0,
color: Color::WHITE,
},
value: "kills: ".to_string(),
},
TextSection {
style: TextStyle {
font: assets.load("fonts/PressStart2P-Regular.ttf"),
font_size: 15.0,
color: Color::RED,
},
value: "0".to_string(),
},
],
..Default::default()
},
style: Style {
position_type: PositionType::Absolute,
position: Rect {
top: Val::Px(5.0),
left: Val::Px(5.0),
..Default::default()
},
..Default::default()
},
..Default::default()
})
.insert(ScoreBoard);
}
// Unit struct for tracking the ScoreBoard Text UI
#[derive(Component)]
struct ScoreBoard;
fn update_scoreboard_system(
stats: Res<ArnoldStats>,
mut query: Query<&mut Text, With<ScoreBoard>>,
) {
query.single_mut().sections[1].value = format!("{}", stats.kills);
}
struct ArnoldStats {
damage_dealt: i32,
kills: i32,
}
impl ArnoldStats {
fn new() -> Self {
Self {
damage_dealt: 0,
kills: 0,
}
}
} }
#[derive(Component)] #[derive(Component)]
struct Projectile { struct Projectile {
damage: i32,
} }
impl Projectile { impl Projectile {
fn new() -> Self { fn new(damage: i32) -> Self {
Self {} Self { damage }
} }
} }
#[derive(Component)] #[derive(Component)]
struct Hitpoints { struct Hitpoints {
hp: i32,
} }
impl Hitpoints { impl Hitpoints {
fn new() -> Self { fn new(hp: i32) -> Self {
Self {} Self { hp }
} }
} }
fn projectile_collide_system( fn projectile_collide_system(
mut commands: Commands, mut commands: Commands,
mut stats: ResMut<ArnoldStats>,
assets: Res<AssetServer>,
projectile_query: Query<(&Projectile, &Transform)>, projectile_query: Query<(&Projectile, &Transform)>,
target_query: Query<(Entity, &Hitpoints, &Transform)> mut target_query: Query<(Entity, &mut Hitpoints, &Transform)>,
) { ) {
for (entity, _hp, target_transform) in target_query.iter() { for (entity, mut hp, target_transform) in target_query.iter_mut() {
let mut has_been_hit = false; for (projectile, projectile_transform) in projectile_query.iter() {
for (_projectile, projectile_transform) in projectile_query.iter() { if target_transform
if target_transform.translation.distance(projectile_transform.translation) < 32.0 { .translation
has_been_hit = true; .distance(projectile_transform.translation)
< 32.0
{
hp.hp -= projectile.damage;
stats.damage_dealt += projectile.damage;
let font = assets.load("fonts/PressStart2P-Regular.ttf");
let text_style = TextStyle {
font,
font_size: 10.0,
color: Color::YELLOW,
};
let text_alignment = TextAlignment {
vertical: VerticalAlign::Center,
horizontal: HorizontalAlign::Center,
};
commands
.spawn_bundle(Text2dBundle {
text: Text::with_section(
&format!("{}", projectile.damage),
text_style,
text_alignment,
),
transform: Transform {
translation: target_transform.translation + Vec3::new(0.0, 10.0, 10.0),
..Default::default()
},
..Default::default()
})
.insert(ExpirationDate::new(3.0))
.insert(LinearMovement::new(Vec3::new(0.0, 0.5, 0.0)));
} }
} }
if has_been_hit { if hp.hp <= 0 {
stats.kills += 1;
commands.entity(entity).despawn(); commands.entity(entity).despawn();
} }
} }
} }
#[derive(PartialEq)] #[derive(Clone, Copy, PartialEq)]
enum Facing { enum Facing {
Left, Left,
Right, Right,
@ -141,8 +243,10 @@ struct ExpirationDate {
} }
impl ExpirationDate { impl ExpirationDate {
fn new(countdown: Timer) -> Self { fn new(duration: f32) -> Self {
Self { countdown } Self {
countdown: Timer::from_seconds(duration, false),
}
} }
} }
@ -200,30 +304,14 @@ fn arnold_attack_system(
let (mut arnold, arnold_transform) = query.single_mut(); let (mut arnold, arnold_transform) = query.single_mut();
if arnold.attack_timer.tick(time.delta()).just_finished() { if arnold.attack_timer.tick(time.delta()).just_finished() {
let knife_velocity = match arnold.facing { commands.spawn_bundle(KnifeBundle::new(
Facing::Left => Vec3::new(-1.0, 0.0, 0.0), assets.load("knife.png"),
Facing::Right => Vec3::new(1.0, 0.0, 0.0), arnold_transform.translation + Vec3::new(0.0, 0.0, 10.0),
} * 4.0; arnold.facing,
4.0,
commands 5.0,
.spawn_bundle(SpriteBundle { 10,
texture: assets.load("knife.png"), ));
sprite: Sprite {
flip_x: arnold.facing == Facing::Left,
..Default::default()
},
..Default::default()
})
.insert(Knife::new())
.insert(Transform {
translation: arnold_transform.translation
+ Vec3::new(0.0, 0.0, 10.0)
+ knife_velocity,
..Default::default()
})
.insert(LinearMovement::new(knife_velocity))
.insert(ExpirationDate::new(Timer::from_seconds(5.0, false)))
.insert(Projectile::new());
} }
} }
@ -267,7 +355,53 @@ fn enemy_spawner_system(
..Default::default() ..Default::default()
}) })
.insert(FollowArnold::new(1.0)) .insert(FollowArnold::new(1.0))
.insert(Hitpoints::new()); .insert(Hitpoints::new(8));
}
#[derive(Bundle)]
struct KnifeBundle {
_knife: Knife,
#[bundle]
sprite: SpriteBundle,
lin_movement: LinearMovement,
exp_date: ExpirationDate,
projectile: Projectile,
}
impl KnifeBundle {
fn new(
texture: Handle<Image>,
translation: Vec3,
facing: Facing,
speed: f32,
lifetime: f32,
damage: i32,
) -> Self {
let velocity = match facing {
Facing::Left => Vec3::new(-1.0, 0.0, 0.0),
Facing::Right => Vec3::new(1.0, 0.0, 0.0),
} * speed;
let flip_x = velocity.x < 0.0;
KnifeBundle {
_knife: Knife::new(),
sprite: SpriteBundle {
texture,
sprite: Sprite {
flip_x,
..Default::default()
},
transform: Transform {
translation,
..Default::default()
},
..Default::default()
},
lin_movement: LinearMovement::new(velocity),
exp_date: ExpirationDate::new(lifetime),
projectile: Projectile::new(damage),
}
}
} }
#[derive(Component)] #[derive(Component)]