Log In  

Cart #dariusdans8dirmove-1 | 2020-05-27 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

This is my code snippet for 8-dir movement in PICO-8. There are some in BBS like this but I think I have something to add here because:

1 - It doesn't move faster when going diagonals;
2 - It can move at speeds below 1 pixel/frame (sub-pixel movement);
3 - And most importantly: IT DOESN'T HAVE ANY ANNOYING JITTERING (the staircase effect)!!!

Feel free to scrutinize my code and give me any constructive tips. I am still getting started with PICO-8 and Lua.

P#77200 2020-05-26 00:38 ( Edited 2020-05-27 03:35)

This is fantastic!

P#77231 2020-05-26 17:51

Either my memory is wrong or browser/pico8 changed, but now the movement is jittery. Not an up-and-down staircase effect but a back and forth along the diagonal.

P#78352 2020-06-21 02:29

"Either my memory is wrong or browser/pico8 changed, but now the movement is jittery. Not an up-and-down staircase effect but a back and forth along the diagonal."

Not back and forth, but maybe stuttering. This is not an issue. It happens because the speed on the demo is 0.75. If speed is below 1, it means sometimes you don't move this frame. The position is drawn to the rounded values of x and y, which are floating point numbers.

In fact, if speed is equal to any non-integer value, you might think the character's movement is stuttering, like the framerate is inconsistent, when in fact a non-integer speed only means that you don't move a fixed amount of pixels each frame, which can make you feel unconfortable, but mathematically is correct.

P#78524 2020-06-25 23:22 ( Edited 2020-06-25 23:33)

I probably don’t know the right technical terms but that’s not what matters — I see is a visual glitch where the movement goes to some pixel, then back, then there again.

(also if we’re being pedantic, numbers are fixed-point not floating-point! :)

P#78737 2020-07-01 04:17

@merwok, I dunno what to tell you. I even recorded the movement of the pixel in video and watched it frame by frame to try to detect any backsteps.

The demo below is the exact same but here speed is equal to sqrt(2). This makes xspd and yspd equals to 1 when going diagonals, which is very pleasant to the eye, and equals to 1.41 when going horizontal and vertical, which causes a stuttering effect.

Cart #zabadokafe-0 | 2020-07-04 | Code ▽ | Embed ▽ | No License

P#78872 2020-07-04 04:13 ( Edited 2020-07-04 04:15)

Thanks, I’ll have to try it with a sprite!

P#79856 2020-07-24 14:21

I think this is an intractable problem, because of the resolution and have decimal position values.

Perhaps it would be possible to smooth both vertical / horizontal movement and diagonal movement simultaneously, if you normalized the movement based on frames, so the movement rounding comes out right, but perhaps not. It seems like you'd be limited to a specific speed to get the numbers to round right.

My conclusion is that it is just a limitation of p8 and should be used in a game as a trick for gamers to use to their advantage.

P#104847 2022-01-11 23:29

If you set the speed = 1
and spdx and spdy = .75
it creates an even horizontal / vertical and diagonal movement, though vertical movement is not as smooth as the unnormalized movement.

while .75 is not precise in terms of normalization, i think it's close enough and helps create smoother pixel location rounding.

at 30fps though, i still think the unnormalized movement looks better.

P#104849 2022-01-11 23:35 ( Edited 2022-01-11 23:43)

How about this, @dariusdan and co ? Instead of moving in floating point, use the timer to handle diagonal moves. 100% U D L R and 75% for UL UR DL DR.

P#104894 2022-01-12 15:37

@dariusdan this works great! I tried making my own code to normalize diagonals and get rid of jittering, but it only works most of the time. Sometimes when going SW or NW, the jittering returns, but not always. I don't know why. Here is my code:


function _init()

function _update()

 if (btn(⬆️)) dy-=p.spd
 if (btn(⬇️)) dy+=p.spd
 if (btn(⬅️)) dx-=p.spd
 if (btn(➡️)) dx+=p.spd

 --normalized diagonals
 if dx*dy !=0 then

 --anti-jittering/smooth diags
 --idea from lazy devs academy
   --on first diagonal frame
   --set subpixel position
   --to center of the pixel  
 if diag and not 
    prev_diag then


 --update position

function _draw()

I'm jealous of your consistent diagonals. I'm trying to reverse engineer your code, but I'm pretty new to coding and can't quite understand it. Would you consider creating a bare-bones version that optimizes for readability for noobs? It could be a valuable resource for us new developers.

P#129628 2023-05-11 07:08

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2023-12-11 12:12:49 | 0.038s | Q:29