Hi, I'm trying to figure out the best way to approach this: I'm working on a 2D topdown style puzzle game, where the character tries to cut her way out of growing vines that surround her. I'm really in the early stages, trying to build a quick and dirty prototype to play around with the game mechanics, so for the moment I'm more interested in making things work than in making them look good. I made a simple tile map for the environment and a small animated player character. Now I need to tackle the vines. Basically, the vines take over one tile of the grid after the other. I made little four frame animations of the vine growing in different directions and my idea is to place that animation over a tile, let it run once and then stop on the last frame before I start a new animation on the next tile.

I guess I could make a little scene for each vine-element, consisting of an area with a collision shape and an animated sprite. But then I'd have to find a way to place those areas exactly on the tilemap, so I'd have to go back and forth between tile coordinates and screen coordinates. I also saw that there is a way to animate tiles on a tilemap, but I haven't found a way to control these animations from code and make them run just once and then stop on the last frame and to find out if the animation has stopped so that I can then place the next tile. It looks like the animated tiles can only loop endlessly?

There's probably even other ways of doing this that I haven't even thought about, but I think I'd ask for your input before I waste too much time trying something that can't work. So, if any of you have done something similar, I'd love your insight into how to best approach this in Godot 4.1.

You can do this on a TileMap. Look up Conway's Game of Life in Godot and find out about cellular automatons. I made something similar in a project I am working on. It is only visual but it's not a huge leap at all to incorporate physics. (I just didn't need them.)

Essentially, you will want a 0 and 1 tile - one for your blank tile and one for your vines tile. Then figure out whatever math you want to make them populate and probably have them "start" in a different place each level. I agree with your process btw. Always easier to make it work first then make it pretty.

I learned how to do this from a YT video but I can't seem to find it anymore. However, this is a more recent one and will likely be a bit more up-to-date:
Game of Life Godot tutorial 2023

My code from mine which allows user input to "place" tiles, though the code's not terribly efficient or legible if you're not familiar with it:

extends TileMap


const _TILE_SIZE = 32 ## math for mouse input

export(int) var _width = 32
export(int) var _height = 18

var _tempField ## holder variable

var _returnScene


func _ready(): ## calculate cell sizes
	_tempField = []
	for _x in range(_width):
		var _temp = []
		for _y in range(_height):
			_temp.append(0)
		_tempField.append(_temp)



func _process(_delta):
	if $Timer.is_stopped():
		$Timer.start()


func _input(event):
	if event.is_action_pressed("_click"): ## get mouse position and divide by tile size
		var _pos = (get_global_mouse_position()/_TILE_SIZE).floor() ## remove decimal
		set_cellv(_pos, 1-get_cellv(_pos)) ## normalize value to 1 or zero


func _release():
	if Input.is_action_just_pressed("ui_cancel"):
		var _released = get_tree().change_scene(_returnScene)
	

func _updateField():
	## adjust state in temp field, look for neighbors
	for x in range(_width):
		for y in range(_height):
			var _liveNeighbors = 0
			for x_off in [-1, 0, 1]: ## check eight directions on x
				for y_off in [-1, 0, 1]: ## check eight directions on y
					if x_off != y_off or x_off != 0: ## error handling
						if get_cell(x+x_off, y+y_off) == 1:
							_liveNeighbors += 1 ## update neighbors if logic allows
			
			
			if get_cell(x, y) == 1: ## when cell is alive
				if _liveNeighbors in [2, 3]: ## if neighbors equals 2 or 3
					_tempField[x][y] = 1 ## updates tile location
				else:
					_tempField[x][y] = 0
			else:
				if _liveNeighbors == 3:
					_tempField[x][y] = 1 ## updates tile location
				else:
					_tempField[x][y] = 0
	
	### update tilemap
	for x in range(_width):
		for y in range(_height): ## updating tiles with location match
			set_cell(x, y, _tempField[x][y])

    systemerror Actually, that could work as well. Maybe I could mix that. I could use a sprite for the top of the vine, so the part that is actually growing and then change the tiles that has already passed over, so that I don't have to create a new sprite for every tile ... I like that idea. The sprites seem a lot more flexible and straightforward for the animation part of things.

    Okay, this seems to be working. My vine is still pretty stupid at the moment, I just let it grow randomly and there is now collision detection and ray cast system in place yet, so it sometimes grows in circles over itself and it can't interact with the player yet, but I kind of like what it looks like. The "head" of the vine is an animated sprite and once it is done playing, the corresponding tile is set on the tilemap.