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)]
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);
spawn_player(&mut ecs, map_builder.player_start);
spawn_amulet_of_yala(&mut ecs, map_builder.amulet_start);
map_builder
.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) {
ctx.set_active_console(2);
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.");
if let Some(VirtualKeyCode::Key1) = ctx.key {
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);
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);
self.reset_game_state();
}
}
fn victory(&mut self, ctx: &mut BTerm) {
ctx.set_active_console(2);
ctx.print_color_centered(2, GREEN, BLACK, "You have won!");
ctx.print_color_centered(
4,
WHITE,
BLACK,
"You put on the Amulet of Yala and feel its power course through your veins.",
);
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
.execute(&mut self.ecs, &mut self.resources),
TurnState::GameOver => self.game_over(ctx),
TurnState::Victory => self.victory(ctx),
}
render_draw_buffer(ctx).expect("Render error");

View File

@ -6,6 +6,7 @@ pub struct MapBuilder {
pub map: Map,
pub rooms: Vec<Rect>,
pub player_start: Point,
pub amulet_start: Point,
}
impl MapBuilder {
@ -14,11 +15,30 @@ impl MapBuilder {
map: Map::new(),
rooms: Vec::new(),
player_start: Point::zero(),
amulet_start: Point::zero(),
};
mb.fill(TileType::Wall);
mb.build_random_rooms(rng);
mb.build_corridors(rng);
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
}

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) {
(1, "Goblin".to_string(), to_cp437('g'))
}

View File

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

View File

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