--- a/rust/hwphysics/src/collision.rs Fri Mar 22 23:46:48 2019 +0300
+++ b/rust/hwphysics/src/collision.rs Sat Mar 23 01:07:23 2019 +0300
@@ -1,17 +1,13 @@
-use std::{
- ops::RangeInclusive
-};
+use std::ops::RangeInclusive;
use crate::{
- common::{GearId, GearData, GearDataProcessor},
+ common::{GearData, GearDataProcessor, GearId},
+ grid::Grid,
physics::PhysicsData,
- grid::Grid
};
use fpnum::*;
-use integral_geometry::{
- Point, Size, GridIndex
-};
+use integral_geometry::{GridIndex, Point, Size};
use land2d::Land2D;
pub fn fppoint_round(point: &FPPoint) -> Point {
@@ -21,7 +17,7 @@
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct CircleBounds {
pub center: FPPoint,
- pub radius: FPNum
+ pub radius: FPNum,
}
impl CircleBounds {
@@ -39,7 +35,7 @@
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct CollisionData {
- pub bounds: CircleBounds
+ pub bounds: CircleBounds,
}
impl GearData for CollisionData {}
@@ -47,21 +43,21 @@
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct ContactData {
pub elasticity: FPNum,
- pub friction: FPNum
+ pub friction: FPNum,
}
impl GearData for ContactData {}
struct EnabledCollisionsCollection {
gear_ids: Vec<GearId>,
- collisions: Vec<CollisionData>
+ collisions: Vec<CollisionData>,
}
impl EnabledCollisionsCollection {
fn new() -> Self {
Self {
gear_ids: Vec::new(),
- collisions: Vec::new()
+ collisions: Vec::new(),
}
}
@@ -84,7 +80,7 @@
pub struct DetectedCollisions {
pub pairs: Vec<(GearId, GearId)>,
- pub positions: Vec<Point>
+ pub positions: Vec<Point>,
}
impl DetectedCollisions {
@@ -106,7 +102,7 @@
Self {
grid: Grid::new(size),
enabled_collisions: EnabledCollisionsCollection::new(),
- detected_collisions: DetectedCollisions::new(0)
+ detected_collisions: DetectedCollisions::new(0),
}
}
@@ -114,8 +110,13 @@
self.grid.check_collisions(&mut self.detected_collisions);
for (gear_id, collision) in self.enabled_collisions.iter() {
- if collision.bounds.rows().any(|(y, r)| (&land[y][r]).iter().any(|v| *v != 0)) {
- self.detected_collisions.push(gear_id, 0, &collision.bounds.center)
+ if collision
+ .bounds
+ .rows()
+ .any(|(y, r)| (&land[y][r]).iter().any(|v| *v != 0))
+ {
+ self.detected_collisions
+ .push(gear_id, 0, &collision.bounds.center)
}
}
}
--- a/rust/hwphysics/src/grid.rs Fri Mar 22 23:46:48 2019 +0300
+++ b/rust/hwphysics/src/grid.rs Sat Mar 23 01:07:23 2019 +0300
@@ -1,23 +1,15 @@
use crate::{
+ collision::{fppoint_round, CircleBounds, DetectedCollisions},
common::GearId,
- collision::{
- fppoint_round,
- CircleBounds,
- DetectedCollisions
- }
};
-use integral_geometry::{
- Point,
- Size,
- GridIndex
-};
use fpnum::FPPoint;
+use integral_geometry::{GridIndex, Point, Size};
struct GridBin {
refs: Vec<GearId>,
static_entries: Vec<CircleBounds>,
- dynamic_entries: Vec<CircleBounds>
+ dynamic_entries: Vec<CircleBounds>,
}
impl GridBin {
@@ -25,7 +17,7 @@
Self {
refs: vec![],
static_entries: vec![],
- dynamic_entries: vec![]
+ dynamic_entries: vec![],
}
}
}
@@ -36,21 +28,19 @@
bins: Vec<GridBin>,
space_size: Size,
bins_count: Size,
- index: GridIndex
+ index: GridIndex,
}
impl Grid {
pub fn new(size: Size) -> Self {
assert!(size.is_power_of_two());
- let bins_count =
- Size::new(size.width / GRID_BIN_SIZE,
- size.height / GRID_BIN_SIZE);
+ let bins_count = Size::new(size.width / GRID_BIN_SIZE, size.height / GRID_BIN_SIZE);
Self {
bins: (0..bins_count.area()).map(|_| GridBin::new()).collect(),
space_size: size,
bins_count,
- index: Size::square(GRID_BIN_SIZE).to_grid_index()
+ index: Size::square(GRID_BIN_SIZE).to_grid_index(),
}
}
@@ -68,7 +58,9 @@
}
pub fn insert_dynamic(&mut self, gear_id: GearId, bounds: &CircleBounds) {
- self.lookup_bin(&bounds.center).dynamic_entries.push(*bounds)
+ self.lookup_bin(&bounds.center)
+ .dynamic_entries
+ .push(*bounds)
}
pub fn check_collisions(&self, collisions: &mut DetectedCollisions) {
@@ -88,4 +80,4 @@
}
}
}
-}
\ No newline at end of file
+}
--- a/rust/hwphysics/src/lib.rs Fri Mar 22 23:46:48 2019 +0300
+++ b/rust/hwphysics/src/lib.rs Sat Mar 23 01:07:23 2019 +0300
@@ -1,35 +1,23 @@
-mod common;
-mod physics;
+pub mod collision;
+pub mod common;
mod grid;
-mod collision;
+pub mod physics;
use fpnum::FPNum;
use integral_geometry::Size;
use land2d::Land2D;
use crate::{
- common::{
- GearId,
- GearData,
- GearDataAggregator,
- GearDataProcessor
- },
- physics::{
- PhysicsProcessor,
- PhysicsData
- },
- collision::{
- CollisionProcessor,
- CollisionData,
- ContactData
- }
+ collision::{CollisionData, CollisionProcessor, ContactData},
+ common::{GearData, GearDataAggregator, GearDataProcessor, GearId},
+ physics::{PhysicsData, PhysicsProcessor},
};
pub struct JoinedData {
gear_id: GearId,
physics: PhysicsData,
collision: CollisionData,
- contact: ContactData
+ contact: ContactData,
}
pub struct World {
@@ -44,7 +32,7 @@
&mut self.$field
}
}
- }
+ };
}
processor_map!(PhysicsData => physics);
@@ -54,7 +42,7 @@
pub fn new(world_size: Size) -> Self {
Self {
physics: PhysicsProcessor::new(),
- collision: CollisionProcessor::new(world_size)
+ collision: CollisionProcessor::new(world_size),
}
}
@@ -64,8 +52,9 @@
}
pub fn add_gear_data<T>(&mut self, gear_id: GearId, data: T)
- where T: GearData,
- Self: GearDataAggregator<T>
+ where
+ T: GearData,
+ Self: GearDataAggregator<T>,
{
self.find_processor().add(gear_id, data);
}
@@ -74,11 +63,11 @@
#[cfg(test)]
mod tests {
use crate::{
- World,
+ collision::{CircleBounds, CollisionData},
physics::PhysicsData,
- collision::{CollisionData, CircleBounds}
+ World,
};
- use fpnum::{FPNum, FPPoint, fp};
+ use fpnum::{fp, FPNum, FPPoint};
use integral_geometry::Size;
use land2d::Land2D;
@@ -89,17 +78,23 @@
let mut world = World::new(world_size);
let gear_id = 46631;
- world.add_gear_data(gear_id, PhysicsData {
- position: FPPoint::zero(),
- velocity: FPPoint::unit_y()
- });
+ world.add_gear_data(
+ gear_id,
+ PhysicsData {
+ position: FPPoint::zero(),
+ velocity: FPPoint::unit_y(),
+ },
+ );
- world.add_gear_data(gear_id, CollisionData {
- bounds: CircleBounds {
- center: FPPoint::zero(),
- radius: fp!(10)
- }
- });
+ world.add_gear_data(
+ gear_id,
+ CollisionData {
+ bounds: CircleBounds {
+ center: FPPoint::zero(),
+ radius: fp!(10),
+ },
+ },
+ );
let land = Land2D::new(Size::new(world_size.width - 2, world_size.height - 2), 0);
--- a/rust/hwphysics/src/physics.rs Fri Mar 22 23:46:48 2019 +0300
+++ b/rust/hwphysics/src/physics.rs Sat Mar 23 01:07:23 2019 +0300
@@ -1,10 +1,6 @@
-use crate::{
- common::{GearId, GearData, GearDataProcessor}
-};
+use crate::common::{GearData, GearDataProcessor, GearId};
use fpnum::*;
-use integral_geometry::{
- Point, Size, GridIndex
-};
+use integral_geometry::{GridIndex, Point, Size};
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct PhysicsData {
@@ -14,6 +10,12 @@
impl GearData for PhysicsData {}
+impl PhysicsData {
+ pub fn new(position: FPPoint, velocity: FPPoint) -> Self {
+ Self { position, velocity }
+ }
+}
+
pub struct DynamicPhysicsCollection {
gear_ids: Vec<GearId>,
positions: Vec<FPPoint>,
@@ -25,7 +27,7 @@
Self {
gear_ids: Vec::new(),
positions: Vec::new(),
- velocities: Vec::new()
+ velocities: Vec::new(),
}
}
@@ -40,22 +42,23 @@
}
fn iter_pos_update(&mut self) -> impl Iterator<Item = (GearId, (&mut FPPoint, &FPPoint))> {
- self.gear_ids.iter().cloned()
- .zip(self.positions.iter_mut()
- .zip(self.velocities.iter()))
+ self.gear_ids
+ .iter()
+ .cloned()
+ .zip(self.positions.iter_mut().zip(self.velocities.iter()))
}
}
pub struct StaticPhysicsCollection {
gear_ids: Vec<GearId>,
- positions: Vec<FPPoint>
+ positions: Vec<FPPoint>,
}
impl StaticPhysicsCollection {
fn new() -> Self {
Self {
gear_ids: Vec::new(),
- positions: Vec::new()
+ positions: Vec::new(),
}
}
@@ -70,12 +73,12 @@
static_physics: StaticPhysicsCollection,
physics_cleanup: Vec<GearId>,
- position_updates: PositionUpdates
+ position_updates: PositionUpdates,
}
pub struct PositionUpdates {
pub gear_ids: Vec<GearId>,
- pub positions: Vec<FPPoint>
+ pub positions: Vec<FPPoint>,
}
impl PositionUpdates {
@@ -98,7 +101,7 @@
dynamic_physics: DynamicPhysicsCollection::new(),
static_physics: StaticPhysicsCollection::new(),
physics_cleanup: Vec::new(),
- position_updates: PositionUpdates::new(0)
+ position_updates: PositionUpdates::new(0),
}
}
@@ -131,4 +134,4 @@
self.dynamic_physics.push(gear_id, gear_data);
}
}
-}
\ No newline at end of file
+}
--- a/rust/hwrunner/src/main.rs Fri Mar 22 23:46:48 2019 +0300
+++ b/rust/hwrunner/src/main.rs Sat Mar 23 01:07:23 2019 +0300
@@ -6,6 +6,7 @@
use hedgewars_engine::instance::EngineInstance;
use integral_geometry::Point;
+use std::time::Duration;
fn init(event_loop: &EventsLoop, size: dpi::LogicalSize) -> WindowedContext {
use glutin::{ContextBuilder, WindowBuilder};
@@ -48,6 +49,7 @@
use std::time::Instant;
let mut now = Instant::now();
+ let mut update = Instant::now();
let mut is_running = true;
while is_running {
@@ -57,6 +59,11 @@
let ms = delta.as_secs() as f64 * 1000.0 + delta.subsec_millis() as f64;
window.set_title(&format!("hwengine {:.3}ms", ms));
+ if update.elapsed() > Duration::from_millis(10) {
+ update = curr;
+ engine.world.step()
+ }
+
event_loop.poll_events(|event| match event {
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => {
--- a/rust/lib-hedgewars-engine/src/world.rs Fri Mar 22 23:46:48 2019 +0300
+++ b/rust/lib-hedgewars-engine/src/world.rs Sat Mar 23 01:07:23 2019 +0300
@@ -1,5 +1,5 @@
-use fpnum::{fp, FPNum};
-use hwphysics as hwp;
+use fpnum::{fp, FPNum, FPPoint};
+use hwphysics::{self as hwp, common::GearId};
use integral_geometry::{Point, Rect, Size};
use land2d::Land2D;
use landgen::{
@@ -27,6 +27,7 @@
game_state: Option<GameState>,
renderer: Option<MapRenderer>,
camera: Camera,
+ last_gear_id: GearId,
}
impl World {
@@ -37,6 +38,7 @@
game_state: None,
renderer: None,
camera: Camera::new(),
+ last_gear_id: GearId::default(),
}
}
@@ -120,8 +122,36 @@
}
}
+ fn get_unused_gear_id(&mut self) -> GearId {
+ let id = self.last_gear_id;
+ self.last_gear_id += 1;
+ 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 fp_position = FPPoint::new(position.x.into(), position.y.into());
+ state.physics.add_gear_data(
+ id,
+ hwp::physics::PhysicsData::new(fp_position, FPPoint::zero()),
+ )
+ }
+ }
+
pub fn step(&mut self) {
if let Some(ref mut state) = self.game_state {
+ let next = self.random_numbers_gen.next().unwrap();
+ if next % 32 == 0 {
+ let position = Point::new(
+ (self.random_numbers_gen.next().unwrap() % state.land.width() as u32) as i32,
+ 0,
+ );
+ self.create_gear(position);
+ }
+ }
+
+ if let Some(ref mut state) = self.game_state {
state.physics.step(fp!(1), &state.land);
}
}