Page 1 of 1

[Axe] Automates cellulaires II : Le feu

Unread postPosted: 07 May 2013, 12:51
by Persalteas
CE POST EST UN ENTIER PLAGIAT De CELUI DE MATREF ICI. Mon seul mérite est la traduction HTML>BBCode.


Salut les gens !

Cette fois-ci, avec les automates cellulaires nous allons simuler du feu !

Brûler un endroit précis de l'écran

Le principe

Le principe ici est simple :
  • On teste si un pixel est allumé
    • Dans tous les cas, on éteint le pixel au-dessus
    • Si oui, on tire un nombre aléatoire entre 0 et une valeur au choix, et s'il est différent de 0 on rallume le pixel au-dessus
    • Si non on laisse éteint le pixel du dessus
  • Et ce, pour tous les pixels composant l'aire à "brûler"

Alors allons-y, appliquons dans la joie :] !

Application

On a donc (bien sûr) notre boucle-conteneur, un sprite et ses coordonnées.
Code: Select all
:.FIRE
:
:[FFFFFFFFFFFFFFFF→Pic1
:28→Y+16→X
:
:Repeat getKey(15)
:
:End


Et on a juste à appliquer les étapes bêtement ! Que diriez-vous de faire brûler la ligne du sommet de notre sprite ?
Code: Select all
:.FIRE
:
:[FFFFFFFFFFFFFFFF→Pic1
:28→Y+16→X
:
:Repeat getKey(15)
: Pt-On(X,Y,Pic1
:
: For(A,X,X+7)
:  .Pour une flamme de 14 pixels de haut
:  For(B,Y-14,Y)
:   Pxl-Off(A,B-1        → Règle 1
:   If pxl-Test(A,B
:    If rand^6            → Règle 2
:     Pxl-On(A,B-1
:    End                    → Règle 3
:   End
:  End
: End
:
: DispGraph
:End


Résultat :

Image

Cette méthode a pourtant quelques inconvénients : elle est lente (oooh si, pas tant les boucles For que les routines agissant sur les pixels) et la flamme risque de donner des résultats indésirables si le sprite à brûler se déplace. C'est pour pallier à tout ça qu'on va utiliser une autre méthode !

Brûler tout(e une partie de) l'écran

Le principe

Là, c'est légèrement plus compliqué : on va utiliser deux des aires de RAM pour faire brûler tout ça. L6 si on utilise le buffer, ou L3 pour le back-buffer.

On va donc avoir nos aires libres (qui sont une suite de 768 octets avec un octet = 8 pixels, un par bit) et on va les masquer : c'est à dire leur appliquer un masque dont le but est, comme son nom l'indique, modifier son apparence.

Ce masque, je vous le donne tout de suite, le voici :

Code: Select all
[7FBFDFEFF7FBFDFE→Str1
Alors à voir comme ça, ça doit pas vous inspirer grand chose, mais si vous essayez de l'afficher comme un sprite, vous aurez vu que chaque ligne a un pixel éteint pour 7 allumés. Et bien c'est ça, c'est le masque qu'on va appliquer à L3 ou L6.

Que fait ce masque ? Hé bien il va petit à petit éteindre chaque pixel d'une ligne de 8, ou mettre à 0 chaque bit d'un octet, jusqu'à ce que tout soit éteint / désactivé. En plus de ça, on va copier notre octet sur l'octet au-dessus pour simuler une flamme.

Nous allons appliquer notre masque avec la commande AND.

Application

Allons-y tout de go, on a toutes les clés en main :
Code: Select all
:.FIRE2
:[7FBFDFEFF7FBFDFE→Str1
:
:Repeat getKey(15)
:.Tous les pixels de l'écran
:For(A,0,767)
:{A+L6} and {rand^8+Str1}→{A-12+L6}
:Il y a 12 octets sur une ligne (96 / 8), donc l'octet du dessus est A - 12
:End
:DispGraph
:End

C'est tout ! Pas compliqué, si ?

MAIS on a oublié quelque chose ! Pour brûler, le feu doit avoir une base, un combustible !

Code: Select all
:.FIRE2
:[7FBFDFEFF7FBFDFE→Str1
:
:.On rajoute la ligne qui va brûler
:Line(0,63,95,63
:Repeat getKey(15)
:.Tous les pixels de l'écran
:For(A,0,767)
:{A+L6} and {rand^8+Str1}→{A-12+L6}
:Il y a 12 octets sur une ligne (96 / 8), donc l'octet du dessus est A - 12
:End
:DispGraph
:End


Résultat :

Image

Cette fois-ci, chaque particule flambante est indépendante, on peut donc remplacer la ligne par un sprite, qu'on pourra déplacer ! Je vous laisse le loisir d'essayer, mais sachez juste que <b>tout ce qui se trouvera à l'écran lors de l'exécution de la boucle For va brûler !</b> Donc si vous voulez tout cramer sauf un seul sprite, veillez à l'afficher après la boucle et à l'effacer avant (avec Pt-Change par exemple).

Sachez aussi que si vous remplacez L6 par L3 et DispGraph par DispGraphr, vous aurez du feu en grayscales puisque c'est le back-buffer que vous manipulez !

Autre astuce : remplacez le code précédent par celui-ci :
Code: Select all
:.FIRE2
:[8040201008040201→Str1
:
:.On rajoute la ligne qui va brûler
:Line(0,63,95,63
:.On inverse l'écran
:DrawInv
:Repeat getKey(15)
:.Tous les pixels de l'écran
:For(A,0,767)
:{A+L6} or {rand^8+Str1}→{A-12+L6}
:Il y a 12 octets sur une ligne (96 / 8), donc l'octet du dessus est A - 12
:End
:DispGraph
:End


Et vous aurez du feu blanc sur un fond noir ! Essayez pour voir !

Cet effet peut très bien rendre sur un menu, ou même une animation où tout brûle à l'écran ! Vous pouvez aussi changer la zone qui brûle en manipulant les 2 valeurs de la boucle For !

Faites bon usage de cet effet, et bonne programmation !

Re: [Axe] Automates cellulaires II : Le feu

Unread postPosted: 07 May 2013, 16:25
by Hayleia
Persalteas wrote:CE POST EST UN ENTIER PLAGIAT De CELUI DE MATREF ICI.

:quest:
Et celui de Matref est un plagiat total de celui de Builderboy ?

Persalteas wrote:pallier à

ERR: Syntax

Et à part ça, c'est vrai que les flammes c'est beau à voir, mais cet effet a tellement été utilisé inutilement dans plein de jeux plus ou moins biens que les gens commencent à s'en lasser. Mais c'est toujours bien de comprendre comment le truc marche pour pouvoir en refaire d'autres en tout cas ;)

Re: [Axe] Automates cellulaires II : Le feu

Unread postPosted: 07 May 2013, 16:27
by Excale
Mhh.... en quoi c'est un automate cellulaire ça?

EDIT: Moui, si on considère que rand() est une "règle"...

Re: [Axe] Automates cellulaires II : Le feu

Unread postPosted: 07 May 2013, 16:29
by Hayleia
Ben t'as un tas de pixels et ce tas doit évoluer selon un certain nombre de règles. Donc si le Jeu de la Vie est un automate cellulaire, ce feu en est un aussi, il suit juste d'autres règles.

Re: [Axe] Automates cellulaires II : Le feu

Unread postPosted: 07 May 2013, 16:30
by Excale
Ce qui me gène, c'est que rand() soit considéré comme un règle. Je ne vois pas la moindre trace de cela dans les automates cellulaires que je peux trouver sur wikipedia.

Re: [Axe] Automates cellulaires II : Le feu

Unread postPosted: 07 May 2013, 16:33
by Hayleia
Excale wrote:Ce qui me gène, c'est que rand() soit considéré comme un règle. Je ne vois pas la moindre trace de cela dans les automates cellulaires que je peux trouver sur wikipedia.

Ah. Je savais pas que les automates cellulaires ne pouvaient pas avoir de règles dépendant de l'aléatoire. Bon, ben c'est un automate cellulaire approché, par opposition aux automates cellulaires rigoureux :P