reimplementing gameloop with notan's App, instead of bracket-lib BTerm

This commit is contained in:
Llywelwyn 2023-09-24 00:41:02 +01:00
parent 683ab95531
commit 1299524c91
3 changed files with 213 additions and 23 deletions

View file

@ -136,7 +136,7 @@ fn setup(gfx: &mut Graphics) -> State {
gs.ecs.insert(gui::Ancestry::Human); // ancestry gs.ecs.insert(gui::Ancestry::Human); // ancestry
let player_entity = spawner::player(&mut gs.ecs, 0, 0); let player_entity = spawner::player(&mut gs.ecs, 0, 0);
gs.ecs.insert(player_entity); // Player entity gs.ecs.insert(player_entity); // Player entity
gs.ecs.insert(RunState::MapGeneration {}); // RunState gs.ecs.insert(RunState::AwaitingInput {}); // TODO: Set this back to RunState::MapGen
gs.ecs.insert(particle_system::ParticleBuilder::new()); gs.ecs.insert(particle_system::ParticleBuilder::new());
gs.ecs.insert(rex_assets::RexAssets::new()); gs.ecs.insert(rex_assets::RexAssets::new());
@ -156,6 +156,9 @@ fn draw(app: &mut App, gfx: &mut Graphics, gs: &mut State) {
let px = idx_to_px(i, &map); let px = idx_to_px(i, &map);
draw.image(gs.atlas.get("floor_grass_d").unwrap()).position(px.0, px.1); draw.image(gs.atlas.get("floor_grass_d").unwrap()).position(px.0, px.1);
} }
let ppos = gs.ecs.fetch::<Point>();
let px = idx_to_px(map.xy_idx(ppos.x, ppos.y), &map);
draw.image(gs.atlas.get("ui_heart_full").unwrap()).position(px.0, px.1);
// Render batch // Render batch
gfx.render(&draw); gfx.render(&draw);
} }
@ -167,6 +170,6 @@ fn idx_to_px(idx: usize, map: &Map) -> (f32, f32) {
) )
} }
fn update(app: &mut App, state: &mut State) { fn update(ctx: &mut App, state: &mut State) {
//state.tick(app); state.update(ctx);
} }

View file

@ -656,6 +656,50 @@ pub fn player_input(gs: &mut State, ctx: &mut App, on_overmap: bool) -> RunState
return try_move_player(0, -1, &mut gs.ecs); return try_move_player(0, -1, &mut gs.ecs);
} else if key.was_pressed(KeyCode::Numpad2) { } else if key.was_pressed(KeyCode::Numpad2) {
return try_move_player(0, 1, &mut gs.ecs); return try_move_player(0, 1, &mut gs.ecs);
} else if key.was_pressed(KeyCode::Numpad9) {
return try_move_player(1, -1, &mut gs.ecs);
} else if key.was_pressed(KeyCode::Numpad7) {
return try_move_player(-1, -1, &mut gs.ecs);
} else if key.was_pressed(KeyCode::Numpad3) {
return try_move_player(1, 1, &mut gs.ecs);
} else if key.was_pressed(KeyCode::Numpad1) {
return try_move_player(-1, 1, &mut gs.ecs);
} else if key.was_pressed(KeyCode::Period) {
if key.shift() {
let dest = try_change_level(&mut gs.ecs, false);
let curr_map_id = gs.ecs.fetch::<Map>().id;
return match dest {
// If we have no destination, do nothing.
Destination::None => RunState::AwaitingInput,
// If we want to go to the next level, go to the up-stair tile of id + 1.
Destination::NextLevel => RunState::GoToLevel(curr_map_id + 1, TileType::UpStair),
// If we want to go to the previous level, go to the down-stair tile of id - 1.
Destination::PreviousLevel =>
RunState::GoToLevel(curr_map_id - 1, TileType::DownStair),
Destination::ToLocal(id) => RunState::GoToLevel(ID_OVERMAP, TileType::ToLocal(id)),
Destination::ToOvermap(id) => RunState::GoToLevel(id, TileType::ToOvermap(id)),
};
} else {
return skip_turn(&mut gs.ecs); // (Wait a turn)
}
} else if key.was_pressed(KeyCode::Comma) {
if key.shift() {
let dest = try_change_level(&mut gs.ecs, false);
let curr_map_id = gs.ecs.fetch::<Map>().id;
return match dest {
// If we have no destination, do nothing.
Destination::None => RunState::AwaitingInput,
// If we want to go to the next level, go to the up-stair tile of id + 1.
Destination::NextLevel => RunState::GoToLevel(curr_map_id + 1, TileType::UpStair),
// If we want to go to the previous level, go to the down-stair tile of id - 1.
Destination::PreviousLevel =>
RunState::GoToLevel(curr_map_id - 1, TileType::DownStair),
Destination::ToLocal(id) => RunState::GoToLevel(ID_OVERMAP, TileType::ToLocal(id)),
Destination::ToOvermap(id) => RunState::GoToLevel(id, TileType::ToOvermap(id)),
};
} else {
return skip_turn(&mut gs.ecs); // (Wait a turn)
}
} }
return RunState::AwaitingInput; return RunState::AwaitingInput;

View file

@ -23,9 +23,8 @@ use crate::camera;
use crate::saveload_system; use crate::saveload_system;
use crate::morgue; use crate::morgue;
use crate::damage_system; use crate::damage_system;
use crate::data::prelude::*;
use notan::prelude::*;
use std::collections::HashMap; use std::collections::HashMap;
use notan::prelude::*;
#[derive(AppState)] #[derive(AppState)]
pub struct State { pub struct State {
@ -163,21 +162,162 @@ impl State {
} }
impl State { impl State {
pub fn tick(&mut self, app: &mut App) { pub fn update(&mut self, ctx: &mut App) {
let mut new_runstate;
{
let runstate = self.ecs.fetch::<RunState>();
new_runstate = *runstate;
}
// Particle ticker here
match new_runstate {
| RunState::MainMenu { .. }
| RunState::CharacterCreation { .. }
| RunState::PreRun { .. } => {}
_ => {
// Draw map and ui
}
}
match new_runstate {
RunState::PreRun => {
self.run_systems();
self.ecs.maintain();
new_runstate = RunState::AwaitingInput;
}
RunState::AwaitingInput => {
self.refresh_indexes();
effects::run_effects_queue(&mut self.ecs);
let mut can_act = false;
{
let player_entity = self.ecs.fetch::<Entity>();
let turns = self.ecs.read_storage::<TakingTurn>();
if let Some(_) = turns.get(*player_entity) {
can_act = true;
}
}
if can_act {
let on_overmap = self.ecs.fetch::<Map>().overmap;
new_runstate = player_input(self, ctx, on_overmap);
} else {
new_runstate = RunState::Ticking;
}
}
RunState::Ticking => {
while new_runstate == RunState::Ticking && particle_system::check_queue(&self.ecs) {
self.run_systems();
self.ecs.maintain();
try_spawn_interval(&mut self.ecs);
maybe_map_message(&mut self.ecs);
match *self.ecs.fetch::<RunState>() {
RunState::AwaitingInput => {
new_runstate = RunState::AwaitingInput;
}
RunState::MagicMapReveal { row, cursed } => {
new_runstate = RunState::MagicMapReveal { row: row, cursed: cursed };
}
RunState::ShowRemoveCurse => {
new_runstate = RunState::ShowRemoveCurse;
}
RunState::ShowIdentify => {
new_runstate = RunState::ShowIdentify;
}
_ => {
new_runstate = RunState::Ticking;
}
}
}
}
// RunState::Farlook
// RunState::ShowCheatMenu
// RunState::ShowInventory
// RunState::ShowDropItem
// RunState::ShowRemoveItem
// RunState::ShowTargeting
// RunState::ShowRemoveCurse
// RunState::ShowIdentify
// RunState::ActionWithDirection
// RunState::MainMenu
// RunState::CharacterCreation
RunState::SaveGame => {
saveload_system::save_game(&mut self.ecs);
new_runstate = RunState::MainMenu {
menu_selection: gui::MainMenuSelection::LoadGame,
};
}
//RunState::GameOver
RunState::GoToLevel(id, dest_tile) => {
self.goto_id(id, dest_tile);
self.mapgen_next_state = Some(RunState::PreRun);
new_runstate = RunState::MapGeneration;
}
// RunState::HelpScreen
RunState::MagicMapReveal { row, cursed } => {
let mut map = self.ecs.fetch_mut::<Map>();
// Could probably toss this into a function somewhere, and/or
// have multiple simple animations for it.
for x in 0..map.width {
let idx;
if x % 2 == 0 {
idx = map.xy_idx(x as i32, row);
} else {
idx = map.xy_idx(x as i32, (map.height as i32) - 1 - row);
}
if !cursed {
map.revealed_tiles[idx] = true;
} else {
map.revealed_tiles[idx] = false;
}
}
// Dirtify viewshed only if cursed, so our currently visible tiles aren't removed too
if cursed {
let player_entity = self.ecs.fetch::<Entity>();
let mut viewshed_components = self.ecs.write_storage::<Viewshed>();
let viewshed = viewshed_components.get_mut(*player_entity);
if let Some(viewshed) = viewshed {
viewshed.dirty = true;
}
}
if (row as usize) == (map.height as usize) - 1 {
new_runstate = RunState::Ticking;
} else {
new_runstate = RunState::MagicMapReveal { row: row + 1, cursed: cursed };
}
}
// RunState::MapGeneration
_ => {}
}
{
let mut runwriter = self.ecs.write_resource::<RunState>();
*runwriter = new_runstate;
}
damage_system::delete_the_dead(&mut self.ecs);
}
fn tick(&mut self, ctx: &mut BTerm) {
let mut new_runstate; let mut new_runstate;
{ {
let runstate = self.ecs.fetch::<RunState>(); let runstate = self.ecs.fetch::<RunState>();
new_runstate = *runstate; new_runstate = *runstate;
} }
// Clear screen // Clear screen
//particle_system::particle_ticker(&mut self.ecs, ctx); ctx.set_active_console(2);
ctx.cls();
ctx.set_active_console(1);
ctx.cls();
ctx.set_active_console(0);
ctx.cls();
particle_system::particle_ticker(&mut self.ecs, ctx);
match new_runstate { match new_runstate {
RunState::MainMenu { .. } | RunState::PreRun | RunState::CharacterCreation { .. } => {} RunState::MainMenu { .. } => {}
RunState::CharacterCreation { .. } => {}
_ => { _ => {
// Draw map and ui // Draw map and ui
//camera::render_camera(&self.ecs, ctx); camera::render_camera(&self.ecs, ctx);
//gui::draw_ui(&self.ecs, ctx); gui::draw_ui(&self.ecs, ctx);
} }
} }
@ -206,7 +346,7 @@ impl State {
} }
if can_act { if can_act {
let on_overmap = self.ecs.fetch::<Map>().overmap; let on_overmap = self.ecs.fetch::<Map>().overmap;
new_runstate = player_input(self, app, on_overmap); new_runstate = RunState::AwaitingInput; //player_input(self, ctx, on_overmap);
} else { } else {
new_runstate = RunState::Ticking; new_runstate = RunState::Ticking;
} }
@ -237,7 +377,7 @@ impl State {
} }
} }
RunState::Farlook { .. } => { RunState::Farlook { .. } => {
let result = gui::FarlookResult::Cancel; //gui::show_farlook(self, ctx); let result = gui::show_farlook(self, ctx);
match result { match result {
gui::FarlookResult::NoResponse { x, y } => { gui::FarlookResult::NoResponse { x, y } => {
new_runstate = RunState::Farlook { x, y }; new_runstate = RunState::Farlook { x, y };
@ -248,7 +388,7 @@ impl State {
} }
} }
RunState::ShowCheatMenu => { RunState::ShowCheatMenu => {
let result = gui::CheatMenuResult::Cancel; //gui::show_cheat_menu(self, ctx); let result = gui::show_cheat_menu(self, ctx);
match result { match result {
gui::CheatMenuResult::Cancel => { gui::CheatMenuResult::Cancel => {
new_runstate = RunState::AwaitingInput; new_runstate = RunState::AwaitingInput;
@ -291,7 +431,7 @@ impl State {
} }
} }
RunState::ShowInventory => { RunState::ShowInventory => {
let result = gui::ItemMenuResult::Cancel; //gui::show_inventory(self, ctx); let result = gui::show_inventory(self, ctx);
match result.0 { match result.0 {
gui::ItemMenuResult::Cancel => { gui::ItemMenuResult::Cancel => {
new_runstate = RunState::AwaitingInput; new_runstate = RunState::AwaitingInput;
@ -466,10 +606,7 @@ impl State {
} }
} }
RunState::CharacterCreation { .. } => { RunState::CharacterCreation { .. } => {
let result = gui::CharCreateResult::Selected { let result = gui::character_creation(self, ctx);
ancestry: gui::Ancestry::Human,
class: gui::Class::Fighter,
}; //gui::character_creation(self, ctx);
match result { match result {
gui::CharCreateResult::NoSelection { ancestry, class } => { gui::CharCreateResult::NoSelection { ancestry, class } => {
new_runstate = RunState::CharacterCreation { ancestry, class }; new_runstate = RunState::CharacterCreation { ancestry, class };
@ -494,7 +631,7 @@ impl State {
}; };
} }
RunState::GameOver => { RunState::GameOver => {
let result = gui::YesNoResult::No; //gui::game_over(ctx); let result = gui::game_over(ctx);
let write_to_morgue: Option<bool> = match result { let write_to_morgue: Option<bool> = match result {
gui::YesNoResult::NoSelection => None, gui::YesNoResult::NoSelection => None,
gui::YesNoResult::No => Some(false), gui::YesNoResult::No => Some(false),
@ -517,7 +654,7 @@ impl State {
new_runstate = RunState::MapGeneration; new_runstate = RunState::MapGeneration;
} }
RunState::HelpScreen => { RunState::HelpScreen => {
let result = gui::YesNoResult::Yes; //gui::show_help(ctx); let result = gui::show_help(ctx);
match result { match result {
gui::YesNoResult::Yes => { gui::YesNoResult::Yes => {
gamelog::record_event(EVENT::LookedForHelp(1)); gamelog::record_event(EVENT::LookedForHelp(1));
@ -566,9 +703,15 @@ impl State {
new_runstate = self.mapgen_next_state.unwrap(); new_runstate = self.mapgen_next_state.unwrap();
} }
if self.mapgen_history.len() != 0 { if self.mapgen_history.len() != 0 {
//camera::render_debug_map(&self.mapgen_history[self.mapgen_index], ctx); ctx.set_active_console(2);
ctx.cls();
ctx.set_active_console(1);
ctx.cls();
ctx.set_active_console(0);
ctx.cls();
camera::render_debug_map(&self.mapgen_history[self.mapgen_index], ctx);
//self.mapgen_timer += ctx.frame_time_ms; self.mapgen_timer += ctx.frame_time_ms;
if self.mapgen_timer > 300.0 { if self.mapgen_timer > 300.0 {
self.mapgen_timer = 0.0; self.mapgen_timer = 0.0;
self.mapgen_index += 1; self.mapgen_index += 1;
@ -587,6 +730,6 @@ impl State {
damage_system::delete_the_dead(&mut self.ecs); damage_system::delete_the_dead(&mut self.ecs);
//let _ = render_draw_buffer(ctx); let _ = render_draw_buffer(ctx);
} }
} }