UNPKG

bump-ts

Version:

![version](https://img.shields.io/npm/v/bump-ts) ![maintenance](https://img.shields.io/maintenance/yes/2021) ![open-issues](https://img.shields.io/github/issues-raw/hood/bump.ts)

918 lines (777 loc) 27.2 kB
'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