|
|
|
@ -16,16 +16,90 @@ use crate::systems::{BirbGravity, ScrollScrollables};
|
|
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
|
pub struct PlayState<'a, 'b> {
|
|
|
|
|
/// The `State` specific `Dispatcher`, containing `System`s only relevant for this `State`.
|
|
|
|
|
|
|
|
|
|
// Custom dispatch systems for this state
|
|
|
|
|
dispatcher: Option<Dispatcher<'a, 'b>>,
|
|
|
|
|
|
|
|
|
|
sprites: Vec<Entity>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a, 'b> PlayState<'a, 'b> {
|
|
|
|
|
|
|
|
|
|
fn init_sprites(&mut self, world: &mut World) {
|
|
|
|
|
|
|
|
|
|
let sprites = world.try_fetch_mut::<HashMap<String, SpriteRender>>().unwrap().clone();
|
|
|
|
|
let dimensions = (*world.read_resource::<ScreenDimensions>()).clone();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let background_sprite = sprites.get("day-background").unwrap().clone();
|
|
|
|
|
|
|
|
|
|
let background_object = TiledScroller {
|
|
|
|
|
speed: -75.0,
|
|
|
|
|
position: 1.0,
|
|
|
|
|
width: 144.0 * 3.0,
|
|
|
|
|
height: 256.0 * 3.0,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let mut transform = Transform::default();
|
|
|
|
|
transform.set_scale(Vector3::new(3.0, 3.0, 3.0));
|
|
|
|
|
transform.set_translation_xyz(background_object.width/2.0, background_object.height/2.0, 0.0);
|
|
|
|
|
|
|
|
|
|
self.sprites.push(world
|
|
|
|
|
.create_entity()
|
|
|
|
|
.with(background_sprite.clone()) // Sprite Render
|
|
|
|
|
.with(background_object.clone())
|
|
|
|
|
.with(transform.clone())
|
|
|
|
|
.build());
|
|
|
|
|
|
|
|
|
|
transform.set_translation_xyz(3.0*144.0/2.0*3.0, 3.0*256.0/2.0, 0.0);
|
|
|
|
|
|
|
|
|
|
self.sprites.push(world
|
|
|
|
|
.create_entity()
|
|
|
|
|
.with(background_sprite.clone()) // Sprite Render
|
|
|
|
|
.with(TiledScroller {
|
|
|
|
|
speed: -75.0,
|
|
|
|
|
position: 2.0,
|
|
|
|
|
width: 0.0,
|
|
|
|
|
height: 0.0
|
|
|
|
|
})
|
|
|
|
|
.with(transform.clone())
|
|
|
|
|
.build());
|
|
|
|
|
|
|
|
|
|
let ground_sprite = sprites.get("ground").unwrap();
|
|
|
|
|
transform.set_translation_xyz(3.0*168.0/2.0*3.0, 3.0*56.0/2.0, 0.1);
|
|
|
|
|
|
|
|
|
|
self.sprites.push(world
|
|
|
|
|
.create_entity()
|
|
|
|
|
.with(ground_sprite.clone()) // Sprite Render
|
|
|
|
|
.with(TiledScroller {
|
|
|
|
|
speed: -100.0,
|
|
|
|
|
position: 2.0,
|
|
|
|
|
width: 0.0,
|
|
|
|
|
height: 0.0,
|
|
|
|
|
})
|
|
|
|
|
.with(transform.clone())
|
|
|
|
|
.build());
|
|
|
|
|
|
|
|
|
|
let birb_sprite = sprites.get("floppy").unwrap();
|
|
|
|
|
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> {
|
|
|
|
|
|
|
|
|
|
// On start will run when this state is initialized. For more
|
|
|
|
|
// state lifecycle hooks, see:
|
|
|
|
|
// https://book.amethyst.rs/stable/concepts/state.html#life-cycle
|
|
|
|
|
fn on_start(&mut self, data: StateData<'_, GameData<'_, '_>>) {
|
|
|
|
|
|
|
|
|
|
let world = data.world;
|
|
|
|
|
|
|
|
|
|
// Get the screen dimensions so we can initialize the camera and
|
|
|
|
@ -36,7 +110,7 @@ impl<'a, 'b> SimpleState for PlayState<'a, 'b> {
|
|
|
|
|
|
|
|
|
|
// Place the camera
|
|
|
|
|
/// function sets size of camera window
|
|
|
|
|
init_camera(world, &dimensions);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Create the `DispatcherBuilder` and register some `System`s that should only run for this `State`.
|
|
|
|
|
let mut dispatcher_builder = DispatcherBuilder::new();
|
|
|
|
@ -49,10 +123,7 @@ impl<'a, 'b> SimpleState for PlayState<'a, 'b> {
|
|
|
|
|
|
|
|
|
|
self.dispatcher = Some(dispatcher);
|
|
|
|
|
|
|
|
|
|
// Load our sprites and display them
|
|
|
|
|
let sprites = load_sprites(world);
|
|
|
|
|
world.insert(sprites.clone());
|
|
|
|
|
init_sprites(world, &sprites, &dimensions);
|
|
|
|
|
PlayState::init_sprites(self, world);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -69,13 +140,9 @@ impl<'a, 'b> SimpleState for PlayState<'a, 'b> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if is_key_down(&event, VirtualKeyCode::P) {
|
|
|
|
|
// So I need to set the scrolling and gravity systems to pause
|
|
|
|
|
|
|
|
|
|
return Trans::Push(Box::new(PausedState{ sprite: None }));
|
|
|
|
|
return Trans::Pop;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Keep going
|
|
|
|
|
Trans::None
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -84,12 +151,21 @@ impl<'a, 'b> SimpleState for PlayState<'a, 'b> {
|
|
|
|
|
if let Some(dispatcher) = self.dispatcher.as_mut() {
|
|
|
|
|
dispatcher.dispatch(&data.world);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Trans::None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn init_camera(world: &mut World, dimensions: &ScreenDimensions) {
|
|
|
|
|
#[derive(Default)]
|
|
|
|
|
pub struct SplashState {
|
|
|
|
|
sprites: Vec<Entity>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl SplashState {
|
|
|
|
|
|
|
|
|
|
fn init_camera(world: &mut World) {
|
|
|
|
|
|
|
|
|
|
let dimensions = (*world.read_resource::<ScreenDimensions>()).clone();
|
|
|
|
|
|
|
|
|
|
// Center the camera in the middle of the screen, and let it cover
|
|
|
|
|
// the entire screen
|
|
|
|
|
let mut transform = Transform::default();
|
|
|
|
@ -102,6 +178,93 @@ fn init_camera(world: &mut World, dimensions: &ScreenDimensions) {
|
|
|
|
|
.build();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn init_sprites(&mut self, world: &mut World) {
|
|
|
|
|
let sprites = world.try_fetch_mut::<HashMap<String, SpriteRender>>().unwrap().clone();
|
|
|
|
|
|
|
|
|
|
let dimensions = (*world.read_resource::<ScreenDimensions>()).clone();
|
|
|
|
|
|
|
|
|
|
let flappy_bird_text_sprite = sprites
|
|
|
|
|
.get("flappy-bird-text").unwrap().clone();
|
|
|
|
|
let play_button_sprite = sprites
|
|
|
|
|
.get("play-button").unwrap().clone();
|
|
|
|
|
let leaderboard_button_sprite = sprites
|
|
|
|
|
.get("leaderboard-button").unwrap().clone();
|
|
|
|
|
let background_sprite = sprites
|
|
|
|
|
.get("day-background").unwrap().clone();
|
|
|
|
|
let ground_sprite = sprites
|
|
|
|
|
.get("ground").unwrap().clone();
|
|
|
|
|
|
|
|
|
|
let background_object = TiledScroller {
|
|
|
|
|
speed: -75.0,
|
|
|
|
|
position: 1.0,
|
|
|
|
|
width: 144.0 * 3.0,
|
|
|
|
|
height: 256.0 * 3.0,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let mut transform = Transform::default();
|
|
|
|
|
transform.set_scale(Vector3::new(3.0, 3.0, 3.0));
|
|
|
|
|
transform.set_translation_xyz(dimensions.width()/2.0 - 100.0, dimensions.height() - 100.0, 0.1);
|
|
|
|
|
|
|
|
|
|
self.sprites.push(world
|
|
|
|
|
.create_entity()
|
|
|
|
|
.with(background_sprite.clone()) // Sprite Render
|
|
|
|
|
.with(background_object.clone())
|
|
|
|
|
.with(transform.clone())
|
|
|
|
|
.build());
|
|
|
|
|
|
|
|
|
|
transform.set_translation_xyz(3.0*144.0/2.0*3.0, 3.0*256.0/2.0, 0.0);
|
|
|
|
|
|
|
|
|
|
self.sprites.push(world
|
|
|
|
|
.create_entity()
|
|
|
|
|
.with(background_sprite.clone()) // Sprite Render
|
|
|
|
|
.with(TiledScroller {
|
|
|
|
|
speed: -75.0,
|
|
|
|
|
position: 2.0,
|
|
|
|
|
width: 0.0,
|
|
|
|
|
height: 0.0
|
|
|
|
|
})
|
|
|
|
|
.with(transform.clone())
|
|
|
|
|
.build());
|
|
|
|
|
|
|
|
|
|
transform.set_translation_xyz(3.0*168.0/2.0*3.0, 3.0*56.0/2.0, 0.1);
|
|
|
|
|
|
|
|
|
|
self.sprites.push(world
|
|
|
|
|
.create_entity()
|
|
|
|
|
.with(ground_sprite.clone()) // Sprite Render
|
|
|
|
|
.with(TiledScroller {
|
|
|
|
|
speed: -100.0,
|
|
|
|
|
position: 2.0,
|
|
|
|
|
width: 0.0,
|
|
|
|
|
height: 0.0,
|
|
|
|
|
})
|
|
|
|
|
.with(transform.clone())
|
|
|
|
|
.build());
|
|
|
|
|
|
|
|
|
|
transform.set_translation_xyz(background_object.width/2.0, background_object.height/2.0, 0.0);
|
|
|
|
|
|
|
|
|
|
self.sprites.push(world
|
|
|
|
|
.create_entity()
|
|
|
|
|
.with(flappy_bird_text_sprite.clone())
|
|
|
|
|
.with(transform.clone())
|
|
|
|
|
.build());
|
|
|
|
|
|
|
|
|
|
transform.set_translation_xyz(100.0/2.0, 100.0/2.0, 0.1);
|
|
|
|
|
|
|
|
|
|
self.sprites.push(world
|
|
|
|
|
.create_entity()
|
|
|
|
|
.with(play_button_sprite.clone())
|
|
|
|
|
.with(transform.clone())
|
|
|
|
|
.build());
|
|
|
|
|
|
|
|
|
|
transform.set_translation_xyz(500.0/2.0, 100.0/2.0, 0.1);
|
|
|
|
|
|
|
|
|
|
self.sprites.push(world
|
|
|
|
|
.create_entity()
|
|
|
|
|
.with(leaderboard_button_sprite.clone())
|
|
|
|
|
.with(transform.clone())
|
|
|
|
|
.build());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn load_sprites(world: &mut World) -> HashMap<String, SpriteRender> {
|
|
|
|
|
// Load the texture for our sprites. We'll later need to
|
|
|
|
|
// add a handle to this texture to our `SpriteRender`s, so
|
|
|
|
@ -137,6 +300,11 @@ fn load_sprites(world: &mut World) -> HashMap<String, SpriteRender> {
|
|
|
|
|
("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()
|
|
|
|
@ -146,101 +314,100 @@ fn load_sprites(world: &mut World) -> HashMap<String, SpriteRender> {
|
|
|
|
|
}))
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn init_sprites(world: &mut World, sprites: &HashMap<String, SpriteRender>, dimensions: &ScreenDimensions) {
|
|
|
|
|
|
|
|
|
|
let background_sprite = sprites.get("day-background").unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let background_object = TiledScroller {
|
|
|
|
|
speed: -75.0,
|
|
|
|
|
position: 1.0,
|
|
|
|
|
width: 144.0 * 3.0,
|
|
|
|
|
height: 256.0 * 3.0,
|
|
|
|
|
};
|
|
|
|
|
impl SimpleState for SplashState {
|
|
|
|
|
|
|
|
|
|
let mut transform = Transform::default();
|
|
|
|
|
transform.set_scale(Vector3::new(3.0, 3.0, 3.0));
|
|
|
|
|
transform.set_translation_xyz(background_object.width/2.0, background_object.height/2.0, 0.0);
|
|
|
|
|
fn on_start(&mut self, data: StateData<'_, GameData<'_, '_>>) {
|
|
|
|
|
let world = data.world;
|
|
|
|
|
|
|
|
|
|
// Load the sprites. Insert them into the world as this is the first function to be called
|
|
|
|
|
let sprites = SplashState::load_sprites(world);
|
|
|
|
|
world.insert(sprites.clone());
|
|
|
|
|
|
|
|
|
|
world
|
|
|
|
|
.create_entity()
|
|
|
|
|
.with(background_sprite.clone()) // Sprite Render
|
|
|
|
|
.with(background_object.clone())
|
|
|
|
|
.with(transform.clone())
|
|
|
|
|
.build();
|
|
|
|
|
SplashState::load_sprites(world);
|
|
|
|
|
SplashState::init_camera(world);
|
|
|
|
|
SplashState::init_sprites(self, world);
|
|
|
|
|
|
|
|
|
|
transform.set_translation_xyz(3.0*144.0/2.0*3.0, 3.0*256.0/2.0, 0.0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
world
|
|
|
|
|
.create_entity()
|
|
|
|
|
.with(background_sprite.clone()) // Sprite Render
|
|
|
|
|
.with(TiledScroller {
|
|
|
|
|
speed: -75.0,
|
|
|
|
|
position: 2.0,
|
|
|
|
|
width: 0.0,
|
|
|
|
|
height: 0.0
|
|
|
|
|
})
|
|
|
|
|
.with(transform.clone())
|
|
|
|
|
.build();
|
|
|
|
|
fn handle_event(
|
|
|
|
|
&mut self,
|
|
|
|
|
mut data: StateData<'_, GameData<'_, '_>>,
|
|
|
|
|
event: StateEvent,
|
|
|
|
|
) -> SimpleTrans {
|
|
|
|
|
|
|
|
|
|
let ground_sprite = sprites.get("ground").unwrap();
|
|
|
|
|
transform.set_translation_xyz(3.0*168.0/2.0*3.0, 3.0*56.0/2.0, 0.1);
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
world
|
|
|
|
|
.create_entity()
|
|
|
|
|
.with(ground_sprite.clone()) // Sprite Render
|
|
|
|
|
.with(TiledScroller {
|
|
|
|
|
speed: -100.0,
|
|
|
|
|
position: 2.0,
|
|
|
|
|
width: 0.0,
|
|
|
|
|
height: 0.0,
|
|
|
|
|
})
|
|
|
|
|
.with(transform.clone())
|
|
|
|
|
.build();
|
|
|
|
|
// 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();
|
|
|
|
|
|
|
|
|
|
let birb_sprite = sprites.get("floppy").unwrap();
|
|
|
|
|
transform.set_translation_xyz(dimensions.width()/2.0, dimensions.height()/2.0, 0.2);
|
|
|
|
|
return Trans::Push(Box::new(ReadyState::default()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
// Keep going
|
|
|
|
|
Trans::None
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn update(&mut self, data: &mut StateData<'_, GameData<'_, '_>>) -> SimpleTrans {
|
|
|
|
|
Trans::None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
|
pub struct PausedState {
|
|
|
|
|
sprite: Option<Entity>,
|
|
|
|
|
pub struct ReadyState {
|
|
|
|
|
sprites: Vec<Entity>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl SimpleState for PausedState {
|
|
|
|
|
|
|
|
|
|
fn on_start(&mut self, data: StateData<'_, GameData<'_, '_>>) {
|
|
|
|
|
let world = data.world;
|
|
|
|
|
impl ReadyState {
|
|
|
|
|
fn init_sprites(&mut self, world: &mut World, dimensions: &ScreenDimensions) {
|
|
|
|
|
|
|
|
|
|
let dimensions = (*world.read_resource::<ScreenDimensions>()).clone();
|
|
|
|
|
let sprites = world.try_fetch_mut::<HashMap<String, SpriteRender>>().unwrap().clone();
|
|
|
|
|
|
|
|
|
|
let sprite = world.try_fetch::<HashMap<String, SpriteRender>>().unwrap().get("up-pipe").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 sprite = resource.get("up-pipe").unwrap().clone();
|
|
|
|
|
let mut transform = Transform::default();
|
|
|
|
|
transform.set_scale(Vector3::new(3.0, 3.0, 3.0));
|
|
|
|
|
transform.set_translation_xyz(dimensions.width()/2.0 - 100.0, dimensions.height() - 100.0, 0.1);
|
|
|
|
|
|
|
|
|
|
self.sprites.push(world
|
|
|
|
|
.create_entity()
|
|
|
|
|
.with(get_ready_text_sprite.clone()) // Sprite Render
|
|
|
|
|
.with(transform.clone())
|
|
|
|
|
.build());
|
|
|
|
|
|
|
|
|
|
transform.set_translation_xyz(500.0/2.0, 500.0/2.0, 0.1);
|
|
|
|
|
|
|
|
|
|
self.sprite = Some(world
|
|
|
|
|
self.sprites.push(world
|
|
|
|
|
.create_entity()
|
|
|
|
|
.with(sprite.clone()) // Sprite Render
|
|
|
|
|
.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;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn handle_event(
|
|
|
|
|
&mut self,
|
|
|
|
@ -250,12 +417,19 @@ impl SimpleState for PausedState {
|
|
|
|
|
|
|
|
|
|
if let StateEvent::Window(event) = &event {
|
|
|
|
|
// Check if the window should be closed
|
|
|
|
|
if is_key_down(&event, VirtualKeyCode::Space) {
|
|
|
|
|
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;
|
|
|
|
|
world.delete_entity(self.sprite.unwrap());
|
|
|
|
|
self.sprite = None;
|
|
|
|
|
return Trans::Pop;
|
|
|
|
|
for i in &self.sprites {
|
|
|
|
|
world.delete_entity(*i);
|
|
|
|
|
}
|
|
|
|
|
self.sprites.clear();
|
|
|
|
|
|
|
|
|
|
return Trans::Push(Box::new(PlayState::default()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|