Repaired collapse sequences
parent
07ec685c13
commit
749cac6442
|
@ -57,8 +57,27 @@ impl GameData {
|
|||
}
|
||||
|
||||
pub fn step(&mut self, t: f32) {
|
||||
// TODO: don't allocate on step, need a better
|
||||
// way to satisfy the borrow checker.
|
||||
// Same needs to be done in the `world` crate.
|
||||
let mut to_remove = Vec::new();
|
||||
for (_, s) in &mut self.ships {
|
||||
s.step(t);
|
||||
|
||||
if s.is_dead() {
|
||||
to_remove.push(s.get_handle());
|
||||
}
|
||||
}
|
||||
|
||||
// Remove dead ships
|
||||
// No fancy animation here, that's handled by the physics system.
|
||||
for i in to_remove {
|
||||
let system = self.ship_system_table.remove(&i).unwrap();
|
||||
self.system_ship_table
|
||||
.get_mut(&system)
|
||||
.unwrap()
|
||||
.retain(|x| *x != i);
|
||||
self.ships.remove(&i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,7 +93,18 @@ impl GPUState {
|
|||
|
||||
// Draw ships
|
||||
for (s, r) in state.world.iter_ship_body() {
|
||||
let data = state.data.get_ship(s.data_handle).unwrap();
|
||||
// This will be None if this ship is dead.
|
||||
// Stays around while the physics system runs a collapse sequence
|
||||
let color = match state.data.get_ship(s.data_handle) {
|
||||
None => {
|
||||
// TODO: configurable
|
||||
[0.2, 0.2, 0.2, 1.0]
|
||||
}
|
||||
Some(data) => {
|
||||
let c = state.content.get_faction(data.get_faction()).color;
|
||||
[c[0], c[1], c[2], 1.0]
|
||||
}
|
||||
};
|
||||
let ship = state.content.get_ship(s.data_handle.content_handle());
|
||||
let size = (ship.size * ship.sprite.aspect) * ship_scale;
|
||||
let p = util::rigidbody_position(r);
|
||||
|
@ -105,8 +116,6 @@ impl GPUState {
|
|||
continue;
|
||||
}
|
||||
let angle = util::rigidbody_rotation(r).angle(Vector2 { x: 0.0, y: 1.0 });
|
||||
let f = state.content.get_faction(data.get_faction()).color;
|
||||
let f = [f[0], f[1], f[2], 1.0];
|
||||
|
||||
let position = Point2 {
|
||||
x: radar_size / 2.0 + 10.0,
|
||||
|
@ -130,7 +139,7 @@ impl GPUState {
|
|||
position: position.into(),
|
||||
angle: -angle.0, // TODO: consistent angles
|
||||
size,
|
||||
color: f.into(),
|
||||
color,
|
||||
sprite_index: ship_sprite.get_index(),
|
||||
}]),
|
||||
);
|
||||
|
|
|
@ -22,7 +22,6 @@ impl GPUState {
|
|||
s: &ShipWorldObject,
|
||||
) {
|
||||
let r = state.world.get_rigid_body(s.rigid_body).unwrap();
|
||||
let ship = state.data.get_ship(s.data_handle).unwrap();
|
||||
let ship_pos = util::rigidbody_position(&r);
|
||||
let ship_rot = util::rigidbody_rotation(r);
|
||||
let ship_ang = -ship_rot.angle(Vector2 { x: 0.0, y: 1.0 }); // TODO: inconsistent angles. Fix!
|
||||
|
@ -85,8 +84,16 @@ impl GPUState {
|
|||
);
|
||||
self.vertex_buffers.object_counter += 1;
|
||||
|
||||
// This will be None if this ship is dead.
|
||||
// (physics object stays around to complete the death animation)
|
||||
// If that is the case, we're done, no flares to draw anyway!
|
||||
let ship = match state.data.get_ship(s.data_handle) {
|
||||
None => return,
|
||||
Some(s) => s,
|
||||
};
|
||||
|
||||
let flare = ship.get_outfits().get_flare_sprite(state.content);
|
||||
if s.get_controls().thrust && flare.is_some() && !ship.is_dead() {
|
||||
if s.get_controls().thrust && flare.is_some() {
|
||||
for engine_point in &ship_cnt.engines {
|
||||
self.queue.write_buffer(
|
||||
&self.global_uniform.object_buffer,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use cgmath::{Deg, EuclideanSpace, InnerSpace, Matrix2, Rad, Vector2, Zero};
|
||||
use content::{FactionHandle, ShipHandle};
|
||||
use nalgebra::{point, vector};
|
||||
|
||||
use object::GameShipHandle;
|
||||
|
@ -29,6 +30,7 @@ pub struct ShipControls {
|
|||
}
|
||||
|
||||
impl ShipControls {
|
||||
/// Create a new, empty ShipControls
|
||||
pub fn new() -> Self {
|
||||
ShipControls {
|
||||
left: false,
|
||||
|
@ -81,12 +83,11 @@ impl ShipCollapseSequence {
|
|||
fn step(
|
||||
&mut self,
|
||||
res: &mut StepResources,
|
||||
ship: GameShipHandle,
|
||||
ship_handle: ShipHandle,
|
||||
rigid_body: &mut RigidBody,
|
||||
collider: &mut Collider,
|
||||
) {
|
||||
let h = ship.content_handle();
|
||||
let ship_content = res.ct.get_ship(h);
|
||||
let ship_content = res.ct.get_ship(ship_handle);
|
||||
let ship_pos = util::rigidbody_position(rigid_body);
|
||||
let ship_rot = util::rigidbody_rotation(rigid_body);
|
||||
let ship_ang = ship_rot.angle(Vector2 { x: 1.0, y: 0.0 });
|
||||
|
@ -198,6 +199,12 @@ pub struct ShipWorldObject {
|
|||
|
||||
/// This ship's collapse sequence
|
||||
collapse_sequence: ShipCollapseSequence,
|
||||
|
||||
/// This ship's faction.
|
||||
/// This is technically redundant, faction is also stored in
|
||||
/// game data, but that's destroyed once the ship dies.
|
||||
/// We need the faction for the collapse sequence!
|
||||
faction: FactionHandle,
|
||||
}
|
||||
|
||||
impl ShipWorldObject {
|
||||
|
@ -206,6 +213,7 @@ impl ShipWorldObject {
|
|||
ct: &content::Content,
|
||||
data_handle: GameShipHandle,
|
||||
behavior: Box<dyn ShipBehavior>,
|
||||
faction: FactionHandle,
|
||||
rigid_body: RigidBodyHandle,
|
||||
collider: ColliderHandle,
|
||||
) -> Self {
|
||||
|
@ -216,6 +224,7 @@ impl ShipWorldObject {
|
|||
data_handle,
|
||||
behavior,
|
||||
controls: ShipControls::new(),
|
||||
faction,
|
||||
collapse_sequence: ShipCollapseSequence::new(ship_content.collapse.length),
|
||||
}
|
||||
}
|
||||
|
@ -225,12 +234,39 @@ impl ShipWorldObject {
|
|||
self.controls = self.behavior.update_controls(res);
|
||||
}
|
||||
|
||||
/// If this is true, remove this ship from the physics system.
|
||||
pub fn should_be_removed(&self) -> bool {
|
||||
self.collapse_sequence.is_done()
|
||||
}
|
||||
|
||||
/// Step this ship's state by t seconds
|
||||
pub fn step(
|
||||
&mut self,
|
||||
res: &mut StepResources,
|
||||
rigid_body: &mut RigidBody,
|
||||
collider: &mut Collider,
|
||||
) {
|
||||
let ship_data = res.dt.get_ship(self.data_handle);
|
||||
if ship_data.is_none() {
|
||||
// If ship data is none, it has been removed because the ship has been destroyed.
|
||||
// play collapse sequence.
|
||||
self.collapse_sequence.step(
|
||||
res,
|
||||
self.data_handle.content_handle(),
|
||||
rigid_body,
|
||||
collider,
|
||||
);
|
||||
} else {
|
||||
return self.step_live(res, rigid_body, collider);
|
||||
}
|
||||
}
|
||||
|
||||
/// Step this ship's state by t seconds (called when alive)
|
||||
fn step_live(
|
||||
&mut self,
|
||||
res: &mut StepResources,
|
||||
rigid_body: &mut RigidBody,
|
||||
collider: &mut Collider,
|
||||
) {
|
||||
let ship = res.dt.get_ship(self.data_handle).unwrap();
|
||||
let ship_content = res.ct.get_ship(self.data_handle.content_handle());
|
||||
|
@ -306,4 +342,9 @@ impl ShipWorldObject {
|
|||
pub fn get_controls(&self) -> &ShipControls {
|
||||
&self.controls
|
||||
}
|
||||
|
||||
/// Get this ship's faction
|
||||
pub fn get_faction(&self) -> FactionHandle {
|
||||
self.faction
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,15 @@ impl<'a> World {
|
|||
return Some((r, p));
|
||||
}
|
||||
|
||||
fn remove_ship(&mut self, s: &ShipWorldObject) {
|
||||
fn remove_ship(&mut self, s: ColliderHandle) {
|
||||
let s = match self.collider_ship_table.get(&s) {
|
||||
None => return,
|
||||
Some(s) => match self.ships.get(s) {
|
||||
None => return,
|
||||
Some(s) => s,
|
||||
},
|
||||
};
|
||||
|
||||
self.wrapper.rigid_body_set.remove(
|
||||
s.rigid_body,
|
||||
&mut self.wrapper.im,
|
||||
|
@ -90,13 +98,14 @@ impl<'a> World {
|
|||
let projectile = projectile.unwrap();
|
||||
let ship = ship.unwrap();
|
||||
|
||||
let ship_d = res.dt.get_ship_mut(ship.data_handle).unwrap();
|
||||
|
||||
let f = res.ct.get_faction(projectile.faction);
|
||||
let r = f.relationships.get(&ship_d.get_faction()).unwrap();
|
||||
let r = f.relationships.get(&ship.get_faction()).unwrap();
|
||||
let destory_projectile = match r {
|
||||
content::Relationship::Hostile => {
|
||||
ship_d.apply_damage(projectile.content.damage);
|
||||
// We only apply damage if the target ship is alive
|
||||
if let Some(ship_d) = res.dt.get_ship_mut(ship.data_handle) {
|
||||
ship_d.apply_damage(projectile.content.damage);
|
||||
}
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
|
@ -224,6 +233,7 @@ impl World {
|
|||
ct,
|
||||
ship.get_handle(),
|
||||
Box::new(behavior::Null::new()),
|
||||
ship.get_faction(),
|
||||
r,
|
||||
c,
|
||||
),
|
||||
|
@ -238,10 +248,10 @@ impl World {
|
|||
let mut projectiles = Vec::new();
|
||||
let mut to_remove = Vec::new();
|
||||
for (_, ship_object) in &mut self.ships {
|
||||
//if s.remove_from_world() {
|
||||
// to_remove.push(s.physics_handle);
|
||||
// continue;
|
||||
//}
|
||||
if ship_object.should_be_removed() {
|
||||
to_remove.push(ship_object.collider);
|
||||
continue;
|
||||
}
|
||||
|
||||
let rigid_body = &mut self.wrapper.rigid_body_set[ship_object.rigid_body];
|
||||
let collider = &mut self.wrapper.collider_set[ship_object.collider];
|
||||
|
@ -279,8 +289,8 @@ impl World {
|
|||
}
|
||||
|
||||
// Remove ships that don't exist
|
||||
for s in to_remove {
|
||||
self.remove_ship(s);
|
||||
for c in to_remove {
|
||||
self.remove_ship(c);
|
||||
}
|
||||
|
||||
// Create projectiles
|
||||
|
@ -367,9 +377,11 @@ impl World {
|
|||
};
|
||||
|
||||
let p = self.projectiles.get(&a);
|
||||
let s = self
|
||||
.ships
|
||||
.get_mut(self.collider_ship_table.get(&b).unwrap());
|
||||
let s = self.ships.get_mut(match self.collider_ship_table.get(&b) {
|
||||
// If none, this ship is dead.
|
||||
Some(x) => x,
|
||||
None => continue,
|
||||
});
|
||||
if p.is_none() || s.is_none() {
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue