ID:2090492
 
(See the best response by Ter13.)
I use glide effect to smooth out my movement, so the deal is that diagonal movement lags while cardinal movement is totally smooth how to deal with this my idea is to dynamically change the glide_size on each step regarding on the movement direction.

Any better solution??
Let's do some math.

Diagonal distances are bigger than horizontal distances. Why? Because an old greek dude who talked about triangles and little boys a lot said so.

W = 32
H = 32
D = ?

W = A
H = B
D = sqrt(A*A + B*B)

W = 32
H = 32
D = sqrt(32*32 + 32*32)
D = sqrt(1024 + 1024)
D = sqrt(2048)
D = 45.25483399593904156165403917471


Smoothing out the glide using (probably my snippets) requires either accounting for the distance that we're going to be gliding, or telling BYOND to automatically account for it.

There is a way to tell BYOND to treat horizontal and diagonal distances as the same for gliding. It's an appearance flag called LONG_GLIDE.

atom/movable
appearance_flags = LONG_GLIDE


If you do not want to use LONG_GLIDE, you need to increase the speed of the glide_speed based on the diagonal properly.
Yeah I know Pythagoras was the guy ;)
I would prefer not using LONG_GLIDE since diagonal movement becomes faster (if I'm getting it right)

so I need to update the glide size on each step??
right now my idea is this glide_size=step_size*(1/fps)
but I guess step size is always constant and does not account movement direction.
So I will need a distance var right?? to get the euclidean distance

So how do you do this?? do you have a library I could look up??
My solution is overloading the Move() proc and check there if the step that is to be taken is diagonal or cardinal and change the glide_size there.
Is there a better solution to that??
Best response
I would prefer not using LONG_GLIDE since diagonal movement becomes faster (if I'm getting it right)

It doesn't make diagonal movement faster, it makes diagonal movement take the same amount of time to glide as horizontal movement.

This means that your delays for diagonal movements will wind up having to be longer than for horizontal movements unless you use LONG_GLIDE.

My solution is overloading the Move() proc and check there if the step that is to be taken is diagonal or cardinal and change the glide_size there.

Yep. That's exactly the solution, but your math is wrong.

Dilating the movement delay based on whether it's a diagonal move (will cause some inaccuracy in the delays that will make smooth gliding impossible, which is why I don't recommend it.)

#define SQRT2 sqrt(2)
#define ceil(x) (-round(-(x)))

atom/movable
var
move_delay = 0
tmp
last_move = 0
next_move = 0
Move(atom/NewLoc,Dir)
var/mdelay = move_delay
if(world.time<next_move) return 0
glide_size = TILE_WIDTH / max(ceil(move_delay/world.tick_lag),1)
if(get_dist(src,NewLoc)==1)
var/d = get_dir(src,NewLoc)
if(d&d-1)
mdelay *= SQRT2
. = ..()
last_move = world.time
next_move = world.time+mdelay


Instead, I'd really recommend using LONG_GLIDE. It's just cleaner:

atom/movable
appearance_flags = LONG_GLIDE
var
move_delay = 0
tmp
last_move = 0
next_move = 0

Move(atom/NewLoc,Dir)
if(world.time<next_move) return 0
glide_size = TILE_WIDTH / max(move_delay,world.tick_lag) * world.tick_lag
. = ..()
last_move = world.time
next_move = world.time+move_delay
Updated my answer. It shows the two implementations.
what purpose does move_delay serve in the 2nd snippet?? I mean you never update it except if it has something to do with .()=..()
The movement delay prevents you from moving while you are in a glide. This keeps gliding smooth.

If you don't use a set movement delay, you don't have a set period of time to glide over. Gliding requires distance and time, because glide is fundamentally distance over time.

If you don't block movements for the span of time that you are gliding, the last glide will instantly jump to the endpoint and a new glide will start, causing your game to look like a jumpy, jittery piece of shit.

If you want smooth gliding, you need to inform the system of how long the movable takes to move from one tile to the next. Hence, you set move_delay to the duration that the movable takes to go from one tile to another. I'm really fond of 2.5 as a move_delay, because it's exactly 4 tiles per second.
Ok I got it also one last thing when moving diagonally shouldnt movement have a longer delay?? is that adressed with LONG_GLIDE or should I also increase the delay when there is a diagonal movement??
when moving diagonally shouldnt movement have a longer delay??

Reread the post where I showed the code implementation for both approaches. Your question is answered in that post. The first example increases the movement delay by multiplying against the square root of 2. But this is going to cause a small amount of visual jitter to diagonal movement, so it won't be as smooth as using LONG_GLIDE.

is that adressed with LONG_GLIDE or should I also increase the delay when there is a diagonal movement??

LONG_GLIDE only affects the speed of the glide by internally multiplying the glide_size by the square root of 2 when diagonally gliding. move_delay is not part of the built-in system, so LONG_GLIDE cannot possibly affect the movement delays.

LONG_GLIDE makes diagonal glides take the same amount of time as horizontal and vertical glides. That's all it does.

If you want to have diagonal movements take longer, my first snippet shows you how to adjust the movement delay to account for this. If you don't want diagonal movements to take longer, my second snippet shows you how to implement perfectly smoothed movement.
just tested the 1st implementation cardinal movement walks great the only issue is diagonal movement which has a slight lag
diagonal movement which has a slight lag

Dude. Read.

Ter13 wrote:
Dilating the movement delay based on whether it's a diagonal move (will cause some inaccuracy in the delays that will make smooth gliding impossible, which is why I don't recommend it.)

Ter13 wrote:
But this is going to cause a small amount of visual jitter to diagonal movement, so it won't be as smooth as using LONG_GLIDE.

EDIT: I'm really trying not to be rude, but it's absolutely infuriating when you explain something multiple times and then ask me to walk you through it step by step because you don't want to read something longer than a tweet.

Não tenho nenhum problema usando português se você não entender. Apenas me diga que você não está entendendo primeira e posso ajustar. Barreira da língua não é o problema.
lol no I'm not Portoguese yeah I was just stating the obvious after testing it for myself.
Well I'm thinking about calling walk_to again inside the Move() with diferent step_lag if there is a direction change from cardinal to diagonal and vice versa
walk_to again inside the Move()

Yeah, that's going to make the problem worse.

You might be able to fix the jitter a little bit by clamping the movement delay to force it to be a multiple of the tick_lag.

#define SQRT2 sqrt(2)
#define ceil(x) (-round(-(x)))

atom/movable
var
move_delay = 0
tmp
last_move = 0
next_move = 0
Move(atom/NewLoc,Dir)
var/mdelay = move_delay
if(world.time<next_move) return 0
if(get_dist(src,NewLoc)==1)
var/d = get_dir(src,NewLoc)
if(d&d-1)
mdelay = max(round(mdelay*SQRT2,world.tick_lag),world.tick_lag)
glide_size = TILE_WIDTH / max(mdelay/world.tick_lag,1)
. = ..()
last_move = world.time
next_move = world.time+mdelay


That MIGHT work. I'm not 100% sure, but you might see some strangeness. It's better, but still not perfect. Still recommend LONG_GLIDE. It'll just look and feel better and be a lot easier.
Worst case scenario I'll use my custom pathfinding and movement procs, although I'm trying to avoid it because it may cause some bugs.

I will play around a little bit though.
Well my solution works well. I mean no lag at all
I hope my code is readable :) ok edited the code to make it readable ;)

mob/Move()
var/DIR=get_dir(src,get_step_to(src,t,0)) //Direction between src and the next steps location
if(DIR==EAST||DIR==WEST||DIR==SOUTH||DIR==NORTH
if(speed<>1
src.glide_size=16*world.tick_lag;
speed=1;
walk_to(src,t,0,1,16);
return 0;
else
if(speed<>sqrt(2))
src.glide_size=16*sqrt(2)*world.tick_lag;
speed=sqrt(2);
walk_to(src,t,0,sqrt(2),16);
return 0;
..()

t is the target btw
mob/Move() //move has arguments. This is broken.
var/DIR=get_dir(src,get_step_to(src,t,0)) //this is broken. get_step_to has no place in Move().
if(DIR==EAST||DIR==WEST||DIR==SOUTH||DIR==NORTH) //this is bad. DIR&DIR-1 returns true if the direction is diagonal. Don't use a bunch of or statements to test for cardinality.
if(speed<>1) //this is broken logic.
src.glide_size=16*world.tick_lag; //your math is wrong.
speed=1; //this is broken logic.
walk_to(src,t,0,1,16); //walk_to has no place in Move().
return 0; //this is broken logic.
else
if(speed<>sqrt(2)) //this is broken logic.
src.glide_size=16*sqrt(2)*world.tick_lag; //your math is wrong.
speed=sqrt(2); //this is broken logic.
walk_to(src,t,0,sqrt(2),16); //walk_to has no place in Move().
return 0; //this is broken logic.
..() //this is broken logic. Move() must return a value.


Every line in that example is broken in some way.

I strongly suggest you take a look at the code I wrote.

pathfinding procs have no place in Move(). Ever.
yeah there isnt any pathfinding in Move but if I'm to use a custom movement I need a pathfinding algorithm I never said it goes in Move().

Anyway the above is just a draft, but works just fine the only problem appears when there is a change of direction it takes a fraction of a second to activate the new walk_to
well I'll use the LONG_GLIDE for now and then after everything working I'm going to change it to my custom movement
yeah there isnt any pathfinding in Move but if I'm to use a custom movement I need a pathfinding algorithm I never said it goes in Move().

No, you don't understand. step_to, get_step_to, and walk_to are all pathfinding procs. They have NO place in mob/Move().

You know what... I give up. Like herding cats.
lol I love your expressions :D
anyway I'm doing some patches and some messed up stuff that will god-willingly work
like herding cats
Lol'd.
Page: 1 2