Compare commits

..

2 Commits

Author SHA1 Message Date
2fb395a8d4
Keep track of score and reset game after score
Client: only set direction on change
2022-11-04 13:00:54 +01:00
cd7a1f15a9
Added continuous reflection on top and lower border 2022-11-04 12:04:05 +01:00
2 changed files with 57 additions and 24 deletions

View File

@ -16,15 +16,13 @@ public struct PongGameState {
BallState = PongBallState.Initial, BallState = PongBallState.Initial,
Paddle1 = PongPaddleState.Initial, Paddle1 = PongPaddleState.Initial,
Paddle2 = PongPaddleState.Initial, Paddle2 = PongPaddleState.Initial,
Status = GameStatus.WaitingForPlayers, Status = GameStatus.WaitingForPlayers
WinnerLeft = null
}; };
public PongPaddleState Paddle1; public PongPaddleState Paddle1;
public PongPaddleState Paddle2; public PongPaddleState Paddle2;
public PongBallState BallState; public PongBallState BallState;
public GameStatus Status; public GameStatus Status;
public bool? WinnerLeft;
public static void Update(ref PongGameState state) { public static void Update(ref PongGameState state) {
if (state.Status is not GameStatus.InProgress) return; if (state.Status is not GameStatus.InProgress) return;
@ -32,15 +30,24 @@ public struct PongGameState {
PongPaddleState.Update(ref state.Paddle1); PongPaddleState.Update(ref state.Paddle1);
PongPaddleState.Update(ref state.Paddle2); PongPaddleState.Update(ref state.Paddle2);
PongBallState.Update(ref state.BallState); PongBallState.Update(ref state.BallState);
var ballX = state.BallState.Pos.X;
if (ballX is < 0 or > WIDTH) {
state.WinnerLeft = ballX < 0;
state.Status = GameStatus.Finished;
return;
}
Collide(in state.Paddle1, ref state.BallState, true); Collide(in state.Paddle1, ref state.BallState, true);
Collide(in state.Paddle2, ref state.BallState, false); Collide(in state.Paddle2, ref state.BallState, false);
switch (state.BallState.Pos.X) {
case > WIDTH:
AnnounceScore(ref state, ref state.Paddle1);
return;
case < 0:
AnnounceScore(ref state, ref state.Paddle2);
return;
}
}
private static void AnnounceScore(ref PongGameState state, ref PongPaddleState winner) {
winner.Score++;
state.Paddle1.ResetPosition();
state.Paddle2.ResetPosition();
state.BallState.ResetPosition();
} }
private static void Collide(in PongPaddleState paddle, ref PongBallState ballState, bool left) { private static void Collide(in PongPaddleState paddle, ref PongBallState ballState, bool left) {
@ -79,12 +86,24 @@ public struct PongGameState {
state.Pos.X += BALL_SPEED * dx; state.Pos.X += BALL_SPEED * dx;
state.Pos.Y -= BALL_SPEED * dy; state.Pos.Y -= BALL_SPEED * dy;
if (state.Pos.Y < BALL_RADIUS // If reflected from lower or upper border calculate continuous reflection
|| state.Pos.Y > HEIGHT - BALL_RADIUS) // This prevents the ball from temporarily glitching into paddles
if (state.Pos.Y < BALL_RADIUS) {
state.Pos.Y = 2 * BALL_RADIUS - state.Pos.Y;
state.BallAngle = 2 * MathF.PI - state.BallAngle; state.BallAngle = 2 * MathF.PI - state.BallAngle;
} else if (state.Pos.Y > HEIGHT - BALL_RADIUS) {
state.Pos.Y = 2 * (HEIGHT - BALL_RADIUS) - state.Pos.Y;
state.BallAngle = 2 * MathF.PI - state.BallAngle;
}
} }
public RectangleF GetCollider() => new(Pos.X - BALL_RADIUS, Pos.Y - BALL_RADIUS, 2 * BALL_RADIUS, 2 * BALL_RADIUS); public RectangleF GetCollider() => new(Pos.X - BALL_RADIUS, Pos.Y - BALL_RADIUS, 2 * BALL_RADIUS, 2 * BALL_RADIUS);
public void ResetPosition() {
BallAngle = 0.0f;
Pos.X = WIDTH / 2;
Pos.Y = HEIGHT / 2;
}
} }
public struct PongPaddleState { public struct PongPaddleState {
@ -92,19 +111,27 @@ public struct PongGameState {
public const float PADDLE_HALF_LENGTH = PADDLE_LENGTH / 2; public const float PADDLE_HALF_LENGTH = PADDLE_LENGTH / 2;
public const float PADDLE_WIDTH = PADDLE_LENGTH / 5; public const float PADDLE_WIDTH = PADDLE_LENGTH / 5;
public const float PADDLE_SPEED = 8; public const float PADDLE_SPEED = 8;
private const float PADDLE_INITIAL_HEIGHT = HEIGHT / 2;
public static readonly PongPaddleState Initial = new() { public static readonly PongPaddleState Initial = new() {
Score = 0,
Direction = PongPaddleDirection.Stop, Direction = PongPaddleDirection.Stop,
Height = HEIGHT / 2 Height = PADDLE_INITIAL_HEIGHT
}; };
public float Height; public float Height;
public PongPaddleDirection Direction; public PongPaddleDirection Direction;
public int Score;
public static void Update(ref PongPaddleState state) { public static void Update(ref PongPaddleState state) {
state.Height = Math.Clamp(state.Height - ((int)state.Direction) * PADDLE_SPEED, PADDLE_HALF_LENGTH, HEIGHT - PADDLE_HALF_LENGTH); state.Height = Math.Clamp(state.Height + ((int)state.Direction) * PADDLE_SPEED, PADDLE_HALF_LENGTH, HEIGHT - PADDLE_HALF_LENGTH);
} }
public RectangleF GetCollider(float x) => new(x - PADDLE_WIDTH / 2, Height - PADDLE_HALF_LENGTH, PADDLE_WIDTH, PADDLE_LENGTH); public RectangleF GetCollider(float x) => new(x - PADDLE_WIDTH / 2, Height - PADDLE_HALF_LENGTH, PADDLE_WIDTH, PADDLE_LENGTH);
public void ResetPosition() {
Direction = PongPaddleDirection.Stop;
Height = PADDLE_INITIAL_HEIGHT;
}
} }
} }

View File

@ -86,10 +86,6 @@ function movePaddle(direction) {
}); });
} }
function moveUp() { return movePaddle(-1); }
function stopPaddle() { return movePaddle(0); }
function moveDown() { return movePaddle(1); }
// Create the application helper and add its render target to the page // Create the application helper and add its render target to the page
let app = new PIXI.Application({ width: 1000, height: 500 }); let app = new PIXI.Application({ width: 1000, height: 500 });
getElement('canvas-container').appendChild(app.view); getElement('canvas-container').appendChild(app.view);
@ -124,18 +120,25 @@ connection.on("ReceiveGameState", function (state) {
const keyEvent = (function () { const keyEvent = (function () {
var upPressed = false; var upPressed = false;
var downPressed = false; var downPressed = false;
var direction = 0;
function setDirection(dir) {
if (direction != dir) {
direction = dir;
movePaddle(direction);
}
}
function moveUpdated() { function moveUpdated() {
if (upPressed == downPressed) stopPaddle(); if (upPressed == downPressed) setDirection(0);
else if (upPressed) moveUp(); else if (upPressed) setDirection(-1);
else if (downPressed) moveDown(); else if (downPressed) setDirection(1);
else console.error("unknown move!"); else console.error("unknown move!");
} }
function handler(event) { function handler(event) {
if (event.repeat) return; var pressed = event.type == "keydown";
if (event.path.indexOf(document.body) != 0) return; // only use key if it was pressed on empty space
var pressed = event.type == "keyup";
// W Key is 87, Up arrow is 87 // W Key is 87, Up arrow is 87
// S Key is 83, Down arrow is 40 // S Key is 83, Down arrow is 40
switch (event.keyCode) { switch (event.keyCode) {
@ -150,6 +153,9 @@ const keyEvent = (function () {
default: return; default: return;
} }
if (event.repeat) return;
if (event.path.indexOf(document.body) != 0) return; // only use key if it was pressed on empty space
event.preventDefault(); event.preventDefault();
moveUpdated(); moveUpdated();
} }