2026-07-14 19:11:15 +03:00
|
|
|
import './style.css';
|
2026-07-16 08:30:14 +03:00
|
|
|
import { Application, Assets, Container, Graphics, Sprite } from 'pixi.js';
|
2026-07-16 09:05:55 +03:00
|
|
|
import {
|
|
|
|
|
BALL_INITIAL_ANGLE,
|
|
|
|
|
BALL_RADIUS,
|
|
|
|
|
BALL_SPEED,
|
2026-07-18 10:53:38 +03:00
|
|
|
BRICK_COLUMN_AMOUNT,
|
2026-07-16 12:46:09 +03:00
|
|
|
BRICK_HEIGHT,
|
2026-07-18 10:53:38 +03:00
|
|
|
BRICK_ROW_AMOUNT,
|
2026-07-16 12:46:09 +03:00
|
|
|
BRICK_WIDTH,
|
2026-07-16 09:05:55 +03:00
|
|
|
CONTAINER_HEIGHT,
|
|
|
|
|
CONTAINER_WIDTH,
|
|
|
|
|
PADDLE_HEIGHT,
|
|
|
|
|
PADDLE_WIDTH,
|
|
|
|
|
} from './config';
|
2026-07-18 17:47:33 +03:00
|
|
|
import { LEVELS } from './const/levels';
|
2026-07-18 10:53:38 +03:00
|
|
|
import { Game } from './game';
|
2026-07-19 15:09:56 +03:00
|
|
|
import { createGameView, managePerkViewsLifetime, rebuildBrickViews, syncronizeViewsWithGame } from './view';
|
2026-07-14 19:44:13 +03:00
|
|
|
|
|
|
|
|
(async () => {
|
|
|
|
|
const app = new Application();
|
2026-07-16 08:30:14 +03:00
|
|
|
await app.init({ background: '#1099bb', width: CONTAINER_WIDTH, height: CONTAINER_HEIGHT });
|
2026-07-14 19:44:13 +03:00
|
|
|
document.body.appendChild(app.canvas);
|
|
|
|
|
|
2026-07-16 08:30:14 +03:00
|
|
|
const container = new Container({
|
|
|
|
|
eventMode: 'static',
|
|
|
|
|
hitArea: app.screen,
|
|
|
|
|
});
|
|
|
|
|
container.x = 0;
|
|
|
|
|
container.y = 0;
|
2026-07-14 19:44:13 +03:00
|
|
|
|
|
|
|
|
app.stage.addChild(container);
|
|
|
|
|
|
2026-07-20 09:17:23 +03:00
|
|
|
const textures = await Assets.load([
|
|
|
|
|
'/sprites/fire_ball_1.png',
|
|
|
|
|
'/sprites/background_1.png',
|
|
|
|
|
'/sprites/paddle.png',
|
|
|
|
|
'/sprites/block_1.png',
|
|
|
|
|
'/sprites/block_2.png',
|
|
|
|
|
'/sprites/block_3.png',
|
2026-07-20 09:52:59 +03:00
|
|
|
'/sprites/perk_1.png',
|
|
|
|
|
'/sprites/perk_2.png',
|
|
|
|
|
'/sprites/perk_3.png',
|
|
|
|
|
'/sprites/perk_4.png',
|
2026-07-20 09:17:23 +03:00
|
|
|
]);
|
2026-07-19 21:11:56 +03:00
|
|
|
|
2026-07-18 17:47:33 +03:00
|
|
|
const game = new Game(LEVELS);
|
2026-07-19 21:11:56 +03:00
|
|
|
const views = createGameView(game, container, textures);
|
2026-07-19 11:10:48 +03:00
|
|
|
let currentLevel = game.currentLevel;
|
2026-07-14 19:44:13 +03:00
|
|
|
|
2026-07-16 08:30:14 +03:00
|
|
|
container.on('pointermove', (event) => {
|
|
|
|
|
const localPosition = container.toLocal(event.global);
|
2026-07-18 10:53:38 +03:00
|
|
|
game.paddle.moveTo(localPosition.x, 0, CONTAINER_WIDTH);
|
2026-07-14 19:44:13 +03:00
|
|
|
});
|
2026-07-16 09:05:55 +03:00
|
|
|
|
2026-07-19 11:24:37 +03:00
|
|
|
container.on('pointerdown', () => {
|
|
|
|
|
game.ball.launch();
|
|
|
|
|
});
|
|
|
|
|
|
2026-07-16 09:05:55 +03:00
|
|
|
app.ticker.add((time) => {
|
2026-07-18 10:53:38 +03:00
|
|
|
game.update(time.deltaTime);
|
2026-07-19 10:53:40 +03:00
|
|
|
|
|
|
|
|
if (game.currentLevel !== currentLevel) {
|
2026-07-20 09:17:23 +03:00
|
|
|
rebuildBrickViews(views, game, container, textures);
|
2026-07-19 11:10:48 +03:00
|
|
|
currentLevel = game.currentLevel;
|
2026-07-19 10:53:40 +03:00
|
|
|
}
|
2026-07-20 09:52:59 +03:00
|
|
|
managePerkViewsLifetime(views, game, container, textures);
|
2026-07-18 10:53:38 +03:00
|
|
|
syncronizeViewsWithGame(views, game);
|
2026-07-20 10:22:03 +03:00
|
|
|
|
|
|
|
|
if (game.status === 'over' || game.status === 'completed') {
|
|
|
|
|
showEndScreen(game.status === 'completed' ? 'Победа!' : 'Игра окончена!');
|
|
|
|
|
app.ticker.stop();
|
|
|
|
|
}
|
2026-07-16 09:05:55 +03:00
|
|
|
});
|
2026-07-14 19:44:13 +03:00
|
|
|
})();
|
2026-07-20 10:22:03 +03:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Показывает финальный экран с сообщением и кнопкой рестарта (перезагрузка страницы).
|
|
|
|
|
* @param {string} message текст результата игры
|
|
|
|
|
*/
|
|
|
|
|
function showEndScreen(message) {
|
|
|
|
|
const overlay = document.createElement('div');
|
|
|
|
|
overlay.className = 'end-screen';
|
|
|
|
|
overlay.innerHTML = `<p>${message}</p><button class="button" type="button">Начать заново</button>`;
|
|
|
|
|
overlay.querySelector('button').addEventListener('click', () => location.reload());
|
|
|
|
|
document.body.appendChild(overlay);
|
|
|
|
|
}
|