fxplasma
Plasmas en temps réel
Autant vous avertir tout de suite : les plasmas sont obsolètes. De nos jours, ils ne devraient en théorie plus se retrouver dans les démos, à moins qu'ils soient remarquablement bien faits et/ou originaux. Mais à titre pédagogique, les plasmas sont parfaits : pas très difficile à comprendre, et divertissant. En effet, cet effet est un de mes favoris côté 2D. La méthode que je propose est la méthode classique, quoique tout le monde à sa propre formule pour calculé les courbes.
IMPLÉMENTATION
Il existe 2 types distincts de plasmas: les plasmas dit "statiques", et les plasmas calculés en temps réel. Les statiques sont crées à partir d'une fractale, sur laquelle on effectue une rotation de palette. Ils sont beaucoup moins passionnants que leurs confrères "temps réel". Simplement dit, pour réaliser un plasma de ce genre, nous avons besoin de courbes complexes qui s'entrecroisent. La fonction cos nous permet de dessiner des cercles et des lignes courbes. Nous allons donc utiliser ces fonctions afin de créer une série de lignes courbes qui s’entrecroiseront sur l’écran.
Nous allons avoir besoin de courbes. Ces courbes devront, pour crée l'effet désiré, être constituées de pixels de couleurs dégradés. Plutôt que de calculer la couleur de chaque pixel à chaque itération, nous allons plutôt avoir recours au service d'une table pré-calculées, contenant les valeurs de couleur. Les "vagues" sont crées par le déplacement de 4 lignes sinusoïdales. En réalité, nous ne dessinons pas vraiment de lignes mais les dégradés de couleur crée l’impression de mouvement au plasma. Il faudra donc encore une fois mettre sur pied notre palette. Voici le pseudo-code :
- Parcourir chaque pixel sur l’écran
- On recalcule les nouvelles couleurs obtenues pour chaque lignes (320 pixels) et ce en consultant le tableau de cosinus.
- Quand on est rendu au bas de l'écran, on recommence.
Il faudra tenir compte des valeurs possible de x et de y, afin que l’adressage dans notre tableau ne dépasse par ses limites. Puisque l’écran à 320 pixels de large, et qu’on additionne 4 courbes variant entre 0 et 320, le résultat maxium est 640. Un tableau de 640 positions sera donc amplement suffisant. Voici le code de la boucle principale :
void plasma()
{
unsigned int offset,cos1,cos2,cos3,cosinus[640];
unsigned char col;
cos1=cos2=cos3=0;
for (int c=0;c<=640;c++) cosinus[c] = cos(2 * M_PI * c/320) * 32 + 32;
do
{
offset = 0;
cos1+=3; if (cos1 >=320) cos1 = 0;
cos2+=4; if (cos2 >=320) cos2 = 0;
cos3+=5; if (cos3 >=320) cos3 = 0;
for (int y=0;y<200;y++)
for (int x=0;x<320;x++)
screen[offset++] = cosinus[x+cos2] +
cosinus[x+y] +
cosinus[y+cos1] +
cosinus[y+cos3];
} while (!kbhit());
}
Pour que notre table soit complète, il faut rentrer dans chacune des 640 cases du tableau les valeurs contenues entre 0 et 2*pi. Mais cela ne suffit pas, car le cosinus nous retourne toujours des valeurs entre -1 et 1, et nos couleurs se situe entre 0 et 255. C'est pour cela que je multiplie par 32, ce qui nous donne des valeurs entre -32 et 32. Finalement, on additionne 32 pour ramener ces valeurs entre 0 et 64. L'incrémentation des lignes influe directement sur la rapidité du plasma. Cependant, plus l’incrémentation est grande, plus le plasma sera "saccadé" et moins fluide.
FXPLASMA.CPP
//----------------------------------------------------------------------//
// FICHIER : FXPLASMA.CPP //
// AUTEUR : Shaun Dore //
// DESCRIPTION : Plasma en temps reel //
// DATE DE MODIFICATION : 08-05-98 //
// COMPILATEUR : Borland Turbo C++ Real Mode 16-bit compiler //
// NOTES : Compiler avec modele memoire Compact //
//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
// Fichiers include //
//----------------------------------------------------------------------//
#include <math.h>
#include <conio.h>
//----------------------------------------------------------------------//
// Variables globales //
//----------------------------------------------------------------------//
char *screen = (char *) (0xA0000000L);
//----------------------------------------------------------------------//
// 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 - ajuste la palette a mon gout //
//----------------------------------------------------------------------//
void preparepal()
{
for (int i=0;i<64;i++) setpal(i,i,0,0);
for (i=64;i<128;i++) setpal(i,0,i,0);
for (i=128;i<196;i++) setpal(i,0,0,i);
for (i=196;i<256;i++) setpal(i,0,0,i-196);
}
//----------------------------------------------------------------------//
// plasma - genere un plasma plein ecran en temps reel //
//----------------------------------------------------------------------//
void plasma()
{
unsigned int offset,cos1,cos2,cos3,cosinus[640];
unsigned char col;
cos1=cos2=cos3=0;
for (int c=0;c<=640;c++) cosinus[c] = cos(2 * M_PI * c/320) * 32 + 32;
do
{
offset = 0;
cos1+=3; if (cos1 >=320) cos1 = 0;
cos2+=4; if (cos2 >=320) cos2 = 0;
cos3+=5; if (cos3 >=320) cos3 = 0;
for (int y=0;y<200;y++)
for (int x=0;x<320;x++)
screen[offset++] = cosinus[x+cos2] +
cosinus[x+y] +
cosinus[y+cos1] +
cosinus[y+cos3];
} while (!kbhit());
}
//----------------------------------------------------------------------//
// Fonction principale //
//----------------------------------------------------------------------//
void main()
{
asm {MOV AX, 0x13;INT 0x10}
preparepal();
plasma();
asm {MOV AX, 0x03;INT 0x10}
}