Phaser: Jittery camera when following a motion-tweened object in 2.4.7

Created on 18 May 2016  路  25Comments  路  Source: photonstorm/phaser

When the camera is set to follow an object which is being moved via a tween, the camera appears to jitter slightly in relation to the object. (I.e., the object's position on the screen appears to "vibrate" unpredictably along the axis of movement.)

An example can be seen at this sandbox or this codepen. (Tested in Firefox 45 and Chrome 50.)

The same thing doesn't seem to happen in 2.4.6: I can use the same code and have the camera locked perfectly on the object, so that the object is stationary on the screen without any jitter.

This happens in 2.4.7 regardless of the use of the renderSession.roundPixels setting.

Most helpful comment

Alright. Fixed the issue with Tilemap cropping - and actually optmised the whole game loop a lot more. Tilemaps are now much more conservative about their rendering, which should help performance quite a bit. Still won't render as fast as the new shader based WebGL renderer we've got in build, but should definitely be better than before. New RC1 build uploaded.

All 25 comments

Hmm, the example is jittery for me in every version of Phaser back to 2.4.1 (I didn't test earlier than that). I agree it is _worse_ in 2.4.7+, but it's definitely still there previous to that too.

I think the issue is tween timing based, rather than camera specifically. Will have a look.

Bug confirmed on my setup in 2.4.8 with the Camera set to follow a sprite (LOCKON) that's been tweened, seeing as a lot of games have the camera follow objects (a player sprite for example) I would say it's a relatively important issue that needs fixing.

@photonstorm What has changed in relation to tweens and the camera in recent releases that you know of?

Nothing. There isn't a single line of code that is specific to the combination of tweens and camera movement, so this is a side-effect of something else.

Seems to not be affected when the tween is within the camera dead zone, could the interpolation between the sprite tweening and camera moving be fighting one another?

Here is a post on html5 that demonstrates this happening and is exactly what I get.

http://www.html5gamedevs.com/topic/22699-tweened-sprite-movement-is-jerky-while-camera-is-moving/

Confimed for me also, it's annoying as this is the only way of moving a player sprite a fixed value smoothly using the built in phaser libraries, I'll try to roll my own interpolation in the update function but I believe it might produce the same results.

I get this problem too, and have done as far back as I can remember. Even with camera.lerp, once the camera reaches terminal velocity (alongside the object being followed) there's jittering. This is without using any tweens.

You can see this in the arcade slopes demo actually.

Ok I took a good, long look at this today. The problem was the properties that the Camera was using to determine where to move to next. I have refactored quite a lot of the code, and the examples run perfectly smooth for me now - both with tweens, and with direct position modification (see below).

I've uploaded all the changes to the dev branch, including new build files. So please give those a go, and let me know what you see.

var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update, render: render });

function preload() {

    game.load.image('atari', 'assets/sprites/atari800xl.png');
    game.load.image('backdrop', 'assets/pics/remember-me.jpg');

}

var sprite;
var text;

function create() {

    game.world.setBounds(0, 0, 1920, 1200*2);

    game.add.sprite(0, 0, 'backdrop');
    game.add.sprite(0, 1200, 'backdrop');

    text = game.add.text(130, 8, "Jittery :(");
    text.fill = '#ff00ff';

    sprite = game.add.sprite(300, 0, 'atari');
    sprite.addChild(text);

    //  Either uncomment this, and comment-out the 2 lines in the 'update' function
    //  Or leave this commented out, and use the 'update' method instead. Just don't have both.

    // game.add.tween(sprite).to({ y: game.world.height }, 3000).start().loop(true);

    game.camera.follow(text);

}

function update() {

    sprite.y += 10;
    if (sprite.y > game.world.height) { sprite.y = 0; }

}

function render() {

    game.debug.text(sprite.y, 32, 32);
    game.debug.text(text.y, 320, 32);

}

Assets can be found in the Phaser examples repo if needed.

Just updated to this build on my demo page and the jitter still remains, with the added issue of tilemaps cropping as the player moves; guessing this is down to camera.lerp.

To replicate, just go up and down the hill and observe the right and bottom sides of the canvas.

I'll take a look, but this change will make no difference to improving tilemap jitter, which is a separate problem not part of this issue.

Ah yeah, I know; it's the player sprite that I was judging the jitter by. Just holding down a single direction makes this noticeable.

I don't see it at all on your demo page now, not on the sprite itself, only on the tilemap. The sprite is moving smoothly.

Hmm. I'll see if I can make it more obvious in a codepen or something. Can you see the cropping of the tilemap as the camera pans though?

Yes I can see the tilemap padding, that will be easy enough to fix.

Thank you @photonstorm it's definitely better! But seems to still be there ever so slightly, I'll do some more testing to make sure it's not my code accentuating the problem.

It will _always_ be there slightly, because there's no per-frame rendering interpolation going on anywhere in Phaser, and as tweens are time bound they don't always update at the right time. Even so, I'm confident this is as good as it's ever going to get for now really, at least until we move to Lazer.

Ah, I see. More to it than meets the eye. :wink: Thanks for tackling this!

Alright. Fixed the issue with Tilemap cropping - and actually optmised the whole game loop a lot more. Tilemaps are now much more conservative about their rendering, which should help performance quite a bit. Still won't render as fast as the new shader based WebGL renderer we've got in build, but should definitely be better than before. New RC1 build uploaded.

You absolute legend @photonstorm, I will trial this out tomorrow morning as I happen to be using stitched tilemaps so I should see quite an improvement from your changes. You've made my day!

@photonstorm

Phaser 2.4.9 RC1 problems

I seem to be getting weird errors in regards to tilemaps (my tilemaps no longer stitch together in short), I'm guessing the tileMapLayer.position attribute is not being accounted for? This is my code to position the tileMapLayer so that I can stitch them together.

this.tileMapLayer.fixedToCamera = false;
this.tileMapLayer.debug = true;
this.tileMapLayer.scrollFactorX = 0;
this.tileMapLayer.scrollFactorY = 0;
this.tileMapLayer.position.set(startingXPos, startingYPos);

Also when tweening sprites they do not move much and just seem to "jiggle" when trying to move it you can see, these two problems only seem to be happening on RC1.

http://imgur.com/tHUupFI - Phaser 2.4.9 RC1


Phaser 2.4.9 + 2.4.9 RC1 problems

Though Phaser 2.4.9 doesn't show the problems above, they both show that the text above seems to move with the camera rather than being fixed.

var help = game.add.text(10, 10, 'Arrows to move, click and drag to cast a ray', { font: '16px Arial', fill: '#ffffff' });
help.fixedToCamera = true;`

http://imgur.com/PuouEKh - Phaser 2.4.9

Many Thanks!

I'm also thinking of doing something like that for a project of mine, with a huge map split up into regions and stitched together like that so they can be loaded/discarded on demand as the player navigates the map.

As TilemapLayers are fixedToCamera by default (and really, should be always), I was hard-coding the camera position into the layer position. This is now put back under a conditional in RC2, so your stitched maps should scroll properly again.

@photonstorm Thanks for the fix! could you expand on why the tilemapLayer should always be fixed to the camera?

I did come across a problem with arcade collision but have fixed it on my branch, basically what happens is similar to the problem you have fixed in regards to the stitching, because the tileMapLayer position is not accounted for the collision fails as it expects it to have a default position of 0,0.

I have submitted a pull request for that issue - https://github.com/photonstorm/phaser/pull/2522

Basically they should always be fixedToCamera because none of the collision checks take their position into account. As you've now fixed this with your PR, it's less of an issue :)

Going to close this one off now, as I'm confident this is as good as it's going to get (without a rewrite of the main loop and rendering interpolation!)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Legomite picture Legomite  路  4Comments

HDouss picture HDouss  路  3Comments

Secretmapper picture Secretmapper  路  3Comments

samme picture samme  路  4Comments

rexrainbow picture rexrainbow  路  4Comments