--- a/rust/hwphysics/src/collision.rs Thu Jul 25 21:59:20 2019 +0300
+++ b/rust/hwphysics/src/collision.rs Thu Jul 25 22:31:24 2019 +0300
@@ -147,4 +147,8 @@
fn add(&mut self, gear_id: GearId, gear_data: CollisionData) {
self.grid.insert_static(gear_id, &gear_data.bounds);
}
+
+ fn remove(&mut self, gear_id: GearId) {
+ self.grid.remove(gear_id);
+ }
}
--- a/rust/hwphysics/src/common.rs Thu Jul 25 21:59:20 2019 +0300
+++ b/rust/hwphysics/src/common.rs Thu Jul 25 22:31:24 2019 +0300
@@ -1,10 +1,40 @@
-pub type GearId = std::num::NonZeroU16;
+use std::{collections::BinaryHeap, num::NonZeroU16};
+
+pub type GearId = NonZeroU16;
pub trait GearData {}
pub trait GearDataProcessor<T: GearData> {
fn add(&mut self, gear_id: GearId, gear_data: T);
+ fn remove(&mut self, gear_id: GearId);
}
pub trait GearDataAggregator<T: GearData> {
fn find_processor(&mut self) -> &mut GearDataProcessor<T>;
}
+
+pub struct GearAllocator {
+ max_id: u16,
+ free_ids: BinaryHeap<GearId>,
+}
+
+impl GearAllocator {
+ pub fn new() -> Self {
+ Self {
+ max_id: 0,
+ free_ids: BinaryHeap::with_capacity(1024),
+ }
+ }
+
+ pub fn alloc(&mut self) -> Option<GearId> {
+ self.free_ids.pop().or_else(|| {
+ self.max_id.checked_add(1).and_then(|new_max_id| {
+ self.max_id = new_max_id;
+ NonZeroU16::new(new_max_id)
+ })
+ })
+ }
+
+ pub fn free(&mut self, gear_id: GearId) {
+ self.free_ids.push(gear_id)
+ }
+}
--- a/rust/hwphysics/src/grid.rs Thu Jul 25 21:59:20 2019 +0300
+++ b/rust/hwphysics/src/grid.rs Thu Jul 25 22:31:24 2019 +0300
@@ -71,6 +71,8 @@
bin.dynamic_entries.push(*bounds);
}
+ pub fn remove(&mut self, gear_id: GearId) {}
+
pub fn update_position(
&mut self,
gear_id: GearId,
--- a/rust/hwphysics/src/lib.rs Thu Jul 25 21:59:20 2019 +0300
+++ b/rust/hwphysics/src/lib.rs Thu Jul 25 22:31:24 2019 +0300
@@ -10,7 +10,7 @@
use crate::{
collision::{CollisionData, CollisionProcessor, ContactData},
- common::{GearData, GearDataAggregator, GearDataProcessor, GearId},
+ common::{GearAllocator, GearData, GearDataAggregator, GearDataProcessor, GearId},
physics::{PhysicsData, PhysicsProcessor},
time::TimeProcessor,
};
@@ -23,6 +23,7 @@
}
pub struct World {
+ allocator: GearAllocator,
physics: PhysicsProcessor,
collision: CollisionProcessor,
time: TimeProcessor,
@@ -44,12 +45,26 @@
impl World {
pub fn new(world_size: Size) -> Self {
Self {
+ allocator: GearAllocator::new(),
physics: PhysicsProcessor::new(),
collision: CollisionProcessor::new(world_size),
time: TimeProcessor::new(),
}
}
+ #[inline]
+ pub fn new_gear(&mut self) -> Option<GearId> {
+ self.allocator.alloc()
+ }
+
+ #[inline]
+ pub fn delete_gear(&mut self, gear_id: GearId) {
+ self.physics.remove(gear_id);
+ self.collision.remove(gear_id);
+ self.time.cancel(gear_id);
+ self.allocator.free(gear_id)
+ }
+
pub fn step(&mut self, time_step: FPNum, land: &Land2D<u32>) {
let updates = self.physics.process(time_step);
let collision = self.collision.process(land, &updates);
--- a/rust/hwphysics/src/physics.rs Thu Jul 25 21:59:20 2019 +0300
+++ b/rust/hwphysics/src/physics.rs Thu Jul 25 22:31:24 2019 +0300
@@ -35,12 +35,20 @@
self.gear_ids.len()
}
- fn push(&mut self, id: GearId, physics: PhysicsData) {
- self.gear_ids.push(id);
+ fn push(&mut self, gear_id: GearId, physics: PhysicsData) {
+ self.gear_ids.push(gear_id);
self.positions.push(physics.position);
self.velocities.push(physics.velocity);
}
+ fn remove(&mut self, gear_id: GearId) {
+ if let Some(index) = self.gear_ids.iter().position(|id| *id == gear_id) {
+ self.gear_ids.swap_remove(index);
+ self.positions.swap_remove(index);
+ self.velocities.swap_remove(index);
+ }
+ }
+
fn iter_pos_update(&mut self) -> impl Iterator<Item = (GearId, (&mut FPPoint, &FPPoint))> {
self.gear_ids
.iter()
@@ -66,6 +74,13 @@
self.gear_ids.push(gear_id);
self.positions.push(physics.position);
}
+
+ fn remove(&mut self, gear_id: GearId) {
+ if let Some(index) = self.gear_ids.iter().position(|id| *id == gear_id) {
+ self.gear_ids.swap_remove(index);
+ self.positions.swap_remove(index);
+ }
+ }
}
pub struct PhysicsProcessor {
@@ -149,4 +164,9 @@
self.dynamic_physics.push(gear_id, gear_data);
}
}
+
+ fn remove(&mut self, gear_id: GearId) {
+ self.static_physics.remove(gear_id);
+ self.dynamic_physics.remove(gear_id)
+ }
}
--- a/rust/hwphysics/src/time.rs Thu Jul 25 21:59:20 2019 +0300
+++ b/rust/hwphysics/src/time.rs Thu Jul 25 22:31:24 2019 +0300
@@ -79,6 +79,8 @@
event_id
}
+ pub fn cancel(&mut self, gear_id: GearId) {}
+
pub fn process(&mut self, time_step: FPNum) -> &OccurredEvents {
self.timeouts.clear();
self.current_time += time_step;
--- a/rust/lib-hedgewars-engine/src/world.rs Thu Jul 25 21:59:20 2019 +0300
+++ b/rust/lib-hedgewars-engine/src/world.rs Thu Jul 25 22:31:24 2019 +0300
@@ -28,7 +28,6 @@
map_renderer: Option<MapRenderer>,
gear_renderer: Option<GearRenderer>,
camera: Camera,
- last_gear_id: GearId,
}
impl World {
@@ -40,7 +39,6 @@
map_renderer: None,
gear_renderer: None,
camera: Camera::new(),
- last_gear_id: std::num::NonZeroU16::new(1).unwrap(),
}
}
@@ -128,15 +126,9 @@
}
}
- fn get_unused_gear_id(&mut self) -> GearId {
- let id = self.last_gear_id;
- self.last_gear_id = std::num::NonZeroU16::new(self.last_gear_id.get() + 1).unwrap();
- id
- }
-
fn create_gear(&mut self, position: Point) {
- let id = self.get_unused_gear_id();
if let Some(ref mut state) = self.game_state {
+ let id = state.physics.new_gear().unwrap();
let fp_position = FPPoint::new(position.x.into(), position.y.into());
state.physics.add_gear_data(
id,