ID:1098278
 
I've written a quick and dirty implementation of a 3x3 sliding puzzle that can be played on the map or in client.screen.

Playing it on the map automatically adds "slide animations" between the movements because its only 0 to 1 on the x or y value (byond does this automatically).

In client.screen, we're simply setting the screen_loc values and there are no gliding transitions between the movements.

I am wondering how I could achieve this same effect but in client.screen?
Assume pseudo-code because I don't remember variable names or syntax.
var/step_size = round(world.icon_size / world.tick_lag)
var/target_pixel_x = tile.pixel_x + world.icon_size
while(tile.pixel_x + step_size < target_pixel_x)
tile.pixel_x += step_size
sleep(world.tick_lag)
tile.pixel_x = target_pixel_x
This code is really terrible and needs tons of cleaning up, but it works:

    proc/MoveSlide(puzzle_slide/slide, detect = 0)

if(sliding) return



var/y_diff = max(slide.pos_y, zero.pos_y) - min(slide.pos_y, zero.pos_y)
var/x_diff = max(slide.pos_x, zero.pos_x) - min(slide.pos_x, zero.pos_x)

if(slide.pos_x > zero.pos_x)
slide.x_move = -1
if(slide.pos_x < zero.pos_x)
slide.x_move = 1
if(slide.pos_y > zero.pos_y)
slide.y_move = -1
if(slide.pos_y < zero.pos_y)
slide.y_move = 1

if((x_diff == 1 && y_diff == 0) || (x_diff == 0 && y_diff == 1))

var/old_x = slide.pos_x
var/old_y = slide.pos_y
slide.Set(zero.pos_x, zero.pos_y)
zero.Set(old_x, old_y)
slots[slide.pos_x][slide.pos_y] = slide
slots[old_x][old_y] = zero


if(detect)
sliding = 1

slide.target_pixel_x = (x_diff * world.icon_size) * slide.x_move
slide.target_pixel_y = (y_diff * world.icon_size) * slide.y_move

spawn
var/loops = 8
while(loops > 0)
loops--
slide.offset_x += (slide.target_pixel_x / 8)
slide.offset_y += (slide.target_pixel_y / 8)
slide.SetScreenLoc()
sleep(world.tick_lag)
if(loops <= 0)
slide.offset_x = 0
slide.offset_y = 0
slide.SetScreenLoc()


spawn(world.tick_lag * 8)
ShowInClient(src.parent.client, 1,1)
sliding = 0
//ShowOnMap(2,2)
if(detect && DetectWin())
spawn(2*(world.icon_size * world.tick_lag) / 4) Win()
if(detect)
moves++
move_counter.maptext = "[moves]"
return 1
return 0


screen objects are not individually effected by pixel_x (changing pixel_x of an object that is in client.screen does not move it). You must use the colon in screen_loc (ie: x:offset_x,y:offset_y)
In response to Zaoshi
Zaoshi wrote:
Assume pseudo-code because I don't remember variable names or syntax.
> var/step_size = round(world.icon_size / world.tick_lag)
> var/target_pixel_x = tile.pixel_x + world.icon_size
> while(tile.pixel_x + step_size < target_pixel_x)
> tile.pixel_x += step_size
> sleep(world.tick_lag)
> tile.pixel_x = target_pixel_x
>


I think you meant world.icon_size * world.tick_lag for step_size

I decided to just hard-code the step size