[SOLVED] Character Shaking when Moving Diagonally

I've seen some issues with this in other threads, but nothing I've tried has worked. Basically, when the camera doesn't move everything looks fine, but when it does and I'm moving diagonally my character shakes slightly, which is of course unwanted.

Step Event
GML:
inputDirection = point_direction(0, 0,keyRight - keyLeft, keyDown - keyUp);
inputMagnitude = (keyRight - keyLeft != 0) || (keyDown - keyUp != 0);
hSpeed = lengthdir_x(inputMagnitude * speedWalk, inputDirection);
vSpeed = lengthdir_y(inputMagnitude * speedWalk, inputDirection);
x += hSpeed;
y += vSpeed;
Draw Event
GML:
draw_sprite_ext(sprite_index, image_index, floor(x), floor(y), image_xscale, image_yscale, image_angle, image_blend, image_alpha);
The camera is set to follow the player's x and y coordinates. Camera's set view code in the step event
GML:
camera_set_view_pos(cam, floor(x) - viewWidthHalf, floor(y) - viewHeightHalf);
I've tried flooring my x and y positions of my player, and while it no longer shakes, it causes my diagonal speed to be too fast.

Any help I could be very much appreciated.
 
Last edited:

TheouAegis

Member
Have you been flooring your coordinates in the Draw Event since day 1? Typically it's the player that doesn't shake while everything else in the room does when a camera is following the player.

What's your view's size?

Why don't you set the camera to follow the player explicitly using camera_set_view_target()?

The camera is set to follow the player. Camera's set view code


GML:

camera_set_view_pos(cam, floor(x) - viewWidthHalf, floor(y) - viewHeightHalf);
What event is this in?
 
Have you been flooring your coordinates in the Draw Event since day 1? Typically it's the player that doesn't shake while everything else in the room does when a camera is following the player.

What's your view's size?

Why don't you set the camera to follow the player explicitly using camera_set_view_target()?


What event is this in?
The draw events have been floored since day 1, but not in the camera's step event (which is the event you inquired about).
My view size is 1280 x 720.
I haven't used camera_set_view_target() because for one I'm not very familiar with that function and manipulating the x and y coordinates with it since they are not parameters.
 

NightFrost

Member
Is your view the same size as your application surface? Scaling up using different sizes has some consequences which become problematic when for example you're rounding (round/ceil/floor) positions.
 
Is your view the same size as your application surface? Scaling up using different sizes has some consequences which become problematic when for example you're rounding (round/ceil/floor) positions.
I have the viewport set to twice what the application size, but the problem persists even if I set them to be the same thing.
 

NightFrost

Member
I have the viewport set to twice what the application size, but the problem persists even if I set them to be the same thing.
Hm, so you're actually scaling down from room to application surface? Never seen that before, but the same probably applies.

In case of this upscaling technique (and downscaling I guess) the problem arises from disrepancies in positions. The camera, which frames your view, is positioned in room coordinate space. When you floor its position, it floors to integers in room coordinates. However, I've noticed draws behave differently. A draw first interpolates the coordinates to application surface position when there's a difference between view and application surface size. Only then, when they are in application surface coordinate space, they get the floor applied.

For example, if player's x-position is 5.7 and you floor camera's x-position from it, you'd get 5. If your application surface is five times larger (like, for a big pixelart upscale), the draw position to app surface is 5.7 * 5 = 28.5 and you then floor it to 28. The problem is, in your upscaled frame of observation the camera position is 5*5 = 25, which gives a 3-pixel difference with a position that was supposedly directly derived from player coordinates.

When you floor player coordinates before deriving camera position and drawing, the fractions get dropped and you end up with identical positions. However, as the coordinate rounding now aligns everything to pixels, the entire upscaling process becomes pointless. One might just as well set app surface equal to view, then do a single stretch when drawing app surface to display.

Well, the TL;DR of this is, you don't floor/round/ceil those positions when using view and app surface to do scaling or you get the shakes (exception: all the things are moving with only integer values forever, so there's no fractions to mess things up). Try dropping the floors and see if the shaking stops. If it does not, scaling is not the cause, something else is.
 
When you floor player coordinates before deriving camera position and drawing, the fractions get dropped and you end up with identical positions. However, as the coordinate rounding now aligns everything to pixels, the entire upscaling process becomes pointless. One might just as well set app surface equal to view, then do a single stretch when drawing app surface to display.

Well, the TL;DR of this is, you don't floor/round/ceil those positions when using view and app surface to do scaling or you get the shakes (exception: all the things are moving with only integer values forever, so there's no fractions to mess things up). Try dropping the floors and see if the shaking stops. If it does not, scaling is not the cause, something else is.
Well, dropping the floor on both the player's draw event and the camera's position did the trick and the player no longer shakes, so thanks! The only thing I don't understand is why the shaking still happened when I had both the application surface and viewport set to the same dimensions, but either way I suppose it doesn't matter now.
 
Top