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 std::time::Instant;
|
||||||
use winit::event::{ElementState, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode};
|
use winit::event::{ElementState, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode};
|
||||||
|
|
||||||
use super::{Camera, InputStatus, Ship, System};
|
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 struct Game {
|
||||||
pub input: InputStatus,
|
pub input: InputStatus,
|
||||||
|
@ -13,6 +37,7 @@ pub struct Game {
|
||||||
pub system: System,
|
pub system: System,
|
||||||
pub camera: Camera,
|
pub camera: Camera,
|
||||||
paused: bool,
|
paused: bool,
|
||||||
|
pub projectiles: Vec<Projectile>,
|
||||||
pub time_scale: f32,
|
pub time_scale: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,12 +46,14 @@ impl Game {
|
||||||
Game {
|
Game {
|
||||||
last_update: Instant::now(),
|
last_update: Instant::now(),
|
||||||
input: InputStatus::new(),
|
input: InputStatus::new(),
|
||||||
|
projectiles: Vec::new(),
|
||||||
player: Ship::new(&ct.ships[0], (0.0, 0.0).into()),
|
player: Ship::new(&ct.ships[0], (0.0, 0.0).into()),
|
||||||
camera: Camera {
|
camera: Camera {
|
||||||
pos: (0.0, 0.0).into(),
|
pos: (0.0, 0.0).into(),
|
||||||
zoom: 500.0,
|
zoom: 500.0,
|
||||||
},
|
},
|
||||||
system: System::new(&ct.systems[0]),
|
system: System::new(&ct.systems[0]),
|
||||||
|
|
||||||
paused: false,
|
paused: false,
|
||||||
time_scale: 1.0,
|
time_scale: 1.0,
|
||||||
test: Ship::new(&ct.ships[0], (100.0, 100.0).into()),
|
test: Ship::new(&ct.ships[0], (100.0, 100.0).into()),
|
||||||
|
@ -57,17 +84,16 @@ impl Game {
|
||||||
pub fn update(&mut self) {
|
pub fn update(&mut self) {
|
||||||
let t: f32 = self.last_update.elapsed().as_secs_f32() * self.time_scale;
|
let t: f32 = self.last_update.elapsed().as_secs_f32() * self.time_scale;
|
||||||
|
|
||||||
self.player.engines_on = self.input.key_thrust;
|
self.projectiles.retain_mut(|p| {
|
||||||
if self.input.key_thrust {
|
p.tick(t);
|
||||||
self.player.physicsbody.thrust(50.0 * t);
|
!p.is_expired()
|
||||||
}
|
});
|
||||||
|
|
||||||
if self.input.key_right {
|
// Update player and handle result
|
||||||
self.player.physicsbody.rot(Deg(35.0) * t);
|
self.player.update_controls(&self.input);
|
||||||
}
|
let mut p = self.player.tick(t);
|
||||||
|
if p.projectiles.len() != 0 {
|
||||||
if self.input.key_left {
|
self.projectiles.append(&mut p.projectiles);
|
||||||
self.player.physicsbody.rot(Deg(-35.0) * t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.input.v_scroll != 0.0 {
|
if self.input.v_scroll != 0.0 {
|
||||||
|
@ -76,7 +102,6 @@ impl Game {
|
||||||
self.input.v_scroll = 0.0;
|
self.input.v_scroll = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.player.physicsbody.tick(t);
|
|
||||||
self.camera.pos = self.player.physicsbody.pos;
|
self.camera.pos = self.player.physicsbody.pos;
|
||||||
|
|
||||||
self.last_update = Instant::now();
|
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.
|
// 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));
|
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;
|
return sprites;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ pub struct InputStatus {
|
||||||
pub key_left: bool,
|
pub key_left: bool,
|
||||||
pub key_right: bool,
|
pub key_right: bool,
|
||||||
pub key_thrust: bool,
|
pub key_thrust: bool,
|
||||||
|
pub key_guns: bool,
|
||||||
pub v_scroll: f32,
|
pub v_scroll: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ impl InputStatus {
|
||||||
key_left: false,
|
key_left: false,
|
||||||
key_right: false,
|
key_right: false,
|
||||||
key_thrust: false,
|
key_thrust: false,
|
||||||
|
key_guns: false,
|
||||||
v_scroll: 0.0,
|
v_scroll: 0.0,
|
||||||
scroll_speed: 10.0,
|
scroll_speed: 10.0,
|
||||||
}
|
}
|
||||||
|
@ -23,6 +25,7 @@ impl InputStatus {
|
||||||
self.key_left = false;
|
self.key_left = false;
|
||||||
self.key_right = false;
|
self.key_right = false;
|
||||||
self.key_thrust = false;
|
self.key_thrust = false;
|
||||||
|
self.key_guns = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_key(&mut self, state: &ElementState, key: &VirtualKeyCode) {
|
pub fn process_key(&mut self, state: &ElementState, key: &VirtualKeyCode) {
|
||||||
|
@ -31,6 +34,7 @@ impl InputStatus {
|
||||||
VirtualKeyCode::Left => self.key_left = down,
|
VirtualKeyCode::Left => self.key_left = down,
|
||||||
VirtualKeyCode::Right => self.key_right = down,
|
VirtualKeyCode::Right => self.key_right = down,
|
||||||
VirtualKeyCode::Up => self.key_thrust = 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::{
|
use crate::{
|
||||||
content::{self, ship::Engine},
|
content,
|
||||||
physics::PhysicsBody,
|
physics::PhysicsBody,
|
||||||
render::{Sprite, SpriteTexture, Spriteable, SubSprite},
|
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 struct Ship {
|
||||||
pub physicsbody: PhysicsBody,
|
pub physicsbody: PhysicsBody,
|
||||||
pub engines_on: bool,
|
pub controls: ShipControls,
|
||||||
|
|
||||||
sprite: SpriteTexture,
|
sprite: SpriteTexture,
|
||||||
size: f32,
|
size: f32,
|
||||||
engines: Vec<Engine>,
|
engines: Vec<content::Engine>,
|
||||||
|
guns: Vec<content::ShipGun>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ship {
|
impl Ship {
|
||||||
pub fn new(ct: &content::ship::Ship, pos: Point2<f32>) -> Self {
|
pub fn new(ct: &content::Ship, pos: Point2<f32>) -> Self {
|
||||||
Ship {
|
Ship {
|
||||||
physicsbody: PhysicsBody::new(pos),
|
physicsbody: PhysicsBody::new(pos),
|
||||||
sprite: SpriteTexture(ct.sprite.clone()),
|
sprite: SpriteTexture(ct.sprite.clone()),
|
||||||
size: ct.size,
|
size: ct.size,
|
||||||
engines: ct.engines.clone(),
|
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 {
|
impl Spriteable for Ship {
|
||||||
fn get_sprite(&self) -> Sprite {
|
fn get_sprite(&self) -> Sprite {
|
||||||
let engines = if self.engines_on {
|
let engines = if self.controls.thrust {
|
||||||
Some(
|
Some(
|
||||||
self.engines
|
self.engines
|
||||||
.iter()
|
.iter()
|
||||||
|
|
Loading…
Reference in New Issue