Skip to content
AI Sprite Maker

Docs

Godot 4 addon and SpriteFrames import

Updated November 6, 2026
On this page
  1. The AI Sprite Maker addon
  2. Install
  3. Generate from the dock
  4. Convert sheets you already have
  5. Use the result
  6. 1. Set up the project for pixel art (once)
  7. 2. Or export a .tres from the website
  8. 3. Use it with AnimatedSprite2D
  9. 4. Import any PNG sheet manually
  10. 5. Build SpriteFrames from code
  11. 6. Sprite2D + AnimationPlayer instead
  12. Troubleshooting
  13. Other ways to generate for Godot

Godot is the engine we use most ourselves, so everything is built around how Godot 4 wants 2D animation: a SpriteFrames resource played by an AnimatedSprite2D. There are three ways in:

  1. The Godot addon: generate from a dock inside the editor and get a ready SpriteFrames file. It also converts any PNG + JSON sheet (ours, Aseprite or TexturePacker).
  2. The .tres export from the website, if you’d rather generate in the browser.
  3. A plain PNG sheet, imported by hand or built from code.

This page also covers the project settings that keep pixel art sharp. For a longer walkthrough with 8-direction movement code, read How to import a sprite sheet in Godot 4.

Tested with Godot 4.3 and 4.4. Everything here also applies to 4.2.

Download the addon

aispritemaker-godot.zip · Godot 4.2 or newer · free, MIT licensed · generating needs an API key (every plan includes one); the sheet converter works without a key.

The AI Sprite Maker addon

Install

  1. Download aispritemaker-godot.zip and unzip it into your project so you get res://addons/aispritemaker/plugin.cfg. Or, in the editor, open AssetLib → Import…, pick the zip and install.
  2. Open Project → Project Settings → Plugins and enable AI Sprite Maker.
  3. The AI Sprite Maker dock appears on the right.

Generate from the dock

  1. Paste your API key (asm_live_…, from Dashboard → API keys) and press Save. The key is stored in Editor Settings (aispritemaker/api_key), which is per user and outside the project, so it never ends up in git.
  2. Pick a Type: Sprite, Animation (choose a motion from the list, loaded live from the motion library), Turnaround (4 or 8 directions) or Tileset.
  3. Write a prompt and choose style, size, palette (0 = the style’s default) and view. Optionally pick a Reference image from the project, or press Selected to use the image selected in the FileSystem dock.
  4. Press Generate. The dock shows progress; Cancel cancels the job and releases its credits.

Results are saved to Save to (default res://sprites/aispritemaker/):

FileWhat it is
fox-knight_walk.pngThe sheet: one row per direction, one column per frame
fox-knight_walk.jsonFrame rectangles, durations and one tag per animation (Aseprite-compatible)
fox-knight_walk.tresA SpriteFrames with AtlasTexture frames, fps and loop set per animation

Animations are named <motion>_<direction>, for example walk_down, walk_left, walk_right and walk_up. Two options at the bottom of the dock save setup time:

  • Add an AnimatedSprite2D to the open scene drops a configured AnimatedSprite2D (Nearest filter, autoplay) under the selected node. It’s a normal editor action, so Ctrl+Z undoes it.
  • Use Nearest filter project-wide sets rendering/textures/canvas_textures/default_texture_filter to Nearest, which is step 1 below in one click.

Convert sheets you already have

The addon turns any PNG + JSON sheet into SpriteFrames: our exports, Aseprite JSON (array or hash; tags with forward, reverse and pingpong; per-frame durations) and TexturePacker JSON (hash or array with an animations map). The PNG must be the file named in the JSON’s meta.image, next to the JSON.

  • In the dock: Sheet JSON → SpriteFrames…, pick the .json; the .tres is written next to it.
  • In the FileSystem dock (Godot 4.4+): right-click a .json → Create SpriteFrames (AI Sprite Maker).
  • Headless, for CI or batch jobs:
godot --headless --path . -s res://addons/aispritemaker/tools/convert_sheet.gd -- res://sprites/hero.json res://sprites/slime.json

Per-frame durations become SpriteFrames frame durations relative to the animation speed, so uneven timing from Aseprite survives the conversion.

Use the result

$AnimatedSprite2D.sprite_frames = load("res://sprites/aispritemaker/fox-knight_walk.tres")
$AnimatedSprite2D.play("walk_down")

The rest of this page applies whether you use the addon or not.

1. Set up the project for pixel art (once)

Do this before importing anything, or Godot will smooth your sprites into mush.

  1. Project → Project Settings → Rendering → Textures → Canvas Textures → Default Texture Filter → Nearest.
  2. Display → Window → Stretch: set Mode to viewport for a fixed low-res look (or canvas_items if you mix pixel art with smooth UI), Aspect to keep, and Scale Mode to integer (Godot 4.2+) so the game only scales by whole numbers.
  3. Set the base Viewport Width/Height to your game’s native resolution, e.g. 480 × 270 or 320 × 180, and use Window Width/Height Override for the size of the desktop window.
  4. Optional, for movement without shimmering: Rendering → 2D → Snap → Snap 2D Transforms to Pixel on.

If you only want nearest filtering on some nodes, leave the project default alone and set CanvasItem → Texture → Filter to Nearest on the node instead. Children inherit it.

2. Or export a .tres from the website

Open the job in the generator or your dashboard and choose Export → Godot 4 (SpriteFrames .tres). You get a ZIP with two files:

fox_knight_walk_godot.zip
├── fox_knight_walk.png    # the sheet, one row per direction
└── fox_knight_walk.tres   # SpriteFrames: one animation per row

Inside the .tres there is one animation per direction, named after the job and the direction, for example fox_knight_walk_down, fox_knight_walk_left, fox_knight_walk_right and fox_knight_walk_up. Check the exact names in the SpriteFrames panel or with sprite_frames.get_animation_names(). Each animation uses the job’s frame rate as its speed and loops if the motion loops (attacks and deaths don’t). Every frame is an AtlasTexture that points at a region of the PNG, so there is only one texture in memory.

Keep the PNG next to the .tres, or update the path

The .tres refers to the sheet as res://<name>.png. The simplest setup is to unzip both files into your project root, open the .tres once so Godot imports it, then move both together inside the Godot FileSystem dock (drag and drop). Godot rewrites the path for you. If you move them in your OS file manager instead, Godot shows a “Fix Dependencies” dialog the next time you open the resource; point it at the PNG.

3. Use it with AnimatedSprite2D

  1. Add an AnimatedSprite2D node to your character scene.
  2. In the Inspector, drag the .tres file onto Sprite Frames.
  3. Pick an animation in the Animation dropdown and tick Autoplay on Load if you want it to start immediately.
  4. Set Offset so the feet sit on the node origin. Our frames put the character’s feet on the bottom edge, so with a 64 px frame use Offset = (0, -32) and Centered on. That way position is where the character stands, which makes Y-sorting and collisions line up.

Play animations from code:

extends CharacterBody2D

const SPEED := 90.0
@onready var anim: AnimatedSprite2D = $AnimatedSprite2D
var facing := "down"

func _physics_process(_delta: float) -> void:
	var input := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
	velocity = input * SPEED
	move_and_slide()

	if input != Vector2.ZERO:
		# pick the dominant axis for 4-direction art
		if absf(input.x) > absf(input.y):
			facing = "right" if input.x > 0.0 else "left"
		else:
			facing = "down" if input.y > 0.0 else "up"
		anim.play("fox_knight_walk_" + facing)
	else:
		anim.play("fox_knight_idle_" + facing)

play() does nothing if that animation is already playing, so calling it every frame is fine. For one-shot animations like an attack, wait for animation_finished:

func attack() -> void:
	anim.play("fox_knight_attack-slash_" + facing)
	await anim.animation_finished
	anim.play("fox_knight_idle_" + facing)

Combining several motions in one SpriteFrames

Each export is one motion. To keep idle, walk and attack in one resource, open the first .tres, then in the SpriteFrames panel use Add Frames from Sprite Sheet (the grid icon) to add the other sheets as new animations. Or merge them in code at load time with SpriteFrames.add_animation() and add_frame() as shown below.

4. Import any PNG sheet manually

If you exported a plain PNG (or the sheet came from somewhere else), build the SpriteFrames in the editor:

  1. Add an AnimatedSprite2D, then in Sprite Frames choose New SpriteFrames and click it to open the SpriteFrames panel at the bottom.
  2. Rename default to your animation name, e.g. walk_down.
  3. Click Add Frames from Sprite Sheet (the grid icon), pick the PNG, and set Horizontal to the number of columns and Vertical to the number of rows. Both values are in the job’s JSON metadata (columns, rows) and in the export dialog.
  4. Click the frames of the first row in order, then Add Frame(s). Repeat for each row as its own animation.
  5. Set the FPS box to the job’s fps and toggle Loop for looping motions.

5. Build SpriteFrames from code

This is handy for tools, mods or loading sheets at runtime. It reads the frame layout from the JSON metadata we export with every sheet:

func frames_from_sheet(sheet: Texture2D, frame_w: int, frame_h: int,
		columns: int, directions: PackedStringArray, prefix: String,
		fps: float, loop := true) -> SpriteFrames:
	var sf := SpriteFrames.new()
	sf.remove_animation("default")
	for row in directions.size():
		var anim_name := "%s_%s" % [prefix, directions[row]]
		sf.add_animation(anim_name)
		sf.set_animation_speed(anim_name, fps)
		sf.set_animation_loop(anim_name, loop)
		for col in columns:
			var tex := AtlasTexture.new()
			tex.atlas = sheet
			tex.region = Rect2(col * frame_w, row * frame_h, frame_w, frame_h)
			sf.add_frame(anim_name, tex)
	return sf

Then use it:

var sheet: Texture2D = load("res://sprites/fox_knight_walk.png")
$AnimatedSprite2D.sprite_frames = frames_from_sheet(
	sheet, 64, 64, 8, PackedStringArray(["down", "left", "right", "up"]),
	"walk", 10.0)
$AnimatedSprite2D.play("walk_down")

If you want to keep the result, save it with ResourceSaver.save(sf, "res://sprites/fox_knight.tres").

6. Sprite2D + AnimationPlayer instead

If you already drive everything with an AnimationPlayer (for hitboxes, sounds and particles on exact frames), skip SpriteFrames. Use a Sprite2D with Animation → Hframes = columns and Vframes = rows, then key the Frame property in the AnimationPlayer. Frame numbers count left to right, top to bottom, so row r, column c is r * columns + c. Set the track’s update mode to Discrete.

Troubleshooting

ProblemCause and fix
Sprites look blurryTexture filter is Linear. Set the project default to Nearest (step 1) or the node’s Texture → Filter to Nearest
Sprites shimmer or wobble when the camera movesNon-integer scaling or sub-pixel positions. Use Scale Mode integer and turn on Snap 2D Transforms to Pixel
Thin lines from the neighbouring frame at the edgeFiltering or a non-integer scale samples outside the region. Fix the filter and scale first. If you pack sheets yourself, add 1–2 px padding
“Fix Dependencies” dialog when opening the .tresThe PNG isn’t at the path the .tres expects. Point the dialog at the PNG, or move files inside the FileSystem dock
Animation plays too fast or slowThe SpriteFrames speed is in frames per second. Match the job’s fps, or change Speed Scale on the node
Character slides when changing directionOffsets differ between animations. Use the same frame size and the same Offset for all of a character’s sheets

Other ways to generate for Godot

  • The CLI writes the same PNG, JSON and .tres files from your terminal (--format png,json,godot), with correct res:// paths when run inside a Godot project.
  • With the MCP server, a coding agent such as Claude Code can generate a sheet and wire it into your scenes.
← Previous Aseprite Next → Unity

Found a mistake or something out of date? Email hello@aispritemaker.com and we will fix it.