A simple terminal animation library
Project description
Animpy
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-cekeyboardmouserich
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. 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 listset_frame(index)— switch to a specific frameset_text(text)— replace the text content or frame listset_position(x, y)— directly set the positionmove_to(x, y)— alias forset_positionset_color(r, g, b)— update the color using RGB valueschange_rgb_values(r, g, b)— same asset_colormoveX(dx)— move horizontallymoveY(dy)— move verticallyslide_to_pos(new_pos, speed=1)— move smoothly toward a coordinate-like objectcenterX()— center the text horizontallycenterY()— center the text verticallycollides_with(other)— test for bounding-box overlapon_collide_callback(other, callback)— run a callback when collision occurstype_out(text, speed=0.05, scene=None)— print text gradually, optionally rendering after each characterfall(velocity, floor)— move the object downward until a floor is reached
Useful properties:
width— number of characters in the current frameheight— number of lines in the current framecurrent_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 floorshaking_text(intensity=1)— jitter position randomlydecaying_text(time, decay_rate=0.1)— shorten the text over timefade_out_text(time, fade_rate=0.1)— fade the object toward blacklerp_text(target_x, target_y, t)— interpolate smoothly to a target positionpulse_text(time, pulse_rate=0.5)— change brightness over timeset_velocity(vx, vy)— set motion in X/Yreset_velocity()— clear velocity valuesapply_force(fx, fy)— add to the current velocityfade_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 objectsremove(*items)— remove one or more objectsclear()— remove all itemscontains(item)— check if an item exists in the groupfind_by_color(r, g, b)— return matching items by colorposition(newx, newy)— shift every item by an offsetchange_rgb_values(r, g, b)— recolor every itemchange_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 containerdistance_to(other)— calculate Euclidean distanceoffset(dx, dy)— return a new offset coordinateKeyframe(pos)— stores a target positionset_pos(pos)— update keyframe positiondistance_to(other)— measure the distance to another keyframe or coordinateKeyChains(*keyframes)— store a list of keyframesappend(keyframe)— add a keyframeclear()— remove all keyframesreverse_path()— reverse the path orderis_complete— becomesTrueonce the path has no more keyframesfollow_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 sceneremove(*items)— remove objects from the scenerender()— draw the current frame to the terminalupdate(delta_time)— update particles and remove expired itemsset_bg_rgb(r, g, b)— set a background colorshake(intensity=1)— apply a random shaking offsetclear()— clear the terminal displayclear_items()— remove every object from the scenecount_items()— return the number of scene itemsfind_items_at(x, y)— return the objects sitting at a coordinate
Scene properties:
dt— elapsed time since the last frameoffset_x,offset_y— manual rendering offsetscamera— optionalCameraattached 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 directlylook_at(new_target)— point the camera at a new targetfollow(target_object)— track an object by referenceget_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 floorapply_friction(obj, friction=0.1)— reduce velocity over timebounce(obj, bounce_factor=0.5)— reverse vertical motion when hitting the floorapply_physics(obj)— combine gravity, friction, and bounceangular_motion(obj, angle, speed)— set an angled velocitypush(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 downkey_released(key)— check whether a key has been releasedon_key_press_callback(key, callback)— run a callback when a key is pressedon_key_release_callback(key, callback)— run a callback when a key is releasedmouse_pressed(button="left")— check whether a mouse button is held downmouse_position()— return the current mouse positionon_mouse_press_callback(button, callback)— run a callback when a mouse button is pressedmouse_release(button, callback)— run a callback when a button is releasedmouse_release_callback(button, callback)— alias for the release callback helperquick_exit(key="esc")— exit immediately when a key is pressedquick_exit_callback(key, callback)— run a callback when a key is pressedlimit_to_bounds(obj)— keep an object inside the terminal arealimit_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 timeemit(scene)— add a single particle to the sceneburst(scene, count=10, speed=1.0)— create many particles with random velocitieschange_rgb_values(r, g, b)— change the particle colorset_velocity(vx, vy)— set particle velocityapply_force(fx, fy)— add velocity changesset_color(r, g, b)— alias for setting colorreset(x, y, lifetime=None)— reset particle position and ageis_alive()— check whether the particle is still aliveupdate_all(delta_time)— update all particle children created by the parentis_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 fileplay(name, loop=0)— start playbackstop(name)— stop a specific soundstop_all()— stop everythingis_playing(name=None)— check whether a sound is activeset_volume(name, volume)— update a volume levelpause(name)— pause playbackresume(name)— resume playbackfade_out(name, duration)— fade the sound outfade_in(name, duration, loop=0)— fade in and optionally loopplay_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 interpolationhide_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"]andanimpy.ANSI["bg_blue"] - terminal size helpers such as
get_terminal_size(),set_terminal_size(columns, lines),reset_terminal_size(),get_terminal_width(), andget_terminal_height()
Example projects
The repository contains examples for:
- basic movement and interpolation
- 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 targetposition— tuple of (x, y) representing the camera's current locationtarget— optional object or position to point the camera at; defaults toNone
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 objectfollow(target_object)— Continuously track a Text or object withxandypropertiesget_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 positionemit(scene)— Add a single particle instance to the sceneburst(scene, count=10, speed=1.0)— Create multiple particles with random velocities in all directionschange_rgb_values(r, g, b)— Update particle colorset_velocity(vx, vy)— Set particle velocity directlyapply_force(fx, fy)— Add velocity changes via forceset_color(r, g, b)— Alias for changing colorreset(x, y, lifetime=None)— Reset particle position and ageis_alive()— Check if particle is still activeupdate_all(delta_time)— Update all child particles created by burstis_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 effectPresets.create_smoke(x, y, count=10, speed=0.5, lifetime=2.0)— Create a smoke effectPresets.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 valueshide_cursor()— Hide the terminal cursorshow_cursor()— Show the terminal cursorclear_screen()— Clear terminal displayprint_panel(text, title="Panel", style="bold white on blue")— Print text in a styled panelprint_centered(text)— Print text centered in the terminalprint_with_color(text, r, g, b)— Print colored text using RGB valuesget_terminal_size()— Return current terminal dimensionsset_terminal_size(columns, lines)— Set terminal sizereset_terminal_size()— Reset terminal size to defaultsget_terminal_width()— Get terminal column countget_terminal_height()— Get terminal line countANSI— Dictionary of ANSI color and style codes for advanced terminal formatting
v2.5.0
- Added coordinate helpers such as
Coords.distance_to()andCoords.offset() - Added
KeyframeandKeyChainshelpers for path-based motion - Added
Audio.pause(),Audio.resume(),Audio.fade_in(), andAudio.fade_out() - Added
Group.clear(),Group.contains(), andGroup.find_by_color() - Added particle helpers such as
set_velocity(),apply_force(),set_color(),reset(), andis_alive() - Added scene helpers such as
clear_items(),count_items(), andfind_items_at() - Added shape builders
square()anddonut() - Added text convenience setters such as
set_frame(),set_text(),set_position(),move_to(), andset_color()
v2.1.0
- Added
Shapes.line(),Shapes.ellipse(),Shapes.heart(), andShapes.triangle() - Added
clear_screen(),print_centered(), andprint_with_color()
v2.0.0
- Added
PhysicsScenefor gravity, friction, bounce, and force-driven motion - Added
EffectTextanimation helpers such asfade_out_text(),lerp_text(), andpulse_text() - Added interactive scene helpers such as
limit_to_bounds(),quick_exit(), andlimit_group_to_bounds()
Support
If you enjoy Animpy, please consider starring the project on GitHub:
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file animpy-3.0.0.tar.gz.
File metadata
- Download URL: animpy-3.0.0.tar.gz
- Upload date:
- Size: 21.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
21ba5b249cec66dfd74aae278530db4486fc9450e7b330da0a8b35de2a136628
|
|
| MD5 |
93f6ff937d7c40d0e5d4a2446fcd79d2
|
|
| BLAKE2b-256 |
fe3b278b6ca20b9ad1feeb2c76fe87bd5fbf234251d96f973ba693e958f41d88
|
File details
Details for the file animpy-3.0.0-py3-none-any.whl.
File metadata
- Download URL: animpy-3.0.0-py3-none-any.whl
- Upload date:
- Size: 18.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
273b241ce02ee7f22afa090dbf31e9613c08fbfec09a69466f2a1399f1a0a6fc
|
|
| MD5 |
0cd67c36f9035bcf31fddffa64712d70
|
|
| BLAKE2b-256 |
082eeb3a7f059e8693ca75649baa74785338e0fcaf58a51399cb17a0eb0819a9
|