visible area limited

This commit is contained in:
Ben Morrison 2019-09-18 14:43:14 -04:00
parent 1e7fb1e98b
commit af9db4789b
Signed by: gbmor
GPG Key ID: 8F192E4720BB0DAC
5 changed files with 123 additions and 36 deletions

8
src/component.rs Normal file
View File

@ -0,0 +1,8 @@
use rltk;
use specs::prelude::*;
#[derive(Component)]
pub struct Viewshed {
pub visible_tiles: Vec<rltk::Point>,
pub range: i32,
}

View File

@ -4,26 +4,33 @@ extern crate specs_derive;
use rltk::{Rltk, RGB};
use specs::prelude::*;
mod component;
mod entity;
mod map;
mod player;
mod rect;
mod state;
mod visibility;
use crate::component::Viewshed;
use crate::entity::{Player, Position, Renderable};
use crate::map::Map;
use crate::state::State;
use crate::visibility::VisibilitySystem;
fn main() {
let context =
Rltk::init_simple8x8(80, 50, "MORTAL WOMBAT", "resources");
let mut gs = State {
ecs: World::new(),
systems: DispatcherBuilder::new().build(),
systems: DispatcherBuilder::new()
.with(VisibilitySystem {}, "visibility_system", &[])
.build(),
};
gs.ecs.register::<Position>();
gs.ecs.register::<Renderable>();
gs.ecs.register::<Player>();
gs.ecs.register::<Viewshed>();
let map = Map::new_room_corridors();
gs.ecs.insert(map.clone());
@ -39,6 +46,10 @@ fn main() {
bg: RGB::named(rltk::BLACK),
})
.with(Player {})
.with(Viewshed {
visible_tiles: vec![],
range: 8,
})
.build();
rltk::main_loop(context, gs);

View File

@ -1,8 +1,13 @@
use std::cmp::{max, min};
use rltk::{Console, RandomNumberGenerator, Rltk, RGB};
use rltk::{
Algorithm2D, BaseMap, Console, Point, RandomNumberGenerator, Rltk,
RGB,
};
use specs::prelude::*;
use crate::entity::TileType;
use crate::component::Viewshed;
use crate::entity::{Player, TileType};
use crate::rect::Rect;
#[derive(Clone)]
@ -13,6 +18,32 @@ pub struct Map {
pub height: i32,
}
impl Algorithm2D for Map {
fn point2d_to_index(&self, pt: Point) -> i32 {
(pt.y * self.width) + pt.x
}
fn index_to_point2d(&self, idx: i32) -> Point {
Point {
x: idx % self.width,
y: idx / self.width,
}
}
}
impl BaseMap for Map {
fn is_opaque(&self, idx: i32) -> bool {
self.tiles[idx as usize] == TileType::Wall
}
fn get_available_exits(&self, _idx: i32) -> Vec<(i32, f32)> {
Vec::new()
}
fn get_pathing_distance(&self, idx1: i32, idx2: i32) -> f32 {
let p1 = Point::new(idx1 % self.width, idx1 / self.width);
let p2 = Point::new(idx2 % self.width, idx2 / self.width);
rltk::DistanceAlg::Pythagoras.distance2d(p1, p2)
}
}
impl Map {
pub fn xy_idx(&self, x: i32, y: i32) -> usize {
(y as usize * 80) + x as usize
@ -131,35 +162,46 @@ pub fn new_test() -> Vec<TileType> {
}
*/
pub fn draw(map: &[TileType], ctx: &mut Rltk) {
let mut y = 0;
let mut x = 0;
map.iter().for_each(|tile| {
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('#'),
);
}
}
pub fn draw(ecs: &World, ctx: &mut Rltk) {
let mut viewsheds = ecs.write_storage::<Viewshed>();
let mut players = ecs.write_storage::<Player>();
let map = ecs.fetch::<Map>();
x += 1;
if x > 79 {
x = 0;
y += 1;
}
});
(&mut players, &mut viewsheds).join().into_iter().for_each(
|(_player, viewshed)| {
let mut y = 0;
let mut x = 0;
map.tiles.iter().for_each(|tile| {
let pt = Point::new(x, y);
if viewshed.visible_tiles.contains(&pt) {
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;
}
});
},
);
}

View File

@ -1,7 +1,7 @@
use rltk::{Console, GameState, Rltk};
use specs::prelude::*;
use crate::entity::{Position, Renderable, TileType};
use crate::entity::{Position, Renderable};
use crate::map;
use crate::player;
@ -17,8 +17,7 @@ impl GameState for State {
player::input(self, ctx);
self.systems.dispatch(&self.ecs);
let map = self.ecs.fetch::<Vec<TileType>>();
map::draw(&map, ctx);
map::draw(&self.ecs, ctx);
let positions = self.ecs.read_storage::<Position>();
let renderables = self.ecs.read_storage::<Renderable>();

27
src/visibility.rs Normal file
View File

@ -0,0 +1,27 @@
use super::{Map, Position, Viewshed};
use rltk::{field_of_view, Point};
use specs::prelude::*;
pub struct VisibilitySystem {}
impl<'a> System<'a> for VisibilitySystem {
type SystemData = (
ReadExpect<'a, Map>,
WriteStorage<'a, Viewshed>,
WriteStorage<'a, Position>,
);
fn run(&mut self, data: Self::SystemData) {
let (map, mut viewshed, pos) = data;
(&mut viewshed, &pos).join().into_iter().for_each(
|(viewshed, pos)| {
viewshed.visible_tiles.clear();
viewshed.visible_tiles = field_of_view(
Point::new(pos.x, pos.y),
viewshed.range,
&*map,
);
},
);
}
}