Big Bad Waffle преди 6 години
родител
ревизия
5be17080f2
променени са 7 файла, в които са добавени 107 реда и са изтрити 60 реда
  1. +20
    -8
      src/client/js/components/player.js
  2. +30
    -28
      src/client/js/misc/pathfinder.js
  3. +31
    -21
      src/client/js/misc/physics.js
  4. +5
    -1
      src/server/components/door.js
  5. +3
    -1
      src/server/config/maps/cave/zone.js
  6. +13
    -0
      src/server/objects/objects.js
  7. +5
    -1
      src/server/world/physics.js

+ 20
- 8
src/client/js/components/player.js Целия файл

@@ -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);
},
};
});
});

+ 30
- 28
src/client/js/misc/pathfinder.js Целия файл

@@ -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
};

});
});

+ 31
- 21
src/client/js/misc/physics.js Целия файл

@@ -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;
}
};
});
});

+ 5
- 1
src/server/components/door.js Целия файл

@@ -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);


+ 3
- 1
src/server/config/maps/cave/zone.js Целия файл

@@ -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);
}
}
}


+ 13
- 0
src/server/objects/objects.js Целия файл

@@ -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;


+ 5
- 1
src/server/world/physics.js Целия файл

@@ -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);


Зареждане…
Отказ
Запис