use dreamwell_engine::physics::simulation::PhysicsWorld;
use dreamwell_engine::TopologyLayer;
pub struct GameState {
pub tick: u64,
pub paused: bool,
pub active_layer: TopologyLayer,
pub player_position: glam::Vec3,
accumulated_time: f32,
tick_rate_ms: f32,
pub physics: PhysicsWorld,
}
impl Default for GameState {
fn default() -> Self {
Self {
tick: 0,
paused: false,
active_layer: TopologyLayer::Area,
player_position: glam::Vec3::ZERO,
accumulated_time: 0.0,
tick_rate_ms: 50.0,
physics: PhysicsWorld::new(),
}
}
}
impl GameState {
pub fn update(&mut self, delta_time: f32) {
if self.paused {
return;
}
self.physics.step(delta_time);
self.accumulated_time += delta_time * 1000.0;
while self.accumulated_time >= self.tick_rate_ms {
self.accumulated_time -= self.tick_rate_ms;
self.tick += 1;
}
}
pub fn toggle_pause(&mut self) {
self.paused = !self.paused;
}
pub fn player_position(&self) -> glam::Vec3 {
self.player_position
}
pub fn active_layer(&self) -> TopologyLayer {
self.active_layer
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_state() {
let gs = GameState::default();
assert_eq!(gs.tick, 0);
assert!(!gs.paused);
assert_eq!(gs.active_layer, TopologyLayer::Area);
}
#[test]
fn tick_accumulation() {
let mut gs = GameState::default();
gs.update(0.1);
assert_eq!(gs.tick, 2);
}
#[test]
fn pause_stops_ticks() {
let mut gs = GameState::default();
gs.paused = true;
gs.update(1.0);
assert_eq!(gs.tick, 0);
}
#[test]
fn physics_steps_with_update() {
use dreamwell_engine::physics::simulation::{CollisionShape, RigidBody};
let mut gs = GameState::default();
let id = gs
.physics
.add_body(RigidBody::dynamic(1.0, CollisionShape::Sphere { radius: 0.5 }).with_position([0.0, 10.0, 0.0]));
gs.update(1.0 / 60.0);
let body = gs.physics.body(id).unwrap();
assert!(body.position[1] < 10.0, "Sphere should fall under gravity");
}
#[test]
fn physics_paused_no_step() {
use dreamwell_engine::physics::simulation::{CollisionShape, RigidBody};
let mut gs = GameState::default();
let id = gs
.physics
.add_body(RigidBody::dynamic(1.0, CollisionShape::Sphere { radius: 0.5 }).with_position([0.0, 10.0, 0.0]));
gs.paused = true;
gs.update(1.0);
let body = gs.physics.body(id).unwrap();
assert_eq!(body.position[1], 10.0, "Sphere should not move when paused");
}
}