#include #include #include #include "goom_core.h" #include "goom_tools.h" #include "filters.h" #include "lines.h" #include "ifs.h" #include "tentacle3d.h" #include "gfontlib.h" //#define VERBOSE #ifdef VERBOSE #include #endif #define STOP_SPEED 128 #define TIME_BTW_CHG 300 /**-----------------------------------------------------** ** SHARED DATA ** **-----------------------------------------------------**/ static guint32 *pixel; static guint32 *back; static guint32 *p1, *p2, *tmp; static guint32 cycle; typedef struct { int drawIFS; int drawPoints; int drawTentacle; int drawScope; int farScope; int rangemin; int rangemax; } GoomState; #define STATES_NB 8 #define STATES_RANGEMAX 510 GoomState states[STATES_NB] = { {1,0,0,1,4, 000, 100}, {1,0,0,0,1, 101, 140}, {1,0,0,1,2, 141, 200}, {0,1,0,1,2, 201, 260}, {0,1,0,1,0, 261, 330}, {0,1,1,1,4, 331, 400}, {0,0,1,0,5, 401, 450}, {0,0,1,1,1, 451, 510} }; GoomState *curGState = states+4; guint32 resolx, resoly, buffsize, c_black_height = 0, /* hauteur des bande * * * noires en bas et * * * en * haut */ c_offset = 0, c_resoly = 0; /* avec prise en compte de ca */ // effet de ligne.. static GMLine *gmline1 = NULL; static GMLine *gmline2 = NULL; void choose_a_goom_line (float *param1, float *param2, int *couleur, int *mode, float *amplitude, int farparm); // la police //int ***font_chars; //int *font_width; //int *font_height; //void goom_draw_text (guint32 * buf, // int x, int y, // const char *str, float chspace, int center); void update_message (char *message); void goom_init (guint32 resx, guint32 resy, int cinemascope) { #ifdef VERBOSE printf ("GOOM: init (%d, %d);\n", resx, resy); #endif if (cinemascope) c_black_height = resy / 5; else c_black_height = 0; resolx = resx; resoly = resy; buffsize = resx * resy; c_offset = c_black_height * resx; c_resoly = resy - c_black_height * 2; pixel = (guint32 *) malloc (buffsize * sizeof (guint32) + 128); back = (guint32 *) malloc (buffsize * sizeof (guint32) + 128); //RAND_INIT (); srand ((guint32) pixel); if (!rand_tab) rand_tab = (int *) malloc (NB_RAND * sizeof(int)) ; rand_pos = 1 ; while (rand_pos != 0) rand_tab [rand_pos++] = rand () ; cycle = 0; p1 = (guint32 *) ((1 + ((unsigned int) (pixel)) / 128) * 128); p2 = (guint32 *) ((1 + ((unsigned int) (back)) / 128) * 128); init_ifs (resx, c_resoly); gmline1 = goom_lines_init (resx, c_resoly, GML_HLINE, c_resoly, GML_BLACK, GML_CIRCLE, 0.4f * (float) c_resoly, GML_VERT); gmline2 = goom_lines_init (resx, c_resoly, GML_HLINE, 0, GML_BLACK, GML_CIRCLE, 0.2f * (float) c_resoly, GML_RED); // font_height = NULL; // font_width = NULL; // font_chars = NULL; gfont_load (); tentacle_new (); } void goom_set_resolution (guint32 resx, guint32 resy, int cinemascope) { free (pixel); free (back); if (cinemascope) c_black_height = resy / 8; else c_black_height = 0; c_offset = c_black_height * resx; c_resoly = resy - c_black_height * 2; resolx = resx; resoly = resy; buffsize = resx * resy; pixel = (guint32 *) malloc (buffsize * sizeof (guint32) + 128); bzero (pixel, buffsize * sizeof (guint32) + 128); back = (guint32 *) malloc (buffsize * sizeof (guint32) + 128); bzero (back, buffsize * sizeof (guint32) + 128); p1 = (guint32 *) ((1 + ((unsigned int) (pixel)) / 128) * 128); p2 = (guint32 *) ((1 + ((unsigned int) (back)) / 128) * 128); init_ifs (resx, c_resoly); goom_lines_set_res (gmline1, resx, c_resoly); goom_lines_set_res (gmline2, resx, c_resoly); } guint32 * goom_update (gint16 data[2][512], int forceMode, float fps, char *songTitle, char *message) { static int lockvar = 0; // pour empecher de nouveaux changements static int goomvar = 0; // boucle des gooms static int totalgoom = 0; // nombre de gooms par seconds static int agoom = 0; // un goom a eu lieu.. static int abiggoom = 0; // un big goom a eu lieu.. static int loopvar = 0; // mouvement des points static int speedvar = 0; // vitesse des particules // duree de la transition entre afficher les lignes ou pas #define DRAWLINES 80 static int lineMode = DRAWLINES; // l'effet lineaire a dessiner static int nombreCDDC = 0; // nombre de Cycle Depuis Dernier Changement guint32 *return_val; guint32 pointWidth; guint32 pointHeight; int incvar; // volume du son static int accelvar=0; // acceleration des particules int i; float largfactor; // elargissement de l'intervalle d'évolution static int stop_lines = 0; // des points static int ifs_incr = 1; // dessiner l'ifs (0 = non: > = increment) static int decay_ifs = 0; // disparition de l'ifs static int recay_ifs = 0; // dédisparition de l'ifs #define SWITCHMULT (29.0f/30.0f) #define SWITCHINCR 0x7f static float switchMult = 1.0f; static int switchIncr = SWITCHINCR; // static int lastgoom = 0; static char goomlimit = 2; // sensibilité du goom static ZoomFilterData zfd = { 127, 8, 16, 1, 1, 0, NORMAL_MODE, 0, 0, 0, 0, 0 }; ZoomFilterData *pzfd; /* test if the config has changed, update it if so */ pointWidth = (resolx * 2) / 5; pointHeight = ((c_resoly) * 2) / 5; /* ! etude du signal ... */ incvar = 0; for (i = 0; i < 512; i++) { if (incvar < data[0][i]) incvar = data[0][i]; } i = accelvar; accelvar = incvar / 1000; if (speedvar > 5) { accelvar--; if (speedvar > 20) accelvar--; if (speedvar > 40) speedvar = 40; } accelvar--; i = accelvar - i; if (i<0) i=-i; speedvar += (speedvar + i/2); speedvar /= 2; if ((speedvar) && (cycle%9==0)) { speedvar -= 1; } if ((speedvar) && (cycle%5==0)) { speedvar = (speedvar*7)/8; } if (speedvar < 0) speedvar = 0; if (speedvar > 50) speedvar = 50; /* ! calcul du deplacement des petits points ... */ largfactor = ((float) speedvar / 40.0f + (float) incvar / 50000.0f) / 1.5f; if (largfactor > 1.5f) largfactor = 1.5f; /* if ((ifs_incr == 1) && (iRAND (300) == 0) && (decay_ifs < -300) && (agoom)) { decay_ifs = 200; } */ decay_ifs--; if (decay_ifs > 0) ifs_incr += 2; if (decay_ifs == 0) ifs_incr = 0; /* if ((ifs_incr == 0) && (iRAND (300) == 0) && (agoom) && (decay_ifs < -100)) { recay_ifs = 5; ifs_incr = 11; if (iRAND(2)) stop_lines = 0xf000 & 5; } */ if (recay_ifs) { ifs_incr -= 2; recay_ifs--; if ((recay_ifs == 0)&&(ifs_incr<=0)) ifs_incr = 1; } if (ifs_incr > 0) ifs_update (p1 + c_offset, p2 + c_offset, resolx, c_resoly, ifs_incr); if (curGState->drawPoints) { for (i = 1; i * 15 <= speedvar + 15; i++) { loopvar += speedvar*2/3 + 1; pointFilter (p1 + c_offset, YELLOW, ((pointWidth - 6.0f) * largfactor + 5.0f), ((pointHeight - 6.0f) * largfactor + 5.0f), i * 152.0f, 128.0f, loopvar + i * 2032); pointFilter (p1 + c_offset, ORANGE, ((pointWidth / 2) * largfactor) / i + 10.0f * i, ((pointHeight / 2) * largfactor) / i + 10.0f * i, 96.0f, i * 80.0f, loopvar / i); pointFilter (p1 + c_offset, VIOLET, ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i, ((pointHeight / 3 + 5.0f) * largfactor) / i + 10.0f * i, i + 122.0f, 134.0f, loopvar / i); pointFilter (p1 + c_offset, BLACK, ((pointHeight / 3) * largfactor + 20.0f), ((pointHeight / 3) * largfactor + 20.0f), 58.0f, i * 66.0f, loopvar / i); pointFilter (p1 + c_offset, WHITE, (pointHeight * largfactor + 10.0f * i) / i, (pointHeight * largfactor + 10.0f * i) / i, 66.0f, 74.0f, loopvar + i * 500); } } // par défaut pas de changement de zoom pzfd = NULL; /* * Test forceMode */ #ifdef VERBOSE if (forceMode != 0) { printf ("forcemode = %d\n", forceMode); } #endif // diminuer de 1 le temps de lockage // note pour ceux qui n'ont pas suivis : le lockvar permet d'empecher un // changement d'etat du plugins juste apres un autre changement d'etat. oki // // ? if (--lockvar < 0) lockvar = 0; // temps du goom if (--agoom < 0) agoom = 0; // temps du goom if (--abiggoom < 0) abiggoom = 0; if ((!abiggoom) && (speedvar > 4) && (goomlimit > 4) && ((accelvar > goomlimit*9/8+7)||(accelvar < -goomlimit*9/8-7))) { int size,i; static int couleur = (0xc0<<(ROUGE*8)) |(0xc0<<(VERT*8)) |(0xf0<<(BLEU*8)) |(0xf0<<(ALPHA*8)); abiggoom = 100; size = resolx*c_resoly; for (i=0;i goomlimit) || (accelvar < -goomlimit) || (forceMode > 0) || (nombreCDDC > TIME_BTW_CHG)) { // if (nombreCDDC > 300) { // } // UN GOOM !!! YAHOO ! totalgoom++; agoom = 20; // mais pdt 20 cycles, il n'y en aura plus. // lineMode = (lineMode + 1)%40; // Tous les 10 gooms on change de mode // lineaire // if (iRAND(12) == 0) // zfd.vitesse=STOP_SPEED-1; // if (iRAND(13) == 0) // zfd.vitesse=STOP_SPEED+1; // changement eventuel de mode if (iRAND(16) == 0) switch (iRAND (32)) { case 0: case 10: zfd.hypercosEffect = iRAND (2); case 13: case 20: case 21: zfd.mode = WAVE_MODE; zfd.reverse = 0; zfd.waveEffect = (iRAND (3) == 0); if (iRAND (2)) zfd.vitesse = (zfd.vitesse + 127) >> 1; break; case 1: case 11: zfd.mode = CRYSTAL_BALL_MODE; zfd.waveEffect = 0; zfd.hypercosEffect = 0; break; case 2: case 12: zfd.mode = AMULETTE_MODE; zfd.waveEffect = 0; zfd.hypercosEffect = 0; break; case 3: zfd.mode = WATER_MODE; zfd.waveEffect = 0; zfd.hypercosEffect = 0; break; case 4: case 14: zfd.mode = SCRUNCH_MODE; zfd.waveEffect = 0; zfd.hypercosEffect = 0; break; case 5: case 15: case 22: zfd.mode = HYPERCOS1_MODE; zfd.waveEffect = 0; zfd.hypercosEffect = (iRAND (3) == 0); break; case 6: case 16: zfd.mode = HYPERCOS2_MODE; zfd.waveEffect = 0; zfd.hypercosEffect = 0; break; case 7: case 17: zfd.mode = CRYSTAL_BALL_MODE; zfd.waveEffect = (iRAND (4) == 0); zfd.hypercosEffect = iRAND (2); break; case 8: case 18: case 19: zfd.mode = SCRUNCH_MODE; zfd.waveEffect = 1; zfd.hypercosEffect = 1; break; case 29: case 30: zfd.mode = YONLY_MODE; break; case 31: case 32: zfd.mode = SPEEDWAY_MODE; break; default: zfd.mode = NORMAL_MODE; zfd.waveEffect = 0; zfd.hypercosEffect = 0; } } // tout ceci ne sera fait qu'en cas de non-blocage if (lockvar == 0) { // reperage de goom (acceleration forte de l'acceleration du volume) // -> coup de boost de la vitesse si besoin.. if ((accelvar > goomlimit) || (accelvar < -goomlimit)) { static int rndn = 0 ,i; static int blocker = 0; goomvar++; /* SELECTION OF THE GOOM STATE */ if ((!blocker)&&(iRAND(3))) { rndn = iRAND(STATES_RANGEMAX); blocker = 3; } else if (blocker) blocker--; for (i=0;i= states[i].rangemin) && (rndn <= states[i].rangemax)) curGState = states+i; if ((curGState->drawIFS) && (ifs_incr<=0)) { recay_ifs = 5; ifs_incr = 11; } if ((!curGState->drawIFS) && (ifs_incr>0) && (decay_ifs<=0)) decay_ifs = 100; if (!curGState->drawScope) stop_lines = 0xf000 & 5; if (!curGState->drawScope) { stop_lines = 0; lineMode = DRAWLINES; } // if (goomvar % 1 == 0) { guint32 vtmp; guint32 newvit; lockvar = 50; newvit = STOP_SPEED + 1 - ((float)4.0f * log10(speedvar+1)); // retablir le zoom avant.. if ((zfd.reverse) && (!(cycle % 13)) && (rand () % 5 == 0)) { zfd.reverse = 0; zfd.vitesse = STOP_SPEED - 2; lockvar = 75; } if (iRAND (10) == 0) { zfd.reverse = 1; lockvar = 100; } if (iRAND (10) == 0) zfd.vitesse = STOP_SPEED - 1; if (iRAND (12) == 0) zfd.vitesse = STOP_SPEED + 1; // changement de milieu.. switch (iRAND (25)) { case 0: case 3: case 6: zfd.middleY = c_resoly - 1; zfd.middleX = resolx / 2; break; case 1: case 4: zfd.middleX = resolx - 1; break; case 2: case 5: zfd.middleX = 1; break; default: zfd.middleY = c_resoly / 2; zfd.middleX = resolx / 2; } if ((zfd.mode == WATER_MODE) || (zfd.mode == YONLY_MODE) || (zfd.mode == AMULETTE_MODE)) { zfd.middleX = resolx / 2; zfd.middleY = c_resoly / 2; } switch (vtmp = (iRAND (15))) { case 0: zfd.vPlaneEffect = iRAND (3) - iRAND (3); zfd.hPlaneEffect = iRAND (3) - iRAND (3); break; case 3: zfd.vPlaneEffect = 0; zfd.hPlaneEffect = iRAND (8) - iRAND (8); break; case 4: case 5: case 6: case 7: zfd.vPlaneEffect = iRAND (5) - iRAND (5); zfd.hPlaneEffect = -zfd.vPlaneEffect; break; case 8: zfd.hPlaneEffect = 5 + iRAND (8); zfd.vPlaneEffect = -zfd.hPlaneEffect; break; case 9: zfd.vPlaneEffect = 5 + iRAND (8); zfd.hPlaneEffect = -zfd.hPlaneEffect; break; case 13: zfd.hPlaneEffect = 0; zfd.vPlaneEffect = iRAND (10) - iRAND (10); break; case 14: zfd.hPlaneEffect = iRAND (10) - iRAND (10); zfd.vPlaneEffect = iRAND (10) - iRAND (10); break; default: if (vtmp < 10) { zfd.vPlaneEffect = 0; zfd.hPlaneEffect = 0; } } if (iRAND (5) != 0) zfd.noisify = 0; else { zfd.noisify = iRAND (2) + 1; lockvar *= 2; } if (zfd.mode == AMULETTE_MODE) { zfd.vPlaneEffect = 0; zfd.hPlaneEffect = 0; zfd.noisify = 0; } if ((zfd.middleX == 1) || (zfd.middleX == resolx - 1)) { zfd.vPlaneEffect = 0; zfd.hPlaneEffect = iRAND (2) ? 0 : zfd.hPlaneEffect; } if (newvit < zfd.vitesse) // on accelere { pzfd = &zfd; if (((newvit < STOP_SPEED - 7) && (zfd.vitesse < STOP_SPEED - 6) && (cycle % 3 == 0)) || (iRAND (40) == 0)) { zfd.vitesse = STOP_SPEED - iRAND (2) + iRAND (2); zfd.reverse = !zfd.reverse; } else { zfd.vitesse = (newvit + zfd.vitesse * 7) / 8; } lockvar += 50; } } if (lockvar > 150) { switchIncr = SWITCHINCR; switchMult = 1.0f; } } // mode mega-lent if (iRAND (700) == 0) { /* * printf ("coup du sort...\n") ; */ pzfd = &zfd; zfd.vitesse = STOP_SPEED - 1; zfd.pertedec = 8; zfd.sqrtperte = 16; goomvar = 1; lockvar += 50; switchIncr = SWITCHINCR; switchMult = 1.0f; } } /* * gros frein si la musique est calme */ if ((speedvar < 1) && (zfd.vitesse < STOP_SPEED - 4) && (cycle % 16 == 0)) { pzfd = &zfd; zfd.vitesse += 3; zfd.pertedec = 8; zfd.sqrtperte = 16; goomvar = 0; } /* * baisser regulierement la vitesse... */ if ((cycle % 73 == 0) && (zfd.vitesse < STOP_SPEED - 5)) { pzfd = &zfd; zfd.vitesse++; } /* * arreter de decrémenter au bout d'un certain temps */ if ((cycle % 101 == 0) && (zfd.pertedec == 7)) { pzfd = &zfd; zfd.pertedec = 8; zfd.sqrtperte = 16; } /* * Permet de forcer un effet. */ if ((forceMode > 0) && (forceMode <= NB_FX)) { pzfd = &zfd; pzfd->mode = forceMode - 1; } if (forceMode == -1) { pzfd = NULL; } /* * Changement d'effet de zoom ! */ if (pzfd != NULL) { static int exvit = 128; int dif; nombreCDDC = 0; switchIncr = SWITCHINCR; dif = zfd.vitesse - exvit; if (dif < 0) dif = -dif; if (dif > 2) { switchIncr *= (dif + 2) / 2; } exvit = zfd.vitesse; switchMult = 1.0f; if (((accelvar > goomlimit) && (totalgoom < 2)) || (forceMode > 0)) { switchIncr = 0; switchMult = SWITCHMULT; } } else { if (nombreCDDC > TIME_BTW_CHG) { pzfd = &zfd; nombreCDDC = 0; } else nombreCDDC++; } #ifdef VERBOSE if (pzfd) { printf ("GOOM: pzfd->mode = %d\n", pzfd->mode); } #endif // Zoom here ! zoomFilterFastRGB (p1 + c_offset, p2 + c_offset, pzfd, resolx, c_resoly, switchIncr, switchMult); /* * Affichage tentacule */ // if (curGState->drawTentacle) if (goomlimit!=0) tentacle_update(p2 + c_offset, p1 + c_offset, resolx, c_resoly, data, (float)accelvar/goomlimit, curGState->drawTentacle); else tentacle_update(p2 + c_offset, p1 + c_offset, resolx, c_resoly, data,0.0f, curGState->drawTentacle); /* * Affichage de texte */ { static char title[1024]; static int displayTitle = 0; char text[255]; /* * Le fps */ if (fps > 0) { int i; if (speedvar>0) { for (i=0;i0) { for (i=0;i 0) { sprintf (text, "%2.f fps", fps); goom_draw_text (p1 + c_offset,resolx,c_resoly, 10, 24, text, 1, 0); } /* * Le titre */ if (songTitle != NULL) { sprintf (title, songTitle); // la flemme d'inclure string.h :) displayTitle = 200; } if (displayTitle) { goom_draw_text (p1 + c_offset,resolx,c_resoly, resolx / 2, c_resoly / 2 + 7, title, ((float) (190 - displayTitle) / 10.0f), 1); displayTitle--; if (displayTitle < 4) goom_draw_text (p2 + c_offset,resolx,c_resoly, resolx / 2, c_resoly / 2 + 7, title, ((float) (190 - displayTitle) / 10.0f), 1); } } /* * Gestion du Scope */ /* * arret demande */ if ((stop_lines & 0xf000)||(!curGState->drawScope)) { float param1, param2, amplitude; int couleur; int mode; choose_a_goom_line (¶m1, ¶m2, &couleur, &mode, &litude,1); couleur = GML_BLACK; goom_lines_switch_to (gmline1, mode, param1, amplitude, couleur); goom_lines_switch_to (gmline2, mode, param2, amplitude, couleur); stop_lines &= 0x0fff; } /* * arret aleatore.. changement de mode de ligne.. */ if (lineMode != DRAWLINES) { lineMode--; if (lineMode == -1) lineMode = 0; } else if ((cycle%80==0)&&(iRAND(5)==0)&&lineMode) lineMode--; if ((cycle % 120 == 0) && (iRAND (4) == 0) && (curGState->drawScope)) { if (lineMode == 0) lineMode = DRAWLINES; else if (lineMode == DRAWLINES) { float param1, param2, amplitude; int couleur1,couleur2; int mode; lineMode--; choose_a_goom_line (¶m1, ¶m2, &couleur1, &mode, &litude,stop_lines); couleur2 = 5-couleur1; if (stop_lines) { stop_lines--; if (iRAND(2)) couleur2=couleur1 = GML_BLACK; } goom_lines_switch_to (gmline1, mode, param1, amplitude, couleur1); goom_lines_switch_to (gmline2, mode, param2, amplitude, couleur2); } } /* * si on est dans un goom : afficher les lignes... */ if ((lineMode != 0) || (agoom > 15)) { gmline2->power = gmline1->power; goom_lines_draw (gmline1, data[0], p2 + c_offset); goom_lines_draw (gmline2, data[1], p2 + c_offset); if (((cycle % 121) == 9) && (iRAND (3) == 1) && ((lineMode == 0) || (lineMode == DRAWLINES))) { float param1, param2, amplitude; int couleur1,couleur2; int mode; choose_a_goom_line (¶m1, ¶m2, &couleur1, &mode, &litude, stop_lines); couleur2 = 5-couleur1; if (stop_lines) { stop_lines--; if (iRAND(2)) couleur2=couleur1 = GML_BLACK; } goom_lines_switch_to (gmline1, mode, param1, amplitude, couleur1); goom_lines_switch_to (gmline2, mode, param2, amplitude, couleur2); } } return_val = p1; tmp = p1; p1 = p2; p2 = tmp; // affichage et swappage des buffers.. cycle++; // toute les 2 secondes : vérifier si le taux de goom est correct // et le modifier sinon.. if (!(cycle % 64)) { if (speedvar<1) goomlimit /= 2; if (totalgoom > 4) { goomlimit++; } if (totalgoom > 7) { goomlimit*=4/3; goomlimit+=2; } if ((totalgoom == 0) && (goomlimit > 1)) goomlimit--; if ((totalgoom == 1) && (goomlimit > 1)) goomlimit--; totalgoom = 0; } return return_val; } void goom_close (void) { if (pixel != NULL) free (pixel); if (back != NULL) free (back); pixel = back = NULL; RAND_CLOSE (); release_ifs (); goom_lines_free (&gmline1); goom_lines_free (&gmline2); tentacle_free(); } void choose_a_goom_line (float *param1, float *param2, int *couleur, int *mode, float *amplitude, int farparm) { *mode = iRAND (3); *amplitude = 1.0f; switch (*mode) { case GML_CIRCLE: if (farparm) { *param1 = *param2 = 0.47f; *amplitude = 0.8f; break; } if (iRAND (3) == 0) { *param1 = *param2 = 0; *amplitude = 3.0f; } else if (iRAND (2)) { *param1 = 0.40f * c_resoly; *param2 = 0.22f * c_resoly; } else { *param1 = *param2 = c_resoly * 0.35; } break; case GML_HLINE: if (iRAND (4) || farparm) { *param1 = c_resoly / 7; *param2 = 6.0f * c_resoly / 7.0f; } else { *param1 = *param2 = c_resoly / 2.0f; *amplitude = 2.0f; } break; case GML_VLINE: if (iRAND (3) || farparm) { *param1 = resolx / 7.0f; *param2 = 6.0f * resolx / 7.0f; } else { *param1 = *param2 = resolx / 2.0f; *amplitude = 1.5f; } break; } *couleur = iRAND (6); } void goom_set_font (int ***chars, int *width, int *height) { if (chars == NULL) return ; // font_chars = chars; // font_width = width; // font_height = height; // tester les fonts.. } /* * Met a jour l'affichage du message defilant */ void update_message (char *message) { static int nbl; static char msg2 [0x800]; static int affiche = 0; static int longueur; int fin = 0; if (message) { int i=1,j=0; sprintf (msg2,message); for (j=0;msg2[j];j++) if (msg2[j]=='\n') i++; nbl = i; affiche = resoly + nbl * 25 + 105; longueur = strlen (msg2); } if (affiche) { int i = 0; char *msg=malloc(longueur+1); char *ptr = msg; int pos; float ecart; message = msg; sprintf (msg,msg2); while (!fin) { while (1) { if (*ptr == 0) { fin = 1; break; } if (*ptr == '\n') { *ptr = 0; break; } ++ptr; } pos = affiche - (nbl-i)*25; pos += 6.0*(cos((double)pos/20.0)); pos -= 80; ecart = (1.0+2.0*sin((double)pos/20.0)); if ((fin) && (2 * pos < (int)resoly)) pos = (int)resoly / 2; pos += 7; goom_draw_text(p1 + c_offset,resolx,c_resoly, resolx/2, pos, message, ecart, 1); message = ++ptr; i++; } affiche --; free (msg); } }