KevinN KevinN - 7 months ago 21
Javascript Question

Collision detection between bricks and ball (working with an array of numbers)

I want to detect a collision between my ball and my bricks with an array made of numbers. It works but not completely.

If you look at my code, you see an array made of numbers from 0 to 5. 0 means that there is no brick detected and the rest is made of a color. The problem is that my function only detects a collision with the color 1 (black) but not the rest. What is the problem?

var canvas = document.getElementById("mijnCanvas");
var mijnObject = canvas.getContext("2d");

var afbeelding = new Image();
var balkX = (canvas.width/2)-50;
var balkY = canvas.height-40;

var balX = canvas.width/2;
var balY = canvas.height-50;
var radius = 8;
var balNaarX = 5;
var balNaarY = 5;

function makenBalkKort() {
mijnObject.drawImage(afbeelding, balkX, balkY, afbeelding.width, afbeelding.height);
}
afbeelding.src = "Afbeeldingen/BrickSmasher_Balk_Kort.png";

function makenBal() {
mijnObject.beginPath();
var mijnBalGradient = mijnObject.createRadialGradient(balX, balY, 0, balX, balY, 6);
mijnBalGradient.addColorStop(0, "#000000");
mijnBalGradient.addColorStop(1, "#FFFFFF");
mijnObject.fillStyle = mijnBalGradient;
mijnObject.strokeStyle = "#000000";
mijnObject.arc(balX, balY, radius, 0, 2*Math.PI, false);
mijnObject.fill();
mijnObject.stroke();
mijnObject.closePath();
}

function tekenenObjecten() {
mijnObject.clearRect(0, 0, canvas.width, canvas.height);
makenBalkKort();
makenBal();
makenMuur();
collisieMetStenenX();

setTimeout(function() {
if(balX+balNaarX < radius || balX+balNaarX > canvas.width-radius) {
balNaarX = -balNaarX;
}

if(balY+balNaarY < radius) {
balNaarY = -balNaarY;
}

if(balY+balNaarY > balkY-radius) {
if(balX+balNaarX >= balkX && balX+balNaarX <= balkX+afbeelding.width) {
balNaarY = -balNaarY;
}
else {
alert("Game over");
document.location.reload();
}
}
balX += balNaarX;
balY += balNaarY;
}, 1000);
}
setInterval(tekenenObjecten, 20);

window.addEventListener("keydown", function LinksOfRechts() {
mijnObject.clearRect(balkX, balkY, canvas.width, canvas.height);
var balkNaarX = 10;
var code = event.which || event.keyCode;
if(code == 37) {
if(balkX > 0) {
balkX -= balkNaarX;
}
}
else if(code == 39) {
if(balkX < canvas.width-afbeelding.width) {
balkX += balkNaarX;
}
}
mijnObject.drawImage(afbeelding, balkX, balkY, afbeelding.width, afbeelding.height);
});

canvas.addEventListener("click", function balkLangMaken() {
mijnObject.clearRect(balkX, balkY, canvas.width, canvas.height);
afbeelding.src = "Afbeeldingen/BrickSmasher_Balk_Lang.png";
setTimeout(function() {
mijnObject.clearRect(balkX, balkY, canvas.width, canvas.height);
afbeelding.src = "Afbeeldingen/BrickSmasher_Balk_Kort.png";
}, 3000);
});

var stenenPerRij = 27;
var steenHoogte = 20;
var steenBreedte = canvas.width/stenenPerRij;

var stenen = [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,1,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,1,0],
[0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,1,1,0,0,2,2,2,2,0,0,0,0,0,0,1,0,1,4,4,4,0,1,0,0,0,1],
[1,0,0,1,0,2,0,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,1,1,0,0,1],
[1,1,1,1,0,2,2,2,2,0,0,0,0,0,0,1,0,1,4,4,0,0,1,0,1,0,1],
[1,0,0,1,0,2,0,2,0,0,0,1,0,0,0,1,0,1,0,0,0,0,1,0,0,1,1],
[1,0,0,1,0,2,0,0,2,2,0,0,1,1,1,0,0,1,4,4,4,0,1,0,0,0,1],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
];

function makenMuur() {
for(var i = 0; i < stenen.length; i = i+1) {
for(var j = 0; j < stenen[i].length; j = j+1) {
tekenenStenen(j,i,stenen[i][j]);
}
}
}

function tekenenStenen(x,y,stenen) {
switch(stenen) {
case 1:
mijnObject.fillStyle = "#0d0d0d";
break;
case 2:
mijnObject.fillStyle = "#333333";
break;
case 3:
mijnObject.fillStyle = "#595959";
break;
case 4:
mijnObject.fillStyle = "#808080";
break;
case 5:
mijnObject.fillStyle = "#a6a6a6";
break;
default:
mijnObject.clearRect(0, 0, steenBreedte, steenHoogte);
break;
}
if(stenen) {
mijnObject.beginPath();
mijnObject.strokeStyle = "#000000";
mijnObject.rect(x*steenBreedte, y*steenHoogte, steenBreedte, steenHoogte);
mijnObject.fill();
mijnObject.stroke();
mijnObject.closePath();
}
}

function collisieMetStenenX() {
for(var i = 0; i < stenen.length; i = i+1) {
for(var j = 0; j < stenen[i].length; j = j+1) {
if(stenen[i][j] == true) {
var steenX = j*steenBreedte;
var steenY = i*steenHoogte;
if((balX+balNaarX > steenX && balX+balNaarX < steenX+steenBreedte)
&& (balY+balNaarY > steenY && balY+balNaarY < steenY+steenHoogte)) {
balNaarY = -balNaarY;
}
}
}
}
}


Here is my HTML-code:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>BrickSmasher</title>
<style>
canvas {
position: relative;
margin-left: auto;
margin-right: auto;
display: block;
}
</style>
</head>

<body>
<canvas id="mijnCanvas" width="1200" height="600" style="border: 1px solid black"></canvas>
<script src="BrickSmasher.js"></script>
</body>
</html>

Answer

Replace this line:

 if(stenen[i][j] == true) {

with:

 if(stenen[i][j] > 0) {

or simply:

 if(stenen[i][j]) {

The reason is that when you compare with true, JavaScript needs to do a conversion. The left side of the equation is numeric, so the right side is converted to the numeric equivalent of true, which is 1. That means there is no equality when the left side is 2, 3, ...

The last alternative works, because there the conversion is in the opposite sense: an if condition needs to resolve to a boolean value. So the numerical value is converted to boolean. And there any non-zero value will convert to true.

Comments