How do I select a sprite from a spritesheet at runtime?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Arecher

We are working on a game that uses a lot of tilesets. We have some questions about how to optimally work with spritesheets in Godot.

1. How do we efficiently select a new sprite from the spritesheet at runtime?
We want to change the sprite of a tile. Should we just set the TextureRegion to the correct tile, or is that not optimized if a lot of sprites change at the same time?
2. Can we check if a sprite in the spritesheet is empty?
Since we plan to have variations of our sprites, there is a chance that regions of the spritesheet are empty. What would be the best way to detect this?

Example of a small spritesheet with empty tiles. We would want to randomly select one of the variations, while making sure it never selects an empty tile.

3. How should we handle large amounts of sprites in Godot?
We are planning to have a lot of different biomes in our project. Would it be best to organise each biome in it’s own spritesheet? Should we combine all of them in one massive spritesheet, or should each tile be it’s own file? What is the optimal way to handle this in Godot?


:bust_in_silhouette: Reply From: pospathos

I think you should use TileMap Node, and make TileSet from your sprite sheet in TileSet edit menu (add Texetures button down left corner) - see this tutorial.

You set your sprites to each individual Tile and change Tile on a specific loacation, not sprite.

You can check if Tile index is empty or not in TileMap with get_cell( int x, int y )or get_cellv( Vector2 position ), in documentation it reads if tile on a given index does not exist function returns [constant INVALID_CELL]., but if there is no tile on a specific location right now (Godot 3.1) it returns -1 (so check if index in a specific tile position if greater than -1). Use world_to_map and map_to_world to convert position between world space and tile space. You can change specific Tile in TileMap with set_cell() or set_cellv()- if you set your tile index to -1 in this functions you can erase Tile in a specific tile position.

I think it is more efficient to have all biomes in one sprite sheet if you are using them in one map (you would have to load them in memory anyway), then you can make either one TileMap with all sprites as separate Tiles, or each biome as one separate TileMap (but same sprite sheet) - it depends what you need (but in second case if you need to check if Tile is empty you must determine TileSet first, and then check Tile index on that TileMap.
Sorry for bad english.

Hey Pospathos,

First of all, thank you for taking your time to look at our question! It is much appreciated!
Secondly, I feel like I should give some context. Our world is rather large (3M tiles) and I have already started working on the project a while ago.

Currently the game has chunks working and has the tiles properly instantiating. The issue however is purely on how to organize spritesheets. Now, I have not looked at the video you linked yet (I will when I have some more time) but I suspect it will be rather hard to change the game to work with tilesets instead! In addition to this, I think checking each tile will start to cause issues as the game’s running. Our current system already has something for that (checks only when the player is viewing them and spits out a number).

We are also using a custom ruleset to determine what each sprite should be (8bit) and this complicates things a little more. This ruleset provides us with a number 0->255 that indicates what this tile should look like. (so our edges look nice.)
What we basically need is a setup that allows us to effectively get sprites from spritesheets OR preload all the tiles beforehand in a way that would allow us to access it using code. I’m totally unfamiliar with the way Godot handles sprites so that’s really the thing causing issues here.

I’ve previously worked with Unity and Game Maker (1 & 2) and in both I can simply refer to a spritesheet and then set a radius. However, with Godot doing things a little different I wanted to be sure that this would be the right way to go about things. (because it feels like it isnt.)
What I’m really hoping for here is:

  • Is it doable and a good idea to check spritesheets?
  • Can I load in spritesheets to my tiles or should I really be using something else?

Once again, thank you for your answer!
Ps: Your English was fine, the answer provided was perfectly understandable :slight_smile:

Syraleaf | 2019-04-04 15:32

Not sure that I understand your problem fully, sorry. But you can limit your search using TileMap node only on a specific array of nodes (say nodes in view) via code, or a specific tile in TileMap. If you need to access to specific region in a sprite sheet then you can do it with Region option in inspector of Sprite node, but that way you must manually set a system for creating sprites from sprite sheet - but that’s job of TileMap node. Check autotile option in TileMap editor for automatic transistion of different types of “terrain” in sprite sheet (see video). Not sure that this helps, but I that’s all I got. Good luck with your game!

pospathos | 2019-04-04 15:50