basic Websocket client-server

This commit is contained in:
LuckyLaszlo
2022-11-16 15:40:44 +01:00
parent 2f62331559
commit a873b23d0f
9 changed files with 305 additions and 40 deletions

View File

@@ -25,8 +25,9 @@ class GameArea {
deleteKey(key: string) {
key = key.toLowerCase();
var i = this.keys.indexOf(key);
if (i != -1)
if (i != -1) {
this.keys.splice(i, 1);
}
}
clear() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);

View File

@@ -55,7 +55,7 @@ class MovingRectangle extends Rectangle implements Moving {
this.speed = baseSpeed;
}
move(delta: number) { // Math.floor WIP until VectorInteger debug
console.log("delta: "+ delta);
// console.log("delta: "+ delta);
// console.log("speed: "+ this.speed);
// console.log("speed*delta: "+ this.speed * delta);
this.pos.x += Math.floor(this.dir.x * this.speed * delta);

View File

@@ -24,7 +24,7 @@
}
#canvas-container {
text-align: center;
/* border: dashed red 5px; */
border: dashed red 5px;
/* max-height: 80vh; */
/* overflow: hidden; */
}
@@ -32,7 +32,7 @@
background-color: #333333;
max-width: 75vw;
/* max-height: 100vh; */
/* width: 80%; */
width: 80%;
}
</style>
</head>

View File

@@ -6,6 +6,8 @@ import {TextElem, TextNumericValue} from "./class/Text.js";
import * as d from "./draw.js";
import {gameLoop, newRound} from "./gameLoop.js"
import {random} from "./utils.js";
import {socket} from "./ws.js";
/* Keys
Player 1: W/S
@@ -31,10 +33,56 @@ export let h_grid_mid: Rectangle;
export let h_grid_u1: Rectangle;
export let h_grid_d1: Rectangle;
function init()
{
initGame();
initGameClientOnly();
console.log("socket state %i", socket.readyState);
}
function startGame()
{
pong = new GameArea();
// Start
d.drawInit();
window.addEventListener('keydown', function (e) {
pong.addKey(e.key);
});
window.addEventListener('keyup', function (e) {
pong.deleteKey(e.key);
});
pong.interval = window.setInterval(gameLoop, 15); // min interval on Firefox seems to be 15. Chrome can go lower.
setTimeout(newRound, 1000);
}
function initGameClientOnly()
{
let pos = new VectorInteger;
// Const
const w = pong.canvas.width;
const h = pong.canvas.height;
const w_mid = Math.floor(w/2);
const h_mid = Math.floor(h/2);
const gridSize = Math.floor(w/500);
// Grid
pos.assign(0, h_mid);
w_grid_mid = new Rectangle(pong.ctx, pos, "darkgreen", w, gridSize);
pos.assign(0, h/4);
w_grid_u1 = new Rectangle(pong.ctx, pos, "darkgreen", w, gridSize);
pos.assign(0, h-h/4);
w_grid_d1 = new Rectangle(pong.ctx, pos, "darkgreen", w, gridSize);
pos.assign(w_mid, 0);
h_grid_mid = new Rectangle(pong.ctx, pos, "darkgreen", gridSize, h);
pos.assign(w/4, 0);
h_grid_u1 = new Rectangle(pong.ctx, pos, "darkgreen", gridSize, h);
pos.assign(w-w/4, 0);
h_grid_d1 = new Rectangle(pong.ctx, pos, "darkgreen", gridSize, h);
}
function initGame()
{
pong = new GameArea();
// Const
const w = pong.canvas.width;
const h = pong.canvas.height;
@@ -46,7 +94,6 @@ function startGame()
const scoreSize = Math.floor(w/16);
const midLineSize = Math.floor(w/150);
const wallSize = Math.floor(w/100);
const gridSize = Math.floor(w/500);
const playerSpeed = Math.floor(w/1.5); // pixel per second
const ballSpeed = Math.floor(w/1.5); // pixel per second
@@ -75,34 +122,11 @@ function startGame()
pos.assign(w_mid-midLineSize/2, 0+wallSize);
midLine = new Line(pong.ctx, pos, "white", midLineSize, h-wallSize*2, 15);
// Grid
pos.assign(0, h_mid);
w_grid_mid = new Rectangle(pong.ctx, pos, "darkgreen", w, gridSize);
pos.assign(0, h/4);
w_grid_u1 = new Rectangle(pong.ctx, pos, "darkgreen", w, gridSize);
pos.assign(0, h-h/4);
w_grid_d1 = new Rectangle(pong.ctx, pos, "darkgreen", w, gridSize);
pos.assign(w_mid, 0);
h_grid_mid = new Rectangle(pong.ctx, pos, "darkgreen", gridSize, h);
pos.assign(w/4, 0);
h_grid_u1 = new Rectangle(pong.ctx, pos, "darkgreen", gridSize, h);
pos.assign(w-w/4, 0);
h_grid_d1 = new Rectangle(pong.ctx, pos, "darkgreen", gridSize, h);
// Start
d.drawInit();
window.addEventListener('keydown', function (e) {
pong.addKey(e.key);
});
window.addEventListener('keyup', function (e) {
pong.deleteKey(e.key);
});
pong.interval = window.setInterval(gameLoop, 15); // min interval on Firefox seems to be 15. Chrome can go lower.
setTimeout(newRound, 1000);
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
startGame();
init();
export {startGame}

View File

@@ -3,4 +3,8 @@ function random(min: number = 0, max: number = 1) {
return Math.random() * (max - min) + min;
}
export {random}
function sleep (ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
export {random, sleep}

81
src/client/ws.ts Normal file
View File

@@ -0,0 +1,81 @@
import * as g from "./pong.js"
import {startGame} from "./pong.js";
const wsPort = 8042;
const wsUrl = "ws://" + document.location.hostname + ":" + wsPort + "/pong";
const socket = new WebSocket(wsUrl, "json");
enum EventTypes {
gameUpdate = 1,
start,
pause,
resume
}
interface EventData {
type: EventTypes;
}
class EventGameUpdate implements EventData {
type: EventTypes = EventTypes.gameUpdate;
player1 = {y: 0};
player2 = {y: 0};
ball = {x: 0, y: 0, speed: 0};
}
socket.addEventListener("message", logListener);
socket.addEventListener("message", matchmakingListener);
function logListener(event: MessageEvent) {
console.log("data: " + event.data + " | [" + Date.now() + "]");
}
function matchmakingListener(event: MessageEvent)
{
console.log("matchmakingListener");
const data: EventData = JSON.parse(event.data);
if (data.type == EventTypes.start)
{
console.log("Event type = start");
socket.removeEventListener("message", matchmakingListener);
socket.addEventListener("message", inGameListener);
startGame();
}
}
function inGameListener(event: MessageEvent)
{
console.log("inGameListener");
const data: EventData = JSON.parse(event.data);
switch (data.type) {
case EventTypes.gameUpdate:
console.log("Event type = gameUpdate");
serverGameUpdate(data as EventGameUpdate);
break;
case EventTypes.pause:
console.log("Event type = pause");
break;
case EventTypes.resume:
console.log("Event type = resume");
break;
}
}
function serverGameUpdate(data: EventGameUpdate)
{
g.player1.clear();
g.player1.pos.y = Math.floor(data.player1.y);
g.player1.update();
g.player2.clear();
g.player2.pos.y = Math.floor(data.player2.y);
g.player2.update();
}
// socket.addEventListener("open", (event) => {
// console.log("socket state %i", socket.readyState);
// });
export {socket}

View File

@@ -1,17 +1,16 @@
// var http = require("http");
// var url = require("url");
// var fs = require("fs");
// var path = require("path");
import http from "http";
import url from "url";
import fs from "fs";
import path from "path";
import { WebSocketServer, WebSocket } from "ws";
import { v4 as uuidv4 } from 'uuid';
import { random } from "../client/utils.js";
const hostname = "localhost";
const port = 8080;
const root = "/mnt/c/Users/Lucky/Desktop/code/ft_transcendence/www/";
const wsPort = 8042; // pas indispensable d'avoir un autre port si le WebSocket est limité à certaines routes
const root = "../../www/";
const server = http.createServer((req, res) => {
// var q = new URL(req.url, `http://${req.getHeaders().host}`)
@@ -36,4 +35,79 @@ const server = http.createServer((req, res) => {
server.listen(port, hostname, () => {
console.log(`Pong running at http://${hostname}:${port}/pong.html`);
});
});
const wsServer = new WebSocketServer({port: wsPort, path: "/pong"});
class Client {
socket: WebSocket;
id: string;
isAlive: boolean = true;
constructor(socket: WebSocket, id: string) {
this.socket = socket;
this.id = id;
}
}
const clientsArr: Client[] = [];
wsServer.on("connection", (socket, request) => {
const id = uuidv4();
const client = new Client(socket, id);
clientsArr.push(client);
socket.on("pong", function heartbeat() {
client.isAlive = true;
console.log("client %s alive at %i", client.id, Date.now());
});
socket.on("message", function message(data) {
console.log("received: %s", data);
});
socket.send(JSON.stringify({type: 2})); // start
// socket.send("connection success, bravo client " + id);
// socket.send("start");
// socket.send("json/20");
});
function deleteClient(client: Client)
{
var i = clientsArr.indexOf(client);
if (i != -1) {
clientsArr.splice(i, 1);
}
}
const pingInterval = setInterval( () => {
clientsArr.forEach( (client) => {
if (client.isAlive === false) {
client.socket.terminate();
console.log("client %s is no more at %i :'(", client.id, Date.now());
deleteClient(client);
return;
}
client.isAlive = false;
client.socket.ping();
});
}, 5000);
const gameUpdateInterval = setInterval( () => {
clientsArr.forEach( (client) => {
const update = {
type: 1,
player1: {y: random(50, 650)},
player2: {y: random(50, 650)},
ball: {x: 0, y: 0, speed: 0}
};
client.socket.send(JSON.stringify(update));
});
}, 500);
wsServer.on('close', () => {
clearInterval(pingInterval);
clearInterval(gameUpdateInterval);
});