import { Container, Graphics } from 'pixi.js'; import { Ball } from './entities/ball/ball'; import { Brick } from './entities/brick/brick'; import { Paddle } from './entities/paddle/paddle'; import { Perk } from './entities/perk/perk'; import { Game } from './game'; /** * Создает визуальное отображение мяча с помощью Pixi.js * @param {Ball} ball экземпляр класса мяч */ function createBallView(ball) { return new Graphics().circle(0, 0, ball.radius).fill('#ffffff'); } /** * Создает визуальное отображение ракетки с помощью Pixi.js * @param {Paddle} paddle экземпляр класса ракетка */ function createPaddleView(paddle) { return new Graphics().rect(0, 0, paddle.width, paddle.height).fill('#fff000'); } /** * Создает визуальное отображение кирпича с помощью Pixi.js * @param {Brick} brick экземпляр класса кирпич * @returns {Graphics} графическое отображение кирпича */ function createBrickView(brick) { const brickView = new Graphics().rect(0, 0, brick.width, brick.height); switch (brick.type) { case 2: return brickView.fill('#00ff00'); case 3: return brickView.fill('#ff00ff'); case 1: default: return brickView.fill('#000fff'); } } /** * Создает визуальное отображение бонуса с помощью Pixi.js * @param {Perk} perk экземпляр класса бонус * @returns {Graphics} графическое отображение бонуса */ function createPerkView(perk) { const perkView = new Graphics().rect(0, 0, perk.width, perk.height); switch (perk.type) { case 'slow': return perkView.fill('#00ffff'); case 'wide': return perkView.fill('#0f0f0f'); case 'life': return perkView.fill('#f0f0f0'); default: return perkView.fill('#ffffff'); } } /** * Создает визуальное отображение всех сущностей в игре с помощью Pixi.js и добавляет в контейнер * @param {Game} game экземпляр класса игра * @param {Container} container экземпляр класса контейнер Pixi.js */ export function createGameView(game, container) { try { const balls = new Map(); for (const ball of game.balls) { const ballView = createBallView(ball); container.addChild(ballView); balls.set(ball, ballView); } const paddle = createPaddleView(game.paddle); container.addChild(paddle); const bricks = game.bricks.map((brick) => { const brickView = createBrickView(brick); container.addChild(brickView); return brickView; }); const perks = new Map(); return { balls, paddle, bricks, perks, }; } catch (err) { console.error(err); return null; } } /** * Создает отображения для новых бонусов и удаляет отображения исчезнувших * @param {object} views объект с визуальными отображениями сущностей игры * @param {Game} game экземпляр класса игра * @param {Container} container экземпляр класса контейнер Pixi.js */ export function managePerkViewsLifetime(views, game, container) { if (views.paddle.width !== game.paddle.width) { container.removeChild(views.paddle); views.paddle.destroy(); views.paddle = createPaddleView(game.paddle); container.addChild(views.paddle); } for (const [ball, ballView] of views.balls) { if (!game.balls.includes(ball)) { container.removeChild(ballView); ballView.destroy(); views.balls.delete(ball); } } for (const ball of game.balls) { if (!views.balls.has(ball)) { const ballView = createBallView(ball); container.addChild(ballView); views.balls.set(ball, ballView); } } for (const [perk, perkView] of views.perks) { if (!game.perks.includes(perk)) { container.removeChild(perkView); perkView.destroy(); views.perks.delete(perk); } } for (const perk of game.perks) { if (!views.perks.has(perk)) { const perkView = createPerkView(perk); container.addChild(perkView); views.perks.set(perk, perkView); } } } /** * Синхронизирует отображение сущностей Pixi.js с логикой игры (координаты и тд.) * @param {object} views объект с визуальными отображениями сущностей игры * @param {Game} game экземпляр класса игра */ export function syncronizeViewsWithGame(views, game) { try { if (!(game instanceof Game)) { throw new Error('Аргумент game должен быть экземпляром класса Game'); } for (const ball of game.balls) { const ballView = views.balls.get(ball); ballView.x = ball.x; ballView.y = ball.y; } views.paddle.x = game.paddle.x; views.paddle.y = game.paddle.y; for (let i = 0; i < game.bricks.length; i++) { const brick = game.bricks[i]; const brickView = views.bricks[i]; brickView.x = brick.x; brickView.y = brick.y; brickView.visible = brick.alive; } for (const perk of game.perks) { const perkView = views.perks.get(perk); perkView.x = perk.x; perkView.y = perk.y; } } catch (err) { console.error(err); } } /** * Пересоздает отображения кирпичей под текущий уровень игры. * @param {object} views объект с визуальными отображениями сущностей игры * @param {Game} game экземпляр класса игра * @param {Container} container экземпляр класса контейнер Pixi.js */ export function rebuildBrickViews(views, game, container) { for (const brickView of views.bricks) { container.removeChild(brickView); brickView.destroy(); } views.bricks = game.bricks.map((brick) => { const brickView = createBrickView(brick); container.addChild(brickView); return brickView; }); }