A tiny Python 3D windowing wrapper powered by a C++ OpenGL backend.
Project description
speepy3d
speepy3d is a tiny Python 3D/game library with a C++ OpenGL backend.
The backend is currently Windows-only through Win32/WGL. Version 0.3.0 adds a
real shader/VBO renderer while keeping the old fixed-pipeline helpers for debug
grid/axes.
Features
- Native OpenGL window creation.
- Keyboard and mouse state:
is_key_down,is_mouse_down,mouse_delta. - Cursor helpers:
set_cursor_locked,set_cursor_visible. - Timing:
delta_time,fps,fpsbar=True, optionalset_vsync. - Resize and close callbacks.
- Input bindings:
Input.action(),Input.axis(),Input.vec2(), mouse sensitivity and click-to-lock mouse. - Game layer helpers:
GameApp,AssetManager,Timer,Profiler, controllers and particles. - Modern OpenGL basics:
Shader,Material,Mesh,Texture,Renderer. MeshBatchfor building many cubes into one fast mesh.- Built-in
Shader.basic(),Mesh.cube(),Mesh.plane(),Texture.checkerboard(). - Mesh normals and basic ambient + directional lighting.
- Simple OBJ loader:
Mesh.from_obj("model.obj"). - Simple glTF loader:
Mesh.from_gltf("model.gltf"). - Texture loading for
.png,.jpg,.jpeg,.bmpand.ppm. - Math:
Vec2,Vec3,Mat4. - Scene objects:
Camera3D,Transform,Model,Scene,DirectionalLight. - Collision helpers:
AABB,PhysicsBody,PhysicsWorld,move_and_collide,SphereCollider,Ray,raycast_aabb. - Debug drawing:
DebugDraw.line(),DebugDraw.box(),DebugDraw.ray(). - WAV sound helpers on Windows:
Sound,Music. - Immediate UI:
Label,Button,Panel,Menu,ContextMenu,UIManager. - Tiny game loop helper:
run(window, update, render).
Install
python -m pip install -e .
Modern Renderer Example
from speepy3d import Camera3D, DirectionalLight, Input, Model, Renderer, Scene, Texture, Vec3, Window
win = Window(800, 600, "speepy3d", fpsbar=True)
win.enable_depth_test(True)
camera = Camera3D(position=Vec3(0.0, 2.0, 6.0), pitch=-15.0)
renderer = Renderer(win)
controls = Input(win, mouse_sensitivity=0.08, mouse_locked_by_click=True)
controls.action("jump", "SPACE")
controls.axis("move_x", negative="A", positive="D")
controls.axis("move_z", negative="S", positive="W")
scene = Scene(
camera=camera,
ambient_light=Vec3(0.36, 0.40, 0.48),
directional_light=DirectionalLight(direction=Vec3(-0.35, -1.0, -0.45), intensity=1.1),
)
cube = scene.add(Model.cube(1.5, texture=Texture.checkerboard()))
scene.add(Model.grid(10.0, 1.0))
scene.add(Model.axes(2.0))
while not win.should_close():
win.poll_events()
controls.update()
dt = win.delta_time or 1.0 / 60.0
raw_move = controls.vec2("move")
move = camera.right * raw_move.x + camera.forward * raw_move.y
if move.length > 0.0:
camera.position += move.normalized() * camera.move_speed * dt
controls.apply_look(camera)
cube.transform.rotation.y += 60.0 * dt
renderer.render(scene)
win.swap_buffers()
Game Examples
python examples\snake3d.py
python examples\minicraft3d.py
python examples\platformer3d.py
Input
from speepy3d import Input
controls = Input(win, mouse_sensitivity=0.06, mouse_locked_by_click=True)
controls.action("jump", "SPACE")
controls.axis("move_x", negative="A", positive="D")
controls.axis("move_z", negative="S", positive="W")
while not win.should_close():
win.poll_events()
controls.update()
if controls.action("jump"):
jump()
move = controls.vec2("move")
Game Layer
from speepy3d import GameApp, MeshBatch, PhysicsBody, PlatformerController, Vec3
app = GameApp(1280, 720, "short game")
app.set_camera((0, 3, 10), pitch=-15)
app.input.action("jump", "SPACE")
app.input.axis("move_x", negative="A", positive="D")
material = app.assets.material("grass", color=Vec3(0.25, 0.85, 0.35))
cube = app.assets.cube()
player = app.scene.spawn(cube, position=(0, 2, 0), material=material, name="player", tag="actor")
world = MeshBatch()
world.cube((0, 0, 0), size=(12, 1, 4), color=(0.3, 0.8, 0.35))
app.scene.add(world.build_model(material))
body = PhysicsBody.from_values(player.position, (1, 1, 1))
app.physics.static_box((0, 0, 0), (12, 1, 4))
controller = PlatformerController(body, app.input, app.physics)
@app.update
def update(dt):
controller.update(dt)
player.position = body.position
app.debug.box(body.box)
@app.render
def render():
app.draw_scene()
app.ui.begin()
app.ui.panel(20, 20, 220, 90)
app.ui.label(f"FPS {app.fps:.0f}")
app.profiler.draw(app.ui, 260, 20)
app.ui.end()
app.run()
Useful systems:
app.timer.after(2.0, spawn_enemy)
app.timer.every(1.0, add_score)
app.particles.emit((0, 2, 0), count=24)
player = app.scene.find("player")
enemies = app.scene.find_by_tag("enemy")
Loading Assets
from speepy3d import Material, Mesh, Model, Shader, Texture, Vec3
mesh = Mesh.from_gltf("assets/crate.gltf")
material = Material(
shader=Shader.basic(),
texture=Texture.from_file("assets/crate.png"),
color=Vec3(1.0, 1.0, 1.0),
roughness=0.5,
)
model = Model(mesh, material=material)
Mesh.from_gltf() supports .gltf JSON files with triangle meshes and external
or embedded buffers. .glb, skinning and animation are not implemented yet.
Collision
from speepy3d import AABB, Vec3, intersects
player = AABB.from_center_size(Vec3(0, 1, 0), Vec3(1, 2, 1))
wall = AABB.from_center_size(Vec3(2, 1, 0), Vec3(1, 2, 4))
if intersects(player, wall):
print("hit")
UI
from speepy3d import Button, Label, Menu, MenuItem, UIManager
ui = UIManager()
ui.add(Label(20, 20, "SCORE 0"))
ui.add(Button(20, 55, 140, 36, text="START", on_click=start_game))
ui.add(Menu(20, 100, 120, 32, title="GAME", items=[
MenuItem("RESET", reset_game),
MenuItem("QUIT", win.close),
]))
while not win.should_close():
win.poll_events()
ui.update(win)
render_3d()
ui.draw(win)
win.swap_buffers()
Immediate-mode UI:
ui = UIManager(win)
while not win.should_close():
win.poll_events()
render_3d()
ui.begin()
ui.panel(20, 20, 250, 180)
ui.label("Score: 10")
if ui.button("Restart"):
restart()
ui.end()
win.swap_buffers()
Sound
from speepy3d import Sound
Sound("jump.wav").play()
Sound currently uses Python's Windows winsound, so WAV is the practical target.
Build
python setup.py sdist bdist_wheel
Project details
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 speepy3d-0.8.0.tar.gz.
File metadata
- Download URL: speepy3d-0.8.0.tar.gz
- Upload date:
- Size: 50.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
64b5613539378e4547bb11245652e3fa4fa3c8af37a05b5598078b7c428f1f5b
|
|
| MD5 |
0a538fe72879684b6b756f63e0ac5947
|
|
| BLAKE2b-256 |
5455e56475251dbc283f0205b089efc0a401fe7113e27bb921bc52e5f7ad6540
|
File details
Details for the file speepy3d-0.8.0-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: speepy3d-0.8.0-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 58.1 kB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
86bccfad6a4846d855de4e86fef7090a4133ceb6ce6417b5bc004e0390bbde54
|
|
| MD5 |
7df7d4d78f78a9902a0f9df9379f1df8
|
|
| BLAKE2b-256 |
440445e8f311cbd63783b5a7ddc467ea1fdfd1f7400997b0b3fa7681fd6ac0c0
|