Metadata-Version: 2.5
Name: sypy-engine-beginner
Version: 0.1.1
Summary: A beginner-friendly 2D game engine built with Python and Pygame
Author: Methuka Koralage
License: MIT License
        
        Copyright (c) 2026 Methuka
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files, to deal in the Software
        without restriction, including without limitation the rights to use, copy,
        modify, merge, publish, distribute, sublicense, and/or sell copies of the
        Software, and to permit persons to whom the Software is furnished to do so,
        subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Requires-Python: >=3.10
Requires-Dist: pygame==2.6.1
Description-Content-Type: text/markdown

# My 2D Engine

A beginner-friendly 2D game engine built with **Python and Pygame**.

My 2D Engine is designed to make building 2D games easier without requiring you to write an entire game framework from scratch.

It provides systems for:

* 🎮 Entities
* ⚙️ Physics
* 🧱 Collision
* 🟦 One-way platforms
* ↔️ Moving platforms
* 🗺️ Tilemaps
* 🎥 Cameras
* 🎨 Rendering
* 🎞️ Animations
* 💥 Hitboxes
* ✨ Particles
* 🔊 Sound
* 🎹 Keyboard and mouse input
* 🖼️ Asset management
* 🧩 Components
* 🖥️ UI
* 🎬 Scenes
* 💾 Save/load
* 🐛 Debugging

The engine is intended primarily for **2D platformers, arcade games, rhythm games, top-down games, shooters, and other small-to-medium 2D projects**.

---

# Table of Contents

1. [Requirements](#requirements)
2. [Installation](#installation)
3. [Project Structure](#project-structure)
4. [Quick Start](#quick-start)
5. [Engine](#engine)
6. [Entities](#entities)
7. [Entity Properties](#entity-properties)
8. [Movement](#movement)
9. [Physics](#physics)
10. [Gravity](#gravity)
11. [Jumping](#jumping)
12. [Friction](#friction)
13. [Acceleration](#acceleration)
14. [Maximum Speed](#maximum-speed)
15. [Custom Entity Updates](#custom-entity-updates)
16. [Tags](#tags)
17. [Sprites](#sprites)
18. [Animations](#animations)
19. [Solids](#solids)
20. [Collision](#collision)
21. [One-Way Platforms](#one-way-platforms)
22. [Moving Platforms](#moving-platforms)
23. [Hitboxes](#hitboxes)
24. [Particles](#particles)
25. [Input](#input)
26. [Keyboard Input](#keyboard-input)
27. [Mouse Input](#mouse-input)
28. [Tilemaps](#tilemaps)
29. [Tile Definitions](#tile-definitions)
30. [Tilemap Layers](#tilemap-layers)
31. [Spawn Points](#spawn-points)
32. [Tilemap Collision](#tilemap-collision)
33. [Camera](#camera)
34. [Rendering](#rendering)
35. [Components](#components)
36. [Scenes](#scenes)
37. [UI](#ui)
38. [Asset Manager](#asset-manager)
39. [Sound](#sound)
40. [Save and Load](#save-and-load)
41. [Debug Mode](#debug-mode)
42. [Complete Example](#complete-example)
43. [Recommended Game Structure](#recommended-game-structure)
44. [Common Mistakes](#common-mistakes)
45. [Engine Architecture](#engine-architecture)
46. [Current Limitations](#current-limitations)
47. [FAQ](#faq)

---

# Requirements

You need:

* Python 3.10+
* Pygame 2.x

Install Pygame with:

```bash
pip install pygame
```

Or:

```bash
python -m pip install pygame
```

---

# Installation

Clone or download the engine.

Your project should contain the engine folder:

```text
my_game/
│
├── main.py
│
└── engine/
    ├── engine.py
    ├── core/
    ├── collisions/
    ├── camera/
    ├── rendering/
    ├── scenes/
    └── tilemap/
```

Run your game with:

```bash
python main.py
```

---

# Project Structure

The engine is separated into different systems.

```text
engine/
│
├── engine.py
│
├── core/
│   ├── entity.py
│   ├── updater.py
│   ├── animation.py
│   ├── physics.py
│   ├── solid.py
│   ├── sound.py
│   ├── particle.py
│   ├── hitbox.py
│   ├── component.py
│   ├── input.py
│   ├── asset_manager.py
│   ├── ui.py
│   ├── save.py
│   └── debug.py
│
├── collisions/
│   └── collisions.py
│
├── camera/
│   └── camera.py
│
├── rendering/
│   └── renderer.py
│
├── scenes/
│   └── scene.py
│
└── tilemap/
    └── tilemap.py
```

You normally don't need to modify these files when making a game.

Your game code should primarily go into:

```text
main.py
```

and your own game-specific files.

---

# Quick Start

The smallest possible game is:

```python
from engine.engine import Engine

game = Engine()

game.run()
```

This creates the game window and starts the engine.

---

# Creating an Entity

Entities are the basic objects used in the engine.

Create one:

```python
player = game.add_entity("player")
```

Set its position:

```python
player.position = [100, 100]
```

Set its size:

```python
player.size = [40, 40]
```

Set its color:

```python
player.color = [255, 0, 0]
```

Enable collision:

```python
player.collidable = True
```

---

# Entity Properties

An entity contains several useful properties.

## Position

```python
player.position = [100, 200]
```

The position is:

```text
[x, y]
```

---

## Velocity

```python
player.velocity = [5, 0]
```

The first value controls horizontal velocity.

The second controls vertical velocity.

```python
player.velocity[0] = 5
```

moves right.

```python
player.velocity[0] = -5
```

moves left.

```python
player.velocity[1] = -10
```

moves upward.

---

## Size

```python
player.size = [50, 50]
```

---

## Color

```python
player.color = [255, 0, 0]
```

Colors use RGB values:

```text
Red    = [255, 0, 0]
Green  = [0, 255, 0]
Blue   = [0, 0, 255]
White  = [255, 255, 255]
Black  = [0, 0, 0]
```

---

## Visibility

```python
player.visible = True
```

Hide an entity:

```python
player.visible = False
```

---

## Active State

```python
player.active = True
```

Disable an entity:

```python
player.active = False
```

Inactive entities are not updated.

---

# Movement

The engine lets you directly control velocity:

```python
player.velocity[0] = 5
```

Or create acceleration-based movement:

```python
player.set_acceleration(0.5)
```

For a normal platformer, a custom update function is usually useful:

```python
def update(player, keys):

    if game.input.down("left"):
        player.velocity[0] -= 0.5

    if game.input.down("right"):
        player.velocity[0] += 0.5

player.set_update(update)
```

---

# Physics

Every entity has a physics system:

```python
player.physics
```

The physics system supports:

* Acceleration
* Maximum speed
* Friction
* Air friction
* Gravity scaling

---

# Gravity

Enable gravity:

```python
player.set_gravity(0.5)
```

The value controls how quickly vertical velocity increases.

Example:

```python
player.set_gravity(0.6)
```

You can modify the gravity scale:

```python
player.physics.gravity_scale = 0.5
```

This makes the entity experience half the normal gravity.

---

# Jumping

Set jump strength:

```python
player.set_jump(12)
```

Then:

```python
player.jump()
```

The engine checks whether the entity is grounded.

You can also check:

```python
if player.grounded:
    print("Player is standing on something")
```

---

# Friction

Set ground and air friction:

```python
player.set_friction(
    2,
    0.2
)
```

The first value is ground friction.

The second value is air friction.

Higher friction makes the entity stop faster.

For responsive movement, smaller values are usually preferable.

---

# Acceleration

Enable acceleration:

```python
player.set_acceleration(0.5)
```

You can also specify X and Y acceleration:

```python
player.set_acceleration(
    0.5,
    0.2
)
```

---

# Maximum Speed

Set horizontal and vertical maximum speeds:

```python
player.set_max_speed(
    7,
    20
)
```

The first value is maximum X speed.

The second value is maximum Y speed.

---

# Custom Entity Updates

Every entity can have its own update function.

```python
def player_update(player, keys):

    if game.input.down("left"):
        player.velocity[0] -= 0.5

    if game.input.down("right"):
        player.velocity[0] += 0.5

    if game.input.pressed("jump"):
        player.jump()

player.set_update(
    player_update
)
```

The engine calls this function every frame.

This is where game-specific logic should normally go.

---

# Tags

Tags allow you to categorize entities.

Add a tag:

```python
player.add_tag("player")
```

Add multiple:

```python
player.add_tag("character")
player.add_tag("friendly")
```

Check:

```python
if player.has_tag("player"):
    print("This is the player")
```

Remove:

```python
player.remove_tag("friendly")
```

Tags are useful for:

```text
player
enemy
boss
projectile
coin
NPC
enemy_projectile
collectible
```

---

# Finding Entities

Get an entity by name:

```python
player = game.get_entity("player")
```

If it cannot be found, the result is:

```python
None
```

---

# Sprites

Entities can use images.

```python
player.set_sprite(
    "assets/player.png"
)
```

Remove the sprite:

```python
player.remove_sprite()
```

The renderer automatically uses the sprite when rendering the entity.

---

# Animations

The engine contains an animation manager.

You can create an animation from separate images:

```python
player.add_animation_images(
    "idle",
    [
        "assets/idle1.png",
        "assets/idle2.png",
        "assets/idle3.png"
    ],
    speed=10
)
```

Play it:

```python
player.play_animation("idle")
```

Restart it:

```python
player.play_animation(
    "idle",
    restart=True
)
```

Check whether an animation has finished:

```python
if player.animation_finished():
    print("Animation finished")
```

You can use animations for:

```text
Idle
Run
Jump
Fall
Attack
Death
Hurt
Dash
```

---

# Solids

Solids are objects that entities can collide with.

Create one:

```python
platform = game.add_solid(
    100,
    400,
    500,
    40
)
```

The arguments are:

```text
x
y
width
height
```

You can change its color:

```python
platform.color = [
    100,
    100,
    100
]
```

---

# Collision

Enable collision on an entity:

```python
player.collidable = True
```

The collision system handles movement against solid objects.

The system separates horizontal and vertical movement so basic platformer collisions can be handled independently.

---

# One-Way Platforms

One-way platforms allow an entity to pass through from below and land on top.

Create one:

```python
platform = game.add_one_way_platform(
    200,
    300,
    200,
    20
)
```

Conceptually:

```text
        PLAYER
          ↓

    ───────────────
      PLATFORM

Player can pass upward
and land when falling.
```

This is useful for platformers.

---

# Moving Platforms

Create a horizontal moving platform:

```python
platform = game.add_moving_platform(
    400,
    350,
    150,
    25,
    velocity_x=50
)
```

Create a vertical moving platform:

```python
platform = game.add_moving_platform(
    400,
    350,
    150,
    25,
    velocity_y=-50
)
```

Both directions can be used:

```python
platform = game.add_moving_platform(
    400,
    350,
    150,
    25,
    velocity_x=50,
    velocity_y=-30
)
```

Moving platforms are useful for:

* Platforming challenges
* Elevators
* Moving obstacles
* Puzzle levels

---

# Hitboxes

Hitboxes are areas that detect entities.

Create one:

```python
trigger = game.add_hitbox(
    600,
    300,
    100,
    100
)
```

Create an event:

```python
def entered(entity):

    print(
        entity.name,
        "entered the trigger"
    )

trigger.on_enter(
    entered
)
```

Hitboxes are useful for:

```text
Triggers
Damage zones
Checkpoints
Portals
Collectibles
Boss arenas
Level transitions
```

---

# Particles

The particle system can create visual effects.

Example:

```python
game.particles.emit(
    400,
    300,
    count=30,
    color=(255, 200, 50),
    size=6,
    speed=150,
    lifetime=1,
    gravity=100
)
```

Parameters include:

```text
x
y
count
color
size
speed
lifetime
gravity
image
```

Example explosion:

```python
game.particles.emit(
    enemy.position[0],
    enemy.position[1],
    count=50,
    color=(255, 100, 20),
    size=5,
    speed=250,
    lifetime=0.8,
    gravity=150
)
```

Particles can also load animation images and sprite sheets.

---

# Input

The input system provides keyboard and mouse controls.

Bind a key:

```python
game.input.bind(
    "left",
    pygame.K_a
)
```

```python
game.input.bind(
    "right",
    pygame.K_d
)
```

```python
game.input.bind(
    "jump",
    pygame.K_SPACE
)
```

This means your game logic doesn't need to constantly reference raw Pygame keys.

---

# Keyboard Input

## Held

Use:

```python
game.input.down("left")
```

This is `True` while the key is held.

Example:

```python
if game.input.down("left"):
    player.velocity[0] -= 0.5
```

---

## Pressed

Use:

```python
game.input.pressed("jump")
```

This is useful for actions that should happen once per press.

Example:

```python
if game.input.pressed("jump"):
    player.jump()
```

---

# Mouse Input

Get mouse position:

```python
mouse_x, mouse_y = game.input.mouse_pos()
```

Check whether a mouse button is held:

```python
game.input.mouse_down(1)
```

Check whether it was pressed:

```python
game.input.mouse_pressed(1)
```

Mouse button `1` is normally the left mouse button.

---

# Tilemaps

Tilemaps let you build levels using characters.

Create a tilemap:

```python
tilemap = Tilemap(
    game,
    50
)
```

The `50` means each tile is 50×50 pixels.

---

# Defining Tiles

Define a solid tile:

```python
tilemap.define_tile(
    "#",
    color=[80, 80, 80],
    solid=True,
    layer=0
)
```

Define another:

```python
tilemap.define_tile(
    "G",
    color=[80, 180, 80],
    solid=True,
    layer=1
)
```

The character determines which tile gets created.

---

# Loading a Tilemap

Example:

```python
tilemap.load(
    """
########################
#                      #
#        GGG           #
#                      #
#   P                  #
########################
"""
)
```

If `#` is defined as a tile, every `#` becomes that tile.

---

# Tilemap Layers

Tiles can be assigned layers:

```python
tilemap.define_tile(
    "#",
    color=[100, 100, 100],
    solid=True,
    layer=0
)
```

Higher layers can be used for visual ordering.

A possible design is:

```text
Layer 0 → Ground
Layer 1 → Decoration
Layer 2 → Foreground
```

---

# Spawn Points

Define a spawn character:

```python
tilemap.define_spawn(
    "P",
    "player_spawn"
)
```

Load the map:

```python
tilemap.load(
    """
########
#      #
#  P   #
########
"""
)
```

Get the spawn:

```python
spawn = tilemap.get_spawn(
    "player_spawn"
)
```

Place the player:

```python
player.position = spawn
```

---

# Tilemap Collision

Add an entity to the tilemap's collision system:

```python
tilemap.add_collision_entity(
    player
)
```

Solid tiles can then interact with that entity.

---

# Camera

The camera controls what part of the world is visible.

Create one:

```python
camera = Camera(
    game.window_w,
    game.window_h
)
```

Make it follow the player:

```python
camera.follow(
    player
)
```

Attach it to the engine:

```python
game.add_camera(
    camera
)
```

The camera is useful for:

* Large levels
* Platformers
* Scrolling games
* Top-down games
* Following players

---

# Rendering

The renderer is responsible for drawing the game world.

The general rendering order is:

```text
Background
    ↓
Solids / Tilemap
    ↓
Entities
    ↓
Particles
    ↓
UI
    ↓
Debug information
```

This means UI and debug information can be displayed above the game world.

---

# Components

Components let you attach custom systems/data to entities.

Create a component:

```python
from engine.core.component import Component


class Health(Component):

    def __init__(self, amount):
        super().__init__()
        self.health = amount

    def damage(self, amount):
        self.health -= amount
```

Add it:

```python
player.add_component(
    Health(100)
)
```

Get a component:

```python
health = player.get_component(
    Health
)
```

Check:

```python
if player.has_component(Health):
    print("Player has health")
```

Remove:

```python
player.remove_component(
    health
)
```

Components are useful for systems such as:

```text
Health
Inventory
Weapons
AI
Stats
Dialogue
Abilities
Status effects
```

---

# Scenes

Scenes allow different parts of a game to be separated.

Example:

```python
from engine.scenes.scene import Scene


class Level1(Scene):

    def start(self):

        self.player = self.game.add_entity(
            "player"
        )

    def update(self, dt):

        pass
```

Register it:

```python
game.scene.register(
    "level1",
    Level1(game)
)
```

Load it:

```python
game.scene.load(
    "level1"
)
```

Possible scenes:

```text
Main Menu
Level 1
Level 2
Boss
Game Over
Credits
```

Scenes can track game objects created for them and clean them up when switching scenes.

---

# UI

The engine contains a UI system for screen-space elements.

The UI manager can create:

```text
Text
Panels
Buttons
Sliders
```

---

# Text

Example:

```python
game.ui.text(
    "Hello World",
    20,
    20,
    size=28
)
```

Another:

```python
game.ui.text(
    "A / D = Move",
    20,
    60,
    size=20
)
```

---

# Panels

Create a UI panel:

```python
panel = game.ui.panel(
    20,
    20,
    300,
    200
)
```

Panels are useful for:

```text
Menus
Inventory
Settings
HUD backgrounds
Dialogue boxes
```

---

# Buttons

Create a button:

```python
def clicked():
    print("Button clicked!")


button = game.ui.button(
    "Start Game",
    100,
    100,
    200,
    50,
    clicked
)
```

Buttons can be used for:

```text
Menus
Settings
Inventory
Pause screens
Level selection
```

---

# Sliders

Create a slider:

```python
slider = game.ui.slider(
    100,
    200,
    300,
    30
)
```

Sliders are useful for:

```text
Volume
Brightness
Settings
Game values
```

---

# Asset Manager

The asset manager handles loading and caching resources.

Access it with:

```python
game.assets
```

---

# Images

Load an image:

```python
image = game.assets.image(
    "assets/player.png"
)
```

Give it a custom name:

```python
image = game.assets.image(
    "assets/player.png",
    name="player"
)
```

The engine caches loaded images so the same resource does not need to be loaded repeatedly.

---

# Sounds

Load a sound:

```python
sound = game.assets.sound(
    "assets/jump.wav"
)
```

---

# Fonts

Load a font:

```python
font = game.assets.font(
    "assets/font.ttf",
    32
)
```

---

# Asset Caching

The asset manager keeps loaded resources in memory.

This is useful because repeatedly loading the same file is inefficient.

You can clear the asset cache:

```python
game.assets.clear()
```

---

# Sound

The engine includes a sound manager.

Access it with:

```python
game.sounds
```

Use the sound manager for game audio instead of creating a completely separate audio system for every object.

Typical uses include:

```text
Jump sounds
Weapons
UI clicks
Explosions
Music
Environment sounds
```

---

# Save and Load

The engine includes a JSON-based save system.

Save:

```python
game.save(
    "save1"
)
```

Load:

```python
game.load(
    "save1"
)
```

The engine can automatically save basic entity information such as:

```text
Position
Velocity
Active state
```

You can also provide your own data:

```python
game.save(
    "save1",
    {
        "coins": 50,
        "level": 3
    }
)
```

---

# Debug Mode

Debugging can be enabled with:

```python
game.debug = True
```

Press:

```text
F3
```

to toggle debugging during runtime.

The debug system can display information such as:

```text
FPS
Entity count
Solid count
Hitbox count
Particle count
Camera information
Entity collision boxes
Solid collision boxes
Physics information
Velocity visualization
```

Debug mode is extremely useful when developing a game.

---

# Complete Example

Here is a small complete platformer using the engine:

```python
import pygame

from engine.engine import Engine
from engine.camera.camera import Camera
from engine.tilemap.tilemap import Tilemap


game = Engine()

game.input.bind(
    "left",
    pygame.K_a
)

game.input.bind(
    "right",
    pygame.K_d
)

game.input.bind(
    "jump",
    pygame.K_SPACE
)


player = game.add_entity(
    "player"
)

player.position = [
    100,
    100
]

player.size = [
    40,
    40
]

player.color = [
    255,
    50,
    50
]

player.collidable = True

player.set_gravity(
    0.6
)

player.set_jump(
    12
)

player.set_friction(
    2,
    0.2
)

player.set_max_speed(
    7,
    20
)


def player_update(
    player,
    keys
):

    if game.input.down("left"):
        player.velocity[0] -= 0.5

    if game.input.down("right"):
        player.velocity[0] += 0.5

    if game.input.pressed("jump"):
        player.jump()


player.set_update(
    player_update
)


ground = game.add_solid(
    0,
    500,
    1200,
    50
)

ground.color = [
    80,
    80,
    80
]


platform = game.add_one_way_platform(
    300,
    350,
    200,
    20
)

platform.color = [
    80,
    150,
    255
]


moving = game.add_moving_platform(
    600,
    400,
    150,
    25,
    velocity_x=50
)

moving.color = [
    255,
    170,
    50
]


camera = Camera(
    game.window_w,
    game.window_h
)

camera.follow(
    player
)

game.add_camera(
    camera
)


game.ui.text(
    "A / D = Move    SPACE = Jump",
    20,
    20,
    size=22
)


game.debug = True


game.run()
```

---

# Recommended Game Structure

As your game becomes larger, don't put everything in `main.py`.

A recommended structure is:

```text
my_game/
│
├── main.py
│
├── engine/
│
├── game/
│   ├── player.py
│   ├── enemies.py
│   ├── weapons.py
│   ├── levels.py
│   ├── items.py
│   └── game_manager.py
│
├── assets/
│   ├── images/
│   ├── sounds/
│   ├── music/
│   └── fonts/
│
└── saves/
```

For example:

```python
from game.player import create_player
```

Then:

```python
player = create_player(game)
```

This keeps your game organized.

---

# Recommended Architecture

Try to keep the engine and game separate.

## Engine

The engine should provide:

```text
Physics
Rendering
Input
Collision
Camera
Scenes
UI
Particles
Audio
Assets
Saving
```

## Game

Your game should provide:

```text
Player
Enemies
Weapons
Levels
Story
Items
Rules
Game-specific mechanics
```

For example, the engine should **not** contain:

```python
if player.has_tag("player"):
```

unless that is part of a generic engine system.

Instead, your game should decide what a player is.

---

# Engine Architecture

The basic flow of the engine is:

```text
                 Engine
                   │
        ┌──────────┼──────────┐
        ↓          ↓          ↓
      Input      Scene      Assets
        │          │
        ↓          ↓
     Entities   Game Objects
        │
        ↓
     Updater
        │
        ├───────────────┐
        ↓               ↓
    Physics         Components
        │
        ↓
    Collision
        │
        ↓
     Camera
        │
        ↓
    Renderer
        │
        ├── Tilemap
        ├── Entities
        └── Solids
        │
        ↓
    Particles
        ↓
       UI
        ↓
      Debug
        ↓
      Screen
```

---

# Game Loop

The engine continuously performs roughly this process:

```text
Start
 ↓
Read events
 ↓
Update input
 ↓
Update moving solids
 ↓
Update entities
 ↓
Apply physics
 ↓
Resolve collisions
 ↓
Update hitboxes
 ↓
Update particles
 ↓
Update scenes
 ↓
Update UI
 ↓
Update camera
 ↓
Render world
 ↓
Render particles
 ↓
Render UI
 ↓
Render debug information
 ↓
Display frame
 ↓
Repeat
```

This happens every frame while:

```python
game.running
```

is true.

---

# Getting Started With Your Own Game

A good development order is:

## Step 1 — Create the engine

```python
game = Engine()
```

## Step 2 — Create your player

```python
player = game.add_entity(
    "player"
)
```

## Step 3 — Add movement

```python
player.set_update(
    player_update
)
```

## Step 4 — Add physics

```python
player.set_gravity(
    0.6
)
```

## Step 5 — Add level geometry

```python
game.add_solid(
    0,
    500,
    1000,
    50
)
```

## Step 6 — Add camera

```python
camera.follow(
    player
)
```

## Step 7 — Add graphics

```python
player.set_sprite(
    "assets/player.png"
)
```

## Step 8 — Add game mechanics

Use:

```text
Components
Hitboxes
Particles
Animations
Scenes
```

## Step 9 — Add UI

Create:

```text
Health bar
Score
Menus
Buttons
```

## Step 10 — Enable debugging

```python
game.debug = True
```

---

# Common Mistakes

## 1. Forgetting to enable collision

This:

```python
player = game.add_entity("player")
```

doesn't automatically make the entity collide.

Use:

```python
player.collidable = True
```

---

## 2. Forgetting gravity

If your player doesn't fall:

```python
player.set_gravity(
    0.6
)
```

---

## 3. Forgetting to set an update function

If you expect custom movement, make sure you have:

```python
player.set_update(
    player_update
)
```

---

## 4. Using excessive friction

If your player barely moves or stops instantly:

```python
player.set_friction(
    2,
    0.2
)
```

is generally more responsive than:

```python
player.set_friction(
    8,
    1
)
```

---

## 5. Forgetting the camera

Create and attach it:

```python
camera = Camera(
    game.window_w,
    game.window_h
)

camera.follow(player)

game.add_camera(camera)
```

---

## 6. Forgetting to start the engine

Your program needs:

```python
game.run()
```

---

# Performance Tips

Don't create expensive resources every frame.

Avoid:

```python
def update(player, keys):

    image = pygame.image.load(
        "player.png"
    )
```

Instead, load assets once.

Use the asset manager:

```python
image = game.assets.image(
    "player.png"
)
```

---

# Debugging Your Game

When something doesn't work:

First enable:

```python
game.debug = True
```

Then press:

```text
F3
```

Check:

```text
FPS
Entity count
Collision boxes
Hitboxes
Physics
Camera
```

If Python gives you a traceback, look at the **last line first**.

For example:

```text
AttributeError:
'Player' object has no attribute 'something'
```

usually means the code is trying to use a property or method that doesn't exist.

---

# Current Limitations

This engine is designed to be lightweight and beginner-friendly. It is **not currently intended to replace full commercial engines such as Unity or Godot**.

Some advanced features may require implementation in future versions.

Current areas that can be improved include:

* Advanced slope collision
* Continuous collision detection
* Spatial partitioning for extremely large numbers of objects
* More advanced tilemap optimization
* More advanced animation systems
* Advanced audio management
* A visual level editor
* Prefab systems
* More sophisticated particle simulation
* Advanced rendering effects
* Networking/multiplayer
* 3D rendering

The engine is primarily designed for **2D games**.

---

# FAQ

## Is this a 3D engine?

No.

It is a 2D engine built using Pygame.

---

## Do I need to know Pygame?

Basic Pygame knowledge helps, but the engine hides many common Pygame tasks.

You can mostly work with:

```python
game
player
platform
camera
scene
tilemap
```

instead of directly managing the entire Pygame game loop yourself.

---

## Can I make a platformer?

Yes.

The engine provides:

* Gravity
* Jumping
* Collision
* One-way platforms
* Moving platforms
* Camera
* Tilemaps
* Particles
* Animations
* Hitboxes

---

## Can I make a top-down game?

Yes.

You can disable gravity:

```python
player.gravity_enabled = False
```

and implement top-down movement.

---

## Can I make a shooter?

Yes.

Entities, hitboxes, particles, input, components and collision can be used to build weapons and projectiles.

---

## Can I make a Geometry Dash-style game?

Yes.

The engine can provide many of the underlying systems needed for a rhythm-platformer, including:

```text
Automatic movement
Collision
Gravity
Platforms
Triggers
Particles
Camera
Animations
Tilemaps
```

The actual game mechanics should be implemented by your game.

---

## Can I make menus?

Yes.

Use the UI system:

```text
Text
Panels
Buttons
Sliders
```

and scenes for different screens.

---

## Can I save games?

Yes.

Use:

```python
game.save("save1")
```

and:

```python
game.load("save1")
```

---

# Minimal Template

For a new game, this is a good starting point:

```python
import pygame

from engine.engine import Engine
from engine.camera.camera import Camera


game = Engine()


game.input.bind(
    "left",
    pygame.K_a
)

game.input.bind(
    "right",
    pygame.K_d
)

game.input.bind(
    "jump",
    pygame.K_SPACE
)


player = game.add_entity(
    "player"
)

player.position = [
    100,
    100
]

player.size = [
    40,
    40
]

player.color = [
    255,
    50,
    50
]

player.collidable = True

player.set_gravity(
    0.6
)

player.set_jump(
    12
)

player.set_friction(
    2,
    0.2
)

player.set_max_speed(
    7,
    20
)


def player_update(
    player,
    keys
):

    if game.input.down("left"):
        player.velocity[0] -= 0.5

    if game.input.down("right"):
        player.velocity[0] += 0.5

    if game.input.pressed("jump"):
        player.jump()


player.set_update(
    player_update
)


game.add_solid(
    0,
    500,
    1200,
    50
)


camera = Camera(
    game.window_w,
    game.window_h
)

camera.follow(
    player
)

game.add_camera(
    camera
)


game.run()
```

---

# Final Notes

My 2D Engine is built around one main idea:

> **The engine provides the systems. Your game provides the rules.**

You should be able to create a game without rewriting the engine every time.

For example:

```text
ENGINE
│
├── Physics
├── Collision
├── Rendering
├── Input
├── Camera
├── Tilemaps
├── Particles
├── Audio
├── UI
├── Scenes
├── Components
└── Saving
        │
        ↓
      YOUR GAME
        │
        ├── Player
        ├── Enemies
        ├── Levels
        ├── Weapons
        ├── Items
        ├── Game rules
        └── Story
```

Build the engine once.

Then use it to build many different games.

---

# License

Add your chosen license here before publicly distributing the engine.

For example:

```text
MIT License
```

or another license appropriate for your project.

---

# My 2D Engine

**Python + Pygame**

A lightweight, beginner-friendly foundation for creating 2D games.
