Basically I hold a variable called pmove that holds the fractional float value of movement.
Its works by basically adding the movement speed onto the current pmove, then rounding it down to get the number of pixels actually moved. The pmove is subtracted by the number of pixels moved. This allows a floating pmove to build up and jump an extra pixel every few steps, depending on the speed. It's a bit difficult to explain without any visual aids, but just trust me.
The rate of these extra pixels is typically fast enough and small enough that you'll never notice in animation, but will provide a very simple method of calculating fractal pixel movements.
This is basically how my current movement system looks right now. On top of the fractal pixel movement, it also includes a simple method of turning verticle and horizontal movement commands into diagonal movement, which I find to be very odd why this isn't a default behaviour.
#define CARD 0
#define DIAG 1
mob
var
vert = 0
horz = 0
speed = 4 //Pixels per move. This can also be a floating value.
pmove = 0 //The remainder of subpixel movement
move = 0 //The amount of pixels being moved at that instance.
list
vertstack = list()
horzstack = list()
proc
moveDir(d)
switch(d)
if(CARD) pmove+=speed
if(DIAG) pmove+=(speed/ROOT2)
move = round(pmove)
pmove -= move
return move
moveStep(d)
if(vert&&horz)
if(!moveDir(DIAG)) return
else
if(!moveDir(CARD)) return
step(src,d,move)
startMove()
moving = 1
while(length(vertstack)||length(horzstack))
if(length(vertstack))
switch(vertstack[length(vertstack)]) //Checks the very last element in the list.
if("N") vert = 1
if("S") vert = 2
else vert = 0
if(length(horzstack))
switch(horzstack[length(horzstack)])
if("E") horz = 4
if("W") horz = 8
else horz = 0
moveStep(vert+horz)
sleep(world.tick_lag)
moving = 0
verb
moveNorth()
set hidden = 1
vertstack.Add("N")
if(!moving) startMove() //Only if the mob isn't already moving does it call this function.
moveSouth()
set hidden = 1
vertstack.Add("S")
if(!moving) startMove()
moveEast()
set hidden = 1
horzstack.Add("E")
if(!moving) startMove()
moveWest()
set hidden = 1
horzstack.Add("W")
if(!moving) startMove()
stopNorth()
set hidden = 1
vertstack.Remove("N")
stopSouth()
set hidden = 1
vertstack.Remove("S")
stopEast()
set hidden = 1
horzstack.Remove("E")
stopWest()
set hidden = 1
horzstack.Remove("W")
I hope that this was a somewhat informative method of creating precise, responsive pixel movement controls. If you see any way to improve this or clean it up, I'd love to hear your comments.
10.8.2015 EDIT: Due to some latency being created by the original proc, I rewrote how I handled the actual verbs. Instead of just dictating the direction, I had each verb add or remove an identifier from a makeshift call stack for each vertical and horizontal direction. The code checks for the very last element in the list, being highest on the stack.
The verbs now no longer require them to be repeating to function properly, all they do is simply update the direction of movement and only if the mob isn't already moving, does it call the startMove() proc.
The reason for the call stack was to prevent the bug where someone would be holding down the left and right buttons for example and when letting go of the button in the direction they were currently going, it would not automatically call them to start moving the other direction. Doing it this way fixes that and adds a lot more responsiveness to the code.
I hope this update serves some people's ideas well.