@@ -1,9 +1,11 @@ | |||
define([ | |||
'js/rendering/renderer', | |||
'js/system/events' | |||
], function( | |||
'js/system/events', | |||
'js/misc/physics' | |||
], function ( | |||
renderer, | |||
events | |||
events, | |||
physics | |||
) { | |||
var scale = 40; | |||
@@ -15,7 +17,7 @@ define([ | |||
y: 0 | |||
}, | |||
init: function() { | |||
init: function () { | |||
this.obj.addComponent('keyboardMover'); | |||
this.obj.addComponent('mouseMover'); | |||
this.obj.addComponent('serverActions'); | |||
@@ -25,7 +27,7 @@ define([ | |||
events.emit('onGetPortrait', this.obj.portrait); | |||
}, | |||
update: function() { | |||
update: function () { | |||
var obj = this.obj; | |||
var oldPos = this.oldPos; | |||
@@ -38,7 +40,7 @@ define([ | |||
var instant = false; | |||
if ((dx > 5) || (dy > 5)) | |||
instant = true; | |||
if (dx != 0) | |||
dx = dx / Math.abs(dx); | |||
if (dy != 0) | |||
@@ -53,7 +55,17 @@ define([ | |||
}, instant); | |||
}, | |||
canvasFollow: function(delta, instant) { | |||
extend: function (blueprint) { | |||
if (blueprint.collisionChanges) { | |||
blueprint.collisionChanges.forEach(function (c) { | |||
physics.setCollision(c.x, c.y, c.collides); | |||
}); | |||
delete blueprint.collisionChanges; | |||
} | |||
}, | |||
canvasFollow: function (delta, instant) { | |||
var obj = this.obj; | |||
delta = delta || { | |||
x: 0, | |||
@@ -66,4 +78,4 @@ define([ | |||
}, instant); | |||
}, | |||
}; | |||
}); | |||
}); |
@@ -4,7 +4,7 @@ | |||
// Implements the astar search algorithm in javascript using a Binary Heap. | |||
// Includes Binary Heap (with modifications) from Marijn Haverbeke. | |||
// http://eloquentjavascript.net/appendix2.html | |||
(function(definition) { | |||
(function (definition) { | |||
/* global module, define */ | |||
if (typeof module === 'object' && typeof module.exports === 'object') { | |||
module.exports = definition(); | |||
@@ -15,7 +15,7 @@ | |||
window.astar = exports.astar; | |||
window.Graph = exports.Graph; | |||
} | |||
})(function() { | |||
})(function () { | |||
function pathTo(node) { | |||
var curr = node; | |||
@@ -28,7 +28,7 @@ | |||
} | |||
function getHeap() { | |||
return new BinaryHeap(function(node) { | |||
return new BinaryHeap(function (node) { | |||
return node.f; | |||
}); | |||
} | |||
@@ -42,10 +42,13 @@ | |||
* @param {Object} [options] | |||
* @param {bool} [options.closest] Specifies whether to return the | |||
path to the closest node if the target is unreachable. | |||
* @param {Function} [options.heuristic] Heuristic function (see | |||
* @param { | |||
Function | |||
}[options.heuristic] Heuristic | |||
function (see | |||
* astar.heuristics). | |||
*/ | |||
search: function(graph, start, end, options) { | |||
search: function (graph, start, end, options) { | |||
start = graph.grid[start.x][start.y] || start; | |||
end = graph.grid[end.x][end.y] || end; | |||
@@ -77,8 +80,7 @@ | |||
if (distance) { | |||
if (currentNode.h == distance) | |||
return pathTo(currentNode); | |||
} | |||
else { | |||
} else { | |||
// End case -- result has been found, return the traced path. | |||
if (currentNode === end) { | |||
return pathTo(currentNode); | |||
@@ -142,17 +144,17 @@ | |||
}, | |||
// See list of heuristics: http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html | |||
heuristics: { | |||
manhattan: function(pos0, pos1) { | |||
manhattan: function (pos0, pos1) { | |||
var d1 = Math.abs(pos1.x - pos0.x); | |||
var d2 = Math.abs(pos1.y - pos0.y); | |||
return Math.max(d1, d2); | |||
}, | |||
manhattanDistance: function(pos0, pos1, distance) { | |||
manhattanDistance: function (pos0, pos1, distance) { | |||
var d1 = Math.abs(pos1.x - pos0.x); | |||
var d2 = Math.abs(pos1.y - pos0.y); | |||
return Math.abs(distance - Math.max(d1, d2)) + 1; | |||
}, | |||
diagonal: function(pos0, pos1) { | |||
diagonal: function (pos0, pos1) { | |||
var D = 1; | |||
var D2 = Math.sqrt(2); | |||
var d1 = Math.abs(pos1.x - pos0.x); | |||
@@ -160,7 +162,7 @@ | |||
return (D * (d1 + d2)) + ((D2 - (2 * D)) * Math.min(d1, d2)); | |||
} | |||
}, | |||
cleanNode: function(node) { | |||
cleanNode: function (node) { | |||
if (!node) | |||
return; | |||
node.f = 0; | |||
@@ -198,25 +200,25 @@ | |||
this.init(); | |||
} | |||
Graph.prototype.init = function() { | |||
Graph.prototype.init = function () { | |||
this.dirtyNodes = []; | |||
for (var i = 0; i < this.nodes.length; i++) { | |||
astar.cleanNode(this.nodes[i]); | |||
} | |||
}; | |||
Graph.prototype.cleanDirty = function() { | |||
Graph.prototype.cleanDirty = function () { | |||
for (var i = 0; i < this.dirtyNodes.length; i++) { | |||
astar.cleanNode(this.dirtyNodes[i]); | |||
} | |||
this.dirtyNodes = []; | |||
}; | |||
Graph.prototype.markDirty = function(node) { | |||
Graph.prototype.markDirty = function (node) { | |||
this.dirtyNodes.push(node); | |||
}; | |||
Graph.prototype.neighbors = function(node) { | |||
Graph.prototype.neighbors = function (node) { | |||
var ret = []; | |||
var x = node.x; | |||
var y = node.y; | |||
@@ -267,7 +269,7 @@ | |||
return ret; | |||
}; | |||
Graph.prototype.toString = function() { | |||
Graph.prototype.toString = function () { | |||
var graphString = []; | |||
var nodes = this.grid; | |||
for (var x = 0; x < nodes.length; x++) { | |||
@@ -287,11 +289,11 @@ | |||
this.weight = weight; | |||
} | |||
GridNode.prototype.toString = function() { | |||
GridNode.prototype.toString = function () { | |||
return "[" + this.x + " " + this.y + "]"; | |||
}; | |||
GridNode.prototype.getCost = function(fromNeighbor) { | |||
GridNode.prototype.getCost = function (fromNeighbor) { | |||
// Take diagonal weight into consideration. | |||
if (fromNeighbor && fromNeighbor.x != this.x && fromNeighbor.y != this.y) { | |||
return this.weight * 1.41421; | |||
@@ -299,7 +301,7 @@ | |||
return this.weight; | |||
}; | |||
GridNode.prototype.isWall = function() { | |||
GridNode.prototype.isWall = function () { | |||
return this.weight === 0; | |||
}; | |||
@@ -309,14 +311,14 @@ | |||
} | |||
BinaryHeap.prototype = { | |||
push: function(element) { | |||
push: function (element) { | |||
// Add the new element to the end of the array. | |||
this.content.push(element); | |||
// Allow it to sink down. | |||
this.sinkDown(this.content.length - 1); | |||
}, | |||
pop: function() { | |||
pop: function () { | |||
// Store the first element so we can return it later. | |||
var result = this.content[0]; | |||
// Get the element at the end of the array. | |||
@@ -329,7 +331,7 @@ | |||
} | |||
return result; | |||
}, | |||
remove: function(node) { | |||
remove: function (node) { | |||
var i = this.content.indexOf(node); | |||
// When it is found, the process seen in 'pop' is repeated | |||
@@ -346,13 +348,13 @@ | |||
} | |||
} | |||
}, | |||
size: function() { | |||
size: function () { | |||
return this.content.length; | |||
}, | |||
rescoreElement: function(node) { | |||
rescoreElement: function (node) { | |||
this.sinkDown(this.content.indexOf(node)); | |||
}, | |||
sinkDown: function(n) { | |||
sinkDown: function (n) { | |||
// Fetch the element that has to be sunk. | |||
var element = this.content[n]; | |||
@@ -375,7 +377,7 @@ | |||
} | |||
} | |||
}, | |||
bubbleUp: function(n) { | |||
bubbleUp: function (n) { | |||
// Look up the target element and its score. | |||
var length = this.content.length; | |||
var element = this.content[n]; | |||
@@ -426,7 +428,7 @@ | |||
return { | |||
astar: astar, | |||
Graph: Graph, | |||
GridNode: GridNode | |||
gridNode: GridNode | |||
}; | |||
}); | |||
}); |
@@ -1,6 +1,6 @@ | |||
define([ | |||
'js/misc/pathfinder' | |||
], function( | |||
], function ( | |||
pathfinder | |||
) { | |||
var sqrt = Math.sqrt.bind(Math); | |||
@@ -15,7 +15,7 @@ define([ | |||
width: 0, | |||
height: 0, | |||
init: function(collisionMap) { | |||
init: function (collisionMap) { | |||
this.collisionMap = collisionMap; | |||
this.width = collisionMap.length; | |||
@@ -28,7 +28,7 @@ define([ | |||
}); | |||
}, | |||
addRegion: function(obj) { | |||
addRegion: function (obj) { | |||
var lowX = obj.x; | |||
var lowY = obj.y; | |||
var highX = lowX + obj.width; | |||
@@ -43,7 +43,7 @@ define([ | |||
} | |||
}, | |||
addObject: function(obj, x, y, fromX, fromY) { | |||
addObject: function (obj, x, y, fromX, fromY) { | |||
var row = this.cells[x]; | |||
if (!row) | |||
@@ -73,7 +73,7 @@ define([ | |||
cell.push(obj); | |||
return true; | |||
}, | |||
removeObject: function(obj, x, y, toX, toY) { | |||
removeObject: function (obj, x, y, toX, toY) { | |||
var row = this.cells[x]; | |||
if (!row) | |||
@@ -108,7 +108,7 @@ define([ | |||
} | |||
}, | |||
isValid: function(x, y) { | |||
isValid: function (x, y) { | |||
var row = this.cells[x]; | |||
if ((!row) || (row.length <= y) || (!this.graph.grid[x][y])) | |||
@@ -117,7 +117,7 @@ define([ | |||
return true; | |||
}, | |||
getCell: function(x, y) { | |||
getCell: function (x, y) { | |||
var row = this.cells[x]; | |||
if (!row) | |||
@@ -130,7 +130,7 @@ define([ | |||
return cell; | |||
}, | |||
getArea: function(x1, y1, x2, y2, filter) { | |||
getArea: function (x1, y1, x2, y2, filter) { | |||
var width = this.width; | |||
var height = this.height; | |||
@@ -177,7 +177,7 @@ define([ | |||
return result; | |||
}, | |||
getOpenCellInArea: function(x1, y1, x2, y2) { | |||
getOpenCellInArea: function (x1, y1, x2, y2) { | |||
var width = this.width; | |||
var height = this.height; | |||
@@ -220,7 +220,7 @@ define([ | |||
return result; | |||
}, | |||
getPath: function(from, to) { | |||
getPath: function (from, to) { | |||
var graph = this.graph; | |||
var grid = graph.grid; | |||
@@ -255,22 +255,24 @@ define([ | |||
return path; | |||
}, | |||
isTileBlocking: function(x, y, mob, obj) { | |||
isTileBlocking: function (x, y, mob, obj) { | |||
if ((x < 0) || (y < 0) || (x >= this.width) | (y >= this.height)) | |||
return true; | |||
x = ~~x; | |||
y = ~~y; | |||
return !this.graph.grid[x][y]; | |||
var node = this.graph.grid[x][y]; | |||
return ((!node) || (node.weight == 0)); | |||
}, | |||
isCellOpen: function(x, y) { | |||
isCellOpen: function (x, y) { | |||
if ((x < 0) || (y < 0) || (x >= this.width) | (y >= this.height)) | |||
return true; | |||
return (this.cells[x][y].length == 0); | |||
}, | |||
hasLos: function(fromX, fromY, toX, toY) { | |||
hasLos: function (fromX, fromY, toX, toY) { | |||
if ((fromX < 0) || (fromY < 0) || (fromX >= this.width) | (fromY >= this.height) || (toX < 0) || (toY < 0) || (toX >= this.width) | (toY >= this.height)) | |||
return false; | |||
@@ -311,7 +313,7 @@ define([ | |||
return true; | |||
}, | |||
getClosestPos: function(fromX, fromY, toX, toY, target) { | |||
getClosestPos: function (fromX, fromY, toX, toY, target) { | |||
var tried = {}; | |||
var hasLos = this.hasLos.bind(this, toX, toY); | |||
@@ -337,8 +339,7 @@ define([ | |||
incX = -1; | |||
lowX = x2; | |||
highX = x1 - 1; | |||
} | |||
else { | |||
} else { | |||
incX = 1; | |||
lowX = x1; | |||
highX = x2 + 1; | |||
@@ -348,8 +349,7 @@ define([ | |||
incY = -1; | |||
lowY = y2; | |||
highY = y1 - 1; | |||
} | |||
else { | |||
} else { | |||
incY = 1; | |||
lowY = y1; | |||
highY = y2 + 1; | |||
@@ -405,7 +405,7 @@ define([ | |||
} | |||
}, | |||
mobsCollide: function(x, y, obj) { | |||
mobsCollide: function (x, y, obj) { | |||
if ((x < 0) || (y < 0) || (x >= this.width) | (y >= this.height)) | |||
return true; | |||
@@ -427,6 +427,16 @@ define([ | |||
} | |||
return false; | |||
}, | |||
setCollision: function (x, y, collides) { | |||
var node = this.graph.grid[x][y]; | |||
if (!node) { | |||
var grid = this.graph.grid; | |||
node = grid[x][y] = new pathfinder.gridNode(x, y, collides ? 0 : 1); | |||
} | |||
node.weight = collides ? 0 : 1; | |||
} | |||
}; | |||
}); | |||
}); |
@@ -23,8 +23,10 @@ define([ | |||
this.destroyKey = blueprint.destroyKey; | |||
this.autoClose = blueprint.autoClose; | |||
if (this.closed) | |||
if (this.closed) { | |||
this.obj.instance.physics.setCollision(this.obj.x, this.obj.y, true); | |||
this.obj.instance.objects.notifyCollisionChange(this.obj.x, this.obj.y, true); | |||
} | |||
var o = this.obj.instance.objects.buildObjects([{ | |||
properties: { | |||
@@ -143,6 +145,7 @@ define([ | |||
thisObj.cell = this.openSprite; | |||
syncO.cell = this.openSprite; | |||
this.obj.instance.physics.setCollision(thisObj.x, thisObj.y, false); | |||
this.obj.instance.objects.notifyCollisionChange(thisObj.x, thisObj.y, false); | |||
this.closed = false; | |||
this.enterArea(obj); | |||
@@ -150,6 +153,7 @@ define([ | |||
thisObj.cell = this.closedSprite; | |||
syncO.cell = this.closedSprite; | |||
this.obj.instance.physics.setCollision(thisObj.x, thisObj.y, true); | |||
this.obj.instance.objects.notifyCollisionChange(thisObj.x, thisObj.y, true); | |||
this.closed = true; | |||
this.enterArea(obj); | |||
@@ -335,6 +335,7 @@ module.exports = { | |||
cpnBlocker: { | |||
init: function () { | |||
this.obj.instance.physics.setCollision(this.obj.x, this.obj.y, true); | |||
this.obj.instance.objects.notifyCollisionChange(this.obj.x, this.obj.y, true); | |||
} | |||
} | |||
} | |||
@@ -528,6 +529,7 @@ module.exports = { | |||
walls.forEach(function (w) { | |||
w.destroyed = true; | |||
physics.setCollision(w.x, w.y, false); | |||
this.obj.instance.objects.notifyCollisionChange(w.x, w.y, false); | |||
syncer.queue('onGetObject', { | |||
x: w.x, | |||
@@ -538,7 +540,7 @@ module.exports = { | |||
col: 4 | |||
}] | |||
}); | |||
}); | |||
}, this); | |||
} | |||
} | |||
} | |||
@@ -294,6 +294,19 @@ define([ | |||
}); | |||
} | |||
}, | |||
notifyCollisionChange: function (x, y, collides) { | |||
this.objects | |||
.filter(o => o.player) | |||
.forEach(function (o) { | |||
o.syncer.setArray(true, 'player', 'collisionChanges', { | |||
x: x, | |||
y: y, | |||
collides: collides | |||
}); | |||
}); | |||
}, | |||
update: function () { | |||
var objects = this.objects; | |||
var len = objects.length; | |||
@@ -370,7 +370,9 @@ define([ | |||
x = ~~fromX; | |||
y = ~~fromY; | |||
if (!graphGrid[x][y]) | |||
var node = graphGrid[x][y]; | |||
if ((!node) || (node.weight == 0)) | |||
return false; | |||
else if ((x == toX) && (y == toY)) | |||
return true; | |||
@@ -498,6 +500,8 @@ define([ | |||
}, | |||
setCollision: function (x, y, collides) { | |||
this.collisionMap[x][y] = collides ? 1 : 0; | |||
var grid = this.graph.grid; | |||
if (!grid[x][y]) { | |||
grid[x][y] = new pathfinder.gridNode(x, y, collides ? 0 : 1); | |||