Compare commits
2 Commits
07ec685c13
...
7854245a4b
Author | SHA1 | Date |
---|---|---|
Mark | 7854245a4b | |
Mark | 749cac6442 |
9
TODO.md
9
TODO.md
|
@ -1,4 +1,12 @@
|
||||||
## Specific Jobs
|
## Specific Jobs
|
||||||
|
- Check for handle leaks
|
||||||
|
- Rename and crtl-f comments
|
||||||
|
- gameobject and world
|
||||||
|
- behavior and personality
|
||||||
|
- ship (content) / ship (data) / ship (world)
|
||||||
|
- Fix ship controllers
|
||||||
|
- Don't allocate each frame
|
||||||
|
|
||||||
- UI: text arranger
|
- UI: text arranger
|
||||||
- Sound system
|
- Sound system
|
||||||
- Ship death debris
|
- Ship death debris
|
||||||
|
@ -90,7 +98,6 @@
|
||||||
- Clear all `// TODO:` comments littered in the source
|
- Clear all `// TODO:` comments littered in the source
|
||||||
- CLI options (debug, save location, content location, check content)
|
- CLI options (debug, save location, content location, check content)
|
||||||
- Config file and compile options, remove all those consts.
|
- Config file and compile options, remove all those consts.
|
||||||
- Sprite optimization: do we need to allocate a new `Vec` every frame? Probably not.
|
|
||||||
- Better error when run outside of directory
|
- Better error when run outside of directory
|
||||||
- Documentation site & front page
|
- Documentation site & front page
|
||||||
- Random animation delay/fps?
|
- Random animation delay/fps?
|
||||||
|
|
|
@ -57,8 +57,27 @@ impl GameData {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn step(&mut self, t: f32) {
|
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 {
|
for (_, s) in &mut self.ships {
|
||||||
s.step(t);
|
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
|
// Draw ships
|
||||||
for (s, r) in state.world.iter_ship_body() {
|
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 ship = state.content.get_ship(s.data_handle.content_handle());
|
||||||
let size = (ship.size * ship.sprite.aspect) * ship_scale;
|
let size = (ship.size * ship.sprite.aspect) * ship_scale;
|
||||||
let p = util::rigidbody_position(r);
|
let p = util::rigidbody_position(r);
|
||||||
|
@ -105,8 +116,6 @@ impl GPUState {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let angle = util::rigidbody_rotation(r).angle(Vector2 { x: 0.0, y: 1.0 });
|
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 {
|
let position = Point2 {
|
||||||
x: radar_size / 2.0 + 10.0,
|
x: radar_size / 2.0 + 10.0,
|
||||||
|
@ -130,7 +139,7 @@ impl GPUState {
|
||||||
position: position.into(),
|
position: position.into(),
|
||||||
angle: -angle.0, // TODO: consistent angles
|
angle: -angle.0, // TODO: consistent angles
|
||||||
size,
|
size,
|
||||||
color: f.into(),
|
color,
|
||||||
sprite_index: ship_sprite.get_index(),
|
sprite_index: ship_sprite.get_index(),
|
||||||
}]),
|
}]),
|
||||||
);
|
);
|
||||||
|
|
|
@ -22,7 +22,6 @@ impl GPUState {
|
||||||
s: &ShipWorldObject,
|
s: &ShipWorldObject,
|
||||||
) {
|
) {
|
||||||
let r = state.world.get_rigid_body(s.rigid_body).unwrap();
|
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_pos = util::rigidbody_position(&r);
|
||||||
let ship_rot = util::rigidbody_rotation(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!
|
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;
|
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);
|
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 {
|
for engine_point in &ship_cnt.engines {
|
||||||
self.queue.write_buffer(
|
self.queue.write_buffer(
|
||||||
&self.global_uniform.object_buffer,
|
&self.global_uniform.object_buffer,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use cgmath::{Deg, EuclideanSpace, InnerSpace, Matrix2, Rad, Vector2, Zero};
|
use cgmath::{Deg, EuclideanSpace, InnerSpace, Matrix2, Rad, Vector2, Zero};
|
||||||
|
use content::{FactionHandle, ShipHandle};
|
||||||
use nalgebra::{point, vector};
|
use nalgebra::{point, vector};
|
||||||
|
|
||||||
use object::GameShipHandle;
|
use object::GameShipHandle;
|
||||||
|
@ -29,6 +30,7 @@ pub struct ShipControls {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShipControls {
|
impl ShipControls {
|
||||||
|
/// Create a new, empty ShipControls
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
ShipControls {
|
ShipControls {
|
||||||
left: false,
|
left: false,
|
||||||
|
@ -81,12 +83,11 @@ impl ShipCollapseSequence {
|
||||||
fn step(
|
fn step(
|
||||||
&mut self,
|
&mut self,
|
||||||
res: &mut StepResources,
|
res: &mut StepResources,
|
||||||
ship: GameShipHandle,
|
ship_handle: ShipHandle,
|
||||||
rigid_body: &mut RigidBody,
|
rigid_body: &mut RigidBody,
|
||||||
collider: &mut Collider,
|
collider: &mut Collider,
|
||||||
) {
|
) {
|
||||||
let h = ship.content_handle();
|
let ship_content = res.ct.get_ship(ship_handle);
|
||||||
let ship_content = res.ct.get_ship(h);
|
|
||||||
let ship_pos = util::rigidbody_position(rigid_body);
|
let ship_pos = util::rigidbody_position(rigid_body);
|
||||||
let ship_rot = util::rigidbody_rotation(rigid_body);
|
let ship_rot = util::rigidbody_rotation(rigid_body);
|
||||||
let ship_ang = ship_rot.angle(Vector2 { x: 1.0, y: 0.0 });
|
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
|
/// This ship's collapse sequence
|
||||||
collapse_sequence: ShipCollapseSequence,
|
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 {
|
impl ShipWorldObject {
|
||||||
|
@ -206,6 +213,7 @@ impl ShipWorldObject {
|
||||||
ct: &content::Content,
|
ct: &content::Content,
|
||||||
data_handle: GameShipHandle,
|
data_handle: GameShipHandle,
|
||||||
behavior: Box<dyn ShipBehavior>,
|
behavior: Box<dyn ShipBehavior>,
|
||||||
|
faction: FactionHandle,
|
||||||
rigid_body: RigidBodyHandle,
|
rigid_body: RigidBodyHandle,
|
||||||
collider: ColliderHandle,
|
collider: ColliderHandle,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -216,6 +224,7 @@ impl ShipWorldObject {
|
||||||
data_handle,
|
data_handle,
|
||||||
behavior,
|
behavior,
|
||||||
controls: ShipControls::new(),
|
controls: ShipControls::new(),
|
||||||
|
faction,
|
||||||
collapse_sequence: ShipCollapseSequence::new(ship_content.collapse.length),
|
collapse_sequence: ShipCollapseSequence::new(ship_content.collapse.length),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,12 +234,39 @@ impl ShipWorldObject {
|
||||||
self.controls = self.behavior.update_controls(res);
|
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
|
/// Step this ship's state by t seconds
|
||||||
pub fn step(
|
pub fn step(
|
||||||
&mut self,
|
&mut self,
|
||||||
res: &mut StepResources,
|
res: &mut StepResources,
|
||||||
rigid_body: &mut RigidBody,
|
rigid_body: &mut RigidBody,
|
||||||
collider: &mut Collider,
|
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 = res.dt.get_ship(self.data_handle).unwrap();
|
||||||
let ship_content = res.ct.get_ship(self.data_handle.content_handle());
|
let ship_content = res.ct.get_ship(self.data_handle.content_handle());
|
||||||
|
@ -306,4 +342,9 @@ impl ShipWorldObject {
|
||||||
pub fn get_controls(&self) -> &ShipControls {
|
pub fn get_controls(&self) -> &ShipControls {
|
||||||
&self.controls
|
&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));
|
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(
|
self.wrapper.rigid_body_set.remove(
|
||||||
s.rigid_body,
|
s.rigid_body,
|
||||||
&mut self.wrapper.im,
|
&mut self.wrapper.im,
|
||||||
|
@ -90,13 +98,14 @@ impl<'a> World {
|
||||||
let projectile = projectile.unwrap();
|
let projectile = projectile.unwrap();
|
||||||
let ship = ship.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 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 {
|
let destory_projectile = match r {
|
||||||
content::Relationship::Hostile => {
|
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
|
true
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -224,6 +233,7 @@ impl World {
|
||||||
ct,
|
ct,
|
||||||
ship.get_handle(),
|
ship.get_handle(),
|
||||||
Box::new(behavior::Null::new()),
|
Box::new(behavior::Null::new()),
|
||||||
|
ship.get_faction(),
|
||||||
r,
|
r,
|
||||||
c,
|
c,
|
||||||
),
|
),
|
||||||
|
@ -238,10 +248,10 @@ impl World {
|
||||||
let mut projectiles = Vec::new();
|
let mut projectiles = Vec::new();
|
||||||
let mut to_remove = Vec::new();
|
let mut to_remove = Vec::new();
|
||||||
for (_, ship_object) in &mut self.ships {
|
for (_, ship_object) in &mut self.ships {
|
||||||
//if s.remove_from_world() {
|
if ship_object.should_be_removed() {
|
||||||
// to_remove.push(s.physics_handle);
|
to_remove.push(ship_object.collider);
|
||||||
// continue;
|
continue;
|
||||||
//}
|
}
|
||||||
|
|
||||||
let rigid_body = &mut self.wrapper.rigid_body_set[ship_object.rigid_body];
|
let rigid_body = &mut self.wrapper.rigid_body_set[ship_object.rigid_body];
|
||||||
let collider = &mut self.wrapper.collider_set[ship_object.collider];
|
let collider = &mut self.wrapper.collider_set[ship_object.collider];
|
||||||
|
@ -279,8 +289,8 @@ impl World {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove ships that don't exist
|
// Remove ships that don't exist
|
||||||
for s in to_remove {
|
for c in to_remove {
|
||||||
self.remove_ship(s);
|
self.remove_ship(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create projectiles
|
// Create projectiles
|
||||||
|
@ -367,9 +377,11 @@ impl World {
|
||||||
};
|
};
|
||||||
|
|
||||||
let p = self.projectiles.get(&a);
|
let p = self.projectiles.get(&a);
|
||||||
let s = self
|
let s = self.ships.get_mut(match self.collider_ship_table.get(&b) {
|
||||||
.ships
|
// If none, this ship is dead.
|
||||||
.get_mut(self.collider_ship_table.get(&b).unwrap());
|
Some(x) => x,
|
||||||
|
None => continue,
|
||||||
|
});
|
||||||
if p.is_none() || s.is_none() {
|
if p.is_none() || s.is_none() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue