From 8770d8ab77c8dccc89542aa22b1f6469bed1dec9 Mon Sep 17 00:00:00 2001 From: klangner Date: Mon, 31 Aug 2020 14:13:52 +0200 Subject: [PATCH] Basic demo app --- .gitignore | 1 + README.md | 1 - demo/Cargo.toml | 15 +++ demo/assets/texture/cp437_20x20.png | Bin 0 -> 6496 bytes demo/assets/texture/cp437_20x20.ron | 8 ++ demo/config/display.ron | 4 + demo/config/input.ron | 27 +++++ demo/src/main.rs | 150 ++++++++++++++++++++++++++++ src/dungeon/map.rs | 12 +-- 9 files changed, 211 insertions(+), 7 deletions(-) create mode 100644 demo/Cargo.toml create mode 100644 demo/assets/texture/cp437_20x20.png create mode 100644 demo/assets/texture/cp437_20x20.ron create mode 100644 demo/config/display.ron create mode 100644 demo/config/input.ron create mode 100644 demo/src/main.rs diff --git a/.gitignore b/.gitignore index 869df07..93688a9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target +/demo/target Cargo.lock \ No newline at end of file diff --git a/README.md b/README.md index 8c6697f..a15efcb 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ [![Build Status](https://travis-ci.org/klangner/mapgen.rs.svg?branch=master)](https://travis-ci.org/klangner/mapgen.rs) [![Crates.io](https://img.shields.io/crates/v/mapgen.svg)](https://crates.io/crates/mapgen) -[![Crates.io](https://img.shields.io/crates/l/mapgen.svg)](https://github.com/klangner/mapgen.rs/blob/master/LICENSE-MIT) [![mapgen.rs](https://docs.rs/mapgen/badge.svg)](https://docs.rs/mapgen/) Generate procedural maps for games. diff --git a/demo/Cargo.toml b/demo/Cargo.toml new file mode 100644 index 0000000..f329aea --- /dev/null +++ b/demo/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "mapgen-demo" +version = "0.1.0" +authors = ["Krzysztof Langner "] +edition = "2018" + +[dependencies] +amethyst = {version = "0.15", features = ["tiles", "no-slow-safety-checks"]} +log = { version = "0.4.8", features = ["serde"] } +mapgen = {path=".."} + +[features] +default = ["metal"] +metal = ["amethyst/metal"] +vulkan = ["amethyst/vulkan"] diff --git a/demo/assets/texture/cp437_20x20.png b/demo/assets/texture/cp437_20x20.png new file mode 100644 index 0000000000000000000000000000000000000000..e7e2f5f27197fbccab9f09387f88f41cf43af0ef GIT binary patch literal 6496 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, world: &World) -> Option { + let map = world.read_resource::(); + if map.at(p.x as usize, p.y as usize) == TileType::Wall { + Some(35) + } else { + Some(46) + } + } +} + +fn load_tiles_sprite_sheet(world: &mut World, png_path: &str, ron_path: &str) -> SpriteSheetHandle { + let texture_handle = { + let loader = world.read_resource::(); + let texture_storage = world.read_resource::>(); + loader.load(png_path, ImageFormat::default(), (), &texture_storage) + }; + let loader = world.read_resource::(); + let sprite_sheet_store = world.read_resource::>(); + loader.load( + ron_path, + SpriteSheetFormat(texture_handle), + (), + &sprite_sheet_store, + ) +} + +fn init_camera(world: &mut World, transform: Transform, camera: Camera) -> Entity { + world + .create_entity() + .with(transform) + .with(camera) + .named("camera") + .build() +} + + +struct PlayState; +impl SimpleState for PlayState { + fn on_start(&mut self, data: StateData<'_, GameData<'_, '_>>) { + + let world = data.world; + + // Create map + let map = Map::new(80, 50); + world.insert(map); + + let map_sprite_sheet_handle = + load_tiles_sprite_sheet(world, "texture/cp437_20x20.png", "texture/cp437_20x20.ron"); + + let (width, height) = { + let dim = world.read_resource::(); + (dim.width(), dim.height()) + }; + + let _camera = init_camera( + world, + Transform::from(Vector3::new(-10.0, 10.0, 1.1)), + Camera::standard_2d(width, height), + ); + + let tile_map = TileMap::::new( + Vector3::new(80, 50, 1), + Vector3::new(20, 20, 1), + Some(map_sprite_sheet_handle), + ); + + let _map_entity = world + .create_entity() + .with(tile_map) + .with(Transform::default()) + .build(); + } + + fn handle_event( + &mut self, + data: StateData<'_, GameData<'_, '_>>, + event: StateEvent, + ) -> SimpleTrans { + let StateData { .. } = data; + if let StateEvent::Window(event) = &event { + if is_close_requested(&event) || is_key_down(&event, winit::VirtualKeyCode::Escape) { + Trans::Quit + } else { + Trans::None + } + } else { + Trans::None + } + } +} + +fn main() -> amethyst::Result<()> { + amethyst::Logger::from_config(Default::default()) + .level_for("demo", log::LevelFilter::Warn) + .start(); + + let app_root = application_root_dir()?; + let assets_directory = app_root.join("assets"); + let display_config_path = app_root.join("config/display.ron"); + + let game_data = GameDataBuilder::default() + .with_bundle(TransformBundle::new())? + .with_bundle( + InputBundle::::new() + .with_bindings_from_file("config/input.ron")?, + )? + .with_bundle( + RenderingBundle::::new() + .with_plugin( + RenderToWindow::from_config_path(display_config_path)? + .with_clear([0.0, 0.0, 0.0, 1.0]), + ) + .with_plugin(RenderFlat2D::default()) + .with_plugin(RenderTiles2D::::default()), + )?; + + let mut game = Application::build(assets_directory, PlayState)?.build(game_data)?; + game.run(); + Ok(()) +} \ No newline at end of file diff --git a/src/dungeon/map.rs b/src/dungeon/map.rs index b2a9d42..2a0260f 100644 --- a/src/dungeon/map.rs +++ b/src/dungeon/map.rs @@ -6,15 +6,15 @@ pub enum TileType { #[derive(Default, Clone)] pub struct Map { pub tiles : Vec, - pub width : i32, - pub height : i32, + pub width : usize, + pub height : usize, } impl Map { /// Generates an empty map, consisting entirely of solid walls - pub fn new(width: i32, height: i32) -> Map { - let map_tile_count = (width*height) as usize; + pub fn new(width: usize, height: usize) -> Map { + let map_tile_count = width*height; Map{ tiles : vec![TileType::Wall; map_tile_count], width, @@ -22,8 +22,8 @@ impl Map { } } - pub fn at(&self, x: i32, y: i32) -> TileType { - let idx = (y as usize * self.width as usize) + x as usize; + pub fn at(&self, x: usize, y: usize) -> TileType { + let idx = y * self.width + x; self.tiles[idx] }