PhysicsBody dont stop bounce

Hi,

Im trying make a ground and a player dont bounce when collide.

But when the player collide with ground the player are going up more than 500px.

My init code:

    // player
    player = Player::create();    
    addChild(player->getSpriteSheet());
    auto playerMaterial = PhysicsMaterial(0.0f, 0.0f, 0.0f);
    auto playerBody = PhysicsBody::createBox(Size(player->getWidth(), player->getHeight()), playerMaterial);
    playerBody->setRotationEnable(false);
    player->setPhysicsBody(playerBody);
    
    // ground
    auto groundMaterial = PhysicsMaterial(0.0f, 0.0f, 0.0f);
    auto groundSprite = Sprite::create();
    groundSprite->setPosition(Point(origin.x + visibleSize.width/2, origin.y + 34));
    auto body = PhysicsBody::createEdgeBox(Size(visibleSize.width, 1), groundMaterial, 1);
    groundSprite->setPhysicsBody(body);
    addChild(groundSprite);

This is a bug?

might be the restitution part of the body’s fixture definition?

I have tried values between 0 to 50, nothing change. I want make the same as i do here in my other project with v2.0:

The player need be static over the ground.

Can anyone help me? It only contain a ground box and a player (represented by a box).

I think you didn’t set PhysicsMaterial right. you can use default value to test it, or you can browse test-cpp to see how to set it.

i am guessing your ground is Static and player body is Dynamic, so if thats the case then you have to forcefully set collision restitution to 0. In your .h file define it like

	// Physics Contact Listener.....
bool onContactBegin(PhysicsContact& contact);
bool onContactPreSolve(PhysicsContact& contact,
		PhysicsContactPreSolve& solve);
void onContactPostSolve(PhysicsContact& contact,
		const PhysicsContactPostSolve& solve);
void onContactSeperate(PhysicsContact& contact);

and in you init() method define it like
//*************** Setting our Physics Body Contact Listener…**********

EventListenerPhysicsContact *contactListener =
		EventListenerPhysicsContact::create();
contactListener->onContactBegin =
		CC_CALLBACK_1(StateMachine::onContactBegin, this);

contactListener->onContactPreSolve =
		CC_CALLBACK_2(StateMachine::onContactPreSolve, this);

contactListener->onContactPostSolve =
		CC_CALLBACK_2(StateMachine::onContactPostSolve,this);

contactListener->onContactSeperate =
		CC_CALLBACK_1(StateMachine::onContactSeperate,this);

_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener,
		this);

now we to avoid jumping effect when two bodies collide we will only need our “preSolve” callback, this is a mediator callback and is called just before calculating final collision values for two bodies.
define it like this.

// Calling it to eliminate The Jumping Effect... Restitution
    bool StateMachine::onContactPreSolve(PhysicsContact& contact,
	PhysicsContactPreSolve& solve) {
        solve.setRestitution(0);
       	return true;
 }

now this should do the trick for you, hope it helps :innocent:

EDIT:-
i am Assuming that you are using cocos2d-x internal physics (chipmunk), if not then there might be some syntactical dissimilarities although conceptual working is same.

keep in mind that this will work for every collision that will happen, if you want to filter that out and manually handle which two bodies will not bounce after collision then in that case you can filter it out like

       PhysicsBody* a = contact.getShapeA()->getBody();
        PhysicsBody* b = contact.getShapeA()->getBody();
    // only do this when player collide with world, for other collisions 
    //  it will work like normal
        if (a->getTag() == Player::_playerBodyTag || b->getTag() == 
                      Player::_playerBodyTag){
         solve.setRestitution(0);
      }
1 Like

Thanks for replying however I dont think that would work since I just tried it. The reason for this is as I mentioned before one body is static (the wall) and the other body is dynamic for callbacks such as onContactBegin , onContactPreSolve to occur both the bodies need to have setContactTestBitmask(true) and if you set the setContactTestBitmask(true) property of a static body to true then other bodies pass through it.Kindly correct me if I am wrong or missing something.

i suspect the way u create you walls is not right it would be more clear if u can post your code to create static bodies(walls), instead of modifying setContactTestBitmask(true) or any other property, try it like wallBody->setDynamic(false);

Sorry I didn’t post my code earlier.
This is how I am creating my wall

  Sprite* sp = Sprite::create();
    sp->setContentSize(Size(w,h));
    sp->setPosition(SetAnchorFromCenter(Vec2(x,y), sp->getContentSize()));
    PhysicsBody* pb= PhysicsBody::createEdgeBox(Size(w,h),PhysicsMaterial(0,0,0),1,tileMap->getPosition());
    //pb->setContactTestBitmask(true);
    pb->setDynamic(false);
    sp->setPhysicsBody(pb);
    this->addChild(sp);

This is how I am creating my dynamic object

sprite_eagle = Sprite::createWithSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("tmp-10.gif"));
    sprite_eagle->setPosition(50,450);
    sprite_eagle->setAnchorPoint(Vec2(0.5,0.5));
    this->addChild(sprite_eagle);
    
    //Create the physics body for the sprite_eagle
    PhysicsBody* sprite_eagle_body= PhysicsBody::createCircle((sprite_eagle->getContentSize().width)/2,PhysicsMaterial(0,0,0));
    sprite_eagle_body->setCollisionBitmask(2);
    //sprite_eagle_body->setContactTestBitmask(true);
    sprite_eagle->setPhysicsBody(sprite_eagle_body);

I believe a physics body by default is dynamic.

This is how I am moving my object

sprite_eagle->getPhysicsBody()->setVelocity(vel);

instead of creating createEdgeBox(Size(w,h),PhysicsMaterial(0,0,0),1,tileMap->getPosition()); try simple createBox()

I moved the question to a new thread since now I am dealing with slidding and not bouncing.

By default every body will have collision with every other body, now we can make a body static by doing wallBody->setDynamic(false); this will make sure when collision takes place wall doesn’t move from its place, now as you already set restitution to 0(to avoid jumping effect), you must be getting error in player movement(he keeps sliding left & right randomly with random speed(correct me if i am wrong)). Solution lies in other callbacks i have provided, have u played with them? what you should do is after collision you want to set player velocity to 0. do it like

void StateMachine::onContactPostSolve(PhysicsContact& contact,
    	PhysicsContactPostSolve& solve) {
   PhysicsBody* a = contact.getShapeA()->getBody();
   PhysicsBody* b = contact.getShapeA()->getBody();
   PhysicsBody* playerBody = (a->getTag() == Player::_playerBodyTag)?a:b;
    playerBody->setVelocity({0,0});
}

using a physics engine just for collision sounds good , but modifying it according to your needs from given tools can be a daunting task.

Also you should avoid creating multiple threads/posts, this will only confuse developers who may face this issue in future.

Sorry abt that. Thanks for clearing this up.

Like this problem?I haven’t solved. :sob:

yup that’s correct, it will also solve your problem if done right, i suggest you to go through this post.

Only In my Android phone, the effect is the same as I want.I was decisive for box2d.

I am getting same issue.My code on android device working perfectly but on iOS device continuously bouncing when two dynamic bodies are coming in contact.

have you any solution for iOS ?

Here,I got the code to fix this :-

#define __FLT_EPSILON__ 1.19209290e-07F
float  _filteredUpdateDelta;
scene->getPhysicsWorld()->setAutoStep(false);
void GameContrler::updatePhysics(float delta)
{
// How many times to supstep the phyiscs engine per game update.
const int phyiscsSubSteps = 3;

// The delta is divided by the number of substeps, to sync the game step with the physics step.
float dt = delta / static_cast<float>(phyiscsSubSteps);

// Apply a low-pass filter to dt to smoot it out to make the phyiscs simulation smoother.
 _filteredUpdateDelta = dt > __FLT_EPSILON__ ? 0.15 * dt + 0.85 * _filteredUpdateDelta : 0.0;

  // Apply the number of substeps to the phyiscs engine for this game update.
for (int i=phyiscsSubSteps; i>0; i--)
       {
       sceneWorld->step(_filteredUpdateDelta);
      }
}

No, I did not develop on the IOS platform. But in Windows box2d is running normally.
cocos2d-x-3.10