rendering, physics, player and camera WIP
This commit is contained in:
141
src/state.rs
Normal file
141
src/state.rs
Normal file
@@ -0,0 +1,141 @@
|
||||
use std::any::{Any, TypeId};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::world::World;
|
||||
|
||||
pub trait StateAgent {}
|
||||
|
||||
pub trait State: Any
|
||||
{
|
||||
fn get_state_name(&self) -> &'static str;
|
||||
fn on_state_enter(&mut self, world: &mut World) {}
|
||||
fn on_state_exit(&mut self, world: &mut World) {}
|
||||
fn on_state_update(&mut self, world: &mut World, delta: f32) {}
|
||||
fn on_state_physics_update(&mut self, world: &mut World, delta: f32) {}
|
||||
}
|
||||
|
||||
impl dyn State
|
||||
{
|
||||
fn dyn_type_id(&self) -> std::any::TypeId
|
||||
{
|
||||
Any::type_id(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StateTransition
|
||||
{
|
||||
to_state_id: TypeId,
|
||||
condition: Box<dyn Fn(&World) -> bool>,
|
||||
}
|
||||
|
||||
pub struct StateMachine
|
||||
{
|
||||
state_transitions: HashMap<TypeId, Vec<StateTransition>>,
|
||||
current_state_id: TypeId,
|
||||
states: HashMap<TypeId, Box<dyn State>>,
|
||||
pub time_in_state: f32,
|
||||
}
|
||||
|
||||
impl StateMachine
|
||||
{
|
||||
pub fn new(enter_state: Box<dyn State>) -> Self
|
||||
{
|
||||
let state_id = enter_state.dyn_type_id();
|
||||
let mut states = HashMap::new();
|
||||
states.insert(state_id, enter_state);
|
||||
|
||||
Self {
|
||||
state_transitions: HashMap::new(),
|
||||
current_state_id: state_id,
|
||||
states,
|
||||
time_in_state: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, world: &mut World, delta: f32)
|
||||
{
|
||||
if let Some(next_state_id) = self.get_transition_state_id(world)
|
||||
{
|
||||
self.time_in_state = 0.0;
|
||||
self.transition_to(world, next_state_id);
|
||||
}
|
||||
|
||||
if let Some(current_state) = self.states.get_mut(&self.current_state_id)
|
||||
{
|
||||
current_state.on_state_update(world, delta);
|
||||
}
|
||||
|
||||
self.time_in_state += delta;
|
||||
}
|
||||
|
||||
fn get_transition_state_id(&self, world: &World) -> Option<TypeId>
|
||||
{
|
||||
if let Some(transitions) = self.state_transitions.get(&self.current_state_id)
|
||||
{
|
||||
for transition in transitions
|
||||
{
|
||||
if (transition.condition)(world)
|
||||
{
|
||||
return Some(transition.to_state_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn transition_to(&mut self, world: &mut World, new_state_id: TypeId)
|
||||
{
|
||||
if let Some(current_state) = self.states.get_mut(&self.current_state_id)
|
||||
{
|
||||
current_state.on_state_exit(world);
|
||||
}
|
||||
|
||||
self.current_state_id = new_state_id;
|
||||
|
||||
if let Some(new_state) = self.states.get_mut(&self.current_state_id)
|
||||
{
|
||||
new_state.on_state_enter(world);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_current_state(&self) -> Option<&dyn State>
|
||||
{
|
||||
self.states.get(&self.current_state_id).map(|b| b.as_ref())
|
||||
}
|
||||
|
||||
pub fn get_current_state_mut(&mut self) -> Option<&mut dyn State>
|
||||
{
|
||||
self.states
|
||||
.get_mut(&self.current_state_id)
|
||||
.map(|b| b.as_mut())
|
||||
}
|
||||
|
||||
pub fn add_state<T: State + 'static>(&mut self, state: T)
|
||||
{
|
||||
let state_id = TypeId::of::<T>();
|
||||
self.states.insert(state_id, Box::new(state));
|
||||
}
|
||||
|
||||
pub fn add_transition<TFrom: State + 'static, TTo: State + 'static>(
|
||||
&mut self,
|
||||
condition: impl Fn(&World) -> bool + 'static,
|
||||
)
|
||||
{
|
||||
let from_id = TypeId::of::<TFrom>();
|
||||
let to_id = TypeId::of::<TTo>();
|
||||
|
||||
let transitions = self.state_transitions.entry(from_id).or_default();
|
||||
transitions.push(StateTransition {
|
||||
to_state_id: to_id,
|
||||
condition: Box::new(condition),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn get_available_transitions_count(&self) -> usize
|
||||
{
|
||||
self.state_transitions
|
||||
.get(&self.current_state_id)
|
||||
.map(|transitions| transitions.len())
|
||||
.unwrap_or(0)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user