splatjs
Version:
A 2D HTML5 Canvas game engine
98 lines (86 loc) • 2.4 kB
JavaScript
;
var gridSize = 64;
function toGrid(i) {
return Math.floor(i / gridSize);
}
function keys(entity) {
var x1 = toGrid(entity.position.x);
var x2 = toGrid(entity.position.x + entity.size.width);
var y1 = toGrid(entity.position.y);
var y2 = toGrid(entity.position.y + entity.size.height);
var k = [];
for (var x = x1; x <= x2; x++) {
for (var y = y1; y <= y2; y++) {
k.push(x + "," + y);
}
}
return k;
}
function add(hash, entity, key) {
if (!hash[key]) {
hash[key] = [entity];
return;
}
for (var i = 0; i < hash[key].length; i++) {
var peer = hash[key][i];
// FIXME: when an entity's collisions are removed, it stays forever in the hash. this needs to get cleaned up somehow.
if (peer.collisions === undefined) {
continue;
}
if (collides(entity, peer)) {
entity.collisions.push(peer.id);
peer.collisions.push(entity.id);
}
}
hash[key].push(entity);
}
function remove(hash, entity, key) {
var list = hash[key];
var pos = list.indexOf(entity);
if (pos === -1) {
return;
}
list.splice(pos, 1);
}
function collides(b, a) {
return a.position.x + a.size.width > b.position.x &&
a.position.x < b.position.x + b.size.width &&
a.position.y + a.size.height > b.position.y &&
a.position.y < b.position.y + b.size.height;
}
module.exports = function(ecs, data) {
var spatialHash = {};
ecs.addEach(function(entity, elapsed) { // jshint ignore:line
function notCurrentEntityId(id) {
return id !== entity.id;
}
if (entity.collisionKeys === undefined || entity.velocity !== undefined) {
var oldKeys = entity.collisionKeys || [];
entity.collisionKeys = keys(entity);
if (entity.velocity !== undefined || !areArraysSame(oldKeys, entity.collisionKeys)) {
for (var i = 0; i < oldKeys.length; i++) {
remove(spatialHash, entity, oldKeys[i]);
}
for (i = 0; i < entity.collisions.length; i++) {
var peer = data.entities.entities[entity.collisions[i]];
peer.collisions = peer.collisions.filter(notCurrentEntityId);
}
entity.collisions = [];
for (i = 0; i < entity.collisionKeys.length; i++) {
add(spatialHash, entity, entity.collisionKeys[i]);
}
}
}
}, ["position", "size", "collisions"]);
};
function areArraysSame(a, b) {
if (a.length !== b.length) {
return false;
}
for (var i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}