Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.
La shoutbox n'est pas chargée par défaut pour des raisons de performances. Cliquez pour charger.
Tous | Tutoriels du Mercredi | Basic Casio | C/C++/ASM | LuaFX | Graphisme | Transferts | Logiciels | Diverses astuces

Calculatrice
Toutes
Graph 35 à 100
Graph 25+Pro/25+E/25+E II
Graph 35+USB/75(+E)/85/95 SD
Graph 100(+)
Classpad 300/330(+)
fx-CG 10/20 (Prizm)
Classpad 400(+E)
Graph 90+E
fx-92+ SC

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 (Prizm)

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 :


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)

Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 121 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd