Skip to content

Commit 12e8c3c

Browse files
committed
superficial review on the boids TP
1 parent 3570399 commit 12e8c3c

File tree

3 files changed

+184
-187
lines changed

3 files changed

+184
-187
lines changed

notebooks/tps/boids/.teacher/README-boids-corrige-nb.md

Lines changed: 93 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ Licence CC BY-NC-ND, Thierry Parmentelat
2828
````{admonition} nothing to prune
2929
:class: warning
3030
31-
there are no difference - apart from this very cell - between the teacher and the student version, but the notebook is duplicated in .teacher for consistency
31+
there are no difference - apart from this very cell - between the teacher and the student version,
32+
but the notebook is duplicated in `.teacher` for consistency
3233
````
3334

3435
+++
@@ -42,7 +43,8 @@ there are no difference - apart from this very cell - between the teacher and th
4243
## c'est quoi les *boids* ?
4344

4445
une simulation ludique où on tente de reproduire le comportement d'animaux en
45-
groupes - typiquement oiseaux et poissons
46+
groupes
47+
typiquement nuée d'oiseaux ou banc de poissons
4648

4749
### intérêts
4850

@@ -87,12 +89,20 @@ les élèves rapides et/ou motivés pourront poursuivre jusqu'à réaliser une s
8789

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

90-
<https://www.youtube.com/watch?v=d4789cBD3Ek>
92+
::::{figure}
93+
:align: center
94+
```{iframe} https://www.youtube.com/embed/d4789cBD3Ek?rel=0&amp;controls=1
95+
```
96+
penser à la lire en plein écran
97+
::::
9198

92-
l'enjeu principal ici est d'être exposé à ce style de **programmation par spécialisation de classes**
93-
aussi ce chemin est uniquement **indicatif**, et surtout à destination des élèves qui en ressentiront le besoin
94-
si vous vous sentez, vous pouvez très bien vous y prendre complètement autrement,
95-
le contrat est rempli dès que vous avez: **des obstacles** fixes, et **des boids** qui évoluent **spontanément** en **évitant** les autres objets
99+
l'enjeu principal ici est d'être exposé à la **programmation par spécialisation de classes**
100+
aussi ce chemin par étapes est uniquement **indicatif**, et surtout à
101+
destination des élèves qui ressentent le besoin d'être guidés pas à pas
102+
si vous vous sentez, vous pouvez très bien vous y prendre complètement autrement !
103+
le contrat est rempli dès que vous avez: **des obstacles** fixes, et **des
104+
boids** qui évoluent **spontanément** en **évitant** les obstacles et les autres
105+
boids
96106

97107
+++
98108

@@ -111,44 +121,18 @@ le zip contient
111121

112122
### v01: starter code
113123

114-
```python
115-
"""
116-
display a single object, inert, at (100, 100)
117-
"""
118-
119-
import arcade
120-
121-
BACKGROUND = arcade.color.ALMOND
122-
IMAGE = "media/arrow-resized.png"
123-
124-
class Window(arcade.Window):
124+
* dans le zip vous trouverez le code suivant; n'hésitez pas à le renommer dans un fichier `boids.py`
125125

126-
def __init__(self):
127-
super().__init__(800, 800, "My first boid")
128-
arcade.set_background_color(BACKGROUND)
129-
self.boid = None
126+
::::{admonition} le code de départ
127+
:class: dropdown
130128

131-
def setup(self):
132-
boid = arcade.Sprite(IMAGE)
133-
boid.center_x = 100
134-
boid.center_y = 100
135-
self.boid = boid
129+
:::{literalinclude} boids-01.py
130+
:::
131+
::::
136132

137-
def on_draw(self):
138-
arcade.start_render()
139-
self.boid.draw()
140-
141-
def on_update(self, delta_time):
142-
self.boid.update()
143-
144-
window = Window()
145-
window.setup()
146-
arcade.run()
147-
```
148-
149-
* installez la librairie
133+
* installez la librairie (comment fait-on déjà ?)
150134
* vérifiez que vous avez le fichier `media/arrow-resized.png` (il est dans le zip)
151-
* copiez et lancez le code ci-dessus
135+
* lancez le code ci-dessus
152136

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

@@ -171,14 +155,16 @@ comment aurait-on écrit la même chose en `pygame` ?
171155
dans ce code, on utilise - et ce n'est pas du tout explicite - le fait que
172156

173157
* le module `arcade` vient avec une *mainloop* - `arcade.run()`
174-
qui se charge de faire 'avancer' le jeu - par défaut à plusieurs dizaines de Hz
158+
qui se charge de faire 'avancer' le jeu - par défaut à plusieurs dizaines de Hz
159+
(même si avec cette version 01 on ne voit pas grand chose bouger :)
175160

176161
* cette mainloop va appeler les méthodes `on_draw()` et `on_update()`
177162
sur chaque instance de `Window` - c'est là que nous pouvons programmer
178163
la logique de notre "*jeu*"
179164

180165
* la classe `Sprite` permet d'ajouter des objets qui savent s'afficher
181-
ici on a juste créé l'objet à partir d'un png, puis fixé `boid.center_x` et `boid.center_y`
166+
ici on a juste créé l'objet à partir d'une image `.png`, puis fixé
167+
`boid.center_x` et `boid.center_y`
182168

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

@@ -202,11 +188,12 @@ mais je vous invite à utiliser plutôt la classe `SpriteList` que fournit `arca
202188

203189
en plus de ça, je vous recommande de:
204190

205-
* prévoir le cas du debug, par exemple avec une variable globale DEBUG
191+
* prévoir le cas du debug, par exemple avec une variable globale `DEBUG`
206192
* et dans ce cas afficher un message à chaque fois que le boid est mis à jour
207193
(surtout pour mettre en évidence la *mainloop* à ce stade)
208194

209-
* et aussi de [regarder la méthode `set_update_rate()`](https://api.arcade.academy/en/latest/api/window.html?highlight=set_update_rate#arcade.Window.set_update_rate)
195+
* et aussi de [regarder la méthode
196+
`set_update_rate()`](https://api.arcade.academy/en/2.6.1/api/window.html#arcade.Window.set_update_rate)
210197
pour ralentir la cadence, ce qui sera sûrement utile à un moment donné pour débugger
211198

212199
* pourquoi ne pas aussi imprimer un message pour voir à quel rythme sont faits les `draw()` et `update()`
@@ -224,40 +211,41 @@ et on va au contraire la **spécialiser** pour créer notre propre classe `Boid`
224211
#### à savoir
225212

226213
* pour chaque cycle de la *mainloop*, l'objet `Window` utilise
227-
* sa méthode `on_update()` pour mettre à jour l'état des objets
228-
* et sa méthode `on_draw()` pour les redessiner
229-
c'est pour cela que celle-ci commence par `start_render()`
214+
* sa méthode `on_update()` pour mettre à jour l'état des objets (juste en mémoire)
215+
* et sa méthode `on_draw()` pour les redessiner
216+
c'est pour cela que celle-ci commence par `start_render()`
230217
qui efface tout, et remet simplement le fond d'écran
231-
232-
* on peut donc **faire avancer le boid** simplement en **redéfinissant quelques méthodes** dans le code
233-
* par défaut les deux méthodes (`draw()` et `update()`) se produisent à la même fréquence (60Hz),
234-
mais avec `set_update_rate()` on ralentit uniquement `update()`
235-
c'est pourquoi `on_update(time_delta)` reçoit le temps (en ms)
236-
qui s'est écoulé depuis le dernier appel
237-
238-
et aussi, mais moins crucial à ce stade:
239-
240-
* on n'en a pas besoin tout de suite, mais dans la classe `Sprite`
241-
il y a un attribut `angle` qui sert à dire de combien on veut tourner l'image
242-
243-
* et naturellement dans notre cas, on va vouloir que l'objet avance dans la direction de la flêche
244-
(même si ce stade on ne peut pas encore faire tourner le boid)
245-
218+
* bref, le résultat c'est qu'on peut **faire avancer le boid**
219+
simplement en **redéfinissant quelques méthodes** dans le code
220+
* par défaut les deux méthodes (`draw()` et `update()`) se produisent à la même fréquence (60Hz),
221+
et avec `set_update_rate()` on ralentit uniquement `update()`
222+
* `on_update(time_delta)` reçoit le temps (en ms) qui s'est écoulé depuis le
223+
dernier update(), c'est pratique pour faire des mouvements si on connaît la
224+
vitesse de déplacement de l'objet
225+
226+
#### et aussi
227+
228+
mais moins crucial à ce stade:
229+
230+
* on n'en a pas besoin tout de suite, mais dans la classe `Sprite`, il y a un
231+
attribut `angle` qui sert à dire de combien on veut tourner l'image lors de
232+
l'affichage
233+
* et naturellement dans notre cas, on va vouloir que l'objet avance dans la
234+
direction de la flêche (même si ce stade on ne peut pas encore faire tourner
235+
le boid)
246236
* aussi il serait habile de considérer que la vitesse du boid
247237
est un de ses attributs (et non pas une constante)
248238
même si là encore on n'en a pas besoin tout de suite
249-
250239
* pensez à exprimer les vitesses en pixels par seconde
251240

252241
+++
253242

254243
### v04: en circuit fermé
255244

256-
on va faire en sorte que le plateau devienne infini en le refermant sur lui-même
257-
un objet sortant à gauche réapparait à droite, et idem dans tous les sens
258-
ça peut valoir le coup de "sortir" la taille du jeu pour en faire des constantes
259-
260-
et pour que ce soit plus facile à tester on va orienter le boid vers le coin en bas à gauche
245+
* on va faire en sorte que le plateau devienne infini en le refermant sur lui-même
246+
i.e. un objet sortant à gauche réapparait à droite, et idem dans tous les sens&hellip;
247+
* ça peut valoir le coup de "sortir" la taille du jeu pour en faire des constantes
248+
* et pour que ce soit plus facile à tester on va orienter le boid vers le coin en bas à gauche
261249
si vous vous y êtes bien pris pour le faire avancer, c'est juste une question de changer son `.angle`
262250

263251
+++
@@ -287,7 +275,9 @@ def on_key_release(self, key, modifiers):
287275

288276
#### attention
289277

290-
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
278+
soyez sympa avec vos utilisateurs: ceci est beaucoup plus facile à utiliser si
279+
le boid continue de tourner pendant **tout le temps où la touche est enfoncée** - plutôt que
280+
de devoir appuyer plein de fois sur la touche&hellip;
291281

292282
+++
293283

@@ -299,14 +289,15 @@ vous trouverez une image `media/obstacle-resized.png` pour le matérialiser
299289
**2 options**
300290

301291
* on pourrait facilement s'en sortir avec juste la classe `Sprite`
302-
* mais je vous demande, pour vous exercer à la spécialisation de classes, de créer une classe `Obstacle`
292+
* mais je vous demande, pour vous exercer à la spécialisation de classes, de
293+
créer une classe `Obstacle`
303294

304295
+++
305296

306297
### v08: créez une grille d'obstacles
307298

308299
remplacez l'unique obstacle par une grille d'obstacles
309-
mettez en 10 x 10, ils sont donc espacés de 80px
300+
par exemple: mettez en 10 x 10, ils sont donc espacés de 80px
310301

311302
+++
312303

@@ -321,7 +312,7 @@ pour ma part j'ai rendu le boid semi-transparent, en jouant sur l'attribut `alph
321312

322313
#### discussion
323314

324-
ici on a le choix d'utiliser
315+
ici on a le choix d'utiliser
325316

326317
* soit une variable globale (la liste de tous les obstacles)
327318
* ou de rajouter dans la classe `Boid` une liste d'obstacles
@@ -366,7 +357,7 @@ on fait la somme de tous ces vecteurs, et on l'ajoute au déplacement de b
366357
i.e. dans l'exemple de la figure, lorsqu'on traite le boid en b:
367358

368359
* on ignore les boids aux endroits en rouge
369-
* et on fait la somme des 3 vecteurs (en vert)
360+
* et pour les 3 boids proches (en vert) on fait la somme des 3 vecteurs de "repoussement" (en vert aussi)
370361
* qu'on ajoute naturellement au déplacement dû à la vitesse du boid
371362

372363
#### à noter
@@ -375,39 +366,44 @@ dans cette version, en cas de collision, on se contente de modifier la position
375366

376367
+++
377368

378-
### v11: on essaie d'orienter correctement
369+
### v11: orienter correctement
370+
371+
* dans cette version, on va essayer de répercuter les collisions sur l'orientation du boid
372+
* et pour ça on va mettre à jour brutalement l'attribut `angle`
373+
* à ce stade, on se base uniquement sur le mouvement qui est fait à l'instant t:
374+
* pour être explicite, si on passe de *(x1, y1)* à *(x2, y2)*, on oriente
375+
le boid pour s'aligner sur le vecteur *(x2-x1, y2-y1)*
376+
377+
l'effet n'est pas forcément très réussi, vous devez voir l'orientation sauter brutalement d'un angle à un autre
379378

380-
dans cette version, on va essayer de répercuter les collisions sur l'orientation du boid
381-
et pour ça on va mettre à jour brutalement l'attribut `angle` uniquement sur le mouvement qui est fait à l'instant t
382-
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)
383-
l'effet n'est pas forcément très réussi, vous devez voir l'orientation sauter brutalement d'un angle un autre
379+
#### à savoir**
384380

385-
**à savoir**
386381
voyez la fonction `math.atan2` qui est pratique ici
387382

388383
+++
389384

390-
### v12: on lisse les changements d'orientation
385+
### v12: tourner plus doucement
391386

392-
comment pourrait-on obtenir quelque chose d'un peu plus élégant, en ce qui concerne les changements de direction ?
387+
pour lisser les changements d'orientation: comment pourrait-on obtenir quelque
388+
chose d'un peu plus élégant, en ce qui concerne les changements de direction ?
393389

394390
+++
395391

396392
### v13: les touches `` et ``
397393

398-
faire en sorte qu'on puisse contrôler aussi la vitesse avec les touches
394+
faire en sorte qu'on puisse contrôler aussi la vitesse avec les touches `` et ``
399395
essayez le comportement de l'évitement d'obstacles à plusieurs vitesses
400396

401397
+++
402398

403399
### v14: plusieurs boids
404400

405401
remplacez l'unique boid par un ensemble de 20 boids
406-
sans changer la séparation, qui est calculée seulement à partir des obstacles
402+
sans changer, pour l'instant, la séparation, qui est calculée seulement à partir des obstacles
407403

408404
+++
409405

410-
### v15: éviter les obstacles **et** les autres boids
406+
### v15: éviter aussi les autres boids
411407

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

@@ -437,13 +433,16 @@ vous pouvez ensuite améliorer dans les directions suivantes :
437433

438434
## pour aller plus loin
439435

440-
* pour plus de détails sur les boids,
436+
* pour plus de détails sur les boids,
441437
voir [la page de Craig Reynolds](http://www.red3d.com/cwr/boids/),
442-
l'auteur original, et [la page wikipedia](https://en.wikipedia.org/wiki/Boids)
443-
444-
* je vous signale un tutoriel intéressant sur la librairie arcade:
445-
https://realpython.com/arcade-python-game-framework/
446-
447-
* enfin d'autres vidéos qui peuvent vous inspirer également
448-
<https://www.youtube.com/watch?v=QbUPfMXXQIY>
449-
<https://www.youtube.com/watch?v=bqtqltqcQhw>
438+
l'auteur original
439+
* et [la page wikipedia](https://en.wikipedia.org/wiki/Boids)
440+
* je vous signale [un tutoriel intéressant sur la librairie arcade](https://realpython.com/arcade-python-game-framework/) assez long / exhaustif
441+
* enfin d'autres vidéos qui peuvent vous inspirer également (parmi $10^n$ autres) :
442+
443+
::::{grid} 2
444+
```{iframe} https://www.youtube.com/embed/QbUPfMXXQIY?rel=0&amp;controls=1
445+
```
446+
```{iframe} https://www.youtube.com/embed/bqtqltqcQhw?rel=0&amp;controls=1
447+
```
448+
::::
58 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)