Reputation: 135
I'm trying to get my head around using javascript in the html < canvas >, and I started with the MDN Breakout game tutorial. Here is how the complete game looks like. I'm stuck with one of the exercises and I really could not find any solution to my issue after an hour of googling!! :((. The following code generates a ball on the canvas.
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fillStyle = '#FFFFF';
ctx.fill();
ctx.closePath();
I needed the ball to change its colour after it collides with one of the bricks. In order to achieve that, I created a variable to store the colour value: let colour = '#FFFFF';
, and later in a function which detects collisions, changed the value of this variable. It worked fine, however, whenever the ball changed its colour, so did the bricks and the paddle. As I tried to fix this, I found out that whenever I manually change the colour of either a ball, a brick or a paddle (all of which are set in different functions), all of the objects change the colour as well.
This is very strange, because if in an emply .js file I make just two shapes and colour them differently it works fine:
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();
But with all the game code I have right now, I can not assign different colour to different objects, they all change colour instead! I have no idea how to fix this and change just the colour of the ball! Anyone knows what might be causing the issue? Please help, thank you so much in advance 🙏
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>
Upvotes: 5
Views: 106
Reputation: 30370
Looks like a minor error with the colour hex codes you're using for your fillStyle
, which are invalid. See the corrections in the snippet below from:
let colour = '#FFFFF'; // Six characters invalid
To:
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>
Also, consider using fillRect()
as shown above, for a slightly simpler implementation. Hope that helps!
Upvotes: 2