I have experiencing some shocking/jittering -graphics on my game for a while now. I'm trying to get rid of it by playing around with these settings
My FlxG.scaleMode is set to FixedScaleMode and I have a custom camera that does things like setSize, setScale and setPosition to accomadate for zoom, window & stagesizes and also an offset that it seems to be needing for the FlxG.initialHeight and FlxG.initialWidth.
All movement in my game - including that of my character - is done by tweens. This because its a fixed movement game i thought that would make more sens then calculating all my own animations. The world is one bit tilemap and when needed i instantiate a tile with tileToSprite to a FlxSprite and do some tweening on it, when its done I turn it back into a tile with setTile. I also use setTile for lots of other things: eg: If i walk to a new location, i use settile to change the tile. Finally my camera is set to follow my character with: TOPDOWN.
I'm willing to bet that the problem is in the camera somewhere. Because if I set the lerp to 0 and with that set the camera not to move then there are no problems. While writing this I have the idea to just put lerp to 0 and see what happens if i position the camera on every update().
Does anyone have any ideas on how to best fix this? The problem kind of comes and goes and Neko seems more affective then CPP. I have this problem on both Legacy and -Dnext.! So no solution there!
Many thanks for any tips/tricks or solution anyone might have!
After playing around with this for a while I've come up with the following.
First: scrolling manually on every update() does not solve anything, infact it kind of makes it worse.
Second: I've tried tweening the camera along the movement of my character. This also did not solve it and made it worse.
But now, if I use the following settings:
FlxG.fixedTimestep = false; FlxG.maxElapsed = 0.01; FlxG.updateFramerate = 120; followLerp = 1;
Then the game runs really smooth. This only has the big disadvantage of slowing down the game, or perhaps only the timers on FlxTimer & FlxTween. Lucky for me that all my timers are in a global settings file and I already have a global speed constant which usually is just 1.0.
The documentation states this about maxElapsed:
Useful when the timestep is NOT fixed (i.e. variable), to prevent jerky movement or erratic behavior at very low fps. Essentially locks the framerate to a minimum value - any slower and you'll get slowdown instead of frameskip; default is 1/10th of a second.
so now the framerate is locked at 0.01 instead of the usual 0.166* (1/60). So then if I compensate my global speed constant to 60/second * 0.01 equals 0.6. And with that value on my speed constant - that just gets mutiplied to all my speed variables for tweens and timers - then the game runs pretty smooth. Even Neko debug builds that I use for testing run a lot better. (but still not as great as CPP).
I've testen on my Pc and on android. Both run alot smoother now. I'm thinking the problem lays in Lerp. Not because lerp is a bad idea but perhaps the implentation is not that great. For example the documentation states this about followLerp
followLerp:Float = 60 / FlxG.updateFramerate
as default value. But if you then read the description it inverts the division.
Used to smoothly track the camera as it follows: The percent of the distance to the follow target the camera moves per 1/60 sec. Values are bounded between 0.0 and FlxG.updateFrameRate / 60 for consistency across framerates. The maximum value means no camera easing. A value of 0 means the camera does not move.
Other then that It also hardcodes a desired framerate of 60/fps wich can have unwanted side affects if the framerate is set to something else. Would it not make more sense to use it like something like this.
followLerp:Float = FlxG.updateFramerate / FlxG.drawFramerate
Or perhaps even better just just elepased:Float in your calculations.
I've tested my game on 4K resolutions. The screen was hooked up by a HDMI cable. The max frame rate on this configuration is 30/fps because of the HDMI. By default Haxeflixel sets VSync on. This means that the game will be set to 30/fps. When I did this 4K test the game actually runned at half speed. (remember my game is all tweens) This was 3 weeks back and the PC i was testing it on did not have any development tools and I was unwilling to install them at that time. But if you hardcode the framerate on Lerp - and perhaps other places - then this is the effect it will have.!
Quote: WikiPedia HDMI version 1.4
HDMI 1.4 increases the maximum resolution to 4K × 2K, i.e. 4096×2160 at 24 Hz (which is a resolution used with digital theaters) or 3840×2160 (Ultra HD) at 24 Hz/25 Hz/30 Hz;
Now HDMI 2.0+ will run at 60hz but there are still alot of 1.4 systems/cables in the world.
Unless somebody has a other/better solution then setting: FlxG.maxElapsed = 0.01; and then compensating for it i'm going to use it.
I'm still open for tips/tricks!
Well. after playing some more with it I've found out that the problem lies more in FlxG.updateFramerate then anything else. (or atleast it seems that way now).
if FLxG.updateFramerate != FlxG.drawFramerate then I have jitter/jerky/shocky -graphics. In all my tests lerp was always set to 1.
To be honest. I have too much variables to play with. These all effect my smoothness of my game.
followLerp:Float; updateFramerate:Int; drawFramerate:Int; neko || cpp; debug || release; fixedTimestep:Boolean; maxElapsed:Float; Desktop || Android
Just playing around with all this cost a lot of time and does not give any real solution. I can probably just scrap neko and debug from this list because they are performing worse then cpp and release anyways and wont be used in the end product. But still leaves enough variables for testing.
The last thing I can think off is to substitute tweens for normal x, y animations. But then again if I load a map with hardly any tweens other then those of the character the problem still remains. Also the Tweens just manipulate the properties you specify. Even if I would write very optimized code for translations instead of the generalized tweens, then still I'm basically doing the same things and with that probably can assume the same results.
For now i'm going with:
FlxG.updateFramerate = FlxG.drawFramerate; followLerp = 1;
This seems to work best and not being a very big change. Previously my updateFramerate was set to 120 because I sometimes on some maps can have a lot of physics and i thought setting updateFramerate higher would give less lag. But it seems to be doing the opposite.
If anyone still has some great advice or recommended reading on this topic. Them by all means please share.
Small update on this. The movement in general works great, only when the framerate drops even slightly then the jitter is noticeable. Eventually I've just dropped this game for this reason. It had a lot of custom physics which was very cool, but as soon as it gets too much, jitter happens.
Link to a gif that demos the physics. It mostly jitters on weaker targets like phones.
I'm not a perfectionist, they always want a 10/10. I can settle for a 8/10, but it has to be a 8! :D. My game was about 50% done. I've tried putting the physics, along with demanding enemy AI on separate threads. But haxeflixel/openfl is not thread safe. With constantly using mutex to communicate between the threads, the performance gain was minimal.
This was an ambitious project. The physics + the AI where just too much, especially for phones. I've lost about 2 mounts on this, but hey, I had a lot of fun :D
I've started on a new game. One that does not need this much horsepower. Hopefully I can get it out in a couple of months.