This commit is contained in:
bach
2026-10-08 15:25:14 +02:00
parent 32e617f67b
commit da4fac3af7
64 changed files with 3921 additions and 0 deletions
+265
View File
@@ -0,0 +1,265 @@
# Coder ses animations en Python
Krita sert à **dessiner** des animations image par image. Le code sert à les
**calculer** : du hasard, des mouvements continus, des formules, des
réactions à un capteur… des choses très longues, voire impossibles, à
dessiner à la main.
Ce guide s'adresse à ceux qui ont joué avec le code Arduino
([`matrice_8x32.ino`](../matrice_8x32/matrice_8x32.ino)) et veulent continuer
sur le Raspberry Pi. Le fichier de travail est
[`mes_animations.py`](mes_animations.py) : **les mêmes animations que sur
l'Arduino, traduites en Python**. Ouvrez les deux côte à côte !
---
## Sommaire
1. [Lancer un programme](#1-lancer-un-programme)
2. [Python pour qui connaît l'Arduino](#2-python-pour-qui-connaît-larduino)
3. [Les outils de dessin](#3-les-outils-de-dessin)
4. [Exercices](#4-exercices)
5. [Mélanger code et images](#5-mélanger-code-et-images)
6. [Transformer son code en GIF](#6-transformer-son-code-en-gif)
7. [Comment est construit le moteur](#7-comment-est-construit-le-moteur)
---
## 1. Lancer un programme
Pas de téléversement en Python : on **lance** le fichier directement.
| Où | Commande |
|---|---|
| Sur son ordinateur, avec le simulateur | `python3 mes_animations.py --simulateur` (Windows : `py` au lieu de `python3`) |
| Sur le Pi, sur la vraie matrice | `sudo ~/vitrine-env/bin/python mes_animations.py` |
**Ctrl + C** (ou fermer la fenêtre du simulateur) pour arrêter.
> Sur le Pi, si le lecteur tourne déjà en mode vitrine, arrêtez-le d'abord :
> `sudo systemctl stop vitrine-pixels`. Un seul programme à la fois peut
> parler à la matrice.
Pour **éditer** le fichier : sur l'ordinateur, n'importe quel éditeur de
texte (le plus confortable : **Thonny**, <https://thonny.org>, conçu pour
apprendre Python, ou **VS Code**). Sur le Pi : `nano mes_animations.py`.
---
## 2. Python pour qui connaît l'Arduino
| | Arduino (C++) | Python |
|---|---|---|
| Fin d'instruction | `;` obligatoire | rien |
| Bloc (dans une boucle, une fonction…) | entre `{ }` | **décalé de 4 espaces** après un `:` |
| Commentaire | `// texte` | `# texte` |
| Variable | `int x = 3;` | `x = 3` |
| Fonction | `void anim() { … }` | `def anim():` + bloc décalé |
| Boucle « pour » | `for (int x = 0; x < 32; x++) { … }` | `for x in range(32):` |
| Compte à rebours | `for (int y = 7; y > 0; y--)` | `for y in range(7, 0, -1):` |
| Condition | `if (x > 3) { … } else { … }` | `if x > 3:` … `else:` … |
| « et », « ou », « non » | `&&`, `\|\|`, `!` | `and`, `or`, `not` |
| Vrai / faux | `true` / `false` | `True` / `False` (majuscule !) |
| Tableau | `int t[3] = {1, 2, 3};` | `t = [1, 2, 3]` (une « liste ») |
| Couleur | `CRGB(255, 0, 0)` | `(255, 0, 0)` (un « tuple ») |
| Couleur par teinte | `CHSV(160, 255, 255)` | `teinte(160)` |
| Hasard | `random(32)` | `random.randrange(32)` |
| Attendre 100 ms | `delay(100);` | `attendre(100)` |
| Afficher | `FastLED.show();` | `montrer()` |
| Boucle principale | `void loop() { … }` | `while True:` + bloc décalé |
**Le piège n° 1 de Python : l'indentation.** Les espaces en début de ligne
ne sont pas décoratifs, ils **sont** la structure du programme :
```python
for x in range(32):
pixel(x, 0, ROUGE) # dans la boucle : exécuté 32 fois
montrer() # dans la boucle aussi
attendre(1000) # APRÈS la boucle : exécuté une fois
```
Utilisez toujours **4 espaces** (Thonny et VS Code le font tout seuls avec
la touche Tab). Ne mélangez jamais espaces et tabulations.
**Le message d'erreur est votre ami.** Python indique le fichier, la ligne
et la nature de l'erreur, tout en bas :
```
File "mes_animations.py", line 72
attendre(20
^
SyntaxError: '(' was never closed
```
---
## 3. Les outils de dessin
Définis dans [`matrice.py`](matrice.py), disponibles dans `mes_animations.py`
grâce à la ligne `from matrice import *`.
| Outil | Effet |
|---|---|
| `pixel(x, y, couleur)` | colore le pixel de la colonne `x` (0 à 31) et de la ligne `y` (0 à 7). En dehors : ignoré |
| `lire_pixel(x, y)` | renvoie la couleur actuelle d'un pixel |
| `effacer()` | éteint toute la toile |
| `effacer(couleur)` | remplit toute la toile d'une couleur |
| `assombrir(25)` | assombrit toute la toile de 25 % (pour les traînées) |
| `montrer()` | **affiche** la toile. Rien n'apparaît tant qu'on ne l'appelle pas ! |
| `montrer(image)` | affiche une image Pillow de 32 × 8 (voir partie 5) |
| `attendre(100)` | attend 100 millisecondes |
| `teinte(t)` | couleur de l'arc-en-ciel : 0 rouge, 32 orange, 64 jaune, 96 vert, 128 cyan, 160 bleu, 192 violet, 224 rose |
| `teinte(t, saturation, valeur)` | idem, avec saturation (0 = blanc) et valeur (0 = noir), de 0 à 255 |
**Couleurs nommées** : `NOIR`, `BLANC`, `ROUGE`, `ORANGE`, `JAUNE`, `VERT`,
`CYAN`, `BLEU`, `VIOLET`, `MAGENTA`, `ROSE`.
**Dimensions** : `LARGEUR` (32), `HAUTEUR` (8).
Le point `(0, 0)` est **en haut à gauche**, comme dans Krita.
---
## 4. Exercices
Pour chaque exercice, écrivez une nouvelle fonction `def anim_…():` dans
`mes_animations.py` et ajoutez son nom dans `playlist()`. Testez dans le
simulateur.
**1. Le point qui traverse.** Un pixel blanc va de gauche à droite sur la
ligne 3, puis revient. *(Indice : deux boucles `for`, la seconde avec
`range(31, -1, -1)`.)*
**2. Le balayage.** Une colonne entière (8 pixels) balaie la matrice de
gauche à droite. *(Indice : une boucle sur `x`, et dedans une boucle sur `y`.)*
**3. Le dégradé fixe.** Remplissez la matrice d'un arc-en-ciel immobile, de
`teinte(0)` à gauche à `teinte(255)` à droite. Puis faites-le défiler.
*(Comparez avec `anim_arc_en_ciel`.)*
**4. La balle qui rebondit.** Un pixel avance d'un pas en `x` et en `y` à
chaque image, et change de sens quand il touche un bord.
```python
def anim_balle():
x, y = 0, 0 # position
dx, dy = 1, 1 # vitesse (pas par image)
for image in range(300):
effacer()
pixel(x, y, ORANGE)
montrer()
attendre(40)
x = x + dx
y = y + dy
if x <= 0 or x >= LARGEUR - 1:
dx = -dx # rebond sur un bord gauche/droite
if y <= 0 or y >= HAUTEUR - 1:
dy = -dy # rebond en haut/en bas
```
Variante : laissez une traînée en remplaçant `effacer()` par `assombrir(30)`.
**5. Le ciel étoilé.** Des pixels blancs apparaissent au hasard, très
faiblement, puis s'allument et s'éteignent doucement. *(Indice : `assombrir`
et `random.randrange`.)*
**6. Le feu.** Le bas de la matrice est orange vif, des « flammes » montent
au hasard en s'assombrissant et en tirant vers le rouge. *(Indice : partez
de `anim_pluie`, et faites monter au lieu de descendre.)*
**7. Le dessin en lettres.** Modifiez `DESSIN` dans `mes_animations.py` pour
faire défiler votre propre motif. Créez-en un deuxième, et faites-les défiler
l'un derrière l'autre.
---
## 5. Mélanger code et images
Le code peut **lire les images de l'équipe Krita** et les transformer. On
utilise Pillow, la bibliothèque d'images :
```python
from PIL import Image
def anim_logo_qui_defile():
# Remplacez par le chemin d'une image de 32 × 8 exportée depuis Krita.
logo = Image.open("animations/logo.png").convert("RGB")
for i in range(100):
effacer()
# On « colle » le logo deux fois, côte à côte, décalé de i pixels :
# ce qui sort à droite rentre à gauche (défilement en boucle).
toile.paste(logo, (i % LARGEUR - LARGEUR, 0))
toile.paste(logo, (i % LARGEUR, 0))
montrer()
attendre(60)
```
Ici `toile` est l'image de 32 × 8 sur laquelle dessinent `pixel()` et
`effacer()`. Tout ce que sait faire Pillow (coller, retourner, changer les
couleurs, écrire du texte…) fonctionne dessus. Documentation :
<https://pillow.readthedocs.io>.
---
## 6. Transformer son code en GIF
Une animation codée peut devenir un **fichier GIF**, que le lecteur jouera
en vitrine avec les dessins de l'équipe Krita :
```bash
python3 mes_animations.py --enregistrer animations/10_mes_animations.gif
```
Au lieu d'afficher, le moteur **enregistre** chaque image montrée par
`montrer()`, avec la durée de l'`attendre()` qui suit. La playlist est jouée
**une seule fois**, puis le GIF est écrit. Vérifiez-le ensuite :
```bash
python3 outils/verifier_animation.py animations/10_mes_animations.gif
```
> **Attention au hasard** : un GIF enregistre **une** version de
> l'animation. Si votre animation utilise `random`, elle sera identique à
> chaque passage dans le GIF, alors qu'en direct elle change à chaque fois.
---
## 7. Comment est construit le moteur
Pour les curieux, [`matrice.py`](matrice.py) est découpé comme le programme
Arduino, et commenté partie par partie :
1. **Réglages** : taille, broche GPIO, luminosité, limite de courant,
orientation, gamma.
2. **Couleurs** : les noms, et `teinte()` (l'équivalent de `CHSV`).
3. **`XY()`** : la même fonction que sur l'Arduino, qui transforme une
position (x, y) en numéro de LED dans le serpentin.
4. **Gamma et courant** : `preparer_valeurs()` corrige les couleurs avec une
table calculée au démarrage, applique la luminosité, estime le courant
et assombrit l'image si elle consomme trop (comme
`setMaxPowerInVoltsAndMilliamps` de FastLED).
5. **Les écrans** : trois « classes » qui savent toutes `afficher()`,
`attendre()` et `eteindre()` :
- `MatriceReelle` : envoie les couleurs aux LED avec `rpi_ws281x` ;
- `Simulateur` : dessine 256 ronds dans une fenêtre `tkinter` ;
- `Enregistreur` : accumule les images dans un GIF.
Le reste du programme ne sait pas lequel il utilise : c'est le principe
d'une **interface commune**. Ajouter un 4e écran (une page web, une
deuxième matrice…) ne demanderait pas de toucher aux animations.
6. **Outils de dessin** : `pixel()`, `effacer()`, `montrer()`…, qui
travaillent sur la `toile`.
Et [`lecteur.py`](lecteur.py) n'est qu'une boucle : lister le dossier,
charger chaque fichier en liste de couples (image, durée), et les montrer
l'un après l'autre.
### Idées pour aller plus loin
- **Un bouton** branché sur une broche GPIO pour passer à l'animation
suivante (bibliothèque `gpiozero`, déjà installée sur Raspberry Pi OS).
- **Un capteur de présence** (PIR) : la matrice s'anime quand quelqu'un
passe devant la vitrine.
- **L'heure ou la météo** en texte défilant (la police 5 × 7 est dans
[`outils/generer_exemples.py`](outils/generer_exemples.py)).
- **Une page web** sur le Pi pour choisir l'animation depuis son téléphone
(bibliothèque `flask`).