diff --git a/Cargo.toml b/Cargo.toml index 6d03d75..2b9ef19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ amethyst = "0.15.0" log = { version = "0.4.8", features = ["serde"] } [features] -#default = ["vulkan"] +default = ["vulkan"] #empty = ["amethyst/empty"] #metal = ["amethyst/metal"] vulkan = ["amethyst/vulkan"] diff --git a/src/main.rs b/src/main.rs index 6c9da11..5eb8a02 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,9 @@ mod components; mod systems; -mod state; +mod ready_state; +mod play_state; +mod splash_state; + use amethyst::{ input::{InputBundle, StringBindings}, core::transform::TransformBundle, @@ -22,6 +25,7 @@ use crate::components::*; use crate::systems::*; use std::path::PathBuf; use std::str::FromStr; +use crate::splash_state::SplashState; fn main() -> amethyst::Result<()> { @@ -54,7 +58,7 @@ fn main() -> amethyst::Result<()> { // Creates the app with the startup state and bound game data - let mut game = Application::new(resources, state::SplashState::default(), game_data)?; + let mut game = Application::new(resources, SplashState::default(), game_data)?; game.run(); Ok(()) diff --git a/src/play_state.rs b/src/play_state.rs new file mode 100644 index 0000000..9ca680a --- /dev/null +++ b/src/play_state.rs @@ -0,0 +1,104 @@ +use amethyst::{ + assets::{AssetStorage, Loader}, + core::transform::Transform, + core::math::Vector3, + input::{get_key, is_close_requested, is_key_down, VirtualKeyCode}, + prelude::*, + renderer::{Camera, ImageFormat, SpriteRender, SpriteSheet, SpriteSheetFormat, Texture}, + window::ScreenDimensions, + ecs::prelude::{Dispatcher, DispatcherBuilder, Component, DenseVecStorage, Entity}, +}; + +use log::info; +use crate::components::*; +use std::collections::HashMap; +use crate::systems::{BirbGravity, ScrollScrollables}; + +#[derive(Default)] +pub struct PlayState<'a, 'b> { + + // Custom dispatch systems for this state + dispatcher: Option>, + + sprites: Vec, +} + +impl<'a, 'b> PlayState<'a, 'b> { + + fn init_sprites(&mut self, world: &mut World) { + + let sprites = world.try_fetch_mut::>().unwrap().clone(); + let dimensions = (*world.read_resource::()).clone(); + + let birb_sprite = sprites + .get("floppy").unwrap(); + + let mut transform = Transform::default(); + transform.set_scale(Vector3::new(3.0, 3.0, 3.0)); + transform.set_translation_xyz(dimensions.width()/2.0, dimensions.height()/2.0, 0.2); + + self.sprites.push(world + .create_entity() + .with(birb_sprite.clone()) // Sprite Render + .with(Birb { + vertical_speed: 0.0, + position: 0.0, + starting_height: 0.0 + }) + .with(transform) + .build()); + } +} + +impl<'a, 'b> SimpleState for PlayState<'a, 'b> { + + fn on_start(&mut self, data: StateData<'_, GameData<'_, '_>>) { + + let world = data.world; + let dimensions = (*world.read_resource::()).clone(); + + // Create the `DispatcherBuilder` and register some `System`s that should only run for this `State`. + let mut dispatcher_builder = DispatcherBuilder::new(); + dispatcher_builder.add(BirbGravity { fired: false }, "gravity", &[]); + + let mut dispatcher = dispatcher_builder.build(); + dispatcher.setup(world); + + self.dispatcher = Some(dispatcher); + + PlayState::init_sprites(self, world); + + } + + fn handle_event( + &mut self, + mut data: StateData<'_, GameData<'_, '_>>, + event: StateEvent, + ) -> SimpleTrans { + + if let StateEvent::Window(event) = &event { + // Check if the window should be closed + if is_close_requested(&event) || is_key_down(&event, VirtualKeyCode::Escape) { + return Trans::Quit; + } + + if is_key_down(&event, VirtualKeyCode::P) { + let world = data.world; + for i in &self.sprites { + world.delete_entity(*i); + } + self.sprites.clear(); + return Trans::Pop; + } + } + Trans::None + } + + fn update(&mut self, data: &mut StateData<'_, GameData<'_, '_>>) -> SimpleTrans { + + if let Some(dispatcher) = self.dispatcher.as_mut() { + dispatcher.dispatch(&data.world); + } + Trans::None + } +} diff --git a/src/ready_state.rs b/src/ready_state.rs new file mode 100644 index 0000000..085e115 --- /dev/null +++ b/src/ready_state.rs @@ -0,0 +1,104 @@ +use amethyst::{ + assets::{AssetStorage, Loader}, + core::transform::Transform, + core::math::Vector3, + input::{get_mouse_button, get_key, is_close_requested, is_key_down, VirtualKeyCode}, + prelude::*, + renderer::{Camera, ImageFormat, SpriteRender, SpriteSheet, SpriteSheetFormat, Texture}, + window::ScreenDimensions, + ecs::prelude::{Dispatcher, DispatcherBuilder, Component, DenseVecStorage, Entity}, +}; + +use log::info; +use crate::components::*; +use std::collections::HashMap; +use crate::systems::{BirbGravity, ScrollScrollables}; +use crate::play_state::PlayState; + +#[derive(Default)] +pub struct ReadyState { + sprites: Vec, +} + +impl ReadyState { + + fn init_sprites(&mut self, world: &mut World) { + + let dimensions = (*world.read_resource::()).clone(); + let sprites = world.try_fetch_mut::>().unwrap().clone(); + + let get_ready_text_sprite = sprites + .get("get-ready-text").unwrap().clone(); + + let tap_tap_dialogue_sprite = sprites + .get("tap-tap-dialogue").unwrap().clone(); + + let mut transform = Transform::default(); + transform.set_scale(Vector3::new(3.0, 3.0, 3.0)); + + transform.set_translation_xyz(dimensions.width()*0.5, dimensions.height()*0.8, 0.2); + + self.sprites.push(world + .create_entity() + .with(get_ready_text_sprite.clone()) // Sprite Render + .with(transform.clone()) + .build()); + + transform.set_translation_xyz(dimensions.width()*0.5, dimensions.height()*0.5, 0.2); + + self.sprites.push(world + .create_entity() + .with(tap_tap_dialogue_sprite.clone()) // Sprite Render + .with(transform.clone()) + .build()); + } +} +impl SimpleState for ReadyState { + + fn on_start(&mut self, data: StateData<'_, GameData<'_, '_>>) { + let world = data.world; + ReadyState::init_sprites(self, world); + } + + fn on_resume(&mut self, data: StateData<'_, GameData<'_, '_>>) { + + } + + fn handle_event( + &mut self, + mut data: StateData<'_, GameData<'_, '_>>, + event: StateEvent, + ) -> SimpleTrans { + + if let StateEvent::Ui(event) = &event { + + if event.event_type == UiEventType::Click { + + } + + } + + if let StateEvent::Window(event) = &event { + // Check if the window should be closed + if is_close_requested(&event) || is_key_down(&event, VirtualKeyCode::Escape) { + return Trans::Quit; + } + + // Check if the window should be closed + if is_key_down(&event, VirtualKeyCode::Space) { + let world = data.world; + for i in &self.sprites { + world.delete_entity(*i); + } + self.sprites.clear(); + + return Trans::Push(Box::new(PlayState::default())); + } + } + Trans::None + } + + fn update(&mut self, data: &mut StateData<'_, GameData<'_, '_>>) -> SimpleTrans { + Trans::None + } +} \ No newline at end of file diff --git a/src/state.rs b/src/splash_state.rs similarity index 61% rename from src/state.rs rename to src/splash_state.rs index 97e0015..80d218a 100644 --- a/src/state.rs +++ b/src/splash_state.rs @@ -13,105 +13,85 @@ use log::info; use crate::components::*; use std::collections::HashMap; use crate::systems::{BirbGravity, ScrollScrollables}; +use crate::ready_state::ReadyState; -#[derive(Default)] -pub struct PlayState<'a, 'b> { - - // Custom dispatch systems for this state - dispatcher: Option>, +#[derive(Default)] +pub struct SplashState { sprites: Vec, + persistent_sprites: Vec, } -impl<'a, 'b> PlayState<'a, 'b> { - - fn init_sprites(&mut self, world: &mut World) { +impl SplashState { - let sprites = world.try_fetch_mut::>().unwrap().clone(); - let dimensions = (*world.read_resource::()).clone(); + fn load_sprites(world: &mut World) -> HashMap { + // Load the texture for our sprites. We'll later need to + // add a handle to this texture to our `SpriteRender`s, so + // we need to keep a reference to it. + let texture_handle = { + let loader = world.read_resource::(); + let texture_storage = world.read_resource::>(); + loader.load( + "sprites/flappy.png", + ImageFormat::default(), + (), + &texture_storage, + ) + }; - let birb_sprite = sprites - .get("floppy").unwrap(); + // Load the spritesheet definition file, which contains metadata on our + // spritesheet texture. + let sheet_handle = { + let loader = world.read_resource::(); + let sheet_storage = world.read_resource::>(); + loader.load( + "sprites/flappy.ron", + SpriteSheetFormat(texture_handle), + (), + &sheet_storage, + ) + }; - let mut transform = Transform::default(); - transform.set_scale(Vector3::new(3.0, 3.0, 3.0)); - transform.set_translation_xyz(dimensions.width()/2.0, dimensions.height()/2.0, 0.2); + let sprite_map = vec![ + ("day-background".to_string(), 0), + ("night-background".to_string(), 1), + ("down-pipe".to_string(), 2), + ("up-pipe".to_string(), 3), + ("ground".to_string(), 4), + ("floppy".to_string(), 5), + ("tap-tap-dialogue".to_string(), 6), + ("play-button".to_string(), 7), + ("leaderboard-button".to_string(), 8), + ("get-ready-text".to_string(), 9), + ("flappy-bird-text".to_string(), 10), + ]; - self.sprites.push(world - .create_entity() - .with(birb_sprite.clone()) // Sprite Render - .with(Birb { - vertical_speed: 0.0, - position: 0.0, - starting_height: 0.0 - }) - .with(transform) - .build()); + sprite_map.iter() + .map(|i| (i.0.clone(), SpriteRender { + sprite_sheet: sheet_handle.clone(), + sprite_number: i.1, + })) + .collect() } -} -impl<'a, 'b> SimpleState for PlayState<'a, 'b> { - - fn on_start(&mut self, data: StateData<'_, GameData<'_, '_>>) { + fn init_camera(world: &mut World) { - let world = data.world; let dimensions = (*world.read_resource::()).clone(); - // Create the `DispatcherBuilder` and register some `System`s that should only run for this `State`. - let mut dispatcher_builder = DispatcherBuilder::new(); - dispatcher_builder.add(BirbGravity { fired: false }, "gravity", &[]); - - let mut dispatcher = dispatcher_builder.build(); - dispatcher.setup(world); - - self.dispatcher = Some(dispatcher); - - PlayState::init_sprites(self, world); - - } - - fn handle_event( - &mut self, - mut data: StateData<'_, GameData<'_, '_>>, - event: StateEvent, - ) -> SimpleTrans { - - if let StateEvent::Window(event) = &event { - // Check if the window should be closed - if is_close_requested(&event) || is_key_down(&event, VirtualKeyCode::Escape) { - return Trans::Quit; - } - - if is_key_down(&event, VirtualKeyCode::P) { - let world = data.world; - for i in &self.sprites { - world.delete_entity(*i); - } - self.sprites.clear(); - return Trans::Pop; - } - } - Trans::None - } - - fn update(&mut self, data: &mut StateData<'_, GameData<'_, '_>>) -> SimpleTrans { + // Center the camera in the middle of the screen, and let it cover + // the entire screen + let mut transform = Transform::default(); + transform.set_translation_xyz(dimensions.width() * 0.5, dimensions.height() * 0.5, 1.); - if let Some(dispatcher) = self.dispatcher.as_mut() { - dispatcher.dispatch(&data.world); - } - Trans::None + world + .create_entity() + .with(Camera::standard_2d(dimensions.width(), dimensions.height())) + .with(transform) + .build(); } -} - -#[derive(Default)] -pub struct SplashState { - sprites: Vec, - persistent_sprites: Vec, -} - -impl SplashState { fn init_sprites(&mut self, world: &mut World) { + let sprites = world.try_fetch_mut::>().unwrap().clone(); let dimensions = (*world.read_resource::()).clone(); @@ -212,72 +192,6 @@ impl SplashState { .with(transform.clone()) .build()); } - - fn init_camera(world: &mut World) { - - let dimensions = (*world.read_resource::()).clone(); - - // Center the camera in the middle of the screen, and let it cover - // the entire screen - let mut transform = Transform::default(); - transform.set_translation_xyz(dimensions.width() * 0.5, dimensions.height() * 0.5, 1.); - - world - .create_entity() - .with(Camera::standard_2d(dimensions.width(), dimensions.height())) - .with(transform) - .build(); - } - - fn load_sprites(world: &mut World) -> HashMap { - // Load the texture for our sprites. We'll later need to - // add a handle to this texture to our `SpriteRender`s, so - // we need to keep a reference to it. - let texture_handle = { - let loader = world.read_resource::(); - let texture_storage = world.read_resource::>(); - loader.load( - "sprites/flappy.png", - ImageFormat::default(), - (), - &texture_storage, - ) - }; - - // Load the spritesheet definition file, which contains metadata on our - // spritesheet texture. - let sheet_handle = { - let loader = world.read_resource::(); - let sheet_storage = world.read_resource::>(); - loader.load( - "sprites/flappy.ron", - SpriteSheetFormat(texture_handle), - (), - &sheet_storage, - ) - }; - - let sprite_map = vec![ - ("day-background".to_string(), 0), - ("night-background".to_string(), 1), - ("down-pipe".to_string(), 2), - ("up-pipe".to_string(), 3), - ("ground".to_string(), 4), - ("floppy".to_string(), 5), - ("tap-tap-dialogue".to_string(), 6), - ("play-button".to_string(), 7), - ("leaderboard-button".to_string(), 8), - ("get-ready-text".to_string(), 9), - ("flappy-bird-text".to_string(), 10), - ]; - - sprite_map.iter() - .map(|i| (i.0.clone(), SpriteRender { - sprite_sheet: sheet_handle.clone(), - sprite_number: i.1, - })) - .collect() - } } impl SimpleState for SplashState { @@ -325,83 +239,3 @@ impl SimpleState for SplashState { Trans::None } } - -#[derive(Default)] -pub struct ReadyState { - sprites: Vec, -} - -impl ReadyState { - - fn init_sprites(&mut self, world: &mut World) { - - let dimensions = (*world.read_resource::()).clone(); - let sprites = world.try_fetch_mut::>().unwrap().clone(); - - let get_ready_text_sprite = sprites - .get("get-ready-text").unwrap().clone(); - - let tap_tap_dialogue_sprite = sprites - .get("tap-tap-dialogue").unwrap().clone(); - - let mut transform = Transform::default(); - transform.set_scale(Vector3::new(3.0, 3.0, 3.0)); - - transform.set_translation_xyz(dimensions.width()*0.5, dimensions.height()*0.8, 0.2); - - self.sprites.push(world - .create_entity() - .with(get_ready_text_sprite.clone()) // Sprite Render - .with(transform.clone()) - .build()); - - transform.set_translation_xyz(dimensions.width()*0.5, dimensions.height()*0.5, 0.2); - - self.sprites.push(world - .create_entity() - .with(tap_tap_dialogue_sprite.clone()) // Sprite Render - .with(transform.clone()) - .build()); - } -} -impl SimpleState for ReadyState { - - fn on_start(&mut self, data: StateData<'_, GameData<'_, '_>>) { - let world = data.world; - ReadyState::init_sprites(self, world); - } - - fn on_resume(&mut self, data: StateData<'_, GameData<'_, '_>>) { - - } - - fn handle_event( - &mut self, - mut data: StateData<'_, GameData<'_, '_>>, - event: StateEvent, - ) -> SimpleTrans { - - if let StateEvent::Window(event) = &event { - // Check if the window should be closed - if is_close_requested(&event) || is_key_down(&event, VirtualKeyCode::Escape) { - return Trans::Quit; - } - - // Check if the window should be closed - if is_key_down(&event, VirtualKeyCode::Space) { - let world = data.world; - for i in &self.sprites { - world.delete_entity(*i); - } - self.sprites.clear(); - - return Trans::Push(Box::new(PlayState::default())); - } - } - Trans::None - } - - fn update(&mut self, data: &mut StateData<'_, GameData<'_, '_>>) -> SimpleTrans { - Trans::None - } -} \ No newline at end of file diff --git a/src/systems.rs b/src/systems.rs index eea1604..e5f80ff 100644 --- a/src/systems.rs +++ b/src/systems.rs @@ -19,8 +19,6 @@ pub struct ScrollScrollables; /* Pausable systems https://book.amethyst.rs/stable/controlling_system_execution/pausable_systems.html - - */ // This system iterates all the objects with transform (and falling object) component