Added basic ship behaviors
parent
bffc7b9f23
commit
0184418394
|
@ -9,6 +9,7 @@ use crate::{
|
|||
inputstatus::InputStatus,
|
||||
physics::{util, Physics, ShipHandle},
|
||||
render::Sprite,
|
||||
shipbehavior::{self, ShipBehavior},
|
||||
};
|
||||
|
||||
pub struct Game {
|
||||
|
@ -20,14 +21,15 @@ pub struct Game {
|
|||
paused: bool,
|
||||
pub time_scale: f32,
|
||||
|
||||
world: Physics,
|
||||
physics: Physics,
|
||||
shipbehaviors: Vec<Box<dyn ShipBehavior>>,
|
||||
}
|
||||
|
||||
impl Game {
|
||||
pub fn new(ct: Content) -> Self {
|
||||
let mut world = Physics::new();
|
||||
let mut physics = Physics::new();
|
||||
|
||||
let c = world.add_ship(
|
||||
let h1 = physics.add_ship(
|
||||
&ct.ships[0],
|
||||
vec![
|
||||
outfits::ShipOutfit::Gun(outfits::ShipGun::new(ct.guns[0].clone(), 1)),
|
||||
|
@ -37,20 +39,28 @@ impl Game {
|
|||
Point2 { x: 0.0, y: 0.0 },
|
||||
);
|
||||
|
||||
world.add_ship(&ct.ships[0], vec![], Point2 { x: 300.0, y: 300.0 });
|
||||
world.add_ship(
|
||||
let h2 = physics.add_ship(&ct.ships[0], vec![], Point2 { x: 300.0, y: 300.0 });
|
||||
let h3 = physics.add_ship(
|
||||
&ct.ships[0],
|
||||
vec![],
|
||||
vec![outfits::ShipOutfit::Gun(outfits::ShipGun::new(
|
||||
ct.guns[0].clone(),
|
||||
0,
|
||||
))],
|
||||
Point2 {
|
||||
x: -300.0,
|
||||
y: 300.0,
|
||||
},
|
||||
);
|
||||
|
||||
let mut shipbehaviors: Vec<Box<dyn ShipBehavior>> = Vec::new();
|
||||
shipbehaviors.push(shipbehavior::Player::new(h1));
|
||||
shipbehaviors.push(shipbehavior::Point::new(h3));
|
||||
shipbehaviors.push(shipbehavior::Dummy::new(h2));
|
||||
|
||||
Game {
|
||||
last_update: Instant::now(),
|
||||
input: InputStatus::new(),
|
||||
player: c,
|
||||
player: h1,
|
||||
|
||||
camera: Camera {
|
||||
pos: (0.0, 0.0).into(),
|
||||
|
@ -60,7 +70,8 @@ impl Game {
|
|||
|
||||
paused: false,
|
||||
time_scale: 1.0,
|
||||
world,
|
||||
physics,
|
||||
shipbehaviors,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,11 +99,11 @@ impl Game {
|
|||
pub fn update(&mut self) {
|
||||
let t: f32 = self.last_update.elapsed().as_secs_f32() * self.time_scale;
|
||||
|
||||
self.world
|
||||
.get_ship_mut(&self.player)
|
||||
.update_controls(&self.input);
|
||||
for b in &mut self.shipbehaviors {
|
||||
b.update_controls(&mut self.physics, &self.input, self.player);
|
||||
}
|
||||
|
||||
self.world.tick(t);
|
||||
self.physics.step(t);
|
||||
|
||||
if self.input.v_scroll != 0.0 {
|
||||
self.camera.zoom =
|
||||
|
@ -101,8 +112,8 @@ impl Game {
|
|||
}
|
||||
|
||||
// TODO: Camera physics
|
||||
let r = self.world.get_ship_mut(&self.player).physics_handle;
|
||||
let r = self.world.get_rigid_body(r.0); // TODO: r.0 shouldn't be public
|
||||
let r = self.physics.get_ship_mut(&self.player).physics_handle;
|
||||
let r = self.physics.get_rigid_body(r.0); // TODO: r.0 shouldn't be public
|
||||
let ship_pos = util::rigidbody_position(r);
|
||||
self.camera.pos = ship_pos;
|
||||
self.last_update = Instant::now();
|
||||
|
@ -112,7 +123,7 @@ impl Game {
|
|||
let mut sprites: Vec<Sprite> = Vec::new();
|
||||
|
||||
sprites.append(&mut self.system.get_sprites());
|
||||
sprites.extend(self.world.get_ship_sprites());
|
||||
sprites.extend(self.physics.get_ship_sprites());
|
||||
|
||||
// Make sure sprites are drawn in the correct order
|
||||
// (note the reversed a, b in the comparator)
|
||||
|
@ -122,7 +133,7 @@ impl Game {
|
|||
sprites.sort_by(|a, b| b.pos.z.total_cmp(&a.pos.z));
|
||||
|
||||
// Don't waste time sorting these, they should always be on top.
|
||||
sprites.extend(self.world.get_projectile_sprites());
|
||||
sprites.extend(self.physics.get_projectile_sprites());
|
||||
|
||||
return sprites;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ mod inputstatus;
|
|||
mod objects;
|
||||
mod physics;
|
||||
mod render;
|
||||
mod shipbehavior;
|
||||
|
||||
use anyhow::Result;
|
||||
use galactica_content as content;
|
||||
|
|
|
@ -11,11 +11,14 @@ use super::ProjectileBuilder;
|
|||
use crate::{
|
||||
content,
|
||||
game::outfits,
|
||||
inputstatus::InputStatus,
|
||||
physics::{util, ShipHandle},
|
||||
render::{Sprite, SpriteTexture},
|
||||
};
|
||||
|
||||
pub struct ShipTickResult {
|
||||
pub projectiles: Vec<ProjectileBuilder>,
|
||||
}
|
||||
|
||||
pub struct ShipControls {
|
||||
pub left: bool,
|
||||
pub right: bool,
|
||||
|
@ -34,10 +37,6 @@ impl ShipControls {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct ShipTickResult {
|
||||
pub projectiles: Vec<ProjectileBuilder>,
|
||||
}
|
||||
|
||||
pub struct Ship {
|
||||
pub physics_handle: ShipHandle,
|
||||
outfits: outfits::ShipOutfits,
|
||||
|
@ -45,8 +44,6 @@ pub struct Ship {
|
|||
sprite: SpriteTexture,
|
||||
size: f32,
|
||||
pub hull: f32,
|
||||
|
||||
// TODO: replace with AI enum
|
||||
pub controls: ShipControls,
|
||||
}
|
||||
|
||||
|
@ -64,20 +61,13 @@ impl Ship {
|
|||
Ship {
|
||||
physics_handle,
|
||||
outfits: o,
|
||||
controls: ShipControls::new(),
|
||||
sprite: SpriteTexture(c.sprite.clone()),
|
||||
size: c.size,
|
||||
hull: c.hull,
|
||||
controls: ShipControls::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_controls(&mut self, input: &InputStatus) {
|
||||
self.controls.thrust = input.key_thrust;
|
||||
self.controls.right = input.key_right;
|
||||
self.controls.left = input.key_left;
|
||||
self.controls.guns = input.key_guns;
|
||||
}
|
||||
|
||||
pub fn fire_guns(&mut self, r: &RigidBody) -> Vec<ProjectileBuilder> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut out = Vec::new();
|
||||
|
@ -130,10 +120,11 @@ impl Ship {
|
|||
return out;
|
||||
}
|
||||
|
||||
pub fn tick(&mut self, r: &mut RigidBody, t: f32) -> ShipTickResult {
|
||||
/// Apply the effects of all active controls
|
||||
pub fn apply_controls(&mut self, r: &mut RigidBody, t: f32) -> ShipTickResult {
|
||||
let ship_ang = util::rigidbody_angle(r);
|
||||
|
||||
let engine_force = Matrix2::from_angle(ship_ang) * Vector2 { x: 0.0, y: 1.0 } * t;
|
||||
|
||||
if self.controls.thrust {
|
||||
for e in self.outfits.iter_engines() {
|
||||
r.apply_impulse(vector![engine_force.x, engine_force.y] * e.thrust, true);
|
||||
|
|
|
@ -101,7 +101,7 @@ impl Physics {
|
|||
return h;
|
||||
}
|
||||
|
||||
pub fn tick(&mut self, t: f32) {
|
||||
pub fn step(&mut self, t: f32) {
|
||||
// Run ship updates
|
||||
let mut res = Vec::new();
|
||||
let mut to_remove = Vec::new();
|
||||
|
@ -111,7 +111,7 @@ impl Physics {
|
|||
continue;
|
||||
}
|
||||
let r = &mut self.wrapper.rigid_body_set[s.physics_handle.0];
|
||||
res.push(s.tick(r, t));
|
||||
res.push(s.apply_controls(r, t));
|
||||
}
|
||||
for r in to_remove {
|
||||
self.remove_ship(r);
|
||||
|
@ -170,6 +170,14 @@ impl Physics {
|
|||
self.ships.get_mut(&s.1).unwrap()
|
||||
}
|
||||
|
||||
pub fn get_ship_body(&self, s: &ShipHandle) -> (&objects::Ship, &RigidBody) {
|
||||
// TODO: handle dead handles
|
||||
(
|
||||
self.ships.get(&s.1).unwrap(),
|
||||
self.wrapper.rigid_body_set.get(s.0).unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_ship_sprites(&self) -> impl Iterator<Item = Sprite> + '_ {
|
||||
self.ships
|
||||
.values()
|
||||
|
|
|
@ -18,6 +18,13 @@ pub fn rigidbody_angle(r: &RigidBody) -> Deg<f32> {
|
|||
.into()
|
||||
}
|
||||
|
||||
pub fn rigidbody_rotation(r: &RigidBody) -> Vector2<f32> {
|
||||
Vector2 {
|
||||
x: r.rotation().im,
|
||||
y: r.rotation().re,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rigidbody_velocity(r: &RigidBody) -> cgmath::Vector2<f32> {
|
||||
let v = r.velocity_at_point(&nalgebra::Point2::new(
|
||||
r.translation()[0],
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
use cgmath::{Deg, InnerSpace};
|
||||
|
||||
use crate::{
|
||||
inputstatus::InputStatus,
|
||||
physics::{util, Physics, ShipHandle},
|
||||
};
|
||||
|
||||
pub trait ShipBehavior
|
||||
where
|
||||
Self: Send,
|
||||
{
|
||||
fn update_controls(&mut self, physics: &mut Physics, input: &InputStatus, player: ShipHandle);
|
||||
}
|
||||
|
||||
pub struct Dummy {
|
||||
_handle: ShipHandle,
|
||||
}
|
||||
|
||||
impl Dummy {
|
||||
pub fn new(handle: ShipHandle) -> Box<Self> {
|
||||
Box::new(Self { _handle: handle })
|
||||
}
|
||||
}
|
||||
|
||||
impl ShipBehavior for Dummy {
|
||||
fn update_controls(
|
||||
&mut self,
|
||||
_physics: &mut Physics,
|
||||
_input: &InputStatus,
|
||||
_player: ShipHandle,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Player {
|
||||
handle: ShipHandle,
|
||||
}
|
||||
|
||||
impl Player {
|
||||
pub fn new(handle: ShipHandle) -> Box<Self> {
|
||||
Box::new(Self { handle })
|
||||
}
|
||||
}
|
||||
|
||||
impl ShipBehavior for Player {
|
||||
fn update_controls(&mut self, physics: &mut Physics, input: &InputStatus, _player: ShipHandle) {
|
||||
let s = physics.get_ship_mut(&self.handle);
|
||||
s.controls.left = input.key_left;
|
||||
s.controls.right = input.key_right;
|
||||
s.controls.guns = input.key_guns;
|
||||
s.controls.thrust = input.key_thrust;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Point {
|
||||
handle: ShipHandle,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
pub fn new(handle: ShipHandle) -> Box<Self> {
|
||||
Box::new(Self { handle })
|
||||
}
|
||||
}
|
||||
|
||||
impl ShipBehavior for Point {
|
||||
fn update_controls(&mut self, physics: &mut Physics, _input: &InputStatus, player: ShipHandle) {
|
||||
let (_, r) = physics.get_ship_body(&player);
|
||||
let p = util::rigidbody_position(r);
|
||||
|
||||
let (_, r) = physics.get_ship_body(&self.handle);
|
||||
let t = util::rigidbody_position(r);
|
||||
let pa = util::rigidbody_rotation(r);
|
||||
let v = r.angvel();
|
||||
|
||||
let d: Deg<f32> = (t - p).angle(pa).into();
|
||||
println!("{:?}", d);
|
||||
|
||||
let s = physics.get_ship_mut(&self.handle);
|
||||
|
||||
s.controls.left = false;
|
||||
s.controls.right = false;
|
||||
|
||||
if d < Deg(0.0) && v < 0.1 {
|
||||
s.controls.left = false;
|
||||
s.controls.right = true;
|
||||
println!("r")
|
||||
} else if d > Deg(0.0) && v > -0.1 {
|
||||
println!("l");
|
||||
s.controls.left = true;
|
||||
s.controls.right = false;
|
||||
}
|
||||
|
||||
s.controls.guns = true;
|
||||
s.controls.thrust = false;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue