Added ship collapse sequence
parent
46313b4880
commit
27c8bf6093
2
assets
2
assets
|
@ -1 +1 @@
|
|||
Subproject commit 38fd6766762ce90bb699f98e30e46b17c4eda50c
|
||||
Subproject commit 74ddbde9e1cec1418c17844bc7336324ece88d15
|
|
@ -2,13 +2,19 @@
|
|||
sprite = "particle::explosion::small"
|
||||
lifetime = "inherit"
|
||||
inherit_velocity = "target"
|
||||
size = 3.0
|
||||
size = 8.0
|
||||
|
||||
[effect."large explosion"]
|
||||
sprite = "particle::explosion::large"
|
||||
lifetime = "inherit"
|
||||
inherit_velocity = "target"
|
||||
size = 25.0
|
||||
|
||||
[effect."huge explosion"]
|
||||
sprite = "particle::explosion::huge"
|
||||
lifetime = "inherit"
|
||||
inherit_velocity = "target"
|
||||
size = 3.0
|
||||
size = 50.0
|
||||
|
||||
[effect."blaster expire"]
|
||||
sprite = "particle::blaster"
|
||||
|
@ -25,5 +31,4 @@ size = 3.0
|
|||
# effect probabilities & variants
|
||||
# multiple particles in one effect
|
||||
# fade
|
||||
# better physics
|
||||
# document: effect vs particle
|
||||
|
|
|
@ -6,6 +6,9 @@ hull = 200
|
|||
linear_drag = 0.2
|
||||
angular_drag = 0.2
|
||||
|
||||
# TODO: disable
|
||||
# TODO: damage effects
|
||||
|
||||
space.outfit = 200
|
||||
space.engine = 50
|
||||
space.weapon = 50
|
||||
|
@ -13,6 +16,19 @@ space.weapon = 50
|
|||
engines = [{ x = 0.0, y = -1.05, size = 50.0 }]
|
||||
guns = [{ x = 0.0, y = 1 }, { x = 0.1, y = 0.80 }, { x = -0.1, y = 0.80 }]
|
||||
|
||||
|
||||
# Length of death sequence, in seconds
|
||||
collapse.length = 5.0
|
||||
|
||||
# Effects to create during the collapse sequence.
|
||||
# On average, `count` will be spawned over the sequence,
|
||||
# with a distribution of (x^2 + 0.1)
|
||||
collapse.effects = [
|
||||
{ effect = "small explosion", count = 30 },
|
||||
{ effect = "large explosion", count = 5 },
|
||||
]
|
||||
|
||||
|
||||
collision = [
|
||||
#[rustfmt:skip],
|
||||
[0.53921, 1.0000],
|
||||
|
@ -37,3 +53,44 @@ collision = [
|
|||
[-0.53921, 0.29343],
|
||||
[-0.53921, 1.0000],
|
||||
]
|
||||
|
||||
|
||||
# Scripted explosion
|
||||
[[ship."Gypsum".collapse.event]]
|
||||
time = 5.0
|
||||
effects = [
|
||||
#[rustfmt:skip],
|
||||
{ effect = "small explosion", count = 8 },
|
||||
{ effect = "large explosion", count = 5 },
|
||||
{ effect = "huge explosion", count = 1, pos = [0, 0] },
|
||||
{ effect = "huge explosion", count = 4 },
|
||||
]
|
||||
|
||||
# Scripted explosion
|
||||
[[ship."Gypsum".collapse.event]]
|
||||
time = 0.0
|
||||
effects = [
|
||||
#[rustfmt:skip],
|
||||
{ effect = "small explosion", count = 3 },
|
||||
{ effect = "large explosion", count = 1 },
|
||||
]
|
||||
|
||||
# Play a sprite reel (or change sprite)
|
||||
#[[ship."Gypsum".death.collapse.event]]
|
||||
#time = 10.0
|
||||
#reel = "gypsum post-death"
|
||||
|
||||
# Create debris
|
||||
#[[ship."Gypsum".death.collapse.event]]
|
||||
#time = "end"
|
||||
#physics = "inherit"
|
||||
# OR (relative to original rigidbody)
|
||||
#physics.position = [0, 0]
|
||||
#physics.velocity = [0, 0]
|
||||
#physics.angle = 0
|
||||
#physics.angvel = 0
|
||||
#debris = "debris"
|
||||
|
||||
# Burning, interactable, destructible debris
|
||||
#[debris]
|
||||
#effects = [{ type = "small explosion", count = 10 }]
|
||||
|
|
|
@ -21,10 +21,7 @@ use walkdir::WalkDir;
|
|||
pub use handle::{
|
||||
EffectHandle, FactionHandle, GunHandle, OutfitHandle, ShipHandle, SpriteHandle, SystemHandle,
|
||||
};
|
||||
pub use part::{
|
||||
Effect, EnginePoint, Faction, Gun, GunPoint, ImpactInheritVelocity, Outfit, OutfitSpace,
|
||||
Projectile, ProjectileCollider, Relationship, RepeatMode, Ship, Sprite, System,
|
||||
};
|
||||
pub use part::*;
|
||||
|
||||
mod syntax {
|
||||
use anyhow::{bail, Context, Result};
|
||||
|
|
|
@ -48,8 +48,10 @@ pub enum ProjectileCollider {
|
|||
Ball(BallCollider),
|
||||
}
|
||||
|
||||
/// A simple ball-shaped collider, centered at the object's position
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct BallCollider {
|
||||
/// The radius of this ball
|
||||
pub radius: f32,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,22 @@
|
|||
//! Content parts
|
||||
|
||||
pub mod effect;
|
||||
pub mod faction;
|
||||
pub mod gun;
|
||||
pub mod outfit;
|
||||
pub mod outfitspace;
|
||||
pub mod ship;
|
||||
pub mod sprite;
|
||||
pub mod system;
|
||||
pub(crate) mod effect;
|
||||
pub(crate) mod faction;
|
||||
pub(crate) mod gun;
|
||||
pub(crate) mod outfit;
|
||||
pub(crate) mod outfitspace;
|
||||
pub(crate) mod ship;
|
||||
pub(crate) mod sprite;
|
||||
pub(crate) mod system;
|
||||
|
||||
pub use effect::{Effect, ImpactInheritVelocity};
|
||||
pub use faction::{Faction, Relationship};
|
||||
pub use gun::{Gun, Projectile, ProjectileCollider};
|
||||
pub use outfit::Outfit;
|
||||
pub use outfitspace::OutfitSpace;
|
||||
pub use ship::{EnginePoint, GunPoint, Ship};
|
||||
pub use ship::{
|
||||
CollapseEffectSpawner, CollapseEvent, EffectCollapseEvent, EnginePoint, GunPoint, Ship,
|
||||
ShipCollapse,
|
||||
};
|
||||
pub use sprite::{RepeatMode, Sprite};
|
||||
pub use system::{Object, System};
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use cgmath::Point2;
|
||||
use nalgebra::{point, Point};
|
||||
|
||||
use crate::{handle::SpriteHandle, Content, ContentBuildContext, OutfitSpace};
|
||||
use crate::{handle::SpriteHandle, Content, ContentBuildContext, EffectHandle, OutfitSpace};
|
||||
|
||||
pub(crate) mod syntax {
|
||||
use crate::part::outfitspace;
|
||||
use crate::part::{effect::syntax::EffectReference, outfitspace};
|
||||
use serde::Deserialize;
|
||||
|
||||
// Raw serde syntax structs.
|
||||
|
@ -25,6 +25,7 @@ pub(crate) mod syntax {
|
|||
pub angular_drag: f32,
|
||||
pub linear_drag: f32,
|
||||
pub space: outfitspace::syntax::OutfitSpace,
|
||||
pub collapse: Option<Collapse>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
@ -39,6 +40,34 @@ pub(crate) mod syntax {
|
|||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// plural or not? document!
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Collapse {
|
||||
pub length: f32,
|
||||
pub effects: Vec<CollapseEffectSpawner>,
|
||||
pub event: Vec<CollapseEvent>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct CollapseEffectSpawner {
|
||||
pub effect: EffectReference,
|
||||
pub count: f32,
|
||||
pub pos: Option<[f32; 2]>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum CollapseEvent {
|
||||
Effect(EffectCollapseEvent),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct EffectCollapseEvent {
|
||||
pub time: f32,
|
||||
pub effects: Vec<CollapseEffectSpawner>,
|
||||
}
|
||||
}
|
||||
|
||||
// Processed data structs.
|
||||
|
@ -86,6 +115,9 @@ pub struct Ship {
|
|||
|
||||
/// Outfit space in this ship
|
||||
pub space: OutfitSpace,
|
||||
|
||||
/// Ship collapse sequence
|
||||
pub collapse: ShipCollapse,
|
||||
}
|
||||
|
||||
/// Collision shape for this ship
|
||||
|
@ -116,16 +148,60 @@ pub struct GunPoint {
|
|||
pub pos: Point2<f32>,
|
||||
}
|
||||
|
||||
/// Parameters for a ship's collapse sequence
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ShipCollapse {
|
||||
/// Collapse sequence length, in seconds
|
||||
pub length: f32,
|
||||
|
||||
/// Effects to create during collapse
|
||||
pub effects: Vec<CollapseEffectSpawner>,
|
||||
|
||||
/// Scripted events during ship collapse
|
||||
pub events: Vec<CollapseEvent>,
|
||||
}
|
||||
|
||||
/// A scripted event during a ship collapse sequence
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CollapseEffectSpawner {
|
||||
/// The effect to create
|
||||
pub effect: EffectHandle,
|
||||
|
||||
/// How many effects to create
|
||||
pub count: f32,
|
||||
|
||||
/// Where to create these effects.
|
||||
/// Position is random if None.
|
||||
pub pos: Option<Point2<f32>>,
|
||||
}
|
||||
|
||||
/// A scripted event during a ship collapse sequence
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum CollapseEvent {
|
||||
/// A scripted effect during a ship collapse sequence
|
||||
Effect(EffectCollapseEvent),
|
||||
}
|
||||
|
||||
/// A scripted effect during a ship collapse sequence
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EffectCollapseEvent {
|
||||
/// When to trigger this event
|
||||
pub time: f32,
|
||||
|
||||
/// The effect to create
|
||||
pub effects: Vec<CollapseEffectSpawner>,
|
||||
}
|
||||
|
||||
impl crate::Build for Ship {
|
||||
type InputSyntaxType = HashMap<String, syntax::Ship>;
|
||||
|
||||
fn build(
|
||||
ship: Self::InputSyntaxType,
|
||||
_build_context: &mut ContentBuildContext,
|
||||
content: &mut Content,
|
||||
build_context: &mut ContentBuildContext,
|
||||
ct: &mut Content,
|
||||
) -> Result<()> {
|
||||
for (ship_name, ship) in ship {
|
||||
let handle = match content.sprite_index.get(&ship.sprite) {
|
||||
let handle = match ct.sprite_index.get(&ship.sprite) {
|
||||
None => bail!(
|
||||
"In ship `{}`: sprite `{}` doesn't exist",
|
||||
ship_name,
|
||||
|
@ -135,10 +211,67 @@ impl crate::Build for Ship {
|
|||
};
|
||||
|
||||
let size = ship.size;
|
||||
let aspect = content.get_sprite(handle).aspect;
|
||||
let aspect = ct.get_sprite(handle).aspect;
|
||||
|
||||
content.ships.push(Self {
|
||||
let collapse = if let Some(c) = ship.collapse {
|
||||
let mut effects = Vec::new();
|
||||
for e in c.effects {
|
||||
effects.push(CollapseEffectSpawner {
|
||||
effect: e
|
||||
.effect
|
||||
.to_handle(build_context, ct)
|
||||
.with_context(|| format!("while loading ship `{}`", ship_name))?,
|
||||
count: e.count,
|
||||
pos: e.pos.map(|p| Point2 {
|
||||
x: p[0] * (size / 2.0) * aspect,
|
||||
y: p[1] * size / 2.0,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
let mut events = Vec::new();
|
||||
for e in c.event {
|
||||
match e {
|
||||
syntax::CollapseEvent::Effect(e) => {
|
||||
let mut effects = Vec::new();
|
||||
for g in e.effects {
|
||||
effects.push(CollapseEffectSpawner {
|
||||
effect: g.effect.to_handle(build_context, ct).with_context(
|
||||
|| format!("while loading ship `{}`", ship_name),
|
||||
)?,
|
||||
count: g.count,
|
||||
pos: g.pos.map(|p| Point2 {
|
||||
x: p[0] * (size / 2.0) * aspect,
|
||||
y: p[1] * size / 2.0,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
events.push(CollapseEvent::Effect(EffectCollapseEvent {
|
||||
time: e.time,
|
||||
effects,
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShipCollapse {
|
||||
length: c.length,
|
||||
effects,
|
||||
events,
|
||||
}
|
||||
} else {
|
||||
// Default collapse sequence
|
||||
ShipCollapse {
|
||||
length: 0.0,
|
||||
effects: vec![],
|
||||
events: vec![],
|
||||
}
|
||||
};
|
||||
|
||||
ct.ships.push(Self {
|
||||
aspect,
|
||||
collapse,
|
||||
name: ship_name,
|
||||
sprite: handle,
|
||||
mass: ship.mass,
|
||||
|
|
|
@ -41,6 +41,7 @@ impl Game {
|
|||
o1.add(&ct, content::OutfitHandle { index: 0 });
|
||||
o1.add_gun(&ct, content::GunHandle { index: 0 });
|
||||
o1.add_gun(&ct, content::GunHandle { index: 0 });
|
||||
o1.add_gun(&ct, content::GunHandle { index: 0 });
|
||||
|
||||
let s = object::Ship::new(
|
||||
&ct,
|
||||
|
@ -57,14 +58,14 @@ impl Game {
|
|||
// This method of specifying factions is non-deterministic,
|
||||
// but that's ok since this is for debug.
|
||||
// TODO: fix
|
||||
content::FactionHandle { index: 0 },
|
||||
content::FactionHandle { index: 1 },
|
||||
object::OutfitSet::new(ss),
|
||||
);
|
||||
let h2 = physics.add_ship(&ct, s, Point2 { x: 300.0, y: 300.0 });
|
||||
|
||||
let mut o1 = object::OutfitSet::new(ss);
|
||||
o1.add(&ct, content::OutfitHandle { index: 0 });
|
||||
o1.add_gun(&ct, content::GunHandle { index: 0 });
|
||||
//o1.add_gun(&ct, content::GunHandle { index: 0 });
|
||||
|
||||
let s = object::Ship::new(
|
||||
&ct,
|
||||
|
|
|
@ -30,8 +30,7 @@ impl Ship {
|
|||
}
|
||||
}
|
||||
|
||||
/// Has this ship been destroyed?
|
||||
pub fn is_destroyed(&self) -> bool {
|
||||
pub fn is_dead(&self) -> bool {
|
||||
self.hull <= 0.0
|
||||
}
|
||||
|
||||
|
@ -42,8 +41,10 @@ impl Ship {
|
|||
let r = f.relationships.get(&p.faction).unwrap();
|
||||
match r {
|
||||
content::Relationship::Hostile => {
|
||||
// TODO: implement death and spawning, and enable damage
|
||||
//s.hull -= p.damage;
|
||||
if self.is_dead() {
|
||||
return true;
|
||||
}
|
||||
self.hull -= p.content.damage;
|
||||
return true;
|
||||
}
|
||||
_ => return false,
|
||||
|
@ -51,6 +52,10 @@ impl Ship {
|
|||
}
|
||||
|
||||
pub fn fire_guns(&mut self) -> Vec<(Projectile, content::GunPoint)> {
|
||||
if self.is_dead() {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
self.outfits
|
||||
.iter_guns_points()
|
||||
.filter(|(g, _)| g.cooldown <= 0.0)
|
||||
|
|
|
@ -2,6 +2,7 @@ use anyhow::Result;
|
|||
use bytemuck;
|
||||
use cgmath::{Deg, EuclideanSpace, Matrix2, Matrix4, Point2, Vector3};
|
||||
use galactica_constants;
|
||||
use rand::seq::SliceRandom;
|
||||
use std::{iter, rc::Rc};
|
||||
use wgpu;
|
||||
use winit::{self, dpi::LogicalSize, window::Window};
|
||||
|
@ -624,6 +625,7 @@ impl GPUState {
|
|||
);
|
||||
|
||||
// Write all new particles to GPU buffer
|
||||
state.new_particles.shuffle(&mut rand::thread_rng());
|
||||
for i in state.new_particles.iter() {
|
||||
self.queue.write_buffer(
|
||||
&self.vertex_buffers.particle.instances,
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
use cgmath::{Deg, InnerSpace, Vector2};
|
||||
use nalgebra::vector;
|
||||
use cgmath::{Deg, EuclideanSpace, InnerSpace, Matrix2, Rad, Vector2, Zero};
|
||||
use nalgebra::{point, vector};
|
||||
|
||||
use rapier2d::dynamics::RigidBody;
|
||||
use rand::{rngs::ThreadRng, Rng};
|
||||
use rapier2d::{dynamics::RigidBody, geometry::Collider};
|
||||
|
||||
use crate::{util, ShipPhysicsHandle};
|
||||
use galactica_content as content;
|
||||
use galactica_gameobject as object;
|
||||
use galactica_render::ObjectSprite;
|
||||
use galactica_render::{ObjectSprite, ParticleBuilder};
|
||||
|
||||
pub struct ShipControls {
|
||||
pub left: bool,
|
||||
|
@ -26,6 +27,141 @@ impl ShipControls {
|
|||
}
|
||||
}
|
||||
|
||||
struct ShipCollapseSequence {
|
||||
total_length: f32,
|
||||
time_elapsed: f32,
|
||||
rng: ThreadRng,
|
||||
}
|
||||
|
||||
impl ShipCollapseSequence {
|
||||
fn new(total_length: f32) -> Self {
|
||||
Self {
|
||||
total_length: total_length,
|
||||
time_elapsed: 0.0,
|
||||
rng: rand::thread_rng(),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_done(&self) -> bool {
|
||||
self.time_elapsed >= self.total_length
|
||||
}
|
||||
|
||||
fn random_in_ship(
|
||||
&mut self,
|
||||
ship_content: &content::Ship,
|
||||
collider: &Collider,
|
||||
) -> Vector2<f32> {
|
||||
// Pick a random point inside this ship's collider
|
||||
let mut y = 0.0;
|
||||
let mut x = 0.0;
|
||||
let mut a = false;
|
||||
while !a {
|
||||
y = self.rng.gen_range(-1.0..=1.0) * ship_content.size / 2.0;
|
||||
x = self.rng.gen_range(-1.0..=1.0) * ship_content.size * ship_content.sprite.aspect
|
||||
/ 2.0;
|
||||
a = collider.shape().contains_local_point(&point![x, y]);
|
||||
}
|
||||
Vector2 { x, y }
|
||||
}
|
||||
|
||||
fn step(
|
||||
&mut self,
|
||||
ship: &object::Ship,
|
||||
ct: &content::Content,
|
||||
particles: &mut Vec<ParticleBuilder>,
|
||||
rigid_body: &mut RigidBody,
|
||||
collider: &mut Collider,
|
||||
t: f32,
|
||||
) {
|
||||
let h = ship.handle;
|
||||
let ship_content = ct.get_ship(h);
|
||||
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 });
|
||||
|
||||
// The fraction of this collapse sequence that has been played
|
||||
let frac_done = self.time_elapsed / self.total_length;
|
||||
|
||||
// Trigger collapse events
|
||||
for event in &ship_content.collapse.events {
|
||||
match event {
|
||||
content::CollapseEvent::Effect(event) => {
|
||||
if (event.time > self.time_elapsed && event.time <= self.time_elapsed + t)
|
||||
|| (event.time == 0.0 && self.time_elapsed == 0.0)
|
||||
{
|
||||
for spawner in &event.effects {
|
||||
let effect = ct.get_effect(spawner.effect);
|
||||
|
||||
for _ in 0..spawner.count as usize {
|
||||
let pos = if let Some(pos) = spawner.pos {
|
||||
pos.to_vec()
|
||||
} else {
|
||||
self.random_in_ship(ship_content, collider)
|
||||
};
|
||||
|
||||
// Position, adjusted for ship rotation
|
||||
let pos =
|
||||
Matrix2::from_angle(-ship_ang - Rad::from(Deg(90.0))) * pos;
|
||||
|
||||
particles.push(ParticleBuilder {
|
||||
sprite: effect.sprite,
|
||||
pos: ship_pos + pos,
|
||||
velocity: Vector2::zero(),
|
||||
angle: Deg::zero(),
|
||||
lifetime: effect.lifetime,
|
||||
size: effect.size,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create collapse effects
|
||||
for spawner in &ship_content.collapse.effects {
|
||||
let effect = ct.get_effect(spawner.effect);
|
||||
|
||||
// Probability of adding a particle this frame.
|
||||
// The area of this function over [0, 1] should be 1.
|
||||
let pdf = |x: f32| {
|
||||
let f = 0.2;
|
||||
let y = if x < (1.0 - f) {
|
||||
let x = x / (1.0 - f);
|
||||
(x * x + 0.2) * 1.8 - f
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
return y;
|
||||
};
|
||||
|
||||
let p_add = (t / self.total_length) * pdf(frac_done) * spawner.count;
|
||||
|
||||
if self.rng.gen_range(0.0..=1.0) <= p_add {
|
||||
let pos = if let Some(pos) = spawner.pos {
|
||||
pos.to_vec()
|
||||
} else {
|
||||
self.random_in_ship(ship_content, collider)
|
||||
};
|
||||
|
||||
// Position, adjusted for ship rotation
|
||||
let pos = Matrix2::from_angle(-ship_ang - Rad::from(Deg(90.0))) * pos;
|
||||
|
||||
particles.push(ParticleBuilder {
|
||||
sprite: effect.sprite,
|
||||
pos: ship_pos + pos,
|
||||
velocity: Vector2::zero(),
|
||||
angle: Deg::zero(),
|
||||
lifetime: effect.lifetime,
|
||||
size: effect.size,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.time_elapsed += t;
|
||||
}
|
||||
}
|
||||
|
||||
/// A ship instance in the physics system
|
||||
pub struct ShipWorldObject {
|
||||
/// This ship's physics handle
|
||||
|
@ -36,20 +172,46 @@ pub struct ShipWorldObject {
|
|||
|
||||
/// This ship's controls
|
||||
pub controls: ShipControls,
|
||||
|
||||
collapse_sequence: ShipCollapseSequence,
|
||||
}
|
||||
|
||||
impl ShipWorldObject {
|
||||
/// Make a new ship
|
||||
pub fn new(ship: object::Ship, physics_handle: ShipPhysicsHandle) -> Self {
|
||||
pub fn new(
|
||||
ct: &content::Content,
|
||||
ship: object::Ship,
|
||||
physics_handle: ShipPhysicsHandle,
|
||||
) -> Self {
|
||||
let ship_content = ct.get_ship(ship.handle);
|
||||
ShipWorldObject {
|
||||
physics_handle,
|
||||
ship,
|
||||
controls: ShipControls::new(),
|
||||
collapse_sequence: ShipCollapseSequence::new(ship_content.collapse.length),
|
||||
}
|
||||
}
|
||||
|
||||
/// Should this ship should be removed from the world?
|
||||
pub fn remove_from_world(&self) -> bool {
|
||||
return self.ship.is_dead() && self.collapse_sequence.is_done();
|
||||
}
|
||||
|
||||
/// Step this ship's state by t seconds
|
||||
pub fn step(&mut self, r: &mut RigidBody, t: f32) {
|
||||
pub fn step(
|
||||
&mut self,
|
||||
ct: &content::Content,
|
||||
particles: &mut Vec<ParticleBuilder>,
|
||||
r: &mut RigidBody,
|
||||
c: &mut Collider,
|
||||
t: f32,
|
||||
) {
|
||||
if self.ship.is_dead() {
|
||||
return self
|
||||
.collapse_sequence
|
||||
.step(&self.ship, ct, particles, r, c, t);
|
||||
}
|
||||
|
||||
let ship_rot = util::rigidbody_rotation(r);
|
||||
let engine_force = ship_rot * t;
|
||||
|
||||
|
|
|
@ -253,7 +253,8 @@ impl<'a> World {
|
|||
);
|
||||
|
||||
let h = ShipPhysicsHandle(r, c);
|
||||
self.ships.insert(c, objects::ShipWorldObject::new(ship, h));
|
||||
self.ships
|
||||
.insert(c, objects::ShipWorldObject::new(ct, ship, h));
|
||||
return h;
|
||||
}
|
||||
|
||||
|
@ -264,16 +265,19 @@ impl<'a> World {
|
|||
let mut projectiles = Vec::new();
|
||||
let mut to_remove = Vec::new();
|
||||
for (_, s) in &mut self.ships {
|
||||
if s.ship.is_destroyed() {
|
||||
to_remove.push(s.physics_handle);
|
||||
continue;
|
||||
}
|
||||
|
||||
let r = &mut self.wrapper.rigid_body_set[s.physics_handle.0];
|
||||
s.step(r, t);
|
||||
let c = &mut self.wrapper.collider_set[s.physics_handle.1];
|
||||
|
||||
// TODO: unified step info struct
|
||||
s.step(ct, particles, r, c, t);
|
||||
if s.controls.guns {
|
||||
projectiles.push((s.physics_handle, s.ship.fire_guns()));
|
||||
}
|
||||
|
||||
if s.remove_from_world() {
|
||||
to_remove.push(s.physics_handle);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
for (s, p) in projectiles {
|
||||
self.add_projectiles(s, p);
|
||||
|
|
Loading…
Reference in New Issue