GhostWriter

Create Arkanoid Game: HTML/JS

GhostWriter

Ouvrir le chat partagé d'origine

Utilisateur

write code for the game Arkanoid (Breakout) using html and JS in color, in full so I can play immediately without fixnig anything

GhostWriter

To create a fully functional Arkanoid (Breakout) game using HTML and JavaScript, we'll need several components. The game involves a paddle, a ball, bricks, and the logic for collision detection, game score, and levels. Let's break down the necessary components and then provide the complete code:

  1. index.html: This file will contain the basic HTML structure and link our JavaScript and CSS files.
  2. styles.css: This file will contain the CSS styles to make our game look more appealing.
  3. game.js: This is the main JavaScript file where we will write the game logic, including handling user input, drawing the game elements, and the game's mechanics.

Project Files and Code

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Arkanoid Game</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <canvas id="gameCanvas"></canvas>
    <script src="game.js"></script>
</body>
</html>

styles.css

body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #f0f0f0;
}

canvas {
    border: 1px solid #000;
    background-color: #eee;
}

game.js

const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');

canvas.width = 800;
canvas.height = 600;

let ballRadius = 10;
let x = canvas.width / 2;
let y = canvas.height - 30;
let dx = 2;
let dy = -2;

let paddleHeight = 10;
let paddleWidth = 75;
let paddleX = (canvas.width - paddleWidth) / 2;

let rightPressed = false;
let leftPressed = false;

let brickRowCount = 5;
let brickColumnCount = 3;
let brickWidth = 75;
let brickHeight = 20;
let brickPadding = 10;
let brickOffsetTop = 30;
let brickOffsetLeft = 30;

let score = 0;

let bricks = [];
for (let c = 0; c < brickColumnCount; c++) {
    bricks[c] = [];
    for (let r = 0; r < brickRowCount; r++) {
        bricks[c][r] = { x: 0, y: 0, status: 1 };
    }
}

document.addEventListener('keydown', keyDownHandler, false);
document.addEventListener('keyup', keyUpHandler, false);

function keyDownHandler(e) {
    if (e.key === 'Right' || e.key === 'ArrowRight') {
        rightPressed = true;
    } else if (e.key === 'Left' || e.key === 'ArrowLeft') {
        leftPressed = true;
    }
}

function keyUpHandler(e) {
    if (e.key === 'Right' || e.key === 'ArrowRight') {
        rightPressed = false;
    } else if (e.key === 'Left' || e.key === 'ArrowLeft') {
        leftPressed = false;
    }
}

function collisionDetection() {
    for (let c = 0; c < brickColumnCount; c++) {
        for (let r = 0; r < brickRowCount; r++) {
            let b = bricks[c][r];
            if (b.status === 1) {
                if (x > b.x && x < b.x + brickWidth && y > b.y && y < b.y + brickHeight) {
                    dy = -dy;
                    b.status = 0;
                    score++;
                    if (score === brickRowCount * brickColumnCount) {
                        alert('Congratulations! You win!');
                        document.location.reload();
                    }
                }
            }
        }
    }
}

function drawBall() {
    ctx.beginPath();
    ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
    ctx.fillStyle = '#0095DD';
    ctx.fill();
    ctx.closePath();
}

function drawPaddle() {
    ctx.beginPath();
    ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
    ctx.fillStyle = '#0095DD';
    ctx.fill();
    ctx.closePath();
}

function drawBricks() {
    for (let c = 0; c < brickColumnCount; c++) {
        for (let r = 0; r < brickRowCount; r++) {
            if (bricks[c][r].status === 1) {
                let brickX = (c * (brickWidth + brickPadding)) + brickOffsetLeft;
                let brick

GhostWriter

Y = (r * (brickHeight + brickPadding)) + brickOffsetTop; bricks[c][r].x = brickX; bricks[c][r].y = brickY; ctx.beginPath(); ctx.rect(brickX, brickY, brickWidth, brickHeight); ctx.fillStyle = '#0095DD'; ctx.fill(); ctx.closePath(); } } } }

function drawScore() { ctx.font = '16px Arial'; ctx.fillStyle = '#0095DD'; ctx.fillText('Score: ' + score, 8, 20); }

function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); drawBricks(); drawBall(); drawPaddle(); drawScore(); collisionDetection();

if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
    dx = -dx;
}
if (y + dy < ballRadius) {
    dy = -dy;
} else if (y + dy > canvas.height - ballRadius) {
    if (x > paddleX && x < paddleX + paddleWidth) {
        dy = -dy;
    } else {
        alert('GAME OVER');
        document.location.reload();
    }
}

if (rightPressed && paddleX < canvas.width - paddleWidth) {
    paddleX += 7;
} else if (leftPressed && paddleX > 0) {
    paddleX -= 7;
}

x += dx;
y += dy;
requestAnimationFrame(draw);

}

draw();


To play the game, simply place these three files (`index.html`, `styles.css`, and `game.js`) in the same directory and open `index.html` in a web browser. The game should start immediately, and you can play Arkanoid with keyboard arrow keys to move the paddle.

Utilisateur

Update the code to display text on the screen instead of the alerts. They are locking up the system and can't close properly.

GhostWriter

To replace the alert dialogs with on-screen text notifications in the Arkanoid game, we need to modify the JavaScript file (game.js). Instead of using alert for game over and win messages, we'll draw the text directly onto the canvas. This approach will provide a smoother user experience.

Updated game.js

const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');

canvas.width = 800;
canvas.height = 600;

let ballRadius = 10;
let x = canvas.width / 2;
let y = canvas.height - 30;
let dx = 2;
let dy = -2;

let paddleHeight = 10;
let paddleWidth = 75;
let paddleX = (canvas.width - paddleWidth) / 2;

let rightPressed = false;
let leftPressed = false;

let brickRowCount = 5;
let brickColumnCount = 3;
let brickWidth = 75;
let brickHeight = 20;
let brickPadding = 10;
let brickOffsetTop = 30;
let brickOffsetLeft = 30;

let score = 0;
let isGameOver = false;
let isGameWon = false;

let bricks = [];
for (let c = 0; c < brickColumnCount; c++) {
    bricks[c] = [];
    for (let r = 0; r < brickRowCount; r++) {
        bricks[c][r] = { x: 0, y: 0, status: 1 };
    }
}

document.addEventListener('keydown', keyDownHandler, false);
document.addEventListener('keyup', keyUpHandler, false);

function keyDownHandler(e) {
    if (e.key === 'Right' || e.key === 'ArrowRight') {
        rightPressed = true;
    } else if (e.key === 'Left' || e.key === 'ArrowLeft') {
        leftPressed = true;
    }
}

function keyUpHandler(e) {
    if (e.key === 'Right' || e.key === 'ArrowRight') {
        rightPressed = false;
    } else if (e.key === 'Left' || e.key === 'ArrowLeft') {
        leftPressed = false;
    }
}

function collisionDetection() {
    for (let c = 0; c < brickColumnCount; c++) {
        for (let r = 0; r < brickRowCount; r++) {
            let b = bricks[c][r];
            if (b.status === 1) {
                if (x > b.x && x < b.x + brickWidth && y > b.y && y < b.y + brickHeight) {
                    dy = -dy;
                    b.status = 0;
                    score++;
                    if (score === brickRowCount * brickColumnCount) {
                        isGameWon = true;
                    }
                }
            }
        }
    }
}

function drawBall() {
    ctx.beginPath();
    ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
    ctx.fillStyle = '#0095DD';
    ctx.fill();
    ctx.closePath();
}

function drawPaddle() {
    ctx.beginPath();
    ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
    ctx.fillStyle = '#0095DD';
    ctx.fill();
    ctx.closePath();
}

function drawBricks() {
    for (let c = 0; c < brickColumnCount; c++) {
        for (let r = 0; r < brickRowCount; r++) {
            if (bricks[c][r].status === 1) {
                let brickX = (c * (brickWidth + brickPadding)) + brickOffsetLeft;
                let brickY = (r * (brickHeight + brickPadding)) + brickOffsetTop;
                bricks[c][r].x = brickX;
                bricks[c][r].y = brickY;
                ctx.beginPath();
                ctx.rect(brickX, brickY, brickWidth, brickHeight);
                ctx.fillStyle = '#0095DD';
                ctx.fill();
                ctx.closePath();
            }
        }
    }
}

function drawScore() {
    ctx.font = '16px Arial';
    ctx.fillStyle = '#0095DD';
    ctx.fillText('Score: ' + score, 8, 20);
}

function drawMessage(message) {
    ctx.font = '48px Arial';
    ctx.fillStyle = '#0095DD';
    ctx.fillText(message, canvas.width / 4, canvas.height / 2);
}

function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawBricks();
    drawBall();
    drawPaddle();
    drawScore();

    if (isGameWon) {
        drawMessage("Congratulations! You win!");
        return;
    }

    if (isGameOver) {
        drawMessage("GAME OVER");
        return;
    }

    collisionDetection();

    if (x + dx >

GhostWriter

canvas.width - ballRadius || x + dx < ballRadius) { dx = -dx; } if (y + dy < ballRadius) { dy = -dy; } else if (y + dy > canvas.height - ballRadius) { if (x > paddleX && x < paddleX + paddleWidth) { dy = -dy; } else { isGameOver = true; return; } }

if (rightPressed && paddleX < canvas.width - paddleWidth) {
    paddleX += 7;
} else if (leftPressed && paddleX > 0) {
    paddleX -= 7;
}

x += dx;
y += dy;
requestAnimationFrame(draw);

}

draw();


This updated `game.js` code replaces the use of `alert` with drawing text directly onto the canvas. When the game is over or the player wins, it will display a message in the middle of the canvas and stop the game loop. To restart the game, the player will need to reload the page.

Utilisateur

write an IIFE

GhostWriter

An Immediately Invoked Function Expression (IIFE) in JavaScript is a design pattern used to execute a function immediately as it is defined. It is a common approach to prevent polluting the global namespace, allowing for a more modular and maintainable code structure. Here's a basic example of an IIFE:

(function() {
    // Code here is executed immediately
    console.log("This is an Immediately Invoked Function Expression (IIFE)");
})();

In this example, the function is defined and then immediately invoked. The parentheses around the function turn the function declaration into a function expression, and the following parentheses () cause it to be immediately executed.