Skip to content

Commit

Permalink
add round ending
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksa2808 committed Nov 14, 2023
1 parent 04269d6 commit 0c28069
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 89 deletions.
14 changes: 13 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ use crate::{
types::GGRSConfig,
};
#[cfg(not(target_arch = "wasm32"))]
use crate::{native::{Args, native_input}, resources::MatchboxConfig};
use crate::{
native::{native_input, Args},
resources::MatchboxConfig,
};

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, States)]
pub enum AppState {
Expand Down Expand Up @@ -117,11 +120,20 @@ pub fn run() {
GgrsSchedule,
(
increase_frame_system,
leaderboard_display,
apply_deferred,
player_move,
bomb_drop,
apply_deferred,
fire_tick,
apply_deferred,
crumbling_tick,
apply_deferred,
explode_bombs,
apply_deferred,
player_burn,
apply_deferred,
finish_round,
)
.chain(),
)
Expand Down
9 changes: 9 additions & 0 deletions src/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,12 @@ impl FromWorld for GameTextures {
pub struct FrameCount {
pub frame: usize,
}

#[derive(Resource)]
pub enum RoundOutcome {
Winner(Penguin),
Tie,
}

#[derive(Resource)]
pub struct FreezeEndFrame(pub usize);
196 changes: 110 additions & 86 deletions src/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use crate::{
},
resources::*,
types::Direction,
utils::{get_x, get_y, init_hud, spawn_map},
utils::{
get_battle_mode_map_size_fill, get_x, get_y, init_hud, spawn_battle_mode_players, spawn_map,
},
AppState, GGRSConfig,
};

Expand Down Expand Up @@ -135,7 +137,7 @@ pub fn lobby_system(

commands.insert_resource(Session::P2P(sess));

// transition to in-game state
// transition to game state
app_state.set(AppState::InGame);
}

Expand All @@ -154,90 +156,6 @@ pub fn increase_frame_system(mut frame_count: ResMut<FrameCount>) {
frame_count.frame += 1;
}

pub fn get_battle_mode_map_size_fill(player_count: usize) -> (MapSize, f32) {
if player_count > 4 {
(
MapSize {
rows: 13,
columns: 17,
},
70.0,
)
} else {
(
MapSize {
rows: 11,
columns: 15,
},
60.0,
)
}
}

pub fn spawn_battle_mode_players(
commands: &mut Commands,
game_textures: &GameTextures,
map_size: MapSize,
players: &[Penguin],
) -> Vec<Position> {
let possible_player_spawn_positions = [
(1, 1),
(map_size.rows - 2, map_size.columns - 2),
(1, map_size.columns - 2),
(map_size.rows - 2, 1),
(3, 5),
(map_size.rows - 4, map_size.columns - 6),
(3, map_size.columns - 6),
(map_size.rows - 4, 5),
];
let mut possible_player_spawn_positions =
possible_player_spawn_positions
.iter()
.map(|(y, x)| Position {
y: *y as isize,
x: *x as isize,
});

let mut player_spawn_positions = vec![];

let mut spawn_player = |penguin_tag: Penguin| {
let player_spawn_position = possible_player_spawn_positions.next().unwrap();
let base_texture = game_textures.get_penguin_texture(penguin_tag).clone();
commands
.spawn((
SpriteBundle {
texture: base_texture.clone(),
transform: Transform::from_xyz(
get_x(player_spawn_position.x),
get_y(player_spawn_position.y),
50.0,
),
sprite: Sprite {
custom_size: Some(Vec2::new(TILE_WIDTH as f32, TILE_HEIGHT as f32)),
..Default::default()
},
..Default::default()
},
Player,
penguin_tag,
player_spawn_position,
BombSatchel {
bombs_available: 1,
bomb_range: 2,
},
))
.add_rollback();

player_spawn_positions.push(player_spawn_position);
};

for penguin_tag in players {
spawn_player(*penguin_tag);
}

player_spawn_positions
}

pub fn setup_battle_mode(
mut commands: Commands,
mut game_textures: ResMut<GameTextures>,
Expand Down Expand Up @@ -320,7 +238,14 @@ pub fn player_move(
Query<(&mut Transform, &Penguin, &mut Position, &mut Sprite)>,
Query<&Position, With<Solid>>,
)>,
freeze_end_frame: Option<ResMut<FreezeEndFrame>>,
) {
if freeze_end_frame.is_some() {
// The current round is over.
// TODO convert into a run criteria
return;
}

let solids: HashSet<Position> = p.p1().iter().copied().collect();

for (mut transform, penguin, mut position, mut sprite) in p.p0().iter_mut() {
Expand Down Expand Up @@ -367,7 +292,14 @@ pub fn bomb_drop(
mut query: Query<(Entity, &Penguin, &Position, &mut BombSatchel)>,
query2: Query<&Position, With<Solid>>,
frame_count: Res<FrameCount>,
freeze_end_frame: Option<ResMut<FreezeEndFrame>>,
) {
if freeze_end_frame.is_some() {
// The current round is over.
return;
}

// TODO this might need to be sorted as the query order is non deterministic which might break rollback IDs
for (entity, penguin, position, mut bomb_satchel) in query.iter_mut() {
if inputs[penguin.0].0.inp & INPUT_ACTION != 0
&& bomb_satchel.bombs_available > 0
Expand Down Expand Up @@ -437,7 +369,13 @@ pub fn fire_tick(
mut commands: Commands,
frame_count: Res<FrameCount>,
query: Query<(Entity, &Fire)>,
freeze_end_frame: Option<ResMut<FreezeEndFrame>>,
) {
if freeze_end_frame.is_some() {
// The current round is over.
return;
}

for (entity, fire) in query.iter() {
if frame_count.frame >= fire.expiration_frame {
commands.entity(entity).despawn_recursive();
Expand All @@ -449,7 +387,13 @@ pub fn crumbling_tick(
mut commands: Commands,
frame_count: Res<FrameCount>,
query: Query<(Entity, &Crumbling)>,
freeze_end_frame: Option<ResMut<FreezeEndFrame>>,
) {
if freeze_end_frame.is_some() {
// The current round is over.
return;
}

for (entity, crumbling) in query.iter() {
if frame_count.frame >= crumbling.expiration_frame {
commands.entity(entity).despawn_recursive();
Expand All @@ -471,7 +415,13 @@ pub fn explode_bombs(
(With<Wall>, With<Destructible>),
>,
frame_count: Res<FrameCount>,
freeze_end_frame: Option<ResMut<FreezeEndFrame>>,
) {
if freeze_end_frame.is_some() {
// The current round is over.
return;
}

let fireproof_positions: HashSet<Position> = p
.p1()
.iter()
Expand Down Expand Up @@ -560,3 +510,77 @@ pub fn explode_bombs(
}
}
}

pub fn player_burn(
mut commands: Commands,
query: Query<(Entity, &Position), With<Player>>,
query2: Query<&Position, With<Fire>>,
freeze_end_frame: Option<ResMut<FreezeEndFrame>>,
) {
if freeze_end_frame.is_some() {
// The current round is over.
return;
}

let fire_positions: HashSet<Position> = query2.iter().copied().collect();

for (e, p) in query.iter() {
if fire_positions.contains(p) {
commands.entity(e).despawn();
}
}
}

pub fn finish_round(
mut commands: Commands,
query: Query<&Penguin, With<Player>>,
frame_count: Res<FrameCount>,
freeze_end_frame: Option<ResMut<FreezeEndFrame>>,
) {
if freeze_end_frame.is_some() {
// The current round is over.
return;
}

let mut round_over = false;
if query.iter().count() == 0 {
commands.insert_resource(RoundOutcome::Tie);

round_over = true;
} else if let Ok(penguin) = query.get_single() {
commands.insert_resource(RoundOutcome::Winner(*penguin));

round_over = true;
}

if round_over {
println!("Round over, freezing...");
commands.insert_resource(FreezeEndFrame(frame_count.frame + 2 * FPS));
}
}

pub fn leaderboard_display(
mut commands: Commands,
round_outcome: Option<Res<RoundOutcome>>,
freeze_end_frame: Option<ResMut<FreezeEndFrame>>,
frame_count: Res<FrameCount>,
query: Query<Entity, Without<Window>>,
) {
if let Some(round_outcome) = round_outcome.as_deref() {
// TODO merge the two round end resources
let mut freeze_end_frame = freeze_end_frame.unwrap();
if frame_count.frame >= freeze_end_frame.0 {
match round_outcome {
RoundOutcome::Winner(penguin) => println!("Winner: {:?}", penguin.0),
RoundOutcome::Tie => println!("Tie!"),
}

for e in query.iter() {
commands.entity(e).despawn();
}

commands.remove_resource::<RoundOutcome>();
freeze_end_frame.0 = frame_count.frame + 2 * FPS;
}
}
}
Loading

0 comments on commit 0c28069

Please sign in to comment.