adding some gamestate timers

main
Jordan Orelli 1 year ago
parent 9275445bfe
commit 042e7357fa

@ -1,7 +1,7 @@
use crate::game::Throw;
use bevy::prelude::*;
#[derive(Event, Default)]
#[derive(Event, Default, Debug)]
pub(crate) struct Play;
#[derive(Event)]

@ -6,13 +6,6 @@ use crate::{events::Events, play::Play, start_menu::StartMenu};
/// The top-level structure of our game, which is a bevy plugin
pub struct Game {}
#[derive(Debug)]
pub(crate) enum Throw {
Rock,
Paper,
Scissors,
}
impl Plugin for Game {
fn build(&self, app: &mut App) {
info!("Building rps Plugin");
@ -25,3 +18,10 @@ impl Default for Game {
Self {}
}
}
#[derive(Debug, Clone)]
pub(crate) enum Throw {
Rock,
Paper,
Scissors,
}

@ -2,6 +2,7 @@ mod events;
mod game;
mod play;
mod start_menu;
mod ui;
use bevy::prelude::*;

@ -1,19 +1,80 @@
use crate::{events, game::Throw};
use crate::{events, game::Throw, ui};
use bevy::ecs::system::EntityCommand;
use bevy::prelude::*;
use bevy::text::DEFAULT_FONT_HANDLE;
use bevy::time::Stopwatch;
use std::time::Duration;
#[derive(Debug)]
pub enum Phase {
BeforePlay,
Countdown(Timer),
Reveal(Timer),
AfterPlay,
}
#[derive(Resource, Debug)]
pub struct Board {
phase: Phase,
p1_throw: Option<Throw>,
p2_throw: Option<Throw>,
}
impl Board {
fn new() -> Self {
Self {
phase: Phase::BeforePlay,
p1_throw: None,
p2_throw: None,
}
}
}
pub struct Play {}
pub(crate) enum GameEvent {
RoundBegin,
RoundEnd,
}
#[derive(Component, Debug)]
struct Action {
throw: Throw,
}
fn handle_actions(actions: Query<(&Interaction, &Action), (Changed<Interaction>, With<Action>)>) {
fn advance_game_state(time: Res<Time>, mut board: ResMut<Board>) {
// add some stuff here
match &mut board.phase {
Phase::BeforePlay => {}
Phase::Countdown(timer) => {
timer.tick(time.delta());
if timer.just_finished() {
info!("Countdown timer finished");
board.phase = Phase::Reveal(Timer::new(Duration::from_secs(3), TimerMode::Once));
}
}
Phase::Reveal(timer) => {
timer.tick(time.delta());
if timer.just_finished() {
info!("Reveal timer finished");
board.phase = Phase::AfterPlay;
}
}
Phase::AfterPlay => {}
}
}
fn handle_actions(
actions: Query<(&Interaction, &Action), (Changed<Interaction>, With<Action>)>,
mut board: ResMut<Board>,
) {
for (interaction, action) in actions.iter() {
if matches!(interaction, Interaction::Pressed) {
info!("Clicked {throw:?}", throw = action.throw);
if board.p1_throw.is_some() {
info!("Replacing existing throw");
}
board.p1_throw = Some(action.throw.clone())
}
}
}
@ -28,22 +89,27 @@ impl EntityCommand for ActionButton {
let style = TextStyle {
font: DEFAULT_FONT_HANDLE.typed(),
font_size: 24.0,
color: Color::WHITE,
color: Color::BLACK,
};
let button = world
.spawn((
Name::new(format!("{action} button", action = &self.text)),
Action { throw: self.throw },
ui::HoverColor {
on: Color::BEIGE.into(),
off: Color::BISQUE.into(),
},
ButtonBundle {
style: Style {
align_items: AlignItems::Center,
width: Val::Percent(100.0),
height: Val::Percent(100.0),
border: UiRect::all(Val::Px(2.0)),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
border_color: Color::RED.into(),
border_color: Color::BLACK.into(),
background_color: Color::GRAY.into(),
..default()
},
@ -60,44 +126,62 @@ impl EntityCommand for ActionButton {
}
}
fn handle_play(mut events: EventReader<events::Play>, mut commands: Commands) {
for _ in events.iter() {
let mut bg = commands.spawn((
Name::new("Play Container"),
fn header() -> impl Bundle {
(
Name::new("Header"),
NodeBundle {
style: Style {
display: Display::Flex,
flex_direction: FlexDirection::Column,
height: Val::Percent(100.0),
height: Val::Percent(10.0),
width: Val::Percent(100.0),
border: UiRect {
bottom: Val::Px(2.0),
..default()
},
border_color: Color::RED.into(),
..default()
},
border_color: Color::BLACK.into(),
background_color: Color::GRAY.into(),
..default()
},
));
)
}
bg.with_children(|bg| {
bg.spawn((
Name::new("Header"),
fn handle_play(
mut events: EventReader<events::Play>,
mut commands: Commands,
mut board: ResMut<Board>,
) {
if events.is_empty() {
return;
}
info!("handling play events");
for e in events.iter() {
info!("play event {e:?}");
}
board.phase = Phase::Countdown(Timer::new(Duration::from_millis(3000), TimerMode::Once));
info!("Starting countdown");
let mut bg = commands.spawn((
Name::new("Play Container"),
NodeBundle {
style: Style {
display: Display::Flex,
height: Val::Percent(10.0),
flex_direction: FlexDirection::Column,
height: Val::Percent(100.0),
width: Val::Percent(100.0),
border: UiRect {
bottom: Val::Px(2.0),
..default()
},
..default()
},
border_color: Color::BLACK.into(),
border_color: Color::RED.into(),
background_color: Color::GRAY.into(),
..default()
},
));
bg.with_children(|bg| {
// bg.add_command(x);
bg.spawn(header());
bg.spawn((
Name::new("Play"),
NodeBundle {
@ -126,6 +210,7 @@ fn handle_play(mut events: EventReader<events::Play>, mut commands: Commands) {
display: Display::Flex,
height: Val::Percent(40.0),
width: Val::Percent(100.0),
padding: UiRect::all(Val::Px(30.0)),
..default()
},
background_color: Color::GRAY.into(),
@ -146,11 +231,11 @@ fn handle_play(mut events: EventReader<events::Play>, mut commands: Commands) {
throw: Throw::Scissors,
});
});
}
}
impl Plugin for Play {
fn build(&self, app: &mut App) {
app.add_systems(Update, (handle_play, handle_actions));
app.add_systems(Update, (handle_play, handle_actions, advance_game_state));
app.insert_resource(Board::new());
}
}

@ -1,4 +1,7 @@
use crate::events;
use crate::{
events,
ui::{self, HoverColor},
};
use bevy::ecs::system::EntityCommand;
use bevy::prelude::*;
use bevy::text::DEFAULT_FONT_HANDLE;
@ -9,12 +12,6 @@ pub struct StartMenu {}
#[derive(Component)]
struct MainMenu;
#[derive(Component)]
struct HoverColor {
on: Color,
off: Color,
}
#[derive(Component)]
struct Title;
@ -48,31 +45,13 @@ fn thicc_button() -> impl Bundle {
}
}
fn hover_colors(
mut actions: Query<
(&Interaction, &mut BackgroundColor, &HoverColor),
(Changed<Interaction>, With<HoverColor>),
>,
) {
for (act, mut bg, colors) in &mut actions {
match act {
Interaction::Pressed => {}
Interaction::Hovered => {
bg.0 = colors.on;
}
Interaction::None => {
bg.0 = colors.off;
}
}
}
}
fn click_play(
mut actions: Query<&Interaction, (Changed<Interaction>, With<PlayButton>)>,
mut play: EventWriter<events::Play>,
) {
for interaction in &mut actions {
if matches!(interaction, Interaction::Pressed) {
info!("sending play event");
play.send_default();
}
}
@ -83,8 +62,9 @@ fn handle_play(
mut events: EventReader<events::Play>,
mut commands: Commands,
) {
for _ in events.iter() {
for e in events.iter() {
info!("Handling Play event");
for m in menu.iter() {
commands.entity(m).despawn_recursive();
}
@ -202,7 +182,8 @@ fn setup(mut commands: Commands) {
impl Plugin for StartMenu {
fn build(&self, app: &mut App) {
app.add_plugins(ui::Plugin {});
app.add_systems(Startup, setup);
app.add_systems(Update, (hover_colors, click_quit, click_play, handle_play));
app.add_systems(Update, (click_quit, click_play, handle_play));
}
}

@ -0,0 +1,60 @@
use bevy::prelude::*;
#[derive(Component)]
pub(crate) struct HoverColor {
pub on: Color,
pub off: Color,
}
pub struct Plugin;
impl bevy::app::Plugin for Plugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, hover_colors);
}
}
fn hover_colors(
mut actions: Query<
(&Interaction, &mut BackgroundColor, &HoverColor),
(Changed<Interaction>, With<HoverColor>),
>,
) {
for (act, mut bg, colors) in &mut actions {
match act {
Interaction::Pressed => {}
Interaction::Hovered => {
bg.0 = colors.on;
}
Interaction::None => {
bg.0 = colors.off;
}
}
}
}
pub(crate) fn row() -> NodeBundle {
NodeBundle {
style: Style {
display: Display::Flex,
flex_direction: FlexDirection::Row,
height: Val::Percent(100.0),
width: Val::Percent(100.0),
..default()
},
..default()
}
}
pub(crate) fn column() -> NodeBundle {
NodeBundle {
style: Style {
display: Display::Flex,
flex_direction: FlexDirection::Column,
height: Val::Percent(100.0),
width: Val::Percent(100.0),
..default()
},
..default()
}
}
Loading…
Cancel
Save