2d "camera" follow target looks ugly

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.

I just tried this:

  • adding another Node as child, and adding a body to this new child
    and the result is very confusing:

THE SPRITE THAT CAMERA FOLLOWS… JITTERS (same as old video)… BUT HIS CHILD… LOOKS PERFECT

auto child = cocos2d::Node::create();
auto newBody = cocos2d::PhysicsBody::create();
auto shape = cocos2d::PhysicsShapeCircle::create(50);
shape->setSensor(true);
newBody->addShape(shape);
newBody->setDynamic(false);
newBody->setPositionOffset({ 30,0 });

child->setPhysicsBody(newBody);
sprite->addChild(child);

… WTF

The problem still the same…
any idea?? @slackmoehrle @zhangxm

I just created this question, that looks like the same problem… Im just hoping to solve the problem… thnx

Solution is there 2d "camera" follow target looks ugly

Repeating question and ignoring links for solution will not help you)
Also you can google for smoothDamp function implementation from unity, it’s filtering camera super smoothly.

Im sorry, but I have try (if Im correct) every and each single solution has been presented here.

The “solution” you mentioned here:[quote=“KAMIKAZE, post:7, topic:36509”]
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.
[/quote]

I am actually implementing it:

  • setup:

    getPhysicsWorld()->setAutoStep(false);
    getPhysicsWorld()->setSpeed(5.0f);
    getPhysicsWorld()->setGravity(Vec2(0, -98));
    schedule(schedule_selector(GS_1::MyUpdate), 1.0f / 90.0f);

-update:

void GS_1::MyUpdate(float dt)
{
    getPhysicsWorld()->step(dt);
    actionLayer->update(dt);
    getDefaultCamera()->setPosition(cameraTarget->getPhysicsBody()->getPosition());
    getDefaultCamera()->update(dt);
}

Also, I implemented the solution mentioned in the links you provided
(How to fix Jittery Side Scrolling with Box2D) & (Fixed Time Step and Box2D)
and even if using all of these methods kinda solves or make it less obvious the problem of the jittering on the camera, some “secondary effect” persists, like the fact that children’s bodies have a small delay, seems like thery are updated at a diferent time.

I appreciate your solutions and clarifications, specially from you (@anon98020523) and (@almax27). You have helped me a lot. And now I could say the jiterring is not bothering me anymore.

I just think that this “secondary effect” is part of the same problem. I dont think im repeating a question, and definitely im not ignoring any answer (I even made a list of the result of each answer given). I think I am showing another side effect of the same problem which current solutions does not fix.

I created another thread because I think If someone else search specifically for it would be easier to find, and I dont consider it the exact same question. But…to be honest, seems like if anyone knows (and answers) in this forum is mainly both of you (and some how I think is conected to this issue)

I repeat: now I could say the jiterring is not bothering me anymore, So I guess I wil set this as solved.
Thanks everyone for the help, I really appreciate it.

Hi!

I am new to Cocos2d and had the same (worst!) problem. After some debugging I discovered that when a scene is created, a new camera is added. If you look closely, you see that when the scene starts, there are 2 (same) cameras!
To fix that, I went to cocos2d::CCCamera::setScene(~line 451) and replaced the code:

// FX:: 25/09/2017??? auto it = std::find(cameras.begin(), cameras.end(), this);
//if (it == cameras.end())
with this
if (cameras.size() < 1)

after that everything works perfectly.

(NB: I use windows10/C++ 2017)

1 Like

Can you please create a GitHub issue for this?

I am sorry, but as a noobie, I must ask.

How should I do that?

Here, please: https://github.com/cocos2d/cocos2d-x/issues

Thank you. I did so, and the new issue id is: Scene cameras #18320