|
1 pub mod collision; |
|
2 pub mod common; |
|
3 mod data; |
|
4 mod grid; |
|
5 pub mod physics; |
|
6 pub mod time; |
|
7 |
|
8 use integral_geometry::Size; |
|
9 use land2d::Land2D; |
|
10 |
|
11 use crate::{ |
|
12 collision::CollisionProcessor, |
|
13 common::{GearAllocator, GearId, Millis}, |
|
14 data::GearDataManager, |
|
15 physics::PhysicsProcessor, |
|
16 time::TimeProcessor, |
|
17 }; |
|
18 |
|
19 pub struct World { |
|
20 allocator: GearAllocator, |
|
21 data: GearDataManager, |
|
22 physics: PhysicsProcessor, |
|
23 collision: CollisionProcessor, |
|
24 time: TimeProcessor, |
|
25 } |
|
26 |
|
27 impl World { |
|
28 pub fn new(world_size: Size) -> Self { |
|
29 let mut data = GearDataManager::new(); |
|
30 PhysicsProcessor::register_components(&mut data); |
|
31 CollisionProcessor::register_components(&mut data); |
|
32 |
|
33 Self { |
|
34 data, |
|
35 allocator: GearAllocator::new(), |
|
36 physics: PhysicsProcessor::new(), |
|
37 collision: CollisionProcessor::new(world_size), |
|
38 time: TimeProcessor::new(), |
|
39 } |
|
40 } |
|
41 |
|
42 #[inline] |
|
43 pub fn new_gear(&mut self) -> Option<GearId> { |
|
44 self.allocator.alloc() |
|
45 } |
|
46 |
|
47 #[inline] |
|
48 pub fn delete_gear(&mut self, gear_id: GearId) { |
|
49 self.data.remove_all(gear_id); |
|
50 self.collision.remove(gear_id); |
|
51 self.time.cancel(gear_id); |
|
52 self.allocator.free(gear_id) |
|
53 } |
|
54 |
|
55 pub fn step(&mut self, time_step: Millis, land: &Land2D<u32>) { |
|
56 let updates = if time_step == Millis::new(1) { |
|
57 self.physics.process_single_tick(&mut self.data) |
|
58 } else { |
|
59 self.physics |
|
60 .process_multiple_ticks(&mut self.data, time_step) |
|
61 }; |
|
62 let collisions = self.collision.process(land, &updates); |
|
63 let events = self.time.process(time_step); |
|
64 } |
|
65 |
|
66 #[inline] |
|
67 pub fn add_gear_data<T: Clone + 'static>(&mut self, gear_id: GearId, data: &T) { |
|
68 self.data.add(gear_id, data); |
|
69 } |
|
70 } |
|
71 |
|
72 #[cfg(test)] |
|
73 mod tests { |
|
74 use crate::{ |
|
75 collision::{CircleBounds, CollisionData}, |
|
76 common::Millis, |
|
77 physics::{PositionData, VelocityData}, |
|
78 World, |
|
79 }; |
|
80 use fpnum::{fp, FPNum, FPPoint}; |
|
81 use integral_geometry::Size; |
|
82 use land2d::Land2D; |
|
83 |
|
84 #[test] |
|
85 fn data_flow() { |
|
86 let world_size = Size::new(2048, 2048); |
|
87 |
|
88 let mut world = World::new(world_size); |
|
89 let gear_id = world.new_gear().unwrap(); |
|
90 |
|
91 world.add_gear_data(gear_id, &PositionData(FPPoint::zero())); |
|
92 world.add_gear_data(gear_id, &VelocityData(FPPoint::unit_y())); |
|
93 |
|
94 world.add_gear_data( |
|
95 gear_id, |
|
96 &CollisionData { |
|
97 bounds: CircleBounds { |
|
98 center: FPPoint::zero(), |
|
99 radius: fp!(10), |
|
100 }, |
|
101 }, |
|
102 ); |
|
103 |
|
104 let land = Land2D::new(Size::new(world_size.width - 2, world_size.height - 2), 0); |
|
105 |
|
106 world.step(Millis::new(1), &land); |
|
107 } |
|
108 } |