Game Development Community

Sticky collision... bug?

by Tom Spilman · in Torque Game Builder · 07/24/2006 (5:14 pm) · 36 replies

So this is what is happening...


www.sickheadgames.com/stuff/collisionbug_t.png
(click for larger version)

1. In the first frame you can see that the player is away from the wall... no collision.

2. The second frame i'm running into the wall... my velocity is low, but the player collision poly is clearly penetrating the wall.

3. When i release the control stick the player is pushed out of the wall... but it seems not completely. If i set a breakpoint in t2dPhysics::resolveForwardCollision() it hits... so i'm still penetrating the wall even with zero velocity. I would have expected to be fully pushed out.

4. So when i decide to run away from the wall... no matter how long i hold down the run left button i stick to the wall. I suspect this is because i'm still penetrating the wall.

My collision settings on the player are:

%player.setCollisionPolyCustom( 4, "-0.4 0.2", "0 -0.1", "0.4 0.2", "0 0.5" );
   %player.setCollisionActive( true, true );
   %player.setCollisionPhysics( true, true );
   %player.setCollisionResponse( CLAMP );
   %player.setCollisionCallback( true );
   %player.setCollisionMaxIterations( 3 );

And the collision settings on the wall are:

new t2dStaticSprite() {
      imageMap = "stonewalls_map";
      position = "241.865 357.879";
      size = "4.690 20.500";
      Layer = "10";
      CollisionActiveSend = "1";
      CollisionPhysicsSend = "0";
      CollisionPhysicsReceive = "0";
      CollisionPolyList = "0.988 -0.245 0.915 0.989 -0.952 0.994 -1.000 -0.245";
      mountID = "4";
   };

So is this a bug or something i'm doing wrong? It seems like you should never get penetration in the collision and especially not at low speeds.

About the author

Tom is a programmer and co-owner of Sickhead Games, LLC.

Page «Previous 1 2
#1
07/25/2006 (2:54 pm)
What version are you using ?
#2
07/25/2006 (2:59 pm)
I'm using the TGB 1.1 release.

Thinking about this issue further it seems to me, and i'm in no way an expert in this area, that t2dPhysics::findMinimumSeperation() isn't calculating a sufficient penetration depth to push the player out of the wall when it penetrates. I'm not familiar with the algorithm used, but i suspect it may be related to the fact that the penetration is on the point of that diamond shaped collision poly.

Still investigating... but i could use some help. :)
#3
07/25/2006 (3:14 pm)
Ok... penetration and sticking occurs even with simple rectangular shapes.

www.sickheadgames.com/stuff/boxpen.png

There goes my theory.... but this should be simpler to debug.
#4
07/25/2006 (3:30 pm)
Ok progress.... if i set the player collision response to STICKY the collision polys do not visually penetrate and i do not get hung up on the wall when i try to walk away. So the problem seems to be in how the CLAMP response mode works.

STICKY just called setAtRest() on the dst/src shape to stop its movement.

CLAMP clamps the velocity of the object so that it can slide along the surface. My guess now is that it is doing that part incorrectly.

More debugging to do...
#5
07/25/2006 (3:46 pm)
Fixed!

This was a silly bug in t2dPhysics::resolveClampCollision() which is probably screwing up a lot of people's stuff.

Change both instances of...

// Any velocity to clamp?
        if ( dotVelocityNormal < 0.0f )
        {

... to...

// Any velocity to clamp?
        if ( mNotZero( dotVelocityNormal ) )
        {

That's it... a silly bug... big pain in the ass. My collision is now rock solid... no penetration and no sticking to surfaces.
#6
07/25/2006 (11:54 pm)
Tom,

This has been fixed and will be in the 1.1.1 release! Thanks a ton for finding this, you rock!

Cheers,
-Justin
#7
07/26/2006 (2:06 pm)
On a somewhat similar note:
I've experienced a situation where my little ball-and-paddle game behaves strange - the ball sometimes get stuck in the paddle and "bounces around like mad" within it. The collision response of the ball is set to BOUNCE and to send/receive both collisions and physics. The paddle is setup to send both collisions and physics, but not receiving anything.
Could this be a related problem?
#8
07/26/2006 (2:10 pm)
@Johan - Well my code fix will only effect the CLAMP response mode, so i don't think so. Still take a look at the t2dPhysics::resolveBounceCollision() function... it may have a similar bug!

I have found 2-3 more simple reproducable test cases of CLAMP response screwing up and warping my player thru objects. I'll try to debug those this weekend and solidify the 1.1.1 release even further.
#9
07/26/2006 (6:17 pm)
Thanks Tom,

Collision issues were one of my main problems. Glad you found the bug.
#10
07/26/2006 (7:33 pm)
I've got the pro version, so I can fix this bug in my version. However, I haven't tried editing any TGB C++ files, so I'm not sure what to do. Do I need to move any files, or is it just a case of opening the file in dev-C++, edit it and then compile it?
Thanks
#11
07/26/2006 (8:06 pm)
@Apurva - All you need to do is open t2dPhysics.cc, make the changes i documented above for t2dPhysics::resolveClampCollision(), and compile the EXE.
#12
07/27/2006 (6:05 am)
Ah, nice and simple. Thanks Tom!
#13
08/08/2006 (10:00 am)
Well, cant wait for the v1.1.1, since I do not own the source.
Please release it quickly >_<
#14
08/08/2006 (1:17 pm)
Tom,

I've had a look at this issue but the trouble is that I can't seem to easily duplicate the problem you're having which is a major bummer. Maybe this is related to the speed of the machine(s) I'm using.

One bug that I did find recently that could well cause similar issues and most definately causes objects to not move to the actual collision-point after a collision has been detected by the sweep routine is a change to "t2dPhysics::solveCollision()"...

Change...

if ( pCollisionStatus->mOverlapped )
...to...
if ( !pCollisionStatus->mOverlapped )

This is quite a serious problem and affects all collision detection. I would be most interested to see if this fixes your problem rather than the fix you suggest. If it doesn't, is there any chance you could send me the mod directory that shows this problem?

Thanks for your help Tom, much appreciated!

- Melv.
#15
08/08/2006 (1:59 pm)
I just reverted my clamp fix and added your fix... it still visibly penetrates when walking into objects and will stick to them.

Answer me this... am i fundamentally not understanding how clamp is supposed to work here? Is clamp supposed to make you stick or "clamp" to the surface of your collider? If so what response mode should i use... bounce with zero restitution (bounce also causes me to stick to surfaces as well... same dotVelocityNormal < 0.0f thing there)?

My 'mNotZero( dotVelocityNormal )' fix keeps the penetration from happening because it causes it to calculate an opposing force to push it back out of the collision poly, but it seems from your fix above that it shouldn't need to do that in the first place.

I was planning on sending the latest version of our kit for review by the GG guys tonight. I'll plan on CC'ing you on that email so you can see the issue in action.
#16
08/09/2006 (1:21 am)
Tom,

You're not incorrect in your fix (and it has indeed gone into the codebase); the main thing I was concerned about was that no matter what I tried, I couldn't duplicate it and being as the col-det is fairly complex, there could be several reasons why people are getting this issue. Also, I was interested in seeing if the "moveToCollision()" error was also a culprit of a similar problem.

I look forward to seeing your email; hopefully then I can try to duplicate the issue and ensure that there isn't anything else that is causing this.

- Melv.
#17
08/31/2006 (11:26 pm)
I am now getting this problem of an object sticking into another. Checking the code, Tom's fix is already in (I'm using 1.1.1) and even after adding Melv's fix I still get the sticky sticky.
#18
09/01/2006 (6:05 am)
@Ben - What collision response are you using? I think the same bug may be around in the BOUNCE mode.
#19
09/01/2006 (2:42 pm)
I am using CLAMP in getting the bug. When I switch to BOUNCE it stops happening.
#20
09/03/2006 (5:56 pm)
I'm actually having similar problems after downloading 1.1.1 for the Mac. I made the changes that Tom and Mel suggested, and my problem didn't go away.

My problem is --after completing the platformer tutorial-- my character's velocity will not change when jumping against a wall. If she's jumping up, she keeps going up until she hits the ceiling. If she's falling slowly, she slowly drags herself down the wall.

As far as I can tell, I followed the tutorial correctly. Here's my source code:
function playerClass::onLevelLoaded(%this, %scenegraph)
{
     $CL = %this;
      
      moveMap.bindCmd(keyboard, "left", "playerLeft();", "playerLeftStop();");
      moveMap.bindCmd(keyboard, "right", "playerRight();", "playerRightStop();");
      moveMap.bindCmd(keyboard, "up", "playerJump();", "");
	  $CL.setCollisionMaxIterations(2);
	  %force = 20;
      sceneWindow2D.mount($CL, "0 0", %force, true);
}

function playerLeft()
{
    $CL.moveLeft = true;
	$CL.setFlip(true, false);
}

function playerLeftStop()
{
    $CL.moveLeft = false;
}

function playerRight()
{
     $CL.moveRight = true;
	 $CL.setFlip(false, false);
}

function playerRightStop()
{
     $CL.moveRight = false;
}

function playerJump()
{
	%yVelocity = $CL.getLinearVelocityY();
	%xVelocity = $CL.getLinearVelocityX();

	$CL.setLinearVelocityY(100);
	$CL.setLinearVelocityX(0);

  	%collision = $CL.castCollision(0.005);
    
	if(!(%collision $= ""))
	{
		$CL.setLinearVelocityY(-100);
	}
	else
	{
		$CL.setLinearVelocityY(%yVelocity);
	}

	$CL.setLinearVelocityX(%xVelocity);
}

function playerClass::updateMovement(%this)
{ 
     if(%this.moveLeft)
     {
            %this.setLinearVelocityX(-60);
     }
    
     if(%this.moveRight)
     {
            %this.setLinearVelocityX(60);
     }
    
     if(!%this.moveLeft && !%this.moveRight)
     {
            %this.setLinearVelocityX(0);
     }
	 
	 %yVelocity = $CL.getLinearVelocityY();
	 $CL.setCurrentAnimation(%yVelocity);
                
    $CL.setLinearVelocityY(100);
  
    %collision = $CL.castCollision(0.005);
    $CL.setLinearVelocityY(%yVelocity );
    
    if(%collision $= "")
    {
        $CL.setConstantForceY(100);
    }
    else
    {
        $CL.setConstantForceY(0);
    }   
}

function playerClass::setCurrentAnimation(%this, %yVelocity)
{
    if(%yVelocity < 0 )
    {
    	 %this.playAnimation(CLjumpup);
    }
    else if(%yVelocity > 0 )
    {
    	 %this.playAnimation(CLjumpdown);
    }
    else
    {
         if(%this.moveLeft || %this.moveRight)
    {
        if(%this.getAnimationName() $= "CLwalk")
        {
            if(%this.getIsAnimationFinished())
            {
                %this.playAnimation(CLwalk);
            }
        }
        else
        {
            %this.playAnimation(CLwalk);
        }
    }   
    else
    {
        %this.playAnimation(CLstand);
    }
    }
	
}

function t2dSceneGraph::onUpdateScene()
{
       $CL.updateMovement();
}
Page «Previous 1 2