input desynchro, rollback to instant handle.
This commit is contained in:
1
memo.txt
1
memo.txt
@@ -10,6 +10,7 @@ Done:
|
|||||||
- draw on the canvas "WIN", "LOSE", "MATCHMAKING COMPLETE", ...
|
- draw on the canvas "WIN", "LOSE", "MATCHMAKING COMPLETE", ...
|
||||||
- interpolation (mis à jour progressif des mouvements de l'adversaire)
|
- interpolation (mis à jour progressif des mouvements de l'adversaire)
|
||||||
- traitement groupé des inputs clients toutes les x millisecondes
|
- traitement groupé des inputs clients toutes les x millisecondes
|
||||||
|
(BUG désynchronisation: revenu à un traitement immédiat en attendant)
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
- mode multi-balles
|
- mode multi-balles
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
|
|
||||||
import * as en from "../../shared_js/enums.js"
|
import * as en from "../../shared_js/enums.js"
|
||||||
|
import * as ev from "../../shared_js/class/Event.js"
|
||||||
|
|
||||||
class InputHistory {
|
class InputHistory {
|
||||||
input: en.InputEnum;
|
input: en.InputEnum;
|
||||||
inputId: number;
|
id: number;
|
||||||
deltaTime: number;
|
deltaTime: number;
|
||||||
constructor(input: en.InputEnum, inputId: number, deltaTime: number) {
|
constructor(inputState: ev.EventInput, deltaTime: number) {
|
||||||
this.input = input;
|
this.input = inputState.input;
|
||||||
this.inputId = inputId;
|
this.id = inputState.id;
|
||||||
this.deltaTime = deltaTime;
|
this.deltaTime = deltaTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +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 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 soundMutedFlag = true;
|
export const soundMutedFlag = true;
|
||||||
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
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
|
import * as c from "./constants.js";
|
||||||
import { gc, clientInfo } from "./global.js";
|
import { gc, clientInfo } from "./global.js";
|
||||||
|
|
||||||
let actual_time: number = Date.now();
|
let actual_time: number = Date.now();
|
||||||
@@ -7,9 +8,12 @@ let delta_time: number;
|
|||||||
|
|
||||||
function gameLoop()
|
function gameLoop()
|
||||||
{
|
{
|
||||||
last_time = actual_time;
|
/* last_time = actual_time;
|
||||||
actual_time = Date.now();
|
actual_time = Date.now();
|
||||||
delta_time = (actual_time - last_time) / 1000;
|
delta_time = (actual_time - last_time) / 1000; */
|
||||||
|
|
||||||
|
delta_time = c.fixedDeltaTime;
|
||||||
|
// console.log(`delta_gameLoop: ${delta_time}`);
|
||||||
|
|
||||||
// interpolation
|
// interpolation
|
||||||
// console.log(`dir.y: ${clientInfo.opponent.dir.y}, pos.y: ${clientInfo.opponent.pos.y}, opponentNextPos.y: ${clientInfo.opponentNextPos.y}`);
|
// console.log(`dir.y: ${clientInfo.opponent.dir.y}, pos.y: ${clientInfo.opponent.pos.y}, opponentNextPos.y: ${clientInfo.opponentNextPos.y}`);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { pong, gc, socket, clientInfo } 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 { InputHistory } from "./class/InputHistory.js"
|
import { InputHistory } from "./class/InputHistory.js"
|
||||||
|
import * as c from "./constants.js";
|
||||||
|
|
||||||
export let gridDisplay = false;
|
export let gridDisplay = false;
|
||||||
|
|
||||||
@@ -10,58 +11,66 @@ let actual_time: number = Date.now();
|
|||||||
let last_time: number;
|
let last_time: number;
|
||||||
let delta_time: number;
|
let delta_time: number;
|
||||||
|
|
||||||
|
const inputState: ev.EventInput = new ev.EventInput();
|
||||||
const inputHistoryArr: InputHistory[] = [];
|
const inputHistoryArr: InputHistory[] = [];
|
||||||
let id = 0;
|
|
||||||
/* idMax should be high enough to prevent duplicate "id" in "inputHistoryArr".
|
// test
|
||||||
In theory a little more than (1000/handleInputIntervalMS) should be enough. */
|
/* export function sendLoop()
|
||||||
const idMax = 999; // 999 arbitrary
|
{
|
||||||
|
socket.send(JSON.stringify(inputState));
|
||||||
|
} */
|
||||||
|
|
||||||
function handleInput()
|
function handleInput()
|
||||||
{
|
{
|
||||||
last_time = actual_time;
|
/* last_time = actual_time;
|
||||||
actual_time = Date.now();
|
actual_time = Date.now();
|
||||||
delta_time = (actual_time - last_time) / 1000;
|
delta_time = (actual_time - last_time) / 1000; */
|
||||||
|
|
||||||
|
delta_time = c.fixedDeltaTime;
|
||||||
|
// console.log(`delta_time: ${delta_time}`);
|
||||||
|
|
||||||
|
inputState.id = Date.now();
|
||||||
|
inputState.input = en.InputEnum.noInput;
|
||||||
|
|
||||||
const keys = pong.keys;
|
const keys = pong.keys;
|
||||||
if (keys.length == 0) {
|
if (keys.length !== 0)
|
||||||
return;
|
|
||||||
}
|
|
||||||
// console.log("handleInput");
|
|
||||||
if (id > idMax) {
|
|
||||||
id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keys.indexOf("g") != -1)
|
|
||||||
{
|
{
|
||||||
gridDisplay = !gridDisplay;
|
if (keys.indexOf("g") != -1)
|
||||||
pong.deleteKey("g");
|
{
|
||||||
|
gridDisplay = !gridDisplay;
|
||||||
|
pong.deleteKey("g");
|
||||||
|
}
|
||||||
|
playerMovements(delta_time, keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
playerMove(delta_time, keys);
|
socket.send(JSON.stringify(inputState));
|
||||||
|
// setTimeout(testInputDelay, 100);
|
||||||
|
inputHistoryArr.push(new InputHistory(inputState, delta_time));
|
||||||
|
|
||||||
|
// client prediction
|
||||||
|
if (inputState.input !== en.InputEnum.noInput) {
|
||||||
|
// TODO: peut-etre le mettre dans game loop ?
|
||||||
|
// Attention au delta time dans ce cas !
|
||||||
|
playerMovePrediction(delta_time, inputState.input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function playerMove(delta: number, keys: string[])
|
function playerMovements(delta: number, keys: string[])
|
||||||
{
|
{
|
||||||
if (keys.indexOf("w") !== -1 || keys.indexOf("ArrowUp".toLowerCase()) !== -1) {
|
if (keys.indexOf("w") !== -1 || keys.indexOf("ArrowUp".toLowerCase()) !== -1)
|
||||||
|
{
|
||||||
if (keys.indexOf("s") === -1 && keys.indexOf("ArrowDown".toLowerCase()) === -1) {
|
if (keys.indexOf("s") === -1 && keys.indexOf("ArrowDown".toLowerCase()) === -1) {
|
||||||
const input = new ev.EventInput(en.InputEnum.up, ++id);
|
inputState.input = en.InputEnum.up;
|
||||||
inputHistoryArr.push(new InputHistory(input.input, input.inputId, delta));
|
|
||||||
socket.send(JSON.stringify(input));
|
|
||||||
playerMovePrediction(delta, input.input); // client prediction
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (keys.indexOf("s") !== -1 || keys.indexOf("ArrowDown".toLowerCase()) !== -1) {
|
else if (keys.indexOf("s") !== -1 || keys.indexOf("ArrowDown".toLowerCase()) !== -1) {
|
||||||
const input = new ev.EventInput(en.InputEnum.down, ++id);
|
inputState.input = en.InputEnum.down;
|
||||||
inputHistoryArr.push(new InputHistory(input.input, input.inputId, delta));
|
|
||||||
socket.send(JSON.stringify(input));
|
|
||||||
playerMovePrediction(delta, input.input); // client prediction
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testInputDelay(input: ev.EventInput) {
|
function testInputDelay() {
|
||||||
socket.send(JSON.stringify(input));
|
socket.send(JSON.stringify(inputState));
|
||||||
}
|
}
|
||||||
// setTimeout(testInputDelay, 100, input);
|
|
||||||
|
|
||||||
|
|
||||||
function playerMovePrediction(delta: number, input: en.InputEnum)
|
function playerMovePrediction(delta: number, input: en.InputEnum)
|
||||||
@@ -81,16 +90,20 @@ function repeatInput(lastInputId: number)
|
|||||||
{
|
{
|
||||||
// server reconciliation
|
// server reconciliation
|
||||||
let i = inputHistoryArr.findIndex((value: InputHistory) => {
|
let i = inputHistoryArr.findIndex((value: InputHistory) => {
|
||||||
if (value.inputId === lastInputId) {
|
if (value.id === lastInputId) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// console.log(`inputHistory total: ${inputHistoryArr.length}` );
|
||||||
inputHistoryArr.splice(0, i+1);
|
inputHistoryArr.splice(0, i+1);
|
||||||
|
// console.log(`inputHistory left: ${inputHistoryArr.length}` );
|
||||||
|
|
||||||
inputHistoryArr.forEach((value: InputHistory) => {
|
inputHistoryArr.forEach((value: InputHistory) => {
|
||||||
playerMovePrediction(value.deltaTime, value.input);
|
if (value.input !== en.InputEnum.noInput) {
|
||||||
|
playerMovePrediction(value.deltaTime, value.input);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import * as c from "./constants.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";
|
||||||
|
// import { sendLoop } 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";
|
||||||
@@ -54,8 +55,9 @@ function resumeGame()
|
|||||||
pong.deleteKey(e.key);
|
pong.deleteKey(e.key);
|
||||||
});
|
});
|
||||||
pong.handleInputInterval = window.setInterval(handleInput, c.handleInputIntervalMS);
|
pong.handleInputInterval = window.setInterval(handleInput, c.handleInputIntervalMS);
|
||||||
|
// pong.handleInputInterval = window.setInterval(sendLoop, c.sendLoopIntervalMS);
|
||||||
pong.gameLoopInterval = window.setInterval(gameLoop, c.gameLoopIntervalMS);
|
pong.gameLoopInterval = window.setInterval(gameLoop, c.gameLoopIntervalMS);
|
||||||
pong.gameLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS);
|
pong.drawLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -93,6 +93,9 @@ function gameUpdate(data: ev.EventGameUpdate)
|
|||||||
gc.ball.pos.assign(data.ball.x, data.ball.y);
|
gc.ball.pos.assign(data.ball.x, data.ball.y);
|
||||||
gc.ball.dir.assign(data.ball.dirX, data.ball.dirY);
|
gc.ball.dir.assign(data.ball.dirX, data.ball.dirY);
|
||||||
gc.ball.speed = data.ball.speed;
|
gc.ball.speed = data.ball.speed;
|
||||||
|
|
||||||
|
const predictionPos = new VectorInteger(clientInfo.racket.pos.x, clientInfo.racket.pos.y); // debug
|
||||||
|
|
||||||
if (clientInfo.side === en.PlayerSide.left) {
|
if (clientInfo.side === en.PlayerSide.left) {
|
||||||
clientInfo.racket.pos.assign(clientInfo.racket.pos.x, data.playerLeft.y);
|
clientInfo.racket.pos.assign(clientInfo.racket.pos.x, data.playerLeft.y);
|
||||||
}
|
}
|
||||||
@@ -120,11 +123,23 @@ function gameUpdate(data: ev.EventGameUpdate)
|
|||||||
|
|
||||||
// server reconciliation
|
// server reconciliation
|
||||||
repeatInput(data.lastInputId);
|
repeatInput(data.lastInputId);
|
||||||
|
|
||||||
|
// debug
|
||||||
|
if (clientInfo.racket.pos.y > predictionPos.y + 1
|
||||||
|
|| clientInfo.racket.pos.y < predictionPos.y - 1)
|
||||||
|
{
|
||||||
|
console.log(
|
||||||
|
`Reconciliation error:
|
||||||
|
server y: ${data.playerLeft.y}
|
||||||
|
reconciliation y: ${clientInfo.racket.pos.y}
|
||||||
|
prediction y: ${predictionPos.y}`
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function scoreUpdate(data: ev.EventScoreUpdate)
|
function scoreUpdate(data: ev.EventScoreUpdate)
|
||||||
{
|
{
|
||||||
console.log("scoreUpdate");
|
// console.log("scoreUpdate");
|
||||||
if (clientInfo.side === en.PlayerSide.left && data.scoreRight > gc.scoreRight.value) {
|
if (clientInfo.side === en.PlayerSide.left && data.scoreRight > gc.scoreRight.value) {
|
||||||
soundRoblox.play();
|
soundRoblox.play();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class Client {
|
|||||||
isAlive: boolean = true;
|
isAlive: boolean = true;
|
||||||
gameSession: GameSession;
|
gameSession: GameSession;
|
||||||
|
|
||||||
inputBuffer: ev.EventInput;
|
inputBuffer: ev.EventInput = new ev.EventInput();
|
||||||
lastInputId: number = 0;
|
lastInputId: number = 0;
|
||||||
|
|
||||||
constructor(socket: WebSocket, id: string) {
|
constructor(socket: WebSocket, id: string) {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class GameSession {
|
|||||||
});
|
});
|
||||||
|
|
||||||
s.actual_time = Date.now();
|
s.actual_time = Date.now();
|
||||||
s.gameLoopInterval = setInterval(s._gameLoop, c.gameLoopIntervalMS, s);
|
s.gameLoopInterval = setInterval(s._gameLoop, c.serverGameLoopIntervalMS, s);
|
||||||
s.clientsUpdateInterval = setInterval(s._clientsUpdate, c.clientsUpdateIntervalMS, s);
|
s.clientsUpdateInterval = setInterval(s._clientsUpdate, c.clientsUpdateIntervalMS, s);
|
||||||
}
|
}
|
||||||
pause(s: GameSession) {
|
pause(s: GameSession) {
|
||||||
@@ -50,7 +50,11 @@ class GameSession {
|
|||||||
clearInterval(s.gameLoopInterval);
|
clearInterval(s.gameLoopInterval);
|
||||||
clearInterval(s.clientsUpdateInterval);
|
clearInterval(s.clientsUpdateInterval);
|
||||||
}
|
}
|
||||||
|
instantInputDebug(client: ClientPlayer) {
|
||||||
|
this._handleInput(c.fixedDeltaTime, client);
|
||||||
|
}
|
||||||
private _handleInput(delta: number, client: ClientPlayer) {
|
private _handleInput(delta: number, client: ClientPlayer) {
|
||||||
|
// if (client.inputBuffer === null) {return;}
|
||||||
const gc = this.components;
|
const gc = this.components;
|
||||||
const input = client.inputBuffer.input;
|
const input = client.inputBuffer.input;
|
||||||
|
|
||||||
@@ -60,10 +64,13 @@ class GameSession {
|
|||||||
else if (input === en.InputEnum.down) {
|
else if (input === en.InputEnum.down) {
|
||||||
client.racket.dir.y = 1;
|
client.racket.dir.y = 1;
|
||||||
}
|
}
|
||||||
client.racket.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]);
|
|
||||||
|
|
||||||
client.lastInputId = client.inputBuffer.inputId;
|
if (input !== en.InputEnum.noInput) {
|
||||||
client.inputBuffer = null;
|
client.racket.moveAndCollide(delta, [gc.wallTop, gc.wallBottom]);
|
||||||
|
}
|
||||||
|
|
||||||
|
client.lastInputId = client.inputBuffer.id;
|
||||||
|
// client.inputBuffer = null;
|
||||||
}
|
}
|
||||||
private _gameLoop(s: GameSession) {
|
private _gameLoop(s: GameSession) {
|
||||||
/* s.last_time = s.actual_time;
|
/* s.last_time = s.actual_time;
|
||||||
@@ -71,11 +78,10 @@ class GameSession {
|
|||||||
s.delta_time = (s.actual_time - s.last_time) / 1000; */
|
s.delta_time = (s.actual_time - s.last_time) / 1000; */
|
||||||
s.delta_time = c.fixedDeltaTime;
|
s.delta_time = c.fixedDeltaTime;
|
||||||
|
|
||||||
s.playersMap.forEach( (client) => {
|
// WIP, replaced by instantInputDebug() to prevent desynchro
|
||||||
if (client.inputBuffer) {
|
/* s.playersMap.forEach( (client) => {
|
||||||
s._handleInput(s.delta_time, client);
|
s._handleInput(s.delta_time, client);
|
||||||
}
|
}); */
|
||||||
});
|
|
||||||
|
|
||||||
const gc = s.components;
|
const gc = s.components;
|
||||||
if (gc.ballInPlay)
|
if (gc.ballInPlay)
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
export * from "../shared_js/constants.js"
|
export * from "../shared_js/constants.js"
|
||||||
|
|
||||||
// 15ms == 1000/66.666
|
// 15ms == 1000/66.666
|
||||||
export const gameLoopIntervalMS = 15; // millisecond
|
export const serverGameLoopIntervalMS = 15; // millisecond
|
||||||
export const fixedDeltaTime = gameLoopIntervalMS/1000; // second
|
export const fixedDeltaTime = serverGameLoopIntervalMS/1000; // second
|
||||||
|
|
||||||
// 33.333ms == 1000/30
|
// 33.333ms == 1000/30
|
||||||
export const clientsUpdateIntervalMS = 1000/30; // millisecond
|
export const clientsUpdateIntervalMS = 1000/30; // millisecond
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ function clientAnnounceListener(this: WebSocket, data: string)
|
|||||||
try {
|
try {
|
||||||
const msg : ev.ClientAnnounce = JSON.parse(data);
|
const msg : ev.ClientAnnounce = JSON.parse(data);
|
||||||
if (msg.type === en.EventTypes.clientAnnounce) {
|
if (msg.type === en.EventTypes.clientAnnounce) {
|
||||||
// TODO: reconnection with msg.id ?
|
// TODO: reconnection with msg.clientId ?
|
||||||
// TODO: spectator/player distinction with msg.type ?
|
// TODO: spectator/player distinction with msg.role ?
|
||||||
|
|
||||||
this.send(JSON.stringify( new ev.EventAssignId(this.id) ));
|
this.send(JSON.stringify( new ev.EventAssignId(this.id) ));
|
||||||
this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchmakingInProgress) ));
|
this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchmakingInProgress) ));
|
||||||
@@ -152,6 +152,7 @@ export function clientInputListener(this: WebSocket, data: string)
|
|||||||
if (input.type === en.EventTypes.clientInput) {
|
if (input.type === en.EventTypes.clientInput) {
|
||||||
const client = clientsMap.get(this.id) as ClientPlayer;
|
const client = clientsMap.get(this.id) as ClientPlayer;
|
||||||
client.inputBuffer = input;
|
client.inputBuffer = input;
|
||||||
|
client.gameSession.instantInputDebug(client); // wip
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log("Invalid clientInput");
|
console.log("Invalid clientInput");
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class EventMatchEnd extends ServerEvent {
|
|||||||
|
|
||||||
/* From Client */
|
/* From Client */
|
||||||
class ClientEvent {
|
class ClientEvent {
|
||||||
type: en.EventTypes;
|
type: en.EventTypes; // readonly ?
|
||||||
constructor(type: en.EventTypes = 0) {
|
constructor(type: en.EventTypes = 0) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
@@ -74,21 +74,21 @@ class ClientEvent {
|
|||||||
|
|
||||||
class ClientAnnounce extends ClientEvent {
|
class ClientAnnounce extends ClientEvent {
|
||||||
role: en.ClientRole;
|
role: en.ClientRole;
|
||||||
id: string;
|
clientId: string;
|
||||||
constructor(role: en.ClientRole, id: string = "") {
|
constructor(role: en.ClientRole, clientId: string = "") {
|
||||||
super(en.EventTypes.clientAnnounce);
|
super(en.EventTypes.clientAnnounce);
|
||||||
this.role = role;
|
this.role = role;
|
||||||
this.id = id;
|
this.clientId = clientId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EventInput extends ClientEvent {
|
class EventInput extends ClientEvent {
|
||||||
input: en.InputEnum;
|
input: en.InputEnum;
|
||||||
inputId: number;
|
id: number;
|
||||||
constructor(input: en.InputEnum = 0, inputId: number = 0) {
|
constructor(input: en.InputEnum = en.InputEnum.noInput, id: number = 0) {
|
||||||
super(en.EventTypes.clientInput);
|
super(en.EventTypes.clientInput);
|
||||||
this.input = input;
|
this.input = input;
|
||||||
this.inputId = inputId;
|
this.id = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,10 +44,15 @@ class MovingRectangle extends Rectangle implements Moving {
|
|||||||
}
|
}
|
||||||
move(delta: number) { // Math.floor WIP until VectorInteger debug
|
move(delta: number) { // Math.floor WIP until VectorInteger debug
|
||||||
// console.log(`delta: ${delta}, speed: ${this.speed}, speed*delta: ${this.speed * delta}`);
|
// console.log(`delta: ${delta}, speed: ${this.speed}, speed*delta: ${this.speed * delta}`);
|
||||||
this.pos.x += Math.floor(this.dir.x * this.speed * delta);
|
// this.pos.x += Math.floor(this.dir.x * this.speed * delta);
|
||||||
this.pos.y += Math.floor(this.dir.y * this.speed * delta);
|
// this.pos.y += Math.floor(this.dir.y * this.speed * delta);
|
||||||
|
this.pos.x += this.dir.x * this.speed * delta;
|
||||||
|
this.pos.y += this.dir.y * this.speed * delta;
|
||||||
}
|
}
|
||||||
moveAndCollide(delta: number, colliderArr: Rectangle[]) {
|
moveAndCollide(delta: number, colliderArr: Rectangle[]) {
|
||||||
|
this._moveAndCollideAlgo(delta, colliderArr);
|
||||||
|
}
|
||||||
|
protected _moveAndCollideAlgo(delta: number, colliderArr: Rectangle[]) {
|
||||||
let oldPos = new VectorInteger(this.pos.x, this.pos.y);
|
let oldPos = new VectorInteger(this.pos.x, this.pos.y);
|
||||||
this.move(delta);
|
this.move(delta);
|
||||||
if (colliderArr.some(this.collision, this)) {
|
if (colliderArr.some(this.collision, this)) {
|
||||||
@@ -60,6 +65,11 @@ class Racket extends MovingRectangle {
|
|||||||
constructor(pos: VectorInteger, width: number, height: number, baseSpeed: number) {
|
constructor(pos: VectorInteger, width: number, height: number, baseSpeed: number) {
|
||||||
super(pos, width, height, baseSpeed);
|
super(pos, width, height, baseSpeed);
|
||||||
}
|
}
|
||||||
|
moveAndCollide(delta: number, colliderArr: Rectangle[]) {
|
||||||
|
// let oldPos = new VectorInteger(this.pos.x, this.pos.y); // debug
|
||||||
|
this._moveAndCollideAlgo(delta, colliderArr);
|
||||||
|
// console.log(`y change: ${this.pos.y - oldPos.y}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Ball extends MovingRectangle {
|
class Ball extends MovingRectangle {
|
||||||
|
|||||||
@@ -22,8 +22,9 @@ enum EventTypes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum InputEnum {
|
enum InputEnum {
|
||||||
|
noInput = 0,
|
||||||
up = 1,
|
up = 1,
|
||||||
down
|
down,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum PlayerSide {
|
enum PlayerSide {
|
||||||
|
|||||||
Reference in New Issue
Block a user