Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
317570fe9d | ||
|
7ff47d8efc | ||
|
8d50dc1d54 | ||
|
075b55d5ec |
@@ -1,6 +1,6 @@
|
||||
# Blockly.IO
|
||||
|
||||
This is a clone of the original Paper-IO released by Voodoo, except for one aspect. This will attempt to implement a multi-player aspect of the game (like a real IO game). Currently this has a playground at this [link] (https://thekidofarcrania.github.io/PaperIO-Web). It's a demo version of what to come. Hopefully by that time, the necessary server infrastructure could be obtained.
|
||||
This is a clone of the original Paper-IO released by Voodoo, except for one aspect. This will attempt to implement a multi-player aspect of the game (like a real IO game). Currently this has a playground at this [link](https://thekidofarcrania.github.io/BlocklyIO). It's a demo version of what to come. Hopefully by that time, the necessary server infrastructure could be obtained.
|
||||
|
||||
This is just a fun side-project for me. If you would want to use this code, it would be nice to let me know.
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
/* global $ */
|
||||
var Player = require("./player.js");
|
||||
var client = require("./player-client.js");
|
||||
var renderer = require("./game-renderer.js");
|
||||
var consts = require("./game-consts.js");
|
||||
var core = require("./game-core.js");
|
||||
@@ -29,23 +30,8 @@ if ( !window.requestAnimationFrame ) {
|
||||
})();
|
||||
}
|
||||
|
||||
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.
|
||||
}, function(success, msg) {
|
||||
client.connect(function(success, msg) {
|
||||
if (success)
|
||||
{
|
||||
console.info("Connected to game!");
|
||||
@@ -147,7 +133,6 @@ var deadFrames = 0;
|
||||
var requesting = -1; //frame that we are requesting at.
|
||||
var frameCache = []; //Frames after our request.
|
||||
|
||||
//TODO: check if we can connect to server.
|
||||
function connectServer() {
|
||||
io.j = [];
|
||||
io.sockets = [];
|
||||
|
@@ -19,24 +19,22 @@ var BAR_HEIGHT = SHADOW_OFFSET + CELL_WIDTH;
|
||||
var BAR_WIDTH = 400;
|
||||
|
||||
|
||||
var canvasWidth, canvasHeight, gameWidth, gameHeight, ctx, offctx, offscreenCanvas;
|
||||
var canvas, canvasWidth, canvasHeight, gameWidth, gameHeight, ctx, offctx, offscreenCanvas;
|
||||
|
||||
$(function () {
|
||||
var canvas = $("#main-ui")[0];
|
||||
canvas = $("#main-ui")[0];
|
||||
ctx = canvas.getContext('2d');
|
||||
|
||||
offscreenCanvas = document.createElement("canvas");
|
||||
offctx = offscreenCanvas.getContext('2d');
|
||||
|
||||
canvasWidth = offscreenCanvas.width = canvas.width = window.innerWidth;
|
||||
canvasHeight = offscreenCanvas.height = canvas.height = window.innerHeight - 20;
|
||||
canvas.style.marginTop = 20 / 2;
|
||||
|
||||
gameWidth = canvasWidth;
|
||||
gameHeight = canvasHeight - BAR_HEIGHT;
|
||||
canvas.style.marginTop = 10;
|
||||
updateSize();
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
var allowAnimation = true;
|
||||
var animateGrid, players, allPlayers, playerPortion, portionsRolling,
|
||||
barProportionRolling, grid, animateTo, offset, user, zoom, kills, showedDead;
|
||||
@@ -58,6 +56,26 @@ grid = new Grid(GRID_SIZE, function(row, col, before, after) {
|
||||
});
|
||||
});
|
||||
|
||||
function updateSize()
|
||||
{
|
||||
var changed = false;
|
||||
if (canvasWidth != window.innerWidth)
|
||||
{
|
||||
gameWidth = canvasWidth = offscreenCanvas.width = canvas.width = window.innerWidth;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (canvasHeight != window.innerHeight - 20)
|
||||
{
|
||||
canvasHeight = offscreenCanvas.height = canvas.height = window.innerHeight - 20;
|
||||
gameHeight = canvasHeight - BAR_HEIGHT;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed && user)
|
||||
centerOnPlayer(user, offset);
|
||||
}
|
||||
|
||||
function init() {
|
||||
animateGrid = new Grid(GRID_SIZE);
|
||||
grid.reset();
|
||||
@@ -94,7 +112,7 @@ function paintGridBorder(ctx)
|
||||
function paintGrid(ctx)
|
||||
{
|
||||
//Paint background.
|
||||
ctx.fillStyle = "#e2ebf3";
|
||||
ctx.fillStyle = "rgb(211, 225, 237)";
|
||||
ctx.fillRect(0, 0, CELL_WIDTH * GRID_SIZE, CELL_WIDTH * GRID_SIZE);
|
||||
|
||||
paintGridBorder(ctx);
|
||||
@@ -124,7 +142,7 @@ function paintGrid(ctx)
|
||||
{
|
||||
var frac = (animateSpec.frame / ANIMATE_FRAMES);
|
||||
var back = new Color(.58, .41, .92, 1);
|
||||
baseColor = animateSpec.before.baseColor.interpolateToString(back, frac);
|
||||
baseColor = animateSpec.before.lightBaseColor.interpolateToString(back, frac);
|
||||
shadowColor = animateSpec.before.shadowColor.interpolateToString(back, frac);
|
||||
}
|
||||
else
|
||||
@@ -132,7 +150,7 @@ function paintGrid(ctx)
|
||||
}
|
||||
else if (p)
|
||||
{
|
||||
baseColor = p.baseColor;
|
||||
baseColor = p.lightBaseColor;
|
||||
shadowColor = p.shadowColor;
|
||||
}
|
||||
else //No animation nor is this player owned.
|
||||
@@ -175,7 +193,7 @@ function paintGrid(ctx)
|
||||
y -= offsetBounce;
|
||||
|
||||
shadowColor = animateSpec.after.shadowColor;
|
||||
baseColor = animateSpec.after.baseColor.deriveLumination(-(offsetBounce / DROP_HEIGHT) * .1);
|
||||
baseColor = animateSpec.after.lightBaseColor.deriveLumination(-(offsetBounce / DROP_HEIGHT) * .1);
|
||||
|
||||
ctx.fillStyle = shadowColor.rgbString();
|
||||
ctx.fillRect(x, y + CELL_WIDTH, CELL_WIDTH, SHADOW_OFFSET);
|
||||
@@ -285,7 +303,7 @@ function paintUIBar(ctx)
|
||||
|
||||
function paint(ctx)
|
||||
{
|
||||
ctx.fillStyle = 'whitesmoke';
|
||||
ctx.fillStyle = '#e2ebf3'; //'whitesmoke';
|
||||
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
|
||||
|
||||
//Move grid to viewport as said with the offsets, below the stats
|
||||
@@ -327,6 +345,7 @@ function paintDoubleBuff()
|
||||
}
|
||||
|
||||
function update() {
|
||||
updateSize();
|
||||
|
||||
//Change grid offsets.
|
||||
for (var i = 0; i <= 1; i++)
|
||||
@@ -379,8 +398,8 @@ function centerOnPlayer(player, pos)
|
||||
var xOff = Math.floor(player.posX - (gameWidth / zoom - CELL_WIDTH) / 2);
|
||||
var yOff = Math.floor(player.posY - (gameHeight / zoom - CELL_WIDTH) / 2);
|
||||
var gridWidth = grid.size * CELL_WIDTH + BORDER_WIDTH * 2;
|
||||
pos[0] = Math.max(Math.min(xOff, gridWidth + (BAR_WIDTH + 100) / zoom - gameWidth / zoom), 0);
|
||||
pos[1] = Math.max(Math.min(yOff, gridWidth - gameHeight / zoom), 0);
|
||||
pos[0] = xOff; //Math.max(Math.min(xOff, gridWidth + (BAR_WIDTH + 100) / zoom - gameWidth / zoom), 0);
|
||||
pos[1] = yOff; //Math.max(Math.min(yOff, gridWidth - gameHeight / zoom), 0);
|
||||
}
|
||||
|
||||
function getBounceOffset(frame)
|
||||
|
244
player-client.js
Normal file
244
player-client.js
Normal file
@@ -0,0 +1,244 @@
|
||||
var Player = require("./player.js");
|
||||
var consts = require("./game-consts.js");
|
||||
var core = require("./game-core.js");
|
||||
var io = require('socket.io-client');
|
||||
|
||||
var GRID_SIZE = consts.GRID_SIZE;
|
||||
var CELL_WIDTH = consts.CELL_WIDTH;
|
||||
|
||||
var running = false;
|
||||
var user, socket, frame;
|
||||
|
||||
exports.connect = function(callback) {
|
||||
if (running)
|
||||
return; //Prevent multiple runs.
|
||||
running = 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.
|
||||
}, function(success, msg) {
|
||||
if (success)
|
||||
console.info("Connected to game!");
|
||||
else
|
||||
console.error("Unable to connect to game: " + msg);
|
||||
if (callback)
|
||||
callback(success, msg);
|
||||
});
|
||||
}
|
||||
|
||||
exports.changeHeading = function(int newHeading)
|
||||
{
|
||||
if (newHeading === user.currentHeading || ((newHeading % 2 === 0) ^
|
||||
(user.currentHeading % 2 === 0)))
|
||||
{
|
||||
//user.heading = newHeading;
|
||||
if (socket) {
|
||||
socket.emit("frame", {
|
||||
frame: frame,
|
||||
heading: newHeading
|
||||
}, function(success, msg) {
|
||||
if (!success)
|
||||
console.error(msg);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
function connectServer() {
|
||||
io.j = [];
|
||||
io.sockets = [];
|
||||
socket = io('http://' + window.location.hostname + ':8081', {
|
||||
'forceNew': true,
|
||||
upgrade: false,
|
||||
transports: ['websocket']
|
||||
});
|
||||
socket.on('connect', function(){
|
||||
console.info("Connected to server.");
|
||||
});
|
||||
socket.on('game', function(data) {
|
||||
if (timeout != undefined)
|
||||
clearTimeout(timeout);
|
||||
|
||||
//Initialize game.
|
||||
//TODO: display data.gameid --- game id #
|
||||
frame = data.frame;
|
||||
renderer.reset();
|
||||
|
||||
//Load players.
|
||||
data.players.forEach(function(p) {
|
||||
var pl = new Player(grid, p);
|
||||
renderer.addPlayer(pl);
|
||||
});
|
||||
user = renderer.getPlayerFromNum(data.num);
|
||||
if (!user) throw new Error();
|
||||
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));
|
||||
}
|
||||
|
||||
renderer.paint();
|
||||
frame = data.frame;
|
||||
|
||||
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.
|
||||
});
|
||||
|
||||
socket.on('disconnect', function(){
|
||||
if (!user)
|
||||
return;
|
||||
console.info("Server has disconnected. Creating new game.");
|
||||
socket.disconnect();
|
||||
user.die();
|
||||
dirty = true;
|
||||
paintLoop();
|
||||
running = false;
|
||||
|
||||
//TODO: DISCONNECT event
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
function paintLoop()
|
||||
{
|
||||
if (!dirty)
|
||||
return;
|
||||
renderer.paint();
|
||||
dirty = false;
|
||||
|
||||
if (user.dead)
|
||||
{
|
||||
if (timeout)
|
||||
clearTimeout(timeout);
|
||||
if (deadFrames === 60) //One second of frame
|
||||
{
|
||||
var before = renderer.allowAnimation;
|
||||
renderer.allowAnimation = false;
|
||||
renderer.update();
|
||||
renderer.paint();
|
||||
renderer.allowAnimation = before;
|
||||
user = null;
|
||||
deadFrames = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
socket.disconnect();
|
||||
deadFrames++;
|
||||
dirty = true;
|
||||
renderer.update();
|
||||
requestAnimationFrame(paintLoop);
|
||||
}
|
||||
}
|
@@ -373,8 +373,9 @@ function Player(grid, sdata) {
|
||||
var hue = Math.random();
|
||||
this.baseColor = base = new Color(hue, .8, .5);
|
||||
}
|
||||
this.lightBaseColor = base.deriveLumination(.1);
|
||||
this.shadowColor = base.deriveLumination(-.3);
|
||||
this.tailColor = base.deriveLumination(.2).deriveAlpha(.5);
|
||||
this.tailColor = base.deriveLumination(.3).deriveAlpha(.5);
|
||||
|
||||
//Tail requires special handling.
|
||||
this.grid = grid; //Temporary
|
||||
|
6850
public/bundle.js
6850
public/bundle.js
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,7 @@
|
||||
<div>
|
||||
<small id="error">Your browser does not support JavaScript!</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<small>Visit the open-source code on <a href="https://github.com/theKidOfArcrania/PaperIO-Web">GitHub</a>!</small>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
Reference in New Issue
Block a user