Trying to change the speed of animation in TileSetLayer via gdscript

Godot Version

4.4.stable

Question

I’m trying to change the speed of an animation based on a value of a random number generator. However, the code doesn’t work, error below:

Code below:

func wind_characteristics():
	wind_speed = rng2.randi_range(0, 20)
	if wind_speed > 0:
		compass_arrow.rotation_degrees = 45 * rng1.randi_range(0, 7)
		compass_arrow.play("Compass_Arrow")
		if wind_speed > 4 and wind_speed < 10:
			preview.animation_speed = 1.0 <---Error happens here
		elif wind_speed > 9 and wind_speed < 15:
			preview.animation_speed = 2.0 <---Error happens here
		elif wind_speed > 14 and wind_speed < 21:
			preview.animation_speed = 3.0 <---Error happens here

TileMap Animation shown below:

1 Like

Perheps you didn’t set the correct path to an object that takes those changes? Maybe preview is set incorrectly? Did you mean to reference a child node that has an animator on it instead?

Or you could try something like this instead.

var preview = $PathToAnimatedSprite2D
preview.speed_scale = 1.0 or random number generated
instead of animation_speed?

Im not sure without seeing more code.

extends TileMapLayer

@export var noise_height_text : NoiseTexture2D
var noise = FastNoiseLite.new()

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

#Stores the terrain tiles into variables
var source_id = 98

var randomizer: int
var terrain_chooser: int

var sand_atlas: Vector2i
var grass_atlas: Vector2i
var water_atlas: Vector2i

var sand_atlas1 = Vector2i(0, 0)
var sand_atlas2 = Vector2i(1, 0)
var sand_atlas3 = Vector2i(2, 0)
var grass_atlas1 = Vector2i(0, 1)
var grass_atlas2 = Vector2i(1, 1)
var grass_atlas3 = Vector2i(2, 1)
var water_atlas1 = Vector2i(0, 2)
var water_atlas2 = Vector2i(1, 2)
var water_atlas3 = Vector2i(2, 2)

var rng = RandomNumberGenerator.new()
var rng0 = RandomNumberGenerator.new()
var rng1 = RandomNumberGenerator.new()
var rng2 = RandomNumberGenerator.new()
var wind_speed: int = 0
var wind_speed_format: String

@onready var wind_label: Label = $"../Camera2D/CanvasLayer/VBoxContainer/Wind_Speed"
@onready var compass_arrow: AnimatedSprite2D = $"../Camera2D/CanvasLayer/Compass_Arrow"
@onready var buildings: TileMapLayer = $"../Buildings"
@onready var preview: TileMapLayer = $"../Preview"

func _ready():
	#Sets the seed number to a random 32 digit integer, allowing for new terrain to be generated
	noise.seed = randi()
	generate_world()

func generate_world():
	for x in range(-width/2, width/2):
		for y in range (-height/2, height/2):
			#Clears every tile, ensuring a blank slate before populating the terrain tiles
			set_cell(Vector2i(x,y), -1)
	
	for x in range(-width/2, width/2):
		for y in range(-height/2, height/2):
			#Gets noise value to determine which tile to place
			var noise_val:float = noise.get_noise_2d(x,y)
			#Uses noise values to place the grass tile
			if noise_val >= -0.22:
				#Determines which grass tile to use
				randomizer = rng0.randi_range(0, 4)
				if randomizer == 4:
					terrain_chooser = rng.randi_range(0, 1)
					match terrain_chooser:
						0: grass_atlas = grass_atlas2
						1: grass_atlas = grass_atlas3
				else:
					grass_atlas = grass_atlas1
				set_cell(Vector2i(x,y), source_id, grass_atlas)
			#Uses noise values to place the sand tile
			elif noise_val > -0.3 and noise_val < -0.22:
				#Determines which sand tile to use
				randomizer = rng0.randi_range(0, 4)
				if randomizer == 4:
					terrain_chooser = rng.randi_range(0, 1)
					match terrain_chooser:
						0: sand_atlas = sand_atlas2
						1: sand_atlas = sand_atlas3
				else:
					sand_atlas = sand_atlas1
				set_cell(Vector2i(x,y), source_id, sand_atlas)
			#Uses noise values to place the water tile
			elif noise_val <= -0.3:
				#Determines which water to use
				randomizer = rng0.randi_range(0, 5)
				if randomizer == 4:
					terrain_chooser = rng.randi_range(0, 1)
					match terrain_chooser:
						0: water_atlas = water_atlas2
						1: water_atlas = water_atlas3
				else:
					water_atlas = water_atlas1
				set_cell(Vector2i(x,y), source_id, water_atlas)

func _on_generate_world_pressed():
	_ready()

func wind_characteristics():
	wind_speed = rng2.randi_range(0, 20)
	if wind_speed > 0:
		compass_arrow.rotation_degrees = 45 * rng1.randi_range(0, 7)
		compass_arrow.play("Compass_Arrow")
		if wind_speed > 4 and wind_speed < 10:
			preview.animation_speed = 1.0
		elif wind_speed > 9 and wind_speed < 15:
			preview.animation_speed = 2.0
		elif wind_speed > 14 and wind_speed < 21:
			preview.animation_speed = 3.0
		
	if wind_speed < 10:
		wind_speed_format = "%1d mph"
	else:
		wind_speed_format = "%02d mph"
	wind_label.text = wind_speed_format % wind_speed
1 Like

Thanks for more code…

So from my understanding @ this Ready line.
@onready var preview: TileMapLayer = $“../Preview”

You’re explicitly telling Godot that preview is a TileMapLayer, which does not have an animation_speed property, hence the error when trying to assign to it.

If you’re using animated tiles in a TileMap, you cannot change their animation speed at runtime. Godot 4’s tile animation speed is defined in the TileSet editor and is not exposed during runtime I dont think.

If you need control over animation speed in this case, use something other than TileMap, like an AnimatedSprite2D or AnimationPlayer.

And is it possible you ment to call it as an animated sprite 2d instead?

@onready var preview: AnimatedSprite2D = $“../Preview”

And then adjust the speed like this:

preview.speed_scale = 2.0

P.S…
Have you tried the “Rubber Ducky” Method. Its a method in which you take a rubber duck and place it at your work space Or anything but start walking mr ducky through your issues and every bit of code. Pretend like ducky knows nothing about code.. talking to it out loud with all the information can really help move things and solve problems.

Hey! I see that a solution was found. What was it that helped out? Or what did you find that was the issue? Id love to know. And someone else with a similar issue might find this beneficial.

Ah, my apologies. I just realized that you can animate a sprite in the TileSet. And I also just realized that instead of having the windmill blades separate from the turbine’s column, I can just animate the entire windmill turbine. Each frame would be a drawing of the entire windmill, but with the blades in different positions. I feel this would keep things simple.

1 Like