2
\$\begingroup\$

I am working on an low resolution, isometric, pixel game in which several objects move from tile to tile. I do this with this simple interpolation:

let percent = elapsedTime / SPEED

vec.x = start.x + ( (dest.x - start.x) * percent )
vec.y = start.y + ( (dest.y - start.y) * percent )

This seems to work fine except when moving diagonally. It starts to jiggle pretty heavy. Is there a way to smooth this out?

I am using a 32x16 tile size.

edit: added video for better understanding: (video deleted)

edit: for anyone interested. I've solved it using this:

let
percent = elapsedTime / SPEED,
num = Math.round( (dest.x - start.x) * percent )


vec.x = start.x + num
vec.y = start.y + Math.floor(num / 2)

This works only for diagonal movement with 1:2 ratio tiles. I also added some stuff to make it work for all 4 diagonal directions.

\$\endgroup\$
6
  • \$\begingroup\$ Could you please include a minimal verifiable example of your code that exhibits the the phenomenon you're describing? (I am not sure what kind of "jiggling" you mean that's coming from this code.) \$\endgroup\$ Commented Oct 20, 2017 at 22:53
  • \$\begingroup\$ Ok. Added an video since describing it would be way too hard. \$\endgroup\$
    – Mottenmann
    Commented Oct 20, 2017 at 23:41
  • \$\begingroup\$ The video helps. We do still need a minimal, complete, verifiable example so we don't have to make guesses about what could possibly be going on outside of those three lines. \$\endgroup\$ Commented Oct 20, 2017 at 23:44
  • \$\begingroup\$ Hm. The only time i really alter it again is before rendering. But then i only subtract camera offset and round it. My first thought was that the camera was the problem and took it completely out, but wasn't the problem either. It seems to me like interpolating between 2 points and not having them axis aligned or in an 45° angle to each other is the problem. Since only in those situations is no "uneven" movement. \$\endgroup\$
    – Mottenmann
    Commented Oct 21, 2017 at 0:26
  • \$\begingroup\$ Please note that instead of writing your solution inside the question post, the typical way to go is to write an answer. \$\endgroup\$
    – Vaillancourt
    Commented Oct 25, 2017 at 10:38

2 Answers 2

4
\$\begingroup\$

With out code, this might be hard, but if I had to take a guess, your sprites aren't gittering, your camera is. I suspect you are moving the camera either to the exact x or y position both when having it follow your character, on horizontal and vertical movement, this will appear smooth, but when you take diagonal movemnt, since there is no exact x y location for the camera to move to, your scene ends up finding the closest value some how to move everything to.

If you look at the movement you can tell this is probably the case as your camera follows the red dot (your characters position) and thus produces jittery movements (because the red dot produces the same movements on the tiles).

There are three ways to fix this that I've seen. Allow sprite aliasing, so non integer movements can be represented (may not be practical if you aren't using OpenGL or something built off of that). Or possibly limit the directions you can move, such that you can only move in 8 directions. When you move in a diagonal direction both x and y coordinates will update by one. You may also want to slow down diagonal movement to about 70% of the cardinal direction movement speed in order to make sure you can't go faster in one direction than the other. You want to make sure that given a direction, the same number of pixels are added to each side of the screen at once each time you move in that same direction.

You'll notice in a lot of sprite based games they limit movement to either 4 way cardinal direction (manhattan) or 8 way direciton (Chebyschev).

In other games like Zelda this isn't a problem because the camera does not always have to move with the player (another way to solve this problem). For the last method, you have to make sure that one or both are updated at the same time for a given direction (for example, always update x by 1 in traversing one direction, then update y by 1 when you get a chance). updating each by one every other time causes the gittery behavior you see (x gets updated, then y, then x, then y).

This is solved my making sure that your camera moves integers at the proper slope rate for that direction. In your example you move like this (which causes un-even updates):

enter image description here

and you want to move like this:

enter image description here

\$\endgroup\$
1
  • \$\begingroup\$ Thanks. Your answer actually helped me to find the problem. The problem was indeed that it didn't follow the proper slope rate. \$\endgroup\$
    – Mottenmann
    Commented Oct 22, 2017 at 12:48
0
\$\begingroup\$

Your guess is right. I had the same situation. It also involves transforming float coordinates to integer pixel coordinates.

I solved it in my game like this.

If X < targetX { X += V } Else if X > targetX { X -= V } ...// Duplicate the code for Y

Of course V should be actually V/sqrt(2) if you will go in both axis and V if you will go in one. Otherwise your diagonal movement will be faster.

This way when you need to go from p1 to p2, you always go diagonal with 45 degrees

At some point you will reach your targetX or targetY and you will go rest of the way in only one axis. Its not perfect but simpler and worked for me.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .