Visual syncopation in position updates due to pixel rounding

Discussion and feedback on Construct 2

Post » Sun May 15, 2016 11:50 pm

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!

Image

Image

Image
Image
B
33
S
11
G
2
Posts: 564
Reputation: 5,153

Post » Mon May 16, 2016 10:56 am

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.
Scirra Founder
B
398
S
236
G
88
Posts: 24,441
Reputation: 194,661

Post » Tue May 17, 2016 5:40 am

ruskul wrote: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.

Ashley wrote: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.
B
39
S
16
G
6
Posts: 542
Reputation: 7,617

Post » Tue May 17, 2016 5:52 am

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.
My professional Royalty Free Music at Scirra Assets Store
--------------------------------
Specs: i5 2500, 16gb of ram, gtx 770, win 7, Focusrite Scarlett 8i6, Mackie mr8mk2, Alesis 320, browsing the net on chrome.
B
89
S
30
G
22
Posts: 1,985
Reputation: 20,099

Post » Tue May 17, 2016 10:45 am

Well, what feature would help with this and how would it work? Things like uneven scroll updates are due to maths, not the technology.
Scirra Founder
B
398
S
236
G
88
Posts: 24,441
Reputation: 194,661

Post » Tue May 17, 2016 5:37 pm

Ashley wrote: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
Last edited by ruskul on Tue May 17, 2016 5:47 pm, edited 2 times in total.
Image
B
33
S
11
G
2
Posts: 564
Reputation: 5,153

Post » Tue May 17, 2016 5:47 pm

Ashley wrote: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.
Image
B
33
S
11
G
2
Posts: 564
Reputation: 5,153

Post » Tue May 17, 2016 6:20 pm

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.
B
45
S
21
G
65
Posts: 1,118
Reputation: 38,227

Post » Tue May 17, 2016 7:56 pm

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.
Image ImageImage
B
169
S
50
G
174
Posts: 8,331
Reputation: 110,806

Post » Tue May 17, 2016 9:43 pm

Prominent wrote: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.
Image
B
33
S
11
G
2
Posts: 564
Reputation: 5,153

Next

Return to Construct 2 General

Who is online

Users browsing this forum: lkatkins and 11 guests