refactor: Создана функция processBrickCollision для инкапсуляции логики проверки столкновения мяча с кирпичами
This commit is contained in:
@@ -0,0 +1,74 @@
|
|||||||
|
import { 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 && 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { Game } from '../../game';
|
||||||
|
import { processBrickCollision } from './processBrickCollision';
|
||||||
|
|
||||||
|
describe('processBrickCollision', () => {
|
||||||
|
it('Возвращает корректное значение при неверных типах аргументов', () => {
|
||||||
|
const game = new Game([[[1]]]);
|
||||||
|
|
||||||
|
expect(processBrickCollision(null, game.ball)).toBeNull();
|
||||||
|
expect(processBrickCollision(game, null)).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Возвращает креектное значение если мяч не касается кирпичей', () => {
|
||||||
|
const game = new Game([[[1]]]);
|
||||||
|
game.ball.x = 5;
|
||||||
|
game.ball.y = 500;
|
||||||
|
|
||||||
|
expect(processBrickCollision(game, game.ball)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('При столкновении разрушает кирпич и меняет направление мяча', () => {
|
||||||
|
const game = new Game([[[1]]]);
|
||||||
|
const brick = game.bricks[0];
|
||||||
|
game.ball.x = brick.x + game.ball.radius + 1;
|
||||||
|
game.ball.y = brick.y + brick.height + game.ball.radius + 1;
|
||||||
|
game.ball.horizontalSpeed = 0;
|
||||||
|
game.ball.verticalSpeed = -10;
|
||||||
|
game.ball.moveForward(1);
|
||||||
|
|
||||||
|
expect(processBrickCollision(game, game.ball)).toBe(true);
|
||||||
|
expect(brick.alive).toBe(false);
|
||||||
|
expect(game.ball.verticalSpeed).toBe(10);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user