UNPKG

@inglorious/utils

Version:

A set of general-purpose utility functions designed with functional programming principles in mind.

70 lines (56 loc) 2.2 kB
// @see https://jonathanwhiting.com/tutorial/collision/ import { isBetween } from "./numbers.js" import { intersectsRectangle } from "./rectangle.js" const FIRST = 0 const HALF = 2 const LAST = 1 export function findCollisions(hitmask, target) { const [tilemapX, tilemapY, tilemapZ] = hitmask.position const [tileWidth, tileDepth] = hitmask.tileSize const halfTileWidth = tileWidth / HALF const halfTileDepth = tileDepth / HALF const dRows = Math.ceil(hitmask.heights.length / hitmask.columns) const tilemapWidth = hitmask.columns * tileWidth const tilemapDepth = dRows * tileDepth const tilemapLeft = tilemapX - tilemapWidth / HALF const tilemapBack = tilemapZ - tilemapDepth / HALF const [targetX, , targetZ] = target.position const [targetWidth, , targetDepth] = target.size const targetHalfWidth = targetWidth / HALF const targetHalfDepth = targetDepth / HALF const targetLeft = targetX - targetHalfWidth const targetRight = targetX + targetHalfWidth const targetBack = targetZ - targetHalfDepth const targetFront = targetZ + targetHalfDepth const minTileX = Math.floor((targetLeft - tilemapLeft) / tileWidth) const maxTileX = Math.floor((targetRight - tilemapLeft) / tileWidth) const minTileZ = Math.floor((targetBack - tilemapBack) / tileDepth) const maxTileZ = Math.floor((targetFront - tilemapBack) / tileDepth) for (let i = minTileX; i <= maxTileX; i++) { for (let j = minTileZ; j <= maxTileZ; j++) { if ( !isBetween(i, FIRST, hitmask.columns - LAST) || !isBetween(j, FIRST, dRows - LAST) ) { continue } const invertedRow = dRows - LAST - j const tileIndex = invertedRow * hitmask.columns + i const tileHeightValue = hitmask.heights[tileIndex] if (tileHeightValue) { const tileRectangle = { position: [ tilemapLeft + i * tileWidth + halfTileWidth, tilemapY, tilemapBack + j * tileDepth + halfTileDepth, ], size: [tileWidth, tileHeightValue, tileDepth], } if (intersectsRectangle(target, tileRectangle)) { return true } } } } return false }