Added basic ship guns
parent
3f92e62724
commit
389803eae9
|
@ -1,9 +1,33 @@
|
|||
use cgmath::Deg;
|
||||
use cgmath::{Deg, Point2, Point3, Vector2};
|
||||
use std::time::Instant;
|
||||
use winit::event::{ElementState, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode};
|
||||
|
||||
use super::{Camera, InputStatus, Ship, System};
|
||||
use crate::{consts, content::Content, render::Sprite, render::Spriteable};
|
||||
use crate::{
|
||||
consts,
|
||||
content::Content,
|
||||
render::Spriteable,
|
||||
render::{Sprite, SpriteTexture},
|
||||
};
|
||||
|
||||
pub struct Projectile {
|
||||
pub position: Point2<f32>,
|
||||
pub velocity: Vector2<f32>,
|
||||
pub sprite: SpriteTexture,
|
||||
pub angle: Deg<f32>,
|
||||
pub lifetime: f32,
|
||||
}
|
||||
|
||||
impl Projectile {
|
||||
pub fn tick(&mut self, t: f32) {
|
||||
self.position += self.velocity * t;
|
||||
self.lifetime -= t;
|
||||
}
|
||||
|
||||
pub fn is_expired(&self) -> bool {
|
||||
return self.lifetime < 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Game {
|
||||
pub input: InputStatus,
|
||||
|
@ -13,6 +37,7 @@ pub struct Game {
|
|||
pub system: System,
|
||||
pub camera: Camera,
|
||||
paused: bool,
|
||||
pub projectiles: Vec<Projectile>,
|
||||
pub time_scale: f32,
|
||||
}
|
||||
|
||||
|
@ -21,12 +46,14 @@ impl Game {
|
|||
Game {
|
||||
last_update: Instant::now(),
|
||||
input: InputStatus::new(),
|
||||
projectiles: Vec::new(),
|
||||
player: Ship::new(&ct.ships[0], (0.0, 0.0).into()),
|
||||
camera: Camera {
|
||||
pos: (0.0, 0.0).into(),
|
||||
zoom: 500.0,
|
||||
},
|
||||
system: System::new(&ct.systems[0]),
|
||||
|
||||
paused: false,
|
||||
time_scale: 1.0,
|
||||
test: Ship::new(&ct.ships[0], (100.0, 100.0).into()),
|
||||
|
@ -57,17 +84,16 @@ impl Game {
|
|||
pub fn update(&mut self) {
|
||||
let t: f32 = self.last_update.elapsed().as_secs_f32() * self.time_scale;
|
||||
|
||||
self.player.engines_on = self.input.key_thrust;
|
||||
if self.input.key_thrust {
|
||||
self.player.physicsbody.thrust(50.0 * t);
|
||||
}
|
||||
self.projectiles.retain_mut(|p| {
|
||||
p.tick(t);
|
||||
!p.is_expired()
|
||||
});
|
||||
|
||||
if self.input.key_right {
|
||||
self.player.physicsbody.rot(Deg(35.0) * t);
|
||||
}
|
||||
|
||||
if self.input.key_left {
|
||||
self.player.physicsbody.rot(Deg(-35.0) * t);
|
||||
// Update player and handle result
|
||||
self.player.update_controls(&self.input);
|
||||
let mut p = self.player.tick(t);
|
||||
if p.projectiles.len() != 0 {
|
||||
self.projectiles.append(&mut p.projectiles);
|
||||
}
|
||||
|
||||
if self.input.v_scroll != 0.0 {
|
||||
|
@ -76,7 +102,6 @@ impl Game {
|
|||
self.input.v_scroll = 0.0;
|
||||
}
|
||||
|
||||
self.player.physicsbody.tick(t);
|
||||
self.camera.pos = self.player.physicsbody.pos;
|
||||
|
||||
self.last_update = Instant::now();
|
||||
|
@ -96,6 +121,21 @@ impl Game {
|
|||
// I've tried this, but it doesn't seem to work with transparent textures.
|
||||
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.
|
||||
for p in &self.projectiles {
|
||||
sprites.push(Sprite {
|
||||
texture: p.sprite.clone(),
|
||||
pos: Point3 {
|
||||
x: p.position.x,
|
||||
y: p.position.y,
|
||||
z: 1.0,
|
||||
},
|
||||
size: 10.0,
|
||||
angle: p.angle,
|
||||
children: None,
|
||||
})
|
||||
}
|
||||
|
||||
return sprites;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ pub struct InputStatus {
|
|||
pub key_left: bool,
|
||||
pub key_right: bool,
|
||||
pub key_thrust: bool,
|
||||
pub key_guns: bool,
|
||||
pub v_scroll: f32,
|
||||
}
|
||||
|
||||
|
@ -14,6 +15,7 @@ impl InputStatus {
|
|||
key_left: false,
|
||||
key_right: false,
|
||||
key_thrust: false,
|
||||
key_guns: false,
|
||||
v_scroll: 0.0,
|
||||
scroll_speed: 10.0,
|
||||
}
|
||||
|
@ -23,6 +25,7 @@ impl InputStatus {
|
|||
self.key_left = false;
|
||||
self.key_right = false;
|
||||
self.key_thrust = false;
|
||||
self.key_guns = false;
|
||||
}
|
||||
|
||||
pub fn process_key(&mut self, state: &ElementState, key: &VirtualKeyCode) {
|
||||
|
@ -31,6 +34,7 @@ impl InputStatus {
|
|||
VirtualKeyCode::Left => self.key_left = down,
|
||||
VirtualKeyCode::Right => self.key_right = down,
|
||||
VirtualKeyCode::Up => self.key_thrust = down,
|
||||
VirtualKeyCode::Space => self.key_guns = down,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,35 +1,118 @@
|
|||
use cgmath::{Deg, Point2, Point3};
|
||||
use cgmath::{Deg, EuclideanSpace, Matrix2, Point2, Point3, Vector2};
|
||||
|
||||
use crate::{
|
||||
content::{self, ship::Engine},
|
||||
content,
|
||||
physics::PhysicsBody,
|
||||
render::{Sprite, SpriteTexture, Spriteable, SubSprite},
|
||||
};
|
||||
|
||||
use super::{game::Projectile, InputStatus};
|
||||
|
||||
pub struct ShipControls {
|
||||
pub left: bool,
|
||||
pub right: bool,
|
||||
pub thrust: bool,
|
||||
pub guns: bool,
|
||||
}
|
||||
|
||||
impl ShipControls {
|
||||
pub fn new() -> Self {
|
||||
ShipControls {
|
||||
left: false,
|
||||
right: false,
|
||||
thrust: false,
|
||||
guns: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ShipTickResult {
|
||||
pub projectiles: Vec<Projectile>,
|
||||
}
|
||||
|
||||
pub struct Ship {
|
||||
pub physicsbody: PhysicsBody,
|
||||
pub engines_on: bool,
|
||||
pub controls: ShipControls,
|
||||
|
||||
sprite: SpriteTexture,
|
||||
size: f32,
|
||||
engines: Vec<Engine>,
|
||||
engines: Vec<content::Engine>,
|
||||
guns: Vec<content::ShipGun>,
|
||||
}
|
||||
|
||||
impl Ship {
|
||||
pub fn new(ct: &content::ship::Ship, pos: Point2<f32>) -> Self {
|
||||
pub fn new(ct: &content::Ship, pos: Point2<f32>) -> Self {
|
||||
Ship {
|
||||
physicsbody: PhysicsBody::new(pos),
|
||||
sprite: SpriteTexture(ct.sprite.clone()),
|
||||
size: ct.size,
|
||||
engines: ct.engines.clone(),
|
||||
engines_on: false,
|
||||
guns: ct.guns.clone(),
|
||||
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) -> Vec<Projectile> {
|
||||
let mut out = Vec::new();
|
||||
for i in &mut self.guns {
|
||||
if i.active_cooldown > 0.0 {
|
||||
continue;
|
||||
}
|
||||
i.active_cooldown = i.cooldown;
|
||||
|
||||
let p = self.physicsbody.pos
|
||||
+ (Matrix2::from_angle(self.physicsbody.angle) * i.pos.to_vec());
|
||||
|
||||
out.push(Projectile {
|
||||
position: p,
|
||||
velocity: self.physicsbody.vel
|
||||
+ (Matrix2::from_angle(self.physicsbody.angle) * Vector2 { x: 0.0, y: 400.0 }),
|
||||
angle: self.physicsbody.angle,
|
||||
sprite: SpriteTexture("projectile::blaster".into()),
|
||||
lifetime: 5.0,
|
||||
})
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
pub fn tick(&mut self, t: f32) -> ShipTickResult {
|
||||
if self.controls.thrust {
|
||||
self.physicsbody.thrust(50.0 * t);
|
||||
}
|
||||
|
||||
if self.controls.right {
|
||||
self.physicsbody.rot(Deg(35.0) * t);
|
||||
}
|
||||
|
||||
if self.controls.left {
|
||||
self.physicsbody.rot(Deg(-35.0) * t);
|
||||
}
|
||||
|
||||
let p = if self.controls.guns {
|
||||
self.fire_guns()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
self.physicsbody.tick(t);
|
||||
for i in &mut self.guns {
|
||||
i.active_cooldown -= t;
|
||||
}
|
||||
|
||||
return ShipTickResult { projectiles: p };
|
||||
}
|
||||
}
|
||||
|
||||
impl Spriteable for Ship {
|
||||
fn get_sprite(&self) -> Sprite {
|
||||
let engines = if self.engines_on {
|
||||
let engines = if self.controls.thrust {
|
||||
Some(
|
||||
self.engines
|
||||
.iter()
|
||||
|
|
Loading…
Reference in New Issue