Big bunch of development
parent
f530b31d98
commit
8e3521fe56
|
@ -1,5 +1,5 @@
|
|||
[root]
|
||||
name = "getting-started-spinning-square"
|
||||
name = "rust-pilot"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"piston_window 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
[package]
|
||||
|
||||
name = "getting-started-spinning-square"
|
||||
name = "rust-pilot"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Levi Pearson <levipearson@gmail.com>"
|
||||
]
|
||||
|
||||
[[bin]]
|
||||
name = "spinning-square"
|
||||
name = "rust-pilot"
|
||||
|
||||
[dependencies]
|
||||
piston_window = "0.40.0"
|
||||
|
|
339
src/game.rs
339
src/game.rs
|
@ -1,339 +0,0 @@
|
|||
use piston_window::*;
|
||||
use piston_window::math::*;
|
||||
use piston_window::draw_state::Blend;
|
||||
use std::f64::consts::*;
|
||||
|
||||
static TURN_RATE: Scalar = 4.0;
|
||||
static THRUST_RATE: Scalar = 4.0;
|
||||
|
||||
struct Controls {
|
||||
up_d: bool,
|
||||
down_d: bool,
|
||||
left_d: bool,
|
||||
right_d: bool,
|
||||
fire: bool
|
||||
}
|
||||
|
||||
impl Controls {
|
||||
fn new() -> Self {
|
||||
Controls {
|
||||
up_d: false, down_d: false, left_d: false, right_d: false,
|
||||
fire: false
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, inp: Input) {
|
||||
match inp {
|
||||
Input::Press(b) => {
|
||||
match b {
|
||||
Button::Keyboard(Key::Up) => { self.up_d = true; }
|
||||
Button::Keyboard(Key::Down) => { self.down_d = true; }
|
||||
Button::Keyboard(Key::Left) => { self.left_d = true; }
|
||||
Button::Keyboard(Key::Right) => { self.right_d = true; }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Input::Release(b) => {
|
||||
match b {
|
||||
Button::Keyboard(Key::Up) => { self.up_d = false; }
|
||||
Button::Keyboard(Key::Down) => { self.down_d = false; }
|
||||
Button::Keyboard(Key::Left) => { self.left_d = false; }
|
||||
Button::Keyboard(Key::Right) => { self.right_d = false; }
|
||||
Button::Keyboard(Key::Space) => { self.fire = true; }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn velocity_change(&self, rot: Scalar, dt: Scalar) -> Vec2d {
|
||||
let thrust = if self.up_d {
|
||||
THRUST_RATE * dt
|
||||
} else if self.down_d {
|
||||
-THRUST_RATE * dt
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
if thrust != 0.0 {
|
||||
[rot.cos() * thrust, rot.sin() * thrust]
|
||||
} else {
|
||||
[0.0, 0.0]
|
||||
}
|
||||
}
|
||||
|
||||
fn rotation_change(&self, dt: Scalar) -> Scalar {
|
||||
if self.left_d {
|
||||
-TURN_RATE * dt
|
||||
} else if self.right_d {
|
||||
TURN_RATE * dt
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
fn fire_check(&self) -> bool {
|
||||
self.fire
|
||||
}
|
||||
}
|
||||
|
||||
const BULLET_POLY: &'static [[Scalar; 2]] = &[
|
||||
[-1.5, -1.5],
|
||||
[-1.5, 1.5],
|
||||
[1.5, 1.5],
|
||||
[1.5, -1.5]
|
||||
];
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Bullet {
|
||||
position: Vec2d,
|
||||
velocity: Vec2d,
|
||||
ttl: Scalar,
|
||||
geometry: &'static [[Scalar; 2]]
|
||||
}
|
||||
|
||||
const SHIP_POLY: &'static [[Scalar; 2]] = &[
|
||||
[-10.0, -8.0],
|
||||
[10.0, 0.0],
|
||||
[-10.0, 8.0]
|
||||
];
|
||||
|
||||
impl Bullet {
|
||||
pub fn new(loc: Vec2d, velocity: Vec2d, ttl: Scalar) -> Self {
|
||||
Bullet {
|
||||
position: loc,
|
||||
velocity: velocity,
|
||||
ttl: ttl,
|
||||
geometry: BULLET_POLY
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, dt: Scalar) -> Scalar {
|
||||
self.position = add(self.position, self.velocity);
|
||||
self.ttl -= dt;
|
||||
self.ttl
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Ship {
|
||||
rotation: Scalar,
|
||||
position: Vec2d,
|
||||
velocity: Vec2d,
|
||||
geometry: &'static [[Scalar; 2]]
|
||||
}
|
||||
|
||||
impl Ship {
|
||||
pub fn new(loc: Vec2d) -> Self {
|
||||
Ship {
|
||||
rotation: -FRAC_PI_2,
|
||||
position: loc,
|
||||
velocity: [0.0, 0.0],
|
||||
geometry: SHIP_POLY
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, dv: Vec2d, dr: Scalar, map: &Map) {
|
||||
self.rotation += dr;
|
||||
self.velocity = add(self.velocity, dv);
|
||||
self.position = add(self.position, self.velocity);
|
||||
if self.position[0] > map.width {
|
||||
self.velocity[0] = 0.0;
|
||||
self.position[0] = map.width;
|
||||
}
|
||||
if self.position[0] < 0.0 {
|
||||
self.velocity[0] = 0.0;
|
||||
self.position[0] = 0.0;
|
||||
}
|
||||
if self.position[1] > map.height {
|
||||
self.velocity[1] = 0.0;
|
||||
self.position[1] = map.height;
|
||||
}
|
||||
if self.position[1] < 0.0 {
|
||||
self.velocity[1] = 0.0;
|
||||
self.position[1] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trajectory(&self) -> (Vec2d, Vec2d, Vec2d) {
|
||||
let nose = self.geometry[1];
|
||||
let rot = rotate_radians(self.rotation);
|
||||
let trans = translate(self.position);
|
||||
let tmat = multiply(trans, rot);
|
||||
(transform_pos(tmat, nose), transform_vec(rot, [1.0,0.0]), self.velocity)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Camera {
|
||||
position: Vec2d,
|
||||
height: Scalar,
|
||||
width: Scalar
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
pub fn new(pos: Vec2d, width: Scalar, height: Scalar) -> Self {
|
||||
Camera {
|
||||
position: pos,
|
||||
width: width,
|
||||
height: height
|
||||
}
|
||||
}
|
||||
|
||||
pub fn follow(&mut self, pos: Vec2d, map: &Map) {
|
||||
let dp = sub(pos, self.position);
|
||||
let xmargin = self.width / 4.0;
|
||||
let ymargin = self.height / 4.0;
|
||||
|
||||
if dp[0] > xmargin {
|
||||
self.position[0] += dp[0] - xmargin;
|
||||
}
|
||||
if dp[0] < -xmargin {
|
||||
self.position[0] += dp[0] + xmargin;
|
||||
}
|
||||
if dp[1] > ymargin {
|
||||
self.position[1] += dp[1] - ymargin;
|
||||
}
|
||||
if dp[1] < -ymargin {
|
||||
self.position[1] += dp[1] + ymargin;
|
||||
}
|
||||
|
||||
if self.position[0] + self.width / 2.0 > map.width {
|
||||
self.position[0] = map.width - self.width / 2.0;
|
||||
}
|
||||
if self.position[0] - self.width / 2.0 < 0.0 {
|
||||
self.position[0] = 0.0 + self.width / 2.0;
|
||||
}
|
||||
if self.position[1] + self.height / 2.0 > map.height {
|
||||
self.position[1] = map.height - self.height / 2.0;
|
||||
}
|
||||
if self.position[1] - self.height / 2.0 < 0.0 {
|
||||
self.position[1] = 0.0 + self.height / 2.0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Map {
|
||||
width: Scalar,
|
||||
height: Scalar
|
||||
}
|
||||
|
||||
impl Map {
|
||||
pub fn new(width: Scalar, height: Scalar) -> Self {
|
||||
Map { width: width, height: height }
|
||||
}
|
||||
pub fn center(&self) -> Vec2d {
|
||||
[self.width / 2.0, self.height / 2.0]
|
||||
}
|
||||
pub fn draw_grid<G>(&self, cpos: Vec2d,
|
||||
cw: Scalar, ch: Scalar,
|
||||
draw_state: &DrawState,
|
||||
transform: Matrix2d, g: &mut G)
|
||||
where G: Graphics {
|
||||
|
||||
const GREEN: [f32; 4] = [0.0, 1.0, 0.0, 0.05];
|
||||
|
||||
let minx = cpos[0] - cw / 2.0;
|
||||
let miny = cpos[1] - ch / 2.0;
|
||||
|
||||
let xcount = (cw / 100.0).ceil() as u32 + 2;
|
||||
let ycount = (ch / 100.0).ceil() as u32 + 2;
|
||||
|
||||
let firstx = (minx / 100.0).trunc() * 100.0;
|
||||
let firsty = (miny / 100.0).trunc() * 100.0;
|
||||
|
||||
for x in 0..xcount {
|
||||
let sy = cpos[1] - ch;
|
||||
let ey = cpos[1] + ch;
|
||||
let lx = firstx + (100.0 * x as Scalar);
|
||||
Line::new(GREEN, 1.0)
|
||||
.draw([lx-cpos[0], sy-cpos[1], lx-cpos[0], ey-cpos[1]],
|
||||
draw_state, transform, g);
|
||||
}
|
||||
for y in 0..ycount {
|
||||
let sx = cpos[0] - cw;
|
||||
let ex = cpos[0] + cw;
|
||||
let ly = firsty + (100.0 * y as Scalar);
|
||||
Line::new(GREEN, 1.0)
|
||||
.draw([sx-cpos[0], ly-cpos[1], ex-cpos[0], ly-cpos[1]],
|
||||
draw_state, transform, g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Game {
|
||||
player: Ship,
|
||||
bullets: Vec<Bullet>,
|
||||
map: Map,
|
||||
camera: Camera,
|
||||
controls: Controls
|
||||
}
|
||||
|
||||
impl Game {
|
||||
pub fn new(width: Scalar, height: Scalar) -> Self {
|
||||
let new_map = Map::new(10000.0, 10000.0);
|
||||
let center = new_map.center();
|
||||
Game {
|
||||
player: Ship::new(center),
|
||||
bullets: Vec::new(),
|
||||
map: new_map,
|
||||
camera: Camera::new(center, width, height),
|
||||
controls: Controls::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(&mut self, args: RenderArgs, w: PistonWindow) {
|
||||
const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];
|
||||
const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
|
||||
const RED: [f32; 4] = [1.0, 0.0, 0.0, 1.0];
|
||||
|
||||
let rotation = self.player.rotation;
|
||||
let cpos = sub(self.player.position, self.camera.position);
|
||||
|
||||
let (x, y) = ((args.width / 2) as Scalar + cpos[0],
|
||||
(args.height / 2) as Scalar + cpos[1]);
|
||||
|
||||
w.draw_2d(|c, gl| {
|
||||
let transform = c.transform
|
||||
.trans(x, y)
|
||||
.rot_rad(rotation);
|
||||
let cp = self.camera.position;
|
||||
let cw = self.camera.width;
|
||||
let ch = self.camera.height;
|
||||
let ct = c.transform.trans((args.width / 2) as Scalar,
|
||||
(args.height / 2) as Scalar);
|
||||
let ds = c.draw_state.blend(Blend::Alpha);
|
||||
|
||||
clear(BLACK, gl);
|
||||
self.map.draw_grid(cp, cw, ch, &ds, ct, gl);
|
||||
for bullet in self.bullets.iter() {
|
||||
let bpos = sub(bullet.position, self.camera.position);
|
||||
let (bx, by) = ((args.width / 2) as Scalar + bpos[0],
|
||||
(args.height / 2) as Scalar + bpos[1]);
|
||||
let btrans = c.transform.trans(bx, by);
|
||||
Polygon::new(WHITE).draw(bullet.geometry, &ds, btrans, gl);
|
||||
}
|
||||
Polygon::new(RED).draw(self.player.geometry, &ds, transform, gl);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn update(&mut self, args: UpdateArgs) {
|
||||
let dv = self.controls.velocity_change(self.player.rotation, args.dt);
|
||||
let dr = self.controls.rotation_change(args.dt);
|
||||
let firing = self.controls.fire_check();
|
||||
|
||||
self.player.update(dv, dr, &self.map);
|
||||
for bullet in self.bullets.iter_mut() { bullet.update(args.dt); }
|
||||
self.bullets.retain(|&ref bullet| bullet.ttl > 0.0);
|
||||
if firing {
|
||||
let (nose, dir, vel) = self.player.trajectory();
|
||||
let bul = Bullet::new(nose, add(vel,mul_scalar(dir, 3.0)), 2.0);
|
||||
self.bullets.push(bul);
|
||||
self.controls.fire = false;
|
||||
}
|
||||
self.camera.follow(self.player.position, &self.map);
|
||||
}
|
||||
|
||||
pub fn input(&mut self, inp: Input) {
|
||||
self.controls.update(inp);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
use piston_window::math::*;
|
||||
|
||||
const BULLET_POLY: &'static [[Scalar; 2]] = &[
|
||||
[-1.5, -1.5],
|
||||
[-1.5, 1.5],
|
||||
[1.5, 1.5],
|
||||
[1.5, -1.5]
|
||||
];
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Bullet {
|
||||
pub position: Vec2d,
|
||||
pub velocity: Vec2d,
|
||||
pub ttl: Scalar,
|
||||
pub geometry: &'static [[Scalar; 2]]
|
||||
}
|
||||
|
||||
impl Bullet {
|
||||
pub fn new(loc: Vec2d, velocity: Vec2d, ttl: Scalar) -> Self {
|
||||
Bullet {
|
||||
position: loc,
|
||||
velocity: velocity,
|
||||
ttl: ttl,
|
||||
geometry: BULLET_POLY
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, dt: Scalar) -> Scalar {
|
||||
self.position = add(self.position, self.velocity);
|
||||
self.ttl -= dt;
|
||||
self.ttl
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
use piston_window::math::*;
|
||||
|
||||
use super::map::Map;
|
||||
|
||||
pub struct Camera {
|
||||
pub position: Vec2d,
|
||||
pub height: Scalar,
|
||||
pub width: Scalar
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
pub fn new(pos: Vec2d, width: Scalar, height: Scalar) -> Self {
|
||||
Camera {
|
||||
position: pos,
|
||||
width: width,
|
||||
height: height
|
||||
}
|
||||
}
|
||||
|
||||
pub fn follow(&mut self, pos: Vec2d, map: &Map) {
|
||||
let dp = sub(pos, self.position);
|
||||
let xmargin = self.width / 4.0;
|
||||
let ymargin = self.height / 4.0;
|
||||
|
||||
if dp[0] > xmargin {
|
||||
self.position[0] += dp[0] - xmargin;
|
||||
}
|
||||
if dp[0] < -xmargin {
|
||||
self.position[0] += dp[0] + xmargin;
|
||||
}
|
||||
if dp[1] > ymargin {
|
||||
self.position[1] += dp[1] - ymargin;
|
||||
}
|
||||
if dp[1] < -ymargin {
|
||||
self.position[1] += dp[1] + ymargin;
|
||||
}
|
||||
|
||||
if self.position[0] + self.width / 2.0 > map.width {
|
||||
self.position[0] = map.width - self.width / 2.0;
|
||||
}
|
||||
if self.position[0] - self.width / 2.0 < 0.0 {
|
||||
self.position[0] = 0.0 + self.width / 2.0;
|
||||
}
|
||||
if self.position[1] + self.height / 2.0 > map.height {
|
||||
self.position[1] = map.height - self.height / 2.0;
|
||||
}
|
||||
if self.position[1] - self.height / 2.0 < 0.0 {
|
||||
self.position[1] = 0.0 + self.height / 2.0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
use piston_window::*;
|
||||
use piston_window::math::*;
|
||||
|
||||
static TURN_RATE: Scalar = 4.0;
|
||||
static THRUST_RATE: Scalar = 4.0;
|
||||
|
||||
pub struct Controls {
|
||||
up_d: bool,
|
||||
down_d: bool,
|
||||
left_d: bool,
|
||||
right_d: bool,
|
||||
fire: bool
|
||||
}
|
||||
|
||||
impl Controls {
|
||||
pub fn new() -> Self {
|
||||
Controls {
|
||||
up_d: false, down_d: false, left_d: false, right_d: false,
|
||||
fire: false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, inp: Input) {
|
||||
match inp {
|
||||
Input::Press(b) => {
|
||||
match b {
|
||||
Button::Keyboard(Key::Up) => { self.up_d = true; }
|
||||
Button::Keyboard(Key::Down) => { self.down_d = true; }
|
||||
Button::Keyboard(Key::Left) => { self.left_d = true; }
|
||||
Button::Keyboard(Key::Right) => { self.right_d = true; }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Input::Release(b) => {
|
||||
match b {
|
||||
Button::Keyboard(Key::Up) => { self.up_d = false; }
|
||||
Button::Keyboard(Key::Down) => { self.down_d = false; }
|
||||
Button::Keyboard(Key::Left) => { self.left_d = false; }
|
||||
Button::Keyboard(Key::Right) => { self.right_d = false; }
|
||||
Button::Keyboard(Key::Space) => { self.fire = true; }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn velocity_change(&self, rot: Scalar, dt: Scalar) -> Vec2d {
|
||||
let thrust = if self.up_d {
|
||||
THRUST_RATE * dt
|
||||
} else if self.down_d {
|
||||
-THRUST_RATE * dt
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
if thrust != 0.0 {
|
||||
[rot.cos() * thrust, rot.sin() * thrust]
|
||||
} else {
|
||||
[0.0, 0.0]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rotation_change(&self, dt: Scalar) -> Scalar {
|
||||
if self.left_d {
|
||||
-TURN_RATE * dt
|
||||
} else if self.right_d {
|
||||
TURN_RATE * dt
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fire_check(&mut self) -> bool {
|
||||
let firing = self.fire;
|
||||
self.fire = false;
|
||||
firing
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
use piston_window::*;
|
||||
use piston_window::math::*;
|
||||
|
||||
const GREEN: [f32; 4] = [0.0, 1.0, 0.0, 0.05];
|
||||
|
||||
pub struct Map {
|
||||
pub width: Scalar,
|
||||
pub height: Scalar
|
||||
}
|
||||
|
||||
impl Map {
|
||||
pub fn new(width: Scalar, height: Scalar) -> Self {
|
||||
Map { width: width, height: height }
|
||||
}
|
||||
|
||||
pub fn center(&self) -> Vec2d {
|
||||
[self.width / 2.0, self.height / 2.0]
|
||||
}
|
||||
|
||||
pub fn draw_grid<G>(&self,
|
||||
cam_pos: Vec2d,
|
||||
cam_width: Scalar,
|
||||
cam_height: Scalar,
|
||||
draw_state: &DrawState,
|
||||
transform: Matrix2d,
|
||||
g: &mut G)
|
||||
where G: Graphics
|
||||
{
|
||||
|
||||
let xcount = (cam_width / 100.0).ceil() as u32 + 2;
|
||||
let ycount = (cam_height / 100.0).ceil() as u32 + 2;
|
||||
|
||||
let min_x = cam_pos[0] - cam_width / 2.0;
|
||||
let min_y = cam_pos[1] - cam_height / 2.0;
|
||||
|
||||
let first_x = (min_x / 100.0).trunc() * 100.0;
|
||||
let first_y = (min_y / 100.0).trunc() * 100.0;
|
||||
|
||||
let start_y = cam_pos[1] - cam_height;
|
||||
let end_y = cam_pos[1] + cam_height;
|
||||
for x in 0..xcount {
|
||||
let line_x = first_x + (100.0 * x as Scalar);
|
||||
let p1 = sub([line_x, start_y], cam_pos);
|
||||
let p2 = sub([line_x, end_y], cam_pos);
|
||||
Line::new(GREEN, 1.0)
|
||||
.draw([p1[0], p1[1], p2[0], p2[1]],
|
||||
draw_state, transform, g);
|
||||
}
|
||||
|
||||
let start_x = cam_pos[0] - cam_width;
|
||||
let end_x = cam_pos[0] + cam_width;
|
||||
for y in 0..ycount {
|
||||
let line_y = first_y + (100.0 * y as Scalar);
|
||||
let p1 = sub([start_x, line_y], cam_pos);
|
||||
let p2 = sub([end_x, line_y], cam_pos);
|
||||
Line::new(GREEN, 1.0)
|
||||
.draw([p1[0], p1[1], p2[0], p2[1]],
|
||||
draw_state, transform, g);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
mod controls;
|
||||
mod bullet;
|
||||
mod ship;
|
||||
mod camera;
|
||||
mod map;
|
||||
|
||||
use piston_window::*;
|
||||
use piston_window::math::*;
|
||||
use piston_window::draw_state::Blend;
|
||||
|
||||
use self::ship::Ship;
|
||||
use self::bullet::Bullet;
|
||||
use self::camera::Camera;
|
||||
use self::map::Map;
|
||||
use self::controls::Controls;
|
||||
|
||||
const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];
|
||||
const RED: [f32; 4] = [1.0, 0.0, 0.0, 1.0];
|
||||
const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
|
||||
|
||||
pub struct Game {
|
||||
player: Ship,
|
||||
bullets: Vec<Bullet>,
|
||||
map: Map,
|
||||
camera: Camera,
|
||||
pub controls: Controls
|
||||
}
|
||||
|
||||
fn draw_background<G>(g: &mut G) where G: Graphics {
|
||||
clear(BLACK, g);
|
||||
}
|
||||
|
||||
fn draw_player<G>(player: &Ship, ds: &DrawState, trans: Matrix2d, g: &mut G)
|
||||
where G: Graphics {
|
||||
|
||||
let trans = trans
|
||||
.append_transform(translate(player.position))
|
||||
.rot_rad(player.rotation);
|
||||
Polygon::new(RED).draw(player.geometry, ds, trans, g);
|
||||
}
|
||||
|
||||
fn draw_bullet<G>(bullet: &Bullet, ds: &DrawState, trans: Matrix2d, g: &mut G)
|
||||
where G: Graphics {
|
||||
|
||||
let trans = trans
|
||||
.append_transform(translate(bullet.position));
|
||||
Polygon::new(WHITE).draw(bullet.geometry, &ds, trans, g);
|
||||
}
|
||||
|
||||
impl Game {
|
||||
pub fn new(width: Scalar, height: Scalar) -> Self {
|
||||
let new_map = Map::new(10000.0, 10000.0);
|
||||
let center = new_map.center();
|
||||
Game {
|
||||
player: Ship::new(center),
|
||||
bullets: Vec::new(),
|
||||
map: new_map,
|
||||
camera: Camera::new(center, width, height),
|
||||
controls: Controls::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(&mut self, args: RenderArgs, w: PistonWindow) {
|
||||
|
||||
w.draw_2d(|context, gl| {
|
||||
draw_background(gl);
|
||||
|
||||
let ds = context.draw_state.blend(Blend::Alpha);
|
||||
|
||||
let ct = context.transform.trans((args.width / 2) as Scalar,
|
||||
(args.height / 2) as Scalar);
|
||||
|
||||
let cam_pos = self.camera.position;
|
||||
let cam_width = self.camera.width;
|
||||
let cam_height = self.camera.height;
|
||||
|
||||
self.map.draw_grid(cam_pos, cam_width, cam_height, &ds, ct, gl);
|
||||
|
||||
let cam_trans = ct.append_transform(translate(mul_scalar(cam_pos, -1.0)));
|
||||
|
||||
for bullet in self.bullets.iter() {
|
||||
draw_bullet(&bullet, &ds, cam_trans, gl);
|
||||
}
|
||||
|
||||
draw_player(&self.player, &ds, cam_trans, gl);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn update(&mut self, args: UpdateArgs) {
|
||||
let dv = self.controls.velocity_change(self.player.rotation, args.dt);
|
||||
let dr = self.controls.rotation_change(args.dt);
|
||||
let firing = self.controls.fire_check();
|
||||
|
||||
self.player.update(dv, dr, &self.map);
|
||||
for bullet in self.bullets.iter_mut() { bullet.update(args.dt); }
|
||||
self.bullets.retain(|&ref bullet| bullet.ttl > 0.0);
|
||||
if firing {
|
||||
let (nose, dir, vel) = self.player.trajectory();
|
||||
let bul = Bullet::new(nose, add(vel,mul_scalar(dir, 3.0)), 2.0);
|
||||
self.bullets.push(bul);
|
||||
}
|
||||
self.camera.follow(self.player.position, &self.map);
|
||||
}
|
||||
|
||||
pub fn input(&mut self, inp: Input) {
|
||||
self.controls.update(inp);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
use piston_window::math::*;
|
||||
use std::f64::consts::*;
|
||||
|
||||
use super::map::Map;
|
||||
|
||||
const SHIP_POLY: &'static [[Scalar; 2]] = &[
|
||||
[-10.0, -8.0],
|
||||
[10.0, 0.0],
|
||||
[-10.0, 8.0]
|
||||
];
|
||||
|
||||
pub struct Ship {
|
||||
pub rotation: Scalar,
|
||||
pub position: Vec2d,
|
||||
pub velocity: Vec2d,
|
||||
pub geometry: &'static [[Scalar; 2]]
|
||||
}
|
||||
|
||||
impl Ship {
|
||||
pub fn new(loc: Vec2d) -> Self {
|
||||
Ship {
|
||||
rotation: -FRAC_PI_2,
|
||||
position: loc,
|
||||
velocity: [0.0, 0.0],
|
||||
geometry: SHIP_POLY
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, dv: Vec2d, dr: Scalar, map: &Map) {
|
||||
self.rotation += dr;
|
||||
self.velocity = add(self.velocity, dv);
|
||||
self.position = add(self.position, self.velocity);
|
||||
if self.position[0] > map.width {
|
||||
self.velocity[0] = 0.0;
|
||||
self.position[0] = map.width;
|
||||
}
|
||||
if self.position[0] < 0.0 {
|
||||
self.velocity[0] = 0.0;
|
||||
self.position[0] = 0.0;
|
||||
}
|
||||
if self.position[1] > map.height {
|
||||
self.velocity[1] = 0.0;
|
||||
self.position[1] = map.height;
|
||||
}
|
||||
if self.position[1] < 0.0 {
|
||||
self.velocity[1] = 0.0;
|
||||
self.position[1] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trajectory(&self) -> (Vec2d, Vec2d, Vec2d) {
|
||||
let nose = self.geometry[1];
|
||||
let rot = rotate_radians(self.rotation);
|
||||
let trans = translate(self.position);
|
||||
let tmat = multiply(trans, rot);
|
||||
(transform_pos(tmat, nose), transform_vec(rot, [1.0,0.0]), self.velocity)
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@ const YDIM: u32 = 600;
|
|||
|
||||
fn main() {
|
||||
let window: PistonWindow = WindowSettings::new(
|
||||
"spinning-square",
|
||||
"rust-pilot",
|
||||
[XDIM, YDIM]
|
||||
)
|
||||
.exit_on_esc(true)
|
||||
|
|
Loading…
Reference in New Issue