Implémentation du jeu dans svelte HOPE
This commit is contained in:
@@ -1,49 +0,0 @@
|
||||
|
||||
import * as c from "./constants.js";
|
||||
import * as en from "../shared_js/enums.js"
|
||||
import { gc, matchOptions, clientInfo } from "./global.js";
|
||||
import { wallsMovements } from "../shared_js/wallsMovement.js";
|
||||
|
||||
let actual_time: number = Date.now();
|
||||
let last_time: number;
|
||||
let delta_time: number;
|
||||
|
||||
function gameLoop()
|
||||
{
|
||||
/* last_time = actual_time;
|
||||
actual_time = Date.now();
|
||||
delta_time = (actual_time - last_time) / 1000; */
|
||||
|
||||
delta_time = c.fixedDeltaTime;
|
||||
// console.log(`delta_gameLoop: ${delta_time}`);
|
||||
|
||||
// interpolation
|
||||
// console.log(`dir.y: ${clientInfo.opponent.dir.y}, pos.y: ${clientInfo.opponent.pos.y}, opponentNextPos.y: ${clientInfo.opponentNextPos.y}`);
|
||||
if (clientInfo.opponent.dir.y != 0 ) {
|
||||
opponentInterpolation(delta_time);
|
||||
}
|
||||
|
||||
// client prediction
|
||||
gc.ballsArr.forEach((ball) => {
|
||||
ball.moveAndBounce(delta_time, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]);
|
||||
});
|
||||
|
||||
if (matchOptions & en.MatchOptions.movingWalls) {
|
||||
wallsMovements(delta_time, gc);
|
||||
}
|
||||
}
|
||||
|
||||
function opponentInterpolation(delta: number)
|
||||
{
|
||||
// interpolation
|
||||
clientInfo.opponent.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]);
|
||||
|
||||
if ((clientInfo.opponent.dir.y > 0 && clientInfo.opponent.pos.y > clientInfo.opponentNextPos.y)
|
||||
|| (clientInfo.opponent.dir.y < 0 && clientInfo.opponent.pos.y < clientInfo.opponentNextPos.y))
|
||||
{
|
||||
clientInfo.opponent.dir.y = 0;
|
||||
clientInfo.opponent.pos.y = clientInfo.opponentNextPos.y;
|
||||
}
|
||||
}
|
||||
|
||||
export {gameLoop}
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
export {pong, gc, matchOptions} from "./pong.js"
|
||||
export {socket, clientInfo} from "./ws.js"
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset='utf-8'>
|
||||
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
||||
|
||||
<title>Svelte app</title>
|
||||
<title>Potato Pong</title>
|
||||
|
||||
<link rel='icon' type='image/png' href='/favicon.png'>
|
||||
<link rel='stylesheet' href='/global.css'>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
9
srcs/requirements/svelte/api_front/src/main.js
Normal file
9
srcs/requirements/svelte/api_front/src/main.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import App from './App.svelte';
|
||||
const app = new App({
|
||||
target: document.body,
|
||||
props: {
|
||||
// name: 'world'
|
||||
}
|
||||
});
|
||||
export default app;
|
||||
//# sourceMappingURL=main.js.map
|
||||
1
srcs/requirements/svelte/api_front/src/main.js.map
Normal file
1
srcs/requirements/svelte/api_front/src/main.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"main.js","sourceRoot":"","sources":["main.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,cAAc,CAAC;AAE/B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC;IACnB,MAAM,EAAE,QAAQ,CAAC,IAAI;IACrB,KAAK,EAAE;IACN,gBAAgB;KAChB;CACD,CAAC,CAAC;AAEH,eAAe,GAAG,CAAC"}
|
||||
@@ -1,45 +1,104 @@
|
||||
|
||||
<script>
|
||||
import "public/game/pong.js"
|
||||
<script lang="ts">
|
||||
import * as enumeration from './shared_js/enums'
|
||||
import * as constants from './client/constants'
|
||||
import { initPong, initGc, initMatchOptions, initStartFunction } from './client/global'
|
||||
import { GameArea } from './client/class/GameArea';
|
||||
import { GameComponentsClient } from './client/class/GameComponentsClient';
|
||||
import { handleInput } from './client/handleInput';
|
||||
import {gameLoop} from './client/gameLoop'
|
||||
import { drawLoop } from './client/draw';
|
||||
import {countdown} from './client/utils'
|
||||
import { initWebSocket } from './client/ws';
|
||||
import { initAudio } from './client/audio';
|
||||
import { pong, gc} from './client/global'
|
||||
|
||||
let optionsAreNotSet = true
|
||||
|
||||
let sound = false;
|
||||
let multi_balls = false;
|
||||
let moving_walls = false;
|
||||
let matchOption : enumeration.MatchOptions = enumeration.MatchOptions.noOption;
|
||||
|
||||
|
||||
// En async au cas où pour la suite mais apriori inutile, les check se feront sûrement au onMount
|
||||
const init = async() => {
|
||||
if (multi_balls === true)
|
||||
matchOption |= enumeration.MatchOptions.multiBalls
|
||||
if (moving_walls === true )
|
||||
matchOption |= enumeration.MatchOptions.movingWalls
|
||||
initAudio(sound)
|
||||
initMatchOptions(matchOption)
|
||||
optionsAreNotSet = false
|
||||
initPong(new GameArea())
|
||||
initGc(new GameComponentsClient(matchOption, pong.ctx))
|
||||
initStartFunction(start)
|
||||
initWebSocket(matchOption)
|
||||
}
|
||||
|
||||
function start() : void {
|
||||
gc.text1.pos.assign(constants.w*0.5, constants.h*0.75);
|
||||
countdown(constants.matchStartDelay/1000, (count: number) => {
|
||||
gc.text1.clear();
|
||||
gc.text1.text = `${count}`;
|
||||
gc.text1.update();
|
||||
}, resume);
|
||||
}
|
||||
|
||||
function resume(): void {
|
||||
gc.text1.text = "";
|
||||
window.addEventListener('keydown', function (e) {
|
||||
pong.addKey(e.key);
|
||||
});
|
||||
window.addEventListener('keyup', function (e) {
|
||||
pong.deleteKey(e.key);
|
||||
});
|
||||
pong.handleInputInterval = window.setInterval(handleInput, constants.handleInputIntervalMS);
|
||||
// pong.handleInputInterval = window.setInterval(sendLoop, c.sendLoopIntervalMS);
|
||||
pong.gameLoopInterval = window.setInterval(gameLoop, constants.gameLoopIntervalMS);
|
||||
pong.drawLoopInterval = window.setInterval(drawLoop, constants.drawLoopIntervalMS);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="preload_font">.</div>
|
||||
|
||||
<div id="div_game_options">
|
||||
<fieldset>
|
||||
<legend>game options</legend>
|
||||
<div>
|
||||
<input type="checkbox" id="multi_balls" name="multi_balls">
|
||||
<label for="multi_balls">multiples balls</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="checkbox" id="moving_walls" name="moving_walls">
|
||||
<label for="moving_walls">moving walls</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>sound :</label>
|
||||
<input type="radio" id="sound_on" name="sound_selector" checked>
|
||||
<label for="sound_on">on</label>
|
||||
<input type="radio" id="sound_off" name="sound_selector">
|
||||
<label for="sound_off">off</label>
|
||||
</div>
|
||||
<div>
|
||||
<button id="play_pong_button">PLAY</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
{#if optionsAreNotSet}
|
||||
<form on:submit|preventDefault={init}>
|
||||
<div id="div_game_options">
|
||||
<fieldset>
|
||||
<legend>game options</legend>
|
||||
<div>
|
||||
<input type="checkbox" id="multi_balls" name="multi_balls" bind:checked={multi_balls}>
|
||||
<label for="multi_balls">Multiples balls</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="checkbox" id="moving_walls" name="moving_walls" bind:checked={moving_walls}>
|
||||
<label for="moving_walls">Moving walls</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="checkbox" id="moving_walls" name="moving_walls" bind:checked={sound}>
|
||||
<label for="moving_walls">Sound</label>
|
||||
</div>
|
||||
<div>
|
||||
<button id="play_pong_button" >PLAY</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</form>
|
||||
<div id="div_game_instructions">
|
||||
<h2>--- keys ---</h2>
|
||||
<p>move up: 'w' or 'up arrow'</p>
|
||||
<p>move down: 's' OR 'down arrow'</p>
|
||||
<p>grid on/off: 'g'</p>
|
||||
</div>
|
||||
|
||||
{/if}
|
||||
<div id="canvas_container">
|
||||
<!-- <p> =) </p> -->
|
||||
</div>
|
||||
|
||||
<script src="public/game/pong.js" type="module" defer></script>
|
||||
</body>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
import * as c from "./constants.js"
|
||||
|
||||
export const soundPongArr: HTMLAudioElement[] = [];
|
||||
export const soundRoblox = new Audio("http://localhost:8080/sound/roblox-oof.ogg");
|
||||
export const soundRoblox = new Audio("http://transcendance:8080/sound/roblox-oof.ogg");
|
||||
|
||||
export function initAudio(muteFlag: boolean)
|
||||
{
|
||||
for (let i = 0; i <= 32; i++) {
|
||||
soundPongArr.push(new Audio("http://localhost:8080/sound/pong/"+i+".ogg"));
|
||||
soundPongArr.push(new Audio("http://transcendance:8080/sound/pong/"+i+".ogg"));
|
||||
soundPongArr[i].volume = c.soundPongVolume;
|
||||
soundPongArr[i].muted = muteFlag;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
import * as c from ".././constants.js"
|
||||
|
||||
class GameArea {
|
||||
export class GameArea {
|
||||
keys: string[] = [];
|
||||
handleInputInterval: number = 0;
|
||||
gameLoopInterval: number = 0;
|
||||
@@ -34,5 +34,3 @@ class GameArea {
|
||||
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
}
|
||||
}
|
||||
|
||||
export {GameArea}
|
||||
@@ -62,12 +62,13 @@ class GameComponentsExtensionForClient extends GameComponents {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class GameComponentsClient extends GameComponentsExtensionForClient {
|
||||
export class GameComponentsClient extends GameComponentsExtensionForClient {
|
||||
midLine: Line;
|
||||
scoreLeft: TextNumericValue;
|
||||
scoreRight: TextNumericValue;
|
||||
text1: TextElem;
|
||||
text2: TextElem;
|
||||
text3: TextElem;
|
||||
|
||||
w_grid_mid: RectangleClient;
|
||||
w_grid_u1: RectangleClient;
|
||||
@@ -90,6 +91,8 @@ class GameComponentsClient extends GameComponentsExtensionForClient {
|
||||
// Text
|
||||
pos.assign(0, c.h_mid);
|
||||
this.text1 = new TextElem(pos, Math.floor(c.w/8), ctx, "white");
|
||||
this.text2 = new TextElem(pos, Math.floor(c.w/24), ctx, "white");
|
||||
this.text3 = new TextElem(pos, Math.floor(c.w/24), ctx, "white");
|
||||
|
||||
// Dotted Midline
|
||||
pos.assign(c.w_mid-c.midLineSize/2, 0+c.wallSize);
|
||||
@@ -110,5 +113,3 @@ class GameComponentsClient extends GameComponentsExtensionForClient {
|
||||
this.h_grid_d1 = new RectangleClient(pos, c.gridSize, c.h, ctx, "darkgreen");
|
||||
}
|
||||
}
|
||||
|
||||
export {GameComponentsClient}
|
||||
@@ -2,7 +2,7 @@
|
||||
import * as en from "../../shared_js/enums.js"
|
||||
import * as ev from "../../shared_js/class/Event.js"
|
||||
|
||||
class InputHistory {
|
||||
export class InputHistory {
|
||||
input: en.InputEnum;
|
||||
id: number;
|
||||
deltaTime: number;
|
||||
@@ -12,5 +12,3 @@ class InputHistory {
|
||||
this.deltaTime = deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
export {InputHistory}
|
||||
@@ -17,7 +17,7 @@ function clearRectangle(this: RectangleClient, pos?: VectorInteger) {
|
||||
this.ctx.clearRect(this.pos.x, this.pos.y, this.width, this.height);
|
||||
}
|
||||
|
||||
class RectangleClient extends Rectangle implements GraphicComponent {
|
||||
export class RectangleClient extends Rectangle implements GraphicComponent {
|
||||
ctx: CanvasRenderingContext2D;
|
||||
color: string;
|
||||
update: () => void;
|
||||
@@ -31,19 +31,9 @@ class RectangleClient extends Rectangle implements GraphicComponent {
|
||||
this.update = updateRectangle;
|
||||
this.clear = clearRectangle;
|
||||
}
|
||||
// update() {
|
||||
// this.ctx.fillStyle = this.color;
|
||||
// this.ctx.fillRect(this.pos.x, this.pos.y, this.width, this.height);
|
||||
// }
|
||||
// clear(pos?: VectorInteger) {
|
||||
// if (pos)
|
||||
// this.ctx.clearRect(pos.x, pos.y, this.width, this.height);
|
||||
// else
|
||||
// this.ctx.clearRect(this.pos.x, this.pos.y, this.width, this.height);
|
||||
// }
|
||||
}
|
||||
|
||||
class MovingRectangleClient extends MovingRectangle implements GraphicComponent {
|
||||
export class MovingRectangleClient extends MovingRectangle implements GraphicComponent {
|
||||
ctx: CanvasRenderingContext2D;
|
||||
color: string;
|
||||
update: () => void;
|
||||
@@ -59,7 +49,7 @@ class MovingRectangleClient extends MovingRectangle implements GraphicComponent
|
||||
}
|
||||
}
|
||||
|
||||
class RacketClient extends Racket implements GraphicComponent {
|
||||
export class RacketClient extends Racket implements GraphicComponent {
|
||||
ctx: CanvasRenderingContext2D;
|
||||
color: string;
|
||||
update: () => void;
|
||||
@@ -75,7 +65,7 @@ class RacketClient extends Racket implements GraphicComponent {
|
||||
}
|
||||
}
|
||||
|
||||
class BallClient extends Ball implements GraphicComponent {
|
||||
export class BallClient extends Ball implements GraphicComponent {
|
||||
ctx: CanvasRenderingContext2D;
|
||||
color: string;
|
||||
update: () => void;
|
||||
@@ -93,10 +83,6 @@ class BallClient extends Ball implements GraphicComponent {
|
||||
this._bounceAlgo(collider);
|
||||
soundPongArr[ Math.floor(random(0, soundPongArr.length)) ].play();
|
||||
}
|
||||
/* protected _bounceRacket(collider: Racket) {
|
||||
this._bounceRacketAlgo(collider);
|
||||
soundRoblox.play();
|
||||
} */
|
||||
}
|
||||
|
||||
function updateLine(this: Line) {
|
||||
@@ -105,17 +91,20 @@ function updateLine(this: Line) {
|
||||
let i = 0;
|
||||
while (i < this.segmentCount)
|
||||
{
|
||||
// for Horizontal Line
|
||||
/* Horizontal Line */
|
||||
// pos.y = this.pos.y;
|
||||
// pos.x = this.pos.x + this.segmentWidth * i;
|
||||
|
||||
/* Vertical Line */
|
||||
pos.x = this.pos.x;
|
||||
pos.y = this.pos.y + this.segmentHeight * i;
|
||||
|
||||
this.ctx.fillRect(pos.x, pos.y, this.segmentWidth, this.segmentHeight);
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
class Line extends RectangleClient {
|
||||
export class Line extends RectangleClient {
|
||||
gapeCount: number = 0;
|
||||
segmentCount: number;
|
||||
segmentWidth: number;
|
||||
@@ -129,13 +118,12 @@ class Line extends RectangleClient {
|
||||
this.gapeCount = gapeCount;
|
||||
this.segmentCount = this.gapeCount * 2 + 1;
|
||||
|
||||
/* Vertical Line */
|
||||
this.segmentWidth = this.width;
|
||||
this.segmentHeight = this.height / this.segmentCount;
|
||||
|
||||
// for Horizontal Line
|
||||
/* Horizontal Line */
|
||||
// this.segmentWidth = this.width / this.segmentCount;
|
||||
// this.segmentHeight = this.height;
|
||||
}
|
||||
}
|
||||
|
||||
export {RectangleClient, MovingRectangleClient, RacketClient, BallClient, Line}
|
||||
@@ -3,7 +3,7 @@ import { Vector, VectorInteger } from "../../shared_js/class/Vector.js";
|
||||
import { Component } from "../../shared_js/class/interface.js";
|
||||
|
||||
// conflict with Text
|
||||
class TextElem implements Component {
|
||||
export class TextElem implements Component {
|
||||
ctx: CanvasRenderingContext2D;
|
||||
pos: VectorInteger;
|
||||
color: string;
|
||||
@@ -39,7 +39,7 @@ class TextElem implements Component {
|
||||
}
|
||||
}
|
||||
|
||||
class TextNumericValue extends TextElem {
|
||||
export class TextNumericValue extends TextElem {
|
||||
private _value: number = 0;
|
||||
constructor(pos: VectorInteger, size: number,
|
||||
ctx: CanvasRenderingContext2D, color: string, font?: string)
|
||||
@@ -54,5 +54,3 @@ class TextNumericValue extends TextElem {
|
||||
this.text = v.toString();
|
||||
}
|
||||
}
|
||||
|
||||
export {TextElem, TextNumericValue}
|
||||
@@ -1,10 +1,8 @@
|
||||
|
||||
import { pong, gc } from "./global.js"
|
||||
import * as c from "./constants.js"
|
||||
import * as en from "../shared_js/enums.js"
|
||||
import { gridDisplay } from "./handleInput.js";
|
||||
|
||||
function drawLoop()
|
||||
export function drawLoop()
|
||||
{
|
||||
pong.clear();
|
||||
|
||||
@@ -15,6 +13,8 @@ function drawLoop()
|
||||
drawStatic();
|
||||
|
||||
gc.text1.update();
|
||||
gc.text2.update();
|
||||
gc.text3.update();
|
||||
|
||||
drawDynamic();
|
||||
}
|
||||
@@ -47,5 +47,3 @@ function drawGrid()
|
||||
gc.h_grid_u1.update();
|
||||
gc.h_grid_d1.update();
|
||||
}
|
||||
|
||||
export {drawLoop}
|
||||
@@ -0,0 +1,71 @@
|
||||
|
||||
import * as c from "./constants.js";
|
||||
import * as en from "../shared_js/enums.js"
|
||||
import { gc, matchOptions, clientInfo, clientInfoSpectator} from "./global.js";
|
||||
import { wallsMovements } from "../shared_js/wallsMovement.js";
|
||||
import { RacketClient } from "./class/RectangleClient.js";
|
||||
import { VectorInteger } from "../shared_js/class/Vector.js";
|
||||
|
||||
let actual_time: number = Date.now();
|
||||
let last_time: number;
|
||||
let delta_time: number;
|
||||
|
||||
export function gameLoop()
|
||||
{
|
||||
/* last_time = actual_time;
|
||||
actual_time = Date.now();
|
||||
delta_time = (actual_time - last_time) / 1000; */
|
||||
|
||||
delta_time = c.fixedDeltaTime;
|
||||
// console.log(`delta_gameLoop: ${delta_time}`);
|
||||
|
||||
// interpolation
|
||||
// console.log(`dir.y: ${clientInfo.opponent.dir.y}, pos.y: ${clientInfo.opponent.pos.y}, opponentNextPos.y: ${clientInfo.opponentNextPos.y}`);
|
||||
if (clientInfo.opponent.dir.y != 0 ) {
|
||||
racketInterpolation(delta_time, clientInfo.opponent, clientInfo.opponentNextPos);
|
||||
}
|
||||
|
||||
// client prediction
|
||||
gc.ballsArr.forEach((ball) => {
|
||||
ball.moveAndBounce(delta_time, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]);
|
||||
});
|
||||
|
||||
if (matchOptions & en.MatchOptions.movingWalls) {
|
||||
wallsMovements(delta_time, gc);
|
||||
}
|
||||
}
|
||||
|
||||
export function gameLoopSpectator()
|
||||
{
|
||||
delta_time = c.fixedDeltaTime;
|
||||
|
||||
// interpolation
|
||||
if (gc.playerLeft.dir.y != 0 ) {
|
||||
racketInterpolation(delta_time, gc.playerLeft, clientInfoSpectator.playerLeftNextPos);
|
||||
}
|
||||
if (gc.playerRight.dir.y != 0 ) {
|
||||
racketInterpolation(delta_time, gc.playerRight, clientInfoSpectator.playerRightNextPos);
|
||||
}
|
||||
|
||||
// client prediction
|
||||
gc.ballsArr.forEach((ball) => {
|
||||
ball.moveAndBounce(delta_time, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]);
|
||||
});
|
||||
|
||||
if (matchOptions & en.MatchOptions.movingWalls) {
|
||||
wallsMovements(delta_time, gc);
|
||||
}
|
||||
}
|
||||
|
||||
function racketInterpolation(delta: number, racket: RacketClient, nextPos: VectorInteger)
|
||||
{
|
||||
// interpolation
|
||||
racket.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]);
|
||||
|
||||
if ((racket.dir.y > 0 && racket.pos.y > nextPos.y)
|
||||
|| (racket.dir.y < 0 && racket.pos.y < nextPos.y))
|
||||
{
|
||||
racket.dir.y = 0;
|
||||
racket.pos.y = nextPos.y;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
import * as en from "../shared_js/enums.js";
|
||||
import type { GameArea } from "./class/GameArea.js";
|
||||
import type { GameComponentsClient } from "./class/GameComponentsClient.js";
|
||||
|
||||
// export {pong, gc, matchOptions} from "./pong.js"
|
||||
export {socket, clientInfo, clientInfoSpectator} from "./ws.js"
|
||||
|
||||
export let pong: GameArea;
|
||||
export let gc: GameComponentsClient;
|
||||
export let matchOptions: en.MatchOptions = en.MatchOptions.noOption;
|
||||
|
||||
export function initPong(value: GameArea) {
|
||||
pong = value;
|
||||
}
|
||||
|
||||
export function initGc(value: GameComponentsClient) {
|
||||
gc = value;
|
||||
}
|
||||
|
||||
export function initMatchOptions(value: en.MatchOptions) {
|
||||
matchOptions = value;
|
||||
}
|
||||
|
||||
export let startFunction: () => void;
|
||||
|
||||
export function initStartFunction(value: () => void) {
|
||||
startFunction = value;
|
||||
}
|
||||
@@ -20,7 +20,7 @@ const inputHistoryArr: InputHistory[] = [];
|
||||
socket.send(JSON.stringify(inputState));
|
||||
} */
|
||||
|
||||
function handleInput()
|
||||
export function handleInput()
|
||||
{
|
||||
/* last_time = actual_time;
|
||||
actual_time = Date.now();
|
||||
@@ -86,7 +86,7 @@ function playerMovePrediction(delta: number, input: en.InputEnum)
|
||||
racket.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]);
|
||||
}
|
||||
|
||||
function repeatInput(lastInputId: number)
|
||||
export function repeatInput(lastInputId: number)
|
||||
{
|
||||
// server reconciliation
|
||||
let i = inputHistoryArr.findIndex((value: InputHistory) => {
|
||||
@@ -106,5 +106,3 @@ function repeatInput(lastInputId: number)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export {handleInput, repeatInput}
|
||||
@@ -0,0 +1,80 @@
|
||||
|
||||
import * as c from "./constants.js"
|
||||
import { gc } from "./global.js"
|
||||
import * as en from "../shared_js/enums.js"
|
||||
|
||||
/*
|
||||
before game
|
||||
*/
|
||||
export function matchmaking()
|
||||
{
|
||||
const text = "searching...";
|
||||
console.log(text);
|
||||
gc.text1.clear();
|
||||
gc.text1.pos.assign(c.w*0.2, c.h*0.5);
|
||||
gc.text1.text = text;
|
||||
gc.text1.update();
|
||||
}
|
||||
|
||||
export function matchmakingComplete()
|
||||
{
|
||||
const text = "match found !";
|
||||
console.log(text);
|
||||
gc.text1.clear();
|
||||
gc.text1.pos.assign(c.w*0.15, c.h*0.5);
|
||||
gc.text1.text = text;
|
||||
gc.text1.update();
|
||||
}
|
||||
|
||||
export function matchAbort()
|
||||
{
|
||||
const text = "match abort";
|
||||
console.log(text);
|
||||
gc.text1.clear();
|
||||
gc.text1.pos.assign(c.w*0.15, c.h*0.5);
|
||||
gc.text1.text = text;
|
||||
gc.text1.update();
|
||||
|
||||
setTimeout(() => {
|
||||
gc.text2.pos.assign(c.w*0.44, c.h*0.6);
|
||||
gc.text2.text = "pardon =(";
|
||||
const oriSize = gc.text2.size;
|
||||
gc.text2.size = c.w*0.025;
|
||||
gc.text2.update();
|
||||
gc.text2.size = oriSize;
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
in game
|
||||
*/
|
||||
export function win()
|
||||
{
|
||||
gc.text1.pos.assign(c.w*0.415, c.h*0.5);
|
||||
gc.text1.text = "WIN";
|
||||
}
|
||||
|
||||
export function lose()
|
||||
{
|
||||
gc.text1.pos.assign(c.w*0.383, c.h*0.5);
|
||||
gc.text1.text = "LOSE";
|
||||
}
|
||||
|
||||
export function forfeit(playerSide: en.PlayerSide)
|
||||
{
|
||||
if (playerSide === en.PlayerSide.left) {
|
||||
gc.text2.pos.assign(c.w*0.65, c.h*0.42);
|
||||
gc.text3.pos.assign(c.w*0.65, c.h*0.52);
|
||||
}
|
||||
else {
|
||||
gc.text2.pos.assign(c.w*0.09, c.h*0.42);
|
||||
gc.text3.pos.assign(c.w*0.09, c.h*0.52);
|
||||
}
|
||||
setTimeout(() => {
|
||||
gc.text2.text = "par forfait";
|
||||
}, 1500);
|
||||
setTimeout(() => {
|
||||
gc.text3.text = "calme ta joie";
|
||||
}, 3500);
|
||||
}
|
||||
@@ -17,15 +17,10 @@ import { initWebSocket } from "./ws.js";
|
||||
import { initAudio } from "./audio.js";
|
||||
|
||||
|
||||
/* Keys
|
||||
Racket: W/S OR Up/Down
|
||||
Grid On-Off: G
|
||||
*/
|
||||
|
||||
/* TODO: A way to delay the init of variables, but still use "const" not "let" ? */
|
||||
export let pong: GameArea;
|
||||
export let gc: GameComponentsClient;
|
||||
export let matchOptions: en.MatchOptions = en.MatchOptions.noOption;
|
||||
import { pong, gc } from "./global.js"
|
||||
import { initPong, initGc, initMatchOptions, initStartFunction } from "./global.js"
|
||||
|
||||
|
||||
function init()
|
||||
{
|
||||
@@ -39,48 +34,35 @@ function init()
|
||||
}
|
||||
initAudio(soundMutedFlag);
|
||||
|
||||
let matchOptions: en.MatchOptions = en.MatchOptions.noOption;
|
||||
if ( (<HTMLInputElement>document.getElementById("multi_balls")).checked ) {
|
||||
matchOptions |= en.MatchOptions.multiBalls;
|
||||
}
|
||||
if ( (<HTMLInputElement>document.getElementById("moving_walls")).checked ) {
|
||||
matchOptions |= en.MatchOptions.movingWalls;
|
||||
}
|
||||
initMatchOptions(matchOptions);
|
||||
|
||||
document.getElementById("div_game_options").hidden = true;
|
||||
document.getElementById("div_game_options").remove();
|
||||
document.getElementById("div_game_instructions").remove();
|
||||
|
||||
pong = new GameArea();
|
||||
gc = new GameComponentsClient(matchOptions, pong.ctx);
|
||||
initPong(new GameArea());
|
||||
initGc(new GameComponentsClient(matchOptions, pong.ctx));
|
||||
initStartFunction(start);
|
||||
initWebSocket(matchOptions);
|
||||
}
|
||||
|
||||
function matchmaking()
|
||||
function start()
|
||||
{
|
||||
console.log("Searching an opponent...");
|
||||
gc.text1.clear();
|
||||
gc.text1.pos.assign(c.w/5, c.h_mid);
|
||||
gc.text1.text = "Searching...";
|
||||
gc.text1.update();
|
||||
}
|
||||
|
||||
function matchmakingComplete()
|
||||
{
|
||||
console.log("Match Found !");
|
||||
gc.text1.clear();
|
||||
gc.text1.pos.assign(c.w/8, c.h_mid);
|
||||
gc.text1.text = "Match Found !";
|
||||
gc.text1.update();
|
||||
}
|
||||
|
||||
function startGame() {
|
||||
gc.text1.pos.assign(c.w_mid, c.h_mid+c.h/4);
|
||||
gc.text1.pos.assign(c.w*0.5, c.h*0.75);
|
||||
countdown(c.matchStartDelay/1000, (count: number) => {
|
||||
gc.text1.clear();
|
||||
gc.text1.text = `${count}`;
|
||||
gc.text1.update();
|
||||
}, resumeGame);
|
||||
}, resume);
|
||||
}
|
||||
|
||||
function resumeGame()
|
||||
function resume()
|
||||
{
|
||||
gc.text1.text = "";
|
||||
window.addEventListener('keydown', function (e) {
|
||||
@@ -94,6 +76,3 @@ function resumeGame()
|
||||
pong.gameLoopInterval = window.setInterval(gameLoop, c.gameLoopIntervalMS);
|
||||
pong.drawLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS);
|
||||
}
|
||||
|
||||
|
||||
export {matchmaking, matchmakingComplete, startGame}
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
initSpectator();
|
||||
function initSpectator() {
|
||||
// Wip
|
||||
init();
|
||||
}
|
||||
|
||||
import * as c from "./constants.js"
|
||||
import * as en from "../shared_js/enums.js"
|
||||
import { GameArea } from "./class/GameArea.js";
|
||||
import { GameComponentsClient } from "./class/GameComponentsClient.js";
|
||||
import { gameLoopSpectator } from "./gameLoop.js"
|
||||
import { drawLoop } from "./draw.js";
|
||||
import { initWebSocketSpectator } from "./ws.js";
|
||||
import { initAudio } from "./audio.js";
|
||||
|
||||
|
||||
/* TODO: A way to delay the init of variables, but still use "const" not "let" ? */
|
||||
import { pong, gc } from "./global.js"
|
||||
import { initPong, initGc, initMatchOptions, initStartFunction } from "./global.js"
|
||||
|
||||
function init()
|
||||
{
|
||||
initAudio(false);
|
||||
|
||||
// WIP matchOptions
|
||||
let matchOptions: en.MatchOptions = en.MatchOptions.noOption;
|
||||
initMatchOptions(matchOptions);
|
||||
|
||||
|
||||
initPong(new GameArea());
|
||||
initGc(new GameComponentsClient(matchOptions, pong.ctx));
|
||||
initStartFunction(start);
|
||||
initWebSocketSpectator(c.gameSessionIdPLACEHOLDER);
|
||||
}
|
||||
|
||||
function start()
|
||||
{
|
||||
resume();
|
||||
}
|
||||
|
||||
function resume()
|
||||
{
|
||||
pong.gameLoopInterval = window.setInterval(gameLoopSpectator, c.gameLoopIntervalMS);
|
||||
pong.drawLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
export * from "../shared_js/utils.js"
|
||||
|
||||
function countdown(count: number, callback?: (count: number) => void, endCallback?: () => void)
|
||||
export function countdown(count: number, callback?: (count: number) => void, endCallback?: () => void)
|
||||
{
|
||||
console.log("countdown ", count);
|
||||
if (count > 0) {
|
||||
@@ -14,5 +14,3 @@ function countdown(count: number, callback?: (count: number) => void, endCallbac
|
||||
endCallback();
|
||||
}
|
||||
}
|
||||
|
||||
export {countdown}
|
||||
@@ -1,10 +1,10 @@
|
||||
|
||||
import * as c from "./constants.js"
|
||||
import { gc, matchOptions } from "./global.js"
|
||||
import { gc, matchOptions, startFunction } from "./global.js"
|
||||
import * as ev from "../shared_js/class/Event.js"
|
||||
import * as en from "../shared_js/enums.js"
|
||||
import { matchmaking, matchmakingComplete, startGame } from "./pong.js";
|
||||
import { RacketClient } from "./class/RectangleClient.js";
|
||||
import * as msg from "./message.js";
|
||||
import type { RacketClient } from "./class/RectangleClient.js";
|
||||
import { repeatInput } from "./handleInput.js";
|
||||
import { soundRoblox } from "./audio.js"
|
||||
import { sleep } from "./utils.js";
|
||||
@@ -18,16 +18,24 @@ class ClientInfo {
|
||||
opponentNextPos: VectorInteger;
|
||||
}
|
||||
|
||||
class ClientInfoSpectator {
|
||||
// side: en.PlayerSide;
|
||||
/* WIP: playerLeftNextPos and playerRightNextPos could be in clientInfo for simplicity */
|
||||
playerLeftNextPos: VectorInteger;
|
||||
playerRightNextPos: VectorInteger;
|
||||
}
|
||||
|
||||
const wsPort = 8042;
|
||||
const wsUrl = "ws://" + document.location.hostname + ":" + wsPort + "/pong";
|
||||
const wsUrl = "ws://transcendance:" + wsPort + "/pong";
|
||||
export let socket: WebSocket; /* TODO: A way to still use "const" not "let" ? */
|
||||
export const clientInfo = new ClientInfo();
|
||||
export const clientInfoSpectator = new ClientInfoSpectator(); // WIP, could refactor this
|
||||
|
||||
export function initWebSocket(options: en.MatchOptions)
|
||||
{
|
||||
socket = new WebSocket(wsUrl, "json");
|
||||
socket.addEventListener("open", (event) => {
|
||||
socket.send(JSON.stringify( new ev.ClientAnnounce(en.ClientRole.player, options, clientInfo.id) ));
|
||||
socket.send(JSON.stringify( new ev.ClientAnnouncePlayer(options, clientInfo.id) ));
|
||||
});
|
||||
// socket.addEventListener("message", logListener); // for testing purpose
|
||||
socket.addEventListener("message", preMatchListener);
|
||||
@@ -45,7 +53,7 @@ function preMatchListener(this: WebSocket, event: MessageEvent)
|
||||
clientInfo.id = (<ev.EventAssignId>data).id;
|
||||
break;
|
||||
case en.EventTypes.matchmakingInProgress:
|
||||
matchmaking();
|
||||
msg.matchmaking();
|
||||
break;
|
||||
case en.EventTypes.matchmakingComplete:
|
||||
clientInfo.side = (<ev.EventMatchmakingComplete>data).side;
|
||||
@@ -62,17 +70,21 @@ function preMatchListener(this: WebSocket, event: MessageEvent)
|
||||
clientInfo.opponentNextPos = new VectorInteger(clientInfo.opponent.pos.x, clientInfo.opponent.pos.y);
|
||||
clientInfo.racket.color = "darkgreen"; // for testing purpose
|
||||
socket.send(JSON.stringify( new ev.ClientEvent(en.EventTypes.clientPlayerReady) )); // TODO: set an interval/timeout to resend until matchStart response (in case of network problem)
|
||||
matchmakingComplete();
|
||||
msg.matchmakingComplete();
|
||||
break;
|
||||
case en.EventTypes.matchStart:
|
||||
socket.removeEventListener("message", preMatchListener);
|
||||
socket.addEventListener("message", inGameListener);
|
||||
startGame();
|
||||
startFunction();
|
||||
break;
|
||||
case en.EventTypes.matchAbort:
|
||||
socket.removeEventListener("message", preMatchListener);
|
||||
msg.matchAbort();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function inGameListener(event: MessageEvent)
|
||||
function inGameListener(this: WebSocket, event: MessageEvent)
|
||||
{
|
||||
const data: ev.ServerEvent = JSON.parse(event.data);
|
||||
switch (data.type) {
|
||||
@@ -169,14 +181,122 @@ function scoreUpdate(data: ev.EventScoreUpdate)
|
||||
function matchEnd(data: ev.EventMatchEnd)
|
||||
{
|
||||
if (data.winner === clientInfo.side) {
|
||||
gc.text1.pos.assign(c.w*0.415, c.h_mid);
|
||||
gc.text1.text = "WIN";
|
||||
msg.win();
|
||||
if (data.forfeit) {
|
||||
msg.forfeit(clientInfo.side);
|
||||
}
|
||||
}
|
||||
else {
|
||||
gc.text1.pos.assign(c.w*0.383, c.h_mid);
|
||||
gc.text1.text = "LOSE";
|
||||
msg.lose();
|
||||
}
|
||||
// matchEnded = true;
|
||||
// matchEnded = true; // unused
|
||||
}
|
||||
|
||||
// export let matchEnded = false;
|
||||
// export let matchEnded = false; // unused
|
||||
|
||||
|
||||
|
||||
/* Spectator */
|
||||
|
||||
export function initWebSocketSpectator(gameSessionId: string)
|
||||
{
|
||||
socket = new WebSocket(wsUrl, "json");
|
||||
socket.addEventListener("open", (event) => {
|
||||
socket.send(JSON.stringify( new ev.ClientAnnounceSpectator(gameSessionId) ));
|
||||
});
|
||||
// socket.addEventListener("message", logListener); // for testing purpose
|
||||
socket.addEventListener("message", preMatchListenerSpectator);
|
||||
|
||||
clientInfoSpectator.playerLeftNextPos = new VectorInteger(gc.playerLeft.pos.x, gc.playerLeft.pos.y);
|
||||
clientInfoSpectator.playerRightNextPos = new VectorInteger(gc.playerRight.pos.x, gc.playerRight.pos.y);
|
||||
|
||||
}
|
||||
|
||||
export function preMatchListenerSpectator(this: WebSocket, event: MessageEvent)
|
||||
{
|
||||
const data: ev.ServerEvent = JSON.parse(event.data);
|
||||
if (data.type === en.EventTypes.matchStart)
|
||||
{
|
||||
socket.removeEventListener("message", preMatchListenerSpectator);
|
||||
socket.addEventListener("message", inGameListenerSpectator);
|
||||
startFunction();
|
||||
}
|
||||
}
|
||||
|
||||
function inGameListenerSpectator(this: WebSocket, event: MessageEvent)
|
||||
{
|
||||
const data: ev.ServerEvent = JSON.parse(event.data);
|
||||
switch (data.type) {
|
||||
case en.EventTypes.gameUpdate:
|
||||
gameUpdateSpectator(data as ev.EventGameUpdate);
|
||||
break;
|
||||
case en.EventTypes.scoreUpdate:
|
||||
scoreUpdateSpectator(data as ev.EventScoreUpdate);
|
||||
break;
|
||||
case en.EventTypes.matchEnd:
|
||||
matchEndSpectator(data as ev.EventMatchEnd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function gameUpdateSpectator(data: ev.EventGameUpdate)
|
||||
{
|
||||
console.log("gameUpdateSpectator");
|
||||
|
||||
if (matchOptions & en.MatchOptions.movingWalls) {
|
||||
gc.wallTop.pos.y = data.wallTop.y;
|
||||
gc.wallBottom.pos.y = data.wallBottom.y;
|
||||
}
|
||||
|
||||
data.ballsArr.forEach((ball, i) => {
|
||||
gc.ballsArr[i].pos.assign(ball.x, ball.y);
|
||||
gc.ballsArr[i].dir.assign(ball.dirX, ball.dirY);
|
||||
gc.ballsArr[i].speed = ball.speed;
|
||||
});
|
||||
|
||||
// interpolation
|
||||
for (const racket of [gc.playerLeft, gc.playerRight])
|
||||
{
|
||||
let nextPos: VectorInteger;
|
||||
if (racket === gc.playerLeft) {
|
||||
nextPos = clientInfoSpectator.playerLeftNextPos;
|
||||
}
|
||||
else {
|
||||
nextPos = clientInfoSpectator.playerRightNextPos;
|
||||
}
|
||||
|
||||
racket.pos.assign(nextPos.x, nextPos.y);
|
||||
if (racket === gc.playerLeft) {
|
||||
nextPos.assign(racket.pos.x, data.playerLeft.y);
|
||||
}
|
||||
else {
|
||||
nextPos.assign(racket.pos.x, data.playerRight.y);
|
||||
}
|
||||
|
||||
racket.dir = new Vector(
|
||||
nextPos.x - racket.pos.x,
|
||||
nextPos.y - racket.pos.y
|
||||
);
|
||||
|
||||
if (Math.abs(racket.dir.x) + Math.abs(racket.dir.y) !== 0) {
|
||||
racket.dir = racket.dir.normalized();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function scoreUpdateSpectator(data: ev.EventScoreUpdate)
|
||||
{
|
||||
console.log("scoreUpdateSpectator");
|
||||
gc.scoreLeft.value = data.scoreLeft;
|
||||
gc.scoreRight.value = data.scoreRight;
|
||||
}
|
||||
|
||||
function matchEndSpectator(data: ev.EventMatchEnd)
|
||||
{
|
||||
console.log("matchEndSpectator");
|
||||
// WIP
|
||||
/* msg.win();
|
||||
if (data.forfeit) {
|
||||
msg.forfeit(clientInfo.side);
|
||||
} */
|
||||
}
|
||||
@@ -2,14 +2,14 @@
|
||||
import * as en from "../enums.js"
|
||||
|
||||
/* From Server */
|
||||
class ServerEvent {
|
||||
export class ServerEvent {
|
||||
type: en.EventTypes;
|
||||
constructor(type: en.EventTypes = 0) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
class EventAssignId extends ServerEvent {
|
||||
export class EventAssignId extends ServerEvent {
|
||||
id: string;
|
||||
constructor(id: string) {
|
||||
super(en.EventTypes.assignId);
|
||||
@@ -17,7 +17,7 @@ class EventAssignId extends ServerEvent {
|
||||
}
|
||||
}
|
||||
|
||||
class EventMatchmakingComplete extends ServerEvent {
|
||||
export class EventMatchmakingComplete extends ServerEvent {
|
||||
side: en.PlayerSide;
|
||||
constructor(side: en.PlayerSide) {
|
||||
super(en.EventTypes.matchmakingComplete);
|
||||
@@ -25,7 +25,7 @@ class EventMatchmakingComplete extends ServerEvent {
|
||||
}
|
||||
}
|
||||
|
||||
class EventGameUpdate extends ServerEvent {
|
||||
export class EventGameUpdate extends ServerEvent {
|
||||
playerLeft = {
|
||||
y: 0
|
||||
};
|
||||
@@ -51,7 +51,7 @@ class EventGameUpdate extends ServerEvent {
|
||||
}
|
||||
}
|
||||
|
||||
class EventScoreUpdate extends ServerEvent {
|
||||
export class EventScoreUpdate extends ServerEvent {
|
||||
scoreLeft: number;
|
||||
scoreRight: number;
|
||||
constructor(scoreLeft: number, scoreRight: number) {
|
||||
@@ -61,36 +61,52 @@ class EventScoreUpdate extends ServerEvent {
|
||||
}
|
||||
}
|
||||
|
||||
class EventMatchEnd extends ServerEvent {
|
||||
export class EventMatchEnd extends ServerEvent {
|
||||
winner: en.PlayerSide;
|
||||
constructor(winner: en.PlayerSide) {
|
||||
forfeit: boolean;
|
||||
constructor(winner: en.PlayerSide, forfeit = false) {
|
||||
super(en.EventTypes.matchEnd);
|
||||
this.winner = winner;
|
||||
this.forfeit = forfeit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* From Client */
|
||||
class ClientEvent {
|
||||
export class ClientEvent {
|
||||
type: en.EventTypes; // readonly ?
|
||||
constructor(type: en.EventTypes = 0) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
class ClientAnnounce extends ClientEvent {
|
||||
export class ClientAnnounce extends ClientEvent {
|
||||
role: en.ClientRole;
|
||||
clientId: string;
|
||||
matchOptions: en.MatchOptions;
|
||||
constructor(role: en.ClientRole, matchOptions: en.MatchOptions, clientId: string = "") {
|
||||
constructor(role: en.ClientRole) {
|
||||
super(en.EventTypes.clientAnnounce);
|
||||
this.role = role;
|
||||
}
|
||||
}
|
||||
|
||||
export class ClientAnnouncePlayer extends ClientAnnounce {
|
||||
clientId: string;
|
||||
matchOptions: en.MatchOptions;
|
||||
constructor(matchOptions: en.MatchOptions, clientId: string = "") {
|
||||
super(en.ClientRole.player);
|
||||
this.clientId = clientId;
|
||||
this.matchOptions = matchOptions;
|
||||
}
|
||||
}
|
||||
|
||||
class EventInput extends ClientEvent {
|
||||
export class ClientAnnounceSpectator extends ClientAnnounce {
|
||||
gameSessionId: string;
|
||||
constructor(gameSessionId: string) {
|
||||
super(en.ClientRole.spectator);
|
||||
this.gameSessionId = gameSessionId;
|
||||
}
|
||||
}
|
||||
|
||||
export class EventInput extends ClientEvent {
|
||||
input: en.InputEnum;
|
||||
id: number;
|
||||
constructor(input: en.InputEnum = en.InputEnum.noInput, id: number = 0) {
|
||||
@@ -99,9 +115,3 @@ class EventInput extends ClientEvent {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
ServerEvent, EventAssignId, EventMatchmakingComplete,
|
||||
EventGameUpdate, EventScoreUpdate, EventMatchEnd,
|
||||
ClientEvent, ClientAnnounce, EventInput
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import { VectorInteger } from "./Vector.js";
|
||||
import { Rectangle, MovingRectangle, Racket, Ball } from "./Rectangle.js";
|
||||
import { random } from "../utils.js";
|
||||
|
||||
class GameComponents {
|
||||
export class GameComponents {
|
||||
wallTop: Rectangle | MovingRectangle;
|
||||
wallBottom: Rectangle | MovingRectangle;
|
||||
playerLeft: Racket;
|
||||
@@ -61,5 +61,3 @@ class GameComponents {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {GameComponents}
|
||||
@@ -3,7 +3,7 @@ import { Vector, VectorInteger } from "./Vector.js";
|
||||
import { Component, Moving } from "./interface.js";
|
||||
import * as c from "../constants.js"
|
||||
|
||||
class Rectangle implements Component {
|
||||
export class Rectangle implements Component {
|
||||
pos: VectorInteger;
|
||||
width: number;
|
||||
height: number;
|
||||
@@ -33,7 +33,7 @@ class Rectangle implements Component {
|
||||
}
|
||||
}
|
||||
|
||||
class MovingRectangle extends Rectangle implements Moving {
|
||||
export class MovingRectangle extends Rectangle implements Moving {
|
||||
dir: Vector = new Vector(0,0);
|
||||
speed: number;
|
||||
readonly baseSpeed: number;
|
||||
@@ -61,7 +61,7 @@ class MovingRectangle extends Rectangle implements Moving {
|
||||
}
|
||||
}
|
||||
|
||||
class Racket extends MovingRectangle {
|
||||
export class Racket extends MovingRectangle {
|
||||
constructor(pos: VectorInteger, width: number, height: number, baseSpeed: number) {
|
||||
super(pos, width, height, baseSpeed);
|
||||
}
|
||||
@@ -72,13 +72,22 @@ class Racket extends MovingRectangle {
|
||||
}
|
||||
}
|
||||
|
||||
class Ball extends MovingRectangle {
|
||||
export class Ball extends MovingRectangle {
|
||||
readonly speedIncrease: number;
|
||||
ballInPlay: boolean = false;
|
||||
constructor(pos: VectorInteger, size: number, baseSpeed: number, speedIncrease: number) {
|
||||
super(pos, size, size, baseSpeed);
|
||||
this.speedIncrease = speedIncrease;
|
||||
}
|
||||
moveAndBounce(delta: number, colliderArr: Rectangle[]) {
|
||||
this.move(delta);
|
||||
let i = colliderArr.findIndex(this.collision, this);
|
||||
if (i != -1)
|
||||
{
|
||||
this.bounce(colliderArr[i]);
|
||||
this.move(delta);
|
||||
}
|
||||
}
|
||||
bounce(collider?: Rectangle) {
|
||||
this._bounceAlgo(collider);
|
||||
}
|
||||
@@ -92,15 +101,6 @@ class Ball extends MovingRectangle {
|
||||
this._bounceWall();
|
||||
}
|
||||
}
|
||||
moveAndBounce(delta: number, colliderArr: Rectangle[]) {
|
||||
this.move(delta);
|
||||
let i = colliderArr.findIndex(this.collision, this);
|
||||
if (i != -1)
|
||||
{
|
||||
this.bounce(colliderArr[i]);
|
||||
this.move(delta);
|
||||
}
|
||||
}
|
||||
protected _bounceWall() { // Should be enough for Wall
|
||||
this.dir.y = this.dir.y * -1;
|
||||
}
|
||||
@@ -140,5 +140,3 @@ class Ball extends MovingRectangle {
|
||||
// console.log(`x: ${this.dir.x}, y: ${this.dir.y}`);
|
||||
}
|
||||
}
|
||||
|
||||
export {Rectangle, MovingRectangle, Racket, Ball}
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
class Vector {
|
||||
export class Vector {
|
||||
x: number;
|
||||
y: number;
|
||||
constructor(x: number = 0, y: number = 0) {
|
||||
@@ -16,13 +16,13 @@ class Vector {
|
||||
}
|
||||
}
|
||||
|
||||
class VectorInteger extends Vector {
|
||||
export class VectorInteger extends Vector {
|
||||
// PLACEHOLDER
|
||||
// VectorInteger with set/get dont work (No draw on the screen). Why ?
|
||||
}
|
||||
|
||||
/*
|
||||
class VectorInteger {
|
||||
export class VectorInteger {
|
||||
// private _x: number = 0;
|
||||
// private _y: number = 0;
|
||||
// constructor(x: number = 0, y: number = 0) {
|
||||
@@ -45,5 +45,3 @@ class VectorInteger {
|
||||
// }
|
||||
}
|
||||
*/
|
||||
|
||||
export {Vector, VectorInteger}
|
||||
@@ -1,21 +1,19 @@
|
||||
|
||||
import { Vector, VectorInteger } from "./Vector.js";
|
||||
|
||||
interface Component {
|
||||
export interface Component {
|
||||
pos: VectorInteger;
|
||||
}
|
||||
|
||||
interface GraphicComponent extends Component {
|
||||
export interface GraphicComponent extends Component {
|
||||
ctx: CanvasRenderingContext2D;
|
||||
color: string;
|
||||
update: () => void;
|
||||
clear: (pos?: VectorInteger) => void;
|
||||
}
|
||||
|
||||
interface Moving {
|
||||
export interface Moving {
|
||||
dir: Vector;
|
||||
speed: number; // pixel per second
|
||||
move(delta: number): void;
|
||||
}
|
||||
|
||||
export {Component, GraphicComponent, Moving}
|
||||
@@ -24,3 +24,7 @@ export const newRoundDelay = 1500; // millisecond
|
||||
export const multiBallsCount = 3;
|
||||
export const movingWallPosMax = Math.floor(w*0.12);
|
||||
export const movingWallSpeed = Math.floor(w*0.08);
|
||||
|
||||
|
||||
export const gameSessionIdPLACEHOLDER = "42"; // TESTING SPECTATOR PLACEHOLDER
|
||||
// for testing, force gameSession.id in wsServer.ts->matchmaking()
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
enum EventTypes {
|
||||
export enum EventTypes {
|
||||
// Class Implemented
|
||||
gameUpdate = 1,
|
||||
scoreUpdate,
|
||||
@@ -10,6 +10,7 @@ enum EventTypes {
|
||||
// Generic
|
||||
matchmakingInProgress,
|
||||
matchStart,
|
||||
matchAbort,
|
||||
matchNewRound, // unused
|
||||
matchPause, // unused
|
||||
matchResume, // unused
|
||||
@@ -21,27 +22,25 @@ enum EventTypes {
|
||||
|
||||
}
|
||||
|
||||
enum InputEnum {
|
||||
export enum InputEnum {
|
||||
noInput = 0,
|
||||
up = 1,
|
||||
down,
|
||||
}
|
||||
|
||||
enum PlayerSide {
|
||||
export enum PlayerSide {
|
||||
left = 1,
|
||||
right
|
||||
}
|
||||
|
||||
enum ClientRole {
|
||||
export enum ClientRole {
|
||||
player = 1,
|
||||
spectator
|
||||
}
|
||||
|
||||
enum MatchOptions {
|
||||
export enum MatchOptions {
|
||||
// binary flags, can be mixed
|
||||
noOption = 0b0,
|
||||
multiBalls = 1 << 0,
|
||||
movingWalls = 1 << 1
|
||||
}
|
||||
|
||||
export {EventTypes, InputEnum, PlayerSide, ClientRole, MatchOptions}
|
||||
@@ -1,15 +1,15 @@
|
||||
|
||||
import { MovingRectangle } from "./class/Rectangle.js";
|
||||
|
||||
function random(min: number = 0, max: number = 1) {
|
||||
export function random(min: number = 0, max: number = 1) {
|
||||
return Math.random() * (max - min) + min;
|
||||
}
|
||||
|
||||
function sleep (ms: number) {
|
||||
export function sleep (ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
function clamp(n: number, min: number, max: number) : number
|
||||
export function clamp(n: number, min: number, max: number) : number
|
||||
{
|
||||
if (n < min)
|
||||
n = min;
|
||||
@@ -19,9 +19,7 @@ function clamp(n: number, min: number, max: number) : number
|
||||
}
|
||||
|
||||
// Typescript hack, unused
|
||||
function assertMovingRectangle(value: unknown): asserts value is MovingRectangle {
|
||||
export function assertMovingRectangle(value: unknown): asserts value is MovingRectangle {
|
||||
// if (value !== MovingRectangle) throw new Error("Not a MovingRectangle");
|
||||
return;
|
||||
}
|
||||
|
||||
export {random, sleep, clamp, assertMovingRectangle}
|
||||
@@ -3,7 +3,7 @@ import * as c from "./constants.js";
|
||||
import { MovingRectangle } from "../shared_js/class/Rectangle.js";
|
||||
import { GameComponents } from "./class/GameComponents.js";
|
||||
|
||||
function wallsMovements(delta: number, gc: GameComponents)
|
||||
export function wallsMovements(delta: number, gc: GameComponents)
|
||||
{
|
||||
const wallTop = <MovingRectangle>gc.wallTop;
|
||||
const wallBottom = <MovingRectangle>gc.wallBottom;
|
||||
@@ -16,5 +16,3 @@ function wallsMovements(delta: number, gc: GameComponents)
|
||||
wallTop.moveAndCollide(delta, [gc.playerLeft, gc.playerRight]);
|
||||
wallBottom.moveAndCollide(delta, [gc.playerLeft, gc.playerRight]);
|
||||
}
|
||||
|
||||
export {wallsMovements}
|
||||
@@ -4,125 +4,15 @@ import SplashPage from "../pages/SplashPage.svelte";
|
||||
import TwoFactorAuthentication from '../pages/TwoFactorAuthentication.svelte';
|
||||
import UnauthorizedAccessPage from '../pages/UnauthorizedAccessPage.svelte';
|
||||
import { wrap } from 'svelte-spa-router/wrap'
|
||||
import { get } from 'svelte/store';
|
||||
import TestPage from '../pages/TmpTestPage.svelte';
|
||||
import Game from '../pages/game/Game.svelte'
|
||||
|
||||
|
||||
|
||||
// "/article/:title": Article, // this is how you would do parameters!
|
||||
// "/": LoginPage,
|
||||
|
||||
// TMP not using this cuz need to work out how to authentical both 42 and 2FA from the backend
|
||||
|
||||
// export const primaryRoutes = {
|
||||
// '/': SplashPage,
|
||||
// // '/2fa': TwoFactorAuthentication,
|
||||
// '/2fa': wrap({
|
||||
// component: TwoFactorAuthentication,
|
||||
// conditions: [
|
||||
// (detail) => {
|
||||
// // let loggedIn;
|
||||
// // loginStatus.subscribe(value => {
|
||||
// // loggedIn = value;
|
||||
// // });
|
||||
|
||||
// const { fortyTwo, tfa } = get(loginStatus);
|
||||
|
||||
// console.log('condition in /2fa');
|
||||
// // return (loginStatus.fortyTwo && loginStatus.tfa);
|
||||
// // console.log($loginStatus.fortyTwo)
|
||||
// console.log(fortyTwo);
|
||||
// console.log(tfa);
|
||||
// return true;
|
||||
// }
|
||||
// ]
|
||||
// }),
|
||||
// '/profile': wrap({
|
||||
// component: ProfilePage,
|
||||
// conditions: [
|
||||
// (detail) => {
|
||||
// const { fortyTwo, tfa } = get(loginStatus);
|
||||
// // console.log(fortyTwo);
|
||||
// // console.log(tfa);
|
||||
// // return true;
|
||||
// return (fortyTwo && tfa);
|
||||
// }
|
||||
// ]
|
||||
// }),
|
||||
// '/profile/*': wrap({
|
||||
// component: ProfilePage,
|
||||
// conditions: [
|
||||
// (detail) => {
|
||||
// const { fortyTwo, tfa } = get(loginStatus);
|
||||
// // console.log(fortyTwo);
|
||||
// // console.log(tfa);
|
||||
// // return true;
|
||||
// return (fortyTwo && tfa);
|
||||
// }
|
||||
// ]
|
||||
// }),
|
||||
// '/profile': wrap({
|
||||
// // Use a dynamically-loaded component for this
|
||||
// asyncComponent: () => import('./ProfilePage.svelte'),
|
||||
// // Adding one pre-condition that's an async function
|
||||
// conditions: [
|
||||
// async (detail) => {
|
||||
// // Make a network request, which are async operations
|
||||
// const response = await fetch('http://transcendance:8080/api/v2/user')
|
||||
// const data = await response.json()
|
||||
// // Return true to continue loading the component, or false otherwise
|
||||
// if (data.isAdmin) {
|
||||
// return true
|
||||
// }
|
||||
// else {
|
||||
// return false
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// }),
|
||||
// '/unauthorized-access': UnauthorizedAccessPage,
|
||||
// '*': NotFound
|
||||
// };
|
||||
|
||||
export const primaryRoutes = {
|
||||
'/': SplashPage,
|
||||
'/2fa': TwoFactorAuthentication,
|
||||
// '/test': wrap({
|
||||
// component: TestPage,
|
||||
// conditions: [
|
||||
// (detail) => {
|
||||
// const user = get(userStore); // seems like get(store) is not an option
|
||||
// // // const user = userStore;
|
||||
// // // console.log(fortyTwo);
|
||||
// // // console.log(tfa);
|
||||
// // console.log('in /test what is in user')
|
||||
// // console.log(user)
|
||||
|
||||
// // you moron $userStore is a Svelte Abreviation, this is .JS, duh
|
||||
// // let user = $userStore;
|
||||
// // let user;
|
||||
// // const unsub = userStore.subscribe(value => {
|
||||
// // console.log(value);
|
||||
// // user = value;
|
||||
// // });
|
||||
// console.log('in /test what is in userStore directly')
|
||||
// console.log(user)
|
||||
|
||||
// // return true;
|
||||
// // obvi this doesn't work cuz skips to true after no user...
|
||||
// // you gotta make the condition the true and the everything else false
|
||||
// // if (user && user.statusCode && user.statusCode === 403)
|
||||
// // if (user && user.username) {
|
||||
// if (user !== null) {
|
||||
// unsub();
|
||||
// return true;
|
||||
// } else {
|
||||
// unsub();
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// }),
|
||||
'/game': Game,
|
||||
'/test': wrap({
|
||||
component: TestPage,
|
||||
conditions: [
|
||||
@@ -141,9 +31,7 @@ export const primaryRoutes = {
|
||||
return false;
|
||||
}
|
||||
],
|
||||
// props: {
|
||||
// user: user
|
||||
// }
|
||||
|
||||
}),
|
||||
'/profile': wrap({
|
||||
component: ProfilePage,
|
||||
@@ -179,82 +67,7 @@ export const primaryRoutes = {
|
||||
}
|
||||
]
|
||||
}),
|
||||
// '/game': wrap({
|
||||
// component: ProfilePage,
|
||||
// conditions: [
|
||||
// async(detail) => {
|
||||
// const user = await fetch('http://transcendance:8080/api/v2/user')
|
||||
// .then((resp) => resp.json())
|
||||
|
||||
// console.log('in /test what is in user')
|
||||
// console.log(user)
|
||||
|
||||
// if (user && user.username)
|
||||
// return true;
|
||||
// else
|
||||
// return false;
|
||||
// }
|
||||
// ]
|
||||
// }),
|
||||
// '/spectate': wrap({
|
||||
// component: ProfilePage,
|
||||
// conditions: [
|
||||
// async(detail) => {
|
||||
// const user = await fetch('http://transcendance:8080/api/v2/user')
|
||||
// .then((resp) => resp.json())
|
||||
|
||||
// console.log('in /test what is in user')
|
||||
// console.log(user)
|
||||
|
||||
// if (user && user.username)
|
||||
// return true;
|
||||
// else
|
||||
// return false;
|
||||
// }
|
||||
// ]
|
||||
// }),
|
||||
// '/chat': wrap({
|
||||
// component: ProfilePage,
|
||||
// conditions: [
|
||||
// async(detail) => {
|
||||
// const user = await fetch('http://transcendance:8080/api/v2/user')
|
||||
// .then((resp) => resp.json())
|
||||
|
||||
// console.log('in /test what is in user')
|
||||
// console.log(user)
|
||||
|
||||
// if (user && user.username)
|
||||
// return true;
|
||||
// else
|
||||
// return false;
|
||||
// }
|
||||
// ]
|
||||
// }),
|
||||
'/unauthorized-access': UnauthorizedAccessPage,
|
||||
'*': NotFound
|
||||
};
|
||||
|
||||
// export const primaryRoutes = {
|
||||
// "/": SplashPage,
|
||||
// "/profile": ProfilePage,
|
||||
// "/game": GamePage,
|
||||
// "/chat": ChatPage,
|
||||
// "*": NotFound
|
||||
// };
|
||||
|
||||
|
||||
// i might need to add /profile/* and such to make the nested routers work
|
||||
|
||||
// ok maybe these need to be in their own files?
|
||||
|
||||
|
||||
|
||||
// export const gameRoutes = {
|
||||
// "/": GamePage,
|
||||
// "*": NotFound
|
||||
// };
|
||||
|
||||
// export const chatRoutes = {
|
||||
// "/": ChatPage,
|
||||
// "*": NotFound
|
||||
// };
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user