Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Tsenko Aleksiev
3,819 PointsLittle help explaining me closures in js anyone... I suck a bit in math
Hi! This is something I've learned from a different site, but I don't want to make it look like a commercial. Because the html part is really small, I did it in one file:
<html>
<head>
<title></title>
<style type="text/css">
canvas {
border: 1px solid black;
width: 100%;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="640" height="360"></canvas>
<script type="text/javascript">
window.addEventListener('load', function(){
//constants
var GAME_WIDTH = 640;
var GAME_HEIGHT = 360;
//enemies array
var enemies = [
{
x: 100,
y: 100,
speedY: 1,
w: 40,
h: 40
},
{
x: 260,
y: 100,
speedY: 3,
w: 40,
h: 40
},
{
x: 380,
y: 100,
speedY: 5,
w: 40,
h: 40
},
{
x: 480,
y: 100,
speedY: 7,
w: 40,
h: 40
}
];
//player
var player = {
x: 10,
y: 160,
speedX: 2,
w: 40,
h: 40,
isMoving: false
};
//make the player move
var movePlayer = function(){
player.isMoving = true;
};
//make the player stop
var stopPlayer = function(){
player.isMoving = false;
};
//get the canvas and the context
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
//event listeners to move player
canvas.addEventListener("mousedown", movePlayer);
canvas.addEventListener("mouseup", stopPlayer);
//update
var update = function(){
//update player
if(player.isMoving){
player.x += player.speedX;
};
//update enemies
enemies.forEach(function(element){
element.y += element.speedY;
//check borders
if(element.y <= 0){
element.y = 0;
element.speedY *= -1;
}else if(element.y >= GAME_HEIGHT - 40){
element.y = GAME_HEIGHT - 40;
element.speedY *= -1;
};
});
};
//draw
var draw = function(){
//clear the canvas
ctx.clearRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
//draw player
ctx.fillStyle = "green";
ctx.fillRect(player.x, player.y, player.w, player.h);
//draw enemies
ctx.fillStyle = "blue";
enemies.forEach(function(element){
ctx.fillRect(element.x, element.y, element.w, element.h);
});
};
// check collision
var collision = false;
var checkCollision = function(obj1, obj2){
if((obj1.x + obj1.w <= obj2.x) || (obj1.y + obj1.h <= obj2.y)){
collision = true; //game over
console.log(collision);
}
};
//step up
var step = function(){
update();
draw();
for(var i = 0; i < enemies.length; i++){
checkCollision(player, enemies[i]);
};
window.requestAnimationFrame(step);
};
step();
});
</script>
</body>
</html>
Now, I know that if we start from top left corner of the canvas and the player object starts from position x and y, let's say 10 and 160, it has something to do with the fact that if the width of the player is 40 and it's height is also 40, if the enemy objects hits players x + 40 and y + 40 on the coordinate system, than I have a collision aka if enemy hits x = 50 and y = 200. But tell me how to get it working inside a let's call it checkCollision function?? Can someone give me a hint how to do it, because with my code it doesn't work as I think it should and I'm a bit stuck...for the last week or something no ideas at all. In my head it works but not in the browser. I haven't added the goal yet because I know that if I get it working for the enemies, I'll do it for the goal as well. My code keeps hitting "true" on the console and I know I'm doing something wrong with the math, because it gives me that result even if I don't move the player at all ... :( Any ideas? Thanks a lot!!!
1 Answer
Steven Parker
243,186 PointsTry this:
var checkCollision = (obj1, obj2) => {
if(!(obj1.x + obj1.w < obj2.x || obj1.x > obj2.x + obj2.w ||
obj1.y + obj1.h < obj2.y || obj1.y > obj2.y + obj2.h)) {
collision = true; //game over
}
};
Also, I didn't calculate it, but I suspect it's not possible to get past the last block given the current speeds.
Tsenko Aleksiev
3,819 PointsTsenko Aleksiev
3,819 PointsCan you please explain to me, is the logic I thought about the collision right? I just woke up and I haven’t tried it yet but I can’t fully understand your code. I mean the “!” part, why reversing the result? May be I’m still sleeping :) Thank for your time, Steven! EDITED: it's not working @Steven Parker, I tried it and I'm not getting true in the console. Maybe my check in the step up function is wrong? I haven't thought about the speed of the player honestly, I think I did beat the game once, but with not working closures I can't be sure :) Probably you are right, I'll fix the player's speed.
Steven Parker
243,186 PointsSteven Parker
243,186 PointsIt's easier to test if there is no collision. There are 4 parts to the test: obj1 is left of obj2, obj1 is right of obj2, obj1 is above obj2 and obj1 is below obj2. These are all combined with OR operations since any of them means no collision. Finally, the NOT operator (!) is placed in front to switch the result to true when there is a collision.
My version has no console.log statement, but if you put it back in, you will see "true" (over and over) when a collision occurs. You could also do this to stop all motion on a collision:
Steven Parker
243,186 PointsSteven Parker
243,186 PointsTsenko Aleksiev — so did you get it working?