import { BlockTypeEnum } from "../Blocks/blockTypeEnum"; import { Constants } from "../constants"; import { Map } from "../Graphics/Map/map"; import { Tank } from "../Tanks/tank"; import { SoundEnum, SoundManager } from "./soundManager"; export class CollisionManager { /** * @type {Map} */ _map; /** * @type {Tank} */ _mainTank; /** * @type {Tank[]} */ _aiTanks = []; /** * @param {SoundManager} soundManager */ constructor(soundManager) { this.soundManager = soundManager; } attachMap(map) { this._map = map; } setMainTank(tank) { this._mainTank = tank; } addNewAITank(tank) { if (tank) this._aiTanks.push(tank); } deleteFromAITank(tank) { this._aiTanks = this._aiTanks.filter(t => tank.x != t.x && tank.y != t.y); } checkCollisionForTank(xMin, xMax, yMin, yMax, tank) { if (!this._map) return false; return (this._checkTankCollision(xMin, xMax, yMin, yMax, tank) != null) || (this._checkBoundaries(xMin, xMax, yMin, yMax) != null) || (this._checkBlockCollision(xMin, xMax, yMin, yMax, false) != null); } checkCollisionForShots(xMin, xMax, yMin, yMax, direction, tank) { if (!this._map) return false; let blockColl = this._checkBlockCollision(xMin, xMax, yMin, yMax, true); if (blockColl) { for (let blockInfo of Array.from(blockColl)) { blockInfo.block.resolveAttack(blockInfo.boxId, direction); switch(blockInfo.block.getType()) { case BlockTypeEnum.Brick: this.soundManager.playSound(SoundEnum.BrickCollision); break; case BlockTypeEnum.Iron: this.soundManager.playSound(SoundEnum.SteelCollision); break; } } return true; } if (this._checkBoundaries(xMin, xMax, yMin, yMax) != null) return true; let collTank = this._checkTankCollision(xMin, xMax, yMin, yMax, tank); if (collTank && collTank.id != tank.id) { collTank.isDestroyed = true; this.soundManager.playSound(SoundEnum.Explosion); return true; } else { return false; } } _checkTankCollision(xMin, xMax, yMin, yMax, tank) { let tanks = [this._mainTank].concat(this._aiTanks).filter(t => t !== tank); for (let tankToCheck of tanks) { let box = tankToCheck.getCollisionBox(); if (this.intersect(xMin, xMax, yMin, yMax, box.minX, box.maxX, box.minY, box.maxY)) return tankToCheck; } return null; } _checkBoundaries(xMin, xMax, yMin, yMax) { const tilesize = Constants.TILE_SIZE.getValue(); if (xMin < 0 || yMin < 0 || xMax > this._map.width * tilesize || yMax > this._map.height * tilesize) return []; return null; } _checkBlockCollision(xMin, xMax, yMin, yMax, isShot) { const blocksToCheck = this._getAllElementsOfMapOn(xMin, xMax, yMin, yMax); const tilesize = Constants.TILE_SIZE.getValue(); let blockColl = new Set(); for (let i = 0; i < blocksToCheck.length; i++) { if (isShot && blocksToCheck[i].block.getType() == BlockTypeEnum.River) continue; let boxes = blocksToCheck[i].block.getAllBoxes(); let x = blocksToCheck[i].xPos; let y = blocksToCheck[i].yPos; for (let j = 0; j < boxes.length; j++) { const box = boxes[j]; if (this.intersect(xMin, xMax, yMin, yMax, x * tilesize + box.getXMin(), x * tilesize + box.getXMax(), y * tilesize + box.getYMin(), y * tilesize + box.getYMax())) blockColl.add({block:blocksToCheck[i].block, boxId:j}); } } if (blockColl.size != 0){ return blockColl.values(); } return null; } _getAllElementsOfMapOn(xMin, xMax, yMin, yMax) { const tilesize = Constants.TILE_SIZE.getValue(); let elements = []; for (let x = 0; x < this._map.width; x++) { for (let y = 0; y < this._map.height; y++) { if (this.intersect(xMin, xMax, yMin, yMax, x * tilesize, (x + 1) * tilesize, y * tilesize, (y + 1) * tilesize)) elements.push({ block: this._map.getElement(x, y), xPos: x, yPos: y }); } } return elements; } intersect(xMin, xMax, yMin, yMax, anXMin, anXMax, anYMin, anYMax) { return (xMin <= anXMax && xMax >= anXMin) && (yMin <= anYMax && yMax >= anYMin); } }