How to update sprites on a timer

I'm working on making a game that lets sprites move on a timer rather than in response to input. So far, I've done this by having a game loop event check if frame % updateRate is 0, then telling every tile to call updateTile. The tiles that listen for that event then choose an empty adjacent tile to move to, then swaps that tile to themself, and swaps their existing tile to "white".

The problem, I've found, is that since the loop calls an event on every tile in order, when a sprite moves down, they get called twice. I haven't figured out a way to prevent that from happening yet.

Perhaps there could be some way to save a list of sprites that have moved already, and then use that to prevent double actions.

Or maybe there's some way to attach a variable to the sprite itself, that says its most recent update frame, to let it ignore if it gets a second event on the same frame.

Or maybe I need to create a similar sprite, that's something like an "exhausted sprite" which looks the same but doesn't listen for that event, then after a frame replace itself with the regular sprite.

One method been using the frame of a sprite- see my Game Of Life clone. You set the frame of each sprite when they move, then at the end reset them all back to default frame. This kind-of allows you one variable per sprite that can be get and set.

Other method is to create a brute force if else array of numbers. Example:

on GetTileData do
	i = y
	i *= 25
	i += x
	if i==0 then
		n = mapData0
	elseif i==1 then
		n = mapData1
	elseif i==2 then
		n = mapData2
    end
end
1 Like

This works out great for me. I am still animating these sprites and using this method I need to set the sprite's fps to 0, I'm instead using the update function to alternate advancing a frame and move a tile. What I ended up doing is setting the first frame to nothing important and when I swap a sprite in the frame is already 0. Then when all the actions happen I iterate again "advancing" all of them, which tells these sprites to advance their frame by 1. Then, when the frame is 2 or higher I perform the move function.

Edit: I moved "advanceAll" in front of "updateAll" which means the visible frames are 0 and 1 instead of 1 and 2, much cleaner.

Here's a clip of how it's going now:

ezgif-5-7a80e2d299

2 Likes

You want emit “eventName”. No need to tell each tile individually. emit will call the the event on all tiles that implement a handler. It’s designed for this specific purpose and makes a copy of the room tiles in their original order and iterates over that so moving a tile lower or right of its current position doesn’t result in its event handler being called multiple times.

1 Like

Not to take away from Munro’s really clever solution to use the frame to persist state. :exploding_head:

1 Like

Oh hey, that works much better. Thanks!