Visual syncopation in position updates due to pixel rounding

  • Know what I'm talking about?

    i.e... Jitters... You know, when an object rounding to the nearest pixel clicks to a new x coordinate one tick and then a new y coordinate the next and back and forth. Rarely does the object update both x and y simultaneously at lower velocities. The result is a sort of jittering stair step movement. Once the object is moving fast enough (say 200 pixels per second, depends on resolution as well) the effect is much harder to notice. But it is super obvious when a platformer reaches the apex of a jump or a top down guy is running diagonally... and so on...

    I spent some time with the nes and noticed this doesn't exist. If an object needs x updated more often than y then y only updates with x. Basically it won't alternate between the two... even if it makes mathematical sense. Now, I know the nes had a fixed frame rate.... but it did have sub pixel positions (though I only think 4). But either way if my object was at 0.5,1 and I started making it move at 1 sub pixel per component per frame, it would still update (visually) only one component per 4 frames and be alternating between the two and giving that jagged jitter movement look. But thats not what happens on the nes... Something goes on to ensure that x/y are updated together or that only one gets rounded while the other has to wait for the next update time.

    Does anyone have any idea how this could be achieved with a variable frame rate... Iv'e messed around with a few ideas but I am curious if a.) anyone else has a system they use to mitigate this... and b.) why it should probably be a feature in project settings as it would be way better for the engine to deal with this.

    ------------------

    Because some people can't visualize: Check this out. Red pixels "Jitter" sometimes because they stair step. The green pixel doesn't.... cause he is cool, so cool.

    https://dl.dropboxusercontent.com/u/11449416/TestsJitterDemonstration.capx

    Pixel paths and rounding: what this means for you!

  • This sort of came up in another thread recently. It wasn't quite the same thing since it was to do with scrolling, but it's kind of related. Basically if you use letterbox integer scale, point sampling, low-quality fullscreen mode etc. for pixellated display, then scroll to an object moving at something like 40 pixels per second, you get an irregular scroll pattern. 40 doesn't divide neatly in to 60 (the most common display refresh rate) so you get an irregular on - off - off - on - off - on - off style pattern which looks bad (the human eye much prefers regular updates). And the cause of that is maths, not any particular aspect of Construct 2. Then it gets more complicated when you consider different display rates: it will look OK on a 120Hz gaming display, because 40 divides in to 120 (exactly one pixel every three frames).

    One of the issues is pixel rounding rounds the display position but not the actual stored position, which is also why you can get uneven stair-step movements as the X and Y axes update at different times. You can probably resolve that just by making sure the object starts on the same pixel offset on both axes. Then you have to avoid features that adjust the position smoothly as well. Then you also lose the benefits of framerate-independent games: it could well run at double-speed on a 120Hz gaming display.

    Construct 2 is a modern game engine so everything is done by floats with delta-time, which is often useful for smooth, accurate and consistent movement. However older games on much more primitive hardware would have manually adjusted positions as integers on a tick-by-tick basis. You can also do that with events, but it means not using the built-in behaviors. Also I am fairly sure modern displays make this more apparent than it was in the heydey of older consoles - something like the NES would have been running at a tiny 256 x 240, likely on a small CRT display, which were often slightly fuzzy making pixel boundaries less obvious. Run the same game on a 1080p display with perfectly crisp pixels, making each pixel a large clear crisp square, and suddenly you notice things you might not have noticed before.

  • why it should probably be a feature in project settings as it would be way better for the engine to deal with this.

    +1. This would be grand to have if possible.

    Also I am fairly sure modern displays make this more apparent than it was in the heydey of older consoles - something like the NES would have been running at a tiny 256 x 240, likely on a small CRT display, which were often slightly fuzzy making pixel boundaries less obvious. Run the same game on a 1080p display with perfectly crisp pixels, making each pixel a large clear crisp square, and suddenly you notice things you might not have noticed before.

    I just fired up a NES emulator in 1920x1080 res fullscreen to have a look. Object movements and camera scrolling are certainly choppier than the slickness you get with pixel rounding off in C2 but I never saw any stairstep jitter like in ruskul's example file either.

  • I've been annoyed by this kind of jitter since day one of using construct. Would be really good to have option added to make it render movement smoother. And yes, it happens when moving diagonally.

  • Well, what feature would help with this and how would it work? Things like uneven scroll updates are due to maths, not the technology.

  • Well, what feature would help with this and how would it work? Things like uneven scroll updates are due to maths, not the technology.

    That's just it though, I've been thinking on and off for a year or so on this topic and really haven't found a good solution. Many objects have to be synchronized (camera, player, etc...) so that makes it a hard part to make part of the engine right? I mean how is construct supposed to know what you have moving and whats not and which moving objects matter. The only thing I could figure is that some sort of behavior could be applied that looks at the objects last position that it rendered to, and its new render position. If the difference between oldx and newx is greater than oldy/newy, then it only updates y render position when x render position updates and vica versa. This can eliminate stair stepping mostly... I have a project from a year ago that does this... I just stopped doing it though because via events it starts to take a toll setting and resetting object positions twice a frame, storing the old render position and the "real" position... and so on- especially when you have many dynamic objects. As it stands I don't think there is a way to even tell the c2 renderer to render this sprite at an offset (you could do that via an effect I suppose... but again performance can tank if you have many actors) which would be helpful (actually it would be cool to be able to change the objects render setting in game - you know, draw it this big, at this offset, at this color, using this blend mode (x,y,sx,sy,rgb,mode).

    On a side, I was running a nes emulator on my laptop when I was talking about nes games... They have something going on like what I described above to ensure you get that nice pixel line instead of thicker stairstepping lines (like the middle image I provided)

    ---- My current practical solutions via c2

    In general, these days I turn pixel rounding off and then make sure I have my camera position make sure it is only updated if the actor it is following would have had a visual rounding. the stair stepping is usually only obvious when using lower resolutions. Or the character is moving at a steady angle.

    This is a stupid way to do it but I also sometimes make pixel art, scale it up in Photoshop using nearest neighbor (to like 4x or 6x), then I run the game with linear and no pixel rounding at a decent resolution. Its not as crips as pure pixels but You get amazingly smooth everything including scaling the screen, and zooming in and out. It takes longer to make all the assets, and it does less well performance wise, and if you use tilemaps you have to fix that... but you get the gist.

    ------

    Of course, it bears noting as you said, this isn't a c2 specific problem but, as you noted, a problem with trying to emulate crappy hardware of the 80s on a modern platform. Unity has the exact same problem... only it can get worse because you have to deal with fixedUpdate and regular Update syncopation and how the game interpolates position if you are rendering faster than updating fixedUpdate,

    Sorry for the Long read, I'm trying to be brief.... lol

  • Well, what feature would help with this and how would it work? Things like uneven scroll updates are due to maths, not the technology.

    TLDR from previous post:

    You could have an option that when enabled the following would occur:

    compare the difference between the actual position of the object and its new position. (dx,dy)

    if (dx > dy) then only update the render position on the y axis if x is also updating

    else vica verca.

    does that make sense? You would have to track the rounded render positions and were they are force to.

  • Couldn't you just create a family and put all the objects you want in them, then give it instance variables to record their x/y positions and compare them each frame and do any corrections if necessary?

    So you'd shift them at the end of the events, and then restore their positions at the beginning of the events.

    Idk.. just an idea i had.

    But yeah, I only make low-res pixel games, so this sort of thing would be important to solve, as well as any other jitter related issues.

  • Instead of x+1, y+1, how about x+2, y+1, etc?

    X+ random(2)......

    We have one platform engine, shouldn't there be others?

    Or as I've stated before, a bunch of behaviours that can work together.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Couldn't you just create a family and put all the objects you want in them, then give it instance variables to record their x/y positions and compare them each frame and do any corrections if necessary?

    So you'd shift them at the end of the events, and then restore their positions at the beginning of the events.

    Idk.. just an idea i had.

    But yeah, I only make low-res pixel games, so this sort of thing would be important to solve, as well as any other jitter related issues.

    Thats 1 solution in a nut shell, but can be performance costly doing that via events depending on the type of game you are making.

  • Naw, takes 1 event.

    Make a family containing all moving objects.

    Loop through them with a 'for each'

    Set x to x + (x%2)

    Set y to y + (y%2)

    Dunno about the inpact on performance. But i expect it to draw quicker because the n^2 rule.

  • 99Instances2Go

    whats the n^2 rule?

    ...and I'm confused... what would x +=x%2 do to change the stair stepping... I didn't try it but I don't understand why doing this would change it?

  • > Couldn't you just create a family and put all the objects you want in them, then give it instance variables to record their x/y positions and compare them each frame and do any corrections if necessary?

    > So you'd shift them at the end of the events, and then restore their positions at the beginning of the events.

    > Idk.. just an idea i had.

    > But yeah, I only make low-res pixel games, so this sort of thing would be important to solve, as well as any other jitter related issues.

    >

    Thats 1 solution in a nut shell, but can be performance costly doing that via events depending on the type of game you are making.

    Naw, takes 1 event.

    Make a family containing all moving objects.

    Loop through them with a 'for each'

    Set x to x + (x%2)

    Set y to y + (y%2)

    Dunno about the inpact on performance. But i expect it to draw quicker because the n^2 rule.

  • hi pple ... to whom may concern,

    the n^2 rule applies to audio i think... as i read and tested the capx shared in this post im not personally sure if that has anything to do with it. but more a problem of this rule Delta-Time and frame rate independence its not fixed when minimum FPS is under or equaling to 60 FPS however even if you apply the lerp(a,b,1-f^dt) or lerp(a,b,60*dt) still same thing its similar to just adding 0.25 or (60*dt)/4 ...

    if i remember correctly the 2dcanvas cant process faster then the frame rate... so its impossible to not have jitters. even if solved 80% 20% will fail most of times.

    this problem was raised before in other topics around years on forum... the answer was pretty much the same... back then ...

    @ruskul ... instead of substracting 1 substract 0.75 or 0.5 or 0.25 its going to work ... you had it pretty good from start ... but the trail spawning doesn't happen everytime when it moves.. however the movement happens in stairs ... for green and 1 of the reds ... then the other of the reds will brake some times.

    not sure if this old post is the right one but take a look r190 jitter problem maybe you find something useful

    anyway im waiting for the plot-twist on C3 .... i bet will have some cool goodies inside the engine that fixes all this problems and the breaks in physics collisions.

  • http://gamedev.stackexchange.com/questions/18787/how-does-one-avoid-the-staircase-effect-in-pixel-art-motion

    This has a fix, found it while working with unity. Th op also does a better job explaining the problem too.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)