Comments
parent
afa6bd6690
commit
b309a074dc
|
@ -1,14 +1,24 @@
|
|||
#![warn(missing_docs)]
|
||||
|
||||
//! Compile-time parameters
|
||||
|
||||
/// Minimum zoom level
|
||||
pub const ZOOM_MIN: f32 = 200.0;
|
||||
/// Maximum zoom level
|
||||
pub const ZOOM_MAX: f32 = 2000.0;
|
||||
|
||||
/// Z-axis range for starfield stars
|
||||
/// This does not affect scale.
|
||||
pub const STARFIELD_Z_MIN: f32 = 100.0;
|
||||
/// Z-axis range for starfield stars
|
||||
/// This does not affect scale.
|
||||
pub const STARFIELD_Z_MAX: f32 = 200.0;
|
||||
|
||||
/// Size range for starfield stars, in game units.
|
||||
/// This is scaled for zoom, but NOT for distance.
|
||||
pub const STARFIELD_SIZE_MIN: f32 = 0.2;
|
||||
/// Size range for starfield stars, in game units.
|
||||
/// This is scaled for zoom, but NOT for distance.
|
||||
pub const STARFIELD_SIZE_MAX: f32 = 1.8;
|
||||
|
||||
/// Size of a square starfield tile, in game units.
|
||||
|
@ -34,9 +44,8 @@ pub const CONTENT_ROOT: &'static str = "./content";
|
|||
/// Root directory of game textures
|
||||
pub const TEXTURE_ROOT: &'static str = "./assets/render";
|
||||
|
||||
// We can draw at most this many sprites on the screen.
|
||||
// TODO: compile-time option or config file
|
||||
/// We can draw at most this many sprites on the screen.
|
||||
pub const SPRITE_INSTANCE_LIMIT: u64 = 500;
|
||||
|
||||
// Must be small enough to fit in an i32
|
||||
/// Must be small enough to fit in an i32
|
||||
pub const STARFIELD_INSTANCE_LIMIT: u64 = STARFIELD_COUNT * 24;
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
#![warn(missing_docs)]
|
||||
|
||||
//! This module keeps track of all objects and interactions in the game:
|
||||
//! Ships, projectiles, collisions, etc.
|
||||
//! TODO: Rename & re-organize
|
||||
|
||||
pub mod objects;
|
||||
mod physics;
|
||||
pub mod util;
|
||||
|
@ -7,5 +13,6 @@ pub use physics::Physics;
|
|||
|
||||
use rapier2d::{dynamics::RigidBodyHandle, geometry::ColliderHandle};
|
||||
|
||||
/// A lightweight handle for a specific ship in a physics system
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct ShipHandle(pub RigidBodyHandle, ColliderHandle);
|
||||
|
|
|
@ -5,12 +5,18 @@ use galactica_render::ObjectSubSprite;
|
|||
/// Represents a gun attached to a specific ship at a certain gunpoint.
|
||||
#[derive(Debug)]
|
||||
pub struct ShipGun {
|
||||
/// The kind of gun this is
|
||||
pub kind: content::Gun,
|
||||
|
||||
/// How many seconds we must wait before this gun can fire
|
||||
pub cooldown: f32,
|
||||
|
||||
/// Index of the gunpoint this gun is attached to
|
||||
pub point: usize,
|
||||
}
|
||||
|
||||
impl ShipGun {
|
||||
/// Make a new shipgun
|
||||
pub fn new(kind: content::Gun, point: usize) -> Self {
|
||||
Self {
|
||||
kind: kind,
|
||||
|
@ -63,11 +69,15 @@ impl OutfitStatSum {
|
|||
|
||||
/// Represents all the outfits attached to a ship.
|
||||
/// Keeps track of the sum of their stats, so it mustn't be re-computed every frame.
|
||||
/// TODO: rename (outfitset?)
|
||||
/// TODO: ctrl-f outfitset in comments
|
||||
#[derive(Debug)]
|
||||
pub struct ShipOutfits {
|
||||
/// The total sum of the stats this set of outfits provides
|
||||
/// TODO: this shouldn't be pub
|
||||
pub stats: OutfitStatSum,
|
||||
pub total_space: content::OutfitSpace,
|
||||
|
||||
//pub total_space: content::OutfitSpace,
|
||||
available_space: content::OutfitSpace,
|
||||
outfits: Vec<content::Outfit>,
|
||||
guns: Vec<ShipGun>,
|
||||
|
@ -80,13 +90,14 @@ pub struct ShipOutfits {
|
|||
}
|
||||
|
||||
impl<'a> ShipOutfits {
|
||||
/// Make a new outfit array
|
||||
pub fn new(content: &content::Ship) -> Self {
|
||||
Self {
|
||||
stats: OutfitStatSum::new(),
|
||||
outfits: Vec::new(),
|
||||
guns: Vec::new(),
|
||||
available_space: content.space.clone(),
|
||||
total_space: content.space.clone(),
|
||||
//total_space: content.space.clone(),
|
||||
enginepoints: content.engines.clone(),
|
||||
gunpoints: content.guns.clone(),
|
||||
engine_flare_sprites: vec![],
|
||||
|
@ -153,10 +164,12 @@ impl<'a> ShipOutfits {
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Iterate over all guns in this outfitset
|
||||
pub fn iter_guns(&mut self) -> impl Iterator<Item = &mut ShipGun> {
|
||||
self.guns.iter_mut()
|
||||
}
|
||||
|
||||
/// Iterate over all guns and the gunpoints they're attached to
|
||||
pub fn iter_guns_points(&mut self) -> impl Iterator<Item = (&mut ShipGun, &content::GunPoint)> {
|
||||
self.guns
|
||||
.iter_mut()
|
||||
|
@ -164,6 +177,7 @@ impl<'a> ShipOutfits {
|
|||
.map(|(a, b)| (b, a))
|
||||
}
|
||||
|
||||
/// Update engine flare sprites
|
||||
pub fn update_engine_flares(&mut self) {
|
||||
// TODO: better way to pick flare texture
|
||||
self.engine_flare_sprites.clear();
|
||||
|
@ -189,6 +203,7 @@ impl<'a> ShipOutfits {
|
|||
.collect();
|
||||
}
|
||||
|
||||
/// Get the sprites we should show if this ship is firing its engines
|
||||
pub fn get_engine_flares(&self) -> Vec<ObjectSubSprite> {
|
||||
return self.engine_flare_sprites.clone();
|
||||
}
|
||||
|
|
|
@ -8,50 +8,81 @@ use crate::util;
|
|||
use galactica_content as content;
|
||||
use galactica_render::ObjectSprite;
|
||||
|
||||
/// A helper struct that contains parameters for a projectile
|
||||
/// TODO: decouple data from physics
|
||||
pub struct ProjectileBuilder {
|
||||
/// TODO
|
||||
pub rigid_body: RigidBodyBuilder,
|
||||
|
||||
/// TODO
|
||||
pub collider: ColliderBuilder,
|
||||
|
||||
/// TODO
|
||||
pub sprite_texture: content::TextureHandle,
|
||||
|
||||
/// TODO
|
||||
pub lifetime: f32,
|
||||
|
||||
/// TODO
|
||||
pub size: f32,
|
||||
|
||||
/// TODO
|
||||
pub damage: f32,
|
||||
|
||||
/// TODO
|
||||
pub faction: content::FactionHandle,
|
||||
}
|
||||
|
||||
impl ProjectileBuilder {
|
||||
pub fn build(self, r: RigidBodyHandle, c: ColliderHandle) -> Projectile {
|
||||
Projectile {
|
||||
rigid_body: r,
|
||||
collider: c,
|
||||
sprite_texture: self.sprite_texture,
|
||||
lifetime: self.lifetime,
|
||||
size: self.size,
|
||||
damage: self.damage,
|
||||
faction: self.faction,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A single projectile in the world
|
||||
#[derive(Debug)]
|
||||
pub struct Projectile {
|
||||
/// TODO
|
||||
pub rigid_body: RigidBodyHandle,
|
||||
|
||||
/// TODO
|
||||
pub collider: ColliderHandle,
|
||||
|
||||
/// TODO
|
||||
pub sprite_texture: content::TextureHandle,
|
||||
|
||||
/// TODO
|
||||
pub lifetime: f32,
|
||||
|
||||
/// TODOd
|
||||
pub size: f32,
|
||||
|
||||
/// TODO
|
||||
pub damage: f32,
|
||||
|
||||
/// TODO
|
||||
pub faction: content::FactionHandle,
|
||||
}
|
||||
|
||||
impl Projectile {
|
||||
/// Make a new projectile
|
||||
pub fn new(b: ProjectileBuilder, r: RigidBodyHandle, c: ColliderHandle) -> Self {
|
||||
Projectile {
|
||||
rigid_body: r,
|
||||
collider: c,
|
||||
sprite_texture: b.sprite_texture,
|
||||
lifetime: b.lifetime,
|
||||
size: b.size,
|
||||
damage: b.damage,
|
||||
faction: b.faction,
|
||||
}
|
||||
}
|
||||
|
||||
/// Update this projectile's state after `t` seconds
|
||||
pub fn tick(&mut self, t: f32) {
|
||||
self.lifetime -= t;
|
||||
}
|
||||
|
||||
/// Is this projectile expired?
|
||||
pub fn is_expired(&self) -> bool {
|
||||
return self.lifetime < 0.0;
|
||||
}
|
||||
|
||||
/// Get this projectiles' sprite
|
||||
pub fn get_sprite(&self, r: &RigidBody) -> ObjectSprite {
|
||||
let pos = util::rigidbody_position(r);
|
||||
let rot = util::rigidbody_rotation(r);
|
||||
|
|
|
@ -35,10 +35,19 @@ impl ShipControls {
|
|||
}
|
||||
}
|
||||
|
||||
/// A ship instance in the physics system
|
||||
/// TODO: Decouple ship data from physics
|
||||
pub struct Ship {
|
||||
/// TODO
|
||||
pub physics_handle: ShipHandle,
|
||||
|
||||
/// TODO
|
||||
pub faction: FactionHandle,
|
||||
|
||||
/// TODO
|
||||
pub hull: f32,
|
||||
|
||||
/// TODO
|
||||
pub controls: ShipControls,
|
||||
|
||||
outfits: ShipOutfits,
|
||||
|
@ -47,6 +56,7 @@ pub struct Ship {
|
|||
}
|
||||
|
||||
impl Ship {
|
||||
/// Make a new ship
|
||||
pub fn new(
|
||||
c: &content::Ship,
|
||||
outfits: ShipOutfits,
|
||||
|
@ -64,6 +74,7 @@ impl Ship {
|
|||
}
|
||||
}
|
||||
|
||||
/// Fire this ship's guns. Called every frame, if this ship is firing.
|
||||
pub fn fire_guns(&mut self, r: &RigidBody) -> Vec<ProjectileBuilder> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut out = Vec::new();
|
||||
|
@ -154,6 +165,7 @@ impl Ship {
|
|||
return ShipTickResult { projectiles: p };
|
||||
}
|
||||
|
||||
/// Get this ship's sprite
|
||||
pub fn get_sprite(&self, r: &RigidBody) -> ObjectSprite {
|
||||
let ship_pos = util::rigidbody_position(r);
|
||||
let ship_rot = util::rigidbody_rotation(r);
|
||||
|
|
|
@ -8,7 +8,12 @@ use rapier2d::{
|
|||
};
|
||||
use std::{collections::HashMap, f32::consts::PI};
|
||||
|
||||
use crate::{objects, objects::ShipOutfits, wrapper::Wrapper, ShipHandle};
|
||||
use crate::{
|
||||
objects,
|
||||
objects::{Projectile, ShipOutfits},
|
||||
wrapper::Wrapper,
|
||||
ShipHandle,
|
||||
};
|
||||
use galactica_content as content;
|
||||
use galactica_render::ObjectSprite;
|
||||
|
||||
|
@ -59,13 +64,14 @@ impl Physics {
|
|||
r,
|
||||
&mut self.wrapper.rigid_body_set,
|
||||
);
|
||||
self.projectiles.insert(c, pb.build(r, c));
|
||||
self.projectiles.insert(c, Projectile::new(pb, r, c));
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
// Public methods
|
||||
impl Physics {
|
||||
/// Create a new physics system
|
||||
pub fn new() -> Self {
|
||||
let (collision_send, collision_queue) = crossbeam::channel::unbounded();
|
||||
let (contact_force_send, _) = crossbeam::channel::unbounded();
|
||||
|
@ -79,6 +85,8 @@ impl Physics {
|
|||
}
|
||||
}
|
||||
|
||||
/// Add a ship to this physics system
|
||||
/// TODO: decouple from Ship::new()
|
||||
pub fn add_ship(
|
||||
&mut self,
|
||||
ct: &content::Ship,
|
||||
|
@ -114,6 +122,7 @@ impl Physics {
|
|||
return h;
|
||||
}
|
||||
|
||||
/// Step this physics system by `t` seconds
|
||||
pub fn step(&mut self, t: f32, ct: &content::Content) {
|
||||
// Run ship updates
|
||||
let mut res = Vec::new();
|
||||
|
@ -183,19 +192,23 @@ impl Physics {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get a rigid body from a handle
|
||||
pub fn get_rigid_body(&self, r: RigidBodyHandle) -> &RigidBody {
|
||||
&self.wrapper.rigid_body_set[r]
|
||||
}
|
||||
|
||||
/// Get a ship from a handle
|
||||
pub fn get_ship_mut(&mut self, s: &ShipHandle) -> Option<&mut objects::Ship> {
|
||||
self.ships.get_mut(&s.1)
|
||||
}
|
||||
|
||||
/// Get a ship and its rigidbody from a handle
|
||||
pub fn get_ship_body(&self, s: &ShipHandle) -> Option<(&objects::Ship, &RigidBody)> {
|
||||
// TODO: handle dead handles
|
||||
Some((self.ships.get(&s.1)?, self.wrapper.rigid_body_set.get(s.0)?))
|
||||
}
|
||||
|
||||
/// Iterate over all ships in this physics system
|
||||
pub fn iter_ship_body(&self) -> impl Iterator<Item = (&objects::Ship, &RigidBody)> + '_ {
|
||||
self.ships.values().map(|x| {
|
||||
(
|
||||
|
@ -205,12 +218,14 @@ impl Physics {
|
|||
})
|
||||
}
|
||||
|
||||
/// Iterate over all ship sprites in this physics system
|
||||
pub fn get_ship_sprites(&self) -> impl Iterator<Item = ObjectSprite> + '_ {
|
||||
self.ships
|
||||
.values()
|
||||
.map(|x| x.get_sprite(&self.wrapper.rigid_body_set[x.physics_handle.0]))
|
||||
}
|
||||
|
||||
/// Iterate over all projectile sprites in this physics system
|
||||
pub fn get_projectile_sprites(&self) -> impl Iterator<Item = ObjectSprite> + '_ {
|
||||
self.projectiles
|
||||
.values()
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
//! Conversion utilities
|
||||
|
||||
use cgmath::{Point2, Vector2};
|
||||
use nalgebra;
|
||||
use rapier2d::dynamics::RigidBody;
|
||||
|
||||
// TODO: Migrate to nalgebra fully, remove these converters
|
||||
|
||||
/// Convert a rigidbody position to a position in game coordinates
|
||||
pub fn rigidbody_position(r: &RigidBody) -> cgmath::Point2<f32> {
|
||||
Point2 {
|
||||
x: r.translation()[0],
|
||||
|
@ -9,6 +14,7 @@ pub fn rigidbody_position(r: &RigidBody) -> cgmath::Point2<f32> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Convert a rigidbody rotation to a rotation in game coordinates
|
||||
pub fn rigidbody_rotation(r: &RigidBody) -> Vector2<f32> {
|
||||
Vector2 {
|
||||
x: r.rotation().re,
|
||||
|
@ -16,6 +22,7 @@ pub fn rigidbody_rotation(r: &RigidBody) -> Vector2<f32> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Convert a rigidbody velocity to a velocity in game coordinates
|
||||
pub fn rigidbody_velocity(r: &RigidBody) -> cgmath::Vector2<f32> {
|
||||
let v = r.velocity_at_point(&nalgebra::Point2::new(
|
||||
r.translation()[0],
|
||||
|
|
|
@ -2,11 +2,14 @@ use crate::ShipBehavior;
|
|||
use galactica_content as content;
|
||||
use galactica_physics::{Physics, ShipHandle};
|
||||
|
||||
/// Dummy ship behavior.
|
||||
/// Does nothing.
|
||||
pub struct Dummy {
|
||||
_handle: ShipHandle,
|
||||
}
|
||||
|
||||
impl Dummy {
|
||||
/// Create a new ship controller
|
||||
pub fn new(handle: ShipHandle) -> Box<Self> {
|
||||
Box::new(Self { _handle: handle })
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Various implementations of [`crate::ShipBehavior`]
|
||||
|
||||
mod dummy;
|
||||
mod player;
|
||||
mod point;
|
||||
|
|
|
@ -2,6 +2,8 @@ use crate::ShipBehavior;
|
|||
use galactica_content as content;
|
||||
use galactica_physics::{Physics, ShipHandle};
|
||||
|
||||
/// Player ship behavior.
|
||||
/// Controls a ship using controller input
|
||||
pub struct Player {
|
||||
handle: ShipHandle,
|
||||
key_left: bool,
|
||||
|
@ -11,6 +13,7 @@ pub struct Player {
|
|||
}
|
||||
|
||||
impl Player {
|
||||
/// Make a new ship controller
|
||||
pub fn new(handle: ShipHandle) -> Box<Self> {
|
||||
Box::new(Self {
|
||||
handle,
|
||||
|
|
|
@ -4,11 +4,14 @@ use crate::ShipBehavior;
|
|||
use galactica_content as content;
|
||||
use galactica_physics::{util, Physics, ShipHandle};
|
||||
|
||||
/// "Point" ship behavior.
|
||||
/// Point and shoot towards the nearest enemy.
|
||||
pub struct Point {
|
||||
handle: ShipHandle,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
/// Create a new ship controller
|
||||
pub fn new(handle: ShipHandle) -> Box<Self> {
|
||||
Box::new(Self { handle })
|
||||
}
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
#![warn(missing_docs)]
|
||||
|
||||
//! Computer-controlled ship behaviors
|
||||
|
||||
pub mod behavior;
|
||||
|
||||
use galactica_content as content;
|
||||
use galactica_physics::{Physics, ShipHandle};
|
||||
|
||||
/// Main behavior trait. Any struct that implements this
|
||||
/// may be used to control a ship.
|
||||
pub trait ShipBehavior
|
||||
where
|
||||
Self: Send,
|
||||
{
|
||||
/// Update a ship's controls based on world state
|
||||
fn update_controls(&mut self, physics: &mut Physics, content: &content::Content);
|
||||
|
||||
/// Get the ship this behavior is attached to
|
||||
fn get_handle(&self) -> ShipHandle;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue