rename types. still probably confusing. naming is very hard.

especially hard when some of your types are just split up to appease
the borrow checker. ugh.
This commit is contained in:
Gered 2023-02-03 18:15:46 -05:00
parent da66e10bbd
commit 24916ae4c7
5 changed files with 45 additions and 43 deletions

View file

@ -76,7 +76,7 @@ impl Game {
pub struct SimulationState; pub struct SimulationState;
impl GameState<Game> for SimulationState { impl AppState<Game> for SimulationState {
fn update(&mut self, _state: State, context: &mut Game) -> Option<StateChange<Game>> { fn update(&mut self, _state: State, context: &mut Game) -> Option<StateChange<Game>> {
if context.context.system.keyboard.is_key_up(Scancode::S) { if context.context.system.keyboard.is_key_up(Scancode::S) {
context.do_events(); context.do_events();

View file

@ -23,7 +23,7 @@ impl MainMenuState {
} }
} }
impl GameState<Game> for MainMenuState { impl AppState<Game> for MainMenuState {
fn update(&mut self, state: State, context: &mut Game) -> Option<StateChange<Game>> { fn update(&mut self, state: State, context: &mut Game) -> Option<StateChange<Game>> {
if state == State::Active { if state == State::Active {
if context.core.system.keyboard.is_key_pressed(Scancode::Escape) { if context.core.system.keyboard.is_key_pressed(Scancode::Escape) {
@ -108,7 +108,7 @@ impl GamePlayState {
} }
} }
impl GameState<Game> for GamePlayState { impl AppState<Game> for GamePlayState {
fn update(&mut self, state: State, context: &mut Game) -> Option<StateChange<Game>> { fn update(&mut self, state: State, context: &mut Game) -> Option<StateChange<Game>> {
if state == State::Active { if state == State::Active {
if self.in_menu { if self.in_menu {

View file

@ -97,7 +97,7 @@ impl DemoState {
} }
} }
impl GameState<Game> for DemoState { impl AppState<Game> for DemoState {
fn update(&mut self, state: State, context: &mut Game) -> Option<StateChange<Game>> { fn update(&mut self, state: State, context: &mut Game) -> Option<StateChange<Game>> {
if state == State::Active { if state == State::Active {
if context.core.system.keyboard.is_key_pressed(Scancode::Escape) { if context.core.system.keyboard.is_key_pressed(Scancode::Escape) {

View file

@ -7,12 +7,12 @@ use crate::events::*;
use crate::states::*; use crate::states::*;
use crate::system::*; use crate::system::*;
pub trait AppState { pub trait PrimaryState {
fn system(&self) -> &System; fn system(&self) -> &System;
fn system_mut(&mut self) -> &mut System; fn system_mut(&mut self) -> &mut System;
} }
pub trait AppStateWithFrameTiming: AppState { pub trait PrimaryStateWithFrameTiming: PrimaryState {
fn delta(&self) -> f32; fn delta(&self) -> f32;
fn set_delta(&mut self, delta: f32); fn set_delta(&mut self, delta: f32);
@ -25,7 +25,7 @@ pub trait AppStateWithFrameTiming: AppState {
} }
} }
pub trait AppStateWithEvents<EventType>: AppState { pub trait PrimaryStateWithEvents<EventType>: PrimaryState {
fn event_publisher(&mut self) -> &mut EventPublisher<EventType>; fn event_publisher(&mut self) -> &mut EventPublisher<EventType>;
} }
@ -33,7 +33,7 @@ pub trait SupportSystems {}
pub trait SupportSystemsWithEvents<EventType, ContextType>: SupportSystems pub trait SupportSystemsWithEvents<EventType, ContextType>: SupportSystems
where where
ContextType: AppStateWithEvents<EventType>, ContextType: PrimaryStateWithEvents<EventType>,
{ {
fn event_listeners(&mut self) -> &mut EventListeners<EventType, ContextType>; fn event_listeners(&mut self) -> &mut EventListeners<EventType, ContextType>;
@ -43,14 +43,14 @@ where
} }
} }
pub struct App<StateType, SupportType> { pub struct App<PrimaryType, SupportType> {
pub state: StateType, pub primary_state: PrimaryType,
pub support: SupportType, pub support_systems: SupportType,
} }
impl<StateType, SupportType> App<StateType, SupportType> { impl<PrimaryType, SupportType> App<PrimaryType, SupportType> {
pub fn new(state: StateType, support: SupportType) -> Self { pub fn new(primary_state: PrimaryType, support_systems: SupportType) -> Self {
App { state, support } App { primary_state, support_systems }
} }
} }
@ -63,33 +63,35 @@ pub enum MainLoopError {
SystemError(#[from] SystemError), SystemError(#[from] SystemError),
} }
pub fn main_loop<StateType, SupportType, State>( pub fn main_loop<PrimaryType, SupportType, State>(
mut app: App<StateType, SupportType>, primary_state: PrimaryType,
support_systems: SupportType,
initial_state: State, initial_state: State,
) -> Result<(), MainLoopError> ) -> Result<(), MainLoopError>
where where
StateType: AppStateWithFrameTiming, PrimaryType: PrimaryStateWithFrameTiming,
SupportType: SupportSystems, SupportType: SupportSystems,
State: GameState<StateType> + 'static, State: AppState<App<PrimaryType, SupportType>> + 'static,
{ {
let mut app = App::new(primary_state, support_systems);
let mut states = States::new(); let mut states = States::new();
states.push(initial_state)?; states.push(initial_state)?;
let mut is_running = true; let mut is_running = true;
let mut last_ticks = app.state.system().ticks(); let mut last_ticks = app.primary_state.system().ticks();
while is_running && !states.is_empty() { while is_running && !states.is_empty() {
app.state.system_mut().do_events_with(|event| match event { app.primary_state.system_mut().do_events_with(|event| match event {
SystemEvent::Quit => { SystemEvent::Quit => {
is_running = false; is_running = false;
} }
_ => {} _ => {}
}); });
last_ticks = app.state.update_frame_delta(last_ticks); last_ticks = app.primary_state.update_frame_delta(last_ticks);
states.update(&mut app.state)?; states.update(&mut app)?;
states.render(&mut app.state); states.render(&mut app);
app.state.system_mut().display()?; app.primary_state.system_mut().display()?;
} }
Ok(()) Ok(())

View file

@ -30,8 +30,8 @@ pub enum State {
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
pub enum StateChange<ContextType> { pub enum StateChange<ContextType> {
Push(Box<dyn GameState<ContextType>>), Push(Box<dyn AppState<ContextType>>),
Swap(Box<dyn GameState<ContextType>>), Swap(Box<dyn AppState<ContextType>>),
Pop(u32), Pop(u32),
} }
@ -46,7 +46,7 @@ impl<ContextType> std::fmt::Debug for StateChange<ContextType> {
} }
} }
pub trait GameState<ContextType> { pub trait AppState<ContextType> {
fn update(&mut self, state: State, context: &mut ContextType) -> Option<StateChange<ContextType>>; fn update(&mut self, state: State, context: &mut ContextType) -> Option<StateChange<ContextType>>;
fn render(&mut self, state: State, context: &mut ContextType); fn render(&mut self, state: State, context: &mut ContextType);
fn transition(&mut self, state: State, context: &mut ContextType) -> bool; fn transition(&mut self, state: State, context: &mut ContextType) -> bool;
@ -60,14 +60,14 @@ pub enum StateError {
#[error("Operation cannot currently be performed because there is already a pending state change.")] #[error("Operation cannot currently be performed because there is already a pending state change.")]
HasPendingStateChange, HasPendingStateChange,
#[error("Operation cannot currently be performed because the GameState's current state ({0:?}) does not allow it.")] #[error("Operation cannot currently be performed because the State's current state ({0:?}) does not allow it.")]
GameStateInvalidState(State), AppStateInvalidState(State),
} }
struct StateContainer<ContextType> { struct StateContainer<ContextType> {
current_state: State, current_state: State,
pending_state_change: Option<State>, pending_state_change: Option<State>,
state: Box<dyn GameState<ContextType>>, state: Box<dyn AppState<ContextType>>,
} }
impl<ContextType> std::fmt::Debug for StateContainer<ContextType> { impl<ContextType> std::fmt::Debug for StateContainer<ContextType> {
@ -80,7 +80,7 @@ impl<ContextType> std::fmt::Debug for StateContainer<ContextType> {
} }
impl<ContextType> StateContainer<ContextType> { impl<ContextType> StateContainer<ContextType> {
pub fn new(state: Box<dyn GameState<ContextType>>) -> Self { pub fn new(state: Box<dyn AppState<ContextType>>) -> Self {
StateContainer { StateContainer {
current_state: State::Dead, current_state: State::Dead,
pending_state_change: None, pending_state_change: None,
@ -110,7 +110,7 @@ impl<ContextType> StateContainer<ContextType> {
} }
#[inline] #[inline]
pub fn state(&mut self) -> &mut dyn GameState<ContextType> { pub fn state(&mut self) -> &mut dyn AppState<ContextType> {
self.state.deref_mut() self.state.deref_mut()
} }
@ -119,7 +119,7 @@ impl<ContextType> StateContainer<ContextType> {
self.change_state(State::TransitionOut(to), context); self.change_state(State::TransitionOut(to), context);
Ok(()) Ok(())
} else { } else {
Err(StateError::GameStateInvalidState(self.current_state)) Err(StateError::AppStateInvalidState(self.current_state))
} }
} }
@ -135,7 +135,7 @@ impl<ContextType> StateContainer<ContextType> {
Ok(()) Ok(())
}, },
_ => { _ => {
Err(StateError::GameStateInvalidState(self.current_state)) Err(StateError::AppStateInvalidState(self.current_state))
} }
} }
} }
@ -180,7 +180,7 @@ impl<ContextType> StateContainer<ContextType> {
pub struct States<ContextType> { pub struct States<ContextType> {
states: VecDeque<StateContainer<ContextType>>, states: VecDeque<StateContainer<ContextType>>,
command: Option<StateChange<ContextType>>, command: Option<StateChange<ContextType>>,
pending_state: Option<Box<dyn GameState<ContextType>>>, pending_state: Option<Box<dyn AppState<ContextType>>>,
pop_count: Option<u32>, pop_count: Option<u32>,
} }
@ -226,7 +226,7 @@ impl<ContextType> States<ContextType> {
true true
} }
fn push_boxed_state(&mut self, boxed_state: Box<dyn GameState<ContextType>>) -> Result<(), StateError> { fn push_boxed_state(&mut self, boxed_state: Box<dyn AppState<ContextType>>) -> Result<(), StateError> {
if !self.can_push_or_pop() { if !self.can_push_or_pop() {
Err(StateError::HasPendingStateChange) Err(StateError::HasPendingStateChange)
} else { } else {
@ -235,7 +235,7 @@ impl<ContextType> States<ContextType> {
} }
} }
fn swap_boxed_state(&mut self, boxed_state: Box<dyn GameState<ContextType>>) -> Result<(), StateError> { fn swap_boxed_state(&mut self, boxed_state: Box<dyn AppState<ContextType>>) -> Result<(), StateError> {
if !self.can_push_or_pop() { if !self.can_push_or_pop() {
Err(StateError::HasPendingStateChange) Err(StateError::HasPendingStateChange)
} else { } else {
@ -244,11 +244,11 @@ impl<ContextType> States<ContextType> {
} }
} }
pub fn push(&mut self, state: impl GameState<ContextType> + 'static) -> Result<(), StateError> { pub fn push(&mut self, state: impl AppState<ContextType> + 'static) -> Result<(), StateError> {
self.push_boxed_state(Box::new(state)) self.push_boxed_state(Box::new(state))
} }
pub fn swap(&mut self, state: impl GameState<ContextType> + 'static) -> Result<(), StateError> { pub fn swap(&mut self, state: impl AppState<ContextType> + 'static) -> Result<(), StateError> {
self.swap_boxed_state(Box::new(state)) self.swap_boxed_state(Box::new(state))
} }
@ -382,11 +382,11 @@ impl<ContextType> States<ContextType> {
match self.state_of_front_state() { match self.state_of_front_state() {
Some(State::Paused) => { Some(State::Paused) => {
// should never happen now. leaving here just in case ... // should never happen now. leaving here just in case ...
return Err(StateError::GameStateInvalidState(State::Paused)); return Err(StateError::AppStateInvalidState(State::Paused));
}, },
Some(State::Dead) => { Some(State::Dead) => {
// should never happen now. leaving here just in case ... // should never happen now. leaving here just in case ...
return Err(StateError::GameStateInvalidState(State::Dead)); return Err(StateError::AppStateInvalidState(State::Dead));
}, },
Some(State::TransitionIn) => { Some(State::TransitionIn) => {
let state = self.states.front_mut().unwrap(); let state = self.states.front_mut().unwrap();
@ -506,7 +506,7 @@ mod tests {
} }
} }
impl GameState<TestContext> for TestState { impl AppState<TestContext> for TestState {
fn update(&mut self, state: State, context: &mut TestContext) -> Option<StateChange<TestContext>> { fn update(&mut self, state: State, context: &mut TestContext) -> Option<StateChange<TestContext>> {
context.log(LogEntry::Update(self.id, state)); context.log(LogEntry::Update(self.id, state));
None None
@ -1284,7 +1284,7 @@ mod tests {
} }
} }
impl GameState<TestContext> for SelfPushPopState { impl AppState<TestContext> for SelfPushPopState {
fn update(&mut self, state: State, context: &mut TestContext) -> Option<StateChange<TestContext>> { fn update(&mut self, state: State, context: &mut TestContext) -> Option<StateChange<TestContext>> {
context.log(LogEntry::Update(self.id, state)); context.log(LogEntry::Update(self.id, state));
if state == State::Active { if state == State::Active {