[SOLVED]Chipmunk physics engine bug/flaw? include video demo

Hello. thank you for reading this post.
I am trying to use the integrated chipmunk physics to build a game.
However, physics bodies have some irregular movements while CPU/GPU is on heavy workload.
e.g. caching video ad from admob / phones with low specs
(although the physics bodies are not jumping around crazy like the video, but it happens on my iphone4s, emulator, my cheap android phone.)

can it be fixed or
this is just the flaws of chipmunk physics engine and cannot be fixed?
thank you so much.

here is the link to the video demo

I am using cocos2d-x 3.10
here is the code in the demo

HelloWorld.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
#include "MyBodyParser.h"

class HelloWorld : public cocos2d::Layer
{
public:
	static cocos2d::Scene* createScene();
cocos2d::PhysicsWorld *sceneWorld;
void SetPhysicsWorld(cocos2d::PhysicsWorld *world) { sceneWorld = world; }

virtual bool init();

bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *event);

// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
};

#endif // __HELLOWORLD_SCENE_H__

HelloWorld.cpp

#include "HelloWorldScene.h"

USING_NS_CC;

Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
// auto scene = Scene::create();
auto scene = Scene::createWithPhysics();
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
scene->getPhysicsWorld()->setGravity(Vect(0.0, -300.0));

// 'layer' is an autorelease object
auto layer = HelloWorld::create();
layer->SetPhysicsWorld(scene->getPhysicsWorld());

// add layer as a child to scene
scene->addChild(layer);

// return the scene
return scene;

/*// 'scene' is an autorelease object
auto scene = Scene::create();

// 'layer' is an autorelease object
auto layer = HelloWorld::create();

// add layer as a child to scene
scene->addChild(layer);

// return the scene
return scene;*/
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
    return false;
}

Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin(); 

MyBodyParser::getInstance()->parseJsonFile("testground.json");

auto edgeBody = PhysicsBody::createEdgeBox(Size(1500,3000), PhysicsMaterial(1000.0f, 0.0f, 1.0f), 5);
auto edgeNode = Node::create();
edgeNode->setPhysicsBody(edgeBody);
edgeNode->setPosition(Point(1500.0/4, 3000.0 / 2));
this->addChild(edgeNode);

auto boxB1 = Sprite::create("boxB1.png");
this->addChild(boxB1);
auto boxB1Body = MyBodyParser::getInstance()->bodyFormJson(boxB1, "boxB1.png", PhysicsMaterial(2000.0, 0.0, 1.0));
boxB1Body->setDynamic(false);
boxB1->setPhysicsBody(boxB1Body);
boxB1->setAnchorPoint(Vec2(0.5, 0.0));
boxB1->setPosition(Vec2(visibleSize.width / 2, 0.0));
boxB1->setScale(0.5);

auto boxB2 = Sprite::create("boxB2.png");
this->addChild(boxB2);
auto boxB2Body = MyBodyParser::getInstance()->bodyFormJson(boxB2, "boxB2.png", PhysicsMaterial(2000.0, 0.0, 1.0));
boxB2Body->setDynamic(true);
boxB2->setPhysicsBody(boxB2Body);
boxB2->setAnchorPoint(Vec2(0.5, 0.0));
boxB2->setPosition(Vec2(visibleSize.width / 2,boxB1->getBoundingBox().size.height));


auto touchListener = EventListenerTouchOneByOne::create();
touchListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);

return true;
}

bool HelloWorld::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *event) {
auto box = Sprite::create("box.png");
box->setPosition(touch->getLocation());
auto body = MyBodyParser::getInstance()->bodyFormJson(box, "box.png", PhysicsMaterial(100.0, 0.0, 1.0));
box->setPhysicsBody(body);
this->addChild(box);
return false;
}

I think you use variable time step(dt). You should use fixed time step to get stable physics.
Your update function should be like this(JS example):

update: function(dt){
        this.accumulator += dt;
        while(this.accumulator > this.fixedStep) {
            this.accumulator -= this.fixedStep;     
            this.space.step( this.fixedStep );      
        }
}
2 Likes

thank you so much. I am pretty new in game development. didn’t event know there is a thing call fixed time step. I got the idea. thanks man

No problem. I had some issue some time ago :smile: