Canvas.getContext: изменение цвета объекта при возникновении события

93
6

Я пытаюсь разобраться, используя javascript в html <canvas>, и я начал с учебного курса по MDN Breakout. Вот как выглядит законченная игра. Я застрял в одном из упражнений, и я действительно не мог найти решение своей проблемы после часа поиска в Google !! : ((. Следующий код генерирует шарик на холсте.

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

Мне нужно было, чтобы шар изменил свой цвет после того, как он столкнулся с одним из кирпичей. Для этого я создал переменную для хранения значения цвета: 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();

Но со всем кодом игры, который у меня есть сейчас, я не могу назначить разные цвета разным объектам, они все меняют цвет! Я понятия не имею, как это исправить и изменить только цвет шара! Кто-нибудь знает, что может быть причиной проблемы? Пожалуйста, помогите, большое спасибо заранее 🙏

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);

<!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>

спросил(а) 2019-01-08T01:43:00+03:00 1 год, 6 месяцев назад
1
Решение
67

Похоже, небольшая ошибка с цветными шестнадцатеричными кодами, которые вы используете для fillStyle, которые являются недопустимыми. Смотрите исправления во фрагменте ниже:

let colour = '#FFFFF'; // Six characters invalid

Для того, чтобы:

let colour = '#FF0000'; // Seven characters valid

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

//Ball variables
const radius = 10;

// Fix colour
let colour = '#FF0000';
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() {
// Update to valid colour
ctx.fillStyle = colour;

ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
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() {
// Update to valid colour
ctx.fillStyle = '#00FF00';
// Consider using fillRect
ctx.fillRect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
}

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;

// Update to valid colour
ctx.fillStyle = "#FFFFaa";
// Consider using fillRect
ctx.fillRect(brickX, brickY, brickWidth, brickHeight);
}
}
}
}

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);

<!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>

Кроме того, рассмотрите возможность использования fillRect() как показано выше, для немного более простой реализации. Надеюсь, это поможет!

ответил(а) 2019-01-08T01:55:00+03:00 1 год, 6 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема