diff --git a/src/components.rs b/src/components.rs new file mode 100644 index 0000000..794f6f9 --- /dev/null +++ b/src/components.rs @@ -0,0 +1,19 @@ +use rltk::RGB; +use specs::prelude::*; +use specs_derive::*; + +#[derive(Component)] +pub struct Position { + pub x: i32, + pub y: i32, +} + +#[derive(Component)] +pub struct Renderable { + pub glyph: rltk::FontCharType, + pub fg: RGB, + pub bg: RGB, +} + +#[derive(Component, Debug)] +pub struct Player {} diff --git a/src/main.rs b/src/main.rs index 4c4129c..cf7cda0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,60 +1,24 @@ -use rltk::{GameState, Rltk, RGB}; +use components::*; +use map::*; +use player::*; +use rltk::{GameState, RGB}; use specs::prelude::*; -use specs_derive::Component; -use std::cmp::{max, min}; -#[derive(Component)] -struct Position { - x: i32, - y: i32, -} +mod components; +mod map; +mod player; -#[derive(Component)] -struct Renderable { - glyph: rltk::FontCharType, - fg: RGB, - bg: RGB, -} - -#[derive(Component, Debug)] -struct Player {} - -struct State { +pub struct State { ecs: World, } impl State { fn run_systems(&mut self) { - let mut lw = LeftWalker {}; - lw.run_now(&self.ecs); self.ecs.maintain(); } } -fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) { - let mut positions = ecs.write_storage::(); - let mut players = ecs.write_storage::(); - - for (_player, pos) in (&mut players, &mut positions).join() { - pos.x = min(79, max(0, pos.x + delta_x)); - pos.y = min(49, max(0, pos.y + delta_y)); - } -} - -fn player_input(gs: &mut State, ctx: &mut Rltk) { - match ctx.key { - None => {} - Some(key) => match key { - rltk::VirtualKeyCode::Left => try_move_player(-1, 0, &mut gs.ecs), - rltk::VirtualKeyCode::Right => try_move_player(1, 0, &mut gs.ecs), - rltk::VirtualKeyCode::Up => try_move_player(0, -1, &mut gs.ecs), - rltk::VirtualKeyCode::Down => try_move_player(0, 1, &mut gs.ecs), - _ => {} - }, - } -} - impl GameState for State { fn tick(&mut self, ctx: &mut rltk::Rltk) { ctx.cls(); @@ -62,6 +26,9 @@ impl GameState for State { player_input(self, ctx); self.run_systems(); + let map = self.ecs.fetch::>(); + draw_map(&map, ctx); + let positions = self.ecs.read_storage::(); let renderables = self.ecs.read_storage::(); @@ -75,12 +42,15 @@ fn main() -> rltk::BError { use rltk::RltkBuilder; let context = RltkBuilder::simple80x50() .with_title("Roguelike Tutorial") + .with_automatic_console_resize(false) + .with_dimensions(80 * 3, 50 * 3) .build()?; let mut gs = State { ecs: World::new() }; gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); + gs.ecs.insert(new_map_rooms_and_corridors()); gs.ecs .create_entity() diff --git a/src/map.rs b/src/map.rs new file mode 100644 index 0000000..e65a63f --- /dev/null +++ b/src/map.rs @@ -0,0 +1,79 @@ +use rltk::{Rltk, RGB}; + +#[derive(PartialEq, Copy, Clone)] +pub enum TileType { + Wall, + Floor, +} + +pub fn xy_idx(x: i32, y: i32) -> usize { + (y as usize * 80) + x as usize +} + +pub fn new_map_rooms_and_corridors() -> Vec { + let mut map = vec![TileType::Wall; 80 * 50]; + + map +} + +/// Makes a map with solid boundaries and 400 randomly placed walls. No guarantees that it won't look awful +pub fn new_map_test() -> Vec { + let mut map = vec![TileType::Floor; 80 * 50]; + + for x in 0..80 { + map[xy_idx(x, 0)] = TileType::Wall; + map[xy_idx(x, 49)] = TileType::Wall; + } + + for y in 0..50 { + map[xy_idx(0, y)] = TileType::Wall; + map[xy_idx(79, y)] = TileType::Wall; + } + + let mut rng = rltk::RandomNumberGenerator::new(); + + for _i in 0..400 { + let x = rng.roll_dice(1, 79); + let y = rng.roll_dice(1, 49); + let idx = xy_idx(x, y); + if idx != xy_idx(40, 25) { + map[idx] = TileType::Wall; + } + } + + map +} + +pub fn draw_map(map: &[TileType], ctx: &mut Rltk) { + let mut y = 0; + let mut x = 0; + for tile in map.iter() { + match tile { + TileType::Floor => { + ctx.set( + x, + y, + RGB::from_f32(0.5, 0.5, 0.5), + RGB::from_f32(0., 0., 0.), + rltk::to_cp437('.'), + ); + } + + TileType::Wall => { + ctx.set( + x, + y, + RGB::from_f32(0.0, 1.0, 0.0), + RGB::from_f32(0., 0., 0.), + rltk::to_cp437('#'), + ); + } + } + + x += 1; + if x > 79 { + x = 0; + y += 1; + } + } +} diff --git a/src/player.rs b/src/player.rs new file mode 100644 index 0000000..95300cc --- /dev/null +++ b/src/player.rs @@ -0,0 +1,35 @@ +use crate::{ + components::{Player, Position}, + map::{xy_idx, TileType}, + State, +}; +use rltk::Rltk; +use specs::prelude::*; +use std::cmp::{max, min}; + +pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) { + let mut positions = ecs.write_storage::(); + let mut players = ecs.write_storage::(); + let map = ecs.fetch::>(); + + for (_player, pos) in (&mut players, &mut positions).join() { + let destination_idx = xy_idx(pos.x + delta_x, pos.y + delta_y); + if map[destination_idx] != TileType::Wall { + pos.x = min(79, max(0, pos.x + delta_x)); + pos.y = min(49, max(0, pos.y + delta_y)); + } + } +} + +pub fn player_input(gs: &mut State, ctx: &mut Rltk) { + match ctx.key { + None => {} + Some(key) => match key { + rltk::VirtualKeyCode::Left => try_move_player(-1, 0, &mut gs.ecs), + rltk::VirtualKeyCode::Right => try_move_player(1, 0, &mut gs.ecs), + rltk::VirtualKeyCode::Up => try_move_player(0, -1, &mut gs.ecs), + rltk::VirtualKeyCode::Down => try_move_player(0, 1, &mut gs.ecs), + _ => {} + }, + } +}