HTML game modes selector
+ pong.css in a separate file
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -18,6 +18,7 @@ Thumbs.db
|
|||||||
node_modules
|
node_modules
|
||||||
*.js
|
*.js
|
||||||
www/**/*.html
|
www/**/*.html
|
||||||
|
www/**/*.css
|
||||||
|
|
||||||
large
|
large
|
||||||
old
|
old
|
||||||
|
|||||||
1
make.sh
1
make.sh
@@ -3,6 +3,7 @@ npx tsc
|
|||||||
|
|
||||||
mkdir -p www
|
mkdir -p www
|
||||||
cp ./src/client/*.html ./www/
|
cp ./src/client/*.html ./www/
|
||||||
|
cp ./src/client/*.css ./www/
|
||||||
|
|
||||||
mkdir -p www/js
|
mkdir -p www/js
|
||||||
cp ./src/client/*.js ./www/js/
|
cp ./src/client/*.js ./www/js/
|
||||||
|
|||||||
2
memo.txt
2
memo.txt
@@ -14,8 +14,10 @@ Done:
|
|||||||
- Détruire les GameSession une fois finies.
|
- Détruire les GameSession une fois finies.
|
||||||
- mode multi-balles
|
- mode multi-balles
|
||||||
- mode murs mouvant (la zone de jeu rétréci / agrandi en continu)
|
- mode murs mouvant (la zone de jeu rétréci / agrandi en continu)
|
||||||
|
- Selection des modes de jeu via HTML
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
|
- Match Abort si tout les joueurs ne sont pas pret assez vite (~15 secondes)
|
||||||
- mode spectateur
|
- mode spectateur
|
||||||
- certaines utilisations de Math.floor() superflu ? Vérifier les appels.
|
- certaines utilisations de Math.floor() superflu ? Vérifier les appels.
|
||||||
(éventuellement Math.round() ?)
|
(éventuellement Math.round() ?)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class GameArea {
|
|||||||
this.ctx = this.canvas.getContext("2d") as CanvasRenderingContext2D;
|
this.ctx = this.canvas.getContext("2d") as CanvasRenderingContext2D;
|
||||||
this.canvas.width = c.CanvasWidth;
|
this.canvas.width = c.CanvasWidth;
|
||||||
this.canvas.height = c.CanvasWidth / c.CanvasRatio;
|
this.canvas.height = c.CanvasWidth / c.CanvasRatio;
|
||||||
let container = document.getElementById("canvas-container");
|
let container = document.getElementById("canvas_container");
|
||||||
if (container)
|
if (container)
|
||||||
container.insertBefore(this.canvas, container.childNodes[0]);
|
container.insertBefore(this.canvas, container.childNodes[0]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,19 +8,12 @@ export const gridSize = Math.floor(w/500);
|
|||||||
|
|
||||||
// min interval on Firefox seems to be 15. Chrome can go lower.
|
// min interval on Firefox seems to be 15. Chrome can go lower.
|
||||||
export const handleInputIntervalMS = 15; // millisecond
|
export const handleInputIntervalMS = 15; // millisecond
|
||||||
export const sendLoopIntervalMS = 15; // millisecond
|
export const sendLoopIntervalMS = 15; // millisecond // unused
|
||||||
export const gameLoopIntervalMS = 15; // millisecond
|
export const gameLoopIntervalMS = 15; // millisecond
|
||||||
export const drawLoopIntervalMS = 15; // millisecond
|
export const drawLoopIntervalMS = 15; // millisecond
|
||||||
|
|
||||||
export const fixedDeltaTime = gameLoopIntervalMS/1000; // second
|
export const fixedDeltaTime = gameLoopIntervalMS/1000; // second
|
||||||
|
|
||||||
export const soundMutedFlag = true;
|
export const soundMutedFlag = true; // TODO: Radio selector on website
|
||||||
export const soundRobloxVolume = 0.3; // between 0 and 1
|
export const soundRobloxVolume = 0.3; // between 0 and 1
|
||||||
export const soundPongVolume = 0.3; // between 0 and 1
|
export const soundPongVolume = 0.3; // between 0 and 1
|
||||||
|
|
||||||
// TODO: replace by a selector on the website
|
|
||||||
import * as en from "../shared_js/enums.js"
|
|
||||||
export const optionsPLACEHOLDER = en.MatchOptions.noOption;
|
|
||||||
// export const optionsPLACEHOLDER = en.MatchOptions.multiBalls;
|
|
||||||
// export const optionsPLACEHOLDER = en.MatchOptions.movingWalls;
|
|
||||||
// export const optionsPLACEHOLDER = en.MatchOptions.movingWalls | en.MatchOptions.multiBalls;
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
import * as c from "./constants.js";
|
import * as c from "./constants.js";
|
||||||
import * as en from "../shared_js/enums.js"
|
import * as en from "../shared_js/enums.js"
|
||||||
import { gc, clientInfo } from "./global.js";
|
import { gc, matchOptions, clientInfo } from "./global.js";
|
||||||
import { wallsMovements } from "../shared_js/wallsMovement.js";
|
import { wallsMovements } from "../shared_js/wallsMovement.js";
|
||||||
|
|
||||||
let actual_time: number = Date.now();
|
let actual_time: number = Date.now();
|
||||||
@@ -28,7 +28,7 @@ function gameLoop()
|
|||||||
ball.moveAndBounce(delta_time, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]);
|
ball.moveAndBounce(delta_time, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (c.optionsPLACEHOLDER & en.MatchOptions.movingWalls) {
|
if (matchOptions & en.MatchOptions.movingWalls) {
|
||||||
wallsMovements(delta_time, gc);
|
wallsMovements(delta_time, gc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
|
|
||||||
export {pong, gc} from "./pong.js"
|
export {pong, gc, matchOptions} from "./pong.js"
|
||||||
export {socket, clientInfo} from "./ws.js"
|
export {socket, clientInfo} from "./ws.js"
|
||||||
|
|||||||
53
src/client/pong.css
Normal file
53
src/client/pong.css
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Bit5x3";
|
||||||
|
src: url("http://localhost:8080/Bit5x3.woff2") format("woff2"),
|
||||||
|
url("http://localhost:8080/Bit5x3.woff") format("woff");
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
#preload_font {
|
||||||
|
font-family: "Bit5x3";
|
||||||
|
opacity:0;
|
||||||
|
height:0;
|
||||||
|
width:0;
|
||||||
|
display:inline-block;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
background-color: #222425;
|
||||||
|
}
|
||||||
|
#canvas_container {
|
||||||
|
text-align: center;
|
||||||
|
/* border: dashed white 5px; */
|
||||||
|
/* max-height: 80vh; */
|
||||||
|
/* overflow: hidden; */
|
||||||
|
}
|
||||||
|
#div_game_options {
|
||||||
|
text-align: center;
|
||||||
|
font-family: "Bit5x3";
|
||||||
|
color: white;
|
||||||
|
font-size: x-large;
|
||||||
|
}
|
||||||
|
#div_game_options fieldset {
|
||||||
|
max-width: 50vw;
|
||||||
|
width: auto;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
#div_game_options fieldset div {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
#play_pong_button {
|
||||||
|
font-family: "Bit5x3";
|
||||||
|
color: white;
|
||||||
|
background-color: #333333;
|
||||||
|
font-size: x-large;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
canvas {
|
||||||
|
background-color: #333333;
|
||||||
|
max-width: 75vw;
|
||||||
|
/* max-height: 100vh; */
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
@@ -2,46 +2,35 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
<style>
|
<link rel="stylesheet" href="pong.css">
|
||||||
@font-face {
|
|
||||||
font-family: "Bit5x3";
|
|
||||||
src: url("http://localhost:8080/Bit5x3.woff2") format("woff2"),
|
|
||||||
url("http://localhost:8080/Bit5x3.woff") format("woff");
|
|
||||||
font-weight: normal;
|
|
||||||
font-style: normal;
|
|
||||||
font-display: swap;
|
|
||||||
}
|
|
||||||
#preloadfont {
|
|
||||||
font-family: "Bit5x3";
|
|
||||||
opacity:0;
|
|
||||||
height:0;
|
|
||||||
width:0;
|
|
||||||
display:inline-block;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
background-color: #222425;
|
|
||||||
}
|
|
||||||
#canvas-container {
|
|
||||||
text-align: center;
|
|
||||||
border: dashed red 5px;
|
|
||||||
/* max-height: 80vh; */
|
|
||||||
/* overflow: hidden; */
|
|
||||||
}
|
|
||||||
canvas {
|
|
||||||
background-color: #333333;
|
|
||||||
max-width: 75vw;
|
|
||||||
/* max-height: 100vh; */
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="preloadfont">.</div>
|
<div id="preload_font">.</div>
|
||||||
<div id="canvas-container">
|
|
||||||
|
<div id="div_game_options">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Game options</legend>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="multiBalls" name="multiBalls">
|
||||||
|
<label for="multiBalls">Multiples balls</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="movingWalls" name="movingWalls">
|
||||||
|
<label for="movingWalls">Moving walls</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button id="play_pong_button">Play</button>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="canvas_container">
|
||||||
<!-- <p> =) </p> -->
|
<!-- <p> =) </p> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="http://localhost:8080/js/pong.js" type="module" defer></script>
|
<script src="http://localhost:8080/js/pong.js" type="module" defer></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
|
|
||||||
|
initDom();
|
||||||
|
function initDom() {
|
||||||
|
document.getElementById("play_pong_button").addEventListener("click", init);
|
||||||
|
}
|
||||||
|
|
||||||
import * as c from "./constants.js"
|
import * as c from "./constants.js"
|
||||||
|
import * as en from "../shared_js/enums.js"
|
||||||
import { GameArea } from "./class/GameArea.js";
|
import { GameArea } from "./class/GameArea.js";
|
||||||
import { GameComponentsClient } from "./class/GameComponentsClient.js";
|
import { GameComponentsClient } from "./class/GameComponentsClient.js";
|
||||||
import { handleInput } from "./handleInput.js";
|
import { handleInput } from "./handleInput.js";
|
||||||
@@ -7,16 +13,37 @@ import { handleInput } from "./handleInput.js";
|
|||||||
import { gameLoop } from "./gameLoop.js"
|
import { gameLoop } from "./gameLoop.js"
|
||||||
import { drawLoop } from "./draw.js";
|
import { drawLoop } from "./draw.js";
|
||||||
import { countdown } from "./utils.js";
|
import { countdown } from "./utils.js";
|
||||||
|
import {initWebSocket} from "./ws.js";
|
||||||
|
|
||||||
import {socket} from "./ws.js"; socket; // no-op, just for loading
|
|
||||||
|
|
||||||
/* Keys
|
/* Keys
|
||||||
Racket: W/S OR Up/Down
|
Racket: W/S OR Up/Down
|
||||||
Grid On-Off: G
|
Grid On-Off: G
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const pong = new GameArea();
|
/* TODO: A way to delay the init of variables, but still use "const" not "let" ? */
|
||||||
export const gc = new GameComponentsClient(c.optionsPLACEHOLDER, pong.ctx);
|
export let pong: GameArea;
|
||||||
|
export let gc: GameComponentsClient;
|
||||||
|
export let matchOptions: en.MatchOptions = en.MatchOptions.noOption;
|
||||||
|
|
||||||
|
function init()
|
||||||
|
{
|
||||||
|
console.log("multiBalls:"+(<HTMLInputElement>document.getElementById("multiBalls")).checked);
|
||||||
|
console.log("movingWalls:"+(<HTMLInputElement>document.getElementById("movingWalls")).checked);
|
||||||
|
|
||||||
|
if ( (<HTMLInputElement>document.getElementById("multiBalls")).checked ) {
|
||||||
|
matchOptions |= en.MatchOptions.multiBalls;
|
||||||
|
}
|
||||||
|
if ( (<HTMLInputElement>document.getElementById("movingWalls")).checked ) {
|
||||||
|
matchOptions |= en.MatchOptions.movingWalls;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("div_game_options").hidden = true;
|
||||||
|
|
||||||
|
pong = new GameArea();
|
||||||
|
gc = new GameComponentsClient(matchOptions, pong.ctx);
|
||||||
|
initWebSocket(matchOptions);
|
||||||
|
}
|
||||||
|
|
||||||
function matchmaking()
|
function matchmaking()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
import * as c from "./constants.js"
|
import * as c from "./constants.js"
|
||||||
import { gc } from "./global.js"
|
import { gc, matchOptions } from "./global.js"
|
||||||
import * as ev from "../shared_js/class/Event.js"
|
import * as ev from "../shared_js/class/Event.js"
|
||||||
import * as en from "../shared_js/enums.js"
|
import * as en from "../shared_js/enums.js"
|
||||||
import { matchmaking, matchmakingComplete, startGame } from "./pong.js";
|
import { matchmaking, matchmakingComplete, startGame } from "./pong.js";
|
||||||
@@ -10,10 +10,6 @@ import { soundRoblox } from "./audio.js"
|
|||||||
import { sleep } from "./utils.js";
|
import { sleep } from "./utils.js";
|
||||||
import { Vector, VectorInteger } from "../shared_js/class/Vector.js";
|
import { Vector, VectorInteger } from "../shared_js/class/Vector.js";
|
||||||
|
|
||||||
const wsPort = 8042;
|
|
||||||
const wsUrl = "ws://" + document.location.hostname + ":" + wsPort + "/pong";
|
|
||||||
export const socket = new WebSocket(wsUrl, "json");
|
|
||||||
|
|
||||||
class ClientInfo {
|
class ClientInfo {
|
||||||
id = "";
|
id = "";
|
||||||
side: en.PlayerSide;
|
side: en.PlayerSide;
|
||||||
@@ -22,20 +18,27 @@ class ClientInfo {
|
|||||||
opponentNextPos: VectorInteger;
|
opponentNextPos: VectorInteger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const wsPort = 8042;
|
||||||
|
const wsUrl = "ws://" + document.location.hostname + ":" + wsPort + "/pong";
|
||||||
|
export let socket: WebSocket; /* TODO: A way to still use "const" not "let" ? */
|
||||||
export const clientInfo = new ClientInfo();
|
export const clientInfo = new ClientInfo();
|
||||||
|
|
||||||
socket.addEventListener("open", (event) => {
|
export function initWebSocket(options: en.MatchOptions)
|
||||||
socket.send(JSON.stringify( new ev.ClientAnnounce(en.ClientRole.player, c.optionsPLACEHOLDER, clientInfo.id) ));
|
{
|
||||||
});
|
socket = new WebSocket(wsUrl, "json");
|
||||||
|
socket.addEventListener("open", (event) => {
|
||||||
// socket.addEventListener("message", logListener); // for testing purpose
|
socket.send(JSON.stringify( new ev.ClientAnnounce(en.ClientRole.player, options, clientInfo.id) ));
|
||||||
socket.addEventListener("message", preMatchListener);
|
});
|
||||||
|
// socket.addEventListener("message", logListener); // for testing purpose
|
||||||
|
socket.addEventListener("message", preMatchListener);
|
||||||
|
}
|
||||||
|
|
||||||
function logListener(this: WebSocket, event: MessageEvent) {
|
function logListener(this: WebSocket, event: MessageEvent) {
|
||||||
console.log("%i: " + event.data, Date.now());
|
console.log("%i: " + event.data, Date.now());
|
||||||
}
|
}
|
||||||
|
|
||||||
function preMatchListener(this: WebSocket, event: MessageEvent) {
|
function preMatchListener(this: WebSocket, event: MessageEvent)
|
||||||
|
{
|
||||||
const data: ev.ServerEvent = JSON.parse(event.data);
|
const data: ev.ServerEvent = JSON.parse(event.data);
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case en.EventTypes.assignId:
|
case en.EventTypes.assignId:
|
||||||
@@ -90,7 +93,7 @@ function gameUpdate(data: ev.EventGameUpdate)
|
|||||||
{
|
{
|
||||||
console.log("gameUpdate");
|
console.log("gameUpdate");
|
||||||
|
|
||||||
if (c.optionsPLACEHOLDER & en.MatchOptions.movingWalls) {
|
if (matchOptions & en.MatchOptions.movingWalls) {
|
||||||
gc.wallTop.pos.y = data.wallTop.y;
|
gc.wallTop.pos.y = data.wallTop.y;
|
||||||
gc.wallBottom.pos.y = data.wallBottom.y;
|
gc.wallBottom.pos.y = data.wallBottom.y;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user