ID:141199
 
Code:
mob
animate_movement = 0
icon='Mob.dmi'
proc
px_north()
pixel_y += PX_STEP
if(pixel_y > 32)
y++
pixel_y-=32
px_south()
pixel_y -= PX_STEP
var/turf/T = locate(x,y,z)
world << "Name: [T.name] | Density: [T.density]"
if(!T.density)
if(pixel_y < 32)
y--
pixel_y+=32
px_east()
pixel_x += PX_STEP
if(pixel_x > 32)
x++
pixel_x-=32
px_west()
pixel_x -= PX_STEP
if(pixel_x < 32)
x--
pixel_x+=32


Problem description:

Well I've been messing with pixel based movement and it seems that I have ran into a tiny problem, pixel based collision. For my "px_south()" procedure I am checking for density, now my debug message outputs the density and name perfectly, the things I want dense have a true (density) value yet the mob still moves south, which is what is the problem.

So in general the mob still moves south but the condition is never true so the statements below the condition are never being called and yet it STILL moves.

Another problem: It's not so smooth and is quite slow.

Haywire wrote:
>       px_south()
> pixel_y -= PX_STEP
> var/turf/T = locate(x,y,z)
> world << "Name: [T.name] | Density: [T.density]"
> if(!T.density)
> if(pixel_y < 32)
> y--
> pixel_y+=32
>

So in general the mob still moves south but the condition is never true so the statements below the condition are never being called and yet it STILL moves.

You are changing pixel_y before anything else, so, regardless of whatever else happens, the object will at least appear to move, even if it's just that pixel_y keeps getting smaller but loc never actually changes.

However, there is another issue altogether, or so it appears at first. You're checking to see if you are colliding with something, but you're checking your current location's density, so you're already there by the time you're checking the density.

Is this what you wanted? I suppose, if PX_STEP is guaranteed to be small enough, this will let you start to move into the side of a dense turf and then not move completely into it. I wouldn't think that'd be how you'd want it though.

If you want a normal movement system where it checks to see if you can move somewhere and just doesn't move you at all if so, you will need to find out where you will be if you were to move, check to see if the movement is possible, then only make changes if the movement should be a success.

For example...
px_south()
// find out what turf you would be on if you were to move
var/turf/T = get_pixel_step(src, 0, -PX_STEP)
// return if you're not in T and you can't move into it
if(T != loc && !T.Enter(src))
return 0
// change pixel_y and adjust as you did
pixel_y -= PX_STEP
while(pixel_y < -32)
pixel_y += 32
y -= 1

get_pixel_step(atom/A, xStep, yStep)
var
x = A.x; y = A.y
px = A.pixel_x + xStep
py = A.pixel_y + yStep
while(px > 32)
x += 1
px -= 32
while(px < -32)
x -= 1
px += 32
while(py > 32)
y += 1
py -= 32
while(py < -32)
y -= 1
py += 32
return locate(x, y, A.z)

Also, after typing that up and re-looking at what you have, I noticed something else. You have if(pixel_y < 32) which, for moving south, should usually be true and therefor usually trigger. Remember, you're subtracting from pixel_y, so pixel_y will be going into the negatives. You want to check if pixel_y is less than -32. You are going to have the same problem with west.

And one last note about my example: instead of checking to see if T!=loc and !T.Enter(src), you could do the following...
...
if(T!=loc)
if(Move(T))
// edited this too
// forgot the -PX_STEP when I posted at first
pixel_y += 32-PX_STEP
else
pixel_y -= 32


(edit)
Don't forget that you can even make your own pixel_Move() or pixel_step() to go with a potential get_pixel_step() that handles all of this. So you could do something like...
atom/movable/pixel_Move(amount, dir)
var
x = 0
y = 0
if(dir&NORTH)
y = amount
if(dir&SOUTH)
y = -amount
if(dir&EAST)
x = amount
if(dir&WEST)
x = -amount

var/turf/T = get_pixel_step(src, x,y)

// if you're not even moving off the turf, it's obviously a success
if(T == loc)
pixel_x += x
pixel_y += y
return 1

if(Move(T))
pixel_x += x
pixel_y += y
while(pixel_y > 32)
pixel_y -= 32
while(pixel_y < -32)
pixel_y += 32
while(pixel_x > 32)
...

Something like that would allow you to just call pixel_Move(PX_STEP, SOUTH) whenever you want to move south, or pixel_Move(PX_STEP, whatever_direction). This does include diagonal movement though.
In response to Loduwijk
Thank you very much, I see my problem. It was a stupid one, I made the changes before the if condition which seems extremely stupid of me, thanks for the extra info and improvments. You just made a programmer very happy :)

Thank you again.
In response to Loduwijk
Sorry for the extra post but it seems like it's working but only to the extent that it doesn't allow the mob outside the map zone, but it still lets mobs go through dense turfs and objs.

Any idea?
In response to Haywire
What do you have now?

If you still do pixel_x += step-size as the first line of your function that tries to move you, then it's always going to change your pixel location no matter what.

Are you still checking only the turf's density? If so, only turfs will be able to block you.

When you say "go through," does that mean that only the pixel offset keeps changing, or are you able to change your loc by continually walking in that direction as well?

I would suggest you temporarily add a debugging output so that you can see what x,y,pixel_x,pixel_y are at all times. I would just put it in Stat() and do a stat("loc", "[x],[y]") and stat("pixel_x/y", "[pixel_x],[pixel_y]"). This way you can see what exactly is changing when.

If the loc is indeed changing, I'd also add some debug output to the movement functions, if you are using them like I suggested before. This will let you know if a turf is even being tested for movement blockage.