Metadata-Version: 2.4
Name: gamengine3d
Version: 1.23.2
Summary: A Unity-like 3D engine in Python using pygame
Author-email: Samarth Javagal <samarthjavagal@gmail.com>
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Topic :: Games/Entertainment
Classifier: Operating System :: OS Independent
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE.txt
Requires-Dist: moderngl==5.12.0
Requires-Dist: numpy==2.3.3
Requires-Dist: pygame==2.6.1
Requires-Dist: pyrr==0.10.3
Provides-Extra: dev
Requires-Dist: build==1.6.1; extra == "dev"
Requires-Dist: twine==7.0.0; extra == "dev"
Dynamic: license-file

# GamEngine3D

**A Unity-style 3D engine for Python.** Build interactive 3D worlds — rooms, puzzles, parkour courses, horror arenas — with clean Python and a few files of behavior scripts.

GamEngine3D wraps pygame + moderngl so you get a real OpenGL renderer (lighting, shadows, materials, a free camera) without fighting the graphics stack. You describe the scene; the engine renders it, lights it, and runs your scripts.

```bash
pip install gamengine3d
```

---

## Try it in 10 seconds

Every install ships with playable demos. Pick one and press `W A S D` to move, `Space` to jump, `E` to interact, `M` to grab the mouse.

```bash
gamengine3d demo basics             # a quiet lit scene, easy on the eyes
gamengine3d demo player_movement    # a first-person walking sim: coins, sprint, flashlight
gamengine3d demo parkour            # leap floating discs over a bottomless pit — in the dark
gamengine3d demo reactor            # a full mission: restart four breakers to restore the core
```

Run `gamengine3d demo -h` to list everything. A display is required — demos open a real window.

---

## Your first scene

```python
from gamengine3d import *

# 1. Initialize the engine
engine = Engine(1200, 800, background_color=Color.light_blue)

# 2. Create objects
floor = Cuboid(size=vector3d(5, 0.1, 5), color=Color.light_grey, name="Floor")
player = Cuboid(name="Player", color=Color.light_red,
                size=vector3d(0.2), pos=vector3d(0, 1))

# 3. Give the scene some light
engine.add_light(Light(position=vector3d(0, 6, 0), color=Color.white, intensity=1.0))

# 4. Add objects to the engine
engine.add_object(floor)
engine.add_object(player)

# 5. Attach behavior to objects (movement, input, game logic)
player.attach("player_controller.py", engine.context)

# 6. Run it. dynamic_view=True gives you orbit / zoom / pan with the mouse.
engine.run(dynamic_view=True)
```

That is the whole engine in six steps:

| Step | What it does |
| --- | --- |
| `Engine(...)` | Opens the window and the renderer (lights, shadows, camera). |
| `Cuboid(...)` | Any object — a box, sphere, cylinder, .obj mesh, or text. |
| `engine.add_light(...)` | Add point, directional, or area lights. |
| `engine.add_object(...)` | Put an object in the world. |
| `.attach("script.py", ctx)` | Attach behavior — see Scripting below. |
| `engine.run(...)` | Start the main loop. |

---

## What can you build? The demos

**`reactor`** — the showpiece. An 80-meter reactor hall with a dead core, four breaker stations, and a `director` script orchestrating the whole mission:
stare down the motion gate, reboot the shock coil, override the shield vault, decode the breach code — then watch the petals peel away and confetti rain.

**`parkour`** — a pitch-black arena over a void. Sixteen floating discs snake across the room while lamps stutter, void lights breathe, and a beating eye watches you climb to the summit.

**`player_movement`** — the classic first-person room: sprint, jump, collect eight glowing coins, watch the HUD count them, and check out the flashlight (press `F`).

**`basics`** — the minimal scene: floor, column, two spheres, warm lighting. The pace-setter for learning the API.

All demos are plain Python files in `gamengine3d/examples/` — copy one and start hacking.

---

## Building blocks

- **`Engine`** — owns rendering, lights, the main loop, scene save/load, and even raycasting (`pick_forward`, `pick_at_screen`).
- **Objects** — `Cuboid`, `Sphere`, `Cylinder`, `ObjModel` (load `.obj` files), `Text` (real 3D text, perfect for in-world HUDs), `ImageOverlay` (screen-space sprites).
- **`vector3d` / `vector2d` / `Color`** — friendly helpers; `Color.RGB(255, 200, 150)`, `Color.hex("#ffc896")`, or constants like `Color.light_blue`.
- **Lights** — `Light` (point) and `DirectionalLight`, each casting real-time shadows.

Every object has `pos`, `size/radius`, `rotation`, `color`, `visible`, and `emit` (glow without lighting) — and can be hidden but still collide.

---

## Scripting: bring it to life

Attach a Python file to any object, and the engine instantiates its class and calls `update(dt)` every frame. The class name must match the file (PascalCase): `player_controller.py` defines `PlayerController`.

```python
# player_controller.py
from gamengine3d import *
import math

class PlayerController:
    def __init__(self, obj, context):
        self.obj = obj
        self.context = context
        self.speed = 4
        self.context.on_key_held("up", callback=self.move_forward, dt=True)

    def update(self, dt):
        pass  # called every frame

    def move_forward(self, dt):
        yaw = math.radians(self.obj.rotation.z)
        forward = vector3d(-math.sin(yaw), 0, math.cos(yaw))
        self.obj.pos += forward * self.speed * dt
```

Scripts get everything through a shared **`Context`**:

- `on_key_press("e", fn)`, `on_key_held(...)`, `on_key_released(...)` — input, with optional `dt`.
- `add_delay(seconds, fn)` — schedule one-shot or repeating calls.
- `runtime_vars` — a serializable blackboard for cross-script state (e.g. `coil_powered`).
- `send_message(name, "msg")` → object-to-object messaging between scripts.

Attach to an object with `.attach(path, context)`, or to the whole engine with `engine.attach(path)` for scene-wide directors.

---

## Save and load scenes

Any scene is a plain JSON file — objects, lights, scripts, and context included.

```python
engine.save_scene("my_scene.json")
```

```bash
gamengine3d load my_scene.json 1280x800 60 --dynamic-view
```

---

## Requirements & development

- **Python 3.11+** and a working OpenGL driver.
- Runtime deps (pinned): `pygame`, `moderngl`, `numpy`, `pyrr`.
- On hybrid laptops, the engine auto-prefers the discrete GPU; force a choice with `gpu="nvidia" | "intel"` on `Engine(...)` or the `GAMENGINE3D_GPU` env var.
- For development, use `uv`: `uv sync --extra dev` installs the runtime plus the release toolchain (`build`, `twine`).

---

### Links

- Full documentation: [GamEngine3D Package Docs](https://sites.google.com/view/samarthsprojects/python-packages/gamengine3d)
- The 2D sibling engine, `gamengine2d`, is also on PyPI.
