Big bunch of development
This commit is contained in:
		
							
								
								
									
										2
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -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); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										33
									
								
								src/game/bullet.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/game/bullet.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
|     } | ||||
| } | ||||
							
								
								
									
										52
									
								
								src/game/camera.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/game/camera.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||
|         } | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										78
									
								
								src/game/controls.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/game/controls.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
|     } | ||||
| } | ||||
							
								
								
									
										61
									
								
								src/game/map.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/game/map.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										108
									
								
								src/game/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/game/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -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); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										58
									
								
								src/game/ship.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/game/ship.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user