Dead code removed (21 methods, 4 fields, 3 constants): - Cell: MaterialId::ALL, MaterialId::from_u8 (unsafe transmute) - Grid: get_mut, clear, fill_rect, swap, dump_region, next buffer field - Entity: move_center, EntityManager::iter_mut - Player: move_dir field, entity_mut - VerletSolver: step, SubBody::add_vel, SubBody::apply_force - CellularAutomaton: tick_count - InputHandler: release_all, poll, Action::None - WindowInput: clear - GameSession: perform_action_and_step, is_recording, grid_mut - ReplayPlayer: from_recording - Material: empty() - VulkanRenderer: tick_count field - MaterialBrush: name() Warnings fixed: - Remove unused MaterialRegistry imports from renderers - Remove unused reg variables in terminal/vulkan/graphics - Remove unused water_surface in game.rs - Remove unused p/y_death in tests - Remove unused qf_slice in graphics.rs Duplication eliminated: - main.rs: run_ascii_mode + run_graphics_mode → generic run_gpu_mode<R: GpuRenderer> ~140 lines of duplicated event loop code removed - GpuRenderer trait unifies VulkanRenderer and GraphicsRenderer API Unsafe code fixed: - rand_u8: static mut + unsafe → AtomicU8 + fetch_add (thread-safe) Module cleanup: - world/mod.rs: removed all unused re-exports - physics/mod.rs: removed all unused re-exports - entity/mod.rs: removed unused Entity/EntityId re-exports Result: ~6500 → ~5964 lines, 0 non-deprecation warnings, 109 tests pass
151 lines
3.7 KiB
Rust
151 lines
3.7 KiB
Rust
use crate::world::cell::MaterialId;
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub struct SubBody {
|
|
pub x: f32,
|
|
pub y: f32,
|
|
pub old_x: f32,
|
|
pub old_y: f32,
|
|
pub ax: f32,
|
|
pub ay: f32,
|
|
pub radius: f32,
|
|
pub material: MaterialId,
|
|
pub alive: bool,
|
|
pub health: f32,
|
|
pub on_fire: bool,
|
|
pub fire_timer: u32,
|
|
}
|
|
|
|
impl SubBody {
|
|
pub fn new(x: f32, y: f32, radius: f32, material: MaterialId) -> Self {
|
|
Self {
|
|
x,
|
|
y,
|
|
old_x: x,
|
|
old_y: y,
|
|
ax: 0.0,
|
|
ay: 0.0,
|
|
radius,
|
|
material,
|
|
alive: true,
|
|
health: 100.0,
|
|
on_fire: false,
|
|
fire_timer: 0,
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn vx(&self) -> f32 {
|
|
self.x - self.old_x
|
|
}
|
|
|
|
#[inline]
|
|
pub fn vy(&self) -> f32 {
|
|
self.y - self.old_y
|
|
}
|
|
|
|
#[inline]
|
|
pub fn set_vel(&mut self, vx: f32, vy: f32) {
|
|
self.old_x = self.x - vx;
|
|
self.old_y = self.y - vy;
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub struct Constraint {
|
|
pub a: usize,
|
|
pub b: usize,
|
|
pub rest_length: f32,
|
|
pub stiffness: f32,
|
|
}
|
|
|
|
impl Constraint {
|
|
pub fn new(a: usize, b: usize, rest_length: f32, stiffness: f32) -> Self {
|
|
Self {
|
|
a,
|
|
b,
|
|
rest_length,
|
|
stiffness,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct VerletSolver {
|
|
pub gravity: f32,
|
|
pub damping: f32,
|
|
pub dt: f32,
|
|
pub max_vel: f32,
|
|
pub substeps: u32,
|
|
}
|
|
|
|
impl VerletSolver {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
gravity: 0.04,
|
|
damping: 0.97,
|
|
dt: 1.0,
|
|
max_vel: 2.0,
|
|
substeps: 8,
|
|
}
|
|
}
|
|
|
|
pub fn integrate(&self, bodies: &mut [SubBody]) {
|
|
for b in bodies.iter_mut() {
|
|
if !b.alive {
|
|
continue;
|
|
}
|
|
let mut vx = (b.x - b.old_x) * self.damping;
|
|
let mut vy = (b.y - b.old_y) * self.damping;
|
|
|
|
let v_mag = (vx * vx + vy * vy).sqrt();
|
|
if v_mag > self.max_vel {
|
|
vx = vx / v_mag * self.max_vel;
|
|
vy = vy / v_mag * self.max_vel;
|
|
}
|
|
|
|
b.old_x = b.x;
|
|
b.old_y = b.y;
|
|
b.x += vx + b.ax * self.dt * self.dt;
|
|
b.y += vy + (b.ay + self.gravity) * self.dt * self.dt;
|
|
b.ax = 0.0;
|
|
b.ay = 0.0;
|
|
}
|
|
}
|
|
|
|
pub fn solve_constraints(&self, bodies: &mut [SubBody], constraints: &[Constraint], iterations: u32) {
|
|
const MAX_CORRECTION: f32 = 0.5;
|
|
for _ in 0..iterations {
|
|
for c in constraints {
|
|
let (ba, bb) = if c.a < bodies.len() && c.b < bodies.len() {
|
|
(bodies[c.a], bodies[c.b])
|
|
} else {
|
|
continue;
|
|
};
|
|
if !ba.alive || !bb.alive {
|
|
continue;
|
|
}
|
|
let dx = bb.x - ba.x;
|
|
let dy = bb.y - ba.y;
|
|
let dist = (dx * dx + dy * dy).sqrt();
|
|
if dist < 0.0001 {
|
|
continue;
|
|
}
|
|
let diff = (dist - c.rest_length) / dist;
|
|
let mut sx = dx * 0.5 * diff * c.stiffness;
|
|
let mut sy = dy * 0.5 * diff * c.stiffness;
|
|
let corr_mag = (sx * sx + sy * sy).sqrt();
|
|
if corr_mag > MAX_CORRECTION {
|
|
let scale = MAX_CORRECTION / corr_mag;
|
|
sx *= scale;
|
|
sy *= scale;
|
|
}
|
|
bodies[c.a].x += sx;
|
|
bodies[c.a].y += sy;
|
|
bodies[c.b].x -= sx;
|
|
bodies[c.b].y -= sy;
|
|
}
|
|
}
|
|
}
|
|
}
|