Metadata-Version: 2.4
Name: arcade-machine-sdk
Version: 1.0.3
Summary: SDK oficial para crear juegos compatibles con el Arcade Machine Core.
Author: Neritoou
License-Expression: MIT
Project-URL: Homepage, https://github.com/Neritoou/arcade-machine-sdk
Project-URL: Repository, https://github.com/Neritoou/arcade-machine-sdk
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: pygame>=2.6.0

# Arcade Machine SDK

> SDK para el desarrollo de juegos arcade compatibles con una máquina arcade unificada

[![Python Version](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)

---

## Tabla de Contenidos

- [Descripción](#descripción)
- [Requisitos](#requisitos)
- [Instalación](#instalación)
- [Documentación del SDK](#documentación-del-sdk)

---

## Descripción

<p align="justify">
El <strong></strong>Arcade Machine SDK</strong> es un framework académico desarrollado como parte de la materia <strong>Taller de Objetos y Abstracción de Datos</strong> de la Universidad de Oriente. 
</p> 

<p align="justify">
Este SDK provee una <strong>interfaz estándar</strong> que permite a diferentes equipos desarrollar juegos arcade independientes que posteriormente se integrarán en una única aplicación, permitiendo a los usuarios seleccionar y jugar cualquiera de los juegos disponibles.
</p> 

### Objetivo

Este SDK busca estandarizar el desarrollo de juegos arcade mediante:

**Integración y Estandarización:**
- Unificar múltiples juegos en una máquina arcade común
- Mantener consistencia en la interfaz de usuario
- Estandarizar interfaces para integración fluida

**Principios de Ingeniería de Software:**
- Aplicar Programación Orientada a Objetos (POO)
- Implementar patrones de diseño reconocidos
- Desarrollar arquitectura modular y extensible

**Colaboración y Escalabilidad:**
- Facilitar trabajo independiente entre equipos
- Permitir desarrollo paralelo sin conflictos
- Habilitar crecimiento del sistema con nuevos juegos
  
---

## Requisitos

- **Python:** 3.11 o superior
- **Pygame:** 2.6.0 o superior

---

## Instalación

### Requisitos Previos

Antes de instalar, asegúrate de tener:
- **Python 3.11+** instalado ([Descargar aquí](https://www.python.org/downloads/))
- **pip** actualizado: `python -m pip install --upgrade pip`

### Opción 1: Instalación desde PyPI
```bash
pip install arcade-machine-sdk
```

> **Nota:** En algunos sistemas puede ser necesario usar `python -m pip install arcade-machine-sdk` en lugar de solo `pip`.

### Opción 2: Instalación desde GitHub (Versión de desarrollo)
```bash
pip install git+https://github.com/Neritoou/arcade-machine-sdk.git
```

### Opción 3: Usando `requirements.txt`

Crea un archivo `requirements.txt` en tu proyecto:
```txt
arcade-machine-sdk

# Otras dependencias
pygame>=2.5.0
```

Luego instala:

```bash
pip install -r requirements.txt
```

### Verificar Instalación

Después de instalar, verifica que el SDK esté correctamente instalado:

```bash
python -c "from arcade_machine_sdk import GameBase; print('SDK instalado correctamente')"
```

Si ves el mensaje de confirmación, ¡la instalación fue exitosa! 

### Actualizar el SDK

#### Desde PyPI (versión estable):
```bash
pip install --upgrade arcade-machine-sdk
```

#### Desde GitHub (versión de desarrollo):
```bash
pip install --upgrade --force-reinstall git+https://github.com/Neritoou/arcade-machine-sdk.git@main
```

---

## Documentación del SDK

> **Nota:** Para ejemplos de implementación completos, consulta la carpeta `games/example1/` en el [Arcade Machine](https://github.com/Neritoou/Arcade-Machine-TOAD).

### Índice

- [Arquitectura General](#arquitectura-general)
- [Clase GameBase](#clase-gamebase)
- [Clase GameMeta](#clase-gamemeta)
- [Constantes del SDK](#constantes-del-sdk)
- [Utilidades](#utilidades)
- [Manejo de Rutas](#manejo-de-rutas)
- [Casos de uso a Evitar](#casos-de-uso-a-evitar)

---

### Arquitectura General

El SDK implementa una arquitectura de **loop único centralizado**:

- **El Core** mantiene el loop del juego y la ventana principal
- **Los juegos** NO crean su propio loop ni ventana
- **Los juegos** implementan métodos que el Core llama por frame

Esto permite integración fluida y transiciones controladas perfectamente por los integradores

---

### Clase GameBase

Clase abstracta base que **todos los juegos deben heredar**.

#### Importación

```python
from arcade_machine_sdk import GameBase, GameMeta
```

#### Métodos Abstractos (Obligatorios)

| Método | Parámetros | Descripción |
|--------|------------|-------------|
| `handle_events` | `events: list[pygame.event.Event]` | Procesa eventos de entrada. **NO** usar `pygame.event.get()` |
| `update` | `dt: float` | Actualiza la lógica del juego. `dt` = segundos desde último frame |
| `render` | `surface: pygame.Surface` | Dibuja en la surface pasada por parametro. **NO** llamar `pygame.display.flip()` |

#### Métodos del Ciclo de Vida (Opcionales)

```python
def start(self, surface: pygame.Surface) -> None:
    super().start(surface)  # Obligatorio

def stop(self) -> None:
    super().stop()  # Obligatorio

```

#### Propiedades

| Propiedad | Tipo | Descripción |
|-----------|------|-------------|
| `_running` | `bool` | Indica si el juego está activo (solo lectura) |
| `__surface` | `pygame.Surface` | Superficie para dibujar (solo lectura) |
| `metadata` | `GameMeta` | Metadatos del juego (solo lectura) |

#### Ejecución Independiente en el Main del Juego

```python
from game import Game
from arcade_machine_sdk import GameMeta
import pygame

if not pygame.get_init():
    pygame.init()

metadata = (GameMeta()
            .with_title("Ejemplo 1")
            .with_description("Juego de prueba")
            .with_release_date("16/12/2025")
            .with_group_number(1)
            .add_tag("Plataforma")
            .add_author("Carlos Barranca"))

game = Game(metadata)

if __name__ == "__main__":
    game.run_independently()
```

---

### Clase GameMeta

Builder para construir metadatos del juego. **Todos los campos son obligatorios**.

#### Métodos

| Método | Parámetro | Descripción |
|--------|-----------|-------------|
| `with_title` | `str` | Título del juego |
| `with_description` | `str` | Descripción del juego |
| `with_release_date` | `str` | Fecha de salida Original |
| `with_tags` | `list[str]` | Lista de etiquetas |
| `add_tag` | `str` | Añade una etiqueta |
| `with_group_number` | `int` | Número del grupo |
| `with_authors` | `list[str]` | Lista de autores |
| `add_author` | `str` | Añade un autor |

#### Propiedades (Solo Lectura)

- `title`, `description`, `release_date`, `tags`, `group_number`, `authors`

---

### Constantes del SDK


```python
from arcade_machine_sdk import (
    BASE_WIDTH,      # 1024
    BASE_HEIGHT,     # 768
    BASE_RESOLUTION, # (1024, 768)
    DEFAULT_FPS      # 60
)
```

Usa estas constantes para mantener consistencia entre todos los juegos.

---

### Utilidades

#### JSON

```python
from arcade_machine_sdk import json

# Cargar
data = json.load("archivo.json")

# Guardar
json.save("archivo.json", data_dict)
```

---

### Manejo de Rutas

<p align="justify">
<strong>Siempre usa rutas relativas</strong> para garantizar que tu juego funcione correctamente en cualquier sistema, independientemente de donde se ejecute el código. La forma en que se construyen las rutas depende de la estructura del proyecto y de dónde se encuentra el código que las utiliza.
</p>

<p align="justify">
Cuando tu juego esté empaquetado (por ejemplo, usando PyInstaller) o está siendo ejecutado desde un directorio diferente al del juego, la ubicación de los archivos puede variar, por lo que es importante construir las rutas de forma flexible. A continuación, te mostramos cómo hacerlo.
</p>

#### :heavy_check_mark: Correcto - Rutas Relativas

<p align="justify">
El archivo de código debe ser capaz de encontrar la carpeta en la que se encuentren los assets sin importar dónde se ejecute el juego. Esto significa que necesitamos calcular dinámicamente la ubicación base del proyecto, teniendo en cuenta la estructura de directorios.
</p>

<p align="justify">
En el ejemplo siguiente, se parte del supuesto de que el script donde se encuentra el código puede estar en una subcarpeta dentro del proyecto. Por ejemplo, game/src/util/, pero los assets están en una carpeta superior, en el directorio raíz del proyecto.
</p>

```python
from pathlib import Path

# Obtiene el directorio donde se encuentra el archivo actual (por ejemplo, "game/src/util/")
GAME_DIR = Path(__file__).resolve().parent  # Esto te da el directorio donde está el script actual

# Ahora, accede a la carpeta 'assets' desde la raíz del proyecto
ASSETS_DIR = GAME_DIR.parents[2] / "assets"  # Subimos 2 directorios hacia la raíz del proyecto

# Ruta al archivo de imagen dentro de assets -> raiz/assets/player.png
IMAGE_PATH = ASSETS_DIR / "player.png"

# Cargar el recurso
player_img = pygame.image.load(str(IMAGE_PATH))
```

#### ❌ Incorrecto - Rutas Absolutas

<p align="justify">
Evita usar rutas absolutas como <strong>"C:/Users/.../game/assets/player.png"</strong> o <strong>"/home/user/game/assets/player.png"</strong>. Las rutas absolutas son específicas para el sistema de archivos de tu máquina y no son portables a otros entornos, lo que hace que tu código no sea ejecutable en otras computadoras o plataformas.
</p>

```python
# NO hacer esto - solo funciona en tu computadora
player_img = pygame.image.load("C:/Users/Juan/Desktop/game/assets/player.png")
player_img = pygame.image.load("/home/juan/proyecto/assets/player.png")

# NO hacer esto - puede fallar si se ejecuta desde otro directorio
player_img = pygame.image.load("assets/player.png")
```

---

### Casos de uso a evitar

- Crear ventanas con `pygame.display.set_mode()`
- Llamar `pygame.display.flip()` o `pygame.display.update()`
- Usar `pygame.event.get()` directamente
- Crear loops propios con `while`
- Hardcodear resoluciones o FPS
- Hardcodear rutas absolutas (ej: `"C:/Users/..."` o `"/home/user/..."`)

---

## 🎓 Proyecto Académico

<p align="justify">
Este SDK fue desarrollado como parte del proyecto integrador de la asignatura **Taller de Objetos y Abstracción de Datos** en la Universidad de Oriente.
</p>
  
---

<div align="center">

**Hecho por los Integradores del Proyecto Arcade Machine**

[⬆ Volver arriba](#arcade-machine-sdk)

</div>

