feat(pong): made changes to allow local play
This commit is contained in:
parent
9947970f63
commit
4ec44420db
5 changed files with 66 additions and 11 deletions
|
|
@ -15,7 +15,9 @@ declare module 'ft_state' {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("ft:pageChange", () => {
|
document.addEventListener("ft:pageChange", (newUrl) => {
|
||||||
|
// we are still on a pong page => keep the socket around !
|
||||||
|
if (newUrl.detail.startsWith('/app/pong') || newUrl.detail.startsWith('/pong')) return;
|
||||||
if (window.__state.pongSock !== undefined) window.__state.pongSock.close();
|
if (window.__state.pongSock !== undefined) window.__state.pongSock.close();
|
||||||
window.__state.pongSock = undefined;
|
window.__state.pongSock = undefined;
|
||||||
});
|
});
|
||||||
|
|
@ -59,6 +61,7 @@ function pongClient(_url: string, _args: RouteHandlerParams): RouteHandlerReturn
|
||||||
|
|
||||||
let socket = getSocket();
|
let socket = getSocket();
|
||||||
|
|
||||||
|
let currentGame: GameUpdate | null = null;
|
||||||
// keys handler
|
// keys handler
|
||||||
const keys: Record<string, boolean> = {};
|
const keys: Record<string, boolean> = {};
|
||||||
|
|
||||||
|
|
@ -70,17 +73,23 @@ function pongClient(_url: string, _args: RouteHandlerParams): RouteHandlerReturn
|
||||||
});
|
});
|
||||||
|
|
||||||
setInterval(() => { // key sender
|
setInterval(() => { // key sender
|
||||||
|
if (currentGame === null) return;
|
||||||
let packet: GameMove = {
|
let packet: GameMove = {
|
||||||
move: null,
|
move: null,
|
||||||
|
moveRight: null,
|
||||||
}
|
}
|
||||||
if ((keys['w'] !== keys['s'])) {
|
if ((keys['w'] !== keys['s'])) {
|
||||||
packet.move = keys['w'] ? 'up' : 'down';
|
packet.move = keys['w'] ? 'up' : 'down';
|
||||||
}
|
}
|
||||||
|
if (currentGame.local && (keys['o'] !== keys['l'])) {
|
||||||
|
packet.moveRight = keys['o'] ? 'up' : 'down';
|
||||||
|
}
|
||||||
|
|
||||||
socket.emit('gameMove', packet);
|
socket.emit('gameMove', packet);
|
||||||
}, 1000 / 60);
|
}, 1000 / 60);
|
||||||
|
|
||||||
const render = (state: GameUpdate) => {
|
const render = (state: GameUpdate) => {
|
||||||
|
currentGame = state;
|
||||||
//batLeft.style.transform = `translateY(${state.left.paddle.y}px) translateX(${state.left.paddle.x}px)`;
|
//batLeft.style.transform = `translateY(${state.left.paddle.y}px) translateX(${state.left.paddle.x}px)`;
|
||||||
batLeft.style.top = `${state.left.paddle.y}px`;
|
batLeft.style.top = `${state.left.paddle.y}px`;
|
||||||
batLeft.style.left = `${state.left.paddle.x}px`;
|
batLeft.style.left = `${state.left.paddle.x}px`;
|
||||||
|
|
@ -101,12 +110,15 @@ function pongClient(_url: string, _args: RouteHandlerParams): RouteHandlerReturn
|
||||||
score.innerText = `${state.left.score} | ${state.right.score}`
|
score.innerText = `${state.left.score} | ${state.right.score}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
socket.on('gameEnd', () => currentGame = null);
|
||||||
|
|
||||||
socket.on('gameUpdate', (state: GameUpdate) => render(state));
|
socket.on('gameUpdate', (state: GameUpdate) => render(state));
|
||||||
socket.on('newGame', (state) => render(state));
|
socket.on('newGame', (state: GameUpdate) => render(state));
|
||||||
|
|
||||||
socket.on('updateInformation', (e) => showInfo(`UpdateInformation: t=${e.totalUser};q=${e.inQueue}`));
|
socket.on('updateInformation', (e) => showInfo(`UpdateInformation: t=${e.totalUser};q=${e.inQueue}`));
|
||||||
socket.on('queueEvent', (e) => showInfo(`QueueEvent: ${e}`));
|
socket.on('queueEvent', (e) => showInfo(`QueueEvent: ${e}`));
|
||||||
socket.emit('enqueue');
|
//socket.emit('enqueue');
|
||||||
|
socket.emit('localGame');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,13 @@ export type GameUpdate = {
|
||||||
right: { id: string, paddle: PaddleData, score: number };
|
right: { id: string, paddle: PaddleData, score: number };
|
||||||
|
|
||||||
ball: { x: number, y: number, size: number };
|
ball: { x: number, y: number, size: number };
|
||||||
|
local: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GameMove = {
|
export type GameMove = {
|
||||||
move: 'up' | 'down' | null,
|
move: 'up' | 'down' | null,
|
||||||
|
// only used in local games
|
||||||
|
moveRight: 'up' | 'down' | null,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClientToServer {
|
export interface ClientToServer {
|
||||||
|
|
@ -32,6 +35,7 @@ export interface ClientToServer {
|
||||||
debugInfo: () => void;
|
debugInfo: () => void;
|
||||||
gameMove: (up: GameMove) => void;
|
gameMove: (up: GameMove) => void;
|
||||||
connectedToGame: (gameId: string) => void;
|
connectedToGame: (gameId: string) => void;
|
||||||
|
localGame: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface ServerToClient {
|
export interface ServerToClient {
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,13 @@ export class Pong {
|
||||||
public ball: Ball = new Ball(Pong.GAME_WIDTH / 2, Pong.GAME_HEIGHT / 2, Pong.BALL_START_ANGLES[this.ballAngleIdx++]);
|
public ball: Ball = new Ball(Pong.GAME_WIDTH / 2, Pong.GAME_HEIGHT / 2, Pong.BALL_START_ANGLES[this.ballAngleIdx++]);
|
||||||
|
|
||||||
public score: [number, number] = [0, 0];
|
public score: [number, number] = [0, 0];
|
||||||
|
public local: boolean = false;
|
||||||
|
|
||||||
|
public static makeLocal(owner: UserId): Pong {
|
||||||
|
const game = new Pong(owner, owner);
|
||||||
|
game.local = true;
|
||||||
|
return game;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public userLeft: UserId,
|
public userLeft: UserId,
|
||||||
|
|
@ -202,13 +209,14 @@ export class Pong {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public movePaddle(user: UserId, dir: 'up' | 'down') {
|
public movePaddle(user: UserId | ('left' | 'right'), dir: 'up' | 'down') {
|
||||||
const paddle =
|
let paddle: Paddle | null = null;
|
||||||
user === this.userLeft
|
if (this.local) {
|
||||||
? this.leftPaddle
|
if (user === 'left') { paddle = this.leftPaddle; }
|
||||||
: user == this.userRight
|
else if (user === 'right') { paddle = this.rightPaddle; }
|
||||||
? this.rightPaddle
|
}
|
||||||
: null;
|
else if (user === this.userLeft) { paddle = this.leftPaddle; }
|
||||||
|
else if (user === this.userRight) { paddle = this.rightPaddle; }
|
||||||
if (paddle === null) return;
|
if (paddle === null) return;
|
||||||
paddle.move(dir);
|
paddle.move(dir);
|
||||||
paddle.clamp(0, Pong.GAME_HEIGHT);
|
paddle.clamp(0, Pong.GAME_HEIGHT);
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,13 @@ export type GameUpdate = {
|
||||||
right: { id: string, paddle: PaddleData, score: number };
|
right: { id: string, paddle: PaddleData, score: number };
|
||||||
|
|
||||||
ball: { x: number, y: number, size: number };
|
ball: { x: number, y: number, size: number };
|
||||||
|
local: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GameMove = {
|
export type GameMove = {
|
||||||
move: 'up' | 'down' | null,
|
move: 'up' | 'down' | null,
|
||||||
|
// only used in local games
|
||||||
|
moveRight: 'up' | 'down' | null,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClientToServer {
|
export interface ClientToServer {
|
||||||
|
|
@ -32,6 +35,7 @@ export interface ClientToServer {
|
||||||
debugInfo: () => void;
|
debugInfo: () => void;
|
||||||
gameMove: (up: GameMove) => void;
|
gameMove: (up: GameMove) => void;
|
||||||
connectedToGame: (gameId: string) => void;
|
connectedToGame: (gameId: string) => void;
|
||||||
|
localGame: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface ServerToClient {
|
export interface ServerToClient {
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ class StateI {
|
||||||
left: { id: g.userLeft, score: g.score[0], paddle: { x: g.leftPaddle.x, y: g.leftPaddle.y, width: g.leftPaddle.width, height: g.leftPaddle.height } },
|
left: { id: g.userLeft, score: g.score[0], paddle: { x: g.leftPaddle.x, y: g.leftPaddle.y, width: g.leftPaddle.width, height: g.leftPaddle.height } },
|
||||||
right: { id: g.userRight, score: g.score[1], paddle: { x: g.rightPaddle.x, y: g.rightPaddle.y, width: g.rightPaddle.width, height: g.rightPaddle.height } },
|
right: { id: g.userRight, score: g.score[1], paddle: { x: g.rightPaddle.x, y: g.rightPaddle.y, width: g.rightPaddle.width, height: g.rightPaddle.height } },
|
||||||
ball: { x: g.ball.x, y: g.ball.y, size: g.ball.size },
|
ball: { x: g.ball.x, y: g.ball.y, size: g.ball.size },
|
||||||
|
local: g.local,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,6 +77,27 @@ class StateI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private newLocalGame(sock: SSocket) {
|
||||||
|
const user = this.users.get(sock.authUser.id);
|
||||||
|
if (!user) return;
|
||||||
|
|
||||||
|
const gameId = newUUID() as unknown as GameId;
|
||||||
|
const g = Pong.makeLocal(user.id);
|
||||||
|
const iState: GameUpdate = StateI.getGameUpdateData(gameId, g);
|
||||||
|
|
||||||
|
user.socket.emit('newGame', iState);
|
||||||
|
this.games.set(gameId, g);
|
||||||
|
|
||||||
|
user.currentGame = gameId;
|
||||||
|
|
||||||
|
g.gameUpdate = setInterval(() => {
|
||||||
|
g.tick();
|
||||||
|
this.gameUpdate(gameId, user.socket);
|
||||||
|
if (g.checkWinner() !== null) { this.cleanupGame(gameId, g); }
|
||||||
|
}, 1000 / StateI.UPDATE_INTERVAL_FRAMES);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private gameUpdate(id: GameId, sock: SSocket) {
|
private gameUpdate(id: GameId, sock: SSocket) {
|
||||||
// does the game we want to update the client exists ?
|
// does the game we want to update the client exists ?
|
||||||
if (!this.games.has(id)) return;
|
if (!this.games.has(id)) return;
|
||||||
|
|
@ -94,7 +116,11 @@ class StateI {
|
||||||
if (user.currentGame === null || !this.games.has(user.currentGame)) return;
|
if (user.currentGame === null || !this.games.has(user.currentGame)) return;
|
||||||
const game = this.games.get(user.currentGame)!;
|
const game = this.games.get(user.currentGame)!;
|
||||||
|
|
||||||
if (u.move !== null) { game.movePaddle(user.id, u.move); }
|
if (game.local) {
|
||||||
|
if (u.move !== null) { game.movePaddle('left', u.move); }
|
||||||
|
if (u.moveRight !== null) { game.movePaddle('right', u.moveRight); }
|
||||||
|
}
|
||||||
|
else if (u.move !== null) { game.movePaddle(user.id, u.move); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -119,6 +145,7 @@ class StateI {
|
||||||
socket.on('dequeue', () => this.dequeueUser(socket));
|
socket.on('dequeue', () => this.dequeueUser(socket));
|
||||||
|
|
||||||
socket.on('gameMove', (e) => this.gameMove(socket, e));
|
socket.on('gameMove', (e) => this.gameMove(socket, e));
|
||||||
|
socket.on('localGame', () => this.newLocalGame(socket));
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateClient(socket: SSocket): void {
|
private updateClient(socket: SSocket): void {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue