diff --git a/config/bindings_config.ron b/config/bindings_config.ron new file mode 100644 index 0000000..5d208f8 --- /dev/null +++ b/config/bindings_config.ron @@ -0,0 +1,6 @@ +( + axes: {}, + actions: { + "exit_game": [[Key(Escape)]], + }, +) \ No newline at end of file diff --git a/src/resources/mod.rs b/src/resources/mod.rs new file mode 100644 index 0000000..4e41f28 --- /dev/null +++ b/src/resources/mod.rs @@ -0,0 +1 @@ +pub mod spritesheet; diff --git a/src/resources/spritesheet.rs b/src/resources/spritesheet.rs new file mode 100644 index 0000000..3b349e6 --- /dev/null +++ b/src/resources/spritesheet.rs @@ -0,0 +1,79 @@ +use amethyst::{ + assets::{AssetStorage, Handle, Loader, ProgressCounter}, + prelude::*, + renderer::{ImageFormat, Texture}, + renderer::{SpriteSheet, SpriteSheetFormat}, +}; +use std::{collections::HashMap, path::PathBuf}; + +/// +#[derive(Default)] +pub struct SpriteSheetMapLoader { + map: SpriteSheetMap, + paths: Vec<(String, PathBuf, PathBuf)>, +} + +impl SpriteSheetMapLoader { + /// create a new map loader + pub fn new() -> Self { + Default::default() + } + + /// add a path to a sprite sheet + pub fn with_paths(mut self, name: String, spritesheet: PathBuf, texture: PathBuf) -> Self { + self.paths.push((name, spritesheet, texture)); + self + } + + /// load all the sprites provided to the loader and return a progress counter and spritesheetmap + pub fn load(mut self, world: &mut World) -> (SpriteSheetMap, ProgressCounter) { + let map = &mut self.map; + let mut counter = ProgressCounter::new(); + + for (name, spritesheet_path, texture_path) in self.paths { + let texture_handle = { + let loader = world.read_resource::(); + let texture_storage = world.read_resource::>(); + loader.load( + texture_path.to_str().unwrap(), + ImageFormat::default(), + &mut counter, + &texture_storage, + ) + }; + + let spritesheet_handle = { + let loader = world.read_resource::(); + let spritesheet_storage = world.read_resource::>(); + loader.load( + spritesheet_path.to_str().unwrap(), + SpriteSheetFormat(texture_handle), + &mut counter, + &spritesheet_storage, + ) + }; + + map.insert(name.clone(), spritesheet_handle); + } + + (self.map, counter) + } +} + +/// a map of spritesheets loaded into the game's memory +#[derive(Default)] +pub struct SpriteSheetMap { + map: HashMap>, +} + +impl SpriteSheetMap { + /// insert a new handle into the spritesheet map + pub fn insert(&mut self, name: String, spritesheet_handle: Handle) { + self.map.insert(name, spritesheet_handle); + } + + /// get a spritesheet handle from it's name + pub fn get_handle(&self, name: String) -> Option<&Handle> { + self.map.get(&name) + } +} diff --git a/src/states/mod.rs b/src/states/mod.rs new file mode 100644 index 0000000..a1e64df --- /dev/null +++ b/src/states/mod.rs @@ -0,0 +1,2 @@ +pub mod preload; +pub mod titlescreen; diff --git a/src/states/preload.rs b/src/states/preload.rs new file mode 100644 index 0000000..7e3dbfb --- /dev/null +++ b/src/states/preload.rs @@ -0,0 +1,47 @@ +use crate::resources::spritesheet::*; +use amethyst::{assets::ProgressCounter, prelude::*}; + +/// struct for preloading the game +pub struct PreloadState { + counter: Option, +} + +impl PreloadState { + pub fn new() -> Self { + Self { counter: None } + } +} + +impl SimpleState for PreloadState { + fn on_start(&mut self, data: StateData<'_, GameData<'_, '_>>) { + // load the spritesheet + let (spritesheet_map, counter) = SpriteSheetMapLoader::new() + .with_paths( + "title_screen".into(), + "img/title_screen_sprite_sheet.ron".into(), + "img/title_screen_texture.png".into(), + ) + .load(data.world); + + self.counter = Some(counter); + data.world.insert(spritesheet_map); + } + + fn update(&mut self, _data: &mut StateData<'_, GameData<'_, '_>>) -> SimpleTrans { + if let Some(counter) = &self.counter { + let (assets, finished) = (counter.num_assets(), counter.num_finished()); + + if assets != finished { + println!("{} of {} loaded", counter.num_finished(), counter.num_assets()); + Trans::None + } else if counter.is_complete() { + println!("completed load!"); + Trans::Switch(Box::new(crate::states::titlescreen::TitleScreenState)) + } else { + Trans::None + } + } else { + Trans::None + } + } +} diff --git a/src/states/titlescreen.rs b/src/states/titlescreen.rs new file mode 100644 index 0000000..e958950 --- /dev/null +++ b/src/states/titlescreen.rs @@ -0,0 +1,82 @@ +use crate::resources::spritesheet::SpriteSheetMap; +use amethyst::{ + core::transform::Transform, + prelude::*, + renderer::{Camera, SpriteRender}, + window::ScreenDimensions, +}; +use nalgebra::Vector3; + +const DEFAULT_SPRITE_WIDTH: f32 = 256.0; +const DEFAULT_SPRITE_HEIGHT: f32 = 144.0; + +/// struct for title screen state +pub struct TitleScreenState; + +impl TitleScreenState { + /// initialize the titlescreen + fn init(&self, world: &mut World, dimensions: ScreenDimensions) { + self.init_camera(world, &dimensions); + self.init_scenery(world, &dimensions); + } + + // initialize the camera + fn init_camera(&self, world: &mut World, dimensions: &ScreenDimensions) { + let mut transform = Transform::default(); + transform.set_translation_xyz(dimensions.width() * 0.5, dimensions.height() * 0.5, 1.0); + + world + .create_entity() + .with(Camera::standard_2d(dimensions.width(), dimensions.height())) + .with(transform) + .build(); + } + + // initialize the scenery + fn init_scenery(&self, world: &mut World, dimensions: &ScreenDimensions) { + // create the scale vector + let scale_vector = Vector3::new( + dimensions.width() / DEFAULT_SPRITE_WIDTH, + dimensions.height() / DEFAULT_SPRITE_HEIGHT, + 0.0, + ); + + // create scenery transform + let mut transform = Transform::default(); + transform.set_translation_xyz(dimensions.width() * 0.5, dimensions.height() * 0.5, 0.0); + transform.set_scale(scale_vector); + + // get the sprite sheet from the map + let spritesheet_handle = { + if let Some(map) = world.try_fetch::() { + map.get_handle("title_screen".into()) + .expect("could not find title_screen sprite sheet") + .clone() + } else { + panic!("failed to find") + } + }; + + // create a sprite render + let mut sprite_render = SpriteRender { sprite_sheet: spritesheet_handle, sprite_number: 2 }; + + world.create_entity().with(transform.clone()).with(sprite_render.clone()).build(); + sprite_render.sprite_number = 1; + world.create_entity().with(transform.clone()).with(sprite_render.clone()).build(); + sprite_render.sprite_number = 0; + world.create_entity().with(transform.clone()).with(sprite_render.clone()).build(); + sprite_render.sprite_number = 3; + world.create_entity().with(transform.clone()).with(sprite_render.clone()).build(); + sprite_render.sprite_number = 4; + world.create_entity().with(transform.clone()).with(sprite_render.clone()).build(); + } +} + +impl SimpleState for TitleScreenState { + fn on_start(&mut self, data: StateData<'_, GameData<'_, '_>>) { + let world = data.world; + let dimensions = (*world.read_resource::()).clone(); + + self.init(world, dimensions); + } +}