Created
December 22, 2015 21:48
-
-
Save LLBlumire/ea09341418803a527a10 to your computer and use it in GitHub Desktop.
A simple implementation of Pong, NOTE: Collision engine not written
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// piston_window is our game engine | |
extern crate piston_window; | |
// rand is for random number generation | |
extern crate rand; | |
// Lets us do custom implementations of the `+` function. | |
use std::ops::Add; | |
// Bring all of our game engine stuff into scope | |
use piston_window::*; | |
// Bring our randon number gerneration into scope | |
use rand::{Rng, thread_rng}; | |
// PI. Because PI | |
use std::f64::consts::PI; | |
fn main() { | |
// Our viewport | |
let mut viewport: [u32; 2] = [800, 600]; | |
// The game window | |
let window: PistonWindow = WindowSettings::new("My First Game", viewport).build().unwrap(); | |
// Our paddles | |
let mut paddles: [Paddle; 2] = build_paddles(viewport); | |
// The Ball | |
let mut ball = generate_ball(viewport); | |
// Poll events from our window, loading the window | |
for event in window { | |
// If it's a render event, do the following | |
if let Some(render) = event.render_args() { | |
// Draw to the screen | |
event.draw_2d(|c, g| { | |
// Clear the screen | |
clear([0.0, 0.0, 0.0, 1.0], g); | |
// For both our paddles | |
for paddle in paddles.iter() { | |
// Draw the paddle rectangle | |
rectangle([1.0; 4], | |
[0.0, 0.0, paddle.size[0], paddle.size[1]], | |
c.transform.trans( | |
paddle.center_coord.0 - paddle.size[0]/2.0, | |
paddle.center_coord.1 - paddle.size[1]/2.0), | |
g); | |
} | |
// Draw the ball rectangle | |
rectangle([1.0; 4], | |
[0.0, 0.0, ball.size[0], ball.size[1]], | |
c.transform.trans( | |
ball.center_coord.0 - ball.size[0]/2.0, | |
ball.center_coord.1 - ball.size[1]/2.0), | |
g); | |
}); | |
} | |
// If it's a key press event, do the following | |
if let Some(Button::Keyboard(key)) = event.press_args() { | |
// Check which key it is, change the movement variable accordingly | |
match key { | |
Key::A => paddles[0].left = true, | |
Key::D => paddles[0].right = true, | |
Key::J => paddles[1].left = true, | |
Key::L => paddles[1].right = true, | |
_ => {} | |
} | |
} | |
// If it's a key release event, do the following | |
if let Some(Button::Keyboard(key)) = event.release_args() { | |
// Check which key it is, change the movement variable accordingly | |
match key { | |
Key::A => paddles[0].left = false, | |
Key::D => paddles[0].right = false, | |
Key::J => paddles[1].left = false, | |
Key::L => paddles[1].right = false, | |
_ => {} | |
} | |
} | |
// If it's an update event, do the following | |
if let Some(update) = event.update_args() { | |
// Foe each of our paddles | |
for paddle in paddles.iter_mut() { | |
// Move the paddle 3/5ths of the way across the screen in the active key direction | |
// each second. | |
paddle.center_coord.0 += update.dt * | |
(viewport[0] as f64 * 3.0 / 5.0) * | |
(paddle.right as u8 as f64); | |
paddle.center_coord.0 -= update.dt * | |
(viewport[0] as f64 * 3.0 / 5.0) * | |
(paddle.left as u8 as f64); | |
} | |
// Move the ball half way across the screen each second | |
ball.center_coord = update.dt | |
ball.center_coord + (viewport[0]*0.5*ball.bearing.cos(), | |
viewport[1]*0.5*ball.bearing.sin()); | |
} | |
// If it's a resize event, do the following | |
if let Some(resize) = event.resize_args() { | |
// Resize the screen | |
viewport = resize; | |
// Reset the paddles | |
paddles = build_paddles(viewport); | |
// Reset the ball | |
ball = generate_ball(viewport); | |
} | |
} | |
} | |
/// Build a new paddle | |
fn build_paddles(viewport: [u32; 2]) -> [Paddle; 2] { | |
[Paddle::new(Point(viewport[0] as f64/2.0, viewport[1] as f64/10.0), viewport), | |
Paddle::new(Point(viewport[0] as f64/2.0, viewport[1] as f64 * 9.0 / 10.0), viewport)] | |
} | |
/// Generate a new ball | |
fn generate_ball(viewport: [u32; 2]) -> Ball { | |
Ball::new(viewport) | |
} | |
/// A point on the screen | |
struct Point(f64, f64); | |
impl Add<(f64, f64)> for Point { | |
type Output = Point; | |
/// Add a tuple to our point, Point(a, b) + (c, d) = Point(a+c, b+d) | |
fn add(self, rhs: (f64, f64)) -> Self::Output { | |
Point(self.0 + rhs.0, self.1 + rhs.1) | |
} | |
} | |
/// A paddle | |
struct Paddle { | |
center_coord: Point, | |
size: [f64; 2], | |
left: bool, | |
right: bool | |
} | |
impl Paddle { | |
/// Build a new paddle | |
fn new(center_coord: Point, viewport: [u32; 2]) -> Self { | |
Paddle { | |
center_coord: center_coord, | |
size: [(viewport[0] / 7) as f64, (viewport[1] / 20) as f64], | |
left: false, | |
right: false | |
} | |
} | |
} | |
/// the ball | |
struct Ball { | |
center_coord: Point, | |
size: [f64; 2], | |
bearing: f64 // Radians, Bearing | |
} | |
impl Ball { | |
/// Build a new ball | |
fn new(viewport: [u32; 2]) -> Self { | |
Ball { | |
center_coord: Point(viewport[0] as f64/2.0, viewport[1] as f64/2.0), | |
size: [viewport[0] as f64/50.0, viewport[1] as f64/50.0], | |
bearing: thread_rng().gen_range(0.0, PI * 2.0) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment