Pyxel permet de créer en Python des jeux rendant hommage aux vieilles consoles, comme la Game Boy Color : de gros pixels, une palette de couleur réduite, un son minimaliste (mais sur 4 canaux).
Ce minimalisme permet de créer rapidement des jeux qui fonctionneront de manière fluide, grâce à sa bibliothèque en Rust, sur n’importe quelle brouette, et même sur une page web (avec Wasm).
Préparation
Pyxel fonctionne sur Linux, Mac et Windows.
Le développement se passe depuis le terminal, en tapant des commandes.
Éditeur de texte
Il vous faut un éditeur de texte : VSCode, Sublime Text, ou un autre qui vous plait. Ils sont disponibles en téléchargement depuis leur page web, ou via les appstores des différents OS.
Sur Mac ce sera Homebrew avec brew install vscode
.
Sur Ubuntu, ce sera avec Snap disponible depuis la barre d’outils.
Python
Vérifiez que vous avez Python dans une version décente (>= 3.10) : python3 -V
Sinon, il faut l’installer. Pour Mac, ce sera brew install python
, pour Linux, ce sera sudo apt install python3-dev python3-venv python3-pip
, pour Windows ce sera via python.org.
Installation
Pyxel n’est pas une application, mais un framework Python, avec un éditeur de médias.
Donc, pour l’utiliser, il suffit d’avoir Python sur sa machine, et de créer des projets, avec leur environnement, (un venv
), puis d’ajouter la bibliothèque pyxel
avec l’outil pip
.
Pour ne pas mettre le bazar, on va ranger le code dans un dossier
mkdir pyxel-demo
cd pyxel-demo
Puis créer un environnement pour Python, pour pouvoir installer des bibliothèques uniquement pour ce projet et ne pas tout cochonner.
python3 -m venv .pyxel-env
source .pyxel-env/bin/activate
Sur Windows, l’activation utilise une commande différente.
Installation des bibliothèques. On commence par mettre à jour pip pour ne pas qu’il râle, puis on installe pyxel
.
pip install -U pip
pip install pyxel
Exemples de projets Pyxel
pyxel copy_examples
Pyxel va télécharger son dossier d’exemple et créer le dossier pyxel_examples
.
La commande pyxel run
permet de lancer les démos.
pyxel run pyxel_examples/02_jump_game.py
Jump Game utilise les flèches droite/gauche pour accélérer/ralentir le personnage.
L’éditeur de médias pour Pyxel
Pyxel fournit un éditeur de médias (sprites, tilemap, sound, music).
Pyxel utilise des formats traditionnels (et même antiques).
Les images sont en PNG (la transparence est gérée). Les jeux vidéos ont l’habitude d’avoir le zéro dans le coin haut gauche. Il est possible de glisser/déposer des images PNG/GIF/JPG dans la fenêtre de l’éditeur.
Les polices de caractères (les fonts, quoi) sont en pixel et au format BDF, éditables avec fontforge.
Les maps sont au format TMX, éditables avec Tiled (plus de formats sont disponibles sur Github)
L’éditeur Pyxel crée des archives pyxres
qui sont fichiers ZIP avec un gros TOML à l’intérieur avec les binaires gérés comme des listes d’entiers.
Le son est dans un format spécifique.
pyxel edit
Démo
Demo party !
Une fois ce premier test réussi, et quelques bidouillage pour se l’approprier, il faudra lire la doc, une longue page.
Le code est typé, mais non commenté, ce qui permet d’avoir quelques indices depuis son éditeur.
Éditeur de médias
pyxel edit initiation.pyxres &
Dessinez deux vaisseaux spatiaux, de 16 pixels de côté.
C’est votre vaisseau, vous dessinez bien ce que vous voulez, tant que vous respectez les consignes.
Le premier regarde à droite, le second, à gauche.
Par convention, la transparence est la première couleur (noir), et correspond à la valeur 0 dans le code.
Si vous galérez, vous pouvez simplement télécharger le fichier initiation.pyxres.
Code
Éditez un fichier initiation.py
, puis adaptez le code d’exemple (plus bas) à vos besoins.
# Uniquement sur UNIX
touch initiation.py
Un vaisseau immobile
L’applicaition est rangé dans une class
.
Lors de la création de la class
, on choisit la taille de l’écran et son titre. Les assets
sont chargés.
La méthode update
gère les entrées (le clavier dans ce cas).
La méthode draw
va entièrement redessiner l’écran.
import pyxel
class App:
def __init__(self):
pyxel.init(160, 120, title="UFO static") # width, height, title
pyxel.load("initiation.pyxres")
self.player_x = 72 # 🛸 X position
self.player_y = 72 # 🛸 Y position
self.ship = (0, 0, 16, 16, 0) # x, y, width, height, transparent color
pyxel.run(self.update, self.draw)
def update(self):
if pyxel.btnp(pyxel.KEY_Q):
pyxel.quit()
def draw(self):
pyxel.cls(0) # clear screen with color 0
# Draw 🛸
pyxel.blt(self.player_x, self.player_y, 0, *self.ship)
App()
Demandez à Pyxel de surveiller votre jeu.
pyxel watch . initiation.py
Le vaisseau s’affiche au milieu du vide de l’espace, et on peut juste quitter l’application avec la touche Q.
Le vaisseau est secoué
Un peu de math, un simple cosinus, pour que le vaisseau rebondisse mollement.
import pyxel
class App:
def __init__(self):
pyxel.init(160, 120, title="UFO shaken") # width, height, title
pyxel.load("initiation.pyxres")
self.player_x = 72 # 🛸 X position
self.player_y = 72 # 🛸 Y position
self.ship = (0, 0, 16, 16, 0) # x, y, width, height, transparent color
pyxel.run(self.update, self.draw)
def update(self):
if pyxel.btnp(pyxel.KEY_Q):
pyxel.quit()
# 🛸 bumps slowly 1/16 per tick starting with y = 72
self.player_y = pyxel.cos(pyxel.frame_count * 360 / 16) + 72
def draw(self):
pyxel.cls(0) # clear screen with color 0
# Draw 🛸
pyxel.blt(self.player_x, self.player_y, 0, *self.ship)
App()
Le vaisseau peut avancer dans un sens ou dans l’autre
Le vaisseau peut pointer d’un côté ou de l’autre, grâce à deux sprites.
Avec les flèches, on peut avancer ou reculer de 2 pixels (sans sortir du cadre).
import pyxel
class App:
def __init__(self):
pyxel.init(160, 120, title="UFO exploration") # width, height, title
pyxel.load("initiation.pyxres")
self.player_x = 72 # 🛸 X position
self.player_y = 72 # 🛸 Y position
self.spaceship_r = (0, 0, 16, 16, 0) # x, y, width, height, transparent color
self.spaceship_l = (16, 0, 16, 16, 0)
self.ship = self.spaceship_r # 🛸 looks ->
pyxel.run(self.update, self.draw)
def update(self):
if pyxel.btnp(pyxel.KEY_Q):
pyxel.quit()
if pyxel.btn(pyxel.KEY_LEFT) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_LEFT):
self.player_x = max(self.player_x - 2, 0) # go ->
self.ship = self.spaceship_l # 🛸 looks <-
if pyxel.btn(pyxel.KEY_RIGHT) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_RIGHT):
self.player_x = min(self.player_x + 2, pyxel.width - 16) # go ->
self.ship = self.spaceship_r # 🛸 looks ->
# 🛸 bumps slowly 1/16 per tick starting with y = 72
self.player_y = pyxel.cos(pyxel.frame_count * 360 / 16) + 72
def draw(self):
pyxel.cls(0) # clear screen with color 0
# Draw 🛸
pyxel.blt(self.player_x, self.player_y, 0, *self.ship)
App()
Voilà, vous avez un sprite qui gigote et réagit aux frappes sur un clavier.