Trouble with movement (moving a dynamic tile)

Started by DementedKirby, July 26, 2015, 08:00:11 AM

Previous topic - Next topic
I want to create a dynamic tile that moves to the right in an infinite loop. Here's what I got for code:

local map = ...

function map:on_started()
      local movement = sol.movement.create("straight")
      function loop()
         movement:set_xy(0,96)         
         movement:set_speed(256)
         movement:set_angle(math.pi)
         movement:set_ignore_obstacles()
         movement:set_max_distance(-144)
         movement:start(MovingFloor,loop)
      end
end


The dynamic tile, MovingFloor, is located on 0,96. I want it to move to -256 and then go back to 0,96 to start all over. What am I doing wrong? Hopefully nothing too horribly wrong, lol  :P

By what I see, you never start the movement (you start it in the loop function, but when do you call the loop function for the first time ?). I'm a little rusted on code but it seems good.

Just to test, I changed the code so that it only moves once. Still, nothing:

local map = ...

function map:on_started()

   local movement = sol.movement.create("straight")
   movement:set_speed(256)
   movement:set_angle(math.pi)
   movement:set_ignore_obstacles()
   movement:set_max_distance(-144)
   movement:start(MovingFloor)
end

Your last code should work easily, this is weird. Do you have an error message or an error.txt file?

Yeah, here's the error message:
Error: Failed to load script 'maps/Map4': [string "maps/Map4.lua"]:12: '<eof>' expected near 'end'
Error: In maps/Map4: attempt to call a string value

July 26, 2015, 05:33:25 PM #5 Last Edit: July 26, 2015, 05:40:14 PM by DementedKirby
Okay, now I don't get an error message but the tile only moves 1 pixel to the left. I understand it's supposed to go all the way to -144 from 240, so the movement is considerable and I should be able to see it no question, but it only moves a single pixel.

edit:
Ok, I fixed the problem (accidental negative sign in front of the distance). Now, I want to try and loop this infinitely.

July 26, 2015, 05:53:10 PM #6 Last Edit: July 26, 2015, 08:03:36 PM by DementedKirby
Okay, now I get no error message so at least the syntax is correct. However, I want the movement to loop infinitely. Here's the code:

local map = ...

function map:on_started()
   local movement = sol.movement.create("straight")
   movement:set_speed(64)
   movement:set_angle(math.pi)
   movement:set_ignore_obstacles()
   movement:set_max_distance(100)
   movement:start(MovingFloor)
end


How can I make a tile or sprite or whatever return to its original position after it's finished its movement and then do the movement all over again indefinitely? In an infinite loop? I was able to make the infinite loop. However, there comes a point where the dynamic tile can't go any more to the left so it stops moving altogether (thus stop looping). If I'm able to send it back to a certain point at the beginning of the loop, it should essentially loop forever. I tried using send_MovingFloor(0,96) like one could do with the hero, but that doesn't work. Is there a command like send_hero(x,y,layer) for other map entities?

SUCCESS!!!!
Here's the code that makes it go infinite!

local map = ...

function loop()
   MovingFloor:set_position(0,96)
   local moveback = sol.movement.create("straight")
   moveback:set_speed(64)
   moveback:set_angle(math.pi)
   moveback:set_ignore_obstacles()
   moveback:set_max_distance(64)
   moveback:start(MovingFloor,loop)
end

function map:on_started()
   local movement = sol.movement.create("straight")
   movement:set_speed(64)
   movement:set_angle(math.pi)
   movement:set_ignore_obstacles()
   movement:set_max_distance(64)
   movement:start(MovingFloor,loop)
end


This can create the illusion of conveyor belts like in A Link to the Past. This could also be used for water currents (like the raft area in Link's Awakening). Hope this helps those of you who want to create the illusion! This is under a stream, of course.

I'm not 100% sure, but maybe like this?

local map = ...

function map:on_started()
   local function restartMovement()
     movement:start(MovingFloor)
     movement:set_xy(0,96)
   end
   local movement = sol.movement.create("straight")
   movement:set_speed(64)
   movement:set_angle(math.pi)
   movement:set_ignore_obstacles()
   movement:set_max_distance(100)
   movement:start(MovingFloor,restartMovement)
 
end


I haven't tested it yet, though...

DementedKirby, I suggest to make local the function loop, if it is possible. Just to improve the code.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

Quote from: the bread on July 26, 2015, 08:16:16 PM
I'm not 100% sure, but maybe like this?

local map = ...

function map:on_started()
   local function restartMovement()
     movement:start(MovingFloor)
     movement:set_xy(0,96)
   end
   local movement = sol.movement.create("straight")
   movement:set_speed(64)
   movement:set_angle(math.pi)
   movement:set_ignore_obstacles()
   movement:set_max_distance(100)
   movement:start(MovingFloor,restartMovement)
 
end


I haven't tested it yet, though...

Thanks for the effort but I don't think it will work because you're trying to use the movement variable before creating it first.

Quote from: Diarandor on July 26, 2015, 08:40:51 PM
DementedKirby, I suggest to make local the function loop, if it is possible. Just to improve the code.

Oh! You're right! It's in a specific map so I should make it all local just to be safe. Thanks for pointing that out!

July 26, 2015, 10:30:45 PM #10 Last Edit: July 27, 2015, 07:43:54 PM by froggy77
Shorter


local map = ...

function map:on_started()

  local function restartMovement()
MovingFloor:set_position(0,96)
local m = sol.movement.create("straight")
m:set_speed(64)
m:set_angle(math.pi)
m:set_ignore_obstacles()
m:set_max_distance(64)
m:start(MovingFloor,restartMovement)
  end
  restartMovement()

end


DementedKirby, I like your idea!

Edit: oops,  Frenglish! function "restartMouvement" renamed "restartMovement" without "u"

July 26, 2015, 10:54:24 PM #11 Last Edit: July 26, 2015, 11:08:09 PM by DementedKirby
Thanks! So far, if you move the tile at speed 44 while the stream moves at speed 64 it's almost moving at the same speed as the stream. I still have to see how exactly the stream works in super detail in order to move entities at the same speed that streams move things, but it's pretty much there.

I plan on making this for each dungeon/interior tileset. So far, for testing purposes, I made the conveyor belt in cave palette and it works like a charm.


Just copy/paste that in the cave tileset (use paint.net) and then set each 16x16 tile to traversable (up/left is the up direction, up/right is the down direction, down/left is the right direction, and down/right is the left direction). Then just resize each direction as large as you want and use that code to cycle it. It will give the illusion that it's a conveyor belt. Just place the streams on the conveyor belt (without a graphic) and it will appear that the conveyor belt is moving the hero. The conveyor belts can be resized as large as possible and there will be no pixel hiccups or anything as it moves. Oh! Just make sure to create another floor entity to cover the space the movable floor is going to go beneath so that the player can't see that it's being displaced.

I still don't know what ratio the speed of the stream has to the speed of moving entities, but once I get that down, I can move the entities at the same speed as the stream to give the illusion of forced movement on a conveyor belt. To make it even more ALttP-ish, allow the hero to move, use items, etc. when editing the stream. Hope this helps everyone interested in recreating this aspect of the original game.

I don't understand why you didn't use a simple animated tile instead of a dynamic tile ? Like the waterfall tile, etc. And put your stream with an empty sprite I suppose.

I did, but there was no way of having the animation align with simulating a smooth, infinite movement. The closest I got was having the animation be off by one pixel for one moment. Not good enough. That's why I decided that I had to simply (and literally) move the tile infinitely. The result is so smooth it's flawless. This also works if you want to infinitely loop more difficult things than merely tiles (images, entities, etc).