multiple levels
This commit is contained in:
parent
c17b62985b
commit
da36acbade
@ -8,7 +8,9 @@ pub struct Render {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct Player;
|
pub struct Player {
|
||||||
|
pub map_level: u32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct Enemy;
|
pub struct Enemy;
|
||||||
|
78
src/main.rs
78
src/main.rs
@ -11,8 +11,8 @@ mod prelude {
|
|||||||
pub use legion::systems::CommandBuffer;
|
pub use legion::systems::CommandBuffer;
|
||||||
pub use legion::world::SubWorld;
|
pub use legion::world::SubWorld;
|
||||||
pub use legion::*;
|
pub use legion::*;
|
||||||
pub const SCREEN_WIDTH: i32 = 80;
|
pub const SCREEN_WIDTH: i32 = 60;
|
||||||
pub const SCREEN_HEIGHT: i32 = 50;
|
pub const SCREEN_HEIGHT: i32 = 40;
|
||||||
pub const DISPLAY_WIDTH: i32 = SCREEN_WIDTH / 2;
|
pub const DISPLAY_WIDTH: i32 = SCREEN_WIDTH / 2;
|
||||||
pub const DISPLAY_HEIGHT: i32 = SCREEN_HEIGHT / 2;
|
pub const DISPLAY_HEIGHT: i32 = SCREEN_HEIGHT / 2;
|
||||||
pub use crate::camera::*;
|
pub use crate::camera::*;
|
||||||
@ -33,21 +33,80 @@ struct State {
|
|||||||
monster_systems: Schedule,
|
monster_systems: Schedule,
|
||||||
}
|
}
|
||||||
impl State {
|
impl State {
|
||||||
|
fn advance_level(&mut self) {
|
||||||
|
let player_entity = *<Entity>::query()
|
||||||
|
.filter(component::<Player>())
|
||||||
|
.iter(&mut self.ecs)
|
||||||
|
.nth(0)
|
||||||
|
.unwrap();
|
||||||
|
use std::collections::HashSet;
|
||||||
|
let mut entities_to_keep = HashSet::new();
|
||||||
|
entities_to_keep.insert(player_entity);
|
||||||
|
|
||||||
|
<(Entity, &Carried)>::query()
|
||||||
|
.iter(&self.ecs)
|
||||||
|
.filter(|(_e, carry)| carry.0 == player_entity)
|
||||||
|
.map(|(e, _carry)| *e)
|
||||||
|
.for_each(|e| {
|
||||||
|
entities_to_keep.insert(e);
|
||||||
|
});
|
||||||
|
let mut cb = CommandBuffer::new(&mut self.ecs);
|
||||||
|
for e in Entity::query().iter(&self.ecs) {
|
||||||
|
if !entities_to_keep.contains(e) {
|
||||||
|
cb.remove(*e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cb.flush(&mut self.ecs);
|
||||||
|
|
||||||
|
<&mut FieldOfView>::query()
|
||||||
|
.iter_mut(&mut self.ecs)
|
||||||
|
.for_each(|fov| fov.is_dirty = true);
|
||||||
|
|
||||||
|
let mut rng = RandomNumberGenerator::new();
|
||||||
|
let mut map_builder = MapBuilder::new(&mut rng);
|
||||||
|
let mut map_level = 0;
|
||||||
|
<(&mut Player, &mut Point)>::query()
|
||||||
|
.iter_mut(&mut self.ecs)
|
||||||
|
.for_each(|(player, pos)| {
|
||||||
|
player.map_level += 1;
|
||||||
|
map_level = player.map_level;
|
||||||
|
pos.x = map_builder.player_start.x;
|
||||||
|
pos.y = map_builder.player_start.y;
|
||||||
|
});
|
||||||
|
if map_level == 2 {
|
||||||
|
spawn_amulet_of_yala(&mut self.ecs, map_builder.amulet_start);
|
||||||
|
} else {
|
||||||
|
let exit_idx = map_builder.map.point2d_to_index(map_builder.amulet_start);
|
||||||
|
map_builder.map.tiles[exit_idx] = TileType::Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
map_builder
|
||||||
|
.monster_spawns
|
||||||
|
.iter()
|
||||||
|
.for_each(|pos| spawn_entity(&mut self.ecs, &mut rng, *pos));
|
||||||
|
|
||||||
|
self.resources.insert(map_builder.map);
|
||||||
|
self.resources.insert(Camera::new(map_builder.player_start));
|
||||||
|
self.resources.insert(TurnState::AwaitingInput);
|
||||||
|
self.resources.insert(map_builder.theme);
|
||||||
|
}
|
||||||
|
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
let mut ecs = World::default();
|
let mut ecs = World::default();
|
||||||
let mut resources = Resources::default();
|
let mut resources = Resources::default();
|
||||||
let mut rng = RandomNumberGenerator::new();
|
let mut rng = RandomNumberGenerator::new();
|
||||||
let map_builder = MapBuilder::new(&mut rng);
|
let mut map_builder = MapBuilder::new(&mut rng);
|
||||||
|
|
||||||
spawn_player(&mut ecs, map_builder.player_start);
|
spawn_player(&mut ecs, map_builder.player_start);
|
||||||
spawn_amulet_of_yala(&mut ecs, map_builder.amulet_start);
|
//spawn_amulet_of_yala(&mut ecs, map_builder.amulet_start);
|
||||||
|
let exit_idx = map_builder.map.point2d_to_index(map_builder.amulet_start);
|
||||||
|
map_builder.map.tiles[exit_idx] = TileType::Exit;
|
||||||
|
|
||||||
map_builder
|
map_builder
|
||||||
.monster_spawns
|
.monster_spawns
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|pos| spawn_entity(&mut ecs, &mut rng, *pos));
|
.for_each(|pos| spawn_entity(&mut ecs, &mut rng, *pos));
|
||||||
resources.insert(map_builder.map);
|
resources.insert(map_builder.map);
|
||||||
resources.insert(Camera::new(map_builder.player_start));
|
resources.insert(Camera::new(map_builder.player_start));
|
||||||
|
|
||||||
resources.insert(TurnState::AwaitingInput);
|
resources.insert(TurnState::AwaitingInput);
|
||||||
resources.insert(map_builder.theme);
|
resources.insert(map_builder.theme);
|
||||||
State {
|
State {
|
||||||
@ -89,9 +148,11 @@ impl State {
|
|||||||
self.ecs = World::default();
|
self.ecs = World::default();
|
||||||
self.resources = Resources::default();
|
self.resources = Resources::default();
|
||||||
let mut rng = RandomNumberGenerator::new();
|
let mut rng = RandomNumberGenerator::new();
|
||||||
let map_builder = MapBuilder::new(&mut rng);
|
let mut map_builder = MapBuilder::new(&mut rng);
|
||||||
spawn_player(&mut self.ecs, map_builder.player_start);
|
spawn_player(&mut self.ecs, map_builder.player_start);
|
||||||
spawn_amulet_of_yala(&mut self.ecs, map_builder.amulet_start);
|
//spawn_amulet_of_yala(&mut self.ecs, map_builder.amulet_start);
|
||||||
|
let exit_idx = map_builder.map.point2d_to_index(map_builder.amulet_start);
|
||||||
|
map_builder.map.tiles[exit_idx] = TileType::Exit;
|
||||||
map_builder
|
map_builder
|
||||||
.monster_spawns
|
.monster_spawns
|
||||||
.iter()
|
.iter()
|
||||||
@ -148,6 +209,7 @@ impl GameState for State {
|
|||||||
.execute(&mut self.ecs, &mut self.resources),
|
.execute(&mut self.ecs, &mut self.resources),
|
||||||
TurnState::GameOver => self.game_over(ctx),
|
TurnState::GameOver => self.game_over(ctx),
|
||||||
TurnState::Victory => self.victory(ctx),
|
TurnState::Victory => self.victory(ctx),
|
||||||
|
TurnState::NextLevel => self.advance_level(),
|
||||||
}
|
}
|
||||||
render_draw_buffer(ctx).expect("Render error");
|
render_draw_buffer(ctx).expect("Render error");
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ const NUM_TILES: usize = (SCREEN_WIDTH * SCREEN_HEIGHT) as usize;
|
|||||||
pub enum TileType {
|
pub enum TileType {
|
||||||
Wall,
|
Wall,
|
||||||
Floor,
|
Floor,
|
||||||
|
Exit,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Map {
|
pub struct Map {
|
||||||
@ -29,7 +30,9 @@ impl Map {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_enter_tile(&self, point: Point) -> bool {
|
pub fn can_enter_tile(&self, point: Point) -> bool {
|
||||||
self.in_bounds(point) && self.tiles[map_idx(point.x, point.y)] == TileType::Floor
|
self.in_bounds(point)
|
||||||
|
&& (self.tiles[map_idx(point.x, point.y)] == TileType::Floor
|
||||||
|
|| self.tiles[map_idx(point.x, point.y)] == TileType::Exit)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_idx(&self, point: Point) -> Option<usize> {
|
pub fn try_idx(&self, point: Point) -> Option<usize> {
|
||||||
|
@ -13,6 +13,7 @@ impl MapTheme for DungeonTheme {
|
|||||||
match tile_type {
|
match tile_type {
|
||||||
TileType::Floor => to_cp437('.'),
|
TileType::Floor => to_cp437('.'),
|
||||||
TileType::Wall => to_cp437('#'),
|
TileType::Wall => to_cp437('#'),
|
||||||
|
TileType::Exit => to_cp437('>'),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -28,6 +29,7 @@ impl MapTheme for ForestTheme {
|
|||||||
match tile_type {
|
match tile_type {
|
||||||
TileType::Floor => to_cp437(';'),
|
TileType::Floor => to_cp437(';'),
|
||||||
TileType::Wall => to_cp437('"'),
|
TileType::Wall => to_cp437('"'),
|
||||||
|
TileType::Exit => to_cp437('>'),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ pub use crate::prelude::*;
|
|||||||
|
|
||||||
pub fn spawn_player(ecs: &mut World, pos: Point) {
|
pub fn spawn_player(ecs: &mut World, pos: Point) {
|
||||||
ecs.push((
|
ecs.push((
|
||||||
Player,
|
Player { map_level: 0 },
|
||||||
pos,
|
pos,
|
||||||
Render {
|
Render {
|
||||||
color: ColorPair::new(WHITE, BLACK),
|
color: ColorPair::new(WHITE, BLACK),
|
||||||
|
@ -5,10 +5,11 @@ use crate::prelude::*;
|
|||||||
#[read_component(Point)]
|
#[read_component(Point)]
|
||||||
#[read_component(Player)]
|
#[read_component(Player)]
|
||||||
#[read_component(AmuletOfYala)]
|
#[read_component(AmuletOfYala)]
|
||||||
pub fn end_turn(ecs: &SubWorld, #[resource] turn_state: &mut TurnState) {
|
pub fn end_turn(ecs: &SubWorld, #[resource] turn_state: &mut TurnState, #[resource] map: &Map) {
|
||||||
let mut player_hp = <(&Health, &Point)>::query().filter(component::<Player>());
|
let mut player_hp = <(&Health, &Point)>::query().filter(component::<Player>());
|
||||||
let mut amulet = <&Point>::query().filter(component::<AmuletOfYala>());
|
let mut amulet = <&Point>::query().filter(component::<AmuletOfYala>());
|
||||||
let amulet_pos = amulet.iter(ecs).nth(0).unwrap();
|
let amulet_default = Point::new(-1, -1);
|
||||||
|
let amulet_pos = amulet.iter(ecs).nth(0).unwrap_or(&amulet_default);
|
||||||
|
|
||||||
let current_state = turn_state.clone();
|
let current_state = turn_state.clone();
|
||||||
let mut new_state = match turn_state {
|
let mut new_state = match turn_state {
|
||||||
@ -24,6 +25,10 @@ pub fn end_turn(ecs: &SubWorld, #[resource] turn_state: &mut TurnState) {
|
|||||||
if pos == amulet_pos {
|
if pos == amulet_pos {
|
||||||
new_state = TurnState::Victory;
|
new_state = TurnState::Victory;
|
||||||
}
|
}
|
||||||
|
let idx = map.point2d_to_index(*pos);
|
||||||
|
if map.tiles[idx] == TileType::Exit {
|
||||||
|
new_state = TurnState::NextLevel;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
*turn_state = new_state;
|
*turn_state = new_state;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,10 @@ pub fn hud(ecs: &SubWorld) {
|
|||||||
|
|
||||||
let mut draw_batch = DrawBatch::new();
|
let mut draw_batch = DrawBatch::new();
|
||||||
draw_batch.target(2);
|
draw_batch.target(2);
|
||||||
draw_batch.print_centered(1, "Explore the Dungeon. Cursor keys to move.");
|
draw_batch.print_centered(
|
||||||
|
1,
|
||||||
|
"Explore the Dungeon. Arrow keys to move and attack. G to get item. 1-9 to use item.",
|
||||||
|
);
|
||||||
draw_batch.bar_horizontal(
|
draw_batch.bar_horizontal(
|
||||||
Point::zero(),
|
Point::zero(),
|
||||||
SCREEN_WIDTH * 2,
|
SCREEN_WIDTH * 2,
|
||||||
@ -26,6 +29,17 @@ pub fn hud(ecs: &SubWorld) {
|
|||||||
ColorPair::new(WHITE, RED),
|
ColorPair::new(WHITE, RED),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let (player, map_level) = <(Entity, &Player)>::query()
|
||||||
|
.iter(ecs)
|
||||||
|
.find_map(|(entity, player)| Some((*entity, player.map_level)))
|
||||||
|
.unwrap();
|
||||||
|
draw_batch.print_color_right(
|
||||||
|
Point::new(SCREEN_WIDTH * 2, 1),
|
||||||
|
format!("DUNGEON LEVEL: {}", map_level + 1),
|
||||||
|
ColorPair::new(YELLOW, BLACK),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Inventory
|
||||||
let player = <(Entity, &Player)>::query()
|
let player = <(Entity, &Player)>::query()
|
||||||
.iter(ecs)
|
.iter(ecs)
|
||||||
.find_map(|(entity, _player)| Some(*entity))
|
.find_map(|(entity, _player)| Some(*entity))
|
||||||
|
@ -5,4 +5,5 @@ pub enum TurnState {
|
|||||||
MonsterTurn,
|
MonsterTurn,
|
||||||
GameOver,
|
GameOver,
|
||||||
Victory,
|
Victory,
|
||||||
|
NextLevel,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user