Create camera, and adjust drawing code to render arbitrary size maps
This commit is contained in:
parent
6af7476c51
commit
f749d9a9e5
168
src/camera.rs
Normal file
168
src/camera.rs
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
use rltk::{Point, Rltk, RGB};
|
||||||
|
use specs::prelude::*;
|
||||||
|
|
||||||
|
use crate::{Hidden, Map, Position, Renderable, TileType};
|
||||||
|
|
||||||
|
const SHOW_BOUNDARIES: bool = true;
|
||||||
|
|
||||||
|
pub fn get_screen_bounds(ecs: &World, ctx: &mut Rltk) -> (i32, i32, i32, i32) {
|
||||||
|
let player_pos = ecs.fetch::<Point>();
|
||||||
|
let (x_chars, y_chars) = ctx.get_char_size();
|
||||||
|
|
||||||
|
let center_x = (x_chars / 2) as i32;
|
||||||
|
let center_y = (y_chars / 2) as i32;
|
||||||
|
|
||||||
|
let min_x = player_pos.x - center_x;
|
||||||
|
let max_x = min_x + x_chars as i32;
|
||||||
|
let min_y = player_pos.y - center_y;
|
||||||
|
let max_y = min_y + y_chars as i32;
|
||||||
|
|
||||||
|
(min_x, max_x, min_y, max_y)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_camera(ecs: &World, ctx: &mut Rltk) {
|
||||||
|
let map = ecs.fetch::<Map>();
|
||||||
|
let (min_x, max_x, min_y, max_y) = get_screen_bounds(ecs, ctx);
|
||||||
|
|
||||||
|
// Render the Map
|
||||||
|
let map_width = map.width - 1;
|
||||||
|
let map_height = map.height - 1;
|
||||||
|
|
||||||
|
let mut y = 0;
|
||||||
|
#[allow(clippy::explicit_counter_loop)]
|
||||||
|
for ty in min_y..max_y {
|
||||||
|
let mut x = 0;
|
||||||
|
for tx in min_x..max_x {
|
||||||
|
if tx > 0 && tx < map_width && ty > 0 && ty < map_height {
|
||||||
|
let idx = map.xy_idx(tx, ty);
|
||||||
|
if map.revealed_tiles[idx] {
|
||||||
|
let (glyph, fg, bg) = get_tile_glyph(idx, &*map);
|
||||||
|
ctx.set(x, y, fg, bg, glyph);
|
||||||
|
}
|
||||||
|
} else if SHOW_BOUNDARIES {
|
||||||
|
ctx.set(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
RGB::named(rltk::GRAY),
|
||||||
|
RGB::named(rltk::BLACK),
|
||||||
|
rltk::to_cp437('·'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
x += 1;
|
||||||
|
}
|
||||||
|
y += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render entities
|
||||||
|
let positions = ecs.read_storage::<Position>();
|
||||||
|
let renderables = ecs.read_storage::<Renderable>();
|
||||||
|
let hidden = ecs.read_storage::<Hidden>();
|
||||||
|
let map = ecs.fetch::<Map>();
|
||||||
|
|
||||||
|
let mut data = (&positions, &renderables, !&hidden)
|
||||||
|
.join()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
data.sort_by(|&a, &b| b.1.render_order.cmp(&a.1.render_order));
|
||||||
|
for (pos, render, _hidden) in data.iter() {
|
||||||
|
let idx = map.xy_idx(pos.x, pos.y);
|
||||||
|
if map.visible_tiles[idx] {
|
||||||
|
let entity_screen_x = pos.x - min_x;
|
||||||
|
let entity_screen_y = pos.y - min_y;
|
||||||
|
if entity_screen_x > 0
|
||||||
|
&& entity_screen_x < map_width
|
||||||
|
&& entity_screen_y > 0
|
||||||
|
&& entity_screen_y < map_height
|
||||||
|
{
|
||||||
|
ctx.set(
|
||||||
|
entity_screen_x,
|
||||||
|
entity_screen_y,
|
||||||
|
render.fg,
|
||||||
|
render.bg,
|
||||||
|
render.glyph,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_tile_glyph(idx: usize, map: &Map) -> (rltk::FontCharType, RGB, RGB) {
|
||||||
|
let glyph;
|
||||||
|
let mut fg;
|
||||||
|
let mut bg = RGB::from_f32(0., 0., 0.);
|
||||||
|
|
||||||
|
match map.tiles[idx] {
|
||||||
|
TileType::Floor => {
|
||||||
|
glyph = rltk::to_cp437('.');
|
||||||
|
fg = RGB::from_f32(0., 0.5, 0.5);
|
||||||
|
}
|
||||||
|
TileType::Wall => {
|
||||||
|
let x = idx as i32 % map.width;
|
||||||
|
let y = idx as i32 / map.width;
|
||||||
|
glyph = wall_glyph(&*map, x, y);
|
||||||
|
fg = RGB::from_f32(0., 1.0, 0.);
|
||||||
|
}
|
||||||
|
TileType::DownStairs => {
|
||||||
|
glyph = rltk::to_cp437('>');
|
||||||
|
fg = RGB::from_f32(0., 1.0, 1.0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if map.bloodstains.contains(&idx) {
|
||||||
|
bg = RGB::from_f32(0.75, 0., 0.);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !map.visible_tiles[idx] {
|
||||||
|
fg = fg.to_greyscale();
|
||||||
|
|
||||||
|
// Don't show bloodstains out of visual range
|
||||||
|
bg = RGB::from_f32(0., 0., 0.);
|
||||||
|
}
|
||||||
|
|
||||||
|
(glyph, fg, bg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wall_glyph(map: &Map, x: i32, y: i32) -> rltk::FontCharType {
|
||||||
|
if x < 1 || x > map.width - 2 || y < 1 || y > map.height - 2 {
|
||||||
|
return 35;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut mask = 0u8;
|
||||||
|
|
||||||
|
if is_revealed_and_wall(map, x, y - 1) {
|
||||||
|
mask += 1;
|
||||||
|
}
|
||||||
|
if is_revealed_and_wall(map, x, y + 1) {
|
||||||
|
mask += 2;
|
||||||
|
}
|
||||||
|
if is_revealed_and_wall(map, x - 1, y) {
|
||||||
|
mask += 4;
|
||||||
|
}
|
||||||
|
if is_revealed_and_wall(map, x + 1, y) {
|
||||||
|
mask += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
match mask {
|
||||||
|
0 => 9, // Pillar because we can't see neighbors
|
||||||
|
1 => 186, // Wall only to the north
|
||||||
|
2 => 186, // Wall only to the south
|
||||||
|
3 => 186, // Wall to the north and south
|
||||||
|
4 => 205, // Wall only to the west
|
||||||
|
5 => 188, // Wall to the north and west
|
||||||
|
6 => 187, // Wall to the south and west
|
||||||
|
7 => 185, // Wall to the north, south, and west
|
||||||
|
8 => 205, // Wall only to the east
|
||||||
|
9 => 200, // Wall to the north and east
|
||||||
|
10 => 201, // Wall to the sound and east
|
||||||
|
11 => 204, // Wall to the north, south, and east
|
||||||
|
12 => 205, // Wall to the east and west
|
||||||
|
13 => 202, // Wall to the east, west, and south
|
||||||
|
14 => 203, // Wall to the east, west, and north
|
||||||
|
15 => 206, // ╬ Wall on all sides
|
||||||
|
_ => 35, // We missed one?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_revealed_and_wall(map: &Map, x: i32, y: i32) -> bool {
|
||||||
|
let idx = map.xy_idx(x, y);
|
||||||
|
map.tiles[idx] == TileType::Wall && map.revealed_tiles[idx]
|
||||||
|
}
|
37
src/gui.rs
37
src/gui.rs
@ -6,7 +6,7 @@ use crate::components::{
|
|||||||
};
|
};
|
||||||
use crate::game_log::GameLog;
|
use crate::game_log::GameLog;
|
||||||
use crate::rex_assets::RexAssets;
|
use crate::rex_assets::RexAssets;
|
||||||
use crate::{Equipped, Hidden, Map, RunState, State};
|
use crate::{camera, Equipped, Hidden, Map, RunState, State};
|
||||||
|
|
||||||
pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
||||||
ctx.draw_box(
|
ctx.draw_box(
|
||||||
@ -98,20 +98,32 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn draw_tooltips(ecs: &World, ctx: &mut Rltk) {
|
fn draw_tooltips(ecs: &World, ctx: &mut Rltk) {
|
||||||
|
let (min_x, _max_x, min_y, _max_y) = camera::get_screen_bounds(ecs, ctx);
|
||||||
let map = ecs.fetch::<Map>();
|
let map = ecs.fetch::<Map>();
|
||||||
let names = ecs.read_storage::<Name>();
|
let names = ecs.read_storage::<Name>();
|
||||||
let positions = ecs.read_storage::<Position>();
|
let positions = ecs.read_storage::<Position>();
|
||||||
let hidden = ecs.read_storage::<Hidden>();
|
let hidden = ecs.read_storage::<Hidden>();
|
||||||
|
|
||||||
let mouse_pos = ctx.mouse_pos();
|
let mouse_pos = ctx.mouse_pos();
|
||||||
if mouse_pos.0 >= map.width || mouse_pos.1 >= map.height {
|
let mut mouse_map_pos = mouse_pos;
|
||||||
|
mouse_map_pos.0 += min_x;
|
||||||
|
mouse_map_pos.1 += min_y;
|
||||||
|
if mouse_map_pos.0 >= map.width - 1
|
||||||
|
|| mouse_map_pos.1 >= map.height - 1
|
||||||
|
|| mouse_map_pos.0 < 1
|
||||||
|
|| mouse_map_pos.1 < 1
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !map.visible_tiles[map.xy_idx(mouse_map_pos.0, mouse_map_pos.1)] {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mut tooltip: Vec<String> = Vec::new();
|
let mut tooltip: Vec<String> = Vec::new();
|
||||||
|
|
||||||
for (name, position, _hidden) in (&names, &positions, !&hidden).join() {
|
for (name, position, _hidden) in (&names, &positions, !&hidden).join() {
|
||||||
let idx = map.xy_idx(position.x, position.y);
|
if position.x == mouse_map_pos.0 && position.y == mouse_map_pos.1 {
|
||||||
if position.x == mouse_pos.0 && position.y == mouse_pos.1 && map.visible_tiles[idx] {
|
|
||||||
tooltip.push(name.name.to_string());
|
tooltip.push(name.name.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -475,6 +487,7 @@ pub fn ranged_target(
|
|||||||
ctx: &mut Rltk,
|
ctx: &mut Rltk,
|
||||||
range: i32,
|
range: i32,
|
||||||
) -> (ItemMenuResult, Option<Point>) {
|
) -> (ItemMenuResult, Option<Point>) {
|
||||||
|
let (min_x, max_x, min_y, max_y) = camera::get_screen_bounds(&gs.ecs, ctx);
|
||||||
let player_entity = gs.ecs.fetch::<Entity>();
|
let player_entity = gs.ecs.fetch::<Entity>();
|
||||||
let player_pos = gs.ecs.fetch::<Point>();
|
let player_pos = gs.ecs.fetch::<Point>();
|
||||||
let viewsheds = gs.ecs.read_storage::<Viewshed>();
|
let viewsheds = gs.ecs.read_storage::<Viewshed>();
|
||||||
@ -493,19 +506,31 @@ pub fn ranged_target(
|
|||||||
for idx in visible.visible_tiles.iter() {
|
for idx in visible.visible_tiles.iter() {
|
||||||
let distance = rltk::DistanceAlg::Pythagoras.distance2d(*player_pos, *idx);
|
let distance = rltk::DistanceAlg::Pythagoras.distance2d(*player_pos, *idx);
|
||||||
if distance <= range as f32 {
|
if distance <= range as f32 {
|
||||||
|
let screen_x = idx.x - min_x;
|
||||||
|
let screen_y = idx.y - min_y;
|
||||||
|
|
||||||
|
if screen_x > 1
|
||||||
|
&& screen_x < (max_x - min_x) - 1
|
||||||
|
&& screen_y > 1
|
||||||
|
&& screen_y < (max_y - min_y) - 1
|
||||||
|
{
|
||||||
ctx.set_bg(idx.x, idx.y, RGB::named(rltk::BLUE));
|
ctx.set_bg(idx.x, idx.y, RGB::named(rltk::BLUE));
|
||||||
available_cells.push(idx);
|
available_cells.push(idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return (ItemMenuResult::Cancel, None);
|
return (ItemMenuResult::Cancel, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw mouse cursor
|
// Draw mouse cursor
|
||||||
let mouse_pos = ctx.mouse_pos();
|
let mouse_pos = ctx.mouse_pos();
|
||||||
|
let mut mouse_map_pos = mouse_pos;
|
||||||
|
mouse_map_pos.0 += min_x;
|
||||||
|
mouse_map_pos.1 += min_y;
|
||||||
let mut valid_target = false;
|
let mut valid_target = false;
|
||||||
for idx in available_cells.iter() {
|
for idx in available_cells.iter() {
|
||||||
if idx.x == mouse_pos.0 && idx.y == mouse_pos.1 {
|
if idx.x == mouse_map_pos.0 && idx.y == mouse_map_pos.1 {
|
||||||
valid_target = true;
|
valid_target = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -515,7 +540,7 @@ pub fn ranged_target(
|
|||||||
if ctx.left_click {
|
if ctx.left_click {
|
||||||
return (
|
return (
|
||||||
ItemMenuResult::Selected,
|
ItemMenuResult::Selected,
|
||||||
Some(Point::new(mouse_pos.0, mouse_pos.1)),
|
Some(Point::new(mouse_map_pos.0, mouse_map_pos.1)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
29
src/main.rs
29
src/main.rs
@ -2,6 +2,7 @@ use rltk::{GameState, Point, RandomNumberGenerator, Rltk};
|
|||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use specs::saveload::{SimpleMarker, SimpleMarkerAllocator};
|
use specs::saveload::{SimpleMarker, SimpleMarkerAllocator};
|
||||||
|
|
||||||
|
pub mod camera;
|
||||||
mod components;
|
mod components;
|
||||||
mod damage_system;
|
mod damage_system;
|
||||||
mod game_log;
|
mod game_log;
|
||||||
@ -150,28 +151,10 @@ impl GameState for State {
|
|||||||
RunState::MainMenu { .. } => {}
|
RunState::MainMenu { .. } => {}
|
||||||
RunState::GameOver { .. } => {}
|
RunState::GameOver { .. } => {}
|
||||||
_ => {
|
_ => {
|
||||||
// Draw the UI
|
camera::render_camera(&self.ecs, ctx);
|
||||||
draw_map(&self.ecs.fetch::<Map>(), ctx);
|
|
||||||
{
|
|
||||||
let positions = self.ecs.read_storage::<Position>();
|
|
||||||
let renderables = self.ecs.read_storage::<Renderable>();
|
|
||||||
let hidden = self.ecs.read_storage::<Hidden>();
|
|
||||||
let map = self.ecs.fetch::<Map>();
|
|
||||||
|
|
||||||
let mut data: Vec<_> = (&positions, &renderables, !&hidden).join().collect();
|
|
||||||
data.sort_by(|&a, &b| b.1.render_order.cmp(&a.1.render_order));
|
|
||||||
for (pos, render, _hidden) in data.iter() {
|
|
||||||
let idx = map.xy_idx(pos.x, pos.y);
|
|
||||||
|
|
||||||
if map.visible_tiles[idx] {
|
|
||||||
ctx.set(pos.x, pos.y, render.fg, render.bg, render.glyph)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gui::draw_ui(&self.ecs, ctx);
|
gui::draw_ui(&self.ecs, ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
match newrunstate {
|
match newrunstate {
|
||||||
RunState::MapGeneration => {
|
RunState::MapGeneration => {
|
||||||
@ -345,12 +328,12 @@ impl GameState for State {
|
|||||||
}
|
}
|
||||||
RunState::MagicMapReveal { row } => {
|
RunState::MagicMapReveal { row } => {
|
||||||
let mut map = self.ecs.fetch_mut::<Map>();
|
let mut map = self.ecs.fetch_mut::<Map>();
|
||||||
for x in 0..MAP_WIDTH {
|
for x in 0..map.width {
|
||||||
let idx = map.xy_idx(x as i32, row);
|
let idx = map.xy_idx(x as i32, row);
|
||||||
map.revealed_tiles[idx] = true;
|
map.revealed_tiles[idx] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if row as usize == MAP_HEIGHT - 1 {
|
if row == map.height - 1 {
|
||||||
newrunstate = RunState::MonsterTurn;
|
newrunstate = RunState::MonsterTurn;
|
||||||
} else {
|
} else {
|
||||||
newrunstate = RunState::MagicMapReveal { row: row + 1 };
|
newrunstate = RunState::MagicMapReveal { row: row + 1 };
|
||||||
@ -462,7 +445,7 @@ impl State {
|
|||||||
self.mapgen_history.clear();
|
self.mapgen_history.clear();
|
||||||
|
|
||||||
let mut rng = self.ecs.write_resource::<RandomNumberGenerator>();
|
let mut rng = self.ecs.write_resource::<RandomNumberGenerator>();
|
||||||
let mut builder = map_builders::random_builder(new_depth, &mut rng);
|
let mut builder = map_builders::random_builder(new_depth, &mut rng, 64, 64);
|
||||||
builder.build_map(&mut rng);
|
builder.build_map(&mut rng);
|
||||||
|
|
||||||
std::mem::drop(rng);
|
std::mem::drop(rng);
|
||||||
@ -550,7 +533,7 @@ fn main() -> rltk::BError {
|
|||||||
|
|
||||||
gs.ecs.insert(SimpleMarkerAllocator::<SerializeMe>::new());
|
gs.ecs.insert(SimpleMarkerAllocator::<SerializeMe>::new());
|
||||||
|
|
||||||
gs.ecs.insert(Map::new(1));
|
gs.ecs.insert(Map::new(1, 64, 64));
|
||||||
gs.ecs.insert(Point::zero());
|
gs.ecs.insert(Point::zero());
|
||||||
gs.ecs.insert(rltk::RandomNumberGenerator::new());
|
gs.ecs.insert(rltk::RandomNumberGenerator::new());
|
||||||
|
|
||||||
|
24
src/map.rs
24
src/map.rs
@ -4,10 +4,6 @@ use rltk::{Algorithm2D, BaseMap, Point, Rltk, SmallVec, RGB};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
pub const MAP_WIDTH: usize = 80;
|
|
||||||
pub const MAP_HEIGHT: usize = 43;
|
|
||||||
pub const MAP_COUNT: usize = MAP_HEIGHT * MAP_WIDTH;
|
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize)]
|
#[derive(PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize)]
|
||||||
pub enum TileType {
|
pub enum TileType {
|
||||||
Wall,
|
Wall,
|
||||||
@ -60,15 +56,17 @@ impl Map {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generates an empty map, consisting entirely of solid walls
|
/// Generates an empty map, consisting entirely of solid walls
|
||||||
pub fn new(new_depth: i32) -> Map {
|
pub fn new(new_depth: i32, width: i32, height: i32) -> Map {
|
||||||
|
let map_tile_count = (width * height) as usize;
|
||||||
|
|
||||||
Map {
|
Map {
|
||||||
tiles: vec![TileType::Wall; MAP_COUNT],
|
tiles: vec![TileType::Wall; map_tile_count],
|
||||||
width: MAP_WIDTH as i32,
|
width,
|
||||||
height: MAP_HEIGHT as i32,
|
height,
|
||||||
revealed_tiles: vec![false; MAP_COUNT],
|
revealed_tiles: vec![false; map_tile_count],
|
||||||
visible_tiles: vec![false; MAP_COUNT],
|
visible_tiles: vec![false; map_tile_count],
|
||||||
blocked: vec![false; MAP_COUNT],
|
blocked: vec![false; map_tile_count],
|
||||||
tile_content: vec![Vec::new(); MAP_COUNT],
|
tile_content: vec![Vec::new(); map_tile_count],
|
||||||
depth: new_depth,
|
depth: new_depth,
|
||||||
bloodstains: HashSet::new(),
|
bloodstains: HashSet::new(),
|
||||||
view_blocked: HashSet::new(),
|
view_blocked: HashSet::new(),
|
||||||
@ -173,7 +171,7 @@ pub fn draw_map(map: &Map, ctx: &mut Rltk) {
|
|||||||
|
|
||||||
// Move to the next set of coordinates
|
// Move to the next set of coordinates
|
||||||
x += 1;
|
x += 1;
|
||||||
if x > MAP_WIDTH as i32 - 1 {
|
if x > (map.width * map.height) as i32 - 1 {
|
||||||
x = 0;
|
x = 0;
|
||||||
y += 1;
|
y += 1;
|
||||||
}
|
}
|
||||||
|
@ -66,17 +66,21 @@ pub struct BuilderMap {
|
|||||||
pub rooms: Option<Vec<Rect>>,
|
pub rooms: Option<Vec<Rect>>,
|
||||||
pub corridors: Option<Vec<Vec<usize>>>,
|
pub corridors: Option<Vec<Vec<usize>>>,
|
||||||
pub history: Vec<Map>,
|
pub history: Vec<Map>,
|
||||||
|
pub width: i32,
|
||||||
|
pub height: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuilderMap {
|
impl BuilderMap {
|
||||||
fn new(new_depth: i32) -> BuilderMap {
|
fn new(new_depth: i32, width: i32, height: i32) -> BuilderMap {
|
||||||
BuilderMap {
|
BuilderMap {
|
||||||
spawn_list: Vec::new(),
|
spawn_list: Vec::new(),
|
||||||
map: Map::new(new_depth),
|
map: Map::new(new_depth, width, height),
|
||||||
starting_position: None,
|
starting_position: None,
|
||||||
rooms: None,
|
rooms: None,
|
||||||
corridors: None,
|
corridors: None,
|
||||||
history: Vec::new(),
|
history: Vec::new(),
|
||||||
|
width,
|
||||||
|
height,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,11 +102,11 @@ pub struct BuilderChain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BuilderChain {
|
impl BuilderChain {
|
||||||
pub fn new(new_depth: i32) -> BuilderChain {
|
pub fn new(new_depth: i32, width: i32, height: i32) -> BuilderChain {
|
||||||
BuilderChain {
|
BuilderChain {
|
||||||
starter: None,
|
starter: None,
|
||||||
builders: Vec::new(),
|
builders: Vec::new(),
|
||||||
build_data: BuilderMap::new(new_depth),
|
build_data: BuilderMap::new(new_depth, width, height),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,8 +293,13 @@ fn random_shape_builder(rng: &mut RandomNumberGenerator, builder: &mut BuilderCh
|
|||||||
builder.with(DistantExit::new());
|
builder.with(DistantExit::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn random_builder(new_depth: i32, rng: &mut RandomNumberGenerator) -> BuilderChain {
|
pub fn random_builder(
|
||||||
let mut builder = BuilderChain::new(new_depth);
|
new_depth: i32,
|
||||||
|
rng: &mut RandomNumberGenerator,
|
||||||
|
width: i32,
|
||||||
|
height: i32,
|
||||||
|
) -> BuilderChain {
|
||||||
|
let mut builder = BuilderChain::new(new_depth, width, height);
|
||||||
|
|
||||||
match rng.roll_dice(1, 2) {
|
match rng.roll_dice(1, 2) {
|
||||||
1 => random_room_builder(rng, &mut builder),
|
1 => random_room_builder(rng, &mut builder),
|
||||||
|
@ -33,7 +33,7 @@ impl WaveformCollapseBuilder {
|
|||||||
let constraints = patterns_to_constraints(patterns, CHUNK_SIZE);
|
let constraints = patterns_to_constraints(patterns, CHUNK_SIZE);
|
||||||
self.render_tile_gallery(&constraints, CHUNK_SIZE, build_data);
|
self.render_tile_gallery(&constraints, CHUNK_SIZE, build_data);
|
||||||
|
|
||||||
build_data.map = Map::new(build_data.map.depth);
|
build_data.map = Map::new(build_data.map.depth, build_data.width, build_data.height);
|
||||||
loop {
|
loop {
|
||||||
let mut solver = Solver::new(constraints.clone(), CHUNK_SIZE, &build_data.map);
|
let mut solver = Solver::new(constraints.clone(), CHUNK_SIZE, &build_data.map);
|
||||||
while !solver.iteration(&mut build_data.map, rng) {
|
while !solver.iteration(&mut build_data.map, rng) {
|
||||||
@ -54,7 +54,7 @@ impl WaveformCollapseBuilder {
|
|||||||
chunk_size: i32,
|
chunk_size: i32,
|
||||||
build_data: &mut BuilderMap,
|
build_data: &mut BuilderMap,
|
||||||
) {
|
) {
|
||||||
build_data.map = Map::new(0);
|
build_data.map = Map::new(0, build_data.width, build_data.height);
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
let mut x = 1;
|
let mut x = 1;
|
||||||
let mut y = 1;
|
let mut y = 1;
|
||||||
@ -71,7 +71,7 @@ impl WaveformCollapseBuilder {
|
|||||||
if y + chunk_size > build_data.map.height {
|
if y + chunk_size > build_data.map.height {
|
||||||
// Move to the next page
|
// Move to the next page
|
||||||
build_data.take_snapshot();
|
build_data.take_snapshot();
|
||||||
build_data.map = Map::new(0);
|
build_data.map = Map::new(0, build_data.width, build_data.height);
|
||||||
|
|
||||||
x = 1;
|
x = 1;
|
||||||
y = 1;
|
y = 1;
|
||||||
|
@ -61,8 +61,8 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !map.blocked[destination_idx] {
|
if !map.blocked[destination_idx] {
|
||||||
pos.x = min(79, max(0, pos.x + delta_x));
|
pos.x = min(map.width - 1, max(0, pos.x + delta_x));
|
||||||
pos.y = min(49, max(0, pos.y + delta_y));
|
pos.y = min(map.height - 1, max(0, pos.y + delta_y));
|
||||||
entity_moved
|
entity_moved
|
||||||
.insert(entity, EntityMoved {})
|
.insert(entity, EntityMoved {})
|
||||||
.expect("Failed to add EntityMoved flag to player");
|
.expect("Failed to add EntityMoved flag to player");
|
||||||
|
@ -191,7 +191,7 @@ pub fn load_game(ecs: &mut World) {
|
|||||||
for (e, h) in (&entities, &helper).join() {
|
for (e, h) in (&entities, &helper).join() {
|
||||||
let mut worldmap = ecs.write_resource::<crate::map::Map>();
|
let mut worldmap = ecs.write_resource::<crate::map::Map>();
|
||||||
*worldmap = h.map.clone();
|
*worldmap = h.map.clone();
|
||||||
worldmap.tile_content = vec![Vec::new(); crate::map::MAP_COUNT];
|
worldmap.tile_content = vec![Vec::new(); (worldmap.height * worldmap.width) as usize];
|
||||||
deleteme = Some(e);
|
deleteme = Some(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ use specs::prelude::*;
|
|||||||
use specs::saveload::{MarkedBuilder, SimpleMarker};
|
use specs::saveload::{MarkedBuilder, SimpleMarker};
|
||||||
|
|
||||||
use crate::components::*;
|
use crate::components::*;
|
||||||
use crate::map::MAP_WIDTH;
|
|
||||||
use crate::random_table::RandomTable;
|
use crate::random_table::RandomTable;
|
||||||
use crate::{Map, Rect, TileType};
|
use crate::{Map, Rect, TileType};
|
||||||
|
|
||||||
@ -125,8 +124,13 @@ pub fn spawn_region(
|
|||||||
|
|
||||||
/// Spawns a named entity (name in tuple.1) at the location in (tuple.0)
|
/// Spawns a named entity (name in tuple.1) at the location in (tuple.0)
|
||||||
pub fn spawn_entity(ecs: &mut World, spawn: &(&usize, &String)) {
|
pub fn spawn_entity(ecs: &mut World, spawn: &(&usize, &String)) {
|
||||||
let x = (*spawn.0 % MAP_WIDTH) as i32;
|
let map = ecs.fetch::<Map>();
|
||||||
let y = (*spawn.0 / MAP_WIDTH) as i32;
|
let width = map.width as usize;
|
||||||
|
let x = (*spawn.0 % width) as i32;
|
||||||
|
let y = (*spawn.0 / width) as i32;
|
||||||
|
|
||||||
|
// Drop this map reference to make the borrow checker happy
|
||||||
|
std::mem::drop(map);
|
||||||
|
|
||||||
match spawn.1.as_ref() {
|
match spawn.1.as_ref() {
|
||||||
"Goblin" => goblin(ecs, x, y),
|
"Goblin" => goblin(ecs, x, y),
|
||||||
|
Loading…
Reference in New Issue
Block a user