Files
arkanoid/src/view.js
T

257 lines
8.6 KiB
JavaScript
Raw Normal View History

import { AnimatedSprite, Container, Graphics, NineSliceSprite, Sprite, Text } from 'pixi.js';
import { CONTAINER_HEIGHT, CONTAINER_WIDTH } from './config';
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 экземпляр класса мяч
* @param {object} textures объект с текстурами для визуального отображения
*/
function createBallView(ball, textures) {
const ballFrames = [
textures['/sprites/fire_ball_1.png'],
textures['/sprites/fire_ball_2.png'],
textures['/sprites/fire_ball_3.png'],
textures['/sprites/fire_ball_4.png'],
textures['/sprites/fire_ball_5.png'],
textures['/sprites/fire_ball_6.png'],
textures['/sprites/fire_ball_7.png'],
textures['/sprites/fire_ball_8.png'],
];
const ballSprite = new AnimatedSprite(ballFrames);
ballSprite.animationSpeed = 0.15;
ballSprite.anchor.set(0.5);
ballSprite.width = ball.radius * 2;
ballSprite.height = ball.radius * 2;
ballSprite.play();
return ballSprite;
}
/**
* Создает визуальное отображение ракетки с помощью Pixi.js
* @param {Paddle} paddle экземпляр класса ракетка
* @param {object} textures объект с текстурами для визуального отображения
*/
function createPaddleView(paddle, textures) {
const texture = textures['/sprites/paddle.png'];
const paddleSprite = new NineSliceSprite({ texture, leftWidth: 150, rightWidth: 150, topHeight: 0, bottomHeight: 0 });
paddleSprite.width = paddle.width;
paddleSprite.height = paddle.height;
return paddleSprite;
}
/**
* Создает визуальное отображение кирпича с помощью Pixi.js
* @param {Brick} brick экземпляр класса кирпич
* @returns {Graphics} графическое отображение кирпича
* @param {object} textures объект с текстурами для визуального отображения
*/
function createBrickView(brick, textures) {
const bricksTextures = [
textures['/sprites/block_1.png'],
textures['/sprites/block_2.png'],
textures['/sprites/block_3.png'],
];
const brickSprite = new Sprite(bricksTextures[brick.type - 1]);
brickSprite.width = brick.width;
brickSprite.height = brick.height;
return brickSprite;
}
/**
* Создает визуальное отображение бонуса с помощью Pixi.js
* @param {Perk} perk экземпляр класса бонус
* @returns {Graphics} графическое отображение бонуса
* @param {object} textures текстуры блоков
*/
function createPerkView(perk, textures) {
let texture;
switch (perk.type) {
case 'slow':
texture = textures['/sprites/perk_1.png'];
break;
case 'wide':
texture = textures['/sprites/perk_2.png'];
break;
case 'life':
texture = textures['/sprites/perk_3.png'];
break;
case 'clone':
texture = textures['/sprites/perk_3.png'];
break;
default:
texture = textures['/sprites/perk_1.png'];
break;
}
const perkSprite = new Sprite(texture);
perkSprite.width = perk.width;
perkSprite.height = perk.height;
return perkSprite;
}
/**
* Создает визуальное отображение всех сущностей в игре с помощью Pixi.js и добавляет в контейнер
* @param {Game} game экземпляр класса игра
* @param {Container} container экземпляр класса контейнер Pixi.js
* @param {object} textures объект с текстурами для визуального отображения
*/
export function createGameView(game, container, textures) {
try {
const background = new Sprite(textures['/sprites/background_1.png']);
background.width = CONTAINER_WIDTH;
background.height = CONTAINER_HEIGHT;
container.addChildAt(background, 0);
const header = new Text({ style: { fill: '#ffffff', fontSize: 16 } });
header.x = 8;
header.y = 8;
container.addChild(header);
const balls = new Map();
for (const ball of game.balls) {
const ballView = createBallView(ball, textures);
container.addChild(ballView);
balls.set(ball, ballView);
}
const paddle = createPaddleView(game.paddle, textures);
container.addChild(paddle);
const bricks = game.bricks.map((brick) => {
const brickView = createBrickView(brick, textures);
container.addChild(brickView);
return brickView;
});
const perks = new Map();
return {
header,
balls,
paddle,
bricks,
perks,
};
} catch (err) {
console.error(err);
return null;
}
}
/**
* Создает отображения для новых бонусов и удаляет отображения исчезнувших
* @param {object} views объект с визуальными отображениями сущностей игры
* @param {Game} game экземпляр класса игра
* @param {Container} container экземпляр класса контейнер Pixi.js
* @param {object} textures объект с текстурами для визуального отображения
*/
export function managePerkViewsLifetime(views, game, container, textures) {
if (views.paddle.width !== game.paddle.width) {
views.paddle.width = game.paddle.width;
}
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, textures);
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, textures);
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');
}
views.header.text = `Уровень: ${game.currentLevel + 1} Количество жизней: ${game.livesAmount}`;
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
* @param {object} textures объект с текстурами для визуального отображения
*/
export function rebuildBrickViews(views, game, container, textures) {
for (const brickView of views.bricks) {
container.removeChild(brickView);
brickView.destroy();
}
views.bricks = game.bricks.map((brick) => {
const brickView = createBrickView(brick, textures);
container.addChild(brickView);
return brickView;
});
}