Add Victory turn state, amulet, and victory condition

This commit is contained in:
Daniel Lynn 2021-07-09 01:35:53 -05:00
parent a44c3466e0
commit 3f9d567d8b
6 changed files with 92 additions and 16 deletions

View File

@ -38,3 +38,9 @@ pub struct WantsToAttack {
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub struct ChasingPlayer; pub struct ChasingPlayer;
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Item;
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct AmuletOfYala;

View File

@ -42,6 +42,7 @@ impl State {
let map_builder = MapBuilder::new(&mut rng); let 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);
map_builder map_builder
.rooms .rooms
@ -63,6 +64,24 @@ impl State {
} }
} }
fn reset_game_state(&mut self) {
self.ecs = World::default();
self.resources = Resources::default();
let mut rng = RandomNumberGenerator::new();
let map_builder = MapBuilder::new(&mut rng);
spawn_player(&mut self.ecs, map_builder.player_start);
spawn_amulet_of_yala(&mut self.ecs, map_builder.amulet_start);
map_builder
.rooms
.iter()
.skip(1)
.map(|r| r.center())
.for_each(|pos| spawn_monster(&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);
}
fn game_over(&mut self, ctx: &mut BTerm) { fn game_over(&mut self, ctx: &mut BTerm) {
ctx.set_active_console(2); ctx.set_active_console(2);
ctx.print_color_centered(2, RED, BLACK, "Your quest has ended."); ctx.print_color_centered(2, RED, BLACK, "Your quest has ended.");
@ -87,20 +106,29 @@ impl State {
ctx.print_color_centered(9, GREEN, BLACK, "Press 1 to play again."); ctx.print_color_centered(9, GREEN, BLACK, "Press 1 to play again.");
if let Some(VirtualKeyCode::Key1) = ctx.key { if let Some(VirtualKeyCode::Key1) = ctx.key {
self.ecs = World::default(); self.reset_game_state();
self.resources = Resources::default(); }
let mut rng = RandomNumberGenerator::new(); }
let map_builder = MapBuilder::new(&mut rng);
spawn_player(&mut self.ecs, map_builder.player_start); fn victory(&mut self, ctx: &mut BTerm) {
map_builder ctx.set_active_console(2);
.rooms ctx.print_color_centered(2, GREEN, BLACK, "You have won!");
.iter() ctx.print_color_centered(
.skip(1) 4,
.map(|r| r.center()) WHITE,
.for_each(|pos| spawn_monster(&mut self.ecs, &mut rng, pos)); BLACK,
self.resources.insert(map_builder.map); "You put on the Amulet of Yala and feel its power course through your veins.",
self.resources.insert(Camera::new(map_builder.player_start)); );
self.resources.insert(TurnState::AwaitingInput); ctx.print_color_centered(
5,
WHITE,
BLACK,
"Your town is saved, and you can return to your normal life.",
);
ctx.print_color_centered(7, GREEN, BLACK, "Press 1 to play again.");
if let Some(VirtualKeyCode::Key1) = ctx.key {
self.reset_game_state();
} }
} }
} }
@ -131,6 +159,7 @@ impl GameState for State {
.monster_systems .monster_systems
.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),
} }
render_draw_buffer(ctx).expect("Render error"); render_draw_buffer(ctx).expect("Render error");

View File

@ -6,6 +6,7 @@ pub struct MapBuilder {
pub map: Map, pub map: Map,
pub rooms: Vec<Rect>, pub rooms: Vec<Rect>,
pub player_start: Point, pub player_start: Point,
pub amulet_start: Point,
} }
impl MapBuilder { impl MapBuilder {
@ -14,11 +15,30 @@ impl MapBuilder {
map: Map::new(), map: Map::new(),
rooms: Vec::new(), rooms: Vec::new(),
player_start: Point::zero(), player_start: Point::zero(),
amulet_start: Point::zero(),
}; };
mb.fill(TileType::Wall); mb.fill(TileType::Wall);
mb.build_random_rooms(rng); mb.build_random_rooms(rng);
mb.build_corridors(rng); mb.build_corridors(rng);
mb.player_start = mb.rooms[0].center(); mb.player_start = mb.rooms[0].center();
let dijkstra_map = DijkstraMap::new(
SCREEN_WIDTH,
SCREEN_HEIGHT,
&[mb.map.point2d_to_index(mb.player_start)],
&mb.map,
1024.0,
);
const UNREACHABLE: &f32 = &f32::MAX;
mb.amulet_start = mb.map.index_to_point2d(
dijkstra_map
.map
.iter()
.enumerate()
.filter(|(_, dist)| *dist < UNREACHABLE)
.max_by(|a, b| a.1.partial_cmp(b.1).unwrap())
.unwrap()
.0,
);
mb mb
} }

View File

@ -38,6 +38,19 @@ pub fn spawn_monster(ecs: &mut World, rng: &mut RandomNumberGenerator, pos: Poin
)); ));
} }
pub fn spawn_amulet_of_yala(ecs: &mut World, pos: Point) {
ecs.push((
Item,
AmuletOfYala,
pos,
Render {
color: ColorPair::new(WHITE, BLACK),
glyph: to_cp437('|'),
},
Name("Amulet of Yala".to_string()),
));
}
fn goblin() -> (i32, String, FontCharType) { fn goblin() -> (i32, String, FontCharType) {
(1, "Goblin".to_string(), to_cp437('g')) (1, "Goblin".to_string(), to_cp437('g'))
} }

View File

@ -2,9 +2,13 @@ use crate::prelude::*;
#[system] #[system]
#[read_component(Health)] #[read_component(Health)]
#[read_component(Point)]
#[read_component(Player)] #[read_component(Player)]
#[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) {
let mut player_hp = <&Health>::query().filter(component::<Player>()); let mut player_hp = <(&Health, &Point)>::query().filter(component::<Player>());
let mut amulet = <&Point>::query().filter(component::<AmuletOfYala>());
let amulet_pos = amulet.iter(ecs).next().unwrap();
let current_state = *turn_state; let current_state = *turn_state;
let mut new_state = match current_state { let mut new_state = match current_state {
TurnState::AwaitingInput => return, TurnState::AwaitingInput => return,
@ -13,10 +17,13 @@ pub fn end_turn(ecs: &SubWorld, #[resource] turn_state: &mut TurnState) {
_ => current_state, _ => current_state,
}; };
player_hp.iter(ecs).for_each(|hp| { player_hp.iter(ecs).for_each(|(hp, pos)| {
if hp.current < 1 { if hp.current < 1 {
new_state = TurnState::GameOver; new_state = TurnState::GameOver;
} }
if pos == amulet_pos {
new_state = TurnState::Victory;
}
}); });
*turn_state = new_state; *turn_state = new_state;

View File

@ -4,4 +4,5 @@ pub enum TurnState {
PlayerTurn, PlayerTurn,
MonsterTurn, MonsterTurn,
GameOver, GameOver,
Victory,
} }