PyCgame 1.8.0
Moteur Python pour jeux 2D avec gestion des images, sons et entrées
Requires Python: >=3.8

# 🎮 PyCgame

**PyCgame** est un module Python pour créer facilement des jeux 2D avec :

* 🖼️ Gestion des **images**
* 🔊 Gestion des **sons**
* ⌨️ Gestion du **clavier/souris**
* 🎮 Support des **manettes/joysticks**
* 🧮 Fonctions **mathématiques intégrées**

👉 Compatible avec **Windows** et **Linux**.

---

<img src="https://raw.githubusercontent.com/Baptistegrn/PyCgame/refs/heads/main/demo.gif" width="500">

## ⚡ Installation

### 📦 Depuis PyPI

```bash
pip install PyCgame
```

---

### 🐍 Importation dans votre projet

```python
from PyCgame import PyCgame
```

> ⚠️ **Important :**  
> L’import **doit être exactement** :
> ```python
> from PyCgame import PyCgame
> ```
> Toute autre forme d’import peut empêcher la bibliothèque de localiser correctement ses dépendances internes.

---

### ⚙️ Compilation automatique

Si votre système d’exploitation **n’est pas directement compatible**,  
la compilation de la bibliothèque native sera **automatiquement effectuée via [`xmake`](https://xmake.io)**.

Assurez-vous que :
- la librairie compilée se trouve bien dans **`dist/`** (ex : `PyCgame/dist/`),  
- et que `xmake` est correctement installé et accessible dans votre terminal.

---

### 🧱 Génération d’un exécutable

Pour compiler votre projet en exécutable autonome :

```bash
pycgame_app nom_du_fichier
```

**Détails :**
- Le fichier `.exe` (ou équivalent selon l’OS) sera généré dans le dossier **`/dist`**.  
- **[PyInstaller](https://pyinstaller.org/)** est requis pour cette étape.  
- L’exécutable généré est **spécifique à l’OS** sur lequel la compilation a été faite.  

> 💡 **Astuce :**  
> Si vous avez recompilé la librairie via `xmake`, l’exécutable obtenu **ne sera pas forcément portable** entre distributions Linux différentes.  
> Il est donc recommandé de compiler sur une **distribution largement utilisée** (ex. *Ubuntu*, *Debian*, *Fedora*).



## 🚀 Initialisation d'un jeu

```python
PyCgame.init(
    largeur=160,           # largeur virtuelle
    hauteur=90,            # hauteur virtuelle
    fps=60,                # nombre d'images par seconde
    coeff=3,               # facteur de mise à l'échelle
    chemin_image="./assets", # dossier images
    chemin_son="./assets",   # dossier sons
    dessiner=True,         # dessiner le fond ?
    bande_noir=True,       # bandes noires si ratio différent ?
    r=0, g=0, b=0,         # couleur de fond
    update_func=Update,    # fonction d'update
    nom_fenetre="MonJeu",  # nom de la fenêtre
    debug=False            # on écrit les logs dans erreurs.log ?
)

PyCgame.stopper_jeu()
```

---

## 🔄 Boucle de mise à jour

```python
def Update():
    if PyCgame.touche_presser("Espace"):
        print("Espace pressée !")
```

---

## 📊 Propriétés globales

| Propriété            | Description                         |
| -------------------- | ----------------------------------- |
| `PyCgame.largeur`    | largeur virtuelle                   |
| `PyCgame.hauteur`    | hauteur virtuelle                   |
| `PyCgame.dt`         | delta time entre frames             |
| `PyCgame.fps`        | FPS actuel                          |
| `PyCgame.time`       | temps écoulé                        |
| `PyCgame.run`        | bool : le jeu tourne ?              |
| `PyCgame.decalage_x` | décalage en x du jeu en plein écran |
| `PyCgame.decalage_y` | décalage en y du jeu en plein écran |

---

## 🖱️ Gestion de la souris

```python
PyCgame.mouse_x
PyCgame.mouse_y
PyCgame.mouse_presse
PyCgame.mouse_juste_presse
PyCgame.mouse_droit_presse
PyCgame.mouse_droit_juste_presse
```

---

## ⌨️ Gestion du clavier

### Vérification des touches

```python
PyCgame.touche_presser("A")
PyCgame.touche_enfoncee("A")
```

### Liste complète des touches supportées

#### Lettres :

`A` … `Z` (majuscules ou minuscules acceptées)

#### Chiffres :

`0` … `9`

#### Touches spéciales :

* `espace`
* `entrer` / `return`
* `echap` / `escape`
* `tab`
* `maj` / `shift`
* `ctrl` / `control`
* `alt`
* `altgr`
* `capslock` / `verrmaj`
* `verrnum` / `numlock`

#### Navigation :

* `haut` / `up`
* `bas` / `down`
* `gauche` / `left`
* `droite` / `right`
* `insert`
* `suppr` / `delete`
* `home`
* `end`
* `pageup` / `precedent`
* `pagedown` / `suivant`

#### Système :

* `menu` / `context`
* `printscreen` / `impr`
* `scrolllock`
* `pause` / `break`

#### Pavé numérique :

* `kp0` … `kp9`
* `kp+`
* `kp-`
* `kp*`
* `kp/`
* `kp.`
* `kpentrer` / `kpreturn`

#### Fonctions :

* `F1` … `F12`

---

## 🎮 Gestion des manettes

```python
PyCgame.init_mannette(0)

if PyCgame.touche_mannette_juste_presse("X"):
    PyCgame.pause_son("./assets/test.wav")

if PyCgame.touche_mannette_juste_presse("Y"):
    PyCgame.reprendre_son("./assets/test.wav")

if PyCgame.touche_mannette_enfoncee("A"):
    print("A maintenu")

# Lecture des joysticks
axes = PyCgame.renvoie_joysticks()
if axes:
    x_gauche, y_gauche, x_droit, y_droit, lt, rt = axes
    print("Stick gauche :", x_gauche, y_gauche)
    print("Stick droit  :", x_droit, y_droit)
    print("Triggers     :", lt, rt)

PyCgame.fermer_controller()
```

### Boutons supportés

#### Boutons principaux :

* `a`, `b`, `x`, `y`

#### Système :

* `start`, `back`, `select`, `guide`, `home`, `share`, `capture`

#### Sticks cliquables :

* `leftstick`, `l3`
* `rightstick`, `r3`

#### Bumpers :

* `lb`, `l1`, `leftshoulder`
* `rb`, `r1`, `rightshoulder`

#### Triggers :

* `lt`, `l2`
* `rt`, `r2`

#### Croix directionnelle (D-Pad) :

* `haut` / `up`
* `bas` / `down`
* `gauche` / `left`
* `droite` / `right`

#### Additionnels :

* `paddle1`, `paddle2`, `paddle3`, `paddle4`
* `touchpad`

### 🎮 Joysticks analogiques

`PyCgame.renvoie_joysticks(dead_zone=0.1)`  
Retourne un tableau de 6 valeurs flottantes entre -1 et 1 :

1. axe horizontal du stick gauche  
2. axe vertical du stick gauche  
3. axe horizontal du stick droit  
4. axe vertical du stick droit  
5. gâchette gauche (trigger L2 / LT)  
6. gâchette droite (trigger R2 / RT)  

⚠️ Dead zone : ignore les petites variations au repos (par défaut 0.1)

---

## 🖼️ Images et texte

Le système de rendu utilise **l'ordre de dessin** : les éléments sont affichés dans l'ordre où ils sont ajoutés. Pour placer une image au premier plan, il faut retirer les éléments qui la précèdent puis les rajouter après (coût négligeable).

```python
# Dessiner une image
PyCgame.dessiner_image("./assets/perso.png", x=10, y=20, w=32, h=32, sens=0, rotation=0)

# Dessiner plusieurs images en batch (plus performant)
PyCgame.dessiner_image_batch(
    ids=["./assets/tile.png", "./assets/tile.png", "./assets/enemy.png"],
    xs=[0, 32, 64],
    ys=[0, 0, 16],
    ws=[32, 32, 48],
    hs=[32, 32, 48],
    sens=[0, 0, 1],      # optionnel (par défaut : 0)
    rotations=[0, 0, 90] # optionnel (par défaut : 0)
)

# Dessiner du texte
PyCgame.dessiner_mot(
    lien="./assets/police",  # chemin vers la police de caractères
    mot="Hello World",
    x=50, y=50,
    coeff=1,    # facteur de taille
    ecart=1,    # espacement entre les caractères
    sens=0,     # orientation (0=normal, 1=miroir horizontal)
    rotation=0  # rotation en degrés
)

# Écrire dans la console de debug
PyCgame.ecrire_console("Message de debug")
```

### Paramètres de dessin

* **lien/ids** : chemin vers l'image ou la police de caractères
* **x, y** : position en pixels (coordonnées virtuelles)
* **w, h** : largeur et hauteur en pixels
* **sens** : orientation (0 = normal, 1 = miroir horizontal)
* **rotation** : rotation en degrés (0-360)
* **coeff** : facteur d'échelle pour le texte
* **ecart** : espacement entre les caractères du texte

---

## 🔊 Sons

```python
# Jouer un son
PyCgame.jouer_son("./assets/son.wav", boucle=1, canal=3)

# Arrêter un son spécifique
PyCgame.arreter_son("./assets/son.wav")

# Arrêter un canal
PyCgame.arreter_canal(3)

# Pause/Reprendre par canal
PyCgame.pause_canal(3)
PyCgame.reprendre_canal(3)

# Pause/Reprendre par son
PyCgame.pause_son("./assets/son.wav")
PyCgame.reprendre_son("./assets/son.wav")
```

### Paramètres audio

* **boucle** : nombre de répétitions (-1 = infini, 0 = une fois, 1+ = répétitions)
* **canal** : canal audio à utiliser (-1 = automatique, 0-31 = canal spécifique)

---

## 🧮 Fonctions mathématiques

```python
PyCgame.abs_val(-5)
PyCgame.clamp(10, 0, 5)
PyCgame.pow(2, 3)
PyCgame.sqrt(16)
PyCgame.sin(3.14)
PyCgame.atan2(1, 1)
```

Inclus aussi : `cos`, `tan`, `log`, `exp`, `floor`, `ceil`, `round`, `trunc`, `fmod`, `hypot`, etc.

---

## 🖥️ Redimensionnement

```python
PyCgame.redimensionner_fenetre()
```

---

## 🎨 Colorier fond

```python
PyCgame.colorier(r, g, b)
```

---

## 🎲 Fonction random

```python
PyCgame.random(min, max)
```

---

## 📂 Exemple minimal

```python
from PyCgame import PyCgame

def update():
    # Dessiner une image chaque frame
    PyCgame.dessiner_image("./assets/player.png", 10, 10, 32, 32)
    
    if PyCgame.touche_presser("Espace"):
        print("Espace pressée !")

PyCgame.init(largeur=160, hauteur=90, fps=60, update_func=update)
```

---

## ✅ Notes importantes

* Les chemins des fichiers sont relatifs au projet.
* Les images sont dessinées **dans l'ordre d'ajout** - l'ordre définit la profondeur de rendu.
* `update_func` doit être une **fonction callable**.
* Utilisez `dessiner_image_batch()` pour optimiser le rendu de multiples images similaires.
* Pour les manettes : toujours appeler `PyCgame.init_mannette()` après `PyCgame.init()` et fermer avec `PyCgame.fermer_controller()` avant de quitter.

---

## 📬 Support

Pour signaler un bug ou proposer une amélioration :  
📧 **[Baptiste.guerin34@gmail.com](mailto:Baptiste.guerin34@gmail.com)**