Construct a Mask
.
Subclasses of Mask
should implement, at the least, collidesAt
andclone
. All subclasses are expected to have the properties x
, y
,w
, and h
-- the coordinates, width, and height of a bounding box
around the Mask
.
new Mask()
function Mask () {
this.x = this.y = this.w = this.h = 0;
}
Make a clone of a Mask
.
someMask.clone()
Mask.prototype.clone = function () {
var other = new Mask();
other.x = this.x;
other.y = this.y;
other.w = this.w;
other.h = this.h;
return other;
};
Translate this Mask
in two dimensions.
someMask.translate(10, 10)
Mask.prototype.translate = function (x, y) {
this.x += x;
this.y += y;
};
Make a copy of this Mask
translated to the coordinates given.
someMask.at(10, 10)
Mask.prototype.at = function (x, y) {
var other = this.clone();
other.x = x;
other.y = y;
return other;
};
Mask a copy of this Mask
translated in two dimensions.
someMask.translated(10, 10)
Mask.prototype.translated = function (x, y) {
var other = this.clone();
other.translate(x, y);
return other;
};
Test whether a Mask is completely contained within another.
someMask.within(new Mask.Box(10, 10))
Mask.prototype.within = function (b) {
for (var x = this.x; x < this.w + this.x; x++) {
for (var y = this.y; y < this.h + this.y; y++) {
if (this.collidesAt(x, y) &&
!b.collidesAt(x, y)) {
return false;
}
}
}
return true;
};
Test whether this mask collides at the given location.
new Mask.Box(10, 10).collidesAt(5, 5)
Mask.prototype.collidesAt = function (x, y) {
return false;
};
Test whether two Masks collide.
Mask.collision(new Mask.Box(5, 5), new Mask.Box(10, 10))
Mask.collision = function (a, b) {
var intersect = intersection(a, b);
for (var x = intersect.x; x < intersect.x + intersect.w; x++) {
for (var y = intersect.y; y < intersect.y + intersect.h; y++) {
if (a.collidesAt(x, y) &&
b.collidesAt(x, y)) {
return true;
}
}
}
return false;
};
A mask taken from a PBM image.
new Mask.PBM.load(arrayBuffer, callback);
Mask.PBM = function () {
this.x = 0;
this.y = 0;
this.w = 0;
this.h = 0;
this.data = [];
};
Mask.PBM.prototype = new Mask();
Mask.PBM.prototype.clone = function () {
var other = new Mask.PBM();
other.x = this.x;
other.y = this.y;
other.w = this.w;
other.h = this.h;
other.data = this.data;
return other;
};
Mask.PBM.prototype.collidesAt = function (x, y) {
return !!this.data[x - this.x] &&
!!this.data[x - this.x][y - this.y];
};
Create a Mask
from a PBM image at some URL.
Mask.PBM.url("http://example.com/mask.pbm", callback)
Mask.PBM.url = function (url, callback) {
var req = new XMLHttpRequest();
req.onload = function (ev) {
if (req.response) {
var m = new Mask.PBM();
return m.load(req.response, callback);
} else {
// No response.
return callback(null, new Error("No response."));
}
};
req.onerror = function (e) {
return callback(null, e);
};
req.open("GET", url, true);
req.responseType = "arraybuffer";
req.send();
};
Load an ArrayBuffer
taken as a PBM image to a PBM mask.
N.B. do not use the newly-initialized Mask
directly until
the callback is called.
new Mask.PBM.load(arrayBuffer, callback);
Mask.PBM.prototype.load = function (array, callback) {
var bytes = new Uint8Array(array);
if (bytes.byteLength > 2) {
if (bytes[0] === 'P'.charCodeAt(0)) {
if (bytes[1] === '4'.charCodeAt(0)) {
// This is a PBM binary file...
return fromBinaryPBM(this, bytes, callback);
} else if (bytes[1] == "1".charCodeAt(0)) {
// This is a PBM ASCII file...
return fromASCIIPBM(this, bytes, callback);
} else {
// Unknown signature.
return callback(null, new Error("Unknown PBM signature."));
}
} else {
// Unknown signature.
return callback(null, new Error("Unknown PBM signature."));
}
} else {
// File too short.
return callback(null, Error("Invalid PBM image."));
}
};
Create a mask as an inversion of another.
new Mask.Invert(other)
Mask.Invert = function (other) {
this.x = other.x;
this.y = other.y;
this.w = other.w;
this.h = other.h;
this.inversion = other;
};
Mask.Invert.prototype = new Mask();
Mask.Invert.prototype.clone = function () {
var other = new Mask.Invert(this.inversion);
other.translate(this.x, this.y);
return other;
};
Mask.Invert.prototype.collidesAt = function (x, y) {
return !this.inversion.collidesAt(x, y);
};
Masks representing vector boxes.
new Mask.Box(10, 10)
Mask.Box = function (w, h) {
this.x = 0;
this.y = 0;
this.w = w;
this.h = h;
};
Mask.Box.prototype = new Mask();
Mask.Box.prototype.clone = function () {
var other = new Mask.Box(this.w, this.h);
other.translate(this.x, this.y);
return other;
};
Mask.Box.prototype.collidesAt = function (x, y) {
return x >= this.x && y >= this.y &&
x < (this.x + this.w) && y < (this.y + this.h);
};
Get a mask representing a bounding box of some other mask.
Mask.Box.bounding(someMask)
Mask.Box.bounding = function (m) {
return new Mask.Box(m.w, m.h).at(m.x, m.y);
};
This is
mask
, a tiny MIT-licensed library providing collision masksand thus pixel-perfect collision detection in JavaScript. Collision
masks are read from PBM files. Check the github page for more
information.