Animated spritesheets in "Collection of Images" tilesets / Using Tiled as a NecroDancer Level Editor

Hello! I’d like to use Tiled as a level editor for one specific game that I play, and I’d like to know how possible that sounds, and what Tiled features I should look up that will help me do that. I also have one very specific question at the end of this post detailing the current issue I’ve run into.

I’ve used Tiled a little bit but I am not very experienced; please don’t hold back from telling me any basics that it sounds like I might not understand!

game background info

The game is top-down and based on a 2D grid (see https://braceyourselfgames.com/crypt-of-the-necrodancer/ if you want more details/gameplay footage)

The level format for necrodancer includes things like <tile cracked="0" torch="1" type="100" x="2" y="-6" zone="0"></tile> for a wall-with-a-torch, <enemy beatDelay="1" lord="0" type="113" x="1" y="2"></enemy> for a particular enemy (tar monsters have type="113") etc, you get the idea. Here’s a complete example level if it helps; the custom level shown here:

image

is stored as this xml file:

<?xml version="1.0"?>
<dungeon character="0" name="example" numLevels="1">
	<level bossNum="-1" music="0" num="1">
		<tiles>
			<tile x="-1" y="-4" type="100" zone="0" torch="0" cracked="0" />
			<tile x="-1" y="-3" type="100" zone="0" torch="0" cracked="0" />
			<tile x="-2" y="-2" type="100" zone="0" torch="0" cracked="0" />
			<tile x="-1" y="-2" type="107" zone="0" torch="0" cracked="1" />
			<tile x="-2" y="-1" type="100" zone="0" torch="0" cracked="0" />
			<tile x="-1" y="-1" type="4" zone="0" torch="0" cracked="0" />
			<tile x="-2" y="0" type="107" zone="0" torch="0" cracked="0" />
			<tile x="-1" y="0" type="4" zone="0" torch="0" cracked="0" />
			<tile x="-2" y="1" type="100" zone="0" torch="0" cracked="0" />
			<tile x="-1" y="1" type="0" zone="0" torch="0" cracked="0" />
			<tile x="-2" y="2" type="100" zone="0" torch="0" cracked="0" />
			<tile x="-1" y="2" type="100" zone="0" torch="0" cracked="0" />
			<tile x="0" y="-4" type="100" zone="0" torch="0" cracked="0" />
			<tile x="1" y="-4" type="100" zone="0" torch="0" cracked="0" />
			<tile x="0" y="-3" type="2" zone="0" torch="0" cracked="0" />
			<tile x="1" y="-3" type="100" zone="0" torch="0" cracked="0" />
			<tile x="0" y="-2" type="103" zone="0" torch="0" cracked="0" />
			<tile x="1" y="-2" type="100" zone="0" torch="0" cracked="0" />
			<tile x="2" y="-2" type="100" zone="0" torch="0" cracked="0" />
			<tile x="3" y="-2" type="100" zone="0" torch="0" cracked="0" />
			<tile x="0" y="-1" type="0" zone="0" torch="0" cracked="0" />
			<tile x="1" y="-1" type="0" zone="0" torch="0" cracked="0" />
			<tile x="2" y="-1" type="0" zone="0" torch="0" cracked="0" />
			<tile x="3" y="-1" type="100" zone="0" torch="0" cracked="0" />
			<tile x="0" y="0" type="0" zone="0" torch="0" cracked="0" />
			<tile x="1" y="0" type="0" zone="0" torch="0" cracked="0" />
			<tile x="2" y="0" type="0" zone="0" torch="0" cracked="0" />
			<tile x="3" y="0" type="107" zone="0" torch="1" cracked="0" />
			<tile x="0" y="1" type="0" zone="0" torch="0" cracked="0" />
			<tile x="1" y="1" type="0" zone="0" torch="0" cracked="0" />
			<tile x="2" y="1" type="0" zone="0" torch="0" cracked="0" />
			<tile x="3" y="1" type="100" zone="0" torch="0" cracked="0" />
			<tile x="0" y="2" type="100" zone="0" torch="0" cracked="0" />
			<tile x="1" y="2" type="107" zone="0" torch="1" cracked="0" />
			<tile x="2" y="2" type="100" zone="0" torch="0" cracked="0" />
			<tile x="3" y="2" type="100" zone="0" torch="0" cracked="0" />
		</tiles>
		<traps>
			<trap x="1" y="-1" type="1" subtype="5" />
		</traps>
		<enemies>
			<enemy x="1" y="0" type="106" beatDelay="0" lord="0" />
			<enemy x="-1" y="1" type="103" beatDelay="0" lord="0" />
		</enemies>
		<items>
			<item x="2" y="-1" type="feet_boots_explorers" bloodCost="0" saleCost="0" singleChoice="0" />
			<item x="2" y="0" type="food_1" bloodCost="0" saleCost="0" singleChoice="0" />
		</items>
		<chests />
		<crates />
		<shrines />
	</level>
</dungeon>

Note that multiple things can be in a single square. For example, an enemy, trap, wall, item, and floor could all be placed in the same exact location. (This seems like it’ll be easy to do in Tiled using the Tile Layers feature)

my plan

Here’s my vague outline of a plan so far:

  1. Create an enormous tileset of everything that is in the game. Traps, walls, floors, enemies, items, etc. Possibly a few different tilesets, e.g. one tileset for all the walls, one tileset for all the enemies, etc, so that it’s easier to use?
  2. Create a custom map format exporter in javascript (https://doc.mapeditor.org/en/stable/reference/scripting/#script-registermapformat)
    This will loop through the map and output the required xml snippets for each thing at the correct time.

I’m confident I can do the code in part 2, but I have no idea how to create the tileset. Things I want:

  1. the less time this takes, the better. there are a lot of game assets…
  2. If possible, I’d like to be able to distribute this tileset once I’m done. Now, I don’t want to redistribute all of the art assets for the game, that sounds illegal. But if the tileset .tsx file was just full of entries that looked like this then I’d be able to distribute the tileset to other people who also own the game:
    <tile id="0"> <image width="72" height="48" source="C:/Program Files/Steam/steamapps/common/Crypt of the NecroDancer/data/level/wall_dirt_crypt_diamond1.png"/> </tile> (this snippet is from a “Collection of Images” .tsx file that I’ve started to make, but I’ve run into issues that I’ll explain later in this post)

vague unknowns

Once I’ve figured out how to import tiles correctly, what’s the best way to add custom data to them? I need to somehow tell Tiled that e.g. tarmonsters have type="113" so that I can use that information in my custom map exporter. I assume I should just add a “Custom Property” to each tile? That seems straightforward to me, but I’m new to Tiled so if you have a better idea, let me know.

the main issue I’ve run into so far / the main question of this post

The assets for the game are all stored as individual files that store all animation frames pasted together in a single PNG. Here’s an screenshot of some of the files in windows explorer:
explorer_SIOkQOos8q

I opened Tiled, clicked on “New Tileset”, and made a tileset with type “Collection of Images” - this sounds perfect for my use case. However, when I click “Add Tiles” and choose one of these images, the added tile is the entire image. I want the added tile to be only one frame of the image - you can see in the screenshot that dead_ringer_charge.png is 6 frames in a single PNG file, and when I place that enemy on the map, I only want to see one of the 6 frames. Is there some way to do this?

If I can’t get this working, what should I do instead? Maybe… write a python script that combines all of the individual image files into one enormous PNG and then import that PNG into Tiled? That has its own issues too–the various tiles and enemies are different sizes (in pixels)

summary of my questions

A. Is this a good idea / Will this work? Is my plan reasonable?
B. What should I do about my “Collection of Images” multiple-frames-stored-in-a-single-image problem?

thank you!