Animated tiled background

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By piever
:warning: Old Version Published before Godot 3 was released.

Hi!
I’m a bit of a newcomer to Godot (and game development in general) and I’m struggling on a simple issue. I have an example sky background for a game, which I can repeat tiling all the space I need using Region and Repeat (solution found here). I’d like to animate the sky a bit and I have about 4 frames I’d like to cycle through which I though of doing using animated-sprite. However animated-sprites dont’ have the Region and Repeat option to tile space. The only solution I could find was to do a TextureFrame and I would keep setting a different texture (say at 4Hz) from code, but this feels very suboptimal and I’m afraid could slow down the game.
What’s the recommended solution? Is there something basic that I’m missing?

That could be solved using custom drawing for sure (with a script), but I don’t have a friendly solution using only nodes (It would involve AnimationPlayer, AtlasTexture and TextureFrame).

Zylann | 2017-05-26 17:09

Thanks for the tip! I’ve tried to play a bit with custom drawing and came up with this: is this what you had in mind or there are more elegant/performant solutions? The main thing that I’d like to improve is the manual typing of what to preload. I don’t seem to be able to do it in a loop because preload requires constant strings.

var i = 0
var texture
var frame1 = preload("res://frames/bg1.png")
var frame2 = preload("res://frames/bg2.png")
var frame3 = preload("res://frames/bg3.png")
var frame4 = preload("res://frames/bg4.png")
var frames = [frame1, frame2, frame3, frame4]


func _draw():
    for pt in pts:
	    draw_texture(texture,pt)

func _on_Timer_timeout():
	i = (i+1) % 4
	texture = frames[i]
	update()

piever | 2017-05-26 18:46

:bust_in_silhouette: Reply From: genete

Have you seen this?

Oh, good solution! If you have a linear tile-based animation that does the trick nicely :slight_smile:

Zylann | 2017-05-27 16:25

Thanks for the link, it seems very interesting!

piever | 2017-05-27 17:20

For tilemaps you can use AnimationPlayer on the region rect of the animated tiles, if you have many tiles just save the animation and do some copy-paste on the tres to make it faster.

https://twitter.com/_eons/status/786383684110737409

eons | 2017-05-29 11:14

I managed to implement the tutorial linked by genete, but I’d also like to understand what you’re proposing, because implementing more complicated animations in shader language would probably be tricky. Could you give a more step by step description?
To create a Tileset, should I put a different sprite for every frame or should I do a sprite with multiple frames from an atlastexture? How would I continue from there? I’m not exactly sure what properties should I animate with animation player/ how to use it on a region rect?
If you don’t mind sharing the code for the animation you did I can maybe work my way from that.

piever | 2017-05-29 11:58

I have made so many experiments that I don’t know how made those exactly, but basically you can do discrete animation on the region rect of each tile (key), and is animation, zero code.

Here it can be seen better:
https://twitter.com/_eons/status/785876343271530496

A way to make it simple, is to organize the tilemap, all tiles with animations at the same X or Y pixel distance, animate one, the rest is simple just changing X or Y on the others at the same “distance” on the text file (if you want to do it faster).

If is consistent, it can be done with Tween and a loop too, but any change on the tilemap will require code fix, easier with Animation resource (even for a tileset designer).

I have tested with continuous animation and is good too, just not many uses (because the tileset needs to be made for that motion).

eons | 2017-05-29 14:18

Ahhh! I get it now, I can simply have all frames in one sprite and animate Region to select a different one for different keyframes. That’s pretty smart, thanks for the idea!

piever | 2017-05-29 15:12

:bust_in_silhouette: Reply From: Jocquijoke

Hi,

I know it has been a while, but I needed this too and came up with this solution, using a simple script attached to a tilemap. This requires only one texture and no shader. Note that the texture must be a sequence of all the frames (so a 64x32 image for 2 frames of size 32x32 for example).
The region associated with the tileset will be ((0, 0), cell_size) and we want to translate that in time. So we just create a timer (its wait time will be the time between two consicutive frames) and attach this script to the tilemap:

extends TileMap

var nb_frames: int = 0
var current_frame: int = 0

func _ready():
	nb_frames = tile_set.tile_get_texture(0).get_size().x / cell_size.x

func next_frame():
	current_frame = (current_frame + 1) % nb_frames
	tile_set.tile_set_region(0, Rect2(Vector2(current_frame*cell_size.x, 0), cell_size))

func _on_Timer_timeout():
	next_frame()
 

Of course don’t forget to connect the timer to your tilemap.

I hope it can help!