PyEngine 2D is a lightweight, purely Python-based 2D game engine built with Pygame, inspired by Godot's scene and node system. It focuses on architectural clarity, explicit systems, and educational value.
Note
This project is an experimental prototype focusing on learning and extensibility rather than raw performance.
| Level | Layer | Status |
|---|---|---|
| 0 | Runtime Core | ✅ |
| 1 | Scene System | ✅ |
| 2 | Collision System | ✅ |
| 3 | Physics Layer | ✅ |
| 4 | Gameplay Layer | ✅ |
| 5 | State Layer (FSM) | ✅ |
| 6 | Juice & Animation Layer | ✅ |
| 7 | User Interface (UI) | ✅ |
| 8 | Tilemap Level | ✅ |
| 9 | Audio Layer | ✅ |
| 10 | Scene Editor (GUI) | ✅ |
- Game loop, delta timing, base
Nodeclass, scene tree hierarchy.
- Parent/child transform propagation, local vs global position, update lifecycle.
TilemapNode: Multi-layer tilemap supporting JSON and TMX files, baked surfaces, auto-collision generation, viewport streaming, and parallax.
- Collider2D: Scale-aware AABB — dimensions, layer/mask, static/trigger flags, optional
visibledebug overlay. - CircleCollider2D: Circle-circle and circle-AABB colliders.
- PolygonCollider2D: Convex polygon collisions resolved via SAT (Separating Axis Theorem).
- CollisionWorld: Float-precision shape overlap checks with MTV resolution + layer/mask filtering.
- PhysicsBody2D: Per-axis move-and-collide with float precision (ideal for platformers).
- RigidBody2D: Advanced dynamic physics body with mass, coefficient of restitution (bounciness), and true elastic momentum transfer.
- PhysicsWorld2D: Independent solver node providing localized simulation sub-stepping (e.g., 10 passes per frame) to prevent constraint and tunneling jitters.
- DistanceConstraint: Perfect springless rope/anchor simulation utilizing 2D circular tangent projection.
- Gravity and Impulses: Configurable forces including overlapping mass exchange.
- PlayerController: Engine-agnostic input → physics bridge.
- Ground Detection: Non-invasive downward probe check via
CollisionWorld.
- PlayerStateMachine with concrete states (
IdleState,RunState,JumpState,FallState).
- TweenManager, ParticleEmitter2D, AnimatedSprite, SpriteNode, parallax backgrounds.
- UIControl, containers (
VBoxContainer,HBoxContainer),Button,Label. - Hierarchical event consumption + reactive data binding.
draw2d.py: Standalone infinite-canvas 4-quadrant map editor.- Zoom (scroll wheel), Pan (Space+Click or Middle-click), Draw (Left-click), Erase (Right-click).
- Press [S] to save JSON; [L] to load. Auto-tiling picks correct Left/Mid/Right/Underground edge tiles.
- Output consumed directly by
TilemapNode.load_from_json()in-game.
- AudioManager: Global
pygame.mixerwrapper serving as a unified interface to load and play SFX (play_sound) and stream background music (play_music).
- The Editor (
src/the_editor/): Flutter-based 2D scene editor. - Dockable panels: Scene Tree, Viewport, Inspector, Bottom Panel.
.sceneJSON file format for saving/loading scene trees.
- Infinite 4-Quadrant Canvas: Draw geometry at any positive or negative coordinates.
- Engine Integration:
TilemapNodereadsoffset_x/offset_yto place tiles at exact world-space positions.
- Scale-Aware Hitboxes: Colliders adapt automatically when nodes are tweened.
- Engine-Agnostic Controllers:
PlayerControllernever importspygame. - FSM: Decouples behavioral identity from physics movement.
- Axis-Separated Resolution with float precision and inclusive epsilon bounds.
src/
├── pyengine2D/ # Core engine (reusable)
│ ├── benchmark/ # Performance testing harness
│ ├── collision/ # Collider2D, CircleCollider2D, PolygonCollider2D, CollisionWorld
│ ├── core/ # Engine, Input, Renderer, Audio, Signals
│ ├── fsm/ # State, StateMachine, IdleState, WalkState, FallState
│ ├── physics/ # PhysicsBody2D, RigidBody2D, PhysicsWorld2D, DistanceConstraint
│ ├── rendering/ # Renderer2D, BatchRenderer, TextureAtlas, SurfaceCache, PixelGrid
│ ├── scene/ # Node, Node2D, Camera2D, TilemapNode, AnimatedSprite, Particles
│ ├── time/ # MasterClock (fixed timestep scheduling)
│ ├── ui/ # UIControl, Containers, Widgets, EventSystem, DataBinding
│ └── utils/ # Profiler, ObjectPool, AssetManager, Pathfinding
│
└── games/ # Game examples
├── frog_hop/ # Side-scrolling platformer (Ninja Frog + Fruits)
│ ├── entities/ # Player, Fruit, Enemy, Trap
│ ├── maps/ # JSON tilemaps
│ ├── level.py # Level builder
│ └── main.py
├── breakout/ # Brick-breaking game (paddle + ball)
├── neon_heights/
├── neon_odyssey/
├── neon_tank/
└── newtons_cradle/ # Rigid body simulation
draw2d.py # Infinite 4-Quadrant Map Editor → JSON tilemaps
tests/
└── headless_verify.py # Headless engine verification test
src/the_editor/ # Flutter-based Scene Editor
lib/
├── main.dart # Entry point
├── main_layout.dart # Main editor layout
├── viewport_widget.dart # Scene viewport
├── scene_tree_widget.dart # Scene tree panel
├── inspector_widget.dart # Property inspector
├── bottom_panel_widget.dart
└── engine_node.dart # Engine node definitions
- Python: 3.10+
- Dependencies:
pip install pygame - Engine Import:
from src.pyengine2D import * - Run Frog Hop:
python -m src.games.frog_hop.main - Other examples:
python -m src.games.breakout.mainpython -m src.games.neon_heights.mainpython -m src.games.neon_odyssey.mainpython -m src.games.neon_tank.mainpython -m src.games.newtons_cradle.main
- Run Tests:
python tests/headless_verify.py - Level Editor:
python draw2d.py→ draw → [S] → save tosrc/games/frog_hop/maps/ - Scene Editor:
flutter run -d windowsinsrc/the_editor/
See ENGINE_USAGE.md for a detailed API guide.
Run the headless verification test to verify the engine and games initialize correctly without a display:
pip install pygame
python tests/headless_verify.pyThis test:
- Sets
SDL_VIDEODUMMY=1for headless operation - Imports and initializes the engine core modules
- Runs both
frog_hopandneon_tankgames for 60 frames - Reports pass/fail for each component
Expected output:
============================================================
Testing engine core imports...
============================================================
[PASS] All core engine modules imported successfully
============================================================
Testing frog_hop...
============================================================
[PASS] frog_hop initialized successfully
[PASS] frog_hop ran 60 frames without errors
============================================================
Testing neon_tank...
============================================================
[PASS] neon_tank initialized successfully
[PASS] neon_tank ran 60 frames without errors
FINAL RESULTS
============================================================
Engine Core Imports: PASS
Frog Hop: PASS
Neon Tank: PASS
============================================================
- Runtime Core & Scene Tree
- AABB Collision System (Layer/Mask, Triggers)
- CircleCollider2D (Circle-AABB & Circle-Circle narrow phase)
- PhysicsBody2D with axis-separation and float precision
- Engine-level Gravity and Impulse support
- Engine-Agnostic Player Controller (Level 4)
- Behavioral State Machine (Level 5)
- Tweening & Easing system (Level 6)
- Particle System & Sprite Rendering (Level 6)
- UI & Event Propagation Framework (Level 7)
- TilemapNode: Baked surfaces, auto-collision, streaming, parallax (Level 1)
- Frog Hop: Full side-scrolling platformer with JSON-driven tilemap levels
- Sound & Music Layer
- Polygon collision support
- TMX format support in
TilemapNode
This project is licensed under the MIT License.