|
1 use std::{ |
|
2 ops::RangeInclusive |
|
3 }; |
|
4 |
1 use fpnum::*; |
5 use fpnum::*; |
2 use integral_geometry::{ |
6 use integral_geometry::{ |
3 Point, Size, GridIndex |
7 Point, Size, GridIndex |
4 }; |
8 }; |
|
9 use land2d::Land2D; |
5 |
10 |
6 type Index = u16; |
11 type Index = u16; |
7 |
12 |
8 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
13 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
9 struct PhysicsData { |
14 struct PhysicsData { |
10 position: FPPoint, |
15 position: FPPoint, |
11 velocity: FPPoint, |
16 velocity: FPPoint, |
12 } |
17 } |
13 |
18 |
14 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
19 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
15 struct CollisionData { |
20 struct CollisionData { |
16 bounds: CircleBounds |
21 bounds: CircleBounds |
17 } |
22 } |
18 |
23 |
19 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
24 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
20 struct ContactData { |
25 struct ContactData { |
46 |
51 |
47 pub struct World { |
52 pub struct World { |
48 enabled_physics: PhysicsCollection, |
53 enabled_physics: PhysicsCollection, |
49 disabled_physics: Vec<PhysicsData>, |
54 disabled_physics: Vec<PhysicsData>, |
50 |
55 |
51 collision: Vec<CollisionData>, |
56 enabled_collision: Vec<CollisionData>, |
|
57 disabled_collision: Vec<CollisionData>, |
52 grid: Grid, |
58 grid: Grid, |
53 |
59 |
54 physics_cleanup: Vec<PhysicsData>, |
60 physics_cleanup: Vec<PhysicsData>, |
55 collision_output: Vec<(Index, Index)> |
61 collision_output: Vec<(Index, Index)>, |
|
62 land_collision_output: Vec<Index> |
56 } |
63 } |
57 |
64 |
58 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
65 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
59 struct CircleBounds { |
66 struct CircleBounds { |
60 center: FPPoint, |
67 center: FPPoint, |
61 radius: FPNum |
68 radius: FPNum |
62 } |
69 } |
63 |
70 |
64 impl CircleBounds { |
71 impl CircleBounds { |
65 fn intersects(&self, other: &CircleBounds) -> bool { |
72 pub fn intersects(&self, other: &CircleBounds) -> bool { |
66 (other.center - self.center).is_in_range(self.radius + other.radius) |
73 (other.center - self.center).is_in_range(self.radius + other.radius) |
|
74 } |
|
75 |
|
76 pub fn rows(&self) -> impl Iterator<Item = (usize, RangeInclusive<usize>)> { |
|
77 let radius = self.radius.abs_round() as usize; |
|
78 let center = Point::from_fppoint(&self.center); |
|
79 (center.y as usize - radius..=center.y as usize + radius) |
|
80 .map(move |row| (row, center.x as usize - radius..=center.x as usize + radius)) |
67 } |
81 } |
68 } |
82 } |
69 |
83 |
70 fn fppoint_round(point: &FPPoint) -> Point { |
84 fn fppoint_round(point: &FPPoint) -> Point { |
71 Point::new(point.x().round() as i32, point.y().round() as i32) |
85 Point::new(point.x().round() as i32, point.y().round() as i32) |
146 } |
160 } |
147 } |
161 } |
148 } |
162 } |
149 |
163 |
150 impl World { |
164 impl World { |
151 pub fn step(&mut self, time_step: FPNum) { |
165 pub fn step(&mut self, time_step: FPNum, land: &Land2D<u32>) { |
152 for (pos, vel) in self.enabled_physics.iter_mut_pos() { |
166 for (pos, vel) in self.enabled_physics.iter_mut_pos() { |
153 *pos += *vel |
167 *pos += *vel |
154 } |
168 } |
155 |
169 |
156 self.grid.check_collisions(&mut self.collision_output); |
170 self.grid.check_collisions(&mut self.collision_output); |
|
171 } |
|
172 |
|
173 fn check_land_collisions(&mut self, land: &Land2D<u32>) { |
|
174 for collision in &self.enabled_collision { |
|
175 if collision.bounds.rows().any(|(y, r)| (&land[y][r]).iter().any(|v| *v != 0)) { |
|
176 self.land_collision_output.push(0) |
|
177 } |
|
178 } |
157 } |
179 } |
158 |
180 |
159 pub fn add_gear(&mut self, data: JoinedData) { |
181 pub fn add_gear(&mut self, data: JoinedData) { |
160 if data.physics.velocity == FPPoint::zero() { |
182 if data.physics.velocity == FPPoint::zero() { |
161 self.disabled_physics.push(data.physics); |
183 self.disabled_physics.push(data.physics); |