Moteur de jeu 2D sur PyOpenGL (GLFW + Pillow)
Project description
Tiavina.engine
Moteur de jeu 2D pixel art, construit sur Pygame.
Fonctionne avec un écran virtuel (résolution logique) mis à l'échelle entière vers la fenêtre d'affichage.
Installation
pip install Tiavina.engine
from Engine import engine as e
e.init(200, 200, "Mon Jeu", fps=60, display_scale=4)
def update():
if e.btn(e.KEY_ESCAPE):
e.quit()
def draw():
e.cls((30, 30, 40))
e.rect(10, 10, 20, 20, (255, 0, 0))
e.run(update, draw)
Table des matières
Architecture
Engine/
├── __init__.py ← réexporte l'API
├── engine.py ← le moteur (tout-en-un)
└── fonts/
└── PressStart2P.ttf ← police pixel embarquée
Le moteur expose une API globale : on importe from Engine import engine as e et on appelle e.init(), e.cls(), e.btn(), etc.
Sous le capot :
App— classe principale qui gère la fenêtre Pygame, l'horloge FPS, levirtual_screen(Surface logique), et la boucle d'événements.Graphics— dessin sur l'écran virtuel avec support de caméra, clipping, et alpha.Input— gestion clavier, souris, joystick.Resources— chargement d'images, sons, musiques.Audio— lecture son/musique via les canaux Pygame.
Initialisation
e.init(width, height, title="T.engine", fps=30, display_scale=1)
Crée la fenêtre et initialise tous les sous-systèmes.
| Paramètre | Type | Description |
|---|---|---|
width |
int |
Largeur logique de l'écran virtuel (ex: 200) |
height |
int |
Hauteur logique (ex: 200) |
title |
str |
Titre de la fenêtre |
fps |
int |
Images par seconde cibles |
display_scale |
int |
Facteur d'échelle entier (ex: 5 → fenêtre 1000×1000 pour 200×200) |
L'écran virtuel fait width × height pixels. Chaque frame, il est scaled par display_scale et affiché dans la fenêtre système.
e.init(200, 200, "Mon Jeu", 60, 5)
e.run(update, draw)
Lance la boucle de jeu. update() est appelée à chaque frame pour la logique, draw() pour le rendu.
def update():
pass
def draw():
e.cls((0, 0, 0))
e.run(update, draw)
e.quit()
Ferme Pygame et termine le processus.
e.width(), e.height()
Retourne la largeur/hauteur logique définies dans init().
e.frame_count()
Retourne le nombre de frames écoulées depuis init().
Graphismes — Graphics
Toutes les fonctions de dessin sont affectées par la caméra (sauf si camera() est réinitialisée).
Les coordonnées sont en pixels logiques.
Primitives de dessin
| Fonction | Description |
|---|---|
cls(color) |
Remplit tout l'écran virtuel avec une couleur |
pset(x, y, color) |
Dessine un pixel |
pget(x, y) → Color |
Lit la couleur d'un pixel |
line(x1, y1, x2, y2, color) |
Ligne |
rect(x, y, w, h, color) |
Rectangle plein |
rectb(x, y, w, h, color) |
Rectangle vide (1px de bord) |
circ(x, y, r, color) |
Cercle plein |
circb(x, y, r, color) |
Cercle vide (1px de bord) |
elli(x, y, w, h, color) |
Ellipse pleine |
ellib(x, y, w, h, color) |
Ellipse vide (1px de bord) |
tri(x1, y1, x2, y2, x3, y3, color) |
Triangle plein |
trib(x1, y1, x2, y2, x3, y3, color) |
Triangle vide (1px de bord) |
Couleurs avec alpha (RGBA)
Toutes les primitives sauf text() et pget() acceptent des couleurs RGBA (4 valeurs).
L'alpha est géré via un blending additif sur une surface temporaire.
# Rectangle semi-transparent
e.rect(10, 10, 50, 50, (255, 0, 0, 128))
Blit d'image
blt(x, y, img, u, v, w, h, colkey=None, rotate=0)
| Paramètre | Type | Description |
|---|---|---|
x, y |
int |
Position de destination (coin supérieur gauche) |
img |
pygame.Surface |
Image source |
u, v |
int |
Coordonnées source (coin supérieur gauche dans l'image) |
w, h |
int |
Dimensions de la région source |
colkey |
Color ou None |
Couleur de transparence (optionnelle) |
rotate |
float |
Rotation en degrés horaire (pivot au centre) |
e.blt(100, 100, img, 0, 0, 16, 16) # blit simple
e.blt(100, 100, img, 0, 0, 16, 16, rotate=45) # rotation
Texte
text(x, y, s, color, font=None)
| Paramètre | Type | Description |
|---|---|---|
x, y |
int |
Position |
s |
str |
Texte à afficher |
color |
tuple |
Couleur RGB (pas de support alpha) |
font |
pygame.Font ou None |
Police personnalisée (None = police pixel par défaut) |
La police par défaut est PressStart2P.ttf taille 6px, rendu sans anti-aliasing pour un aspect pixel art.
e.text(5, 5, "Score: 42", (255, 255, 255))
# Avec une police différente
big = e.default_font(16)
e.text(5, 20, "Titre", (255, 200, 0), font=big)
Caméra
camera(dx, dy) # Applique un décalage à tout le dessin suivant
camera() # Réinitialise le décalage à (0, 0)
La caméra est cumulative : tous les appels camera() s'ajoutent.
Pour un système plus avancé, voir la classe Camera.
e.camera(-player.x + 100, -player.y + 100) # suit le joueur
Clipping
clip(x, y, w, h) # Active un rectangle de clipping
clip() # Désactive le clipping
Le clipping est appliqué après la caméra.
Caméra intelligente — Camera
cam = e.Camera(target, screen_width, screen_height,
mouse_influence=0.2, mouse_limit=10)
Classe réutilisable avec suivi de cible, offset souris, tremblement et flash.
Paramètres du constructeur
| Paramètre | Défaut | Description |
|---|---|---|
target |
— | Objet suivi (doit avoir .x, .y) |
screen_width |
— | Largeur de l'écran logique |
screen_height |
— | Hauteur de l'écran logique |
mouse_influence |
0.2 |
Sensibilité du regard vers la souris (0.0–1.0) |
mouse_limit |
10 |
Décalage maximal dû à la souris (en pixels logiques) |
Méthodes
| Méthode | Description |
|---|---|
update() |
Calcule la nouvelle position de la caméra (target + souris + shake) |
apply() |
Applique le décalage au moteur graphique (e.camera(cam.cam_x, cam.cam_y)) |
shake(duration, intensity) |
Déclenche un tremblement d'écran |
flash(color, alpha, duration) |
Déclenche un flash d'écran |
Attributs
| Attribut | Description |
|---|---|
cam_x, cam_y |
Position calculée de la caméra (en pixels logiques) |
flash_color |
Couleur du flash actif |
flash_alpha |
Opacité courante du flash |
shake_intensity |
Intensité du tremblement actuel |
Le flash doit être dessiné manuellement dans draw() :
if cam.flash_alpha > 0:
surf = pygame.Surface((e.width(), e.height()), pygame.SRCALPHA)
surf.fill((*cam.flash_color, cam.flash_alpha))
e.graphics.screen.blit(surf, (0, 0))
Entrées — Input
Clavier
btn(key) # → True si la touche est maintenue
btnp(key) # → True le frame où la touche est pressée (pas de répétition)
btnr(key) # → True le frame où la touche est relâchée
if e.btn(e.KEY_SPACE):
player.jump()
if e.btnp(e.KEY_E):
player.interact()
Souris
mouse_x(), mouse_y() # → Position logique (divisée par display_scale)
mouse_btn(button) # → True si le bouton est maintenu
mouse_btnp(button) # → True le frame du clic
mouse_btnr(button) # → True le frame du relâchement
mouse(visible=True) # → Affiche ou cache le curseur système
Boutons : MOUSE_BUTTON_LEFT (1), MOUSE_BUTTON_MIDDLE (2), MOUSE_BUTTON_RIGHT (3)
if e.mouse_btnp(e.MOUSE_BUTTON_LEFT):
print(f"Clic à ({e.mouse_x()}, {e.mouse_y()})")
Joystick
joy(joy_id, button) # → True si le bouton du joystick est pressé
joy_axis(joy_id, axis) # → Valeur de l'axe (-1.0 à 1.0)
Les joysticks sont détectés et initialisés automatiquement au lancement.
Ressources — Resources
resources.image(bank, path, colkey=None) # → pygame.Surface ou None
resources.sound(bank, path) # → pygame.mixer.Sound ou None
resources.music(bank, path) # → None (enregistre le chemin)
resources.tilemap(bank) # → None (non implémenté)
resources.load(filename) # → lève NotImplementedError
Images
image() charge une image dans resources.images[bank].
bank: index numérique (int)path: chemin relatif ou absolucolkey: couleur de transparence optionnelle (ex:(255, 0, 255))
e.resources.image(0, "./sprites/player.png")
e.resources.image(1, "./sprites/tiles.png", (255, 0, 255))
# Utilisation
img = e.resources.images[1]
Sons
e.resources.sound(0, "./sfx/jump.wav")
e.audio.play(0, 0) # joue sur le canal 0
Audio — Audio
8 canaux (0–7) pour les effets sonores, 1 flux pour la musique.
audio.play(channel, sound_key, loop=False) # joue un son
audio.playm(music_key, loop=False) # joue une musique
audio.stop(channel=None) # stop (tout si channel=None)
audio.play_pos(channel) # → True si le canal est actif
e.audio.play(2, 0) # son index 0 sur canal 2
e.audio.playm("boss_music") # musique
e.audio.stop() # coupe tout
Police pixel — default_font
default_font(size=6) → pygame.Font
Charge et met en cache la police PressStart2P.ttf.
Si le fichier TTF est introuvable, tombe sur pygame.font.Font(None, size).
La police est stockée dans un cache global _pixel_font_cache : chaque taille n'est chargée qu'une fois.
petite = e.default_font(6)
moyenne = e.default_font(8)
grande = e.default_font(16)
Constantes
Touches clavier
KEY_A–KEY_Z, KEY_0–KEY_9,
KEY_SPACE, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT,
KEY_ESCAPE, KEY_RETURN, KEY_TAB, KEY_BACKSPACE,
KEY_LSHIFT, KEY_RSHIFT, KEY_LCTRL, KEY_RCTRL,
KEY_LALT, KEY_RALT
Toutes sont des constantes Pygame (pygame.K_*) réexportées par le module.
Boutons souris
| Constante | Valeur |
|---|---|
MOUSE_BUTTON_LEFT |
1 |
MOUSE_BUTTON_MIDDLE |
2 |
MOUSE_BUTTON_RIGHT |
3 |
Fonctions globales
Le module engine expose des fonctions globales qui délèguent aux sous-systèmes internes :
| Fonction | Délègue à |
|---|---|
cls(c) |
graphics.cls(c) |
pset(x,y,c) |
graphics.pset(x,y,c) |
pget(x,y) |
graphics.pget(x,y) |
line(x1,y1,x2,y2,c) |
graphics.line(...) |
rect(x,y,w,h,c) |
graphics.rect(...) |
rectb(x,y,w,h,c) |
graphics.rectb(...) |
circ(x,y,r,c) |
graphics.circ(...) |
circb(x,y,r,c) |
graphics.circb(...) |
elli(x,y,w,h,c) |
graphics.elli(...) |
ellib(x,y,w,h,c) |
graphics.ellib(...) |
tri(x1,y1,x2,y2,x3,y3,c) |
graphics.tri(...) |
trib(x1,y1,x2,y2,x3,y3,c) |
graphics.trib(...) |
text(x,y,s,c,font) |
graphics.text(...) |
blt(x,y,img,u,v,w,h,...) |
graphics.blt(...) |
bltm(x,y,tm,u,v,w,h,...) |
graphics.bltm(...) |
clip(x,y,w,h) |
graphics.clip(...) |
camera(x,y) |
graphics.camera(...) |
pal(c1,c2) |
graphics.pal(...) (stub) |
dither(a) |
graphics.dither(...) (stub) |
mouse_btn(b) |
input.mouse_btn(b) |
mouse_btnp(b) |
input.mouse_btnp(b) |
mouse_btnr(b) |
input.mouse_btnr(b) |
btn(k) |
input.btn(k) |
btnp(k) |
input.btnp(k) |
btnr(k) |
input.btnr(k) |
Exemple complet
import pygame
from Engine import engine as e
from random import randint
# ── Initialisation ─────────────────────────────────────
e.init(200, 200, "Aventurier", fps=60, display_scale=5)
# ── Ressources ─────────────────────────────────────────
e.resources.image(0, "./sprites/player.png")
e.resources.image(1, "./sprites/tiles.png")
# ── Joueur ─────────────────────────────────────────────
class Player:
def __init__(self):
self.x = 100
self.y = 100
self.w = 8
self.h = 8
self.vie = 100
player = Player()
# ── Caméra ─────────────────────────────────────────────
cam = e.Camera(player, e.width(), e.height(),
mouse_influence=0.3, mouse_limit=12)
# ── Boucle ─────────────────────────────────────────────
def update():
# Déplacements
if e.btn(e.KEY_LEFT): player.x -= 1
if e.btn(e.KEY_RIGHT): player.x += 1
if e.btn(e.KEY_UP): player.y -= 1
if e.btn(e.KEY_DOWN): player.y += 1
if e.btn(e.KEY_ESCAPE): e.quit()
# Clic pour shake
if e.mouse_btnp(e.MOUSE_BUTTON_LEFT):
cam.shake(10, 6)
cam.flash((255, 255, 200), 60, 4)
cam.update()
cam.apply()
def draw():
e.cls((30, 30, 40))
# Sol (en coordonnées monde)
for i in range(-2, 30):
for j in range(-2, 20):
e.rect(i * 8, j * 8, 8, 8, (40, 45, 55))
# Joueur
e.rect(player.x, player.y, player.w, player.h,
(100, 200, 255) if player.vie > 0 else (255, 50, 50))
# Flash overlay (dessiné avant la réinitialisation caméra)
if cam.flash_alpha > 0:
surf = pygame.Surface((e.width(), e.height()), pygame.SRCALPHA)
surf.fill((*cam.flash_color, cam.flash_alpha))
e.graphics.screen.blit(surf, (0, 0))
# ── HUD (coordonnées écran) ──
e.camera() # ← réinitialise la caméra
e.text(4, 4, f"Vie: {player.vie}", (255, 255, 255))
e.text(4, 12, f"Pos: {player.x},{player.y}", (200, 200, 200))
# Curseur
e.circb(e.mouse_x(), e.mouse_y(), 3, (255, 255, 255, 80))
e.run(update, draw)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
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 tiavina_engine_gl-0.1.0-py3-none-any.whl.
File metadata
- Download URL: tiavina_engine_gl-0.1.0-py3-none-any.whl
- Upload date:
- Size: 47.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c0c053d3c73829fc091cf71a936e741b2a88e645b7155bc1cfd6794d930e710a
|
|
| MD5 |
524c723099cf4e19c08d98f33067ea05
|
|
| BLAKE2b-256 |
f6e2d3afc55b3cbb07420bfc90e95b74b9d1caba89b5af68bc047f61ce7cfbdf
|