import { BRICK_POINTS_AMOUNT, PERK_DROP_CHANCE, PERK_HEIGHT, PERK_WIDTH } from '../../config'; import { Ball } from '../../entities/ball/ball'; import { Game } from '../../game'; import { calculateAABBCollision } from '../calculateAABBCollision/calculateAABBCollision'; import { calculateDirection } from '../calculateDirection/calculateDirection'; import { spawnRandomPerk } from '../spawnRandomPerk/spawnRandomPerk'; /** * Базовое взаимодействие мяча и кирпичей: меняет направление, разрушает кирпич и роняет бонус * @param {Game} game экземпляр класса игры * @param {Ball} ball мяч * @returns {boolean | null} true, если произошло столкновение с кирпичом */ export function processBrickCollision(game, ball) { try { if (!(game instanceof Game)) { throw new Error('Аргумент game должен быть экземпляром класса игра'); } if (!(ball instanceof Ball)) { throw new Error('Аргумент ball должен быть экземпляром класса мяч'); } for (const brick of game.bricks) { if (!brick.alive) { continue; } const ballObject = { left: ball.x - ball.radius, right: ball.x + ball.radius, top: ball.y - ball.radius, bottom: ball.y + ball.radius, }; const brickObject = { left: brick.x, right: brick.x + brick.width, top: brick.y, bottom: brick.y + brick.height, }; const isCollided = calculateAABBCollision(ballObject, brickObject); if (!isCollided) { continue; } const directions = calculateDirection(ballObject, brickObject); if (directions === null) { continue; } ball.horizontalSpeed *= directions[0]; ball.verticalSpeed *= directions[1]; brick.kill(); if (!brick.alive) { game.score += BRICK_POINTS_AMOUNT[brick.type] ?? 0; } if (!brick.alive && Math.random() < PERK_DROP_CHANCE) { const perk = spawnRandomPerk( brick.x + brick.width / 2 - PERK_WIDTH / 2, brick.y + brick.height / 2 - PERK_HEIGHT / 2, ); game.perks.push(perk); } return true; } return false; } catch (err) { console.error(err); return null; } }