import './style.css'; import { Application, Assets, Container, Graphics, Sprite } from 'pixi.js'; import { BALL_INITIAL_ANGLE, BALL_RADIUS, BALL_SPEED, BRICK_HEIGHT, BRICK_WIDTH, CONTAINER_HEIGHT, CONTAINER_WIDTH, PADDLE_HEIGHT, PADDLE_WIDTH, } from './config'; import { calculateCollision } from './lib/calculateCollision/calculateCollision'; import { calculateDirection } from './lib/calculateDirection/calculateDirection'; (async () => { // Create a new application const app = new Application(); // Initialize the application await app.init({ background: '#1099bb', width: CONTAINER_WIDTH, height: CONTAINER_HEIGHT }); // Append the application canvas to the document body document.body.appendChild(app.canvas); // Create and add a container to the stage const container = new Container({ eventMode: 'static', hitArea: app.screen, }); container.x = 0; container.y = 0; app.stage.addChild(container); const paddle = new Graphics().rect(0, CONTAINER_HEIGHT - PADDLE_HEIGHT, PADDLE_WIDTH, PADDLE_HEIGHT).fill('#fff000'); container.addChild(paddle); container.on('pointermove', (event) => { const localPosition = container.toLocal(event.global); if (localPosition.x < CONTAINER_WIDTH - PADDLE_WIDTH) { paddle.x = localPosition.x; } }); const bricksRow = Array.from({ length: Math.floor(CONTAINER_WIDTH / BRICK_WIDTH) }).map((_, index) => { const brick = new Graphics().rect(0, 0, BRICK_WIDTH, BRICK_HEIGHT).fill('#000fff'); brick.x = index * BRICK_WIDTH; brick.y = 1; container.addChild(brick); return brick; }); const ball = new Graphics().circle(0, 0, BALL_RADIUS).fill('#ffffff'); ball.x = 100; ball.y = 100; container.addChild(ball); const leftBoundary = BALL_RADIUS; const rightBoundary = CONTAINER_WIDTH - BALL_RADIUS; const topBoundary = BALL_RADIUS; const bottomBoundary = CONTAINER_HEIGHT - BALL_RADIUS; const paddleTop = CONTAINER_HEIGHT - PADDLE_HEIGHT; const bricksBottom = BRICK_HEIGHT; let horizontalSpeed = BALL_SPEED * Math.cos(BALL_INITIAL_ANGLE); let verticalSpeed = -1 * BALL_SPEED * Math.sin(BALL_INITIAL_ANGLE); app.ticker.add((time) => { // Базоввое взаимодействие мяча и кирпича for (let i = bricksRow.length - 1; i >= 0; i--) { const currentBrick = bricksRow[i]; const brickLeft = currentBrick.x; const brickRight = currentBrick.x + BRICK_WIDTH; const brickTop = currentBrick.y; const brickBottom = currentBrick.y + BRICK_HEIGHT; const ballLeft = ball.x - BALL_RADIUS; const ballRight = ball.x + BALL_RADIUS; const ballTop = ball.y - BALL_RADIUS; const ballBottom = ball.y + BALL_RADIUS; const ballObject = { left: ballLeft, right: ballRight, top: ballTop, bottom: ballBottom }; const brickObject = { left: brickLeft, right: brickRight, top: brickTop, bottom: brickBottom }; const isCollided = calculateCollision(ballObject, brickObject); const directions = calculateDirection(ballObject, brickObject); if (isCollided && directions !== null) { horizontalSpeed *= directions[0]; verticalSpeed *= directions[1]; container.removeChild(currentBrick); currentBrick.destroy(); bricksRow.splice(i, 1); break; } } // Не даем мячу выйти за границы стен слева / справав и меняем направление if (ball.x <= leftBoundary || ball.x >= rightBoundary) { ball.x = ball.x <= leftBoundary ? leftBoundary : rightBoundary; horizontalSpeed *= -1; } // Не даем мячу выйти за границы стен сверху / снизу и меняем направление if (ball.y <= topBoundary || ball.y >= bottomBoundary) { ball.y = ball.y <= topBoundary ? topBoundary : bottomBoundary; verticalSpeed *= -1; } // Базоввое взаимодействие мяча и ракетки if ( verticalSpeed > 0 && ball.y + BALL_RADIUS >= paddleTop && ball.x >= paddle.x && ball.x <= paddle.x + PADDLE_WIDTH ) { verticalSpeed *= -1; } ball.x += horizontalSpeed * time.deltaTime; ball.y += verticalSpeed * time.deltaTime; }); })();