papercats/game-client.js

352 lines
8.6 KiB
JavaScript
Raw Normal View History

2017-02-25 18:52:52 -05:00
/* global $ */
var Player = require("./player.js");
2017-02-25 18:52:52 -05:00
var renderer = require("./game-renderer.js");
var consts = require("./game-consts.js");
2017-02-26 02:31:30 -05:00
var core = require("./game-core.js");
2017-02-28 02:20:32 -05:00
var io = require('socket.io-client');
2017-02-25 18:52:52 -05:00
var GRID_SIZE = consts.GRID_SIZE;
var CELL_WIDTH = consts.CELL_WIDTH;
renderer.allowAnimation = true;
2017-02-21 00:54:44 -05:00
/**
* Provides requestAnimationFrame in a cross browser way.
* @author paulirish / http://paulirish.com/
*/
// window.requestAnimationFrame = function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {
// window.setTimeout( callback, 1000 / 60 );
// };
2017-02-21 00:54:44 -05:00
if ( !window.requestAnimationFrame ) {
window.requestAnimationFrame = ( function() {
return window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {
window.setTimeout( callback, 1000 / 60 );
};
})();
}
2017-02-21 17:17:06 -05:00
2017-03-02 14:02:03 -05:00
var norun = false;
function run() {
if (norun)
return; //Prevent multiple clicks.
norun = true;
user = null;
deadFrames = 0;
//Socket connection.
//, {transports: ['websocket'], upgrade: false}
connectServer();
socket.emit('hello', {
name: $("#name").val(),
type: 0, //Free-for-all
gameid: -1 //Requested game-id, or -1 for anyone.
2017-03-03 16:52:59 -05:00
}, function(success, msg) {
if (success)
{
console.info("Connected to game!");
$("#begin").addClass("hidden");
2017-03-03 16:52:59 -05:00
$("#begin").animate({
opacity: 0
}, 1000);
}
else
{
console.error("Unable to connect to game: " + msg);
var error = $("#error");
error.text(msg);
norun = false;
}
2017-03-02 14:02:03 -05:00
});
}
$(function() {
var error = $("#error");
if (!window.WebSocket)
{
error.text("Your browser does not support WebSockets!");
return;
}
error.text("Loading..."); //TODO: show loading screen.
var success = false;
2017-03-02 19:00:09 -05:00
var socket = io('http://' + window.location.hostname + ':8081', {
2017-03-02 14:02:03 -05:00
'forceNew': true,
upgrade: false,
transports: ['websocket']
});
socket.on('connect_error', function() {
if (!success)
error.text("Cannot connect with server. This probably is due to misconfigured proxy server. (Try using a different browser)");
})
socket.emit("checkConn", function() {
success = true;
socket.disconnect();
});
setTimeout(function() {
if (!success)
error.text("Cannot connect with server. This probably is due to misconfigured proxy server. (Try using a different browser)");
else
{
error.text("");
$("input").keypress(function(evt) {
if (evt.which === 13)
requestAnimationFrame(run);
});
$("button").click(function(evt) {
requestAnimationFrame(run);
});
}
}, 2000);
});
var user, socket, frame;
2017-02-21 00:54:44 -05:00
//Event listeners
$(document).keydown(function(e) {
2017-02-28 02:20:32 -05:00
if (!user || user.dead)
return;
var newHeading = -1;
switch (e.which)
2017-02-21 00:54:44 -05:00
{
case 37: newHeading = 3; break; //LEFT
case 38: newHeading = 0; break; //UP
case 39: newHeading = 1; break; //RIGHT
case 40: newHeading = 2; break; //DOWN
default: return; //exit handler for other keys.
2017-02-21 00:54:44 -05:00
}
if (newHeading === user.currentHeading || ((newHeading % 2 === 0) ^
(user.currentHeading % 2 === 0)))
2017-02-21 00:54:44 -05:00
{
2017-02-26 18:01:57 -05:00
//user.heading = newHeading;
if (socket)
socket.emit("frame", {
frame: frame,
heading: newHeading
}, function(success, msg) {
if (!success)
console.error(msg);
});
2017-02-21 00:54:44 -05:00
}
e.preventDefault();
});
2017-02-21 00:54:44 -05:00
2017-03-02 14:02:03 -05:00
2017-02-28 02:20:32 -05:00
var grid = renderer.grid;
var timeout = undefined;
var dirty = false;
var deadFrames = 0;
var requesting = -1; //frame that we are requesting at.
var frameCache = []; //Frames after our request.
2017-02-28 02:20:32 -05:00
//TODO: check if we can connect to server.
2017-02-28 02:20:32 -05:00
function connectServer() {
io.j = [];
io.sockets = [];
2017-03-02 19:00:09 -05:00
socket = io('http://' + window.location.hostname + ':8081', {
2017-03-02 14:02:03 -05:00
'forceNew': true,
upgrade: false,
transports: ['websocket']
});
socket.on('connect', function(){
console.info("Connected to server.");
});
2017-02-25 23:25:06 -05:00
socket.on('game', function(data) {
2017-02-26 18:59:49 -05:00
if (timeout != undefined)
clearTimeout(timeout);
//Initialize game.
//TODO: display data.gameid --- game id #
2017-02-26 02:31:30 -05:00
frame = data.frame;
renderer.reset();
//Load players.
data.players.forEach(function(p) {
var pl = new Player(grid, p);
2017-02-26 02:31:30 -05:00
renderer.addPlayer(pl);
});
2017-02-26 02:31:30 -05:00
user = renderer.getPlayerFromNum(data.num);
if (!user) throw new Error();
2017-02-26 02:31:30 -05:00
renderer.setUser(user);
//Load grid.
var gridData = new Uint8Array(data.grid);
for (var r = 0; r < grid.size; r++)
for (var c = 0; c < grid.size; c++)
{
var ind = gridData[r * grid.size + c] - 1;
grid.set(r, c, ind === -1 ? null : renderer.getPlayer(ind));
}
2017-02-26 18:01:57 -05:00
renderer.paint();
2017-02-26 02:31:30 -05:00
frame = data.frame;
2017-02-28 02:20:32 -05:00
if (requesting !== -1)
{
//Update those cache frames after we updated game.
var minFrame = requesting;
requesting = -1;
while (frameCache.length > frame - minFrame)
processFrame(frameCache[frame - minFrame]);
frameCache = [];
}
});
socket.on('notifyFrame', processFrame);
socket.on('dead', function() {
socket.disconnect(); //In case we didn't get the disconnect call.
});
2017-02-21 00:54:44 -05:00
socket.on('disconnect', function(){
2017-02-28 02:20:32 -05:00
if (!user)
return;
console.info("Server has disconnected. Creating new game.");
2017-02-26 02:31:30 -05:00
socket.disconnect();
user.die();
dirty = true;
2017-02-26 02:31:30 -05:00
paintLoop();
2017-02-28 02:20:32 -05:00
//TODO: Show score stats.
//Show score stats.
$("#stats").removeClass("hidden");
$("#stats").animate({
2017-02-28 02:20:32 -05:00
opacity: .9999
}, 3000, function() {
showStats();
});
//Then fade back into the login screen.
});
}
function showStats() {
$("#begin").removeClass("hidden");
$("#begin").animate({
opacity: .9999
}, 1000, function() {
$("#stats").addClass("hidden").css("opacity", 0);
norun = false;
});
}
function processFrame(data)
{
if (timeout != undefined)
clearTimeout(timeout);
if (requesting !== -1 && requesting < data.frame)
{
frameCache.push(data);
return;
}
if (data.frame - 1 !== frame)
{
console.error("Frames don't match up!");
socket.emit('requestFrame'); //Restore data.
requesting = data.frame;
frameCache.push(data);
return;
}
frame++;
if (data.newPlayers)
{
data.newPlayers.forEach(function(p) {
if (p.num === user.num)
return;
var pl = new Player(grid, p);
renderer.addPlayer(pl);
core.initPlayer(grid, pl);
});
}
var found = new Array(renderer.playerSize());
data.moves.forEach(function(val, i) {
var player = renderer.getPlayerFromNum(val.num);
if (!player) return;
if (val.left) player.die();
found[i] = true;
player.heading = val.heading;
});
for (var i = 0; i < renderer.playerSize(); i++)
{
//Implicitly leaving game.
if (!found[i])
{
var player = renderer.getPlayer();
player && player.die();
}
}
renderer.update();
var locs = {};
for (var i = 0; i < renderer.playerSize(); i++)
{
var p = renderer.getPlayer(i);
locs[p.num] = [p.posX, p.posY, p.waitLag];
}
socket.emit("verify", {
frame: frame,
locs: locs
}, function(frame, success, adviceFix, msg) {
if (!success && requesting === -1)
{
console.error(frame + ": " + msg);
if (adviceFix)
socket.emit('requestFrame');
}
}.bind(this, frame));
dirty = true;
requestAnimationFrame(function() {
paintLoop();
});
timeout = setTimeout(function() {
console.warn("Server has timed-out. Disconnecting.");
socket.disconnect();
}, 3000);
2017-02-28 02:20:32 -05:00
}
function paintLoop()
{
if (!dirty)
return;
renderer.paint();
dirty = false;
2017-02-21 17:17:06 -05:00
2017-02-28 02:20:32 -05:00
if (user.dead)
{
2017-02-28 02:20:32 -05:00
if (timeout)
clearTimeout(timeout);
if (deadFrames === 60) //One second of frame
{
2017-02-28 02:20:32 -05:00
var before = renderer.allowAnimation;
renderer.allowAnimation = false;
renderer.update();
2017-02-28 02:20:32 -05:00
renderer.paint();
renderer.allowAnimation = before;
user = null;
deadFrames = 0;
return;
}
2017-02-28 02:20:32 -05:00
socket.disconnect();
deadFrames++;
dirty = true;
renderer.update();
2017-02-28 02:20:32 -05:00
requestAnimationFrame(paintLoop);
}
2017-03-02 14:02:03 -05:00
}