ID:141683
 
Code:
mob/units
animate_movement = 0
proc
_Move(NewLoc)
var/can = 1
var/turf/t1 = get_step(src,dir)
if(loc == NewLoc){Center(src); can=0}
if(t1.density) can = 0
if(locate(/obj) in t1.contents) can = 0
if(locate(/mob/units) in t1.contents) can = 0
if(!can) return 0
switch(dir)
if(NORTH)
pixel_y += speed
if(NORTHEAST)
pixel_y += speed
pixel_x += speed
if(NORTHWEST)
pixel_y += speed
pixel_x -= speed
if(SOUTH)
pixel_y -= speed
if(SOUTHEAST)
pixel_y -= speed
pixel_x += speed
if(SOUTHWEST)
pixel_y -= speed
pixel_x -= speed
if(EAST)
pixel_x += speed
if(WEST)
pixel_x -= speed

_pixel_x = pixel_x+16
_pixel_y = pixel_y+16
if(_pixel_x > 32)
var/turf/t = get_step(src,EAST)
flick("flick",t)
if(t.density) can = 0
if(locate(/obj) in t.contents) can = 0
if(locate(/mob/units) in t.contents) can = 0

if(can)
pixel_x -= 32
_pixel_x -= 32
x ++
loc.Enter()
if(_pixel_x < 0)
var/turf/t = get_step(src,WEST)
flick("flick",t)
if(t.density) can = 0
if(locate(/obj) in t.contents) can = 0
if(locate(/mob/units) in t.contents) can = 0
if(can)
pixel_x += 32
_pixel_x += 32
x --
loc.Enter()

if(_pixel_y > 32)
var/turf/t = get_step(src,NORTH)
flick("flick",t)
if(t.density) can = 0
if(locate(/obj) in t.contents) can = 0
if(locate(/mob/units) in t.contents) can = 0
if(can)
pixel_y -= 32
_pixel_y -= 32
y ++
loc.Enter()
if(_pixel_y < 0)
var/turf/t = get_step(src,SOUTH)
flick("flick",t)
if(t.density) can = 0
if(locate(/obj) in t.contents) can = 0
if(locate(/mob/units) in t.contents) can = 0
if(can)
pixel_y += 32
_pixel_y += 32
y --
loc.Enter()


Move(NewLoc,Dir)
dir = Dir
// world << "[src] is moving!"
_Move(NewLoc)
turf
Click()
var/mob/player/p = usr
for(var/mob/units/u in p.selected)
if(u.loc == src) Center(u)
else{spawn{Keep_Move(u,src)}}
continue
proc
Keep_Move(mob/units/u,turf/objective)
var/stop = 0
var/int = 3
walk_to(u,objective,0,1)
// world << "Start!"
var/px = u._pixel_x
var/py = u._pixel_y
while(!stop)
sleep(2)
if(u._pixel_x == px && u._pixel_y == py)
int --
if(!int)
stop = 1
walk(u,null)
Center(u)
// world << "Stop!"
else
px = u._pixel_x
py = u._pixel_y
int = 3
Center(mob/units/u)
while(u._pixel_x != 16)
if(u._pixel_x > 16)
u._pixel_x --
u.pixel_x --
if(u._pixel_x < 16)
u._pixel_x ++
u.pixel_x ++
sleep(rand(0,1))
while(u._pixel_y != 16)
if(u._pixel_y > 16)
u._pixel_y --
u.pixel_y --
if(u._pixel_y < 16)
u._pixel_y ++
u.pixel_y ++
sleep(rand(0,1))


Problem description:

First of all, is there a better way to do this?

Second of all, the true problem:

So the movement is alright-- the Keep_Move() proc moves the mobs to the clicked location, and stops the movement if the mob could not move 3 times in a row (the purpose of this check is to prevent units from stopping completely just because they bumped on a mob next to them-- which happens several times, when you move a lot of units to a single place), and after they reach their location, they Center() themselves on their final location.

Problem is, sometimes (specially when a large amount of "clogged up mobs" are moved at a time), one mob or two keep pixel_moving in a direction, but stay in a diff location-- as in, the mob stops at locate(5,5,1) but its icon is at locate(7,7,1) for example. After the icon is FAR from where the mob is, it slowly centers itself in the tile-- but you can see how the icon slowly glides through SEVERAL TILES until it centers itself in the mob's current location.

Why does it happen, what should I do, and how can I make it work better?

Thanks!
Gooseheaded wrote:
First of all, is there a better way to do this?

One thing you should do is separate speed into xspeed and yspeed. Then allow those to be positive or negative values. A positive xspeed value moves the unit East, negative, West. North and South for positive and negative yspeed values, respectfully.

That will allow you to turn that whole switch(dir) proc into two lines of code: (it also allows you to do nifty things, like reverse direction by multiplying the speed var(s) by -1)

    pixel_x += xspeed
pixel_y += yspeed


Another thing is your if(pixel_x > 32) blocks can be reduced to a single block if you calculate the unit's turf location based on their new pixx values.

Assuming you're counting from the bottom-left corner and starting your pixel coordinates at 1,1 (which you probably are, since that's the simplest way to go about it in BYOND), you can use the following bit shifting trick to convert the pixx values into turf coordinates. Then it's a simple matter of checking to see if the coordinates where the unit should be match the turf he's on. If not, move him, otherwise continue on.

    X = round(pixel_x>>5)+1
Y = round(pixel_y>>5)+1



Second of all, the true problem:

When two units bump, make one wait for a tick or two, then try and move again. While it's waiting, make it non-dense so the other mob can't bump it (or if you need them dense to bump other player units, add a check to not collide if waiting for a mob to pass by). That way, one mob will trigger a bump, but the other will pass by. If your timing is good, you should be able to make it look natural, since that's what a normal unit would do.

I think your mobs are getting too congested because they're all trying to get there at the same time, which is causing some of your pixel movements to lag back. If you give them some manners, this might solve their problem.