2d "camera" follow target looks ugly

Hi!
Im on the early stages of creating a platform game, and Im testing the set up for cameras and layers.

currrent Scene hierarchy:
Scene:
– UI layer
– game layer
– (pending) background layers

Reading all the posts in the forum I can see most suggest to use this:
gameLayer->runAction(Follow::create(cameraTarget));
note: cameraTarget is a Node* using physics, child of the same layer

It works fine as long the target is not too fast, once that happens, the scene flickers, like this:

I guess the physics update at diferent time than the layer position.
Im using follow because most of the people suggest, but I guess the correct is to move the camera ( but this bring me the problem that the if camera moves, also my UI moves) so I dont know whats the correct solution.

How can I get rid of this noise?
Should I reaaally use follow or what should I do?
note: update method is empty, im not doing anythig on the update method,

1 Like

its better not to use follow i think.

What do you suggest to use instead, and why?

lerp in update

you will have more control over it… it will be much smoother

Is this how u mean it?

auto a = actionLayer->getPosition();
auto b = (cameraTarget->getPosition()* -1.0f) + Vec2(512, 384); //adjust to center on screen
auto c = ccpLerp(a, b, 0.5);
actionLayer->setPosition(c);

now its just the half of the flicker. after 2 secs more I get back to the same amount of noise :confused: :cry:
but it have a very smooth efect of moving as soon as I change the camera target :smiley:

Long time ago I’ve faced the same problem. That was cocos2d-iphone. Solution was - update physics and camera at same -(void) update: method. Worked well.

Now in another game with cocos2d-x this solutions not works well, sometimes I’ve got jitter.
Moving next - this thread helped me a little bit How to fix Jittery Side Scrolling with Box2D why little - because jitter is still occurs sometimes and really badly, but I’m still not using interpolation… in my game only one main character is physics dynamic body that moving, all other is just static bodies and so camera follows this character… also Fixed Time Step and Box2D

Actually, now I’m facing same problem, I can’t fix jitter. But I’ve today implemented interpolation but anyway jitter is there…

Is anyone can help with this? Maybe post working solution code? I just don’t know, I did all as in my links, but still…

The problem is that actions are processed before scheduled updates so follow is using the last frame’s position, not the current one. You should schedule an update for your camera after (lower priority) the rest of your game updates.

You can try out my code:

void CameraController::follow(float dt){
auto pos = _target->getPosition3D();
auto cameraPos = _camera->getPosition3D();
const Vec3 target(_x + pos.x ,_y + pos.y,_z + pos.z);
cameraPos.smooth(target, 1.f, 10.f);
_camera->setPosition3D(cameraPos);
}

With this camera following looks pretty nice.

Never used camera, is it had some disadvantages? Likely I’m seeing recommendations to use ccfollow…
Also this code auto cameraPos = _camera->getPosition3D(); not compiles.

well you need to create camera node for it. I use it for 3D scenes.

@almax anyways, there shouldnt be a jitter, if its ALWAYS using the previous position, no? I mean: its not the fresh position, its 1 frame behind, but anyways it should be a continuos movement, right? hahaha

and… about updating the camera after any update… you mean something like this?

schedule(schedule_selector(GameScene::update));

and:

void GameScene::update(float dt)
{
	getDefaultCamera()->setPosition(cameraTarget->getPosition());
	getDefaultCamera()->update(dt);
}

because didnt work either :confused:

@serebii01
I just tried… same jitter than every other method :cry:

RESULTS UNTIL NOW:
camera follows with no update = fail
schedule update and manually set position = fail
schedule update and manually set position and then update camera = fail
schedule update and use lerp between positions = fail
schedule update and use vector3:: smooth between positions = fail
schedule update , set camera and/or target position as physhicsBody position = fail

I just cant believe that everything fails XD hahaha ( crying inside )

For physics u should use fixed timestep.

Unfortunately no, movement is a function of time and the delta time for each frame can differ, so even at a constant speed the distance an object travels each frame can be different. This results in the jittering you see.

You can use the following methods to register your update:

void cocos2d::Node::scheduleUpdateWithPriority(int priority);

or

<template class T>
void cocos2d::Scheduler::scheduleUpdate(T *target, int priority, bool paused);

Where priority is the order the update will be executed. Lower numbers will execute first.

By default node updates are scheduled with 0 priority. So try registering your GameScene at priority 1 or more. It’s usually a good idea to create an enum to control update ordering throughout your application, which you can cast to int.

//UpdateOrder.h
enum class UpdateOrder : int
{
    Early = -1,
    Default,
    Late
};

//GameScene.cpp
void GameScene::onEnter()
{
    cocos2d::Scene::onEnter();
    scheduleUpdateWithPriority((int)UpdateOrder::Late);
}
void GameScene::onExit()
{
    cocos2d::Scene::onExit();
    unscheduleUpdate();
}

Hope this helps :slight_smile:

1 Like

@almax27 these is a jitter because of physics not fixed timestep and not used interpolation, so you are wrong. Read this http://gafferongames.com/game-physics/fix-your-timestep/

I’m sorry but that article explains why physics simulations use a fixed time step to keep the simulation stable, but does not address jittering.

The effect could be subtle as your game having a slightly different “feel” depending on framerate or it could be as extreme as your spring simulation exploding to infinity, fast moving objects tunneling through walls and the player falling through the floor!

Even with a variable delta time a physics simulation shouldn’t jitter as shown in the original poster’s video.

The issue is a desynchronisation between the object’s position and the camera’s position in a given frame. An update with a fixed time step wouldn’t solve the issue, only make the jittering less erratic.

Interpolation only covers up the issue, if you follow an object 1:1 every frame, time-step should be irrelevant.

Looking deeper into the cocos2d-x physics implementation it looks like the Physics step is done after all scheduled updates.

void Director::drawScene()
{
    // calculate "global" dt
    calculateDeltaTime();
    
    if (_openGLView)
    {
        _openGLView->pollEvents();
    }

    //tick before glClear: issue #533
    if (! _paused)
    {
        _eventDispatcher->dispatchEvent(_eventBeforeUpdate);
        _scheduler->update(_deltaTime);
        _eventDispatcher->dispatchEvent(_eventAfterUpdate);
    }

    _renderer->clear();
    experimental::FrameBuffer::clearAllFBOs();
    /* to avoid flickr, nextScene MUST be here: after tick and before draw.
     * FIXME: Which bug is this one. It seems that it can't be reproduced with v0.9
     */
    if (_nextScene)
    {
        setNextScene();
    }

    pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
    
    if (_runningScene)
    {
#if (CC_USE_PHYSICS || (CC_USE_3D_PHYSICS && CC_ENABLE_BULLET_INTEGRATION) || CC_USE_NAVMESH)
        _runningScene->stepPhysicsAndNavigation(_deltaTime);
#endif
        //clear draw stats
        _renderer->clearDrawStats();
        
        //render the scene
        _openGLView->renderScene(_runningScene, _renderer);
        
        _eventDispatcher->dispatchEvent(_eventAfterVisit);
    }
    ....

This means in order to make use of the physics position for a given frame you have to do so during Node::visit() or Node::draw()

So my above solution will not work for Nodes with a PhysicsBody. Personally I believe that physics should be updated before the scheduler to allow frame logic to manipulate or override the render position (e.g. interpolate/extrapolate).

Could any of the cocos2d-x devs chime in here and explain why physics is currently updated when it is? @slackmoehrle @zhangxm

2 Likes

Without fixed you will get jitter for fast moving objects. It’s easy way to follow object, just copy CCFollow code in update, also.

Omg, lol, I never used built in physics, just Box2D and all scheduled in one update.

some older posts says this is a soloution:
Refer to @Heyalda 's fix Why jitter/jerk when following sprite with layer? (video included)

It’s not fixed time step, so simulation will be different and I think thats not an option. Better just interpolate graphics, like in the links I’ve posted before. However, I’m seeing that problem in something different.
I just disabled physics and just trying to move Node like CCFollow does, and I’ve got jitter… that some kind of bug… need more investigation maybe I’ll try to create a demo project.