bump-ts
Version:
  
918 lines (777 loc) • 27.2 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _createForOfIteratorHelperLoose(o, allowArrayLike) {
var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
if (it) return (it = it.call(o)).next.bind(it);
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
if (it) o = it;
var i = 0;
return function () {
if (i >= o.length) return {
done: true
};
return {
done: false,
value: o[i++]
};
};
}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function assertIsPositiveNumber(value, name) {
if (isNaN(value) || value <= 0) throw new Error("\"" + name + "\" must be a positive integer, but was " + value + " (" + typeof value + ")");
}
var DELTA = 1e-10; // floating-point margin of error
function nearest(x, a, b) {
return Math.abs(a - x) < Math.abs(b - x) ? a : b;
}
function rect_getNearestCorner(rect, px, py) {
return {
x: nearest(px, rect.x, rect.x + rect.w),
y: nearest(py, rect.y, rect.y + rect.h)
};
} // This is a generalized implementation of the liang-barsky algorithm, which also returns
// the normals of the sides where the segment intersects.
// Returns null if the segment never touches the rect
// Notice that normals are only guaranteed to be accurate when initially ti1, ti2 == -math.huge, math.huge
function rect_getSegmentIntersectionIndices(rect, x1, y1, x2, y2, ti1, ti2) {
var _ti1 = isNaN(ti1) ? 0 : ti1;
var _ti2 = isNaN(ti2) ? 1 : ti2;
var dx = x2 - x1;
var dy = y2 - y1;
var nx;
var ny;
var nx1 = 0;
var ny1 = 0;
var nx2 = 0;
var ny2 = 0;
var p, q, r;
for (var side = 1; side < 5; side++) {
// left
if (side === 1) {
nx = -1;
ny = 0;
p = -dx;
q = x1 - rect.x;
} // right
else if (side === 2) {
nx = 1;
ny = 0;
p = dx;
q = rect.x + rect.w - x1;
} // top
else if (side === 3) {
nx = 0;
ny = -1;
p = -dy;
q = y1 - rect.y;
} // bottom
else {
nx = 0;
ny = 1;
p = dy;
q = rect.y + rect.h - y1;
}
if (p === 0) {
if (q <= 0) return undefined;
} else {
r = q / p;
if (p < 0) {
if (r > _ti2) return undefined;else if (r > _ti1) {
_ti1 = r;
nx1 = nx;
ny1 = ny;
}
} // p > 0
else {
if (r < _ti1) return undefined;else if (r < _ti2) {
_ti2 = r;
nx2 = nx;
ny2 = ny;
}
}
}
}
return [_ti1, _ti2, nx1, ny1, nx2, ny2];
} // Calculates the Minkowsky difference between 2 rects, which is another rect
function rect_getDiff(rect, otherRect) {
return {
x: otherRect.x - rect.x - rect.w,
y: otherRect.y - rect.y - rect.h,
w: rect.w + otherRect.w,
h: rect.h + otherRect.h
};
}
function rect_containsPoint(rect, px, py) {
return px - rect.x > DELTA && py - rect.y > DELTA && rect.x + rect.w - px > DELTA && rect.y + rect.h - py > DELTA;
}
function rect_isIntersecting(x1, y1, w1, h1, otherRect) {
return x1 < otherRect.x + otherRect.w && otherRect.x < x1 + w1 && y1 < otherRect.y + otherRect.h && otherRect.y < y1 + h1;
}
function rect_getSquareDistance(rect, otherRect) {
var dx = rect.x - otherRect.x + (rect.w - otherRect.w) / 2;
var dy = rect.y - otherRect.y + (rect.h - otherRect.h) / 2;
return dx * dx + dy * dy;
}
function rect_detectCollision(rect, otherRect, goalX, goalY) {
var dx = (goalX != null ? goalX : rect.x) - rect.x;
var dy = (goalY != null ? goalY : rect.y) - rect.y;
var diffRect = rect_getDiff(rect, otherRect);
var overlaps;
var nx, ny;
var ti; // If the item was intersecting other
if (rect_containsPoint(diffRect, 0, 0)) {
var _rect_getNearestCorne = rect_getNearestCorner(diffRect, 0, 0),
px = _rect_getNearestCorne.x,
py = _rect_getNearestCorne.y;
var wi = Math.min(rect.w, Math.abs(px)); // area of intersection
var hi = Math.min(rect.h, Math.abs(py)); // area of intersection
ti = -wi * hi; // `ti` is the negative area of intersection
overlaps = true;
} else {
var intersections = rect_getSegmentIntersectionIndices(diffRect, 0, 0, dx, dy, -Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
if (intersections) {
var ti1 = intersections[0],
ti2 = intersections[1],
nx1 = intersections[2],
ny1 = intersections[3]; // item tunnels into other
if (typeof ti1 === 'number' && ti1 < 1 && Math.abs(ti1 - (ti2 || 0)) >= DELTA && (0 < ti1 + DELTA || 0 === ti1 && (ti2 || 0) > 0)) {
ti = ti1;
nx = nx1;
ny = ny1;
overlaps = false;
}
}
}
if (typeof ti !== 'number') return;
var tx, ty;
if (overlaps) {
if (dx === 0 && dy === 0) {
//intersecting and not moving - use minimum displacement vector
var _rect_getNearestCorne2 = rect_getNearestCorner(diffRect, 0, 0),
_px = _rect_getNearestCorne2.x,
_py = _rect_getNearestCorne2.y; // if (px >>> 1 < py >>> 1) py = 0;
if (Math.abs(_px) < Math.abs(_py)) _py = 0;else _px = 0;
nx = Math.sign(_px);
ny = Math.sign(_py);
tx = rect.x + _px;
ty = rect.y + _py;
} else {
// Intersecting and moving - move in the opposite direction.
var _intersections = rect_getSegmentIntersectionIndices(diffRect, 0, 0, dx, dy, -Number.MAX_SAFE_INTEGER, 1);
if (_intersections) {
var _ti = _intersections[0],
_nx = _intersections[2],
_ny = _intersections[3];
nx = _nx;
ny = _ny;
if (!_ti) return;
tx = rect.x + dx * _ti;
ty = rect.y + dy * _ti;
}
} //tunnel
} else {
tx = rect.x + dx * ti;
ty = rect.y + dy * ti;
}
return {
overlaps: overlaps,
// @ts-ignore
ti: ti,
move: {
x: dx,
y: dy
},
normal: {
x: nx,
y: ny
},
touch: {
x: tx,
y: ty
},
itemRect: rect,
otherRect: otherRect
};
}
function grid_toWorld(cellSize, cx, cy) {
return [(cx - 1) * cellSize, (cy - 1) * cellSize];
}
function grid_toCell(cellSize, x, y) {
return [Math.floor(x / cellSize) + 1, Math.floor(y / cellSize) + 1];
} //grid_traverse * functions are based on "A Fast Voxel Traversal Algorithm for Ray Tracing",
//by John Amanides and Andrew Woo - http://www.cse.yorku.ca/~amana/research/grid.pdf
//It has been modified to include both cells when the ray "touches a grid corner",
//and with a different exit condition
function grid_traverse_initStep(cellSize, ct, t1, t2) {
var v = t2 - t1;
if (v > 0) return [1, cellSize / v, ((ct + v) * cellSize - t1) / v];else if (v < 0) return [-1, -cellSize / v, ((ct + v - 1) * cellSize - t1) / v];else return [0, Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER];
}
function grid_traverse(cellSize, x1, y1, x2, y2, traverseFunction) {
var _grid_toCell = grid_toCell(cellSize, x1, y1),
cx1 = _grid_toCell[0],
cy1 = _grid_toCell[1];
var _grid_toCell2 = grid_toCell(cellSize, x2, y2),
cx2 = _grid_toCell2[0],
cy2 = _grid_toCell2[1];
var _grid_traverse_initSt = grid_traverse_initStep(cellSize, cx1, x1, x2),
stepX = _grid_traverse_initSt[0],
dx = _grid_traverse_initSt[1],
tx = _grid_traverse_initSt[2];
var _grid_traverse_initSt2 = grid_traverse_initStep(cellSize, cy1, y1, y2),
stepY = _grid_traverse_initSt2[0],
dy = _grid_traverse_initSt2[1],
ty = _grid_traverse_initSt2[2];
var cx = cx1,
cy = cy1;
traverseFunction(cx, cy); // The default implementation had an infinite loop problem when
// approaching the last cell in some occassions. We finish iterating
// when we are *next* to the last cell.
do {
if (tx < ty) {
var _ref = [tx + dx, cx + stepX];
tx = _ref[0];
cx = _ref[1];
traverseFunction(cx, cy);
} else {
// Addition: include both cells when going through corners
if (tx == ty) traverseFunction(cx + stepX, cy);
ty = ty + dy;
cy = cy + stepY;
traverseFunction(cx, cy);
}
} while (Math.abs(cx - cx2) + Math.abs(cy - cy2) > 1); //If we have not arrived to the last cell, use it
if (cx != cx2 || cy != cy2) traverseFunction(cx2, cy2);
}
function grid_toCellRect(cellSize, rect) {
var _grid_toCell3 = grid_toCell(cellSize, rect.x, rect.y),
cx = _grid_toCell3[0],
cy = _grid_toCell3[1];
var cr = Math.ceil((rect.x + rect.w) / cellSize);
var cb = Math.ceil((rect.y + rect.h) / cellSize);
return {
x: cx,
y: cy,
w: cr - cx + 1,
h: cb - cy + 1
};
}
function assertType(desiredType, value, name) {
if (typeof value !== desiredType) throw new Error("\"" + name + "\" must be a " + desiredType + ", but was a " + value + " (" + typeof value + ")");
}
function assertIsRect(x, y, w, h) {
assertType('number', x, 'x');
assertType('number', y, 'y');
assertIsPositiveNumber(w, 'w');
assertIsPositiveNumber(h, 'h');
}
function touch(_world, column, _rect, _goalX, _goalY, _filter) {
return {
x: column.touch.x,
y: column.touch.y,
collisions: []
};
}
function cross(world, column, rect, goalX, goalY, filter) {
var collisions = world.project(column.item, rect, goalX, goalY, filter);
return {
x: goalX,
y: goalY,
collisions: collisions
};
}
function slide(world, column, rect, goalX, goalY, filter) {
var _goalX = goalX != null ? goalX : rect.x;
var _goalY = goalY != null ? goalY : rect.y;
var touchCoords = column.touch;
var moveCoords = column.move;
if (moveCoords.x !== 0 || moveCoords.y !== 0) if (column.normal.x !== 0) _goalX = touchCoords.x;else _goalY = touchCoords.y; // // TODO: What does his affect?
column.slide = {
x: _goalX,
y: _goalY
};
var collisions = world.project(column.item, {
x: touchCoords.x,
y: touchCoords.y,
w: rect.w,
h: rect.h
}, _goalX, _goalY, filter);
return {
x: _goalX,
y: _goalY,
collisions: collisions
};
}
function bounce(world, collision, rect, goalX, goalY, filter) {
var _goalX = goalX != null ? goalX : rect.x;
var _goalY = goalY != null ? goalY : rect.y;
var touch = collision.touch,
move = collision.move;
var bx = touch.x;
var by = touch.y;
if (move.x !== 0 || move.y !== 0) {
var bnx = _goalX - touch.x;
var bny = _goalY - touch.y;
if (collision.normal.x === 0) bny = -bny;else bnx = -bnx;
bx = touch.x + bnx;
by = touch.y + bny;
}
collision.bounce = {
x: bx,
y: by
};
var collisions = world.project(collision.item, {
x: touch.x,
y: touch.y,
w: rect.w,
h: rect.h
}, bx, by, filter);
return {
x: bx,
y: by,
collisions: collisions
};
}
function sortByTiAndDistance(a, b) {
if (a.ti === b.ti) return rect_getSquareDistance(a.itemRect, a.otherRect) - rect_getSquareDistance(a.itemRect, b.otherRect);
return a.ti - b.ti;
}
function defaultFilter() {
return 'slide';
}
function sortByWeight(a, b) {
return a.weight - b.weight;
}
function getCellsTouchedBySegment(self, x1, y1, x2, y2) {
var cells = [];
var visited = {};
grid_traverse(self.cellSize, x1, y1, x2, y2, function (cx, cy) {
var row = self.rows[cy];
if (!row) return;
var cell = row[cx];
if (!cell || visited[cell.ID]) return;
visited[cell.ID] = true;
cells.push(cell);
});
return cells;
}
function getInfoAboutItemsTouchedBySegment(self, x1, y1, x2, y2, filter) {
var cells = getCellsTouchedBySegment(self, x1, y1, x2, y2);
var rect, ti1, ti2;
var visited = {};
var itemInfo = [];
for (var i = 0; i < cells.length; i++) {
var cell = cells[i];
if (cell != null && cell.items) for (var _i = 0, _Object$keys = Object.keys(cell.items); _i < _Object$keys.length; _i++) {
var itemID = _Object$keys[_i];
if (!visited[itemID]) {
visited[itemID] = true;
if (!filter || filter(itemID)) {
rect = self['getRect'](itemID);
var intersections1 = rect_getSegmentIntersectionIndices(rect, x1, y1, x2, y2, 0, 1);
if (!intersections1) continue;
ti1 = intersections1[0];
ti2 = intersections1[1];
if (!isNaN(ti1) && (0 < ti1 && ti1 < 1 || 0 < ti2 && ti2 < 1)) {
// -- the sorting is according to the t of an infinite line, not the segment
var intersections2 = rect_getSegmentIntersectionIndices(rect, x1, y1, x2, y2, -Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
if (!intersections2) continue;
var tii0 = intersections2[0],
tii1 = intersections2[1];
itemInfo.push({
item: itemID,
ti1: ti1,
ti2: ti2,
weight: Math.min(tii0 || 0, tii1 || 0)
});
}
}
}
}
}
return itemInfo.sort(sortByWeight);
}
var World = /*#__PURE__*/function () {
function World(input) {
this.responses = {};
this.cellSize = 0;
this.rects = new Map();
this.cellSize = input.cellSize;
this.rects = new Map(Object.entries(input.rects));
this.rows = input.rows;
this.nonEmptyCells = input.nonEmptyCells;
this.responses = input.responses;
}
var _proto = World.prototype;
_proto.addResponse = function addResponse(name, response) {
this.responses[name] = response;
};
_proto.getResponseByName = function getResponseByName(name) {
var response = this.responses[name];
if (!response) throw new Error("Unknown collision type: " + name + " (" + typeof name + ")");
return response;
};
_proto.project = function project(itemID, rect, goalX, goalY, filter) {
var _goalX = goalX != null ? goalX : rect.x;
var _goalY = goalY != null ? goalY : rect.y;
var _filter = filter || defaultFilter;
var collisions = [];
var visited = new Set();
if (itemID) visited.add(itemID); // This could probably be done with less cells using a polygon raster over
// the cells instead of a bounding rect of the whole movement. Conditional
// to building a queryPolygon method.
var tl = _goalX !== rect.x ? Math.min(_goalX, rect.x) : _goalX;
var tt = _goalY !== rect.y ? Math.min(_goalY, rect.y) : _goalY;
var tr = _goalX !== rect.x ? Math.max(_goalX + rect.w, rect.x + rect.w) : _goalX + rect.w;
var tb = _goalY !== rect.y ? Math.max(_goalY + rect.h, rect.y + rect.h) : _goalY + rect.h;
var tw = tr - tl;
var th = tb - tt;
var cellRect = grid_toCellRect(this.cellSize, {
x: tl,
y: tt,
w: tw,
h: th
});
var itemsInCellRect = this.getItemsInCellRect(cellRect);
for (var i = 0; i < itemsInCellRect.length; i++) {
var other = itemsInCellRect[i];
if (!visited.has(other)) {
visited.add(other);
if (!this.hasItem(other)) continue;
var responseName = _filter(itemID, other);
if (responseName !== false) {
var collision = rect_detectCollision(rect, this.getRect(other), _goalX, _goalY);
if (collision) collisions.push(_extends({}, collision, {
other: other,
item: itemID,
type: responseName
}));
}
}
}
return collisions.sort(sortByTiAndDistance);
};
_proto.countCells = function countCells() {
var count = 0;
for (var _iterator = _createForOfIteratorHelperLoose(this.rows.filter(function (row) {
return !!row;
})), _step; !(_step = _iterator()).done;) {
var row = _step.value;
for (var _iterator2 = _createForOfIteratorHelperLoose(row), _step2; !(_step2 = _iterator2()).done;) {
var _col = _step2.value;
if (!!_col) count++;
}
}
return count;
};
_proto.hasItem = function hasItem(item) {
return this.rects.has(item);
};
_proto.getItems = function getItems() {
return Array.from(this.rects.values());
};
_proto.countItems = function countItems() {
return this.rects.size;
};
_proto.addItemToCell = function addItemToCell(itemID, cx, cy) {
this.rows[cy] = this.rows[cy] || [];
var row = this.rows[cy]; // Initialize a cell if no cell is present at this point.
if (!row[cx]) row[cx] = {
ID: "Cell_" + cx + ":" + cy,
x: cx,
y: cy,
items: {}
};
var cell = row[cx];
this.nonEmptyCells[cell.ID] = true;
if (!cell.items[itemID]) cell.items[itemID] = true;
};
_proto.getRect = function getRect(itemID) {
var rect = this.rects.get(itemID);
if (!rect) throw new Error("Item \"" + itemID + "\" must be added to the world before getting its rect. Use world:add(item, x,y,w,h) to add it first.");
return rect;
};
_proto.getItemsInCellRect = function getItemsInCellRect(cellRect) {
var results = [];
for (var cy = cellRect.y; cy <= cellRect.y + cellRect.h - 1; cy++) {
var row = this.rows[cy];
if (row) for (var cx = cellRect.x; cx <= cellRect.x + cellRect.w - 1; cx++) {
var _Object$keys2;
var cell = row[cx];
if (cell != null && cell.items && ((_Object$keys2 = Object.keys(cell.items)) == null ? void 0 : _Object$keys2.length) > 0) // no cell.itemCount > 1 because tunneling
results.push(Object.keys(cell.items));
}
}
return results.flat();
} // Optimized version of getDictItemsInCellRect only used in
// queryPoint, made to avoid an unneeded object creation.
;
_proto.getItemsInCellPoint = function getItemsInCellPoint(x, y) {
var items = [];
for (var cy = y; cy <= y; cy++) {
var row = this.rows[cy];
if (row) for (var cx = x; cx <= x; cx++) {
var _Object$keys3;
var cell = row[cx];
if (cell != null && cell.items && ((_Object$keys3 = Object.keys(cell.items)) == null ? void 0 : _Object$keys3.length) > 0) // no cell.itemCount > 1 because tunneling
items.push.apply(items, Object.keys(cell.items));
}
}
return items;
};
_proto.removeItemFromCell = function removeItemFromCell(itemID, cx, cy) {
var _row$cx, _row$cx$items, _Object$keys4;
var row = this.rows[cy];
if (!(row != null && (_row$cx = row[cx]) != null && (_row$cx$items = _row$cx['items']) != null && _row$cx$items[itemID])) return false;
var cell = row[cx];
delete cell.items[itemID];
if (((_Object$keys4 = Object.keys(cell.items)) == null ? void 0 : _Object$keys4.length) === 0) delete this.nonEmptyCells[cell.ID];
return true;
};
_proto.toWorld = function toWorld(cx, cy) {
return grid_toWorld(this.cellSize, cx, cy);
};
_proto.toCell = function toCell(x, y) {
return grid_toCell(this.cellSize, x, y);
};
_proto.queryRect = function queryRect(x, y, w, h, filter) {
assertIsRect(x, y, w, h);
var cellRect = grid_toCellRect(this.cellSize, {
x: x,
y: y,
w: w,
h: h
});
var itemsInCellRect = this.getItemsInCellRect(cellRect);
var items = [];
for (var _iterator3 = _createForOfIteratorHelperLoose(itemsInCellRect), _step3; !(_step3 = _iterator3()).done;) {
var itemID = _step3.value;
if ((!filter || filter(itemID)) && rect_isIntersecting(x, y, w, h, this.getRect(itemID))) items.push(itemID);
}
return [].concat(new Set(items));
};
_proto.queryPoint = function queryPoint(x, y, filter) {
var _this$toCell = this.toCell(x, y),
cx = _this$toCell[0],
cy = _this$toCell[1];
var itemsInCellRect = this.getItemsInCellPoint(cx, cy);
var items = [];
for (var i = 0; i < itemsInCellRect.length; i++) {
var itemID = itemsInCellRect[i];
if ((!filter || filter(itemID)) && rect_containsPoint(this.getRect(itemID), x, y)) items.push(itemID);
}
return items;
};
_proto.querySegment = function querySegment(x1, y1, x2, y2, filter) {
var itemsInfo = getInfoAboutItemsTouchedBySegment(this, x1, y1, x2, y2, filter);
var items = [];
if (itemsInfo) for (var i = 0; i < itemsInfo.length; i++) {
items.push(itemsInfo[i].item);
}
return items;
};
_proto.querySegmentWithCoords = function querySegmentWithCoords(x1, y1, x2, y2, filter) {
var itemInfo = getInfoAboutItemsTouchedBySegment(this, x1, y1, x2, y2, filter);
var dx = x2 - x1;
var dy = y2 - y1;
var info;
var ti1;
var ti2;
for (var _iterator4 = _createForOfIteratorHelperLoose(itemInfo), _step4; !(_step4 = _iterator4()).done;) {
var item = _step4.value;
info = item;
ti1 = info.ti1;
ti2 = info.ti2;
info.weight = null;
info.x1 = x1 + dx * ti1;
info.y1 = y1 + dy * ti1;
info.x2 = x1 + dx * ti2;
info.y2 = y1 + dy * ti2;
}
return itemInfo;
};
_proto.add = function add(itemID, x, y, w, h) {
var rect = this.rects.get(itemID);
if (rect) throw new Error("Item \"" + itemID + "\" added to the world twice.");
assertIsRect(x, y, w, h);
var rectToAdd = {
x: x,
y: y,
w: w,
h: h
};
this.rects.set(itemID, rectToAdd);
var cellRect = grid_toCellRect(this.cellSize, rectToAdd);
for (var cy = cellRect.y; cy < cellRect.y + cellRect.h; cy++) {
for (var cx = cellRect.x; cx < cellRect.x + cellRect.w; cx++) {
this.addItemToCell(itemID, cx, cy);
}
}
return itemID;
};
_proto.remove = function remove(itemID) {
var _itemRect = this.getRect(itemID);
var itemRect = {
x: _itemRect.x,
y: _itemRect.y,
w: _itemRect.w,
h: _itemRect.h
};
this.rects["delete"](itemID);
var cellRect = grid_toCellRect(this.cellSize, itemRect);
for (var cy = cellRect.y; cy < cellRect.y + cellRect.h; cy++) {
for (var cx = cellRect.x; cx < cellRect.x + cellRect.w; cx++) {
this.removeItemFromCell(itemID, cx, cy);
}
}
};
_proto.update = function update(itemID, x2, y2, w2, h2) {
var itemRect = this.getRect(itemID);
w2 = isNaN(w2) ? itemRect.w : w2;
h2 = isNaN(h2) ? itemRect.h : h2;
assertIsRect(x2, y2, w2, h2);
if (itemRect.x != x2 || itemRect.y != y2 || itemRect.w != w2 || itemRect.h != h2) {
var cellRect1 = grid_toCellRect(this.cellSize, itemRect);
var cellRect2 = grid_toCellRect(this.cellSize, {
x: x2,
y: y2,
w: w2,
h: h2
});
if (cellRect1.x != cellRect2.x || cellRect1.y != cellRect2.y || cellRect1.w != cellRect2.w || cellRect1.h != cellRect2.h) {
var cr1 = cellRect1.x + cellRect1.w - 1;
var cb1 = cellRect1.y + cellRect1.h - 1;
var cr2 = cellRect2.x + cellRect2.w - 1;
var cb2 = cellRect2.y + cellRect2.h - 1;
var cyOut;
for (var cy = cellRect1.y; cy <= cb1; cy++) {
cyOut = Number(cy) < cellRect2.y || cy > cb2;
for (var cx = cellRect1.x; cx <= cr1; cx++) {
if (cyOut || cx < cellRect2.x || cx > cr2) this.removeItemFromCell(itemID, cx, cy);
}
}
for (var _cy = cellRect2.y; _cy <= cb2; _cy++) {
cyOut = _cy < cellRect1.y || _cy > cb1;
for (var _cx = cellRect2.x; _cx <= cr2; _cx++) {
if (cyOut || _cx < cellRect1.x || _cx > cr1) this.addItemToCell(itemID, _cx, _cy);
}
}
}
this.rects.set(itemID, {
x: x2,
y: y2,
w: w2,
h: h2
});
}
};
_proto.move = function move(itemID, goalX, goalY, filter) {
var _this$check = this.check(itemID, goalX, goalY, filter),
x = _this$check.x,
y = _this$check.y,
collisions = _this$check.collisions;
this.update(itemID, x, y);
return {
x: x,
y: y,
collisions: collisions
};
};
_proto.check = function check(itemID, goalX, goalY, filter) {
var _projectedCollisions;
var checkFilter = filter || defaultFilter;
var visited = {};
visited[itemID] = true;
var visitedFilter = function visitedFilter(item, other) {
return !!visited[other] ? false : checkFilter(item, other);
};
var detectedCollisions = [];
var itemRect = this.getRect(itemID);
var projectedCollisions = this.project(itemID, itemRect, goalX, goalY, visitedFilter);
var collisionsCounter = ((_projectedCollisions = projectedCollisions) == null ? void 0 : _projectedCollisions.length) || 0;
while (collisionsCounter > 0) {
var collision = projectedCollisions[0];
detectedCollisions.push(collision);
visited[collision.other] = true;
var response = this.getResponseByName(collision.type);
var _response = response(this, collision, itemRect, goalX, goalY, visitedFilter),
x = _response.x,
y = _response.y,
collisions = _response.collisions;
goalX = x;
goalY = y;
projectedCollisions = collisions;
collisionsCounter = (collisions == null ? void 0 : collisions.length) || 0;
}
return {
x: goalX,
y: goalY,
collisions: detectedCollisions
};
};
return World;
}(); // Public library functions
var bump = {
newWorld: function newWorld(cellSize) {
cellSize = cellSize || 64;
assertIsPositiveNumber(cellSize, 'cellSize');
var world = new World({
cellSize: cellSize,
rects: {},
rows: [],
nonEmptyCells: {},
responses: {}
});
world.addResponse('touch', touch);
world.addResponse('cross', cross);
world.addResponse('slide', slide);
world.addResponse('bounce', bounce);
return world;
},
rect: {
getNearestCorner: rect_getNearestCorner,
getSegmentIntersectionIndices: rect_getSegmentIntersectionIndices,
getDiff: rect_getDiff,
containsPoint: rect_containsPoint,
isIntersecting: rect_isIntersecting,
getSquareDistance: rect_getSquareDistance,
detectCollision: rect_detectCollision
},
responses: {
touch: touch,
cross: cross,
slide: slide,
bounce: bounce
}
};
var index = /*#__PURE__*/Object.freeze(bump);
exports.World = World;
exports.default = index;
//# sourceMappingURL=bump-ts.cjs.development.js.map