Box2D Forums

It is currently Thu Sep 02, 2010 3:48 pm

All times are UTC - 8 hours [ DST ]




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: Bounce always becomes perpendicular to surface
PostPosted: Tue Jul 22, 2008 11:40 pm 
Offline

Joined: Tue Jul 22, 2008 11:36 pm
Posts: 5
I decided to make a pong-like game with "improved physics", and decided to use Box2D. But for some reason, the ball always bounces perpendicular to the walls after a while. Is there any way to solve this?

If it helps, here's the code adapted to the testbed:

Code:
#ifndef PONG_H
#define PONG_H

class Pong : public Test
{
public:
   Pong()
   {
      m_world->SetGravity(b2Vec2(0.0f, 0.0f));

      b2BodyDef bodyDef;
      b2PolygonDef polyDef;
      bodyDef.position.Set(-51.f,0.f);
      polyDef.SetAsBox(1.f,38.5f);
      polyDef.friction = 0.1f;

      b2Body* framel = m_world->CreateBody(&bodyDef);
      framel->CreateShape(&polyDef);

      bodyDef.position.Set(51.f,0.f);
      b2Body* framer = m_world->CreateBody(&bodyDef);
      framer->CreateShape(&polyDef);

      bodyDef.position.Set(0.f,38.5f);
      polyDef.SetAsBox(51.f,1.f);
      b2Body* framet = m_world->CreateBody(&bodyDef);
      framet->CreateShape(&polyDef);

      bodyDef.position.Set(0.f,-38.5f);
      b2Body* frameb = m_world->CreateBody(&bodyDef);
      frameb->CreateShape(&polyDef);

      b2CircleDef circleDef;
      circleDef.radius = 1.5f;
      circleDef.friction = 0.4f;
      circleDef.density = 1.f;
      circleDef.restitution = 1.25f;

      bodyDef.position.Set(0.f,0.f);
      b2Body* ball = m_world->CreateBody(&bodyDef);
      ball->CreateShape(&circleDef);
      ball->SetMassFromShapes();
      ball->SetBullet(true);
      ball->SetLinearVelocity(b2Vec2(200.f,0.f));

      bodyDef.position.Set(-45.f,0.f);
      polyDef.SetAsBox(1.5f,6.f);
      polyDef.density = 10.f;
      polyDef.friction = 0.4f;
      circleDef.density = 5.f;
      circleDef.localPosition.Set(0.f,6.f);
      circleDef.restitution = 0.5f;

      b2Body* paddle1 = m_world->CreateBody(&bodyDef);
      paddle1->CreateShape(&polyDef);
      paddle1->CreateShape(&circleDef);
      circleDef.localPosition.Set(0.f,-6.f);
      paddle1->CreateShape(&circleDef);
      paddle1->SetMassFromShapes();

      bodyDef.position.Set(45.f,0.f);
      b2Body* paddle2 = m_world->CreateBody(&bodyDef);
      paddle2->CreateShape(&polyDef);
      paddle2->CreateShape(&circleDef);
      circleDef.localPosition.Set(0.f,6.f);
      paddle2->CreateShape(&circleDef);
      paddle2->SetMassFromShapes();

      b2PrismaticJointDef jointDef;
      b2Vec2 worldAxis(0.0f, 1.0f);
      jointDef.motorSpeed = 0.0f;
      jointDef.maxMotorForce = 10e4f;
      jointDef.enableMotor = true;
      jointDef.collideConnected = true;
      jointDef.Initialize(paddle1, frameb, paddle1->GetWorldCenter(), worldAxis);
      paddle1joint = (b2PrismaticJoint*)m_world->CreateJoint(&jointDef);
      jointDef.Initialize(paddle2, frameb, paddle2->GetWorldCenter(), worldAxis);
      paddle2joint = (b2PrismaticJoint*)m_world->CreateJoint(&jointDef);

      ball->AllowSleeping(false);
      paddle1->AllowSleeping(false);
      paddle2->AllowSleeping(false);
   }

   void Keyboard(unsigned char key)
   {
      switch (key)
      {
      case 'e':
         {
            paddle1joint->SetMotorSpeed(-100.f);
         }
         break;

      case 'd':
         {
            paddle1joint->SetMotorSpeed(100.f);
         }
         break;

      case 'i':
         {
            paddle2joint->SetMotorSpeed(-100.f);
         }
         break;

      case 'k':
         {
            paddle2joint->SetMotorSpeed(100.f);
         }
         break;
      }
   }

   static Test* Create()
   {
      return new Pong;
   }

   b2PrismaticJoint* paddle1joint;
   b2PrismaticJoint* paddle2joint;
};

#endif



Top
 Profile  
 
 Post subject: Re: Bounce always becomes perpendicular to surface
PostPosted: Wed Jul 23, 2008 1:27 am 
Offline
Site Admin

Joined: Thu Sep 06, 2007 12:34 am
Posts: 2211
Thanks for writing the test case. This makes it much easier for me to look at the problem.

You are using a restitution greater than 1, so the velocity of the ball is hitting the maximum linear velocity limit of 200 meters/second (around 600mph). As the velocity is scaled down the perpendicular velocity is reduced since the parallel velocity wants to increase (restitution greater than 1).


Top
 Profile  
 
 Post subject: Re: Bounce always becomes perpendicular to surface
PostPosted: Wed Jul 23, 2008 1:39 am 
Offline

Joined: Tue Jul 22, 2008 11:36 pm
Posts: 5
Erin Catto wrote:
Thanks for writing the test case. This makes it much easier for me to look at the problem.

np. That's exactly why I wrote it :-)

Quote:
You are using a restitution greater than 1, so the velocity of the ball is hitting the maximum linear velocity limit of 200 meters/second (around 600mph). As the velocity is scaled down the perpendicular velocity is reduced since the parallel velocity wants to increase (restitution greater than 1).

hm, makes sense, but i also tried restitution = 1, and the same problem occurred. ideally, only the restitution when colliding with one of the paddles should be > 1, but at the same time the paddles restitution when colliding with a wall should be low (a little bounce, but not too much)


Top
 Profile  
 
 Post subject: Re: Bounce always becomes perpendicular to surface
PostPosted: Wed Jul 23, 2008 10:03 am 
Offline
Site Admin

Joined: Thu Sep 06, 2007 12:34 am
Posts: 2211
You can use joint limits to prevent the paddles from hitting the wall.


Top
 Profile  
 
 Post subject: Re: Bounce always becomes perpendicular to surface
PostPosted: Wed Jul 23, 2008 11:11 am 
Offline

Joined: Tue Jul 22, 2008 11:36 pm
Posts: 5
I don't want to prevent it, i think it looks cool how they bounce of the walls if you move them too far :-)

Any ideas on what's causing the strange bouncing behavior? As long as it persists, I can't really do anything...


Top
 Profile  
 
 Post subject: Re: Bounce always becomes perpendicular to surface
PostPosted: Wed Jul 23, 2008 11:51 am 
Offline
Site Admin

Joined: Thu Sep 06, 2007 12:34 am
Posts: 2211
Once you keep the velocity within the limit, you next need to set all friction values to zero. I would also setup the ball to have fixed rotation.


Top
 Profile  
 
 Post subject: Re: Bounce always becomes perpendicular to surface
PostPosted: Wed Jul 23, 2008 2:35 pm 
Offline

Joined: Tue Jul 22, 2008 11:36 pm
Posts: 5
But then i can't add spin to the ball to make it bounce in a different direction... I guess what I need is some fake physics...


Top
 Profile  
 
 Post subject: Re: Bounce always becomes perpendicular to surface
PostPosted: Wed Jul 23, 2008 3:32 pm 
Offline

Joined: Sun Jan 20, 2008 7:52 pm
Posts: 434
Yes, you definitely need some fake physics. In your case, probably a minimum horizontal velocity.


Top
 Profile  
 
 Post subject: Re: Bounce always becomes perpendicular to surface
PostPosted: Thu Jul 24, 2008 3:03 am 
Offline

Joined: Tue Jul 22, 2008 11:36 pm
Posts: 5
I decided to go for a minimum angle (and a minimum velocity) instead. It seems to work.

Code:
void Step(Settings* settings)
   {
      Test::Step(settings);

      b2Vec2 ballVelocity = ball->GetLinearVelocity();
      float32 absX = fabs(ballVelocity.x);
      float32 length = ballVelocity.Length();

      const float32 xmul = 0.2f;
      const float32 ymul = (2.f*sqrt(6.f))/5.f;

      if(absX < 0.2f*length)
      {
         if(absX > 1e-6f)
         {
            float32 sgnX = (ballVelocity.x < 0.f) ? -1.f : 1.f;
            float32 sgnY = (ballVelocity.y < 0.f) ? -1.f : 1.f;
            ballVelocity.x = sgnX * xmul * length;
            ballVelocity.y = sgnY * ymul * length;
         }
         else
         {
            float32 sgnPos = (ball->GetPosition().x < 0.f) ? 1.f : -1.f;
            float32 sgnY = (ballVelocity.y < 0.f) ? -1.f : 1.f;
            ballVelocity.x = sgnPos * xmul * length;
            ballVelocity.y = sgnY * ymul * length;
         }
      }

      if(length < 10.f)
      {
         if(length > 1e-6f)
         {
            float32 mul = 10.f/length;
            ballVelocity *= mul;
         }
         else
         {
            float32 sgnPos = (ball->GetPosition().x < 0.f) ? 1.f : -1.f;
            ballVelocity.x = sgnPos * 1.f;
            ballVelocity.y = 0.f;
         }
      }
      else if(length > 30.f)
      {
         float32 mul = 30.f/length;
         ballVelocity *= mul;
      }

      ball->SetLinearVelocity(ballVelocity);
   }


Any suggestions on how to increase ball velocity on contact with one of the paddles? (probably something like increasing the minimum velocity after each ball-paddle contact)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 8 hours [ DST ]


Who is online

Users browsing this forum: Yahoo [Bot] and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group