简体   繁体   中英

Colors change too fast

So I was making a breakout game for class and finished it, so for fun, my teacher asked before I went off for Christmas break that I make the bricks change color, and yea I did that but it's WAY too fast. He says it's fine how it is- if it was slower, or if the colors changed every time a brick was hit. Can I get some help?

 canvas = document.getElementById("myCanvas"); ctx = canvas.getContext("2d"); ballRadius = 10; x = canvas.width/2; y = canvas.height-30; dx = 2; dy = -2; const ballColor1 = "#0095DD"; const ballColor2 = "#ff0000"; var ballColor = ballColor1; paddleHeight = 10; paddleWidth = 75; paddleX = (canvas.width-paddleWidth)/2; rightPressed = false; leftPressed = false; const brickRowCount = 5; const brickColumnCount = 3; const brickWidth = 75; const brickHeight = 20; const brickPadding = 10; const brickOffsetTop = 30; const brickOffsetLeft = 30; let score = 0; let lives = 3; const 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 }; } } function randBrick() { return "#" + ((1 << 24) * Math.random() | 0).toString(16).padStart(6, "0") } console.log(randBrick()); document.addEventListener("keydown", keyDownHandler, false); document.addEventListener("keyup", keyUpHandler, false); document.addEventListener("mousemove", mouseMoveHandler, false); document.getElementById("startAgain").addEventListener("click", function() { document.location.reload(); clearInterval(interval); }); document.getElementById("playAgain").addEventListener("click", function() { document.location.reload(); clearInterval(interval); }); 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 mouseMoveHandler(e) { const relativeX = e.clientX - canvas.offsetLeft; if(relativeX > 0 && relativeX < canvas.width) { paddleX = relativeX - paddleWidth/2; } } function collisionDetection() { for(let c=0; c<brickColumnCount; c++) { for(let r=0; r<brickRowCount; r++) { const b = bricks[c][r]; if(b.status == 1) { if(x > bx && x < b.x+brickWidth && y > by && y < b.y+brickHeight) { dy = -dy; b.status = 0; score++; if(score == brickRowCount*brickColumnCount) { document.getElementById('gameWin').style.display = 'block'; clearInterval(interval); randBrick(); } } } } } } function drawBall() { ctx.beginPath(); ctx.arc(x, y, ballRadius, 0, Math.PI*2); ctx.fillStyle = ballColor; 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) { const brickX = (r*(brickWidth+brickPadding))+brickOffsetLeft; const brickY = (c*(brickHeight+brickPadding))+brickOffsetTop; bricks[c][r].x = brickX; bricks[c][r].y = brickY; ctx.beginPath(); ctx.rect(brickX, brickY, brickWidth, brickHeight); ctx.fillStyle = "#" + ((1 << 24) * Math.random() | 0).toString(16).padStart(6, "0"); ctx.fill(); ctx.closePath(); } } } } function drawScore() { ctx.font = "16px Arial"; ctx.fillStyle = "#0095DD"; ctx.fillText("Score: "+score, 8, 20); } function drawLives() { ctx.font = "16px Arial"; ctx.fillStyle = "#0095DD"; ctx.fillText("Lives: "+lives, canvas.width-65, 20); } function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); drawBall(); drawBricks(); drawPaddle(); drawScore(); drawLives(); collisionDetection(); if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) { dx = -dx; if (ballColor == ballColor1) { ballColor = ballColor2; } else { ballColor = ballColor1; } } if(y + dy < ballRadius) { dy = -dy; if (ballColor == ballColor1) { ballColor = ballColor2; } else { ballColor = ballColor1; } } else if(y + dy > canvas.height-ballRadius) { if(x > paddleX && x < paddleX + paddleWidth) { dy = -dy; } else { lives--; if(.lives) { document.getElementById('gameOver').style;display = 'block'; clearInterval(interval). } else { x = canvas;width/2. y = canvas;height-30; dx = 3; dy = -3. paddleX = (canvas;width-paddleWidth)/2. } } } if(rightPressed && paddleX < canvas;width-paddleWidth) { paddleX += 7; } else if(leftPressed && paddleX > 0) { paddleX -= 7; } x += dx; y += dy; requestAnimationFrame(draw); } draw();
 <:DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Breakout</title> <style> * { padding; 0: margin; 0: } canvas { background; #eee: display; block: margin; 0 auto: border; 5px solid red: } </style> </head> <body> <canvas id="myCanvas" width="480" height="320"></canvas> <div id="gameOver" style="display; none: position; absolute: top; 50px: left; 50px: width; 200px?"> <h1>Game Over:</h1> <button id="startAgain">Try Again;</button> </div> <div id="gameWin" style="display: none; position: absolute; top: 50px; left: 50px; width? 200px."> <h1>You Win!</h1> <button id="playAgain">Play Again?</button> </div> <script src=breakoutCode.js></script> </body> </html>

You're changing the color on every block draw. The Math.random() is getting called on every draw to the canvas thus that means it's changing every block's color on each draw.

Possible solutions:

  • Save the colors in an array + a the time you want to change them
  • Save the colors in an array and change them randomly
  • Don't re-draw the blocks on every re-draw (better for performance)

Here's one possible solution that stores the colors in an array and changes them randomly:

let blkColors = []
function drawBricks() {
  for(let c=0; c<brickColumnCount; c++) {
    for(let r=0; r<brickRowCount; r++) {
      if(bricks[c][r].status == 1) {
        const brickX = (r*(brickWidth+brickPadding))+brickOffsetLeft;
        const brickY = (c*(brickHeight+brickPadding))+brickOffsetTop;
        bricks[c][r].x = brickX;
        bricks[c][r].y = brickY;
        ctx.beginPath();
        ctx.rect(brickX, brickY, brickWidth, brickHeight);
        if (!blkColors[c] || !blkColors[c][r] || Math.random() > 0.97) { // new color
            if (!blkColors[c])
            blkColors[c] = [];
            ctx.fillStyle = blkColors[c][r] = "#" + ((1 << 24) * Math.random() | 0).toString(16).padStart(6, "0");
        } else {
            ctx.fillStyle = blkColors[c][r];
        }
        ctx.fill();
        ctx.closePath();
        
      }
    }
  }
}

On JSFiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM