Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
pawelza

Collision detection

Go to solution Solved by Carl,

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hi forum!

 

I've got a 2 part question:

 

Question 1

 

I've forked a copepen sample that I found in the forums and I'm trying to figure our how to use collision detection to get the colorful balls to update the background color of the white balls as they cross over them.

 

I'd like to have the changes be incremental rather than change absolutely i.e. #FFFFFF becomes #AAFFFF rather than #00FFFF if that makes sense.

 

Question 2

 

Maybe this will become obvious once the collision detection question is answered but I'd also want the white balls to "swallow" the colorful balls as they cross paths. Are there any existing elegant ways to achieving this?

See the Pen JRjKLv by anon (@anon) on CodePen

Link to comment
Share on other sites

Hello and welcome to the GreenSock Forum!

 

You might want to look into Draggable.hitTest() to detect collision.

 

http://greensock.com/docs/#/HTML5/GSAP/Utils/Draggable/hitTest/

http://greensock.com/docs/#/HTML5/GSAP/Utils/Draggable/hitTest/

 

codepen examples of use:

 

See the Pen ZOayGO by GreenSock (@GreenSock) on CodePen

 

See the Pen GFBvn by GreenSock (@GreenSock) on CodePen


 

//simple overlap test
if (Draggable.hitTest(element1, element2)) {
   //do stuff
}
 
//test if element1 and element2 have at least 20 pixels of overlap:
if (Draggable.hitTest(element1, element2, 20)) {
   //do stuff
}
 
//test if at least 50% of the surface area of element1 and element2 overlaps:
if (Draggable.hitTest(element1, element2, "50%")) {
   //do stuff
}
 
//test if a mouse event's position (pageX/pageY) overlaps with element1:
if (Draggable.hitTest(element1, mouseEvent)) {
    //do stuff
}

:)

  • Like 4
Link to comment
Share on other sites

Hey Jonathan, thanks for the reply.

 

I'm guessing I need to do something like the following:

See the Pen QKWNBP by anon (@anon) on CodePen

 

Although I think I'm messing up inside of the `Draggable.create` function by passing through a collection instead of a single object because my console log isn't firing.

 

Although I've tried looping through but that doesn't work and nearly crashes the browser:

See the Pen ZpEWPQ by anon (@anon) on CodePen

Link to comment
Share on other sites

You dont really need to setup a Draggable create() to use hitTest(). Just a s long as your including GSAP Draggable in your page so you can use the hitTest() method.

 

The way you have it setup now you would have to initiate a drag of the element to use hitTest(). You can see that in this example how there is no setup of Draggable.create() instance since you are only wanting to do a hitTest() against 2 elements.

 

See the Pen ZOayGO by GreenSock (@GreenSock) on CodePen

 

Notice how in the above example that the to() tween has a onUpdate callback that is calling checkHit function on each onUpdate so it can run the hitTest() check.

 

Draggable.hitTest() accepts 2 parameters:

 

http://greensock.com/docs/#/HTML5/GSAP/Utils/Draggable/hitTest/

Draggable.hitTest( testObject1:Object, testObject2:Object, threshold:* ) : Boolean
  • Draggable.hitTest
    Provides an easy way to test two elements (or an element and a mouse/touch event's position) to determine whether or not they overlap according to whatever threshold you [optionally] define.

Hope this helps :)

  • Like 2
Link to comment
Share on other sites

Figured out that the function called with onUpdate in the TimelineMax to() method shouldn't pass any arguments. So instead it just runs a checkHit() function.

The thing that's tripping me up now is the function itself.

 

var audienceBubbles = $(".audienceBubble");
var msgBubbles = $(".msgBubble");

audienceBubbles.each(function(audienceBubble) {
  msgBubbles.each(function(msgBubble) {
    if (Draggable.hitTest($(msgBubble), $(audienceBubble))) {
      $(msgBubble).addClass("highlight");
    } else {
      $(msgBubble).removeClass("highlight");
    }
  });
});

 

 

Any idea why the above would throw a M(...) is null error?

 

New codepen is at:

See the Pen JRjKLv by anon (@anon) on CodePen

Link to comment
Share on other sites

I believe that is happening due to the way you are doing your jQuery each() loop.

 

jQuery each() has 2 arguments in its function index, element

 

So each() should look like this

jQuery(".elements-your-targeting").each(function(index,element){

       console.log("index is: "+ index);
       console.log(element);
});

You only had one argument in your each function. So Draggable was throwing an error since technically you were passing the index into Draggable but not the element which is the second argument for jQuery each()

 

More info on jQuery each() method

 

https://api.jquery.com/each/

 

:)

  • Like 1
Link to comment
Share on other sites

  • Solution

yup, Jonathan is exactly right about the each() error. Also it appears you were running checkHit on the update of every tween that was moving a msgBubble.

 

I set it up so TweenLite's ticker fires a tick event to fire that function once per tick that checks every audience thing to see if it is hitting a message.

 

I got you a little closer by being able to turn the moving dots yellow when they hit a white circle:

 

http://codepen.io/GreenSock/pen/gwOgRy?editors=0010

 

I didn't have time to work out how to remove the highlight class. This is a little more tricky because you only want to remove the highlight class from an element if it already has the class of highlight. If you remove the class of highlight from EVERY thing that doesn't has a class of highlight it really chokes the processor.

 

I tried quickly with a hasClass() test but even that was  a little strange and I ran out of time

  • Like 3
Link to comment
Share on other sites

Very cool Carl, Thanks :)

  • Like 2
Link to comment
Share on other sites

Here's a simple way to do collision detection against circles...

See the Pen YXpdYN?editors=0010 by osublake (@osublake) on CodePen

 

And here's everything you need to know about simple collision detection.

 

  • Like 5
Link to comment
Share on other sites

Here's that working in your example. When a message ball hits an audience ball, it's going to cause a color shift by subtracting 85 from whatever RGB color channel the ball is. When an audience ball has an RGB value of 0,0,0 (black), it dies off and respawns somewhere else.

 

See the Pen b0923ff7b69cf46d4397335a8bfa650c by osublake (@osublake) on CodePen

  • Like 4
Link to comment
Share on other sites

Wow what great responses.

Jonathan - oh my goodness you're right. I noticed last night when I changed those each() calls to a regular for loop. What a silly oversight

Carl thanks! I didn't know about adding event listeners to TweenLite.ticker - that's waaaaay saner than my approach

Thanks OSUblake, great resources. Love your codepen example as well - working through that now.

  • Like 1
Link to comment
Share on other sites

  • 2 months later...

Thanks guys, I figured how to make a collision detection work because of this topic.

 

I am making a simple game to catch objects and so I need a counter. The problem is that checkHit function which runs onUpdate generates huge numbers.

 

Maybe you have a solution how could I track a score?
 

function checkHit() {
    for (var i = 0; i < cans; i++) {
        var selectCan = document.getElementsByClassName("small-can");
          if (Draggable.hitTest(trolley, selectCan, "80%") ) {
            TweenMax.set(selectCan, {autoAlpha: 0});
            TweenMax.killTweensOf(selectCan);
              if (caughtCans < 5) {
                 counter.textContent = parseInt(counter.textContent) + 1;
                 caughtCans++;
              }
        }
    }
}

 

Link to comment
Share on other sites

I found the solution. I had to get rid of for loop and pass onUpdateParam to this function. Then save it in selectCan var.

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×