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

JavaScript

Little 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
Steven Parker
243,186 Points

Try 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.

Can 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
Steven Parker
243,186 Points

It'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:

         if (!collision)  // continue moving only if no collision
             window.requestAnimationFrame(step);