Woah, interesting! I noticed that the
Jump'n'Run example game has this problem too. It's even more noticeable in the
Physics demo, because there's no animation for the player when moving.
The only reason this problem is not that obvious in Biolab Disaster is because of the damping for the screen movement.
Here's what's happening; your game's update method probably looks something like this (taken from the Jump'n'Run demo):
update: function() {
// screen follows the player
var player = this.getEntitiesByType( EntityPlayer )[0];
if( player ) {
this.screen.x = player.pos.x - ig.system.width/2;
this.screen.y = player.pos.y - ig.system.height/2;
}
// Update all entities and BackgroundMaps
this.parent();
}
So this method moves the screen to center on the player&
039;s position. However, *after* the screen x and y were set, the call to #this.parent()
updates and moves all entities. So the screen is essentially always centered on the position the player had in the
last frame. It's always one frame behind.
To fix this, you first have to call
this.parent()
to update all entities and then set the screen position. Furthermore you also have to call
.setScreenPos()
for all background maps
after you set the screen position. This is normally done in the parent&
039;s #update()
method, but we have to do it again, since we changed
this.screen.x/y
after the call to
this.parent()
.
But that's still not all - an entity's position is rounded before it's being drawn, so you have to round the screen position as well to make sure it's not choppy.
Long story short: this should work, but is quite ugly:
update: function() {
// Update all entities and BackgroundMaps
this.parent();
// screen follows the player
var player = this.getEntitiesByType( EntityPlayer )[0];
if( player ) {
this.screen.x = player.pos.x.round() - ig.system.width/2;
this.screen.y = player.pos.y.round() - ig.system.height/2;
}
// update the screen position for all background maps
for( var i = 0; i < this.backgroundMaps.length; i++ ) {
this.backgroundMaps[i].setScreenPos( this.screen.x, this.screen.y);
}
}
Or - and this is way more elegant at the moment - set the game&
039;s screen position from within the #update()
method of the entity you want to follow, instead of from the game&
039;s #update()
method. So in your game class, don't do anything special:
update: function() {
// Update all entities and BackgroundMaps
this.parent();
}
(You could get rid of the
update()
method in your game class entirely if you only call
this.parent()
)
But in your player entity&
039;s #update()
method, set the screen position
after the entity has been moved:
update: function() {
/*
check your input,
set the acceleration etc.
*/
// move!
this.parent();
// set the screen position
ig.game.screen.x = this.pos.x.round() - ig.system.width/2;
ig.game.screen.y = this.pos.y.round() - ig.system.height/2;
}
I hope that helps!
This is really broken and way more complicated than it should be. Maybe I&
039;ll just introduce a #.setScreenPos()
method for the Game class that you have to call, instead of setting
screen.x/y
yourself.
I'm sorry for that. Thanks for bringing it to my attention!