Compare commits
2 Commits
f728240db9
...
2fb395a8d4
Author | SHA1 | Date | |
---|---|---|---|
2fb395a8d4 | |||
cd7a1f15a9 |
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user