dreamwell_runtime/
game_state.rs1use dreamwell_engine::physics::simulation::PhysicsWorld;
5use dreamwell_engine::TopologyLayer;
6
7pub struct GameState {
9 pub tick: u64,
10 pub paused: bool,
11 pub active_layer: TopologyLayer,
12 pub player_position: glam::Vec3,
13 accumulated_time: f32,
14 tick_rate_ms: f32,
15 pub physics: PhysicsWorld,
17}
18
19impl Default for GameState {
20 fn default() -> Self {
21 Self {
22 tick: 0,
23 paused: false,
24 active_layer: TopologyLayer::Area,
25 player_position: glam::Vec3::ZERO,
26 accumulated_time: 0.0,
27 tick_rate_ms: 50.0,
28 physics: PhysicsWorld::new(),
29 }
30 }
31}
32
33impl GameState {
34 pub fn update(&mut self, delta_time: f32) {
36 if self.paused {
37 return;
38 }
39
40 self.physics.step(delta_time);
42
43 self.accumulated_time += delta_time * 1000.0;
44 while self.accumulated_time >= self.tick_rate_ms {
45 self.accumulated_time -= self.tick_rate_ms;
46 self.tick += 1;
47 }
48 }
49
50 pub fn toggle_pause(&mut self) {
51 self.paused = !self.paused;
52 }
53
54 pub fn player_position(&self) -> glam::Vec3 {
56 self.player_position
57 }
58
59 pub fn active_layer(&self) -> TopologyLayer {
61 self.active_layer
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn default_state() {
71 let gs = GameState::default();
72 assert_eq!(gs.tick, 0);
73 assert!(!gs.paused);
74 assert_eq!(gs.active_layer, TopologyLayer::Area);
75 }
76
77 #[test]
78 fn tick_accumulation() {
79 let mut gs = GameState::default();
80 gs.update(0.1);
82 assert_eq!(gs.tick, 2);
83 }
84
85 #[test]
86 fn pause_stops_ticks() {
87 let mut gs = GameState::default();
88 gs.paused = true;
89 gs.update(1.0);
90 assert_eq!(gs.tick, 0);
91 }
92
93 #[test]
94 fn physics_steps_with_update() {
95 use dreamwell_engine::physics::simulation::{CollisionShape, RigidBody};
96 let mut gs = GameState::default();
97 let id = gs
98 .physics
99 .add_body(RigidBody::dynamic(1.0, CollisionShape::Sphere { radius: 0.5 }).with_position([0.0, 10.0, 0.0]));
100 gs.update(1.0 / 60.0);
101 let body = gs.physics.body(id).unwrap();
102 assert!(body.position[1] < 10.0, "Sphere should fall under gravity");
103 }
104
105 #[test]
106 fn physics_paused_no_step() {
107 use dreamwell_engine::physics::simulation::{CollisionShape, RigidBody};
108 let mut gs = GameState::default();
109 let id = gs
110 .physics
111 .add_body(RigidBody::dynamic(1.0, CollisionShape::Sphere { radius: 0.5 }).with_position([0.0, 10.0, 0.0]));
112 gs.paused = true;
113 gs.update(1.0);
114 let body = gs.physics.body(id).unwrap();
115 assert_eq!(body.position[1], 10.0, "Sphere should not move when paused");
116 }
117}