Added restart, text display and score, updated ReadMe

This commit is contained in:
2022-05-09 16:02:20 +02:00
parent 43afd03fc4
commit 9601dd1360
4 changed files with 120 additions and 58 deletions
+6
View File
@@ -30,6 +30,12 @@ brew install sdl2
export LIBRARY_PATH="$LIBRARY_PATH:/usr/local/lib" export LIBRARY_PATH="$LIBRARY_PATH:/usr/local/lib"
``` ```
### Run the game
```
cargo run --release
```
You can also just enter ``` cargo build --release ```` and then start the binary from target/src
## How to play ? ## How to play ?
This is a local multiplayer game, so two players can play using the same keyboard, player 1 uses 'w' and 's' and so player 2 uses the arrow keys. This is a local multiplayer game, so two players can play using the same keyboard, player 1 uses 'w' and 's' and so player 2 uses the arrow keys.
Binary file not shown.
Binary file not shown.
+63 -7
View File
@@ -5,6 +5,7 @@ use tetra::input::{self, Key};
use tetra::math::Vec2; use tetra::math::Vec2;
use tetra::window; use tetra::window;
use tetra::{Context, ContextBuilder, State}; use tetra::{Context, ContextBuilder, State};
use tetra::graphics::text::*;
const WINDOW_WIDTH:f32 = 640.0; const WINDOW_WIDTH:f32 = 640.0;
const WINDOW_HEIGHT:f32 = 480.0; const WINDOW_HEIGHT:f32 = 480.0;
@@ -12,6 +13,7 @@ const PADDLE_SPEED:f32 = 8.0;
const BALL_SPEED:f32 = 5.0; const BALL_SPEED:f32 = 5.0;
const PADDLE_SPIN: f32 = 4.0; const PADDLE_SPIN: f32 = 4.0;
const BALL_ACC:f32 = 0.05; const BALL_ACC:f32 = 0.05;
const SCORE_LOCATION:Vec2<f32> = Vec2::new(16.0,16.0);
struct Entity { struct Entity {
texture: Texture, texture: Texture,
@@ -51,11 +53,18 @@ impl Entity{
) )
} }
} }
enum GameStatus {
Playing,
Pause,
Ended,
}
struct GameState { struct GameState {
player1: Entity, player1: Entity,
player2: Entity, player2: Entity,
ball: Entity, ball: Entity,
score_text: Text,
score:i32,
state:GameStatus
} }
impl GameState{ impl GameState{
@@ -74,27 +83,52 @@ impl GameState{
let ball_speed = Vec2::new(-BALL_SPEED,0.0); let ball_speed = Vec2::new(-BALL_SPEED,0.0);
let vector_text = Text::new(
format!("Score : {}",0),
Font::vector(ctx, "./resources/Roboto-Regular.ttf", 16.0)?,
);
Ok(GameState { Ok(GameState {
player1: Entity::new(player1_texture,player1_position), player1: Entity::new(player1_texture,player1_position),
player2: Entity::new(player2_texture,player2_position), player2: Entity::new(player2_texture,player2_position),
ball: Entity::with_velocity(ball_texture,ball_position,ball_speed), ball: Entity::with_velocity(ball_texture,ball_position,ball_speed),
score_text: vector_text,
score:0,
state:GameStatus::Pause,
}) })
} }
fn restart(&mut self){
self.player1.position = Vec2::new(16.0,(WINDOW_HEIGHT - self.player1.texture.height() as f32) / 2.0);
self.player2.position = Vec2::new(WINDOW_WIDTH - self.player2.texture.width() as f32 -16.0,(WINDOW_HEIGHT - self.player2.texture.height() as f32) / 2.0);
self.ball.position = Vec2::new(WINDOW_WIDTH / 2.0 - (self.ball.texture.width() as f32 / 2.0) as f32,WINDOW_HEIGHT / 2.0 - (self.ball.texture.height() as f32 / 2.0) as f32);
self.ball.velocity = Vec2::new(-BALL_SPEED,0.0);
self.score = 0;
self.score_text.set_content(format!("Score : {}",0));
self.state = GameStatus::Pause;
}
} }
impl State for GameState{ impl State for GameState{
fn draw(&mut self, ctx: &mut Context) -> tetra::Result { fn draw(&mut self, ctx: &mut Context) -> tetra::Result {
graphics::clear(ctx,Color::hex("#CCCCCC")); graphics::clear(ctx,Color::hex("#333333"));
self.player1.texture.draw(ctx,self.player1.position); self.player1.texture.draw(ctx,self.player1.position);
self.player2.texture.draw(ctx,self.player2.position); self.player2.texture.draw(ctx,self.player2.position);
self.ball.texture.draw(ctx,self.ball.position); self.ball.texture.draw(ctx,self.ball.position);
self.score_text.draw(ctx, SCORE_LOCATION);
Ok(()) Ok(())
} }
fn update(&mut self,ctx: &mut Context) -> tetra::Result{ fn update(&mut self,ctx: &mut Context) -> tetra::Result{
//Player 1 movements //Player 1 movements
match self.state {
GameStatus::Playing =>{
if input::is_key_down(ctx, Key::W) && self.player1.position.y as i32 > 0{ if input::is_key_down(ctx, Key::W) && self.player1.position.y as i32 > 0{
self.player1.position.y -= PADDLE_SPEED; self.player1.position.y -= PADDLE_SPEED;
} }
@@ -132,6 +166,10 @@ impl State for GameState{
let offset = (paddle.centre().y - self.ball.centre().y) / paddle.height(); let offset = (paddle.centre().y - self.ball.centre().y) / paddle.height();
self.ball.velocity.y += PADDLE_SPIN * -offset; self.ball.velocity.y += PADDLE_SPIN * -offset;
//increase the score as
self.score += 1;
self.score_text.set_content(format!("Score : {}",self.score));
} }
self.ball.position += self.ball.velocity; self.ball.position += self.ball.velocity;
@@ -142,20 +180,38 @@ impl State for GameState{
} }
//check winner //check winner
if self.ball.position.x <= 0.0{ if self.ball.position.x <= 0.0{
window::quit(ctx); //window::quit(ctx);
println!("Player 2 won!"); self.score_text.set_content("Player 2 Won!\nPress Enter to play again");
self.state = GameStatus::Ended;
} }
if self.ball.position.x + self.ball.width() >= WINDOW_WIDTH{ if self.ball.position.x + self.ball.width() >= WINDOW_WIDTH{
window::quit(ctx); //window::quit(ctx);
println!("Player 1 won!"); self.score_text.set_content("Player 2 Won!\nPress Enter to play again");
self.state = GameStatus::Ended;
}
}
GameStatus::Pause =>{
self.score_text.set_content("Remember \nPlayer 1 uses 'w' and 's'\nPlayer 2 uses up and down arrow keys\nPress Enter to start the game");
if input::is_key_down(ctx, Key::Enter){
self.state = GameStatus::Playing;
}
}
GameStatus::Ended =>{
if input::is_key_down(ctx, Key::Enter){
self.restart();
println!("DEBUG: game restarted");
}
}
} }
Ok(()) Ok(())
} }
} }
fn main() -> tetra::Result{ fn main() -> tetra::Result{
ContextBuilder::new("Pong",WINDOW_WIDTH as i32,WINDOW_HEIGHT as i32) ContextBuilder::new("Rusty Pong",WINDOW_WIDTH as i32,WINDOW_HEIGHT as i32)
.quit_on_escape(true) .quit_on_escape(true)
.build()? .build()?
.run(GameState::new) .run(GameState::new)