PixelArt - Fablab Robot24.fr

Éditeur · Génération d’objets · Simulateur — Matrice 30×20 · 600 LEDs WS2812B · micro:bit

600 LEDs
Dessin simple
Outils pour coder

Créer du Pixel Art pour la matrice micro:bit, sans se perdre dans le code

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.

1. Mode simple : l’onglet Éditeur

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.

  • Idéal pour une première séance.
  • Pas besoin de comprendre les listes ou les classes.
  • Le dessin est directement converti en programme.

2. Mode projet : les outils de code

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.

  • Image fixe : décor, logo, écran d’accueil.
  • Sprite : personnage, vaisseau, ennemi qui peut bouger.
  • Simulation : test du programme avant la vraie matrice.
DessinerChoisir une couleur puis cliquer sur la matrice. Les coordonnées vont de x=1 à 30 et y=1 à 20.
GénérerCliquer sur le bouton de génération pour obtenir le code correspondant au dessin, à l’image ou au sprite.
Copier / importerCopier le code généré, ou réimporter une liste déjà créée pour corriger quelques pixels.
TesterColler le programme dans la simulation. Dans le mode simple, montrer() est ajouté automatiquement pour afficher les LEDs.

Petit vocabulaire

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.

Conseil pour les élèves

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.

Éditeur prêt à l’emploi : dessinez directement sur la matrice, puis cliquez sur { } Code Python complet. L’outil génère un programme complet à copier ou à télécharger. C’est l’onglet conseillé pour débuter.
Pixels allumés
0
Couleurs
0
LEDs dispo
600
Pixels allumés
Coord.LED Col.R GB
Cliquez sur un pixel pour l'allumer
🐍 Code Python — micro:bit

    
💾 Sauvegarder / Charger un tableau
Aucune sauvegarde
Image fixe : utilisez cet onglet pour créer ou importer un décor, un logo ou un écran d’accueil. Le code généré est une liste au format (x, y, r, g, b).
Pixels de l’image
0
Format
x,y,r,g,b
Liste
IMAGE
🐍 Code liste image fixe
Dessinez ou importez une image, puis cliquez sur “Générer la liste image”. Le code apparaîtra ici.
🖼 Générer une image fixe
Une image fixe est un décor ou un écran complet : logo, fond, paysage, écran d’accueil. Elle utilise les coordonnées absolues du tableau. Chaque pixel est enregistré sous la forme (x, y, r, g, b).
Dans le programme Python, l’élève colle la liste puis utilise une fonction simple :
afficher_image(ACCUEIL)
Une image fixe ne se déplace pas. Pour un objet mobile, utilisez l’onglet Générer un sprite.
📥 Importer une liste image à modifier
Collez une liste au format IMAGE = [(x, y, r, g, b), ...]. Elle sera redessinée dans la grille.
Couleur de l’image
#FF0000
255
0
0
Palettes
Outils image
Images créées / importées
Aucune image générée ou importée pour le moment.
Chaque image apparaît ici dans un cadre. Le bouton “Recharger” la remet dans la grille pour modifier quelques pixels puis regénérer la liste.
Sprite mobile : utilisez cet onglet pour créer ou importer un objet qui pourra se déplacer : vaisseau, personnage, ennemi. Le code généré est une liste au format (dx, dy, r, g, b) autour d’un point de référence.
Pixels du sprite
0
Référence
Liste
OBJET
🐍 Code liste sprite
Dessinez un sprite, choisissez le point de référence, puis cliquez sur “Générer la liste sprite”. Le code apparaîtra ici.
🧩 Générer une liste sprite pour la classe
Dessinez l’objet dans la matrice avec les mêmes outils que dans l’éditeur. Ensuite, choisissez le point de référence : c’est le pixel qui servira de poignée pour déplacer l’objet. Dans le programme, si un élève écrit 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.
Méthode conseillée : choisissez un point facile à retrouver, souvent au centre visuel de l’objet. Pour un vaisseau, cela peut être le cockpit, le milieu du corps ou le nez selon la façon dont vous voulez le déplacer. Cliquez sur Choisir la référence au clic, puis cliquez directement sur le pixel qui doit devenir le centre de commande de l’objet. Exemple : si la référence est le cockpit et que le code dit 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.
📥 Importer une liste sprite à modifier
Collez une liste au format SPRITE = [(dx, dy, r, g, b), ...]. Le sprite est reconstruit autour de la référence x/y ci-dessus.
Couleur du sprite
#FF0000
255
0
0
Palettes
Outils sprite
Sprites créés / importés
Aucun sprite généré pour le moment.
Chaque sprite apparaît ici dans un cadre. “Recharger” le remet dans la grille pour modifier quelques pixels puis regénérer la liste.
Code de base : c’est le socle commun à coller au début d’un programme avancé. Il contient les fonctions de dessin, l’affichage des images fixes et la classe Sprite.
📄 Code de base commun à tous les projets
Ce code contient le repère du tableau, les fonctions de dessin, 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.
🐍 Code Python de base
# ============================================================
#  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 : ce programme montre comment assembler un décor, deux sprites et une animation. Il peut être copié dans l’onglet Simulation pour être testé directement.
🚀 Exemple complet : décor + invader + vaisseau
Cet exemple reprend l’idée du programme fourni : un décor de campagne, un invader et un vaisseau spatial. Le décor a été simplifié et rendu plus lisible, les arbres ont été recolorés, l’alien avance vers la droite et le vaisseau se déplace en diagonale vers la gauche et vers le bas.
🐍 Programme Python d’exemple
# ============================================================
#  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()
Simulation : collez ici un programme Python pour le tester avant de l’envoyer sur la vraie micro:bit. En cas d’erreur, la console indique la ligne concernée.
Matrice NeoPixel 30×20
⏱ Vitesse de simulation
×1.0
Les utime.sleep() sont respectés et divisés par ce facteur.
Instructions reconnues 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 class
La boucle while True s'arrête avec ⏹ ou après 2000 frames.
🐍 Éditeur Python
📦 Télécharger ou envoyer sur la micro:bit Pour les débutants : le bouton Télécharger .hex fabrique un fichier directement flashable. Il suffit ensuite de le glisser sur le lecteur MICROBIT. Le bouton Envoyer micro:bit reste désactivé tant qu’aucune carte n’a été détectée. Cela évite les clics accidentels qui peuvent bloquer le navigateur.
Prêt : téléchargez le .hex, ou cliquez sur “Détecter micro:bit” avant un envoi direct.
Console
Prêt. Écrivez votre code Python puis appuyez sur ▶ Lancer.