Skip to main content

Animpy

PyPI - Version Downloads GitHub License

Animpy is a Python library for building lightweight terminal-based animations, visual effects, mini-games, and interactive apps. It gives you a simple API for placing text objects on a scene, moving them, coloring them, applying physics, reacting to input, playing sound, and even following a moving target with a camera-style offset.

It is built for developers who want to create animated terminal experiences without needing a full game engine or a graphical UI framework.

What Animpy can do

  • Create and animate text objects in the terminal
  • Draw shapes such as rectangles, circles, polygons, lines, hearts, triangles, ellipses, squares, and donuts
  • Create particle bursts, trails, and explosions
  • Apply built-in visual effects such as shaking, gravity, decay, fading, interpolation, pulsing, and typing effects
  • Build scenes with layered objects, background colors, offsets, and camera-style views
  • Add physics behaviors such as gravity, friction, bounce, angular motion, and force pushes
  • Handle keyboard and mouse input for interactive demos and games
  • Play audio clips with basic playback controls
  • Format terminal output with color, panels, centering helpers, and ANSI utilities

Installation

pip install animpy

Animpy depends on the following packages:

  • pygame-ce
  • keyboard
  • mouse
  • rich

Quick start

import animpy

scene = animpy.Scene()
text = animpy.Text("Hello!", 10, 5, r=255, g=100, b=50)
scene.add(text)
scene.render()

A more animated example:

import animpy
import time

scene = animpy.Scene()
text = animpy.Text("Hello", 0, 0, r=0, g=255, b=255)
scene.add(text)

for _ in range(20):
    text.moveX(1)
    scene.render()
    time.sleep(0.05)

Core concepts

1. Scenes

A Scene is the container that holds objects to be rendered to the terminal. It manages the draw order, background color, offsets, and optional camera logic.

scene = animpy.Scene()
scene.set_bg_rgb(0, 0, 30)

2. Renderer

Renderer is the compositing engine used by Scene.render(). It supports text, particles, nested groups, z-order, scene offsets, cameras, and RGB backgrounds. It can also render into a string or inspect a deterministic Frame, which is useful for tests, recordings, and custom terminal integrations.

from io import StringIO

renderer = animpy.Renderer(size=(80, 24))
frame = renderer.render_frame(scene)
plain_text = frame.plain_text()

output = StringIO()
animpy.Renderer(stream=output, size=(80, 24)).render(scene)

3. Text objects

Text is the basic object that can be placed on the screen and moved around. Text can also be created from a list of frames, which allows simple frame-based animation.

text = animpy.Text("Hello", 5, 3)
text.moveX(4)
text.moveY(2)
text.set_color(255, 0, 0)

3. Effects and motion

EffectText adds common visual effects and movement helpers on top of Text.

fx = animpy.EffectText("Bounce", 10, 2)
fx.shaking_text(intensity=2)
fx.gravity_text(floor=10, gravity=0.5)

4. Groups

A Group lets you manage many objects as one unit. Position and color changes can be applied to the entire group.

group = animpy.Group()
group.add(animpy.Text("A", 1, 1), animpy.Text("B", 4, 1))
group.position(2, 0)

5. Camera

A Camera provides a simple view transform for a scene. You can point it at a target object or keep a custom offset.

scene = animpy.Scene()
player = animpy.Text("P", 10, 5)
scene.add(player)

camera = animpy.Camera((0, 0), None)
camera.follow(player)
scene.camera = camera
scene.render()

Feature reference

Text

Text is the base class for terminal objects.

text = animpy.Text("Hello", 2, 2, r=255, g=255, b=255)

Common methods:

  • change_frame() — advance to the next frame if the text was created from a list
  • set_frame(index) — switch to a specific frame
  • set_text(text) — replace the text content or frame list
  • set_position(x, y) — directly set the position
  • move_to(x, y) — alias for set_position
  • set_color(r, g, b) — update the color using RGB values
  • change_rgb_values(r, g, b) — same as set_color
  • moveX(dx) — move horizontally
  • moveY(dy) — move vertically
  • slide_to_pos(new_pos, speed=1) — move smoothly toward a coordinate-like object
  • centerX() — center the text horizontally
  • centerY() — center the text vertically
  • collides_with(other) — test for bounding-box overlap
  • on_collide_callback(other, callback) — run a callback when collision occurs
  • type_out(text, speed=0.05, scene=None) — print text gradually, optionally rendering after each character
  • fall(velocity, floor) — move the object downward until a floor is reached

Useful properties:

  • width — number of characters in the current frame
  • height — number of lines in the current frame
  • current_frame — current frame index

EffectText

EffectText extends Text with reusable animation effects and velocity support.

fx = animpy.EffectText("Shaky", 5, 5)
fx.shaking_text(intensity=2)
fx.gravity_text(floor=10, gravity=0.5)
fx.pulse_text(time=1.0, pulse_rate=0.5)

Available methods:

  • gravity_text(floor=20, gravity=0.5) — apply gravity and clamp to a floor
  • shaking_text(intensity=1) — jitter position randomly
  • decaying_text(time, decay_rate=0.1) — shorten the text over time
  • fade_out_text(time, fade_rate=0.1) — fade the object toward black
  • lerp_text(target_x, target_y, t) — interpolate smoothly to a target position
  • pulse_text(time, pulse_rate=0.5) — change brightness over time
  • set_velocity(vx, vy) — set motion in X/Y
  • reset_velocity() — clear velocity values
  • apply_force(fx, fy) — add to the current velocity
  • fade_in_text(time, fade_rate=0.1) — fade in over time

Shapes

Shapes return multi-line strings that can be used as text content.

rect = animpy.Shapes.rectangle(8, 4, "#")
circle = animpy.Shapes.circle(4, "*")
line = animpy.Shapes.line(0, 0, 10, 4, "-")
heart = animpy.Shapes.heart(5, "♥")
triangle = animpy.Shapes.triangle(0, 0, 6, 0, 3, 5, "^")
ellipse = animpy.Shapes.ellipse(6, 3, 4, 2, "o")
square = animpy.Shapes.square(5, "#")
donut = animpy.Shapes.donut(5, 2, "#")

Supported builders:

  • rectangle(width, height, char)
  • circle(radius, char)
  • polygon(points, char)
  • line(x1, y1, x2, y2, char)
  • triangle(x1, y1, x2, y2, x3, y3, char)
  • ellipse(center_x, center_y, radius_x, radius_y, char)
  • heart(size, char)
  • square(size, char)
  • donut(outer_radius, inner_radius, char)

Group

A Group collects multiple objects so they can be moved or recolored together.

group = animpy.Group()
text1 = animpy.Text("A", 0, 0)
text2 = animpy.Text("B", 2, 0)
group.add(text1, text2)

group.position(3, 1)
group.change_rgb_values(0, 255, 0)

Available methods:

  • add(*items) — add one or more objects
  • remove(*items) — remove one or more objects
  • clear() — remove all items
  • contains(item) — check if an item exists in the group
  • find_by_color(r, g, b) — return matching items by color
  • position(newx, newy) — shift every item by an offset
  • change_rgb_values(r, g, b) — recolor every item
  • change_rgb_values_one(item, r, g, b) — recolor a single item

Coords, Keyframe, and KeyChains

These helpers support path-based movement.

from animpy import Coords, Keyframe, KeyChains

start = Coords(0, 0)
mid = Coords(10, 3)
end = Coords(15, 8)

path = KeyChains(Keyframe(start), Keyframe(mid), Keyframe(end))
path.follow_path(text, speed=1)
  • Coords(x, y) — simple coordinate container
  • distance_to(other) — calculate Euclidean distance
  • offset(dx, dy) — return a new offset coordinate
  • Keyframe(pos) — stores a target position
  • set_pos(pos) — update keyframe position
  • distance_to(other) — measure the distance to another keyframe or coordinate
  • KeyChains(*keyframes) — store a list of keyframes
  • append(keyframe) — add a keyframe
  • clear() — remove all keyframes
  • reverse_path() — reverse the path order
  • is_complete — becomes True once the path has no more keyframes
  • follow_path(obj, speed=1) — moves an object toward the current keyframe

Scene

A Scene handles rendering and object management.

scene = animpy.Scene()
scene.add(text1, text2)
scene.remove(text2)
scene.render()

Useful methods:

  • add(*items) — add objects to the scene
  • remove(*items) — remove objects from the scene
  • render() — draw the current frame to the terminal
  • update(delta_time) — update particles and remove expired items
  • set_bg_rgb(r, g, b) — set a background color
  • shake(intensity=1) — apply a random shaking offset
  • clear() — clear the terminal display
  • clear_items() — remove every object from the scene
  • count_items() — return the number of scene items
  • find_items_at(x, y) — return the objects sitting at a coordinate

Scene properties:

  • dt — elapsed time since the last frame
  • offset_x, offset_y — manual rendering offsets
  • camera — optional Camera attached to the scene

Camera

The Camera helper lets a scene render from a different view.

camera = animpy.Camera((0, 0), None)
camera.follow(player)
scene.camera = camera
scene.render()

Available methods:

  • move(new_position) — set the camera position directly
  • look_at(new_target) — point the camera at a new target
  • follow(target_object) — track an object by reference
  • get_view_matrix() — return the current view position as a tuple

PhysicsScene

PhysicsScene adds simple physical motion helpers to a scene.

scene = animpy.PhysicsScene()
ball = animpy.EffectText("O", 2, 2)
scene.add(ball)

scene.apply_gravity(ball)
scene.apply_friction(ball, friction=0.1)
scene.bounce(ball, bounce_factor=0.7)
scene.apply_physics(ball)
scene.angular_motion(ball, angle=45, speed=2.0)
scene.push(ball, force_x=0.5, force_y=-0.2)

Available methods:

  • apply_gravity(obj) — move an object downward toward the floor
  • apply_friction(obj, friction=0.1) — reduce velocity over time
  • bounce(obj, bounce_factor=0.5) — reverse vertical motion when hitting the floor
  • apply_physics(obj) — combine gravity, friction, and bounce
  • angular_motion(obj, angle, speed) — set an angled velocity
  • push(obj, force_x, force_y) — add force in X/Y directions

InteractiveScene

InteractiveScene makes it possible to react to keyboard and mouse input.

scene = animpy.InteractiveScene()
player = animpy.Text("P", 10, 10)
scene.add(player)

while True:
    if scene.key_pressed("w"):
        player.moveY(-1)
    if scene.key_pressed("s"):
        player.moveY(1)
    if scene.key_pressed("esc"):
        break
    scene.render()

Available methods:

  • key_pressed(key) — check whether a key is held down
  • key_released(key) — check whether a key has been released
  • on_key_press_callback(key, callback) — run a callback when a key is pressed
  • on_key_release_callback(key, callback) — run a callback when a key is released
  • mouse_pressed(button="left") — check whether a mouse button is held down
  • mouse_position() — return the current mouse position
  • on_mouse_press_callback(button, callback) — run a callback when a mouse button is pressed
  • mouse_release(button, callback) — run a callback when a button is released
  • mouse_release_callback(button, callback) — alias for the release callback helper
  • quick_exit(key="esc") — exit immediately when a key is pressed
  • quick_exit_callback(key, callback) — run a callback when a key is pressed
  • limit_to_bounds(obj) — keep an object inside the terminal area
  • limit_group_to_bounds(group) — keep every object in a group inside the terminal area

Particles

Particles are useful for trails, explosions, smoke, sparks, and other visual effects.

particle = animpy.Particle("*", 10, 5, r=255, g=150, b=50, lifetime=2.0)
particle.burst(scene, count=20, speed=1.5)

Available methods:

  • update(delta_time) — advance the particle in time
  • emit(scene) — add a single particle to the scene
  • burst(scene, count=10, speed=1.0) — create many particles with random velocities
  • change_rgb_values(r, g, b) — change the particle color
  • set_velocity(vx, vy) — set particle velocity
  • apply_force(fx, fy) — add velocity changes
  • set_color(r, g, b) — alias for setting color
  • reset(x, y, lifetime=None) — reset particle position and age
  • is_alive() — check whether the particle is still alive
  • update_all(delta_time) — update all particle children created by the parent
  • is_dead() — check whether all tracked particles are dead

There are also built-in particle presets:

  • Presets.create_explosion(x, y, count=20, speed=1.0, lifetime=1.0)
  • Presets.create_smoke(x, y, count=10, speed=0.5, lifetime=2.0)
  • Presets.create_firework(x, y, count=30, speed=2.0, lifetime=1.5)

Audio

Audio support is built on pygame and can be used to add music or effects.

audio = animpy.Audio()
audio.load("bg", "music.mp3")
audio.play("bg", loop=-1)
audio.set_volume("bg", 0.5)

Available methods:

  • load(name, file_path) — load an audio file
  • play(name, loop=0) — start playback
  • stop(name) — stop a specific sound
  • stop_all() — stop everything
  • is_playing(name=None) — check whether a sound is active
  • set_volume(name, volume) — update a volume level
  • pause(name) — pause playback
  • resume(name) — resume playback
  • fade_out(name, duration) — fade the sound out
  • fade_in(name, duration, loop=0) — fade in and optionally loop
  • play_for_time(name, duration) — play for a set length and stop automatically

Terminal utilities

Animpy also includes helpers for terminal output.

animpy.hide_cursor()
animpy.show_cursor()
animpy.clear_screen()
animpy.print_centered("Centered")
animpy.print_with_color("Colored", r=255, g=0, b=0)
animpy.print_panel("Hello", title="Info")

Available helpers:

  • lerp(start, end, t) — linear interpolation
  • hide_cursor() / show_cursor()
  • clear_screen()
  • print_centered(text)
  • print_with_color(text, r, g, b)
  • print_panel(text, title="Panel", style="bold white on blue")
  • ANSI color constants such as animpy.ANSI["red"] and animpy.ANSI["bg_blue"]
  • terminal size helpers such as get_terminal_size(), set_terminal_size(columns, lines), reset_terminal_size(), get_terminal_width(), and get_terminal_height()

Example projects

The repository contains examples for:

  • basic movement and interpolation
  • renderer compositing with camera, groups, particles, z-order, and backgrounds
  • loading screens
  • visual effects
  • physics demos
  • player controls
  • collision and tag-style games
  • audio playback

You can browse the examples folder in the project repository for complete scripts.

Version history

v2.6.0

Added a new Camera class for scene view transformation and object tracking. All existing particle and utility methods now work seamlessly with camera-enabled scenes.

New Camera class:

  • Camera(position, target=None) — Constructor that creates a camera at a specific position with an optional target
    • position — tuple of (x, y) representing the camera's current location
    • target — optional object or position to point the camera at; defaults to None

Camera methods:

  • move(new_position) — Directly set the camera position to a new tuple (x, y)
  • look_at(new_target) — Point the camera at a new target position or object
  • follow(target_object) — Continuously track a Text or object with x and y properties
  • get_view_matrix() — Return the current camera view as a tuple (x, y)

Scene camera support:

  • Scene.camera — New optional property to attach a Camera instance
    • Assign a Camera to enable camera-based rendering offsets
    • When set, all objects render relative to the camera's viewpoint
    • Works with all scene objects: Text, Particles, Shapes, Groups

Particle class methods (now camera-compatible):

  • update(delta_time) — Advance particle age and position
  • emit(scene) — Add a single particle instance to the scene
  • burst(scene, count=10, speed=1.0) — Create multiple particles with random velocities in all directions
  • change_rgb_values(r, g, b) — Update particle color
  • set_velocity(vx, vy) — Set particle velocity directly
  • apply_force(fx, fy) — Add velocity changes via force
  • set_color(r, g, b) — Alias for changing color
  • reset(x, y, lifetime=None) — Reset particle position and age
  • is_alive() — Check if particle is still active
  • update_all(delta_time) — Update all child particles created by burst
  • is_dead() — Check if all tracked particles have expired

Particle Presets class (now camera-compatible):

  • Presets.create_explosion(x, y, count=20, speed=1.0, lifetime=1.0) — Create an explosion effect
  • Presets.create_smoke(x, y, count=10, speed=0.5, lifetime=2.0) — Create a smoke effect
  • Presets.create_firework(x, y, count=30, speed=2.0, lifetime=1.5) — Create a firework effect

Utility functions (now camera-compatible):

  • lerp(start, end, t) — Linear interpolation between start and end values
  • hide_cursor() — Hide the terminal cursor
  • show_cursor() — Show the terminal cursor
  • clear_screen() — Clear terminal display
  • print_panel(text, title="Panel", style="bold white on blue") — Print text in a styled panel
  • print_centered(text) — Print text centered in the terminal
  • print_with_color(text, r, g, b) — Print colored text using RGB values
  • get_terminal_size() — Return current terminal dimensions
  • set_terminal_size(columns, lines) — Set terminal size
  • reset_terminal_size() — Reset terminal size to defaults
  • get_terminal_width() — Get terminal column count
  • get_terminal_height() — Get terminal line count
  • ANSI — Dictionary of ANSI color and style codes for advanced terminal formatting

v2.5.0

  • Added coordinate helpers such as Coords.distance_to() and Coords.offset()
  • Added Keyframe and KeyChains helpers for path-based motion
  • Added Audio.pause(), Audio.resume(), Audio.fade_in(), and Audio.fade_out()
  • Added Group.clear(), Group.contains(), and Group.find_by_color()
  • Added particle helpers such as set_velocity(), apply_force(), set_color(), reset(), and is_alive()
  • Added scene helpers such as clear_items(), count_items(), and find_items_at()
  • Added shape builders square() and donut()
  • Added text convenience setters such as set_frame(), set_text(), set_position(), move_to(), and set_color()

v2.1.0

  • Added Shapes.line(), Shapes.ellipse(), Shapes.heart(), and Shapes.triangle()
  • Added clear_screen(), print_centered(), and print_with_color()

v2.0.0

  • Added PhysicsScene for gravity, friction, bounce, and force-driven motion
  • Added EffectText animation helpers such as fade_out_text(), lerp_text(), and pulse_text()
  • Added interactive scene helpers such as limit_to_bounds(), quick_exit(), and limit_group_to_bounds()

Support

If you enjoy Animpy, please consider starring the project on GitHub:

https://github.com/13DoesPython/animpy

Release files for animpy 3.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for animpy 3.5.0
File Size Uploaded
animpy-3.5.0.tar.gz 23.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for animpy 3.5.0
File Interpreter ABI Platform
animpy-3.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 42.0 kB

Release files / animpy-3.5.0.tar.gz

Download URL animpy-3.5.0.tar.gz
Size 23.1 kB
Tags Source
SHA-256 checksum
How to use checksums
095a5aa5193b63b17cded762565b1b4bdf67425258e357d082e7174d6020f0d4
BLAKE2b-256 checksum
How to use checksums
2c6cd46a23499b685ff4c128f34f1563c22373e1b26411b9ddb566e64b6754ea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release files / animpy-3.5.0-py3-none-any.whl

Download URL animpy-3.5.0-py3-none-any.whl
Size 18.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
64a8f053a623cb453d459304a8b7756ce27d55d6ef205967311c5d900f9b36fe
BLAKE2b-256 checksum
How to use checksums
7ad13a503a3ceeb4774a32d6654a1085c12c5ad4fc5b5be36d295ce9c5a9d7f0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release history Release notifications | RSS feed

This release

3.5.0 This release

2 release files

3.0.0

2 release files

2.5.0

2 release files

2.1.1

2 release files

2.1.0

2 release files

2.0.0

2 release files

1.8.5

2 release files

1.8.0

2 release files

1.7.1

2 release files

1.7.0

2 release files

1.6.5

2 release files

1.6.0

2 release files

1.5.11

2 release files

1.5.8

2 release files

1.5.5

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.24

2 release files

1.4.23

2 release files

1.4.5

2 release files

1.4.2

2 release files

1.4.1

2 release files

1.4.0

2 release files

1.3.9

2 release files

1.3.8

2 release files

1.3.5

2 release files

1.3.1

2 release files

1.3

2 release files

1.2.1

2 release files

1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page