Skip to main content

Sprite2D Node

The Sprite2D node displays a 2D texture. It’s the most common way to show images in Godot.

Loading Textures

extends Sprite2D

func _ready():
    # Load texture at compile time (recommended)
    texture = preload("res://assets/player.png")

Basic Properties

PropertyTypeDefaultDescription
textureTexture2DnullThe texture to display
centeredbooltrueWhether to center the texture on the node
offsetVector2(0, 0)Drawing offset from position
flip_hboolfalseFlip texture horizontally
flip_vboolfalseFlip texture vertically

Centering and Offset

# Center the sprite (default)
centered = true

# Position sprite by top-left corner
centered = false

# Apply custom offset
offset = Vector2(10, -5)
For pixel art games, set centered = false to avoid textures appearing between pixels, which can cause blurriness.

Flipping Sprites

extends Sprite2D

func _process(delta):
    # Flip sprite based on movement direction
    var velocity = get_parent().velocity
    if velocity.x < 0:
        flip_h = true
    elif velocity.x > 0:
        flip_h = false

Sprite Sheets

Sprite sheets combine multiple frames in a single texture for efficiency.

Using hframes and vframes

extends Sprite2D

func _ready():
    texture = preload("res://assets/character_sheet.png")
    
    # 8 columns, 4 rows
    hframes = 8
    vframes = 4
    
    # Show first frame (index 0)
    frame = 0

func _process(delta):
    # Cycle through frames
    frame = (frame + 1) % (hframes * vframes)

Frame Coordinates

# Set frame by coordinates instead of index
frame_coords = Vector2i(2, 1)  # Column 2, Row 1

# Get current frame coordinates
var coords = frame_coords
print("At column %d, row %d" % [coords.x, coords.y])

Region Rect

Display only a portion of a texture using region rectangles:
extends Sprite2D

func _ready():
    texture = preload("res://assets/atlas.png")
    
    # Enable region mode
    region_enabled = true
    
    # Define the rectangle to display (x, y, width, height)
    region_rect = Rect2(0, 0, 32, 32)
    
    # Prevent bleeding from adjacent regions
    region_filter_clip_enabled = true
Enable region_filter_clip_enabled when using texture atlases to prevent color bleeding from adjacent textures.

AnimatedSprite2D

AnimatedSprite2D is designed for frame-based animations using SpriteFrames resources.

Creating SpriteFrames

  1. Select the AnimatedSprite2D node
  2. In the Inspector, create a new SpriteFrames resource
  3. Open the SpriteFrames panel at the bottom of the editor
  4. Create animations and add frames

Playing Animations

extends AnimatedSprite2D

func _ready():
    # Play the "walk" animation
    play("walk")

func jump():
    # Play "jump" animation at 1.5x speed
    play("jump", 1.5)

func take_damage():
    # Play "hit" animation backwards
    play_backwards("hit")

Animation Control

# Play animation
play("run")

# Pause without resetting
pause()

# Resume from pause
play()  # No arguments resumes current animation

# Stop and reset to frame 0
stop()

Animation Signals

extends AnimatedSprite2D

func _ready():
    animation_finished.connect(_on_animation_finished)
    animation_looped.connect(_on_animation_looped)
    frame_changed.connect(_on_frame_changed)

func _on_animation_finished():
    print("Animation completed: ", animation)
    # Switch to idle after attack
    if animation == "attack":
        play("idle")

func _on_animation_looped():
    print("Animation looped")

func _on_frame_changed():
    print("Now on frame: ", frame)
    # Play sound on specific frame
    if animation == "walk" and frame == 2:
        $FootstepSound.play()

Autoplay

# Set in the inspector or code
autoplay = "idle"
The animation specified in autoplay will start automatically when the scene loads.

Advanced Sprite Techniques

Modulation (Tinting)

# Tint sprite red
modulate = Color.RED

# Semi-transparent
modulate = Color(1, 1, 1, 0.5)

# Flash effect
func flash_white():
    modulate = Color.WHITE
    await get_tree().create_timer(0.1).timeout
    modulate = Color(1, 1, 1, 1)

Self-Modulation

# self_modulate doesn't affect children
self_modulate = Color(1, 0, 0)  # Red tint

Pixel Opacity Detection

extends Sprite2D

func _input(event):
    if event is InputEventMouseButton and event.pressed:
        # Check if click is on opaque pixel
        var local_pos = to_local(event.position)
        if get_rect().has_point(local_pos):
            if is_pixel_opaque(local_pos):
                print("Clicked on sprite!")

Get Sprite Bounds

# Get the sprite's rectangle in local coordinates
var rect = get_rect()
print("Size: ", rect.size)
print("Position: ", rect.position)

Texture Filtering

Control how textures are filtered when scaled:
# For pixel art (crisp, no blur)
texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST

# For smooth graphics (default)
texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR
You can also set the default texture filter in Project Settings under Rendering > Textures > Canvas Textures > Default Texture Filter.

Character Animation Example

extends CharacterBody2D

@onready var sprite = $AnimatedSprite2D

const SPEED = 200.0
const JUMP_VELOCITY = -400.0

func _physics_process(delta):
    # Add gravity
    if not is_on_floor():
        velocity += get_gravity() * delta
    
    # Jump
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = JUMP_VELOCITY
        sprite.play("jump")
    
    # Horizontal movement
    var direction = Input.get_axis("move_left", "move_right")
    if direction != 0:
        velocity.x = direction * SPEED
        sprite.flip_h = direction < 0
        if is_on_floor():
            sprite.play("run")
    else:
        velocity.x = move_toward(velocity.x, 0, SPEED)
        if is_on_floor():
            sprite.play("idle")
    
    # In air animation
    if not is_on_floor() and velocity.y > 0:
        sprite.play("fall")
    
    move_and_slide()

Best Practices

preload() loads assets at compile time, making them instantly available and improving performance.
Keep all character animations in a single SpriteFrames resource for easy management.
Combine multiple small textures into atlases to reduce draw calls.
Pixel art needs NEAREST filtering; HD art needs LINEAR filtering.

Next Steps

Physics

Add physics-based movement to your sprites

TileMaps

Create environments with tile-based graphics

Build docs developers (and LLMs) love