Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.

Forum Casio - Vos tutoriels et astuces


Index du Forum » Vos tutoriels et astuces » [C][Prizm] Faire de la fumée
Smashmaster Hors ligne Ancien modérateur Points: 4561 Défis: 253 Message

[C][Prizm] Faire de la fumée

Posté le 11/07/2013 01:00

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


Ziqumu Hors ligne Membre d'honneur Points: 3055 Défis: 9 Message

Citer : Posté le 11/07/2013 01:47 | #


Sympa ce petit tuto
T'as un projet de skyrim sur Fx-CG20 ou quoi ?

(t'as fait un doublon de phrase à la fin du tuto)
Smashmaster Hors ligne Ancien modérateur Points: 4561 Défis: 253 Message

Citer : Posté le 11/07/2013 03:43 | #


Je n'ai pas un projet de skyrim, l'univers de skyrim est beaucoup trop riche, impossible de coder ça seul, je préfère coder mon jeu de zelda et metroid.

(J'ai corrigé la dernière phrase, merci)
Tsuneo Hors ligne Membre Points: 973 Défis: 51 Message

Citer : Posté le 11/07/2013 09:34 | #


Tuto sympa, bien réalisé, même moi qui n'y connait rien en C j'arrive à comprendre à peu près ta démarche
Dommage que tu n'aies pas de projet de Skyrim, rien que l'écran d'accueil nous faisait tous baver

Calculatrices : Graph 35+ USB tweakée et Classpad 330
Suivez moi et mon humour dévastateur ici focliquéla
Totoyo Hors ligne Membre d'honneur Points: 16067 Défis: 102 Message

Citer : Posté le 11/07/2013 09:37 | #


Bravo pour ce tutoriel ! Je l'ai ajouté à la liste des tutoriels de qualité (section Programmation).
Smashmaster Hors ligne Ancien modérateur Points: 4561 Défis: 253 Message

Citer : Posté le 11/07/2013 18:31 | #


Merci à vous
@Tsuneo : l'année dernière j'ai voulu programmé le jeu skyrim sur la prizm, mais le problème c'est que skyrim est un jeu en 3D, donc impossible de trouver des sprites de ce jeu sur le net, de plus l'univers est trop riche, j'ai très vite abandonné l'idée.
Ziqumu Hors ligne Membre d'honneur Points: 3055 Défis: 9 Message

Citer : Posté le 11/07/2013 18:41 | #


De toute façon je pense qu'un bon vieux zelda sera bien plus durable dans le temps
Tsuneo Hors ligne Membre Points: 973 Défis: 51 Message

Citer : Posté le 12/07/2013 21:33 | #


Ne t'inquiète pas je comprends bien, c'est un projet au-delà d'une Prizm ! Ton Zelda me fait baver encore plus !

Calculatrices : Graph 35+ USB tweakée et Classpad 330
Suivez moi et mon humour dévastateur ici focliquéla

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2022 | Il y a 44 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