add lives

This commit is contained in:
Schrottkatze 2024-05-10 21:45:47 +02:00
parent 6a63d13395
commit 0d945de135
Signed by: schrottkatze
SSH key fingerprint: SHA256:hXb3t1vINBFCiDCmhRABHX5ocdbLiKyCdKI4HK2Rbbc
3 changed files with 141 additions and 12 deletions

View file

@ -7,7 +7,11 @@ use bevy_rand::prelude::*;
use bevy_rapier2d::prelude::*; use bevy_rapier2d::prelude::*;
use rand::Rng; use rand::Rng;
use crate::{player::Player, scene::SceneObj, METER}; use crate::{
player::{LifeChangeEvent, Player},
scene::SceneObj,
METER,
};
#[derive(Component)] #[derive(Component)]
struct SpawnTimer(pub Timer); struct SpawnTimer(pub Timer);
@ -27,7 +31,13 @@ pub fn spawner_plugin(app: &mut App) {
.add_systems(Startup, add_timer) .add_systems(Startup, add_timer)
.add_systems( .add_systems(
Update, Update,
(drop_crates, do_drop, crate_collisions, delete_on_env_coll), (
drop_crates,
do_drop,
crate_collisions,
delete_on_env_coll,
player_coll,
),
); );
} }
@ -130,10 +140,27 @@ fn delete_on_env_coll(mut ev_colls: EventReader<CrateCollision>, mut commands: C
if let CollisionType::Player(_) = with { if let CollisionType::Player(_) = with {
continue; continue;
} }
// let CollisionType::Scene(obj) = with else {
// unreachable!()
// };
commands.entity(*coll_crate).despawn(); if let Some(mut e) = commands.get_entity(*coll_crate) {
e.despawn();
}
}
}
fn player_coll(
mut ev_colls: EventReader<CrateCollision>,
mut ev_lives: EventWriter<LifeChangeEvent>,
mut commands: Commands,
) {
for CrateCollision { coll_crate, with } in ev_colls.read() {
if let CollisionType::Scene(_) = with {
continue;
}
ev_lives.send(LifeChangeEvent::Lost);
if let Some(mut e) = commands.get_entity(*coll_crate) {
e.despawn();
}
} }
} }

View file

@ -4,6 +4,7 @@ use bevy::{
}; };
use bevy_rapier2d::prelude::*; use bevy_rapier2d::prelude::*;
use drops::spawner_plugin; use drops::spawner_plugin;
use player::LifeChangeEvent;
const METER: f32 = 48.; const METER: f32 = 48.;
fn main() { fn main() {
@ -19,12 +20,12 @@ fn main() {
.insert_resource(rapier_config) .insert_resource(rapier_config)
.add_plugins(RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(METER)) .add_plugins(RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(METER))
.add_plugins(RapierDebugRenderPlugin::default()) .add_plugins(RapierDebugRenderPlugin::default())
.add_plugins((spawner_plugin)) .add_plugins((
.add_systems(Startup, (scene::setup_scene, setup_cam, player::add_player)) spawner_plugin,
.add_systems( game_state::state_and_ui_plugin,
Update, player::player_plugin,
(player::move_player, player::player_ground_collision), ))
) .add_systems(Startup, (scene::setup_scene, setup_cam))
.run() .run()
} }
@ -38,3 +39,62 @@ fn setup_cam(mut commands: Commands) {
mod drops; mod drops;
mod player; mod player;
mod scene; mod scene;
mod game_state {
use bevy::{prelude::*, time::Stopwatch};
#[derive(Component)]
pub struct GameState {
score: u32,
game_time: Stopwatch,
}
#[derive(Component)]
struct StateText;
pub fn state_and_ui_plugin(app: &mut App) {
app.add_systems(Startup, (setup_gamestate, setup_ui))
.add_systems(Update, (update_time));
}
fn setup_gamestate(mut commands: Commands) {
commands.spawn(GameState {
score: 0,
game_time: Stopwatch::new(),
});
}
fn setup_ui(mut commands: Commands) {
commands.spawn((
TextBundle::from_sections([
TextSection::new("Score: ", TextStyle::default()),
TextSection::new("0", TextStyle::default()),
TextSection::new("\n", TextStyle::default()),
TextSection::new("Time: ", TextStyle::default()),
TextSection::new("0", TextStyle::default()),
TextSection::new("s", TextStyle::default()),
])
.with_style(Style {
position_type: PositionType::Absolute,
top: Val::Px(5.0),
right: Val::Px(5.0),
..default()
}),
StateText,
));
}
fn update_time(
mut state_txt: Query<&mut Text, With<StateText>>,
mut game_state: Query<&mut GameState>,
time: Res<Time>,
) {
let mut txt = state_txt.single_mut();
let time = game_state
.single_mut()
.game_time
.tick(time.delta())
.elapsed_secs();
txt.sections[4].value = format!("{time:.2}");
}
}

View file

@ -11,6 +11,21 @@ use crate::METER;
pub struct Player { pub struct Player {
move_cooldown: Timer, move_cooldown: Timer,
grounded: bool, grounded: bool,
lives: u8,
}
#[derive(Event)]
pub enum LifeChangeEvent {
Gained,
Lost,
}
const DEFAULT_LIVES: u8 = 5;
pub fn player_plugin(app: &mut App) {
app.add_event::<LifeChangeEvent>()
.add_systems(Startup, (add_player, add_lives_ui))
.add_systems(Update, (move_player, player_ground_collision, update_lives));
} }
pub fn add_player( pub fn add_player(
@ -24,6 +39,7 @@ pub fn add_player(
move_cooldown: Timer::from_seconds(0.01, TimerMode::Repeating), move_cooldown: Timer::from_seconds(0.01, TimerMode::Repeating),
// move_cooldown: Timer::from_seconds(0.01, TimerMode::Repeating), // move_cooldown: Timer::from_seconds(0.01, TimerMode::Repeating),
grounded: false, grounded: false,
lives: DEFAULT_LIVES,
}) })
.insert(MaterialMesh2dBundle { .insert(MaterialMesh2dBundle {
mesh: shape, mesh: shape,
@ -41,6 +57,32 @@ pub fn add_player(
.insert(KinematicCharacterController { ..default() }); .insert(KinematicCharacterController { ..default() });
} }
#[derive(Component)]
struct LivesUi;
fn add_lives_ui(mut commands: Commands) {
commands.spawn((
TextBundle::from("<3 ".repeat(DEFAULT_LIVES.into())),
LivesUi,
));
}
fn update_lives(
mut ev_lifechange: EventReader<LifeChangeEvent>,
mut player: Query<&mut Player>,
mut ui: Query<&mut Text, With<LivesUi>>,
) {
let mut txt = ui.single_mut();
let mut p = player.single_mut();
for ev in ev_lifechange.read() {
match ev {
LifeChangeEvent::Lost => p.lives -= 1,
LifeChangeEvent::Gained => p.lives += 1,
}
txt.sections[0].value = "<3 ".repeat(p.lives.into())
}
}
pub fn player_ground_collision( pub fn player_ground_collision(
mut player: Query<(Entity, &mut Player)>, mut player: Query<(Entity, &mut Player)>,
scene_objs: Query<Entity, With<super::scene::SceneObj>>, scene_objs: Query<Entity, With<super::scene::SceneObj>>,