Canvas.getContext:一旦事件发生,就改变对象的颜色

Kal*_*ali 5 javascript html5-canvas

我正试图在html <canvas>中使用javascript来解决这个问题,我开始使用MDN Breakout游戏教程.以下是完整游戏的外观.我坚持使用其中一个练习,经过一个小时的谷歌搜索后我找不到任何解决方案!:((.以下代码在画布上生成一个球.

ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fillStyle = '#FFFFF';
ctx.fill();
ctx.closePath();
Run Code Online (Sandbox Code Playgroud)

我需要球在与其中一块砖碰撞后改变颜色.为了实现这一点,我创建了一个变量来存储颜色值:let colour = '#FFFFF';,然后在检测碰撞的函数中,改变了这个变量的值.然而,无论何时球改变颜色,它的工作都很好,砖块和桨也是如此.当我试图解决这个问题时,我发现无论何时我手动改变球,砖或桨的颜色(所有这些都设置在不同的功能中),所有对象也会改变颜色.

这很奇怪,因为如果在一个emply .js文件中,我只做两个形状并以不同方式着色它可以正常工作:

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

    ctx.beginPath();
    ctx.rect(0, 0, 20, 40);
    ctx.fillStyle = 'cyan';
    ctx.fill();
    ctx.closePath();


    ctx.beginPath();
    ctx.arc(50, 50, 20, 0, Math.PI*2);
    ctx.fillStyle = 'black';
    ctx.fill();
    ctx.closePath();
Run Code Online (Sandbox Code Playgroud)

但是对于我现在拥有的所有游戏代码,我不能为不同的对象分配不同的颜色,它们都会改变颜色!我不知道如何解决这个问题,只改变球的颜色!有谁知道可能导致这个问题的原因?请帮忙,非常感谢你

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

//Ball variables
const radius = 10;
let colour = '#FFFFF';
let x = canvas.width / 2;
let y = canvas.height - 30;
let dx = 2;
let dy = -2;

//Paddle
const paddleHeight = 10;
let paddleWidth = 100;
let paddleX = (canvas.width - paddleWidth) / 2;

//Paddle movement
var rightPressed = false;
var leftPressed = false;

//Bricks
var brickRowCount = 3;
var brickColumnCount = 5;
var brickWidth = 75;
var brickHeight = 20;
var brickPadding = 10;
var brickOffsetTop = 30;
var brickOffsetLeft = 30;
var bricks = [];
for (var c = 0; c < brickColumnCount; c++) {
  bricks[c] = [];
  for (var r = 0; r < brickRowCount; r++) {
    bricks[c][r] = {
      x: 0,
      y: 0,
      status: 1
    };;
  }
}

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  drawBall();
  drawPaddle();
  drawBricks();
  collisionDetection();
  x += dx;
  y += dy;
  if (rightPressed && paddleX < canvas.width - paddleWidth) {
    paddleX += 7;
  } else if (leftPressed && paddleX > 0) {
    paddleX -= 7;
  }
}

function drawBall() {
  ctx.beginPath();
  ctx.arc(x, y, radius, 0, Math.PI * 2);
  ctx.fillStyle = colour;
  ctx.fill();
  ctx.closePath();

  //Bounce off the walls
  if (x + dx > canvas.width - radius || x + dx < radius) {
    dx = -dx;
  }
  if (y + dy < radius) {
    dy = -dy;
  } else if (y + dy > canvas.height - radius) {
    //Collision detection (ball + paddle)
    if (x > paddleX && x < paddleX + paddleWidth) {
      dy = -dy;
    } else {
      //alert("GAME OVER");
      document.location.reload();
    }
  }
}


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

function drawBricks() {
  for (var c = 0; c < brickColumnCount; c++) {
    for (var r = 0; r < brickRowCount; r++) {
      if (bricks[c][r].status == 1) {
        var brickX = (c * (brickWidth + brickPadding)) + brickOffsetLeft;
        var 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 = "#FFFFF";
        ctx.fill();
        ctx.closePath();
      }
    }
  }
}

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 (var c = 0; c < brickColumnCount; c++) {
    for (var r = 0; r < brickRowCount; r++) {
      var 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;
          colour = '#ff9ecb';
        }
      }
    }
  }
}

var interval = setInterval(draw, 10);
Run Code Online (Sandbox Code Playgroud)
<!DOCTYPE html>
<html>
<head>

<title>Breakout Game</title>

</head>
<body>

<canvas id='canvas' height='320' width='480'></canvas>
<script src="app.js"></script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

Dac*_*nny 2

您用于 的颜色十六进制代码看起来像是一个小错误fillStyle,该错误无效。请参阅以下代码片段中的更正:

let colour = '#FFFFF'; // Six characters invalid
Run Code Online (Sandbox Code Playgroud)

到:

let colour = '#FF0000'; // Seven characters valid
Run Code Online (Sandbox Code Playgroud)

let colour = '#FFFFF'; // Six characters invalid
Run Code Online (Sandbox Code Playgroud)
let colour = '#FF0000'; // Seven characters valid
Run Code Online (Sandbox Code Playgroud)

另外,考虑使用fillRect()如上所示的稍微简单的实现。希望有帮助!

  • 实际上,他们最好在drawBricks函数中坚持使用rect(),但他们应该在循环之前仅调用一次beginPath,并在循环之后仅设置fillStyle并调用fill一次。为相同样式的形状创建长路径对象可以提高很多性能。(PS:所有这些对 closePath() 的调用都是 nooops) (2认同)