Skip to content

Instantly share code, notes, and snippets.

View buesing's full-sized avatar

Moriz Büsing buesing

View GitHub Profile
// we interpolate between the actual (received) position and the position
// the user would expect. after 500ms both positions are the same.
const fauxPosition = new Vector3().lerpVectors(
this.physics.ball.position,
new Vector3().addVectors(
this.physics.ball.position,
this.ballPositionDifference
),
this.ballInterpolationAlpha
);
slowdownBall() {
// if the ball is on the way to the opponent,
// we slow it down so it will be on the opponents side
// approximately at the time they actually hit it
// NOTE that we still only receive the hit half a roundtriptime later
if (this.physics.ball.velocity.z > 0) {
return;
}
const velocity = this.physics.ball.velocity.length();
const dist = new Vector3().subVectors(this.ball.position, this.paddleOpponent.position).length();
tryConnecting(id) {
// try to connect to a given room id. the first character is a code for
// which server the opponent is connected to. in case of 2 servers, the
// first half of the available characters is reserved for the first server,
// the second half is reserved for the second server. this way we can still
// have as many random combinations with 4 letters.
this.isHost = false;
return new Promise((resolve, reject) => {
let serverIndex = -1;
this.availablePrefixes.forEach((prefixes, index) => {
$(window).on('beforeunload', () => {
if (this.isOpponentConnected) {
// tell opponent we disconnected
this.statusRecord.set(`player-${this.isHost ? 1 : 2}`, {action: ACTION.DISCONNECT});
}
if (this.statusRecord) {
// delete all records
this.statusRecord.discard();
this.statusRecord.delete();
this.paddle1Record.discard();
sendPings() {
this.pingInterval = setInterval(() => {
this.pings[this.pingNumber] = Date.now();
this.pingRecord.set(`player-${this.isHost ? 1 : 2}-ping-${this.pingNumber}`, {
index: this.pingNumber,
ping: true,
});
this.pingNumber += 1;
if (this.pingNumber >= 20) {
clearInterval(this.pingInterval);
startListening() {
this.statusRecord.subscribe(`player-${this.isHost ? 2 : 1}`, value => {
switch (value.action) {
case ACTION.CONNECT:
setTimeout(this.sendPings.bind(this), 1000);
this.statusRecord.set('room-is-open', false);
this.isOpponentConnected = true;
this.emitter.emit(EVENT.OPPONENT_CONNECTED);
break;
case ACTION.DISCONNECT:
setRecords() {
this.statusRecord = this.client.record.getRecord(`${this.GAME_ID}-status`);
this.paddle1Record = this.client.record.getRecord(`${this.GAME_ID}-paddle1`);
this.paddle2Record = this.client.record.getRecord(`${this.GAME_ID}-paddle2`);
this.hitRecord = this.client.record.getRecord(`${this.GAME_ID}-hit`);
this.missRecord = this.client.record.getRecord(`${this.GAME_ID}-miss`);
this.pingRecord = this.client.record.getRecord(`${this.GAME_ID}-ping`);
}
connectToServer(host) {
// connect to the deepstream server
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('timeout');
}, 2000);
this.client = deepstream(host, {
mergeStrategy: deepstream.MERGE_STRATEGIES.REMOTE_WINS,
});
this.client.login();
chooseClosestServer() {
// try connecting to every available server, choose the one that answers first
return new Promise((resolve, reject) => {
Promise.race(this.availableServers.map((server, index) => this.pingServer(index))).then(fastestServer => {
if (fastestServer === 'timeout') {
reject(fastestServer);
return;
}
this.chosenServer = fastestServer;
// eslint-disable-next-line
const DeepstreamServer = require('deepstream.io');
const C = DeepstreamServer.constants;
const server = new DeepstreamServer({
host: '127.0.0.1',
port: 6020,
});
// start the server
server.start();