Tous | Basic Casio | C/C++/ASM | LuaFX | Graphisme | Transferts | Logiciels | Diverses astuces

Calculatrice
Toutes
Graphs 35 à 100
Graph 25
Graphs 75/85/95 (SD)
Graph 100(+)
Classpad 300/330 (+)
Fx-CG 10/20
Fx-CP 400

Retour à la liste des tutoriels
Tutoriel Casio : Effet de fumée
Tutoriel rédigé le : 2013-07-11 09:36  par Smashmaster  Catégorie : C/C++/ASM  Calculatrice : Fx-CG 10/20

Discutez de ce tutoriel sur le forum >> Voir le sujet dédié (7 commentaires)

Effet de fumée
Tutoriel en cours de rédaction

Dans ce petit tutoriel je vais vous montrer comment faire de la fumée sur la casio prizm, à la fin de ce tutoriel vous serez normalement capable de refaire ceci :
http://www.youtube.com/watch?v=_-4x38FQkrI

Il existe plusieurs méthodes pour faire de la fumée, dans ce tutoriel je vais vous montrer qu'une seule méthode, cette méthode est très facile à refaire. Vous trouverez en fichier joint les codes sources et le .g3a

Avant de commencer il faut savoir que
Cliquez pour découvrir
Cliquez pour recouvrir
La fumée est composée de petites particules, plus il y a de particule, plus la fumée est opaque
Lorques les particules gagnent en hauteurs, il commencent à se propager un peu partout, la fumée devient donc de moins en moins opaque.

étant donné que la prizm est une calculatrice qui n'est pas très performante, on ne va pas afficher les particules pixel par pixel, ça serait beaucoup trop lent, mais on va plutôt afficher un sprite, moi j'ai utilisé ce sprite :
Voici comment on va coder cette algorithme :
Cliquez pour découvrir
Cliquez pour recouvrir
chaque sprite sera affiché avec une valeur de transparence très élevé, les sprites sont donc presques invisible, mais si on superpose les sprites on obtient un résultat plus opaque, ceci n'est pas très diffile à programmer
chaque particule à une durée de vie, entre chaque frame on va baisser la durée de vie de chaque particule, lorsque la durée de vie est égale à 0 on supprime cette sprite , pour plus de réalisme on peut aussi varier le niveau de transparence de chaque sprite en fonction de sa durée de vie actuelle

Maintenant on passe à la partie programmation

chaque particule sera représenté par une variable de type tParticule

typedef [purple]struct[/purple] tParticule
{
    bool estPresent;  [green]//lorque estPresent=true, on affiche notre sprite[/green]
    [purple]int[/purple] x; [green]//position en x du sprite[/green]
    [purple]int[/purple] y; [green]//position en y du sprite[/green]
    [purple]int[/purple] dureeDeVie; [green]//durée de vie, si dureeDeVie=[maroon]0[/maroon], alors estPresent=false[/green]
} tParticule;


on va créer maintenant un tableau de type tParticule, dans l'exemple ci-dessous le tableau contient 70 éléments, donc il y aura au maximum 70 sprites visible à l'écran

[brown]#define TAILLETAB 70[/brown]
[green]//j'ai mis la taille du tableau dans un define, ainsi il sera beaucoup plus simple de paramétrer la fumée ;)[/green]
[purple]int[/purple] main()
{
    tParticule particule[TAILLETAB];
    [b][blue]return[/blue][/b] 0;
}

maintenant il faudrait initialiser notre tableau, pour faire ça j'ai créé la fonction

void Init_tParticule(tParticule * particule)
{
    [purple]int[/purple] i = [maroon]0[/maroon];
    [b][blue]for[/blue][/b] (i=[maroon]0[/maroon];i<TAILLETAB;i++)
    {
        particule[i ].estPresent = false;
        particule[i ].x = [maroon]0[/maroon];
        particule[i ].y = [maroon]0[/maroon];
        particule[i ].dureeDeVie = [maroon]0[/maroon];
    }
}

et je l'utilise dans le main


int main()
{
    tParticule particule[TAILLETAB];
    Init_tParticule(particule);
    [b][blue]return[/blue][/b] 0;
}

maintenant on va créer une boucle et dans cette boucle on va afficher un fond noir

int main()
{
    tParticule particule[TAILLETAB];
    Init_tParticule(particule);
    [b][blue]do[/blue][/b]
    {
        BgColor(0x0000); [green]//ici on affiche le fond noir, vous pouvez retrouver cette fonction en fichier joint[/green]
        Bdisp_PutDisp_DD();
    }while (!keydown(47)); [green]//vous pouvez mettre ce que vous voulez comme cas d'arrêt[/green]
    [b][blue]return[/blue][/b] 0;
}

à chaque fois que l'on tourne en boucle, on va rajouter des particules dans le tableau 'particule', puis on va les afficher

[brown]#define NOMBREPARTICULEARAJOUTER 4[/brown]

[purple]int[/purple] main()
{
    tParticule particule[TAILLETAB];
    Init_tParticule(particule);
    [b][blue]do[/blue][/b]
    {
        BgColor(0x0000);
        [b][blue]for[/blue][/b] (i=[maroon]0[/maroon];i<NOMBREPARTICULEARAJOUTER;i++)
        {
            Add_tParticule(particule);
        }

        [b][blue]for[/blue][/b] (i=[maroon]0[/maroon];i<TAILLETAB;i++)
        {
            [b][blue]if[/blue][/b] (particule[i ].estPresent)
            {
                CopySpriteNbitMaskedAlpha(smoke,particule[i ].x-30,particule[i ].y-30,[maroon]60[/maroon],[maroon]60[/maroon],smoke_palette,[maroon]0[/maroon]xa254,[maroon]2[/maroon],(particule[i ].dureeDeVie*NIVEAUOPACITE)/DUREEDEVIE);
            }
        }
    }while (!keydown(47)); [green]//vous pouvez mettre ce que vous voulez comme cas d'arrêt[/green]
    [b][blue]return[/blue][/b] 0;
}    

Quelques explications :
Cliquez pour découvrir
Cliquez pour recouvrir

Je rajoute 4 sprites à chaque fois que le programme tourne en boucle à l'aide de la fonction Add_tParticule, j'ai mis le nombre de particule dans un #define, ainsi il sera plus facile de paramétrer la fumée, plus la valeur de NOMBREPARTICULEARAJOUTER sera élevé, plus la fumée sera dense, mais le programme sera ralenti et il faudrait augmenter la taille du tableau, sinon le tableau sera vite plein
la fonction Add_tParticule
la fonction Add_tParticule


[brown]#define DUREEDEVIE 17[/brown]
[brown]#define NIVEAUOPACITE 4[/brown]
[brown]#define XMIN 0[/brown]
[brown]#define XMAX 384[/brown]

void Add_tParticule(tParticule * particule)
{
    [purple]int[/purple] i = [maroon]0[/maroon];
    [b][blue]while[/blue][/b] (particule[i ].estPresent && i<TAILLETAB) [green]//on tourne en boucle tant qu[gray]'on n'[/gray]a pas trouver de place de libre[/green]
    {
        i++;
    }
    [b][blue]if[/blue][/b] (i <TAILLETAB) [green]// si on a trouver une place de libre[/green]
    {
        particule[i ].estPresent = true;
        particule[i ].x = Rand32(XMIN,XMAX);[green]//on rajoute les particules aléatoirements sur toute la longueur de l'écran, XMIN et XMAX sont des define[/green]
        particule[i ].y = [maroon]236[/maroon];
        particule[i ].dureeDeVie = DUREEDEVIE;
    }
}

DUREEDEVIE est un #define, plus la durée de vie est élevé, plus les particules monteront haut.
à la place de #define DUREEDEVIE 15 vous pouvez aussi mettre #define DUREEDEVIE Rand32(10,30) par exemple, ainsi il y aura des particules qui disparaitront plus vite que les autres
Plus la durée de vie est élevé, plus il y aura de particules, car il y aura des particules sur une plus grande surface.

Passons maintenant à l'affichage, pour afficher des sprites avec un canal alpha j'ai utilisé la fonction CopySpriteNbitMaskedAlpha, c'est la fonction CopySpriteNbitMasked que j'ai légèrement modifié à l'aide de la fonction SetPixelAlpha de Pierrotll
Les paramètres de la fonction CopySpriteNbitMaskedAlpha
Les paramètres de la fonction CopySpriteNbitMaskedAlpha

les paramètres:
1)nom du sprite (dans mon exemple c'est smoke)
2)coordonnée en x
3)coordonnée en y
4)taille du sprite en x (dans mon exemple c'est 60*60)
5)taille du sprite en y
6)palette (smoke_palette)
7)couleur transparent (dans mon exemple le violet est la couleur transparente)
8)nombre de bits (dans mon exemple le sprite des particules est codé en 2 bits)
9)la valeur d'opacité (0= transparent, 31=opaque) dans mon exemple j'ai mis (particule[i ].dureeDeVie*NIVEAUOPACITE)/DUREEDEVIE), c'est un simple produit en croix.
Plus la valeur de NIVEAUOPACITE sera élevé, plus la fumée sera dense, ainsi on pourra baisser un peu la valeur de NOMBREPARTICULEARAJOUTER, ce qui accélèrera légèrement le programme


Maintenant il ne nous reste plus qu'à déplacer chaque sprite et de modifier la durée de vie

        [b][blue]for[/blue][/b] (i=[maroon]0[/maroon];i<TAILLETAB;i++)
        {
            [b][blue]if[/blue][/b] (particule[i ].estPresent)
            {            
                particule[i ].y -=[maroon]4[/maroon]; [green]//les sprites montent[/green]
                particule[i ].x +=Rand32(1,[maroon]6[/maroon])-3+VENT; [green]//les sprites se déplacent légèrement vers la droite ou vers la gauche[/green]
                particule[i ].dureeDeVie-=Rand32(0,[maroon]2[/maroon]); [green]//on diminue la duree de vie, on aurait pû aussi mettre particule[i ].dureeDeVie-=[maroon]1[/maroon];[/green]
                [b][blue]if[/blue][/b] (particule[i ].dureeDeVie<=[maroon]0[/maroon] || particule[i ].y<10) [green]//on supprime le sprite si la durée de vie vaut 0 ou si le sprite sort de l'écran[/green]
                    particule[i ].estPresent = false;
            }
        }

VENT est un define, si VENT=0 alors il n'y a pas de vent

Voilà !

L'algorithme n'est pas trop difficile, la seule difficulté reste le paramétrage, car il est très difficile de faire de la fumée réaliste sans trop ralentir le programme, libre à vous d'adapter l'algorithme selon vos besoin

Fichier joint


Discutez de ce tutoriel sur le forum >> Voir le sujet dédié (7 commentaires)

Publicité et partenaires
Casio Education
Casio éducation

TI-Planet
Casiopeia
Casiopeia
CasioFan, la communauté ClassPad
CasioFan
CodeWalrus
CodeWalrus

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2015 | Il y a 41 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements
Rugby Manager | Jeu de basket | Jeu de handball | Jeu de tennis | Nova Raider | Réparation téléphone | Soccer Rush | Tasty Tale

Planète Casio est un site communautaire indépendant, géré bénévolement et n'est donc pas affilié à Casio | Toute reproduction de Planète Casio, même partielle, est interdite
Les fichiers, programmes et autres publications présents sur Planète Casio restent la propriété de leurs auteurs respectifs et peuvent être soumis à des licences ou des copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd