|
|
@ -1,19 +1,80 @@
|
|
|
|
use crate::{events, game::Throw};
|
|
|
|
use crate::{events, game::Throw, ui};
|
|
|
|
use bevy::ecs::system::EntityCommand;
|
|
|
|
use bevy::ecs::system::EntityCommand;
|
|
|
|
use bevy::prelude::*;
|
|
|
|
use bevy::prelude::*;
|
|
|
|
use bevy::text::DEFAULT_FONT_HANDLE;
|
|
|
|
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 struct Play {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) enum GameEvent {
|
|
|
|
|
|
|
|
RoundBegin,
|
|
|
|
|
|
|
|
RoundEnd,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Component, Debug)]
|
|
|
|
#[derive(Component, Debug)]
|
|
|
|
struct Action {
|
|
|
|
struct Action {
|
|
|
|
throw: Throw,
|
|
|
|
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() {
|
|
|
|
for (interaction, action) in actions.iter() {
|
|
|
|
if matches!(interaction, Interaction::Pressed) {
|
|
|
|
if matches!(interaction, Interaction::Pressed) {
|
|
|
|
info!("Clicked {throw:?}", throw = action.throw);
|
|
|
|
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 {
|
|
|
|
let style = TextStyle {
|
|
|
|
font: DEFAULT_FONT_HANDLE.typed(),
|
|
|
|
font: DEFAULT_FONT_HANDLE.typed(),
|
|
|
|
font_size: 24.0,
|
|
|
|
font_size: 24.0,
|
|
|
|
color: Color::WHITE,
|
|
|
|
color: Color::BLACK,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let button = world
|
|
|
|
let button = world
|
|
|
|
.spawn((
|
|
|
|
.spawn((
|
|
|
|
Name::new(format!("{action} button", action = &self.text)),
|
|
|
|
Name::new(format!("{action} button", action = &self.text)),
|
|
|
|
Action { throw: self.throw },
|
|
|
|
Action { throw: self.throw },
|
|
|
|
|
|
|
|
ui::HoverColor {
|
|
|
|
|
|
|
|
on: Color::BEIGE.into(),
|
|
|
|
|
|
|
|
off: Color::BISQUE.into(),
|
|
|
|
|
|
|
|
},
|
|
|
|
ButtonBundle {
|
|
|
|
ButtonBundle {
|
|
|
|
style: Style {
|
|
|
|
style: Style {
|
|
|
|
align_items: AlignItems::Center,
|
|
|
|
|
|
|
|
width: Val::Percent(100.0),
|
|
|
|
width: Val::Percent(100.0),
|
|
|
|
height: Val::Percent(100.0),
|
|
|
|
height: Val::Percent(100.0),
|
|
|
|
border: UiRect::all(Val::Px(2.0)),
|
|
|
|
border: UiRect::all(Val::Px(2.0)),
|
|
|
|
|
|
|
|
align_items: AlignItems::Center,
|
|
|
|
|
|
|
|
justify_content: JustifyContent::Center,
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
border_color: Color::RED.into(),
|
|
|
|
border_color: Color::BLACK.into(),
|
|
|
|
background_color: Color::GRAY.into(),
|
|
|
|
background_color: Color::GRAY.into(),
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
@ -60,97 +126,116 @@ impl EntityCommand for ActionButton {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn handle_play(mut events: EventReader<events::Play>, mut commands: Commands) {
|
|
|
|
fn header() -> impl Bundle {
|
|
|
|
for _ in events.iter() {
|
|
|
|
(
|
|
|
|
let mut bg = commands.spawn((
|
|
|
|
Name::new("Header"),
|
|
|
|
Name::new("Play Container"),
|
|
|
|
NodeBundle {
|
|
|
|
|
|
|
|
style: Style {
|
|
|
|
|
|
|
|
display: Display::Flex,
|
|
|
|
|
|
|
|
height: Val::Percent(10.0),
|
|
|
|
|
|
|
|
width: Val::Percent(100.0),
|
|
|
|
|
|
|
|
border: UiRect {
|
|
|
|
|
|
|
|
bottom: Val::Px(2.0),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
border_color: Color::BLACK.into(),
|
|
|
|
|
|
|
|
background_color: Color::GRAY.into(),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
|
|
|
flex_direction: FlexDirection::Column,
|
|
|
|
|
|
|
|
height: Val::Percent(100.0),
|
|
|
|
|
|
|
|
width: Val::Percent(100.0),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
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 {
|
|
|
|
NodeBundle {
|
|
|
|
style: Style {
|
|
|
|
style: Style {
|
|
|
|
display: Display::Flex,
|
|
|
|
display: Display::Flex,
|
|
|
|
flex_direction: FlexDirection::Column,
|
|
|
|
height: Val::Percent(50.0),
|
|
|
|
height: Val::Percent(100.0),
|
|
|
|
|
|
|
|
width: Val::Percent(100.0),
|
|
|
|
width: Val::Percent(100.0),
|
|
|
|
|
|
|
|
border: UiRect {
|
|
|
|
|
|
|
|
bottom: Val::Px(2.0),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
border_color: Color::RED.into(),
|
|
|
|
|
|
|
|
background_color: Color::GRAY.into(),
|
|
|
|
background_color: Color::GRAY.into(),
|
|
|
|
|
|
|
|
border_color: Color::BLACK.into(),
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
));
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
bg.with_children(|bg| {
|
|
|
|
// Action controls
|
|
|
|
bg.spawn((
|
|
|
|
let mut control_row = bg.spawn((
|
|
|
|
Name::new("Header"),
|
|
|
|
Name::new("Controls"),
|
|
|
|
NodeBundle {
|
|
|
|
NodeBundle {
|
|
|
|
style: Style {
|
|
|
|
style: Style {
|
|
|
|
display: Display::Flex,
|
|
|
|
flex_direction: FlexDirection::Row,
|
|
|
|
height: Val::Percent(10.0),
|
|
|
|
display: Display::Flex,
|
|
|
|
width: Val::Percent(100.0),
|
|
|
|
height: Val::Percent(40.0),
|
|
|
|
border: UiRect {
|
|
|
|
width: Val::Percent(100.0),
|
|
|
|
bottom: Val::Px(2.0),
|
|
|
|
padding: UiRect::all(Val::Px(30.0)),
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
border_color: Color::BLACK.into(),
|
|
|
|
|
|
|
|
background_color: Color::GRAY.into(),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bg.spawn((
|
|
|
|
|
|
|
|
Name::new("Play"),
|
|
|
|
|
|
|
|
NodeBundle {
|
|
|
|
|
|
|
|
style: Style {
|
|
|
|
|
|
|
|
display: Display::Flex,
|
|
|
|
|
|
|
|
height: Val::Percent(50.0),
|
|
|
|
|
|
|
|
width: Val::Percent(100.0),
|
|
|
|
|
|
|
|
border: UiRect {
|
|
|
|
|
|
|
|
bottom: Val::Px(2.0),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
background_color: Color::GRAY.into(),
|
|
|
|
|
|
|
|
border_color: Color::BLACK.into(),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
));
|
|
|
|
background_color: Color::GRAY.into(),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
// Action controls
|
|
|
|
control_row.add(ActionButton {
|
|
|
|
let mut control_row = bg.spawn((
|
|
|
|
text: "Rock".into(),
|
|
|
|
Name::new("Controls"),
|
|
|
|
throw: Throw::Rock,
|
|
|
|
NodeBundle {
|
|
|
|
|
|
|
|
style: Style {
|
|
|
|
|
|
|
|
flex_direction: FlexDirection::Row,
|
|
|
|
|
|
|
|
display: Display::Flex,
|
|
|
|
|
|
|
|
height: Val::Percent(40.0),
|
|
|
|
|
|
|
|
width: Val::Percent(100.0),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
background_color: Color::GRAY.into(),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
control_row.add(ActionButton {
|
|
|
|
|
|
|
|
text: "Rock".into(),
|
|
|
|
|
|
|
|
throw: Throw::Rock,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
control_row.add(ActionButton {
|
|
|
|
|
|
|
|
text: "Paper".into(),
|
|
|
|
|
|
|
|
throw: Throw::Paper,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
control_row.add(ActionButton {
|
|
|
|
|
|
|
|
text: "Scissors".into(),
|
|
|
|
|
|
|
|
throw: Throw::Scissors,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
control_row.add(ActionButton {
|
|
|
|
|
|
|
|
text: "Paper".into(),
|
|
|
|
|
|
|
|
throw: Throw::Paper,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
control_row.add(ActionButton {
|
|
|
|
|
|
|
|
text: "Scissors".into(),
|
|
|
|
|
|
|
|
throw: Throw::Scissors,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Plugin for Play {
|
|
|
|
impl Plugin for Play {
|
|
|
|
fn build(&self, app: &mut App) {
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|