fxfeu
Effet de feu
L'effet de feu date des tous débuts de la scène. Il peut sembler très complexe à première vue, mais la solution derrière sont algorithme est décevant de simplicité. Le tout repose sur le "lissage de pixel", une technique qui consiste à calculer la couleur d'un pixel à partir de la moyenne de ses voisins. Cela donne comme effet de mélanger subtilement les couleurs, afin de les rendre plus uniformes. Regardez ce diagramme explicatif:
En conséquence, il faudra que notre palette de couleurs soit constitué de tons formant un dégrader de couleurs. Pour une flamme, il faudra des tons de jaunes, d'orange et de blanc. Voici le pseudo-code, étape par étape, nécessaire à la création de notre feu:
- Créer un tableau, de la grandeur voulu des flammes, disons 320x70. Ce tableau contiendra la couleur de chaque pixel sur l'écran.
- Préparer notre palette en conséquence, selon la couleur et l'appence que l'on veut donner à notre feu.
- Remplir le bas de l'écran, 130 à 200 sur l'ordonné, et tout l'abscisse de pixels. La cordonnée de chaque pixel est directement en relation avec le tableau que nous avons déclarer plus haut (ie: 320x70)
- Parcourir le tableau. A chaque coordonnée (x,y), on calcule la couleur d'un point a partir de la moyenne des 4 points en dessous de lui, pour que le feu s'estompe graduellement. La formule est donc ([x-1][y] + [x+1][y] + [x][y-1] + [x][y-2]) / 4
- Si y = 199 (bas de l'écran), alors génère une couleur aléatoire jaune-blanc random(100) + 100
- Si la couleur n'est pas 0, on la décremente, pour "refroidir le feu". Sinon, entre les couleur 199 et 0, le feu prendrais tout l'écran! De cette manière, il s’éteint avant...
- Redessiner le pixel (x,y) avec sa nouvelle couleur.
- Loop, tant que désiré!
Comment cela fonctionne - t 'il?
Le tableau ne contient que l'ancienne valeur de couleur du pixel au coordonnée (x,y). Sa valeur sera abaissée, puis lors de la prochaine itération, sa moyenne sera recalculé et sa nouvelle valeur établie, puis décrementé de 1. Ce qui crée l'effet de feu, c'est qu'une fois généré, un pixel perd graduellement de sa valeur de couleur, donc il s'éteint tranquillement. Les pixels du bas on leur moyenne constamment augmenté par l'apport de nouveaux pixels provenant du bas de l'écran. Ceux plus haut subissent l'effet "domino", car chaque moyenne recalculé au bas augmente proportionnellement celle du haut. Noter bien que les couleurs de la palette on un rapport direct avec leur coordonnée (x,y).
C'est aussi simple que cela! À présent, vous pourriez vous amusez à modifier le code... en changeant la palette on pourrait obtenir du feu bleu, rose, ou vert! Le feu pourrait être ailleurs dans l'écran, etc..
fxfeu.cpp
//----------------------------------------------------------------------//
// FICHIER : FXFEU.CPP //
// AUTEUR : Shaun Dore //
// DESCRIPTION : Effet de feu //
// DATE DE MODIFICATION : 18-02-97 //
// COMPILATEUR : Borland Turbo C++ Real Mode 16-bit compiler //
// NOTES : Compiler avec modele memoire Compact //
//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
// Fichiers include //
//----------------------------------------------------------------------//
#include <conio.h>
#include <stdlib.h>
//----------------------------------------------------------------------//
// Variables globales //
//----------------------------------------------------------------------//
char *ecran = (char *) (0xA0000000L);
unsigned char flamme[320][80];
//----------------------------------------------------------------------//
// setpal - fixe les attributs r,g,b //
//----------------------------------------------------------------------//
void setpal(unsigned char col, unsigned char r, unsigned char g, unsigned char b)
{
outp (0x03C8,col);
outp (0x03C9,r);
outp (0x03C9,g);
outp (0x03C9,b);
}
//----------------------------------------------------------------------//
// preparepal() - Initialise la palette a noir->rouge->jaune->blanc //
//----------------------------------------------------------------------//
void preparepal()
{
for (int i=0; i<192;i++) setpal(i,(i*63/192),0,0);
for (i=192;i<256;i++) setpal(i,63,(i/2)-64,0);
}
//-----------------------------------------------------------------------//
// feu() - Pour determiner la couleur d'un pixel, on calcule sa valeur //
// de couleur par la moyenne des 4 pixels en dessus de lui, c'est a //
// dire ([x-1],[y] + [x][y+1] + [x+1][y+1] + [x][y+1]) et on divise par 4//
// Puis on trouve sa valeur de couleur col dans le tableau du feu flamme.//
//-----------------------------------------------------------------------//
void feu()
{
unsigned char col;
do
{
for (int x=5;x<315;x++)
for (int y=125;y<199;y++)
{
// Moyenne des couleurs des pixels pour la couleur du nouveau
col = ( flamme[x-1][y+1]+
flamme[x+1][y+1]+
flamme[x][y-1]+
flamme[x][y+1] ) / 4;
// Initialise le foyer du feu et decremente la couleur
if (y == 198) col = random(135) + 120;
if (col != 0) col--;
// Affiche le pixel selon la tableau flamme[x][y]
ecran[(y<<8)+(y<<6)+x] = flamme[x][y] = col;
}
} while (!kbhit());
}
//----------------------------------------------------------------------//
// Fonction MAIN //
//----------------------------------------------------------------------//
void main()
{
randomize();
asm {MOV AX,0x13;INT 0x10}
preparepal();
feu();
asm {MOV AX,0x03; INT 0x10}
}