Skip to article frontmatterSkip to article content

Licence CC BY-NC-ND, Thierry Parmentelat

c’est quoi les boids ?

une simulation ludique où on tente de reproduire le comportement d’animaux en groupes - typiquement oiseaux et poissons

intérêts

c’est intéressant parce que

introduction

dans ce TP nous allons

notre sujet

dans sa version originale chaque animal décide de sa trajectoire, en fonction uniquement de ses voisins proches, et cela en suivant trois règles:

pour la partie imposée de ce TP, on va se contenter d’implémenter la règle de séparation
c’est-à-dire ce qui permet aux boids d’éviter de heurter les autres boids, et les obstacles

les élèves rapides et/ou motivés pourront poursuivre jusqu’à réaliser une simulation complète s’ils le souhaitent

en vidéo

voici d’abord une vidéo très courte pour vous montrer les différentes étapes du TP

https://www.youtube.com/watch?v=d4789cBD3Ek

l’enjeu principal ici est d’être exposé à ce style de programmation par spécialisation de classes
aussi ce chemin est uniquement indicatif, et surtout à destination des élèves qui en ressentiront le besoin
si vous vous sentez, vous pouvez très bien vous y prendre complètement autrement,
le contrat est rempli dès que vous avez: des obstacles fixes, et des boids qui évoluent spontanément en évitant les autres objets

contenu

le zip contient

pas à pas

v01: starter code

"""
display a single object, inert, at (100, 100)
"""

import arcade

BACKGROUND = arcade.color.ALMOND
IMAGE = "media/arrow-resized.png"

class Window(arcade.Window):

    def __init__(self):
        super().__init__(800, 800, "My first boid")
        arcade.set_background_color(BACKGROUND)
        self.boid = None

    def setup(self):
        boid = arcade.Sprite(IMAGE)
        boid.center_x = 100
        boid.center_y = 100
        self.boid = boid

    def on_draw(self):
        arcade.start_render()
        self.boid.draw()

    def on_update(self, delta_time):
        self.boid.update()

window = Window()
window.setup()
arcade.run()

vous devez voir un seul boid immobile, dans le coin en bas à gauche

installez la librairie, copiez le code ci-dessus dans par exemple boid.py, et lancez-le
vous devez voir un seul boid dans le coin en bas à gauche, il est immobile

commentaire

observez la différence de style de programmation par rapport à pygame
comment aurait-on écrit la même chose en pygame ?

l’implicite

dans ce code, on utilise - et ce n’est pas du tout explicite - le fait que

pour les forts: dans le même registre, mais plus subtil:

v02: de la place pour plusieurs boids

on veut garder exactement le même comportement (un seul boid fixe pour l’instant)
mais on va modifier le code pour pouvoir (plus tard) en créer plusieurs

pour cela, on pourrait penser à utiliser une liste standard Python,
mais je vous invite à utiliser plutôt la classe SpriteList que fournit arcade

debugging

en plus de ça, je vous recommande de:

v03: le boid avance

maintenant on va faire bouger notre objet, et lui donner un mouvement rectiligne

et pour ça on va cesser d’utiliser directement la classe Sprite, et on va au contraire la spécialiser pour créer notre propre classe Boid
(c-à-d que la classe Boid hérite de la classe Sprite)

à savoir

et aussi, mais moins crucial à ce stade:

v04: en circuit fermé

on va faire en sorte que le plateau devienne infini en le refermant sur lui-même
un objet sortant à gauche réapparait à droite, et idem dans tous les sens
ça peut valoir le coup de “sortir” la taille du jeu pour en faire des constantes

et pour que ce soit plus facile à tester on va orienter le boid vers le coin en bas à gauche
si vous vous y êtes bien pris pour le faire avancer, c’est juste une question de changer son .angle

v05: du bruit sur le cap

faites en sorte que le trajet du boid ne soit plus strictement rectiligne
en ajoutant à chaque pas un léger bruit sur la direction

v06: les touches et

faites en sorte de pouvoir contrôler la direction du boid avec les touches du clavier

à savoir

def on_key_press(self, key, modifiers):
    pass
def on_key_release(self, key, modifiers):
    pass

attention

ceci est beaucoup plus facile à utiliser si le boid continue de tourner pendant tout le temps où la touche est enfoncée - plutôt que de devoir appuyer plein de fois sur la touche

v07: ajouter un obstacle

ajoutez un unique obstacle, immobile, par exemple au centre du jeu
vous trouverez une image media/obstacle-resized.png pour le matérialiser

2 options

v08: créez une grille d’obstacles

remplacez l’unique obstacle par une grille d’obstacles
mettez en 10 x 10, ils sont donc espacés de 80px

v09: détecter les voisins

faites en sorte d’animer le boid, pour montrer quand il est proche d’un obstacle ou pas
prenez 20 pixels comme rayon de détection
pour ma part j’ai rendu le boid semi-transparent, en jouant sur l’attribut alpha des Sprite
(255 = opaque, 0 = transparent)

discussion

ici on a le choix d’utiliser

quels sont les avantages et les inconvénients des 2 approches ?

je vous recommande la deuxième option

v10: la règle de séparation

implémentez la règle de séparation
on peut la résumer comme ceci:

c’est-à-dire que quand on s’intéresse au boid b, on va

on fait la somme de tous ces vecteurs, et on l’ajoute au déplacement de b

i.e. dans l’exemple de la figure, lorsqu’on traite le boid en b:

à noter

dans cette version, en cas de collision, on se contente de modifier la position du boid, et pas son orientation; on arrangera ca plus tard

v11: on essaie d’orienter correctement

dans cette version, on va essayer de répercuter les collisions sur l’orientation du boid
et pour ça on va mettre à jour brutalement l’attribut angle uniquement sur le mouvement qui est fait à l’instant t
i.e, pour être clair, que si on passe de (x1, y1) à (x2, y2), on oriente le boid pour s’aligner sur le vecteur (x2-x1, y2-y1)
l’effet n’est pas forcément très réussi, vous devez voir l’orientation sauter brutalement d’un angle un autre

à savoir
voyez la fonction math.atan2 qui est pratique ici

v12: on lisse les changements d’orientation

comment pourrait-on obtenir quelque chose d’un peu plus élégant, en ce qui concerne les changements de direction ?

v13: les touches et

faire en sorte qu’on puisse contrôler aussi la vitesse avec les touches
essayez le comportement de l’évitement d’obstacles à plusieurs vitesses

v14: plusieurs boids

remplacez l’unique boid par un ensemble de 20 boids
sans changer la séparation, qui est calculée seulement à partir des obstacles

v15: éviter les obstacles et les autres boids

assurez-vous que la séparation permet d’éviter tous les objets (obstacles et boids)

en option...

vous pouvez ensuite améliorer dans les directions suivantes :

pour aller plus loin