Fix tail rendering!

This commit is contained in:
theKidOfArcrania 2017-02-21 22:17:06 +00:00
parent e4346ae56e
commit bd34fd908d

235
game.js
View File

@ -50,7 +50,7 @@ var Tail = (function() {
};
this.addTail = addTail.bind(this, data);
this.hitsTail = hitsTail.bind(this, data);
this.render = function(ctx) {var prev = []; iterate(data, render.bind(_this, data, prev, ctx), VOID); };
this.render = render.bind(this, data);
this.move = move.bind(this, data);
Object.defineProperty(this, "moves", {
get: function() {return data.tail.slice(0);},
@ -62,7 +62,6 @@ var Tail = (function() {
function addTail(data, orientation)
{
var prev = data.prev;
var tail = data.tail;
if (!prev || prev.orientation !== orientation)
{
prev = data.prev = new TailMove(orientation);
@ -76,43 +75,9 @@ var Tail = (function() {
data.tailGrid[r] = [];
data.tailGrid[r][c] = true;
switch (orientation)
{
case 0: data.prevRow--; break; //UP
case 1: data.prevCol++; break; //RIGHT
case 2: data.prevRow++; break; //DOWN
case 3: data.prevCol--; break; //LEFT
}
}
function iterate(data, callback, reducer)
{
var r = data.startRow;
var c = data.startCol;
var other;
var val;
for (var i = 0; i < data.tail.length; i++) {
var sr = r;
var sc = c;
switch (data.tail[i].orientation)
{
case 0: r -= data.tail[i].move; break; //UP
case 1: c += data.tail[i].move; break; //RIGHT
case 2: r += data.tail[i].move; break; //DOWN
case 3: c -= data.tail[i].move; break; //LEFT
}
if (i === 0)
val = {shortCircuit: false, value: callback(sr, sc, r - sr, c - sc)};
else
val = reducer(val, callback(sr, sc, r - sr, c - sc));
if (val.shortCircuit)
return val.value;
else
val = val.value;
}
return val;
var pos = walk([data.prevRow, data.prevCol], null, orientation, 1);
data.prevRow = pos[0];
data.prevCol = pos[1];
}
function move(data, row, col)
@ -130,75 +95,89 @@ var Tail = (function() {
}
}
function render(data, prev, ctx, srow, scol, drow, dcol)
function render(data, ctx)
{
if (drow === 0 && dcol === 0)
return;
if (drow !== 0 && dcol !== 0)
throw new Error("Invalid tail path.");
ctx.fillStyle = data.player.tailColor;
var startPos = [
{x: scol * CELL_WIDTH, y: srow * CELL_WIDTH},
{x: scol * CELL_WIDTH, y: srow * CELL_WIDTH}
];
var finishPos = [
{x: (scol + dcol) * CELL_WIDTH, y: (srow + drow) * CELL_WIDTH},
{x: (scol + dcol) * CELL_WIDTH, y: (srow + drow) * CELL_WIDTH}
];
var prevOrient = -1;
var start = [data.startRow, data.startCol];
if (drow === 0)
fillTailRect(ctx, start, start);
data.tail.forEach(function(tail) {
var negDir = tail.orientation === 0 || tail.orientation === 3;
var back = start;
if (!negDir)
start = walk(start, null, tail.orientation, 1);
var finish = walk(start, null, tail.orientation, tail.move - 1);
if (tail.move > 1)
fillTailRect(ctx, start, finish);
if (prevOrient !== -1)
//Draw folding triangle.
renderCorner(ctx, back, prevOrient, tail.orientation);
start = finish;
if (negDir)
walk(start, start, tail.orientation, 1);
prevOrient = tail.orientation;
});
var curOrient = data.player.currentHeading;
if (prevOrient === curOrient)
{
startPos[1].y += CELL_WIDTH;
startPos[0].x += CELL_WIDTH * Math.sign(dcol);
startPos[1].x += CELL_WIDTH * Math.sign(dcol);
finishPos[1].y += CELL_WIDTH;
fillTailRect(ctx, start, start);
}
else
{
startPos[1].x += CELL_WIDTH;
startPos[0].y += CELL_WIDTH * Math.sign(drow);
startPos[1].y += CELL_WIDTH * Math.sign(drow);
finishPos[1].x += CELL_WIDTH;
}
if (prev.length != 0)
{
//Draw the fold triangle.
var coords = [];
var ind = 0;
for (var i = 0; i < startPos.length; i++)
for (var j = 0; j < prev.length; j++)
if (startPos[i].x === prev[j].x || startPos[i].y === prev[j].y)
coords = [startPos[i], startPos[(i == 0 ? 1 : 0)], prev[(j == 0 ? 1 : 0)]];
for (i = 0; i < 2; i++)
{
ctx.moveTo(coords[0].x, coords[0].y);
ctx.lineTo(coords[1].x, coords[1].y);
ctx.lineTo(coords[2].x, coords[2].y);
ctx.closePath();
ctx.fill();
}
}
else
{
//Draw starting rectangle.
fillNegRect(ctx, scol * CELL_WIDTH, srow * CELL_WIDTH,
CELL_WIDTH * (dcol >= 0 ? 1 : 0), CELL_WIDTH * (drow >= 0 ? 1 : 0));
}
//Draw main tail line.
var x = startPos[0].x, y = startPos[0].y;
fillNegRect(ctx, x, y, finishPos[1].x - x, finishPos[1].y - y);
prev[0] = finishPos[0];
prev[1] = finishPos[1];
renderCorner(ctx, start, prevOrient, curOrient);
}
function fillNegRect(ctx, x, y, width, height)
function renderCorner(ctx, cornerStart, dir1, dir2)
{
if (dir1 === 0 || dir2 === 0)
walk(cornerStart, cornerStart, 2, 1);
if (dir1 === 3 || dir2 === 3)
walk(cornerStart, cornerStart, 1, 1);
var a = walk(cornerStart, null, dir2, 1);
var b = walk(a, null, dir1, 1);
var triangle = new Path2D();
triangle.moveTo(cornerStart[1] * CELL_WIDTH, cornerStart[0] * CELL_WIDTH);
triangle.lineTo(a[1] * CELL_WIDTH, a[0] * CELL_WIDTH);
triangle.lineTo(b[1] * CELL_WIDTH, b[0] * CELL_WIDTH);
triangle.closePath();
for (var i = 0; i < 2; i++)
ctx.fill(triangle);
}
function walk(from, ret, orient, dist)
{
ret = ret || [];
ret[0] = from[0];
ret[1] = from[1];
switch (orient)
{
case 0: ret[0] -= dist; break; //UP
case 1: ret[1] += dist; break; //RIGHT
case 2: ret[0] += dist; break; //DOWN
case 3: ret[1] -= dist; break; //LEFT
}
return ret;
}
function fillTailRect(ctx, start, end)
{
var x = start[1] * CELL_WIDTH;
var y = start[0] * CELL_WIDTH;
var width = (end[1] - start[1]) * CELL_WIDTH;
var height = (end[0] - start[0]) * CELL_WIDTH;
if (width === 0)
width += CELL_WIDTH;
if (height === 0)
height += CELL_WIDTH;
if (width < 0)
{
x += width;
@ -214,8 +193,6 @@ var Tail = (function() {
function hitsTail(data, other)
{
var r = data.prevRow;
var c = data.prevCol;
return !!(data.tailGrid[other.row] && data.tailGrid[other.row][other.col]);
}
@ -224,17 +201,6 @@ var Tail = (function() {
return {shortCircuit: false, value: undefined};
}
//Helper methods.
function inRange(check, a, b)
{
if (a === b)
return a === check;
else if (a < b)
return a <= check && check < b;
else
return b <= check && check < a;
}
return Tail;
}());
var Player = (function() {
@ -243,6 +209,7 @@ var Player = (function() {
var SHADOW_OFFSET = 10;
function Player(socket, grid, num) {
var _this = this;
var data = {};
//TODO: load player data and color.
@ -257,9 +224,9 @@ var Player = (function() {
this.name = 'Player ' + (num + 1);
data.grid = grid;
data.curHeading = 0;
data.row = Math.floor(Math.random() * 20) + 10;
data.col = num;
data.curHeading = 2;
data.row = Math.floor(Math.random() * 10) + 10;
data.col = 10;//num;
data.dead = false;
data.tail = new Tail(this);
@ -271,6 +238,8 @@ var Player = (function() {
this.posY = data.row * CELL_WIDTH;
this.move = move.bind(this, data);
this.die = function() {data.dead = true;}
//Properties.
Object.defineProperties(this, {
currentHeading: defineGetter(function() {return data.curHeading;}),
@ -278,7 +247,7 @@ var Player = (function() {
row: defineGetter(function() {return data.row;}),
col: defineGetter(function() {return data.col;}),
num: defineGetter(function() {return num;}),
tail: defineGetter(function() {return data.tail;})
tail: defineGetter(function() {return data.tail;}),
});
}
@ -286,10 +255,7 @@ var Player = (function() {
Player.prototype.render = function(ctx)
{
//Render tail.
function a() {};
this.tail.render({
moveTo: a, lineTo: a, closePath: a, fill: a, stroke: a, fillRect : a
}/*ctx*/);
this.tail.render(ctx);
//Render player.
ctx.fillStyle = this.shadowColor;
@ -374,7 +340,7 @@ var Player = (function() {
if(t < 1/2) return q;
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
}
};
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
@ -413,7 +379,7 @@ $(function() {
var grid = [];
//Load players.
for (var p = 0; p < 9; p++)
for (var p = 0; p < 1; p++)
{
//TODO: socket loading.
players[p] = new Player(null, grid, p);
@ -487,8 +453,8 @@ $(function() {
else
{
//...otherwise, the one that sustains most of the collision will be removed.
areaI = area(players[i]);
areaJ = area(players[j]);
var areaI = area(players[i]);
var areaJ = area(players[j]);
if (areaI === areaJ)
removing[i] = removing[j] = true;
@ -503,7 +469,10 @@ $(function() {
players = players.filter(function(val, i) {
if (removing[i])
{
dead.push(val);
val.die();
}
return !removing[i];
});
@ -579,6 +548,9 @@ $(function() {
}
}
//TODO: current player index
var user = players[0];
function paintLoop()
{
ctx.fillStyle = 'whitesmoke';
@ -591,6 +563,12 @@ $(function() {
});
ctx.setTransform(1, 0, 0, 1, 0, 0); //Reset transform.
if (user.dead)
{
console.log("You died!");
return;
}
//TODO: sync each loop with server. (server will give frame count.)
frameCount++;
update();
@ -598,6 +576,7 @@ $(function() {
}
paintLoop();
//Event listeners
$(document).keydown(function(e) {
var newHeading = -1;
@ -610,8 +589,12 @@ $(function() {
default: return; //exit handler for other keys.
}
//TODO: current player index, and notify server.
players[0].heading = newHeading;
if (newHeading === user.currentHeading || ((newHeading % 2 === 0) ^
(user.currentHeading % 2 === 0)))
{
//TODO: notify server.
user.heading = newHeading;
}
e.preventDefault();
});
});
});