Move sprite smoothly?

I have the same problem. I would be happy to know if you solved the problem. Anyway I tested lots of methods people suggested in the net. Using fixed time step, applying delta time, don’t use delta time and many more. However, I get the best result with frame rate 60, overriding update method and applying delta time. In this way sprites move smooth in good quality devices, but there is sometimes a jerk when I run the app on low quality devices(once in a second). I have the same issue when I run it on my laptop. My laptop is powerful enough to run this simple app. I don’t know the reason but I guess it’s related to resolution of the devices(because both my laptop and my low quality device have resolution near 800*1200) or to the fluctuation of frame rate. Although my laptop can handle even 120 frames per second, I noticed more fluctuation of frame rate in my laptop comparing to my good quality android device. And my biggest problem is there are complex games developed in cocos2d-x in the low quality device which runs smoothly. I would appreciate if someone can help me on this matter.

Thanks

1 Like

Look at Easing on this page. Easing is animating with a specified acceleration to make the animations smooth.

Thanks @slackmoehrle. I just want to move a sprite from top of the screen to bottom of the screen and I prefer to do this in update method if possible. Anyway I tried Easing, but jerks are still noticeable. Any Idea ?

1 Like

This is a major problem which has challenged my game too! its a week i’m struggling with this and still nothing! should we consider cocos2d-x as a suitable game engine for android?

Can you show me what you are doing so I can test and report any bugs?

2 Likes

This is my code:

bool HelloWorld::init()
{
	s = cocos2d::Sprite::create("Plain.png");
	s->setPosition(0, 0);
	s->setAnchorPoint(cocos2d::Vec2::ANCHOR_BOTTOM_LEFT);
	
	this->addChild(s);

	this->scheduleUpdate();

    return true;
}

void HelloWorld::update(float dt)
{
	s->setPositionX(s->getPositionX() + dt * 100);
}

Plain.png is a simple blank 200*200 image and the frame rate is 60 frames per second. It jerks sometimes on my laptop and Galaxy Tab 4 but it runs smoothly on my LG G4 phone. Thanks.

I’m waiting to know what the problem is. Thanks.

No improvements yet @slackmoehrle ?

I tried this on my iPhone6, iPad Pro, Android Nexus 9 and all are smooth.

Thanks, but all of the devices you mentioned are high quality devices. It also runs smoothly on my LG G4, but it jerks on my Galaxy Tab 4. Also it jerks on every laptop and PC that I have tested so far. If Galaxy Tab 4 is an old device, how other games(some of them developed with cocos2dx) runs smoothly on it ? Is there any trick ?

I don’t have a Galaxy Tab 4 to test this with.

By PC do you mean Windows ? I can try on my OS X machine too.

Yes, I tested them with visual studio using .sln file in proj.win32.

With setting GLContextAttrs to zero, it looks so much smoother. Is it okay to do so ? However I can’t say it solved my problem completely but jerks occur infrequently now.

I’d assume so, but let’s see what others think as well. I know we are doing this:

//if you want a different context,just modify the value of glContextAttrs
//it will takes effect on all platforms
void AppDelegate::initGLContextAttrs()
{
    //set OpenGL context attributions,now can only set six attributions:
    //red,green,blue,alpha,depth,stencil
    GLContextAttrs glContextAttrs = {8, 8, 8, 8, 24, 8};

    GLView::setGLContextAttrs(glContextAttrs);
}

Looking at the android implementation of Cocos2dxSurfaceView:

 public Cocos2dxGLSurfaceView onCreateView() {
    Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);
    //this line is need on some device if we specify an alpha bits
    if(this.mGLContextAttrs[3] > 0) glSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);

    Cocos2dxEGLConfigChooser chooser = new Cocos2dxEGLConfigChooser(this.mGLContextAttrs);
    glSurfaceView.setEGLConfigChooser(chooser);

    return glSurfaceView;
}

We can see that if the alpha bit is greater than 0 then a Translucent view format is selected. I expect this is the overhead you’re seeing.

Providing 0 for red, green and blue bits I expect will allow the OS to choose the most suitable.
Setting depth to 0 is a good idea if you don’t plan to make use of depth testing, but otherwise you will need it.

The minimum GLContext would be: {5, 6, 5, 0, 0, 0},
With depth buffer: {5, 6, 5, 0, 16, 0}
With stencil buffer: {5, 6, 5, 0, 0, 8}

In fact cocos internally defaults to {5, 6, 5, 0, 16, 0} if you don’t call setGLContextAttrs() in initGLContextAttrs() yourself.

2 Likes

Thanks @almax27 for your clear explanation.

Have you tried just a constant x value, say 1.5f? I think there could be rounding issue with dt*100, i.e. dt is not constant.

s->setPositionX(s->getPositionX() + 1.5f);
1 Like

dt is a parameter in update() for a reason.

I was taught that in order to move x smoothly you have to take the delta value and
the overall animation interval and divide the two.

For example:

void update(double dt) {
    float moveSpeed = 10.0f;
    moveSpeed *= Director::getInstance()->getAnimationInterval()/dt;  
    sprite->setPositionX(sprite->getPositionX() + moveSpeed);
}

The above basically accounts for errors for the targeted animation interval or FPS.
And it scales animation speeds based on that.

2 Likes

I was encountering this same problem and I realized I did something silly, so just posting in case it helps someone else.

I had an update call which was updating my view-port and another which was updating character movement.

  _layer->schedule(CC_CALLBACK_1(World::updateCharacters, this));
  _layer->schedule(CC_CALLBACK_1(World::updateViewPort, this));

These were called with mildly varying deltaTimes (of course) and thus my characters would look glitchy. After moving them to both update on the same callback things look very smooth.

2 Likes

It’s actually dt/Director::getInstance()->getAnimationInterval() and not the other way around.