In the “Starling” project, when moving the drawn block object, the surroundings shake, and the “html5 air window” also shakes
package;
import starling.core.Starling;
import openfl.display.StageAlign;
import openfl.display.StageScaleMode;
import openfl.display.Sprite;
class Main extends Sprite {
public function new() {
super();
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.color = 0xFFE4C4;
stage.frameRate = 60;
var ss:Starling = new Starling(Game, stage);
ss.showStats = true;
ss.showStatsAt("left", "top", 2);
ss.start();
}
}
package;
import openfl.Lib;
import starling.animation.Transitions;
import starling.core.Starling;
import starling.animation.Tween;
import starling.events.EnterFrameEvent;
import starling.display.Canvas;
import starling.display.Sprite;
class Game extends Sprite {
private var ii:Int = 0;
public function new() {
super();
Lib.setTimeout(fn, 5000);
this.addEventListener(EnterFrameEvent.ENTER_FRAME, update);
}
private function update(e:EnterFrameEvent):Void {
ii += 1;
if (ii < 200) {
var node:Sprite = adds(0, 0, 30, 30);
node.x = Math.random() * 960;
node.y = Math.random() * 640;
this.addChild(node);
}
}
private function fn():Void {
var tween:Tween = new Tween(this, 4.0, Transitions.LINEAR);
tween.animate("y", this.y - 200);
tween.onComplete = go1;
Starling.current.juggler.add(tween);
}
private function go1():Void {
var tween:Tween = new Tween(this, 4.0, Transitions.LINEAR);
tween.animate("x", 300);
tween.onComplete = go2;
Starling.current.juggler.add(tween);
}
private function go2():Void {
var tween:Tween = new Tween(this, 4.0, Transitions.LINEAR);
tween.animate("x", 100);
tween.onComplete = go1;
Starling.current.juggler.add(tween);
}
private function adds(x:Float, y:Float, w:Float, h:Float):Sprite {
var node:Sprite = new Sprite();
node.pivotX = w / 2;
node.pivotY = h / 2;
node.x = x;
node.y = y;
var cc:Canvas = new Canvas();
cc.beginFill(0xff0000, 0.5);
cc.drawRectangle(0, 0, w, h);
node.addChild(cc);
return node;
}
}
@785597448, the code you provided is a good demonstration of the issue, thank you ![]()
I was able to replicate what you were seeing. Increasing the anti-aliasing to max had no effect, but I was able to reduce the jitter significantly (although perhaps not entirely), by setting each Tween to roundToInt = true. This stops the sub-pixel positioning, which caused some squares to appear to step ahead while others lagged behind on any given frame.
package;
import openfl.Lib;
import starling.animation.Transitions;
import starling.core.Starling;
import starling.animation.Tween;
import starling.events.EnterFrameEvent;
import starling.display.Canvas;
import starling.display.Sprite;
class Game extends Sprite {
private var ii:Int = 0;
public function new() {
super();
Lib.setTimeout(fn, 5000);
this.addEventListener(EnterFrameEvent.ENTER_FRAME, update);
}
private function update(e:EnterFrameEvent):Void {
ii += 1;
if (ii < 200) {
var node:Sprite = adds(0, 0, 30, 30);
node.x = Math.random() * 960;
node.y = Math.random() * 640;
this.addChild(node);
}
}
private function fn():Void {
var tween:Tween = new Tween(this, 4.0, Transitions.LINEAR);
tween.roundToInt = true;
tween.animate("y", this.y - 200);
tween.onComplete = go1;
Starling.current.juggler.add(tween);
}
private function go1():Void {
var tween:Tween = new Tween(this, 4.0, Transitions.LINEAR);
tween.roundToInt = true;
tween.animate("x", 300);
tween.onComplete = go2;
Starling.current.juggler.add(tween);
}
private function go2():Void {
var tween:Tween = new Tween(this, 4.0, Transitions.LINEAR);
tween.roundToInt = true;
tween.animate("x", 100);
tween.onComplete = go1;
Starling.current.juggler.add(tween);
}
private function adds(x:Float, y:Float, w:Float, h:Float):Sprite {
var node:Sprite = new Sprite();
node.pivotX = w / 2;
node.pivotY = h / 2;
node.x = x;
node.y = y;
var cc:Canvas = new Canvas();
cc.beginFill(0xff0000, 0.5);
cc.drawRectangle(0, 0, w, h);
node.addChild(cc);
return node;
}
}
Is there a solution to the problem of image edge shaking when the map container is moved?
private function onEnterFrame(e:EnterFrameEvent):Void {
this.x += Std.int(800 * e.passedTime);
}
Math.round(), instead of Std.int() is likely going to provide a smoother animation.
If I’m not mistaken, with Std.int(), 1.9999 is rounded to 1, whereas with Math.round(), it’s rounded to 2 which is the nearer integer.
Not very effective! Still shaking Is this a problem with framework rendering? Is there a way to solve jitter?
This article details the issue, as well as various ways the author attempted to address it, largely unsuccessfully.
Note, the author is doing this in JavaScript, but the mathematical principles are the same.
In conclusion
Welp, that was underwhelming. There is no silver bullet when you want to slowly move things on a sub-pixel grid and then render them to a low-resolution pixel grid. The laws of nature and math hate us.
We can alleviate the issue somewhat by
- Massaging our time steps by averaging
- Possibly combining it with fixed-point arithmetic to further quantize and thus more evenly spread out the sampling discontinuities
A perfect solution is however elusive. Unless you make your objects simply move faster
