0

After getting advice to use this "style" of collision detection instead of jQuery Collision -

function isCollide(a, b) {
    return !(
        ((a.y + a.height) < (b.y)) ||
        (a.y > (b.y + b.height)) ||
        ((a.x + a.width) < b.x) ||
        (a.x > (b.x + b.width))
    );
}

I am trying it but am having an issue: the "else" part that is suppose to happen when the collision occurs is happening instantaneously for some reason, as soon as the page is loaded.

Here is the Fiddle.

And here is the function:

function homePage() {

    //initial animation
    for (var i=0; i<links.length; i++) {
        //animate links
        $(links[i]).animate({
            top: '0'
        }, {
            duration: 2000*(Math.random()*(1.1)+1), 
            easing: 'easeOutBounce',
            step: function() {

                if ($(links[i]).x > ($(".footer").x + $(".footer").width) 
                || $(links[i]).y > ($(".footer").y + $(".footer").height) 
                || ($(links[i]).x + $(links[i]).width) < $(".footer").x 
                || ($(links[i]).y + $(links[i]).height) < $(".footer").y)
                {
                    $(links[i]).css("background-color", "yellow");
                } 
                else 
                {
                    $(links[i]).css("background-color", "red");
                }
            }
        })
    }
}
AstroCB
  • 12,337
  • 20
  • 57
  • 73
Terf
  • 51
  • 8

1 Answers1

0

I saw these mistakes:

  1. When the step function is called, i equals links.length. Read How do JavaScript closures work? to understand more about this error. An easy solution is to use Array.forEach (or $.each): FIDDLE

    links.forEach(function(linkId){
        var $link = $(linkId);
        //...
    });
    
  2. There are no .x nor .y on a jquery object, use .offset().left and .offset().top instead: FIDDLE

    if ($link.offset().left > ($(".footer").offset().left + $(".footer").width) //...
    
  3. On a jquery object, width and height are functions: FIDDLE

    if ($link.offset().left > ($(".footer").offset().left + $(".footer").width()) //...
    

That should be enough to fix your code. Also try to use more variables, that will clean your code and help you find bugs.


These three mistakes were making the condition to always equal false:

  1. i was equal to links.length, so links[i] was undefined and $(links[i]) was an empty jQuery object. You can't find the position and the size of an empty jQuery object (and that's not what you want, you want the position and the size of the DIV)
  2. $link.x and $link.y are undefined, so you're comparing undefined values where you want to compare position values.
  3. .width and .height are functions, not the real size. Again, you're comparing streange meaningless values instead of comparing the bottom-right position values.
Volune
  • 4,324
  • 22
  • 23
  • Cheers mate. Could you go into a bit more detail, in simple terms, as to *why* the "else" statement was occurring instantaneously? I'm reading http://stackoverflow.com/questions/111102/how-do-javascript-closures-work but it's hard to understand. Was the fact that "i equals links.length" causing the entire array to change all at once? – Terf Aug 21 '14 at 22:28
  • @Terf I added some explanations, please tell me if you need some point to be more clarified. – Volune Aug 21 '14 at 22:38
  • Good stuff, thanks. A few questions, if you can help: **1)** Why would the step function run the "else" part of the statement (causing the divs to become red) if "$(links[i])" was undefined? **2)** I'm tryin to understand why I could use "$(links[i])" for ".animate" (there it wasn't undefined, right? Animation occurs), but using it in the "step" function within ".animate" caused it to be undefined. Is there a problem because it was already used once at the beginning to define which array item to animate, and using it afterwards *within* ".animate" caused some form of "confusion" (if you will)? – Terf Aug 21 '14 at 22:58
  • **3)** How would I go about making any CSS changes permanent, such as if a collision occurs once but the background colors stay the same even though the collision does not continue? – Terf Aug 21 '14 at 23:00
  • Just remove the line that makes it back to the previous color: turn `if condition then yellow else red` to `if (not condition) then red`. If you want to use CSS, add a class with jquery `$link.addClass('collided')`. [example](http://jsfiddle.net/4xpyzujb/5/) – Volune Aug 21 '14 at 23:08
  • Hey, I dunno if you still get notifications for this, but why am I not able to use "this" in place of "linkId"? Isn't "this" essentially what the argument is? MDN claims it is the "Value to use as 'this' when executing callback" – Terf Aug 27 '14 at 15:14
  • I guess you actually can use `this`, why not ? – Volune Aug 27 '14 at 16:15
  • Chrome gives me the error "Uncaught SyntaxError: Unexpected token this" when using this text (whereas using, say, "n" instead of "this" goes fine): links.forEach(function(this){ var footer2 = $(".footer2"); var link = $(this); – Terf Aug 27 '14 at 17:27
  • `function(this)` here you're naming an argument _this_, which is forbidden in javascript. Using _this_ to access the value works only with the jQuery `.each` functions [1](http://api.jquery.com/each/)[2](http://api.jquery.com/jquery.each/). For example: `$.each(links, function(){/*..*/ var link = $(this);` – Volune Aug 27 '14 at 19:56
  • Interesting, okay. Different subject if that's okay - I'm probably just stating the obvious, but would like some confirmation as for the longest time this confused me: arguments used in "pre-packaged" functions (like forEach, animate, step, etc.) automatically "know" what they refer back to (like the "n" in "links.forEach(function(n)" refers to "this", right?), whereas arguments in "user-created" functions need to be told what they refer to, correct? (Like, "y" in function "burritoMan(y) { alert(y);}" would have to be told what it is by the user, like "burritoMan('Spicy burritos for sale!');") – Terf Aug 27 '14 at 22:07
  • Not correct. What `n`, `this`, `y` refer to depends on how the function is called. When the function is called by a code function (Array.forEach) or by a library (jQuery.each), you have to look in the documentation to know what the arguments/this refers to. (For example, [jQuery.each](http://api.jquery.com/jquery.each/) says _The value can also be accessed through the this keyword_). When you call the function yourself, like `burritoMan('Foo');`, you know what it refers to. You should also have a look at [this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this). – Volune Aug 28 '14 at 08:04
  • Okay, but for the "n" in "links.forEach(function(n))", because it is a code function, *it* automatically knows that "n" refers to "this" (since it is pre-programmed to look for and recognize an argument variable), even if the user doesn't know without looking up the documentation. Whereas if the user creates his own function, "function burritoMan(n)", he has to create what "n" means in this case. Correct? (Sorry, I'm not great at explaining myself.) – Terf Aug 28 '14 at 16:04