From 648040095d08ab4683647b17bdeeb5571b38713e Mon Sep 17 00:00:00 2001 From: Peter Hart Date: Sat, 28 Mar 2020 19:57:47 -0400 Subject: [PATCH] refactor map into struct with impl trait --- src/main.rs | 14 ++-- src/map.rs | 204 ++++++++++++++++++++++++++++------------------------ 2 files changed, 117 insertions(+), 101 deletions(-) diff --git a/src/main.rs b/src/main.rs index 975e87e..ea8f72f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,12 +35,12 @@ pub struct Player {} 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::>(); + let map = ecs.fetch::(); for (_player, pos) in (&mut players, &mut positions).join() { let x = min(79, max(0, pos.x + delta_x)); let y = min(49, max(0, pos.y + delta_y)); - if map[xy_idx(x, y)] != TileType::Wall { + if map.tile_at(x,y) != TileType::Wall { pos.x = x; pos.y = y; } @@ -97,8 +97,8 @@ impl GameState for State { ctx.cls(); self.run_systems(); player_input(self, ctx); - let map = self.ecs.fetch::>(); - draw_map(&map, ctx); + let map = self.ecs.fetch::(); + map.draw_map(ctx); let positions = self.ecs.read_storage::(); let renderables = self.ecs.read_storage::(); @@ -114,8 +114,8 @@ fn main() { .with_title("Roguelike Tutorial") .build(); let mut gs = State { ecs: World::new() }; - let (rooms, map) = new_map_rooms_and_corridors(); - let (player_x, player_y) = rooms[0].center(); + let map = Map::new_map_rooms_and_corridors(); + let (player_x, player_y) = map.rooms[0].center(); gs.ecs.register::(); gs.ecs.register::(); @@ -148,8 +148,6 @@ fn main() { .with(LeftMover {}) .build(); } - - gs.ecs.insert(rooms); gs.ecs.insert(map); rltk::main_loop(context, gs); diff --git a/src/map.rs b/src/map.rs index 0e140a1..391426b 100644 --- a/src/map.rs +++ b/src/map.rs @@ -8,113 +8,131 @@ pub enum TileType { Floor, } -pub fn xy_idx(x: i32, y: i32) -> usize { - (y as usize * 80) + x as usize +pub struct Map { + pub tiles: Vec, + pub rooms: Vec, + pub width: i32, + pub height: i32, } -fn apply_room_to_map(room: &Rect, map: &mut Vec) { - for x in room.x1..room.x2 { - for y in room.y1..room.y2 { - map[xy_idx(x, y)] = TileType::Floor - } +impl Map { + pub fn xy_idx(&self, x: i32, y: i32) -> usize { + ((y * self.width) + x) as usize } -} -fn apply_horizontal_tunnel(map: &mut Vec, x1: i32, x2: i32, y: i32) { - for x in min(x1, x2)..=max(x1, x2) { - map[xy_idx(x, y)] = TileType::Floor + pub fn tile_at(&self, x: i32, y:i32) -> TileType { + self.tiles[self.xy_idx(x, y)] } -} -fn apply_vertical_tunnel(map: &mut Vec, x: i32, y1: i32, y2: i32) { - for y in min(y1, y2)..=max(y1, y2) { - map[xy_idx(x, y)] = TileType::Floor - } -} - -pub fn new_map_rooms_and_corridors() -> (Vec,Vec) { - let mut map = vec![TileType::Wall; 80 * 50]; - - let mut rooms: Vec = Vec::new(); - const MAX_ROOMS: i32 = 30; - const MIN_SIZE: i32 = 6; - const MAX_SIZE: i32 = 10; - - let mut rng = RandomNumberGenerator::new(); - - for _ in 0..MAX_ROOMS { - let w = rng.range(MIN_SIZE, MAX_SIZE); - let h = rng.range(MIN_SIZE, MAX_SIZE); - let x = rng.roll_dice(1, 80 - w - 1) - 1; - let y = rng.roll_dice(1, 50 - h - 1) - 1; - let new_room = Rect::new(x, y, w, h); - let mut ok = true; - for other_room in rooms.iter() { - if new_room.intersect(other_room) { - ok = false + fn apply_room_to_map(&mut self, room: &Rect) { + for x in room.x1..room.x2 { + for y in room.y1..room.y2 { + let idx = self.xy_idx(x,y); + self.tiles[idx] = TileType::Floor } } - if ok { - apply_room_to_map(&new_room, &mut map); - if rooms.len() > 0 { - let r1_center = new_room.center(); - let r2_center = rooms[rooms.len() - 1].center(); - if rng.range(0, 2) == 1 { - apply_horizontal_tunnel(&mut map, r1_center.0, r2_center.0, r1_center.1); - apply_vertical_tunnel( - &mut map, - max(r1_center.0, r2_center.0), - r1_center.1, - r2_center.1, + } + + fn apply_horizontal_tunnel(&mut self, x1: i32, x2: i32, y: i32) { + for x in min(x1, x2)..=max(x1, x2) { + let idx=self.xy_idx(x, y); + self.tiles[idx] = TileType::Floor + } + } + + fn apply_vertical_tunnel(&mut self, x: i32, y1: i32, y2: i32) { + for y in min(y1, y2)..=max(y1, y2) { + let idx=self.xy_idx(x, y); + self.tiles[idx] = TileType::Floor + } + } + + pub fn new_map_rooms_and_corridors() -> Map { + let mut map = Map { + tiles: vec![TileType::Wall; 80 * 50], + rooms: Vec::new(), + width: 80, + height: 50, + }; + + const MAX_ROOMS: i32 = 30; + const MIN_SIZE: i32 = 6; + const MAX_SIZE: i32 = 10; + + let mut rng = RandomNumberGenerator::new(); + + for _ in 0..MAX_ROOMS { + let w = rng.range(MIN_SIZE, MAX_SIZE); + let h = rng.range(MIN_SIZE, MAX_SIZE); + let x = rng.roll_dice(1, 80 - w - 1) - 1; + let y = rng.roll_dice(1, 50 - h - 1) - 1; + let new_room = Rect::new(x, y, w, h); + let mut ok = true; + for other_room in map.rooms.iter() { + if new_room.intersect(other_room) { + ok = false + } + } + if ok { + map.apply_room_to_map(&new_room); + if map.rooms.len() > 0 { + let r1_center = new_room.center(); + let r2_center = map.rooms[map.rooms.len() - 1].center(); + if rng.range(0, 2) == 1 { + map.apply_horizontal_tunnel(r1_center.0, r2_center.0, r1_center.1); + map.apply_vertical_tunnel( + max(r1_center.0, r2_center.0), + r1_center.1, + r2_center.1, + ); + } else { + map.apply_vertical_tunnel(r1_center.0, r1_center.1, r2_center.1); + map.apply_horizontal_tunnel( + r1_center.0, + r2_center.0, + max(r1_center.1, r2_center.1), + ); + } + } + map.rooms.push(new_room); + } + } + + map + } + + pub fn draw_map(&self, ctx: &mut Rltk) { + let mut y = 0; + let mut x = 0; + for tile in self.tiles.iter() { + // Render a tile depending upon the tile type + 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('.'), ); - } else { - apply_vertical_tunnel(&mut map, r1_center.0, r1_center.1, r2_center.1); - apply_horizontal_tunnel( - &mut map, - r1_center.0, - r2_center.0, - max(r1_center.1, r2_center.1), + } + TileType::Wall => { + ctx.set( + x, + y, + RGB::from_f32(0.0, 1.0, 0.0), + RGB::from_f32(0., 0., 0.), + rltk::to_cp437('#'), ); } } - rooms.push(new_room); - } - } - (rooms,map) -} - -pub fn draw_map(map: &[TileType], ctx: &mut Rltk) { - let mut y = 0; - let mut x = 0; - for tile in map.iter() { - // Render a tile depending upon the tile type - 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('.'), - ); + // Move the coordinates + x += 1; + if x > 79 { + x = 0; + y += 1; } - TileType::Wall => { - ctx.set( - x, - y, - RGB::from_f32(0.0, 1.0, 0.0), - RGB::from_f32(0., 0., 0.), - rltk::to_cp437('#'), - ); - } - } - - // Move the coordinates - x += 1; - if x > 79 { - x = 0; - y += 1; } } }