import { BALL_SPLIT_ANGLE, CONTAINER_WIDTH, PADDLE_WIDE_WIDTH, PADDLE_WIDTH, PERK_BALL_SPEED_DECREASE, PERK_DURATION_SEC, } from '../../config'; import { clone } from '../../entities/ball/clone/clone'; import { Game } from '../../game'; import { calculateAABBCollision } from '../calculateAABBCollision/calculateAABBCollision'; /** * Обновляет состояние бонусов, меняет положение, проверяет столкновение с ракеткой и выход за границу поля * @param {Game} game экземпляр класса игры * @param {number} containerHeight высота игрового контейнера в пикселях * @param {number} deltaTime изменение времени из Ticker */ export function updatePerks(game, containerHeight, deltaTime) { try { if (!(game instanceof Game)) { throw new Error('Аргумент game должен быть экземпляром класса игры'); } if (typeof containerHeight !== 'number' || containerHeight <= 0) { throw new Error('Высота игрового контейнера должна быть положительным числом'); } if (typeof deltaTime !== 'number' || deltaTime <= 0) { throw new Error('Значение изменения времени должно быть положительным числом'); } const { paddle } = game; for (const perk of game.perks) { perk.moveForward(deltaTime); const perkObject = { left: perk.x, right: perk.x + perk.width, top: perk.y, bottom: perk.y + perk.height, }; const paddleObject = { left: paddle.x, right: paddle.x + paddle.width, top: paddle.y, bottom: paddle.y + paddle.height, }; const isCollided = calculateAABBCollision(perkObject, paddleObject); if (isCollided) { switch (perk.type) { case 'slow': for (const ball of game.balls) { if (ball.speed - PERK_BALL_SPEED_DECREASE > 0) { ball.increaseSpeed(-1 * PERK_BALL_SPEED_DECREASE); } } setTimeout(() => { for (const ball of game.balls) { ball.increaseSpeed(PERK_BALL_SPEED_DECREASE); } }, PERK_DURATION_SEC * 1000); break; case 'wide': paddle.width = PADDLE_WIDE_WIDTH; paddle.moveTo(paddle.x, 0, CONTAINER_WIDTH); setTimeout(() => { paddle.width = PADDLE_WIDTH; }, PERK_DURATION_SEC * 1000); break; case 'life': game.livesAmount += 1; break; case 'clone': // Основной мяч делится на два клона, разлетающихся под углом game.balls.push(clone(game.ball, BALL_SPLIT_ANGLE), clone(game.ball, -BALL_SPLIT_ANGLE)); break; default: break; } perk.alive = false; } else if (perk.y > containerHeight) { perk.alive = false; } } game.perks = game.perks.filter((perk) => perk.alive); } catch (err) { console.error(err); return null; } }