author | alfadur |
Sat, 16 Oct 2021 02:39:22 +0300 | |
changeset 15822 | 4ede5e84278a |
parent 15780 | f4b563a9ac5e |
child 15828 | 44b49f255e31 |
permissions | -rw-r--r-- |
15380 | 1 |
use crate::{ |
2 |
common::{GearId, Millis}, |
|
3 |
data::GearDataManager, |
|
4 |
}; |
|
15120 | 5 |
use fpnum::*; |
6 |
||
7 |
#[derive(PartialEq, Eq, Clone, Copy, Debug)] |
|
15380 | 8 |
#[repr(transparent)] |
9 |
pub struct PositionData(pub FPPoint); |
|
15120 | 10 |
|
15380 | 11 |
#[derive(PartialEq, Eq, Clone, Copy, Debug)] |
12 |
#[repr(transparent)] |
|
13 |
pub struct VelocityData(pub FPPoint); |
|
15120 | 14 |
|
15393 | 15 |
pub struct AffectedByWind; |
16 |
||
15120 | 17 |
pub struct PositionUpdates { |
18 |
pub gear_ids: Vec<GearId>, |
|
15260 | 19 |
pub shifts: Vec<(FPPoint, FPPoint)>, |
15120 | 20 |
} |
21 |
||
22 |
impl PositionUpdates { |
|
23 |
pub fn new(capacity: usize) -> Self { |
|
24 |
Self { |
|
25 |
gear_ids: Vec::with_capacity(capacity), |
|
15260 | 26 |
shifts: Vec::with_capacity(capacity), |
15120 | 27 |
} |
28 |
} |
|
29 |
||
15260 | 30 |
pub fn push(&mut self, gear_id: GearId, old_position: &FPPoint, new_position: &FPPoint) { |
15120 | 31 |
self.gear_ids.push(gear_id); |
15260 | 32 |
self.shifts.push((*old_position, *new_position)); |
15120 | 33 |
} |
15261 | 34 |
|
35 |
pub fn iter(&self) -> impl Iterator<Item = (GearId, &FPPoint, &FPPoint)> { |
|
36 |
self.gear_ids |
|
37 |
.iter() |
|
38 |
.cloned() |
|
39 |
.zip(self.shifts.iter()) |
|
40 |
.map(|(id, (from, to))| (id, from, to)) |
|
41 |
} |
|
15266
b58f98bbc120
clear intermediate result structures between iterations
alfadur
parents:
15261
diff
changeset
|
42 |
|
b58f98bbc120
clear intermediate result structures between iterations
alfadur
parents:
15261
diff
changeset
|
43 |
pub fn clear(&mut self) { |
b58f98bbc120
clear intermediate result structures between iterations
alfadur
parents:
15261
diff
changeset
|
44 |
self.gear_ids.clear(); |
b58f98bbc120
clear intermediate result structures between iterations
alfadur
parents:
15261
diff
changeset
|
45 |
self.shifts.clear(); |
b58f98bbc120
clear intermediate result structures between iterations
alfadur
parents:
15261
diff
changeset
|
46 |
} |
15120 | 47 |
} |
48 |
||
15381 | 49 |
pub struct PhysicsProcessor { |
50 |
gravity: FPNum, |
|
15393 | 51 |
wind: FPNum, |
15381 | 52 |
position_updates: PositionUpdates, |
53 |
} |
|
54 |
||
15120 | 55 |
impl PhysicsProcessor { |
15380 | 56 |
pub fn register_components(data: &mut GearDataManager) { |
57 |
data.register::<PositionData>(); |
|
58 |
data.register::<VelocityData>(); |
|
15393 | 59 |
data.register::<AffectedByWind>(); |
15380 | 60 |
} |
61 |
||
15120 | 62 |
pub fn new() -> Self { |
15270 | 63 |
Self { |
15383
701ad89a9f2a
avoid time multiplication when not skipping ticks
alfadur
parents:
15382
diff
changeset
|
64 |
gravity: fp!(1 / 10), |
15393 | 65 |
wind: fp!(0), |
15380 | 66 |
position_updates: PositionUpdates::new(64), |
15120 | 67 |
} |
68 |
} |
|
69 |
||
15780 | 70 |
pub fn process( |
15383
701ad89a9f2a
avoid time multiplication when not skipping ticks
alfadur
parents:
15382
diff
changeset
|
71 |
&mut self, |
701ad89a9f2a
avoid time multiplication when not skipping ticks
alfadur
parents:
15382
diff
changeset
|
72 |
data: &mut GearDataManager, |
701ad89a9f2a
avoid time multiplication when not skipping ticks
alfadur
parents:
15382
diff
changeset
|
73 |
time_step: Millis, |
701ad89a9f2a
avoid time multiplication when not skipping ticks
alfadur
parents:
15382
diff
changeset
|
74 |
) -> &PositionUpdates { |
15780 | 75 |
if time_step == Millis::new(1) { |
76 |
self.process_impl::<true>(data, time_step) |
|
77 |
} else { |
|
78 |
self.process_impl::<false>(data, time_step) |
|
79 |
} |
|
80 |
} |
|
81 |
||
82 |
fn process_impl<const SINGLE_TICK: bool>( |
|
83 |
&mut self, |
|
84 |
data: &mut GearDataManager, |
|
85 |
time_step: Millis, |
|
86 |
) -> &PositionUpdates { |
|
87 |
let fp_step = if SINGLE_TICK { |
|
88 |
fp!(1) |
|
89 |
} else { |
|
90 |
time_step.to_fixed() |
|
91 |
}; |
|
15393 | 92 |
let gravity = FPPoint::unit_y() * (self.gravity * fp_step); |
93 |
let wind = FPPoint::unit_x() * (self.wind * fp_step); |
|
94 |
||
15266
b58f98bbc120
clear intermediate result structures between iterations
alfadur
parents:
15261
diff
changeset
|
95 |
self.position_updates.clear(); |
15380 | 96 |
|
15393 | 97 |
data.iter() |
98 |
.with_tags::<&AffectedByWind>() |
|
99 |
.run(|(vel,): (&mut VelocityData,)| { |
|
100 |
vel.0 += wind; |
|
101 |
}); |
|
102 |
||
15392 | 103 |
data.iter().run_id( |
15380 | 104 |
|gear_id, (pos, vel): (&mut PositionData, &mut VelocityData)| { |
15382 | 105 |
let old_pos = pos.0; |
15393 | 106 |
vel.0 += gravity; |
15780 | 107 |
pos.0 += if SINGLE_TICK { vel.0 } else { vel.0 * fp_step }; |
15382 | 108 |
self.position_updates.push(gear_id, &old_pos, &pos.0) |
15380 | 109 |
}, |
110 |
); |
|
111 |
||
15120 | 112 |
&self.position_updates |
113 |
} |
|
114 |
} |