Placing an Animated Sprite onto a TileMapLayer

Godot Version

4.4.stable

Question

I have been able to make an AnimatedSprite2D that changes animation speed based on wind speed. I tried to write my code to where it places this animated sprite onto the tilemaplayer. However, another error happened as a result. The ‘preview’ version of the wind turbine shows up hovering over the mouse AND at the center of the map. When I left click to place the building, the ‘preview’ version of the tile behaves the way I intended, but the ‘built’ wind turbines are static. I have no idea why this is, but I suspect there is only a small change in code needed. The link below is the video showing what I am experiencing:

Code below:

extends TileMapLayer

@onready var terrain: TileMapLayer = $"../Terrain"
@onready var buildings: TileMapLayer = $"../Buildings"
@onready var wind_turbine: AnimatedSprite2D = $Wind_turbine

var width: float = Globals.width
var height: float = Globals.height

var source_id: int
var build_status: bool = false
var building_vector: Vector2i
var mouse_position: Vector2i
var old_mouse_position: Vector2i
var alt_id: int = 0

var solar_qty: int = 0
var wind_qty: int = 0

func _ready():
	#Ensures no building is shown on the mouse pointer on startup
	source_id = -1
	#Makes the preview version of the tile the default setting
	modulate.a = 0.5

func _on_thermal_solar_pressed():
	build_status = true
	source_id = 0
	building_vector = Vector2i(5, 13)

func _on_wind_turbine_pressed():
	build_status = true
	source_id = 0
	building_vector = Vector2i(0, 4)
	wind_turbine.visible = true

func _on_demolish_pressed():
	build_status = true
	source_id = -1

func _input(event: InputEvent):
	#Creates preview version of building sprite, hovers on mouse position
	if event is InputEventMouseMotion and build_status == true:
		#Gets the new coordinates of mouse pointer when mouse moves
		mouse_position = local_to_map(get_local_mouse_position())

		#Erases tile in old position, so the building preview 'follows' the mouse
		if old_mouse_position != mouse_position:
			erase_cell(old_mouse_position)

		#Places the building tile onto the grid and stores the new tile coordinates
		set_cell(mouse_position, source_id, building_vector)
		old_mouse_position = mouse_position
	
		#Indicates if tile is occupied
		if buildings.get_cell_atlas_coords(mouse_position) != Vector2i(-1, -1):
			modulate = Color.RED
		else:
			make_transparent()
		
	if Input.is_action_pressed("click"):
		#Prevents building on an occupied space
		if buildings.get_cell_atlas_coords(mouse_position) != Vector2i(-1, -1):
			make_transparent()
		#Places building on Buildings tilemaplayer
		elif build_status == true and source_id != -1:
			if building_vector == Vector2i(0, 4):
				buildings.set_cell(mouse_position, 3, Vector2i.ZERO, 1)
			else:
				buildings.set_cell(mouse_position, source_id, building_vector)
			erase_cell(mouse_position)
			build_status = false
			match building_vector:
				Vector2i(5, 13): solar_qty += 1
				Vector2i(0, 4): wind_qty += 1
			print("Solar qty: " + str(solar_qty))
			print("Wind qty: " + str(wind_qty))
		#Erases atlas coordinates at tile
		if build_status == true and source_id == -1:
			match buildings.get_cell_atlas_coords(mouse_position):
				Vector2i(5, 13): solar_qty -= 1
				Vector2i.ZERO: wind_qty -= 1
			buildings.erase_cell(mouse_position)
			erase_cell(mouse_position)
	
	if Input.is_action_pressed("right_click"):
		build_status = false
		erase_cell(old_mouse_position)

func make_transparent():
	modulate = Color.TRANSPARENT
	modulate.a = 0.5

Does the tile you set in the tilemap animate? You are setting a tile in the tilemap and if it isn’t an animated tile then it won’t animate

As I stated in my original post, I made an AnimatedSprite2D. My intention is to place that animated sprite onto the tilemaplayer and the animation should start from there. That’s why I have “buildings.set_cell(mouse_position, 3, Vector2i.ZERO, 1)”

However, it doesn’t work that way for some reason, as shown in the video that the google link takes you to.

AnimatedSprite2D and the tiles in TileSet that populate a TilemapLayer are two different things. You can make animated tiles for a tileset, but as far as I understand you need to make those separately, you can’t just plug an AnimatedSprite2D in.

What you can do is float an AnimatedSprite2D over a tilemap. Or float lots of them. You don’t need to bake them into the tilemap as tiles if you don’t want to.

Shoot, sounds like the AnimatedSprite2D makes things too complicated then. I do know how to animate the tiles in a TileSet, but I want the wind turbines to be facing different directions based on the wind direction, as well as change the speed of the animation based on the wind speed. What syntax do I use to do both?

AnimatedSprite2D and TilemapLayer are just abstractions around the underlying 3D hardware. They’re modeled vaguely on home computer/console hardware that peaked between the 8bit and 16bit eras, but they’re software emulation of that style of hardware.

You can put hundreds or thousands of animated sprites in a scene, and it should perform just fine.

If you want to do this with animated tiles, you should be able to, but you’ll have to set the tileset up for it. If you want to use tiles and don’t want the duplication of your ghost preview in a sprite, you could make a separate tiny TilemapLayer for the preview and move that around with the mouse, rather than using a sprite.

You could also do this by placing sprites.

Personally, if it were me, I’d be tempted to do it with a 3D layer overlaying the map; you could use an AnimatedSprite3D and control rotation around y to make the sprite turn with the wind. You could use a second Sprite3D rotated 90 degrees in y (so they make a + shape if you look down from the top) to give your windmill some depth. That would give you smooth 360 degree rotation so the wind could come from anywhere and your 2D windmills would turn to face it properly.

Understood. I already have a separate tilelayer for the preview and another one for the buildings to be ‘built’ on.

I decided to just resort to making the animation with the tilemap, since that’s what I’m more familiar with:

The question I have tho is what syntax do I use to change the ‘built’ buildings to the animation shown in 1, 2, 3, or 4? I’d like to windmill to be facing in different directions based on wind speed, which would simulate real-life windmills.

I’m really a bit lost here. You already have an AnimatedSprite2D done for the preview, right? Why don’t you just instantiate a new AnimatedSprite2D in whatever position you want? Why do you need to modify the tilemap?

I decided to not bother with the AnimatedSprite2D since I can’t seem to get it working. Also, wrote the code to use the tile for the preview. I TRIED to code it so it places a new AnimatedSprite2D when you build the building, but it didn’t work out. So I wanted to try and use animated tiles.

I think you want to make each of 1, 2, 3 and 4 be separate animated tiles in the tileset, at which point you ought to be able to paint them on the screen with .set_cell() on the TilemapLayer.