Skip to content
Blog

Turn Pixel Art Sprite Sheets Into Godot SpriteFrames for 2D Animation

5 min read
Workbench with empty animation frames, a helmet and boots beside the grid.

Prepare your pixel art animation sheet

A predictable grid saves hours. For this tutorial, use a sheet that is 256 by 256 pixels, arranged as 8 columns and 4 rows. That gives 32 by 32 pixel frames. Put idle on row 1, run on row 2, and jump on row 3. Leave row 4 empty for a future attack or spare frames.

Before you import, check three things:

  • Every frame uses the same cell size with no extra padding between cells
  • The character feet sit on the same baseline in each row so the sprite does not bounce when it plays
  • The file is PNG with either full transparency or a single solid background, not a mix

If you generated the sheet outside Godot, the Image Studio and templates workflow is a useful way to keep canvas size and cell alignment consistent across exports.

Drag the PNG into your project, for example into res://art/player_sheet.png. Select the AnimatedSprite2D that will use it later and set texture_filter to Nearest under CanvasItem in the Inspector. That keeps pixel edges sharp when the camera zooms or the window scales.

Slice the sheet into a SpriteFrames resource

You will build one SpriteFrames resource that holds all animations for the character. Work in the main editor, not in code, so you can see each frame as you select it.

  1. Create a CharacterBody2D node, then add a child AnimatedSprite2D and a child CollisionShape2D.
  2. Select the AnimatedSprite2D, find SpriteFrames in the Inspector, and choose New SpriteFrames.
  3. Click the SpriteFrames editor panel at the bottom of the editor to open it.
  4. Rename the default animation from default to idle.
  5. Click Add frames from sprite sheet. It looks like a small grid icon in the panel toolbar.
  6. In the picker, load player_sheet.png. Set Horizontal to 8 and Vertical to 4. You should see the grid lines land exactly on cell borders. If they do not, stop and fix the sheet size before you continue.
  7. Drag to select the 6 frames on row 1, then click Add. Repeat after creating run and jump animations with Add Animation.

Name and fill idle, run, and jump

Keep the naming simple and lowercase: idle, run, jump. Add 4 to 8 frames per animation for pixel art. You can reorder frames by dragging them in the filmstrip. Delete any blank or duplicate frame now, because a single bad frame is very visible at 10 frames per second.

Stick to GDScript for the playback script below unless your team already uses C#. The tradeoffs are explained in GDScript vs C# for AI assisted projects.

Set loop mode and animation speed

Select each animation in the SpriteFrames panel. Two settings control most of the feel.

AnimationLoopSpeed (FPS)Why
idleOn6Slow breathing loop that can repeat forever
runOn10Snappy cycle that matches footstep timing
jumpOff8Plays once so landing can switch to idle or run

Loop is the looping arrow button next to the animation name. Speed is the FPS field to the right of the frames. Pixel art usually looks best between 6 and 12 FPS. Higher values blur the stepped motion that makes pixel art appealing.

Use AnimationPlayer only if you need to animate position or scale at the same time. For pure sprite swapping, AnimatedSprite2D plus SpriteFrames is simpler and easier to test.

Test playback in a sample scene

Build a small room so you can see movement and gravity. Your scene tree should look like this:

  • Player as CharacterBody2D with the script below
    • AnimatedSprite2D
    • CollisionShape2D with a capsule shape
  • Floor as StaticBody2D with a large rectangle shape

Attach this script to the Player node. It handles left and right movement, jumping, and animation switching with no extra setup.

extends CharacterBody2D

@onready var sprite: AnimatedSprite2D = $AnimatedSprite2D

const SPEED := 120.0
const JUMP_VELOCITY := -220.0
const GRAVITY := 800.0

func _physics_process(delta: float) -> void:
    if not is_on_floor():
        velocity.y += GRAVITY * delta
    elif Input.is_action_just_pressed("ui_accept"):
        velocity.y = JUMP_VELOCITY

    var direction := Input.get_axis("ui_left", "ui_right")
    velocity.x = direction * SPEED
    move_and_slide()

    if not is_on_floor():
        sprite.play("jump")
    elif direction != 0.0:
        sprite.play("run")
        sprite.flip_h = direction < 0.0
    else:
        sprite.play("idle")

Press F6 to play the current scene. You should see idle loop when still, run loop when moving, and jump play once in the air. If the feet slide, raise run FPS by 1 or 2. If the sprite looks blurry, check texture_filter is still Nearest.

Tip: test with the window at both 1x and 2x scale. Pixel crawl often hides at one zoom level and appears at another.

If you work with Godot MCP Studio, you can ask the agent to open the sample scene, list the animations in the SpriteFrames resource, play the scene, and report which animation name is active while the character moves. That gives you a quick second check that idle, run, and jump all trigger.


When all three play correctly, save the SpriteFrames as res://art/player_spriteframes.tres so you can reuse it for enemies or alternate skins. You now have a sliced pixel art animation sheet running as timed Godot 2D animation.

Was this helpful?

Comments