2017-01-20 22:42:49 +00:00
|
|
|
var app = require('express')();
|
|
|
|
var http = require('http').Server(app);
|
|
|
|
var io = require('socket.io')(http);
|
|
|
|
|
|
|
|
app.get('/', function(req, res){
|
|
|
|
res.sendFile(__dirname + '/index.html');
|
|
|
|
});
|
|
|
|
|
2017-01-21 17:58:44 +00:00
|
|
|
/** Parameters **/
|
|
|
|
var clients = [], // List of all conected clients
|
|
|
|
players = [], // Store Player 1 and Player 2 in Array {Player1 == players[0]}
|
|
|
|
gameState = 0, // Game-Controler Variable
|
|
|
|
width, height, // Final Width + Height of Game-Window
|
|
|
|
startinterval, // Interval for Counting down (cancelable)
|
|
|
|
calcPos,
|
|
|
|
score = [0,0];
|
2017-01-20 22:42:49 +00:00
|
|
|
|
|
|
|
/** Game-Config **/
|
|
|
|
var cube_width = 50,
|
|
|
|
cube_height = 200,
|
2017-01-21 17:58:44 +00:00
|
|
|
cube_speed = 7; // Depending on 'tickrate' [cube_speed*tickrate == acutal Speed]
|
|
|
|
|
|
|
|
/** Networking-Config **/
|
|
|
|
var tickrate = 20;
|
|
|
|
|
|
|
|
|
|
|
|
/** Ball-Config **/
|
|
|
|
var ball_size = 15,
|
|
|
|
ball_speed = 15,
|
|
|
|
ballX = cube_width+ball_size,
|
|
|
|
ballY = cube_height/2,
|
|
|
|
ball_owner = 1,
|
|
|
|
ball_VX = 0,
|
|
|
|
ball_VY = 0,
|
|
|
|
ball_maxAngle = 5*Math.PI/12;
|
2017-01-20 22:42:49 +00:00
|
|
|
|
|
|
|
/** ########## **/
|
|
|
|
/** CONNECTION **/
|
|
|
|
/** ########## **/
|
|
|
|
io.on('connection', function(socket){
|
2017-01-21 17:58:44 +00:00
|
|
|
/** Set ID for User **/
|
|
|
|
var id = clients.length + 1;
|
|
|
|
if(clients.length == 1)
|
|
|
|
if(clients[0].id == 2) id = 1;
|
|
|
|
var clientkey = clients.push(new Client(id, socket)) - 1;
|
2017-01-20 22:42:49 +00:00
|
|
|
console.log('Client connected. ID=' + id);
|
|
|
|
|
|
|
|
/** ######### **/
|
|
|
|
/** HANDSHAKE **/
|
|
|
|
/** ######### **/
|
2017-01-21 17:58:44 +00:00
|
|
|
socket.emit('handshake', id, gameState, cube_width, cube_height, cube_speed, score, function(w, h){ // Callback function for 1st Client to set screen size //
|
|
|
|
clients[clientkey].width = w;
|
|
|
|
clients[clientkey].height = h;
|
|
|
|
if(clients.length > 1 && gameState == 0) setUp(socket);
|
2017-01-20 22:42:49 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
if(gameState > 0) socket.emit('size', width, height);
|
|
|
|
/** #### **/
|
|
|
|
/** Ping **/
|
|
|
|
/** ### **/
|
|
|
|
socket.on('appping', function(fn){
|
|
|
|
fn(Date.now());
|
|
|
|
});
|
|
|
|
|
2017-01-21 17:58:44 +00:00
|
|
|
/** ######### **/
|
2017-01-21 00:01:23 +00:00
|
|
|
/** Ballshoot **/
|
2017-01-21 17:58:44 +00:00
|
|
|
/** ######### **/
|
2017-01-21 00:01:23 +00:00
|
|
|
socket.on('ballshoot', function(y){
|
2017-01-21 17:58:44 +00:00
|
|
|
// shottball event obsolet
|
|
|
|
// socket.emit('shootball', y);
|
|
|
|
// socket.broadcast.emit('shootball', y);
|
|
|
|
|
|
|
|
console.log('### Ball shoot event ###');
|
|
|
|
if(ball_owner == 1){
|
|
|
|
ball_VX = ball_speed;
|
|
|
|
console.log('owner: left - at:' + players[0].y);
|
|
|
|
|
|
|
|
}
|
|
|
|
else if(ball_owner == 2){
|
|
|
|
ball_VX = -ball_speed;
|
|
|
|
console.log('owner: right - at:' + players[1].y);
|
|
|
|
}
|
|
|
|
ball_owner = 0;
|
2017-01-20 22:42:49 +00:00
|
|
|
});
|
2017-01-20 23:50:32 +00:00
|
|
|
|
|
|
|
/** ################ **/
|
|
|
|
/** Paddel V-Change **/
|
|
|
|
/** ############## **/
|
2017-01-21 17:58:44 +00:00
|
|
|
socket.on('vchange', function(pos, val, y, timestamp){
|
|
|
|
var timediff = Date.now()-timestamp;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// console.log('INTERPOLATING...');
|
|
|
|
|
|
|
|
// var diff = ((players[pos-1].speed/tickrate)*timediff);
|
|
|
|
// if(players[pos-1].vY == 0){ // Lag from Sender (accel)
|
|
|
|
// if(val > 0)
|
|
|
|
// players[pos-1].y -= diff;
|
|
|
|
// if(val < 0)
|
|
|
|
// players[pos-1].y += diff;
|
|
|
|
// }
|
|
|
|
// if(players[pos-1].vY == 1){
|
|
|
|
// if(val == 0)
|
|
|
|
// players[pos-1].y += diff;
|
|
|
|
// }
|
|
|
|
// if(players[pos-1].vY == -1){
|
|
|
|
// if(val == 0)
|
|
|
|
// players[pos-1].y -= diff;
|
|
|
|
// }
|
|
|
|
|
|
|
|
players[pos-1].vY = val;
|
|
|
|
|
|
|
|
// console.log('Diff:' + diff);
|
|
|
|
// console.log('Got: ' + y + ' @ ' + timestamp);
|
|
|
|
// console.log('Expected:' + players[pos-1].y + ' @ ' + Date.now());
|
|
|
|
socket.emit('changeV', pos, val, players[pos-1].y);
|
|
|
|
socket.broadcast.emit('changeV', pos, val, players[pos-1].y);
|
2017-01-20 22:42:49 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
/** ########## **/
|
|
|
|
/** DISCONNECT **/
|
|
|
|
/** ########## **/
|
|
|
|
socket.on('disconnect', function(){
|
|
|
|
var index;
|
2017-01-21 17:58:44 +00:00
|
|
|
clients.forEach(function(sock, ind){
|
2017-01-20 22:42:49 +00:00
|
|
|
if (sock.socket == socket){
|
|
|
|
index = ind;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
});
|
2017-01-21 17:58:44 +00:00
|
|
|
var oldid = clients[index].id;
|
|
|
|
clients.splice(index, 1);
|
2017-01-20 22:42:49 +00:00
|
|
|
console.log('Client disconnected. ID=' + (oldid+1));
|
2017-01-21 17:58:44 +00:00
|
|
|
if(clients.length == 1){
|
|
|
|
clients[0].socket.emit('test', 'player_left'); //TODO win-event
|
2017-01-20 22:42:49 +00:00
|
|
|
console.log('Only one Player left. Sending win-event');
|
|
|
|
// Debug Restart:
|
|
|
|
gameState = 0;
|
2017-01-20 23:50:32 +00:00
|
|
|
clearInterval(startinterval);
|
2017-01-20 22:42:49 +00:00
|
|
|
broadcastGameState(socket);
|
|
|
|
return;
|
|
|
|
}
|
2017-01-21 17:58:44 +00:00
|
|
|
else if(clients.length == 0){
|
2017-01-20 22:42:49 +00:00
|
|
|
console.log('All Players left. Reseting lobby...');
|
|
|
|
gameState = 0;
|
|
|
|
id = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var key = 0;
|
2017-01-21 17:58:44 +00:00
|
|
|
if(clients[0].id == 1 || clients[0].id == 2) key = 1;
|
2017-01-20 22:42:49 +00:00
|
|
|
switch(oldid){
|
2017-01-21 17:58:44 +00:00
|
|
|
case 1 : clients[key].id = 1; clients[key].socket.emit('handshake', 1); console.log('New Player 1 selected.'); setUp(); break;
|
|
|
|
case 2 : clients[key].id = 2; clients[key].socket.emit('handshake', 2); console.log('New Player 2 selected.'); setUp(); break;
|
2017-01-20 22:42:49 +00:00
|
|
|
default : console.log('Spectator left. Nothing need to select new Players.'); break;
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
http.listen(3000, function(){
|
|
|
|
console.log('listening on *:3000');
|
|
|
|
});
|
|
|
|
|
2017-01-21 17:58:44 +00:00
|
|
|
|
|
|
|
/** Sync all settings to client and start the game **/
|
2017-01-20 22:42:49 +00:00
|
|
|
function setUp(socket){
|
|
|
|
gameState = 1;
|
|
|
|
broadcastGameState(socket);
|
|
|
|
console.log('Starting SetUp...');
|
|
|
|
/** Select smalest screensize and set for all clients **/
|
2017-01-21 17:58:44 +00:00
|
|
|
clients.forEach(function(sock){
|
2017-01-20 22:42:49 +00:00
|
|
|
broadcastGameState(socket);
|
2017-01-21 17:58:44 +00:00
|
|
|
if(sock.id == 1){
|
|
|
|
players[0] = new Player(sock.id, sock.socket);
|
|
|
|
clients.forEach(function(sock2){
|
2017-01-20 22:42:49 +00:00
|
|
|
if(sock2.id == 2){
|
2017-01-21 17:58:44 +00:00
|
|
|
players[1] = new Player(sock2.id, sock2.socket);
|
2017-01-20 22:42:49 +00:00
|
|
|
if(sock.width < sock2.width)
|
|
|
|
width = sock.width;
|
|
|
|
else
|
|
|
|
width = sock2.width;
|
|
|
|
if(sock.height < sock2.height)
|
|
|
|
height = sock.height;
|
|
|
|
else
|
|
|
|
height = sock2.height;
|
|
|
|
}
|
|
|
|
});
|
2017-01-21 17:58:44 +00:00
|
|
|
}
|
2017-01-20 22:42:49 +00:00
|
|
|
});
|
2017-01-21 17:58:44 +00:00
|
|
|
if(calcPos == null) // Start tick Server only once
|
|
|
|
tickServer();
|
2017-01-20 22:42:49 +00:00
|
|
|
socket.emit('size', width, height);
|
|
|
|
socket.broadcast.emit('size', width, height);
|
|
|
|
var i = 5;
|
2017-01-20 23:50:32 +00:00
|
|
|
startinterval = setInterval(function(){
|
2017-01-20 22:42:49 +00:00
|
|
|
i--;
|
|
|
|
socket.emit('countdown', i);
|
|
|
|
socket.broadcast.emit('countdown', i);
|
|
|
|
if(i == 0){
|
2017-01-21 17:58:44 +00:00
|
|
|
resetPlayers();
|
2017-01-20 23:50:32 +00:00
|
|
|
clearInterval(startinterval);
|
2017-01-20 22:42:49 +00:00
|
|
|
gameState = 2;
|
|
|
|
broadcastGameState(socket);
|
|
|
|
socket.emit('start');
|
|
|
|
socket.broadcast.emit('start');
|
|
|
|
}
|
|
|
|
}, 1000);
|
|
|
|
}
|
|
|
|
|
2017-01-21 17:58:44 +00:00
|
|
|
/** Broadcast GameState to all clients **/
|
2017-01-20 22:42:49 +00:00
|
|
|
function broadcastGameState(socket){
|
|
|
|
socket.emit('gamestate', gameState);
|
|
|
|
socket.broadcast.emit('gamestate', gameState);
|
|
|
|
}
|
|
|
|
|
2017-01-21 17:58:44 +00:00
|
|
|
function tickServer(){
|
|
|
|
calcPos = setInterval(function(){
|
|
|
|
calculatePlayerPosition();
|
|
|
|
calculateBallPosition();
|
|
|
|
}, tickrate);
|
|
|
|
}
|
|
|
|
|
|
|
|
function calculatePlayerPosition(){
|
|
|
|
players.forEach(function(player){
|
|
|
|
player.y -= player.vY*player.speed;
|
|
|
|
if(player.y > height-player.height || player.y < 0) player.vY = 0;
|
|
|
|
if(player.y < 0) player.y = 0;
|
|
|
|
if(player.y > height-player.height) player.y = height-player.height;
|
|
|
|
player.socket.emit('changeV', player.id, player.vY, player.y);
|
|
|
|
player.socket.broadcast.emit('changeV', player.id, player.vY, player.y);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function calculateBallPosition(){
|
|
|
|
|
|
|
|
/** Move Ball with Paddle if owned by owner (@roundstart) **/
|
|
|
|
if(ball_owner == 1){
|
|
|
|
ballX = cube_width+ball_size,
|
|
|
|
ballY = players[0].y+cube_height/2;
|
|
|
|
}
|
|
|
|
else if(ball_owner == 2){
|
|
|
|
ballX = width-cube_width-ball_size,
|
|
|
|
ballY = players[1].y+cube_height/2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** ############ **/
|
|
|
|
/** Ball Physics **/
|
|
|
|
/** ############ **/
|
|
|
|
|
|
|
|
ballX += ball_VX;
|
|
|
|
ballY += ball_VY;
|
|
|
|
|
|
|
|
/** Collide with right Paddle or get point and respawn **/
|
|
|
|
if(ballX > width - cube_width){
|
|
|
|
if(ballY < players[1].y || ballY > players[1].y+cube_height){
|
|
|
|
console.log('Point for Left');
|
|
|
|
changeScore(1, score[0]+1);
|
|
|
|
ball_VX = 0;
|
|
|
|
ball_VY = 0;
|
|
|
|
ball_owner = 1;
|
|
|
|
} else {
|
|
|
|
var intersect = ((players[1].y+cube_height/2)-ballY)/(cube_height/2);
|
|
|
|
console.log('Intersect with right at:');
|
|
|
|
console.log(intersect);
|
|
|
|
console.log('###########################');
|
|
|
|
ball_VX = -ball_speed*Math.cos(intersect*ball_maxAngle);
|
|
|
|
ball_VY = -ball_speed*Math.sin(intersect*ball_maxAngle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Collide with left Paddle or get point and respawn **/
|
|
|
|
if(ballX < cube_width){
|
|
|
|
if(ballY < players[0].y || ballY > players[0].y+cube_height){
|
|
|
|
console.log('Point for Right');
|
|
|
|
changeScore(2, score[1]+1);
|
|
|
|
ball_VX = 0;
|
|
|
|
ball_VY = 0;
|
|
|
|
ball_owner = 2;
|
|
|
|
} else {
|
|
|
|
var intersect = ((players[0].y+cube_height/2)-ballY)/(cube_height/2);
|
|
|
|
console.log('Intersect with left at:');
|
|
|
|
console.log(intersect);
|
|
|
|
console.log('###########################');
|
|
|
|
ball_VX = ball_speed*Math.cos(intersect*ball_maxAngle);
|
|
|
|
ball_VY = ball_speed*Math.sin(intersect*ball_maxAngle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** TODO INCREASE SPEED ON PADDLE HIT (weiter außen = schneller) **/
|
|
|
|
|
|
|
|
/** Collide with walls **/
|
|
|
|
if(ballY <= 0 || ballY >= height-ball_size){
|
|
|
|
ball_VY = -ball_VY;
|
|
|
|
console.log(ballX + ' : ' + ballY);
|
|
|
|
}
|
|
|
|
|
|
|
|
var data = {
|
|
|
|
x : ballX,
|
|
|
|
y : ballY,
|
|
|
|
vx : ball_VX,
|
|
|
|
vy : ball_VY,
|
|
|
|
speed : ball_speed,
|
|
|
|
owner : ball_owner
|
|
|
|
};
|
|
|
|
players[0].socket.emit('ballpos', data);
|
|
|
|
players[0].socket.broadcast.emit('ballpos', data);
|
|
|
|
}
|
|
|
|
|
|
|
|
function changeScore(id, val){
|
|
|
|
score[id-1] = val;
|
|
|
|
players[0].socket.emit('scoreChange', score);
|
|
|
|
players[0].socket.broadcast.emit('scoreChange', score);
|
|
|
|
}
|
|
|
|
|
|
|
|
function resetPlayers(){
|
|
|
|
players.forEach(function(player){
|
|
|
|
player.speed = cube_speed;
|
|
|
|
player.width = cube_width;
|
|
|
|
player.height = cube_height;
|
|
|
|
player.y = 0;
|
|
|
|
player.vY = 0;
|
|
|
|
changeScore(player.id-1, 0);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function resetServer(){
|
|
|
|
// TODO
|
|
|
|
}
|
|
|
|
|
2017-01-20 22:42:49 +00:00
|
|
|
function Client(id, socket){
|
|
|
|
this.id = id;
|
|
|
|
this.socket = socket;
|
|
|
|
this.width = 0;
|
|
|
|
this.height = 0;
|
|
|
|
}
|
2017-01-21 17:58:44 +00:00
|
|
|
|
|
|
|
function Player(id, socket){
|
|
|
|
this.id = id;
|
|
|
|
this.socket = socket;
|
|
|
|
this.speed = cube_speed;
|
|
|
|
this.width = cube_width;
|
|
|
|
this.height = cube_height;
|
|
|
|
this.y = 0;
|
|
|
|
this.vY = 0;
|
|
|
|
}
|