I am fairly new to using html canvas. I'm creating a breakout game. I want to implement a fall text when a brick is hit that the paddle at the bottom can catch to increase points.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var ballRadius = 10;
var x = canvas.width / 2;
var y = canvas.height - 30;
var dx = 2;
var dy = -2;
var paddleHeight = 10;
var paddleWidth = 75;
var paddleX = (canvas.width - paddleWidth) / 2;
var rightPressed = false;
var leftPressed = false;
var brickRowCount = 4;
var brickColumnCount = 4;
var brickWidth = 50;
var brickHeight = 10;
var brickPadding = 15;
var brickOffsetTop = 30;
var brickOffsetLeft = 30;
var score = 0;
var lives = 3;
var reward = { value: 1, x: canvas.width / 2 - 5, y: 20 };
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 };
}
}
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
document.addEventListener("mousemove", mouseMoveHandler, false);
function keyDownHandler(e) {
if (e.keyCode == 39) {
rightPressed = true;
} else if (e.keyCode == 37) {
leftPressed = true;
}
}
function keyUpHandler(e) {
if (e.keyCode == 39) {
rightPressed = false;
} else if (e.keyCode == 37) {
leftPressed = false;
}
}
function mouseMoveHandler(e) {
var relativeX = e.clientX - canvas.offsetLeft;
if (relativeX > 0 && relativeX < canvas.width) {
paddleX = relativeX - paddleWidth / 2;
}
}
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 + 5 > b.x &&
x - 5 < b.x + brickWidth &&
y > b.y &&
y < b.y + brickHeight
) {
reward.value++;
reward.x = b.x;
reward.y = b.y;
// drawReward();
// drawReward(x, y);
ctx.font = "16px Arial";
ctx.fillStyle = "#50b848";
ctx.fillText("1GB", 8, 10);
dy = -dy;
b.status = 0;
score++;
if (score == brickRowCount * brickColumnCount) {
alert("YOU WIN, CONGRATS!");
document.location.reload();
}
}
}
}
}
}
function drawBall() {
// var img = document.getElementById("icon");
// var img = new Image();
// img.src = "/images/glo_icon.png";
// ctx.drawImage(img, x, y, 25, 25);
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = "#50b848";
ctx.fill();
ctx.closePath();
}
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
ctx.fillStyle = "#50b848";
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 = r * (brickWidth + brickPadding) + brickOffsetLeft;
var 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 = `#50b848`;
ctx.fill();
ctx.closePath();
}
}
}
}
// function drawReward() {
// // ctx.clearRect(reward.x, reward.y, 30, 30);
// ctx.font = "25px Arial";
// ctx.fillStyle = "#ffffff";
// ctx.fillText(reward.value + "GB", canvas.width / 2 - 5, 20);
// if (y >= 300) {
// y = 290; // Set the ball's Y position to the bottom of the canvas
// dy = 0; //And finally this set the falling is zero
// }
// }
function drawScore() {
ctx.font = "16px Arial";
ctx.fillStyle = "purple";
ctx.fillText("Score: " + score, 8, 20);
}
function drawLives() {
ctx.font = "16px Arial";
ctx.fillStyle = "red";
ctx.fillText("Lives: " + lives, canvas.width - 65, 20);
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBricks();
drawBall();
drawPaddle();
drawScore();
drawLives();
// drawReward();
collisionDetection();
if (x + dx > canvas.width - ballRadius || x + dx < -5) {
dx = -dx;
}
if (y + dy < -5) {
dy = -dy;
}
if (y + dy > canvas.height - ballRadius) {
if (x > paddleX - 10 && x < paddleX + paddleWidth + 10) {
dy = -dy;
} else {
dy = -dy;
lives--;
if (!lives) {
// alert("GAME OVER");
// document.location.reload();
} 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();
<canvas id="myCanvas"></canvas>
when a brick is hit, at text like "2X" should be drawn from that point and drop down to the bottom so the paddle can pick it up.
thanks for the assistance in advance
You need to be able to render multiple rewards; this is because several blocks may be hit within a short period of time, leading to several falling text items at once.
The only real trick here is to create an array of rewards, create another top-level rendering function named drawRewards (in the plural), and within that function, loop through all rewards in our rewards array, and render them. (Oh, and don't forget to actually add new rewards into the array whenever a block is hit!) I've modified your code to do all these things; let me know if this is what you were looking for:
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var ballRadius = 10;
var x = canvas.width / 2;
var y = canvas.height - 30;
var dx = 2;
var dy = -2;
var paddleHeight = 10;
var paddleWidth = 75;
var paddleX = (canvas.width - paddleWidth) / 2;
var rightPressed = false;
var leftPressed = false;
var brickRowCount = 4;
var brickColumnCount = 4;
var brickWidth = 50;
var brickHeight = 10;
var brickPadding = 15;
var brickOffsetTop = 30;
var brickOffsetLeft = 30;
var score = 0;
var lives = 3;
var reward = { value: 1, x: canvas.width / 2 - 5, y: 20 };
let rewards = [];
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 };
}
}
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
document.addEventListener("mousemove", mouseMoveHandler, false);
function keyDownHandler(e) {
if (e.keyCode == 39) {
rightPressed = true;
} else if (e.keyCode == 37) {
leftPressed = true;
}
}
function keyUpHandler(e) {
if (e.keyCode == 39) {
rightPressed = false;
} else if (e.keyCode == 37) {
leftPressed = false;
}
}
function mouseMoveHandler(e) {
var relativeX = e.clientX - canvas.offsetLeft;
if (relativeX > 0 && relativeX < canvas.width) {
paddleX = relativeX - paddleWidth / 2;
}
}
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 + 5 > b.x &&
x - 5 < b.x + brickWidth &&
y > b.y &&
y < b.y + brickHeight
) {
reward.value++;
reward.x = b.x;
reward.y = b.y;
rewards.push({ x: b.x, y: b.y, text: '1GB' });
dy = -dy;
b.status = 0;
score++;
if (score == brickRowCount * brickColumnCount) {
document.location.reload();
}
}
}
}
}
}
function drawBall() {
// var img = document.getElementById("icon");
// var img = new Image();
// img.src = "/images/glo_icon.png";
// ctx.drawImage(img, x, y, 25, 25);
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = "#50b848";
ctx.fill();
ctx.closePath();
}
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
ctx.fillStyle = "#50b848";
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 = r * (brickWidth + brickPadding) + brickOffsetLeft;
var 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 = `#50b848`;
ctx.fill();
ctx.closePath();
}
}
}
}
function drawRewards() {
for (let reward of rewards) {
reward.y = reward.y + 1;
ctx.font = "12px Arial";
ctx.fillStyle = "#000";
ctx.fillText(reward.text, reward.x, reward.y);
}
// Remove any rewards which fall out of view
rewards = rewards.filter(reward => reward.y < canvas.height);
}
function drawScore() {
ctx.font = "16px Arial";
ctx.fillStyle = "purple";
ctx.fillText("Score: " + score, 8, 20);
}
function drawLives() {
ctx.font = "16px Arial";
ctx.fillStyle = "red";
ctx.fillText("Lives: " + lives, canvas.width - 65, 20);
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBricks();
drawBall();
drawPaddle();
drawScore();
drawRewards();
drawLives();
// drawReward();
collisionDetection();
if (x + dx > canvas.width - ballRadius || x + dx < -5) {
dx = -dx;
}
if (y + dy < -5) {
dy = -dy;
}
if (y + dy > canvas.height - ballRadius) {
if (x > paddleX - 10 && x < paddleX + paddleWidth + 10) {
dy = -dy;
} else {
dy = -dy;
lives--;
if (!lives) {
// alert("GAME OVER");
// document.location.reload();
} 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();
<canvas id="myCanvas"></canvas>
Related
I made a game of atari breakout of where i want the bricks to be multi coloured. I want it so that each individual brick has its own random colour that is randomly generated. I also dont want the other attributes such as the ball and the paddle to be targeted with this random colour change.
Here are the lines of code:
'use strict';
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var ballRadius = 20;
var x = canvas.width/2;
var y = canvas.height-30;
var dx = 3;
var dy = -3;
var paddleHeight = 10;
var paddleWidth = 175;
var paddleX = (canvas.width-paddleWidth)/2;
var rightPressed = false;
var leftPressed = false;
var brickRowCount = 11;
var brickColumnCount = 5;
var brickWidth = 73;
var brickHeight = 20;
var brickPadding = 10;
var brickOffsetTop = 30;
var brickOffsetLeft = 30;
var score = 0;
var lives = 3;
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 };
}
}
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
document.addEventListener("mousemove", mouseMoveHandler, 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 mouseMoveHandler(e) {
var relativeX = e.clientX - canvas.offsetLeft;
if(relativeX > 0 && relativeX < canvas.width) {
paddleX = relativeX - paddleWidth/2;
}
}
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;
score++;
if(score == brickRowCount*brickColumnCount) {
alert("YOU WIN, CONGRATS!");
document.location.reload();
}
}
}
}
}
}
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
ctx.fill();
ctx.closePath();
}
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height-paddleHeight, paddleWidth, paddleHeight);
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 = (r*(brickWidth+brickPadding))+brickOffsetLeft;
var brickY = (c * (brickHeight + brickPadding)) + brickOffsetTop;
bricks[c][r].x = brickX;
bricks[c][r].y = brickY;
ctx.beginPath();
ctx.rect(brickX, brickY, brickWidth, brickHeight);
ctx.fill();
ctx.closePath();
}
}
}
}
function drawScore() {
ctx.font = "16px Arial";
ctx.fillText("Score: "+score, 8, 20);
}
function drawLives() {
ctx.font = "16px Arial";
ctx.fillText("Lives: "+lives, canvas.width-65, 20);
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBricks();
drawBall();
drawPaddle();
drawScore();
drawLives();
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 {
lives--;
if(!lives) {
alert("GAME OVER");
document.location.reload();
}
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);
}
function hardFunction(){
ballRadius = 8;
paddleWidth = 80;
lives = 1;
dx = 5;
dy = -5;
};
function mediumFunction(){
ballRadius = 15;
paddleWidth = 120;
lives = 2;
dx = 4;
dy = -4;
};
function easyFunction(){
ballRadius = 20;
paddleWidth = 175;
lives = 3;
dx = 3;
dy = -3;
};
draw();
console.log(ctx.fillStyle);
* {
padding: 0;
margin: 0;
}
canvas {
background: #eee;
display: block;
margin: 0 auto;
}
button {
border: none;
color: gray;
padding: 16px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px 0px 16.67%;
transition-duration: 0.4s;
cursor: pointer
}
.buttonHard:hover {
background-color: red;
color: black;
}
.buttonMedium:hover {
background-color: yellow;
color: black;
}
.buttonEasy:hover {
background-color: green;
color: black;
}
<canvas id="myCanvas" width="960" height="640"></canvas>
<button id="button" class="buttonHard" onclick="hardFunction();">Hard Mode</button>
<button id="button" class="buttonMedium" onclick="mediumFunction();">Medium Mode</button>
<button id="button" class="buttonEasy" onclick="easyFunction();">Easy Mode</button>
<script src="script.js"></script>
After the bricks are drawn reset the ctx.fillStyle back to black to not affect the paddle and ball color.
You can try it like this:
'use strict';
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var ballRadius = 20;
var x = canvas.width/2;
var y = canvas.height-30;
var dx = 3;
var dy = -3;
var paddleHeight = 10;
var paddleWidth = 175;
var paddleX = (canvas.width-paddleWidth)/2;
var rightPressed = false;
var leftPressed = false;
var brickRowCount = 11;
var brickColumnCount = 5;
var brickWidth = 73;
var brickHeight = 20;
var brickPadding = 10;
var brickOffsetTop = 30;
var brickOffsetLeft = 30;
var score = 0;
var lives = 3;
// colors picked from here: https://hightekk.com/tools/swatch
const colors = [
"#d1c4e9",
"#b39ddb",
"#9575cd",
"#7e57c2",
"#673ab7",
"#5e35b1",
"#512da8",
"#4527a0",
"#311b92",
"#b388ff",
"#7c4dff",
"#651fff",
"#6200ea",
];
function getRandomColor(){
return colors[Math.floor(Math.random() * colors.length)];
}
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, color: getRandomColor() };
}
}
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
document.addEventListener("mousemove", mouseMoveHandler, 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 mouseMoveHandler(e) {
var relativeX = e.clientX - canvas.offsetLeft;
if(relativeX > 0 && relativeX < canvas.width) {
paddleX = relativeX - paddleWidth/2;
}
}
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;
score++;
if(score == brickRowCount*brickColumnCount) {
alert("YOU WIN, CONGRATS!");
document.location.reload();
}
}
}
}
}
}
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
ctx.fill();
ctx.closePath();
}
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height-paddleHeight, paddleWidth, paddleHeight);
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 = (r*(brickWidth+brickPadding))+brickOffsetLeft;
var 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 = bricks[c][r].color;
ctx.fill();
ctx.closePath();
}
}
}
ctx.fillStyle = "#000000";
}
function drawScore() {
ctx.font = "16px Arial";
ctx.fillText("Score: "+score, 8, 20);
}
function drawLives() {
ctx.font = "16px Arial";
ctx.fillText("Lives: "+lives, canvas.width-65, 20);
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBricks();
drawBall();
drawPaddle();
drawScore();
drawLives();
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 {
lives--;
if(!lives) {
alert("GAME OVER");
document.location.reload();
}
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);
}
function hardFunction(){
ballRadius = 8;
paddleWidth = 80;
lives = 1;
dx = 5;
dy = -5;
};
function mediumFunction(){
ballRadius = 15;
paddleWidth = 120;
lives = 2;
dx = 4;
dy = -4;
};
function easyFunction(){
ballRadius = 20;
paddleWidth = 175;
lives = 3;
dx = 3;
dy = -3;
};
draw();
console.log(ctx.fillStyle);
* {
padding: 0;
margin: 0;
}
canvas {
background: #eee;
display: block;
margin: 0 auto;
}
button {
border: none;
color: gray;
padding: 16px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px 0px 16.67%;
transition-duration: 0.4s;
cursor: pointer
}
.buttonHard:hover {
background-color: red;
color: black;
}
.buttonMedium:hover {
background-color: yellow;
color: black;
}
.buttonEasy:hover {
background-color: green;
color: black;
}
<canvas id="myCanvas" width="960" height="640"></canvas>
<button id="button" class="buttonHard" onclick="hardFunction();">Hard Mode</button>
<button id="button" class="buttonMedium" onclick="mediumFunction();">Medium Mode</button>
<button id="button" class="buttonEasy" onclick="easyFunction();">Easy Mode</button>
<script src="script.js"></script>
Perhaps the desired result would also want to have some control over the randomized colors.
This basic example generate a random color in hsl with a randomized hue, but keep saturation and lightness the same at a set number.
If needed, further calculation based saturation and lightness can be added for coloring each brick with some patterns. The example includes a basic use of this by generating a gradient in lightness based on rows, but it is totally optional.
Example:
"use strict";
// 👇 Set a range for random color hue,
const minHue = 0;
const maxHue = 360;
// 👇 Set custom saturation and lightness
const saturation = 100;
const lightness = 50;
// 👇 Optional: set lightness as an array for a row gradient
const lightnessList = [30, 40, 50, 60, 70];
const randColor = (minHue, maxHue, saturation, lightness) =>
`hsl(${
minHue + Math.floor(Math.random() * (maxHue - minHue))
} ${saturation}% ${lightness}%)`;
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var ballRadius = 20;
var x = canvas.width / 2;
var y = canvas.height - 30;
var dx = 3;
var dy = -3;
var paddleHeight = 10;
var paddleWidth = 175;
var paddleX = (canvas.width - paddleWidth) / 2;
var rightPressed = false;
var leftPressed = false;
var brickRowCount = 11;
var brickColumnCount = 5;
var brickWidth = 73;
var brickHeight = 20;
var brickPadding = 10;
var brickOffsetTop = 30;
var brickOffsetLeft = 30;
var score = 0;
var lives = 3;
var bricks = [];
for (var c = 0; c < brickColumnCount; c++) {
bricks[c] = [];
// 👇 Optional: for using lightnessList
const lit = lightnessList?.[c] || lightness;
for (var r = 0; r < brickRowCount; r++) {
bricks[c][r] = {
x: 0,
y: 0,
status: 1,
color: randColor(minHue, maxHue, saturation, lit),
};
}
}
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
document.addEventListener("mousemove", mouseMoveHandler, 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 mouseMoveHandler(e) {
var relativeX = e.clientX - canvas.offsetLeft;
if (relativeX > 0 && relativeX < canvas.width) {
paddleX = relativeX - paddleWidth / 2;
}
}
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;
score++;
if (score == brickRowCount * brickColumnCount) {
alert("YOU WIN, CONGRATS!");
document.location.reload();
}
}
}
}
}
}
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
ctx.fill();
ctx.closePath();
}
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
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 = r * (brickWidth + brickPadding) + brickOffsetLeft;
var brickY = c * (brickHeight + brickPadding) + brickOffsetTop;
bricks[c][r].x = brickX;
bricks[c][r].y = brickY;
ctx.fillStyle = bricks[c][r]?.color || "#000";
ctx.beginPath();
ctx.rect(brickX, brickY, brickWidth, brickHeight);
ctx.fill();
ctx.closePath();
ctx.fillStyle = "#000";
}
}
}
}
function drawScore() {
ctx.font = "16px Arial";
ctx.fillText("Score: " + score, 8, 20);
}
function drawLives() {
ctx.font = "16px Arial";
ctx.fillText("Lives: " + lives, canvas.width - 65, 20);
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBricks();
drawBall();
drawPaddle();
drawScore();
drawLives();
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 {
lives--;
if (!lives) {
alert("GAME OVER");
document.location.reload();
} 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);
}
function hardFunction() {
ballRadius = 8;
paddleWidth = 80;
lives = 1;
dx = 5;
dy = -5;
}
function mediumFunction() {
ballRadius = 15;
paddleWidth = 120;
lives = 2;
dx = 4;
dy = -4;
}
function easyFunction() {
ballRadius = 20;
paddleWidth = 175;
lives = 3;
dx = 3;
dy = -3;
}
draw();
console.log(ctx.fillStyle);
* {
padding: 0;
margin: 0;
}
canvas {
background: #eee;
display: block;
margin: 0 auto;
}
button {
border: none;
color: gray;
padding: 16px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px 0px 16.67%;
transition-duration: 0.4s;
cursor: pointer;
}
.buttonHard:hover {
background-color: red;
color: black;
}
.buttonMedium:hover {
background-color: yellow;
color: black;
}
.buttonEasy:hover {
background-color: green;
color: black;
}
<canvas id="myCanvas" width="960" height="640"></canvas>
<button id="button" class="buttonHard" onclick="hardFunction();">Hard Mode</button>
<button id="button" class="buttonMedium" onclick="mediumFunction();">Medium Mode</button>
<button id="button" class="buttonEasy" onclick="easyFunction();">Easy Mode</button>
<script src="script.js"></script>
Hope this will help.
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 > b.x && x < b.x+brickWidth && y > b.y && 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
I am trying to code a Pause/Play button for my breakout-clone because I have some text and links planned for the site on which the game will be, so you can pause the game while reading the text or interacting with links. My code is written in JS and mostly consists of "function" and "var". If the CSS or the HTML file is needed for an answer then please contact me. This is my first time asking anything on stackoverflow and I would be glad for any help.
var canvas = document.getElementById("TheCanvas");
var ctx = canvas.getContext("2d");
var x = canvas.width/2;
var y = canvas.height-50;
var dx = 2
var dy = -2;
var ballRadius = 10;
var paddleHeight = 15;
var paddleWidth = 80;
var paddleX = (canvas.width-paddleWidth) / 2;
var rightPressed = false;
var leftPressed = false;
var brickRowCount = 6;
var brickColumnCount = 4;
var brickWidth = 90;
var brickHeight = 20;
var brickPadding = 10;
var brickOffsetTop = 30;
var brickOffsetLeft = 15;
var score = 0;
var lives = 99;
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 };
}
}
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
document.addEventListener("mousemove", mouseMoveHandler, false);
function mouseMoveHandler(e) {
var relativeX = e.clientX - canvas.offsetLeft;
if(relativeX > 0 && relativeX < canvas.width) {
paddleX = relativeX - paddleWidth/2;
}
}
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;
score++;
if(score == brickRowCount*brickColumnCount) {
alert("YOU WIN, WELL DONE!");
document.location.reload();
clearInterval(interval); // <- This is needed for the browser to end the game \\
}
}
}
}
}
}
function drawScore() {
ctx.font = "16px OCR A";
ctx.fillStyle = "#00ffd9"
ctx.fillText("Score: "+score, 8, 20);
}
function drawLives() {
ctx.font = "16px OCR A"
ctx.fillStyle = "00ffd9"
ctx.fillText("Lives: "+lives, canvas.width-85, 20);
}
function drawBall() {
// drawing code \\
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
ctx.lineWidth=3
ctx.strokeStyle = "#00ff00";
ctx.stroke();
ctx.closePath();
}
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height-15, paddleWidth, paddleHeight);
ctx.lineWidth=2
ctx.fillStyle = "#ff0000";
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.strokeStyle = "#33FFFF";
ctx.stroke();
ctx.closePath();
}
}
}
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBricks();
drawBall();
drawPaddle();
drawScore();
drawLives();
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 {
lives--;
if(!lives) {
alert("Game Over! Press 'Ok' to reload!");
document.location.reload();
clearInterval(interval); // Is needed for Browser to end the game \\
}
else {
x = canvas.width/2;
y = canvas.height-30
dx = 2;
dy = -2;
paddleX = (canvas.width-paddleWidth)/2;
}
}
}
if (rightPressed && paddleX < canvas.width - paddleWidth) {
paddleX += 3;
} else if (leftPressed && paddleX > 0) {
paddleX -= 3;
}
x += dx;
y += dy;
}
var interval = setInterval(draw, 9);
var checkbox = document.getElementById('darkmode');
function darkmode() {
if (checkbox.checked == true){
document.documentElement.style.setProperty('--primary-background', 'black');
document.documentElement.style.setProperty('--primary-color', 'white');
} else {
document.documentElement.style.setProperty('--primary-background', 'white');
document.documentElement.style.setProperty('--primary-color', 'black');
}
}
checkbox.addEventListener('click', darkmode);
darkmode();
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>
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!
I am creating a 2 player tennis sort of game right now in JavaScript and I got the ball to make an alert box popup saying "gameover" when it hits the top, but I can't seem to make it work on the top border. If someone could tell me what I'm doing wrong thanks in advance.
I have inputted the code for my game below:
var canvas = document.getElementById("gameCanvas");
var ctx = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height - 30;
var dx = 2;
var dy = -2;
var ballRadius = 10;
var paddleHeight = 10;
var paddleWidth = 75;
var paddle2Height = 10;
var paddle2Width = 75;
var paddleX = (canvas.width - paddleWidth) / 2;
var paddle2X = (canvas.width - paddleWidth) / 2;
var rightPressed = false;
var leftPressed = false;
var rightPressed2 = false;
var leftPressed2 = false;
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = "#0095DD"; //color of ball
ctx.fill();
ctx.closePath();
}
//Draws the bottom paddle
function drawPaddle1() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
ctx.fillStyle = "#0095DD"; //color of paddle
ctx.fill();
ctx.closePath();
}
//Draws the top paddle
function drawPaddle2() {
ctx.beginPath();
ctx.rect(paddle2X, 0, paddle2Width, paddle2Height);
ctx.fillStyle = "#0095DD"; //color of paddle
ctx.fill();
ctx.closePath();
}
function draw() {
//Checks collison for left and right
if (x + dx > canvas.width || x + dx < 0) {
dx = -dx;
}
//Paddle collison for top and down "still fixing"
if (y + dy < ballRadius || y + dy < 0) {
dy = -dy;
} else if (y + dy > canvas.height - ballRadius) {
if (x > paddleX && x < paddleX + paddleWidth) {
dy = -dy;
} else {
alert("GAME OVER");
document.location.reload();
}
}
//Clears canvas so the ball won't leave a trail
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall(); //Draws the ball
//Draws the paddle
drawPaddle1();
drawPaddle2();
//Makes the ball move
x += dx;
y += dy;
//Moves the paddle
if (rightPressed && paddleX < canvas.width - paddleWidth) {
paddleX += 7;
} else if (leftPressed && paddleX > 0) {
paddleX -= 7;
} else if (rightPressed2 && paddle2X < canvas.width - paddleWidth) {
paddle2X += 7;
} else if (leftPressed2 && paddle2X > 0) {
paddle2X -= 7;
}
}
//Handles the keyboard commands
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function keyDownHandler(e) {
if (e.keyCode == 39) {
rightPressed = true;
} else if (e.keyCode == 68) {
rightPressed2 = true;
} else if (e.keyCode == 37) {
leftPressed = true;
} else if (e.keyCode == 65) {
leftPressed2 = true;
}
}
function keyUpHandler(e) {
if (e.keyCode == 39) {
rightPressed = false;
} else if (e.keyCode == 68) {
rightPressed2 = false;
} else if (e.keyCode == 37) {
leftPressed = false;
} else if (e.keyCode == 65) {
leftPressed2 = false;
}
}
//Refreshes screen every 10 seconds
setInterval(draw, 10);
* {
padding: 0;
margin: 0;
}
canvas {
background: #eee;
display: block;
margin: 0 auto;
}
<canvas id="gameCanvas" width="480" height="320"></canvas>
You are missing a block for paddle2.
//Paddle collison for top and down "still fixing"
if (y + dy < ballRadius || y + dy < 0) {
if (x > paddle2X && x < paddle2X + paddleWidth) {
dy = -dy;
} else {
alert("GAME OVER");
document.location.reload();
}
} else if (y + dy > canvas.height - ballRadius) {
if (x > paddleX && x < paddleX + paddleWidth) {
dy = -dy;
} else {
alert("GAME OVER");
document.location.reload();
}
}
Your game is cool. I just want to complete it.
JSfiddle
var canvas = document.getElementById("gameCanvas");
var ctx = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height - 30;
var dx = 2;
var dy = -2;
var ballRadius = 10;
var paddleHeight = 10;
var paddleWidth = 75;
var paddle2Height = 10;
var paddle2Width = 75;
var paddleX = (canvas.width - paddleWidth) / 2;
var paddle2X = (canvas.width - paddleWidth) / 2;
var rightPressed = false;
var leftPressed = false;
var rightPressed2 = false;
var leftPressed2 = false;
var isStart = false;
var interval;
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = "#0095DD"; //color of ball
ctx.fill();
ctx.closePath();
}
//Draws the bottom paddle
function drawPaddle1() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
ctx.fillStyle = "#0095DD"; //color of paddle
ctx.fill();
ctx.closePath();
}
//Draws the top paddle
function drawPaddle2() {
ctx.beginPath();
ctx.rect(paddle2X, 0, paddle2Width, paddle2Height);
ctx.fillStyle = "#0095DD"; //color of paddle
ctx.fill();
ctx.closePath();
}
function draw() {
//Checks collison for left and right
if (x + dx > canvas.width || x + dx < 0) {
dx = -dx;
}
//Paddle collison for top and down "still fixing"
if (y + dy < ballRadius) {
console.log("touch border top - Game over");
start();
}
if (y + dy >= ballRadius && y + dy <= ballRadius + paddle2Height && x > paddle2X && x < paddle2X + paddleWidth) {
console.log("touch paddle top");
dy = -dy;
}
if (y + dy > canvas.height - ballRadius) {
if (x > paddleX && x < paddleX + paddleWidth) {
console.log("touch paddle bot");
dy = -dy;
} else {
console.log("touch border bot - Game over");
start();
}
}
//Clears canvas so the ball won't leave a trail
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall(); //Draws the ball
//Draws the paddle
drawPaddle1();
drawPaddle2();
//Makes the ball move
x += dx;
y += dy;
//Moves the paddle
if (rightPressed && paddleX < canvas.width - paddleWidth) {
paddleX += 7;
};
if (leftPressed && paddleX > 0) {
paddleX -= 7;
};
if (rightPressed2 && paddle2X < canvas.width - paddleWidth) {
paddle2X += 7;
};
if (leftPressed2 && paddle2X > 0) {
paddle2X -= 7;
}
}
//Handles the keyboard commands
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
document.getElementById("start-button").addEventListener("click", start);
function keyDownHandler(e) {
if (e.keyCode == 39) {
rightPressed = true;
};
if (e.keyCode == 68) {
rightPressed2 = true;
};
if (e.keyCode == 37) {
leftPressed = true;
};
if (e.keyCode == 65) {
leftPressed2 = true;
}
}
function keyUpHandler(e) {
if (e.keyCode == 39) {
rightPressed = false;
};
if (e.keyCode == 68) {
rightPressed2 = false;
};
if (e.keyCode == 37) {
leftPressed = false;
};
if (e.keyCode == 65) {
leftPressed2 = false;
}
}
function start() {
isStart = !isStart;
if (isStart) {
x = canvas.width / 2;
y = canvas.height - 30;
paddleX = (canvas.width - paddleWidth) / 2;
paddle2X = (canvas.width - paddleWidth) / 2;
//Refreshes screen every 10 seconds
interval = setInterval(draw, 10);
} else
clearInterval(interval);
}
* {
padding: 0;
margin: 0;
}
canvas {
background: #eee;
display: block;
margin: 0 auto;
}
button {
display: block;
margin: 10px auto;
padding: 10px;
}
<canvas id="gameCanvas" width="480" height="320"></canvas>
<button id="start-button">Start/Pause</button>