Move GameState to its own module
This commit is contained in:
parent
7adf5923b3
commit
a8500b96d2
2 changed files with 178 additions and 164 deletions
188
src/main.rs
188
src/main.rs
|
@ -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
154
src/state.rs
Normal 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();
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue