Smooth Tile Movement

by FIREking
A demo showing you how to achieve perfectly timed gliding for smoothest possible movement.
ID:1072528
 
A demo showing you how to achieve perfectly timed gliding for smoothest possible movement. Uses calculations based off of icon size and world.tick_lag to determine how long is necessary to wait for gliding to finish. Also shows you how to "transfer" movable atoms in this situation.

Version 5
-Fixed a timing issue with portals
-Fixed an accuracy problem
-Added robots to show how step() / NPC's use the same movement system for smooth movement

Version 4
-Updated move loop / step logic for better keyboard & wall-sliding handling

Version 3
-Changed how Move() uses functional procs
-Added proper keyboard / diagonal move / blocked wall sliding support
Version 2
-Changed transfers to set x, y, and z instead of using "loc = " because in multiplayer situations it could cause "black outs"
-Added WASD to control movement, just for fun.
That's how the tile movement should respond :)
Feels great.
In response to Fugsnarf
Fugsnarf wrote:
That's how the tile movement should respond :)
Feels great.

Hi,
Is it possible to use it using mouse click? Will the movement be still smooth then?

Thanks,
Regards.
In response to Burael
Burael wrote:
Hi,
Is it possible to use it using mouse click? Will the movement be still smooth then?

Thanks,
Regards.

Yes, try it out.
turf/Click(){walk_to(usr,src)}
It looks like it is moving smoothly, but still it jumps very badly. May be it is not made for isometric or mouse click.

Thanks,
Regards.
In response to Burael
Burael wrote:
It looks like it is moving smoothly, but still it jumps very badly. May be it is not made for isometric or mouse click.

Thanks,
Regards.

I believe the jumping is from the user moving diagonal.
It jumps not only diagonal but all direction.

Regards.
Let's see, Burael, your game uses isometric, click to move, and has 3D rendered stills. I will likely face many of the same challenges in creating my RTS.

Anyway, isometric is a strange creature. I'm sure you already know that the map coordinates are rotated 45 degrees, relative to the default top-down format. That could have a lot to do with how "jumpy" your mobs are when they move around, depending on what you have the client's direction set to.

You could try overriding the default Move() proc like this:
Move(atom/loc,dir)
var new_dir=turn(dir,45)
return ..(get_step(mob,new_dir),new_dir)

That can rotate the axis of move direction for a mob, so that they move more like in top-down, disregarding the map format. You might have already done something like this to the client though. It gets pretty confusing when you have to correct the directions of everything.
You'd need to modify the glide_size math for isometric I think.
@Multiverse7:
That overriding proc is making some strange behavior. When player mob reach at its target it just keep moving around it!
I tried to change the dir before, something like yours but couldn't and I had to fake it.
OffTopic: Will be eagerly waiting to see/play another iso-game in beyond :).

@FIREking:
I also thought that.

Anyways, thanks for the reply and help. I just asked you it is possible or not. I will try it later.

Regards.
Fireking,
I'm using this demo as a library in my games, and I think it's messing up my projectiles.

All my projectiles do the same thing: step,sleep,step,sleep... but this isn't working anymore...

Can you help me?
In response to Gland Mopa
Gland Mopa wrote:
Fireking,
I'm using this demo as a library in my games, and I think it's messing up my projectiles.

All my projectiles do the same thing: step,sleep,step,sleep... but this isn't working anymore...

Can you help me?

Your projectiles need animate_movement = SLIDE_STEPS
Kaiochao pointed out a bit of an issue that ties into the weird behavior you pointed out in Green Orb Quest.

Changing this bit:
        src.move_time = world.time + get_speed_delay(src.speed)

. = ..()

if(.)
src.glide_size = get_glide_size(src.speed)

to:
        . = ..()

if(.)
src.move_time = world.time + get_speed_delay(src.speed)

src.glide_size = get_glide_size(src.speed)

Seems to clear up the issue of key input being dropped from the testing I did.
In response to LordAndrew
LordAndrew wrote:
Kaiochao pointed out a bit of an issue that ties into the weird behavior you pointed out in Green Orb Quest.

Yeah, I could have spent more time and care on the demo. I don't use the code like this in my games, but this was a quick way to demonstrate it working. I'll update it though.
Big update added. Now has diagonal moving, and better keyboard support, as well as wall sliding.
I wonder why did you write
(WEST || a)

since it always is a true and returns WEST value

so why write this:
proc/move_loop()
if(!step(src, (s && (SOUTH || s)) | (w && (NORTH || w)) | (a && (WEST || a)) | (d && (EAST || d))))
if(!step(src, (s && (SOUTH || s)) | (w && (NORTH || w))))
step(src, (a && (WEST || a)) | (d && (EAST || d)))
spawn(world.tick_lag) move_loop()


when you can write this with the same result:
proc/move_loop()
if(!step(src, (s && SOUTH) | (w && NORTH) | (a && WEST) | (d && EAST)))
if(!step(src, (s && SOUTH) | (w && NORTH)))
step(src, (a && WEST) | (d && EAST))
spawn(world.tick_lag) move_loop()


EDIT:
Also, when you have for example: w,a,d down. Then your mob walks north, which is actually correct behavior, but when using icon with multiple direction states, you can see than his icon's direction is south while moving north.

EDIT 2:
I managed to fix the bug, but I think you would fix it more elegently. This is my code:
proc/move_loop()
if(!step(src, (!w && s && SOUTH) | (!s && w && NORTH) | (!d && a && WEST) | (!a && d && EAST)))
if(!step(src, (s && SOUTH) | (w && NORTH)))
step(src, (a && WEST) | (d && EAST))
spawn(world.tick_lag) move_loop()
I wrote it quick but thanks for optimizing that part. It wasn't that important to me.
Hey FIREking,

This question question is about "Smooth Tile Movement". Using this makes missile() go way to fast. How else should I control missile()? I assume it has something to do with FPS = 40, but is there a way around it?

~Ripper man5
In response to Ripper man5
Ripper man5 wrote:
Hey FIREking,

This question question is about "Smooth Tile Movement". Using this makes missile() go way to fast. How else should I control missile()? I assume it has something to do with FPS = 40, but is there a way around it?

~Ripper man5

missile() is one of the oldest functions in BYOND and unfortunately its tied directly to FPS (tick_lag). You'd need to write your own pixel_projectile to replace it... which is actually my next library.
Page: 1 2