This release is a pre-release and may not be stable for production use.
PyChelonia
PyChelonia brings a familiar Turtle-style drawing API to
pygame.Surface. It is designed for pygame applications that want simple
position, heading, line, circle, fill, dot, and text commands without giving
up control of their window, event loop, composition, or shutdown lifecycle.
PyChelonia is a selected reimplementation, not a drop-in replacement for the
complete Python turtle module.
The sea turtle is drawn on one transparent Chelonia Surface and composed with a pygame-owned background, layout, text, display, and frame loop.
Why PyChelonia?
- Draw with Turtle-style movement instead of calculating rotation matrices for every line.
- Use the result as a normal pygame Surface alongside sprites, UI, and other application rendering.
- Redraw in real time while the host application keeps control of timing and events.
- Test drawing offscreen without creating a pygame window.
- Keep each drawing object isolated on one dedicated Surface.
Quick Start
from pychelonia import Chelonia
turtle = Chelonia((800, 600), alpha=True)
turtle.pencolor(20, 40, 220)
turtle.pensize(3)
turtle.forward(100)
turtle.left(90)
turtle.forward(50)
surface = turtle.surface
Turtle is an alias for Chelonia:
from pychelonia import Chelonia, Turtle
assert Turtle is Chelonia
Requirements
- Python 3.11 or newer
- pygame 2.1.3 or newer
Installation
PyChelonia 1.0.0rc1 is prepared but has not been published to PyPI. Install
the current source from a local checkout:
git clone https://github.com/Imagination12357/PyChelonia.git
cd PyChelonia
python -m pip install .
After publication, the release candidate is intended to be installable with:
python -m pip install --pre pychelonia==1.0.0rc1
That command is not a current availability claim.
For development with uv:
uv sync --extra dev
See the
changelog
and
draft 1.0.0rc1 release notes
for release status and compatibility details.
Pygame Integration
The host application owns pygame initialization, its window and event loop, and composition of the dedicated Chelonia Surface:
import pygame
from pychelonia import Chelonia
pygame.init()
screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
turtle = Chelonia(screen.get_size(), alpha=True)
turtle.pencolor("navy")
turtle.forward(100)
turtle.left(90)
turtle.forward(50)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill("white")
screen.blit(turtle.surface, (0, 0))
pygame.display.flip()
clock.tick(60)
pygame.quit()
PyChelonia only updates turtle.surface. It does not initialize pygame,
create the display, process events, blit to the window, update the display, or
shut pygame down.
Surface Ownership
The 1 Chelonia = 1 dedicated Surface rule is part of the current contract.
Do not attach multiple instances to the same Surface or concurrently modify a
Chelonia-owned Surface from other drawing code.
Three construction forms are supported:
import pygame
from pychelonia import Chelonia
supplied = pygame.Surface((800, 600))
direct = Chelonia(supplied)
from_tuple = Chelonia((800, 600))
from_dimensions = Chelonia(800, 600)
assert direct.surface is supplied
The surface property is getter-only and preserves object identity. The
returned pygame Surface remains mutable because the host must be able to blit
and inspect it.
Internally created surfaces can use per-pixel alpha:
import pygame
from pychelonia import Chelonia
turtle = Chelonia((800, 600), alpha=True)
assert turtle.surface.get_flags() & pygame.SRCALPHA
- Opaque internal surfaces default to white.
- Alpha surfaces default to transparent.
- Every constructor clears the complete active Surface, including a directly supplied Surface.
background_colorchanges the color used by futureclear()andreset()calls; assigning it does not repaint immediately.alpha=Trueis only valid for internally created surfaces. A supplied Surface keeps its existing pixel format.
Coordinate Model
PyChelonia uses centered, y-up Turtle coordinates:
(0, 0)is the center of the Surface.- Heading
0points right. - Heading
90points up. - Positive
ymoves upward.
Conversion to pygame's top-left, y-down coordinates happens internally.
Supported API
| Area | Methods and properties |
|---|---|
| Movement | forward/fd, backward/back/bk, goto/setpos/setposition, teleport, setx, sety, home |
| Rotation | left/lt, right/rt, setheading/seth, heading, towards |
| Drawing | circle, dot, begin_fill, filling, end_fill, write |
| Position | position/pos, xcor, ycor, distance |
| Pen | penup/up/pu, pendown/down/pd, isdown, pen, pencolor, pensize/width |
| Style | fillcolor, color |
| Identity | getpen/getturtle |
| Visibility state | showturtle/st, hideturtle/ht, isvisible |
| Surface | surface, background_color, clear, reset |
Colors and Width
Color setters accept one pygame-compatible color value or fixed-range
red, green, blue integer channels. Getters return copied pygame.Color
values.
turtle.pencolor("navy")
turtle.fillcolor(40, 190, 120)
turtle.color("black", "orange")
turtle.color(20, 40, 220)
color() returns the pen and fill colors. Setter changes are atomic: if any
supplied color is invalid, neither stored color changes. Explicit None is an
invalid setter value.
Pen widths accept positive integer-valued real numbers and are stored as integer pixel widths.
Position and Teleport
position() and pos() return the exported tuple-compatible Vec2D.
Constructor position, goto, towards, and distance accept exact-two
point-like iterables such as tuples, lists, Vec2D, and pygame.Vector2.
teleport(x=None, y=None, *, fill_gap=False) moves without drawing or changing
persistent pen state. During an active fill, the default commits the current
polygon and begins another at the destination. fill_gap=True keeps one fill
path across the invisible movement.
Fill and Text
Polygon filling uses the familiar lifecycle:
turtle = Chelonia((200, 200), fillcolor="orange")
turtle.begin_fill()
for _ in range(4):
turtle.forward(60)
turtle.left(90)
turtle.end_fill()
Fill paths include pen-up movement and sampled circle points. The public Surface object remains stable throughout fill composition.
Text requires a caller-created pygame.font.Font:
import pygame
pygame.font.init()
font = pygame.font.Font(None, 24)
turtle.write("PyChelonia", align="center", font=font)
PyChelonia does not initialize or shut down the font subsystem. Text remains
unrotated and uses the current pen color. write(move=True) moves normally to
the rendered text's right edge.
Clear, Reset, and Visibility
clear() fills the dedicated Surface with background_color while preserving
persistent Turtle state. reset() also restores library defaults. Both
cancel an unfinished fill without replacing the Surface object.
Visibility is logical state only. PyChelonia does not render a turtle cursor.
Compatibility and Limits
The current compatibility matrix contains 32 selected rows:
- 17
Match - 10
Partial - 5
Intentional difference - 0
Unsupported
Important current limits:
- Tk color modes and the complete Tk color-name database are not reproduced.
- Fractional pixel widths are not rendered.
- pygame and Tk Canvas do not produce pixel-identical geometry.
- Direct external Surface mutation during an active fill cannot be guaranteed to survive final fill composition.
- Cursor shapes, stamps, cursor events, animation, undo history, and pygame lifecycle ownership are outside the active scope.
degrees()andradians()are deferred until after1.0.0.
See the selected compatibility matrix and known differences from Python Turtle for exact behavior and test evidence.
Example
The looping README showcase focuses on visual Surface composition:
uv run python examples/readme_showcase.py
The original interactive timer demo shows real-time redraw and rotation without manual matrix calculations:
uv run python examples/pychelonia_demo.py
Both demos open a pygame window and are manual visual examples. Regenerate the README animation without opening a window:
uv run --with pillow python tools/render_readme_gif.py
Development
Run the smoke check and test suite from a checkout:
uv run python main.py
uv run --extra dev pytest
The automated suite uses in-memory pygame surfaces and must not create an application window.
Support
Review the compatibility matrix and known differences before reporting a problem. Bugs and focused compatibility requests can be filed in GitHub Issues. Include the Python and pygame versions, a minimal reproduction, and whether the Surface uses per-pixel alpha.
License and Maintainer
PyChelonia is maintained by @imagination12357 and distributed under the MIT License.
Metadata
Release files for pychelonia 1.0.0rc1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pychelonia-1.0.0rc1.tar.gz | 916.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pychelonia-1.0.0rc1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 933.0 kB
Release files / pychelonia-1.0.0rc1.tar.gz
| Download URL | pychelonia-1.0.0rc1.tar.gz |
|---|---|
| Size | 916.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bbc10a97987dd52d9de40b9882b5da6c2e6bb2a90789c3e600a37906b23b9e88
|
|
BLAKE2b-256 checksum How to use checksums |
6cce6128cd3f2d850b2fb9294e67547ba2a76b7ecb188db5c7f8eacc1b781079
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.10
|
Release files / pychelonia-1.0.0rc1-py3-none-any.whl
| Download URL | pychelonia-1.0.0rc1-py3-none-any.whl |
|---|---|
| Size | 16.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
10b3154795089dd404d2a484c33cc1170449b78120e9f95a4c588eb2b36d16a6
|
|
BLAKE2b-256 checksum How to use checksums |
e83f039286bbe2cf746f716b262ddf9a88ea14bc560cbb8f1ac46c762004d154
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.10
|