a full game loop appears

main
Jordan Orelli 1 year ago
parent 042e7357fa
commit 2535799505

37
Cargo.lock generated

@ -2812,6 +2812,12 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "pretty-type-name"
version = "1.0.1"
@ -2858,6 +2864,36 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17fd96390ed3feda12e1dfe2645ed587e0bea749e319333f104a33ff62f77a0b"
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "range-alloc"
version = "0.1.3"
@ -2963,6 +2999,7 @@ version = "0.1.0"
dependencies = [
"bevy",
"bevy-inspector-egui",
"rand",
"tracing",
]

@ -17,4 +17,5 @@ edition = "2021"
[dependencies]
bevy = { version = "0.11.2", features = [ ] }
bevy-inspector-egui = "0.19.0"
rand = "0.8.5"
tracing = "0.1.37"

@ -4,6 +4,9 @@ use bevy::prelude::*;
#[derive(Event, Default, Debug)]
pub(crate) struct Play;
#[derive(Event, Default, Debug)]
pub(crate) struct GameFinished;
#[derive(Event)]
pub(crate) struct PlayerMove {
throw: Throw,
@ -14,5 +17,6 @@ pub(crate) struct Events {}
impl Plugin for Events {
fn build(&self, app: &mut App) {
app.add_event::<Play>();
app.add_event::<GameFinished>();
}
}

@ -1,4 +1,5 @@
use bevy::prelude::*;
use rand::Rng;
use tracing::info;
use crate::{events::Events, play::Play, start_menu::StartMenu};
@ -25,3 +26,36 @@ pub(crate) enum Throw {
Paper,
Scissors,
}
impl Throw {
pub fn random() -> Self {
let mut rng = rand::thread_rng();
match rng.gen_range(0..3) {
0 => Throw::Rock,
1 => Throw::Paper,
2 => Throw::Scissors,
_ => unreachable!(),
}
}
pub fn against(&self, other: &Self) -> Outcome {
match (self, other) {
(Throw::Rock, Throw::Rock)
| (Throw::Paper, Throw::Paper)
| (Throw::Scissors, Throw::Scissors) => Outcome::Tie,
(Throw::Rock, Throw::Scissors)
| (Throw::Paper, Throw::Rock)
| (Throw::Scissors, Throw::Paper) => Outcome::Win,
(Throw::Rock, Throw::Paper)
| (Throw::Paper, Throw::Scissors)
| (Throw::Scissors, Throw::Rock) => Outcome::Loss,
}
}
}
#[derive(Debug)]
pub(crate) enum Outcome {
Win,
Loss,
Tie,
}

@ -2,9 +2,11 @@ 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(Component)]
struct PlayContainer;
#[derive(Debug)]
pub enum Phase {
BeforePlay,
@ -28,6 +30,11 @@ impl Board {
p2_throw: None,
}
}
pub fn clear(&mut self) {
self.p1_throw = None;
self.p2_throw = None;
}
}
pub struct Play {}
@ -42,7 +49,11 @@ struct Action {
throw: Throw,
}
fn advance_game_state(time: Res<Time>, mut board: ResMut<Board>) {
fn advance_game_state(
time: Res<Time>,
mut board: ResMut<Board>,
mut finished: EventWriter<events::GameFinished>,
) {
// add some stuff here
match &mut board.phase {
Phase::BeforePlay => {}
@ -50,7 +61,23 @@ fn advance_game_state(time: Res<Time>, mut board: ResMut<Board>) {
timer.tick(time.delta());
if timer.just_finished() {
info!("Countdown timer finished");
if board.p1_throw.is_none() {
info!("Player panics and throws at random");
board.p1_throw = Some(Throw::random());
}
board.p2_throw = Some(Throw::random());
board.phase = Phase::Reveal(Timer::new(Duration::from_secs(3), TimerMode::Once));
info!("Player threw: {throw:?}", throw = board.p1_throw);
info!("Computer threw: {throw:?}", throw = board.p2_throw);
info!(
"Outcome: {outcome:?}",
outcome = board
.p1_throw
.as_ref()
.unwrap()
.against(board.p2_throw.as_ref().unwrap())
);
}
}
Phase::Reveal(timer) => {
@ -58,6 +85,7 @@ fn advance_game_state(time: Res<Time>, mut board: ResMut<Board>) {
if timer.just_finished() {
info!("Reveal timer finished");
board.phase = Phase::AfterPlay;
finished.send_default();
}
}
Phase::AfterPlay => {}
@ -71,6 +99,10 @@ fn handle_actions(
for (interaction, action) in actions.iter() {
if matches!(interaction, Interaction::Pressed) {
info!("Clicked {throw:?}", throw = action.throw);
if !matches!(board.phase, Phase::Countdown(_)) {
info!("Ignoring player throw");
return;
}
if board.p1_throw.is_some() {
info!("Replacing existing throw");
}
@ -147,6 +179,20 @@ fn header() -> impl Bundle {
)
}
fn handle_game_finished(
mut events: EventReader<events::GameFinished>,
mut commands: Commands,
q: Query<Entity, With<PlayContainer>>,
) {
if events.is_empty() {
return;
}
events.clear();
for e in q.iter() {
commands.entity(e).despawn_recursive();
}
}
fn handle_play(
mut events: EventReader<events::Play>,
mut commands: Commands,
@ -160,10 +206,12 @@ fn handle_play(
info!("play event {e:?}");
}
board.phase = Phase::Countdown(Timer::new(Duration::from_millis(3000), TimerMode::Once));
board.clear();
info!("Starting countdown");
let mut bg = commands.spawn((
Name::new("Play Container"),
PlayContainer {},
NodeBundle {
style: Style {
display: Display::Flex,
@ -235,7 +283,15 @@ fn handle_play(
impl Plugin for Play {
fn build(&self, app: &mut App) {
app.add_systems(Update, (handle_play, handle_actions, advance_game_state));
app.add_systems(
Update,
(
handle_play,
handle_actions,
advance_game_state,
handle_game_finished,
),
);
app.insert_resource(Board::new());
}
}

@ -138,11 +138,20 @@ impl EntityCommand for Label {
}
}
fn setup(mut commands: Commands) {
fn handle_game_finished(mut events: EventReader<events::GameFinished>, mut commands: Commands) {
if events.is_empty() {
return;
}
events.clear();
info!("Game finished, reconstructing start menu");
spawn_start_menu(commands);
}
fn spawn_start_menu(mut commands: Commands) {
let red = Color::rgb(0.8, 0.2, 0.2);
let green = Color::rgb(0.2, 0.8, 0.2);
commands.spawn(Camera2dBundle::default());
commands
.spawn((Name::new("Start Menu"), MainMenu, column()))
.with_children(|menu| {
@ -180,10 +189,18 @@ fn setup(mut commands: Commands) {
});
}
fn setup(mut commands: Commands) {
commands.spawn(Camera2dBundle::default());
spawn_start_menu(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, (click_quit, click_play, handle_play));
app.add_systems(
Update,
(click_quit, click_play, handle_play, handle_game_finished),
);
}
}

Loading…
Cancel
Save