Éditeur · Génération d’objets · Simulateur — Matrice 30×20 · 600 LEDs WS2812B · micro:bit
Cette application sert à dessiner sur un tableau de 30 × 20 LEDs, puis à obtenir du code Python utilisable sur micro:bit. On peut l’utiliser de deux façons : soit en mode très simple, en dessinant une image et en copiant un programme prêt à l’emploi, soit en mode projet, avec des images fixes, des sprites mobiles et une simulation.
C’est l’entrée la plus facile. On clique sur les cases, on choisit les couleurs, puis on génère un code Python complet. Ce code peut être copié dans l’éditeur micro:bit ou téléchargé en fichier .py.
Les autres onglets servent à construire un vrai programme : images fixes, objets mobiles, code de base et simulation. On fabrique des morceaux de code que l’on assemble ensuite.
montrer() est ajouté automatiquement pour afficher les LEDs.Pixel : une LED du tableau. Image fixe : dessin qui ne bouge pas. Sprite : dessin que l’on place avec une position et que l’on peut déplacer. Code de base : fonctions communes nécessaires pour que les listes fonctionnent.
Commencer par l’onglet Éditeur prêt à l’emploi. Quand le principe est compris, passer aux images fixes et aux sprites. La simulation permet ensuite de vérifier le résultat avant d’envoyer le programme sur la vraie micro:bit.
| Coord. | LED | Col. | R | G | B | |
|---|---|---|---|---|---|---|
| Cliquez sur un pixel pour l'allumer | ||||||
(x, y, r, g, b).Dessinez ou importez une image, puis cliquez sur “Générer la liste image”. Le code apparaîtra ici.
(x, y, r, g, b).
afficher_image(ACCUEIL)IMAGE = [(x, y, r, g, b), ...]. Elle sera redessinée dans la grille.(dx, dy, r, g, b) autour d’un point de référence.Dessinez un sprite, choisissez le point de référence, puis cliquez sur “Générer la liste sprite”. Le code apparaîtra ici.
sprite = Sprite(MON_OBJET, 10, 5), ce point de référence sera placé exactement en (10,5).
Tous les autres pixels seront automatiquement calculés en décalages (dx, dy) autour de cette poignée.
vaisseau = Sprite(VAISSEAU, 15, 10), alors le cockpit sera placé en (15,10).
Pour créer plusieurs objets à la suite : générez la première liste, copiez ou téléchargez le fichier, cliquez sur Effacer l’objet, changez le nom de la liste, puis dessinez le deuxième objet.
SPRITE = [(dx, dy, r, g, b), ...]. Le sprite est reconstruit autour de la référence x/y ci-dessus.Sprite.afficher_image() et la classe Sprite.
Les élèves peuvent le copier au début de leur fichier Python, puis ajouter les listes générées dans les onglets Générer une image et Générer un sprite.
# ============================================================
# PixelArt - FabLab Robot24.fr
# MATRICE PIXEL ART - 600 LEDs NeoPixel sur micro:bit
# ============================================================
#
# Le tableau est un repère orthonormé :
#
# x → de 1 (gauche) à 30 (droite)
# y ↑ de 1 (bas) à 20 (haut)
#
# (1,20)─────────────────────(30,20)
# │ │
# │ TABLEAU │
# │ │
# (1,1) ─────────────────────(30,1)
#
# Exemple : allumer la LED en bas à gauche
# pixel(1, 1, 255, 0, 0) → rouge
#
# Exemple : allumer la LED au centre
# pixel(15, 10, 0, 255, 0) → vert
#
# ============================================================
from microbit import *
import neopixel
import utime
# --- Initialisation de la bande ---
NB_LEDS = 600
np = neopixel.NeoPixel(pin0, NB_LEDS)
# ============================================================
# FONCTION DE CONVERSION (x, y) → numéro de LED
# ============================================================
def xy_vers_led(x, y):
"""
Convertit des coordonnées (x, y) en numéro de LED.
x : entier de 1 (gauche) à 30 (droite)
y : entier de 1 (bas) à 20 (haut)
Retourne le numéro de LED (0 à 599).
"""
# Panneau gauche : colonnes x = 1 à 15
if 1 <= x <= 15:
if y % 2 == 1: # rangées impaires : gauche → droite
return (y - 1) * 15 + (x - 1)
else: # rangées paires : droite → gauche
return (y - 1) * 15 + (15 - x)
# Panneau droit : colonnes x = 16 à 30
else:
xl = 30 - x # distance depuis le bord droit (0 à 14)
if y % 2 == 1: # rangées impaires : droite → gauche
return 300 + (y - 1) * 15 + xl
else: # rangées paires : gauche → droite
return 300 + (y - 1) * 15 + (14 - xl)
# ============================================================
# FONCTIONS UTILITAIRES POUR DESSINER
# ============================================================
def pixel(x, y, r, g, b):
"""
Allume la LED à la position (x, y) avec la couleur (r, g, b).
N'oublie pas d'appeler montrer() pour afficher réellement !
"""
if 1 <= x <= 30 and 1 <= y <= 20:
led = xy_vers_led(x, y)
np[led] = (r, g, b)
def montrer():
"""Envoie les couleurs vers la bande de LEDs."""
np.show()
def effacer():
"""Éteint toutes les LEDs."""
np.fill((0, 0, 0))
np.show()
def tout_allumer(r, g, b):
"""Allume toutes les LEDs avec une couleur."""
np.fill((r, g, b))
np.show()
def ligne(y, r, g, b):
"""Allume toute la rangée y."""
for x in range(1, 31):
pixel(x, y, r, g, b)
montrer()
def colonne(x, r, g, b):
"""Allume toute la colonne x."""
for y in range(1, 21):
pixel(x, y, r, g, b)
montrer()
def rectangle(x1, y1, x2, y2, r, g, b):
"""
Allume un rectangle plein.
(x1,y1) = coin bas-gauche / (x2,y2) = coin haut-droite
"""
for x in range(x1, x2 + 1):
for y in range(y1, y2 + 1):
pixel(x, y, r, g, b)
montrer()
def afficher_image(image):
"""
Affiche une image fixe générée par l'éditeur.
Format d'une image : (x, y, r, g, b)
Une image utilise les coordonnées absolues du tableau.
"""
for x, y, r, g, b in image:
pixel(x, y, r, g, b)
# ============================================================
# CLASSE SPRITE : OBJETS MOBILES
# ============================================================
class Sprite:
def __init__(self, dessin, x, y):
self.dessin = dessin
self.x = x
self.y = y
def afficher(self):
for dx, dy, r, g, b in self.dessin:
pixel(self.x + dx, self.y + dy, r, g, b)
def effacer_sprite(self):
"""Éteint les LEDs occupées par le sprite."""
for dx, dy, r, g, b in self.dessin:
pixel(self.x + dx, self.y + dy, 0, 0, 0)
def deplacer(self, dx, dy):
self.effacer_sprite() # 1. éteindre l'ancienne position
self.x += dx # 2. mettre à jour les coordonnées
self.y += dy
self.afficher() # 3. allumer la nouvelle position
# ============================================================
# COULEURS PRÉDÉFINIES (r, g, b)
# ============================================================
ROUGE = (255, 0, 0)
VERT = (0, 255, 0)
BLEU = (0, 0, 255)
BLANC = (255, 255, 255)
JAUNE = (255, 255, 0)
CYAN = (0, 255, 255)
MAGENTA = (255, 0, 255)
ORANGE = (255, 128, 0)
ETEINT = (0, 0, 0)
# ============================================================
# COLLE ICI LES LISTES GÉNÉRÉES PAR L'ÉDITEUR
# ============================================================
# Exemple d'image fixe :
# ACCUEIL = [
# (1, 1, 255, 0, 0),
# ]
# Exemple de sprite :
# VAISSEAU = [
# (0, 0, 255, 0, 0),
# ]
# ============================================================
# PROGRAMME DES ÉLÈVES ↓ Écrivez votre code ici !
# ============================================================
# Exemple image fixe :
# effacer()
# afficher_image(ACCUEIL)
# montrer()
# Exemple sprite :
# vaisseau = Sprite(VAISSEAU, 10, 5)
# effacer()
# vaisseau.afficher()
# montrer()
# ============================================================
# PROGRAMME D'EXEMPLE - PixelArt Robot24.fr
# Décor + invader + vaisseau spatial
# ============================================================
from microbit import *
import neopixel
import utime
NB_LEDS = 600
np = neopixel.NeoPixel(pin0, NB_LEDS)
def xy_vers_led(x, y):
if 1 <= x <= 15:
if y % 2 == 1:
return (y - 1) * 15 + (x - 1)
else:
return (y - 1) * 15 + (15 - x)
else:
xl = 30 - x
if y % 2 == 1:
return 300 + (y - 1) * 15 + xl
else:
return 300 + (y - 1) * 15 + (14 - xl)
def pixel(x, y, r, g, b):
if 1 <= x <= 30 and 1 <= y <= 20:
np[xy_vers_led(x, y)] = (r, g, b)
def montrer():
np.show()
def effacer():
np.fill((0, 0, 0))
np.show()
def rectangle(x1, y1, x2, y2, r, g, b):
for x in range(x1, x2 + 1):
for y in range(y1, y2 + 1):
pixel(x, y, r, g, b)
class Sprite:
def __init__(self, dessin, x, y):
self.dessin = dessin
self.x = x
self.y = y
def afficher(self):
for dx, dy, r, g, b in self.dessin:
pixel(self.x + dx, self.y + dy, r, g, b)
def effacer_sprite(self):
for dx, dy, r, g, b in self.dessin:
pixel(self.x + dx, self.y + dy, 0, 0, 0)
def deplacer(self, dx, dy):
self.effacer_sprite()
self.x += dx
self.y += dy
self.afficher()
# ============================================================
# SPRITES
# ============================================================
SPACESHIP = [
(0, -2, 0, 0, 255),
(-3, -1, 0, 0, 255), (-2, -1, 0, 0, 255), (-1, -1, 0, 0, 255),
(0, -1, 255, 120, 0), (1, -1, 255, 60, 0),
(-4, 0, 255, 255, 255), (-3, 0, 0, 0, 255),
(-2, 0, 0, 255, 180), (-1, 0, 0, 255, 180),
(0, 0, 255, 120, 0), (1, 0, 255, 60, 0), (2, 0, 255, 0, 0),
(-3, 1, 0, 0, 255), (-2, 1, 0, 0, 255), (-1, 1, 0, 0, 255),
(0, 1, 255, 120, 0), (1, 1, 255, 60, 0),
(0, 2, 0, 0, 255)
]
INVADER = [
(-1, -2, 255, 0, 80), (2, -2, 255, 0, 80),
(-3, -1, 255, 0, 80), (-1, -1, 255, 0, 80), (0, -1, 255, 0, 80),
(1, -1, 255, 0, 80), (2, -1, 255, 0, 80), (4, -1, 255, 0, 80),
(-3, 0, 255, 0, 80), (-2, 0, 255, 0, 80), (-1, 0, 255, 0, 80),
(0, 0, 255, 0, 80), (1, 0, 255, 0, 80), (2, 0, 255, 0, 80),
(3, 0, 255, 0, 80), (4, 0, 255, 0, 80),
(-2, 1, 255, 0, 80), (-1, 1, 255, 255, 255), (0, 1, 255, 0, 80),
(1, 1, 255, 0, 80), (2, 1, 255, 255, 255), (3, 1, 255, 0, 80),
(-1, 2, 255, 0, 80), (0, 2, 255, 0, 80), (1, 2, 255, 0, 80), (2, 2, 255, 0, 80),
(-1, 3, 255, 0, 80), (2, 3, 255, 0, 80),
(-2, 4, 255, 0, 80), (3, 4, 255, 0, 80)
]
# ============================================================
# DÉCOR : ciel, herbe, arbres et étoiles
# ============================================================
def decor_campagne():
np.fill((0, 0, 18)) # ciel de nuit
rectangle(1, 1, 30, 3, 0, 120, 30) # herbe
rectangle(1, 4, 30, 4, 0, 80, 25) # horizon
# étoiles
pixel(4, 18, 255, 255, 120)
pixel(12, 17, 255, 255, 120)
pixel(19, 19, 255, 255, 120)
pixel(27, 16, 255, 255, 120)
# arbre de gauche : tronc + feuillage
rectangle(4, 4, 5, 8, 150, 70, 20)
pixel(3, 8, 20, 180, 60)
pixel(4, 9, 20, 220, 80)
pixel(5, 9, 20, 220, 80)
pixel(6, 8, 20, 180, 60)
pixel(4, 10, 60, 255, 100)
pixel(5, 10, 60, 255, 100)
# arbre de droite : couleurs d'automne
rectangle(23, 4, 24, 7, 140, 60, 20)
pixel(22, 8, 255, 120, 0)
pixel(23, 9, 255, 190, 0)
pixel(24, 9, 255, 190, 0)
pixel(25, 8, 255, 120, 0)
pixel(23, 10, 255, 220, 60)
pixel(24, 10, 255, 220, 60)
# ============================================================
# PROGRAMME PRINCIPAL
# ============================================================
effacer()
# Écran d'introduction rouge
np.fill((120, 0, 0))
montrer()
utime.sleep(0.8)
effacer()
# Affichage du décor
decor_campagne()
montrer()
utime.sleep(0.8)
# Création des deux objets mobiles
alien = Sprite(INVADER, 6, 14)
vaisseau = Sprite(SPACESHIP, 26, 17)
# Première apparition
alien.afficher()
vaisseau.afficher()
montrer()
utime.sleep(0.8)
# Animation : l'alien va à droite, le vaisseau descend en diagonale vers la gauche
for i in range(1, 10):
alien.deplacer(1, 0)
vaisseau.deplacer(-1, -1)
montrer()
utime.sleep(0.35)
# Fin : petit flash blanc
np.fill((80, 80, 80))
montrer()
utime.sleep(0.2)
decor_campagne()
alien.afficher()
vaisseau.afficher()
montrer()
utime.sleep() sont respectés et divisés par ce facteur.np[i] = (r,g,b) · np.show() · np.fill((r,g,b))pixel(x,y,r,g,b) · utime.sleep(s) · utime.sleep_ms(ms)xy_vers_led(x,y) · while True · for … in range()if/else · variables · fonctions def · classes simples classwhile True s'arrête avec ⏹ ou après 2000 frames.