Move GameState to its own module

This commit is contained in:
Alex Page 2022-01-27 01:51:09 -05:00
parent 7adf5923b3
commit a8500b96d2
2 changed files with 178 additions and 164 deletions

View file

@ -7,162 +7,25 @@ pub mod resources;
mod sidebar;
mod sound;
mod sound_effects;
mod state;
pub mod systems;
pub mod vga_color;
use bracket_lib::prelude::*;
use components::{
monster::{color_for_kind, damage_for_kind, glyphs_for_kind, ticks_for_kind, MonsterKind},
monster::{color_for_kind, glyphs_for_kind, ticks_for_kind, MonsterKind},
Monster, Player, Position, Renderable,
};
use constants::*;
use map::{Map, TileType};
use resources::{Clock, LevelNumber, ShowDebugInfo, Stats};
use sound::SoundSystem;
use sound_effects::SoundEffects;
use specs::prelude::*;
use std::time::{Duration, Instant};
use systems::MonsterMotion;
use state::State;
use std::time::Instant;
use vga_color as vga;
struct State {
ecs: World,
}
fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
let entities = ecs.entities();
let mut positions = ecs.write_storage::<Position>();
let mut players = ecs.write_storage::<Player>();
let mut map = ecs.write_resource::<Map>();
let mut stats = ecs.write_resource::<Stats>();
let mut sound_system = ecs.write_resource::<SoundSystem>();
for (player, pos) in (&mut players, &mut positions).join() {
let now = Instant::now();
if now - player.last_moved > Duration::from_secs_f32(PLAYER_STEP_PERIOD) {
let destination = Point {
x: pos.x + delta_x,
y: pos.y + delta_y,
};
let mut sound_effects = ecs.fetch_mut::<SoundEffects>();
if map.in_bounds(destination) {
if map.is_solid(destination) {
sound_system.play_sound(sound_effects.blocked.clone());
} else {
if let TileType::Monster(monster) = map.get_tile_at(destination) {
if let Some(monster_component) =
ecs.read_component::<Monster>().get(monster)
{
if stats.gems > 0 {
stats.gems -= damage_for_kind(monster_component.kind);
}
let _ = entities.delete(monster);
}
}
map.set_tile_at(Point { x: pos.x, y: pos.y }, TileType::Floor);
map.set_tile_at(destination, TileType::Player);
pos.x = destination.x;
pos.y = destination.y;
let mut player_pos = ecs.write_resource::<Point>();
player_pos.x = pos.x;
player_pos.y = pos.y;
ecs.write_resource::<Clock>().force_tick();
sound_system.play_sound(sound_effects.step.clone());
}
} else {
let static_sound = sound_effects.get_new_static_effect(&sound_system);
sound_system.play_sound(static_sound);
}
player.last_moved = now;
}
}
}
fn player_input(gs: &mut State, ctx: &mut BTerm) {
// Player movement
match ctx.key {
None => {} // Nothing happened
Some(key) => match key {
VirtualKeyCode::Left | VirtualKeyCode::J => {
try_move_player(-1, 0, &mut gs.ecs);
}
VirtualKeyCode::U | VirtualKeyCode::Home => try_move_player(-1, -1, &mut gs.ecs),
VirtualKeyCode::Up | VirtualKeyCode::I => {
try_move_player(0, -1, &mut gs.ecs);
}
VirtualKeyCode::O | VirtualKeyCode::PageUp => try_move_player(1, -1, &mut gs.ecs),
VirtualKeyCode::Right | VirtualKeyCode::K => {
try_move_player(1, 0, &mut gs.ecs);
}
VirtualKeyCode::Comma | VirtualKeyCode::PageDown => try_move_player(1, 1, &mut gs.ecs),
VirtualKeyCode::Down | VirtualKeyCode::M => {
try_move_player(0, 1, &mut gs.ecs);
}
VirtualKeyCode::N | VirtualKeyCode::End => try_move_player(-1, 1, &mut gs.ecs),
VirtualKeyCode::S => {
let mut sound_system = gs.ecs.write_resource::<SoundSystem>();
let sound_effects = gs.ecs.fetch::<SoundEffects>();
sound_system.play_sound(sound_effects.pickup.clone());
}
VirtualKeyCode::D => {
let mut show_debug_info = gs.ecs.write_resource::<ShowDebugInfo>();
show_debug_info.0 = !show_debug_info.0;
}
VirtualKeyCode::Escape => {
ctx.quit();
}
_ => {
let mut sound_system = gs.ecs.write_resource::<SoundSystem>();
let sound_effects = gs.ecs.fetch::<SoundEffects>();
sound_system.play_sound(sound_effects.bad_key.clone());
}
},
}
}
impl GameState for State {
fn tick(&mut self, ctx: &mut BTerm) {
ctx.cls();
player_input(self, ctx);
self.run_systems();
let map = self.ecs.fetch::<Map>();
map.draw(ctx);
let positions = self.ecs.read_storage::<Position>();
let renderables = self.ecs.read_storage::<Renderable>();
for (pos, render) in (&positions, &renderables).join() {
ctx.set(
pos.x + MAP_X as i32,
pos.y + MAP_Y as i32,
render.fg,
render.bg,
render.glyph,
);
}
sidebar::draw(&self.ecs, ctx);
}
}
impl State {
fn run_systems(&mut self) {
let mut mm = MonsterMotion {};
mm.run_now(&self.ecs);
self.ecs.maintain();
self.ecs.write_resource::<Clock>().try_tick();
}
}
fn main() -> BError {
let context = BTermBuilder::simple(80, 25)?
.with_fps_cap(60.0)
@ -174,18 +37,18 @@ fn main() -> BError {
let sound_effects = SoundEffects::new(&ss);
ss.play_sound(sound_effects.startup.clone());
let mut gs = State { ecs: World::new() };
let mut ecs = World::new();
gs.ecs.insert(ss);
gs.ecs.insert(LevelNumber(0));
gs.ecs.insert(ShowDebugInfo(false));
gs.ecs.insert(Clock {
ecs.insert(ss);
ecs.insert(LevelNumber(0));
ecs.insert(ShowDebugInfo(false));
ecs.insert(Clock {
last_ticked: Instant::now(),
has_ticked: false,
ticks: 0,
});
gs.ecs.insert(sound_effects);
gs.ecs.insert(Stats {
ecs.insert(sound_effects);
ecs.insert(Stats {
score: 1290,
gems: 14,
whips: 7,
@ -193,10 +56,10 @@ fn main() -> BError {
keys: 0,
});
gs.ecs.register::<Position>();
gs.ecs.register::<Renderable>();
gs.ecs.register::<Monster>();
gs.ecs.register::<Player>();
ecs.register::<Position>();
ecs.register::<Renderable>();
ecs.register::<Monster>();
ecs.register::<Player>();
let mut map = Map::new();
let mut rng = RandomNumberGenerator::new();
@ -204,8 +67,7 @@ fn main() -> BError {
if rng.roll_dice(1, 16) < 2 && *tile == TileType::Floor {
let position = map.index_to_point2d(i);
let kind = MonsterKind::Slow;
gs.ecs
.create_entity()
ecs.create_entity()
.with(Position {
x: position.x,
y: position.y,
@ -224,9 +86,9 @@ fn main() -> BError {
}
{
let entities = gs.ecs.entities();
let positions = gs.ecs.read_storage::<Position>();
let monsters = gs.ecs.read_storage::<Monster>();
let entities = ecs.entities();
let positions = ecs.read_storage::<Position>();
let monsters = ecs.read_storage::<Monster>();
for (entity, _monster, pos) in (&entities, &monsters, &positions).join() {
map.set_tile_at(Point { x: pos.x, y: pos.y }, TileType::Monster(entity));
@ -235,8 +97,7 @@ fn main() -> BError {
let player_start_pos = Point { x: 40, y: 22 };
gs.ecs
.create_entity()
ecs.create_entity()
.with(Position {
x: player_start_pos.x,
y: player_start_pos.y,
@ -253,10 +114,9 @@ fn main() -> BError {
map.set_tile_at(player_start_pos, TileType::Player);
gs.ecs.insert(map);
ecs.insert(map);
gs.ecs
.insert(Point::new(player_start_pos.x, player_start_pos.y));
ecs.insert(Point::new(player_start_pos.x, player_start_pos.y));
// for i in 0..10 {
// gs.ecs
@ -298,5 +158,5 @@ fn main() -> BError {
// let _ = gs.sound_system.play_sound(effect);
main_loop(context, gs)
main_loop(context, State::new(ecs))
}

154
src/state.rs Normal file
View file

@ -0,0 +1,154 @@
use std::time::{Duration, Instant};
use crate::components::monster::damage_for_kind;
use crate::components::{Monster, Player, Position, Renderable};
use crate::map::{Map, TileType};
use crate::resources::{Clock, ShowDebugInfo, Stats};
use crate::sound::SoundSystem;
use crate::sound_effects::SoundEffects;
use crate::systems::MonsterMotion;
use crate::{constants::*, sidebar};
use bracket_lib::prelude::*;
use specs::prelude::*;
pub struct State {
ecs: World,
}
impl GameState for State {
fn tick(&mut self, ctx: &mut BTerm) {
ctx.cls();
self.handle_input(ctx);
self.run_systems();
let map = self.ecs.fetch::<Map>();
map.draw(ctx);
let positions = self.ecs.read_storage::<Position>();
let renderables = self.ecs.read_storage::<Renderable>();
for (pos, render) in (&positions, &renderables).join() {
ctx.set(
pos.x + MAP_X as i32,
pos.y + MAP_Y as i32,
render.fg,
render.bg,
render.glyph,
);
}
sidebar::draw(&self.ecs, ctx);
}
}
impl State {
pub fn new(ecs: World) -> Self {
State { ecs }
}
fn handle_input(&mut self, ctx: &mut BTerm) {
// Player movement
match ctx.key {
None => {} // Nothing happened
Some(key) => match key {
VirtualKeyCode::Left | VirtualKeyCode::J => {
self.try_move_player(-1, 0);
}
VirtualKeyCode::U | VirtualKeyCode::Home => self.try_move_player(-1, -1),
VirtualKeyCode::Up | VirtualKeyCode::I => {
self.try_move_player(0, -1);
}
VirtualKeyCode::O | VirtualKeyCode::PageUp => self.try_move_player(1, -1),
VirtualKeyCode::Right | VirtualKeyCode::K => {
self.try_move_player(1, 0);
}
VirtualKeyCode::Comma | VirtualKeyCode::PageDown => self.try_move_player(1, 1),
VirtualKeyCode::Down | VirtualKeyCode::M => {
self.try_move_player(0, 1);
}
VirtualKeyCode::N | VirtualKeyCode::End => self.try_move_player(-1, 1),
VirtualKeyCode::S => {
let mut sound_system = self.ecs.write_resource::<SoundSystem>();
let sound_effects = self.ecs.fetch::<SoundEffects>();
sound_system.play_sound(sound_effects.pickup.clone());
}
VirtualKeyCode::D => {
let mut show_debug_info = self.ecs.write_resource::<ShowDebugInfo>();
show_debug_info.0 = !show_debug_info.0;
}
VirtualKeyCode::Escape => {
ctx.quit();
}
_ => {
let mut sound_system = self.ecs.write_resource::<SoundSystem>();
let sound_effects = self.ecs.fetch::<SoundEffects>();
sound_system.play_sound(sound_effects.bad_key.clone());
}
},
}
}
fn try_move_player(&mut self, delta_x: i32, delta_y: i32) {
let entities = self.ecs.entities();
let mut positions = self.ecs.write_storage::<Position>();
let mut players = self.ecs.write_storage::<Player>();
let mut map = self.ecs.write_resource::<Map>();
let mut stats = self.ecs.write_resource::<Stats>();
let mut sound_system = self.ecs.write_resource::<SoundSystem>();
for (player, pos) in (&mut players, &mut positions).join() {
let now = Instant::now();
if now - player.last_moved > Duration::from_secs_f32(PLAYER_STEP_PERIOD) {
let destination = Point {
x: pos.x + delta_x,
y: pos.y + delta_y,
};
let mut sound_effects = self.ecs.fetch_mut::<SoundEffects>();
if map.in_bounds(destination) {
if map.is_solid(destination) {
sound_system.play_sound(sound_effects.blocked.clone());
} else {
if let TileType::Monster(monster) = map.get_tile_at(destination) {
if let Some(monster_component) =
self.ecs.read_component::<Monster>().get(monster)
{
if stats.gems > 0 {
stats.gems -= damage_for_kind(monster_component.kind);
}
let _ = entities.delete(monster);
}
}
map.set_tile_at(Point { x: pos.x, y: pos.y }, TileType::Floor);
map.set_tile_at(destination, TileType::Player);
pos.x = destination.x;
pos.y = destination.y;
let mut player_pos = self.ecs.write_resource::<Point>();
player_pos.x = pos.x;
player_pos.y = pos.y;
self.ecs.write_resource::<Clock>().force_tick();
sound_system.play_sound(sound_effects.step.clone());
}
} else {
let static_sound = sound_effects.get_new_static_effect(&sound_system);
sound_system.play_sound(static_sound);
}
player.last_moved = now;
}
}
}
fn run_systems(&mut self) {
let mut mm = MonsterMotion {};
mm.run_now(&self.ecs);
self.ecs.maintain();
self.ecs.write_resource::<Clock>().try_tick();
}
}