Mis à jour le jeudi 31 octobre 2013
  • 4 heures
  • Facile
Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Introduction du cours

Salut à tous!

Vous avez remarqué que la SDL par défaut ne propose que des fonctionnalités de bas niveau. Lorsque j'ai codé plusieurs de mes projets, j'ai eu besoin de tracer des lignes, etc. Je me suis retrouvé à coder par moi-même pas mal de fonctions géométriques de base car je n'ai pas trouvé de bibliothèque qui permette directement de le faire (mis à part OpenGL, mais c'est un peu violent si on veut juste faire un trait ! :lol: ).

Alors, vous allez me dire "Pour tracer un trait, 2 secondes suffisent !", ce qui n'est pas faux (quoique… ^^ ). Mais là, l'intérêt est que le tout est anti-aliasé / anticrénelé:magicien:!

Même si le fait de les coder m'a aidé à progresser, franchement c'est beaucoup de galère ; alors, plutôt que de garder ce travail uniquement pour moi, je vais vous le présenter ici.

Je n'ai pas réussi à faire quelque chose d'efficace pour tracer des arcs de cercle (pour l'instant), donc si quelqu'un y arrive, je serai plus qu'heureux de l'ajouter ici, afin de compléter la bibliothèque !

L'anti-aliasing

Dans cette partie d'introduction, nous allons voir le principe de l'anti-aliasing.

Avant

Image utilisateur

On voit clairement un effet d'escalier sur les traits. Plus on se rapproche de 0° ou de 90°, plus c'est flagrant… Et c'est pas beau ! Voyons comment régler ça :

Après

Image utilisateur

Là, si vous vous approchez un peu de votre écran, vous voyez qu'au bord des escaliers, il y a une sorte de dégradé… c'est ça l'anti-aliasing (ou anticrénelage) !

Le problème de crénelage vient du fait qu'un écran d'ordinateur présente les images de manière discrète et non continue, donc quand la ligne ne passe pas exactement sur un pixel mais entre 2, la couleur du trait est appliquée sur 1 des 2 pixels uniquement.

Pour empêcher cela, pour une droite de 1 px de large, on trace toujours 2 pixels de large et on va répartir la couleur de la droite et du fond entre ces 2 pixels.

Image utilisateur

Par exemple, si l'on souhaite placer un pixel noir sur un fond blanc dans le repère (x;y) à la position (5;3.48), on va placer :

  • un pixel à la position (5;3) avec 48 % de noir et 52 % (100 % moins 48 %) de blanc => 100 % de couleur ;

  • un pixel à la position (5;4) avec 52 % (100 % moins 48 %) de noir et 48 % de blanc => 100 % de couleur.

On a bien 100 % de noir et 100 % de blanc au total sur les 2 pixels, ainsi que 100 % de couleur par pixel. On a bien la même "quantité" de blanc et de noir que celle que l'on aurait si la ligne était passée sur un seul pixel et qu'on avait laissé le pixel d'à côté blanc. On a donc toujours bien l'illusion que la droite fait un pixel de large.

SDL et les pixels

Nous allons à présent voir comment travailler les pixels de votre fenêtre SDL à la main. Tout se résume dans ce code :

*((Uint32*)(map->pixels) + x + y * map->w) = color;

map étant la surface, x la position en x, et y, bien évidemment, la position en y (voir le cours de M@teo si besoin). En gros, dans le SDL, une surface est un grand tableau de 1 ligne et "largeur*hauteur" colonnes, où pour chaque case on associe une couleur (codée sur 32 bits). Pour récupérer la couleur en x;y, on doit donc aller à la colonne x + y*largeur (car elle n'est pas stockée dans une matrice 2D de dimensions x;y !).

Le code, que j'ai donné en haut, set la valeur de couleur au pixel concerné. On pourrait faire l'inverse pour récupérer la couleur :

color_ptr = *((Uint32*)(map->pixels) + x + y * map->w);
color = *color_ptr;

… mais généralement, on souhaite avoir les composantes RGBA de la couleur, on préfèrera donc comme suit :

SDL_GetRGBA(*((Uint32 *)map->pixels + x + y * map->w),map->format,r,g,b,a);

Au final, on obtient les routines suivantes pour interagir facilement sur les pixels :

// Size of a point
#define POINT_SIZE 4

// Sets a pixel on x,y position on a color on the map:
// If the position is out of map, nothing is done
// Returns: void
void setPixel(int x, int y, Uint32 color, SDL_Surface *map)
{
  if(x>0 && y>0 && x<map->w && y<map->h)
    *((Uint32*)(map->pixels) + x + y * map->w) = color;
}

// Getter for a pixel color on x,y position on the map
// The r, g, b, a pointer are set to the red, green, blue and alpha value of the pixel
// If the position is out of map, nothing is done
// Returns: void
void getPixelColor(int x, int y, SDL_Surface *map, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
{
  if(x>0 && y>0 && x<map->w && y<map->h)
    SDL_GetRGBA(*((Uint32 *)map->pixels + x + y * map->w),map->format,r,g,b,a);
}

// Sets a point on x,y position on the map on a color, of the map
// Point's size if 2*POINT_SIZE
// If the position is out of map, nothing is done
// Returns: void
void setPoint(int x, int y, Uint32 color, SDL_Surface *map)
{
  int i,j;

  for(i=-POINT_SIZE;i<=POINT_SIZE;i++)
      for(j=-POINT_SIZE;j<=POINT_SIZE;j++)
            setPixel(x+i, y+j, color, map);
}

Tracer une droite anti-aliasée

On va enfin appliquer le principe d'anticrénelage que l'on a vu précédemment pour tracer une droite.

Le petit point épineux que je vous avais caché jusque-là (eh oui, sinon cela serait bien trop simple…), c'est que la méthode que j'ai présentée en haut (sur 2 pixels), ne marche que pour une pente inférieure à 45° ! :-°

Pourquoi ? Eh bien regardez avec attention l'image que j'avais présentée (je la remets) :

Image utilisateur

La droite a une pente < 45° et les 2 pixels sont verticaux…
Si la pente est > 45° (rotation de 90° de mon image), mes 2 pixels devront être horizontaux !

D'où les 2 cas suivants pour notre droite :

void line_trace(int x1, int y1, int x2, int y2, Uint32 color, SDL_Surface *map)
{
  int xd, yd;

  xd = (x2-x1);
  yd = (y2-y1);

  if (abs(xd) > abs(yd)) // The line angle is smaller than 45°
  {
    ...
  }
  else
  {
    ...
  }

Pour anti-aliaser, vous avez vu qu'il faut la partie après la virgule pour en déduire le pourcentage de couleur de chaque pixel… Pour éviter de réécrire plusieurs fois le même code, voici quelques petites fonctions de mise en bouche qui retournent la fraction ou 1 - la fraction (prenez-les comme telles, c'est cadeau, on va voir leur utilité dans un instant - quel suspense tout de même !).

// Switchs the values of the x and y integers
// Returns: void
void int_switch(int* x, int* y)
{
  int t = *x;
  *x = *y;
  *y = t;
}

// Returns the fractionary part of the x float
// Returns: the frav value (float) [0,1]
float frac(float x)
{
   return x - (int)x;
}

// Returns the missing part to 1 from the fract. part of the x float
// Returns: the invfrac value (float) [0,1]
float invfrac(float x)
{
   return 1 - frac(x);
}

Et enfin, la partie à proprement parler d'anti-aliasing, où il va vous falloir :

  • récupérer les composantes de la couleur du trait ;

  • récupérer les composantes de la couleur du fond actuel (x;y) ;

  • calculer la couleur en fonction de chacun des pourcentages ;

  • blitter les 2 pixels.

Récupérer les composantes de la couleur du trait

On a vu la fonction dans l'intro, mais pour ceux qui auraient déja oublié, il s'agit de SDL_GetRGBA…

// Getting the r,g,b,a values of the specified color
SDL_GetRGBA(color,map->format,&r1,&g1,&b1,&a1);

Récupérer les composantes de la couleur du fond actuel (x;y)

On a créé la fonction juste avant (si, si : pour ceux qui dorment dans le fond, dans l'intro !), donc jusque-là tout va bien !

// Getting the color of current (background) pixel
getPixelColor(x, (int)yf, map, &r2,&g2,&b2,&a2);

Calcul de la couleur en fonction de chacun des pourcentages + "blittage"

Comme nous l'avons vu sur le petit dessin, il faut utiliser 2 pixels côte à côte. Prenons un exemple : mon pixel devrait tomber à une position en y de 56.38 (x quelconque), on va donc travailler avec les pixels 56 et 57.

Sur mon pixel 56, je vais appliquer 38 % (soit 0.38 en channel alpha) de couleur du trait et, comme il faut bien compléter à 100 %, 1-0.38 = 0.62 de couleur de fond. Puis on mixe les 2. Pour mixer les 2, on utilise une fonction de la SDL qui à partir des composantes RGBA donne la couleur (l'inverse de SDL_GetRGBA), qui est… tada ! : SDL_MapRGBA (eh oui, même pas SDL_SetRGBA… Comme quoi, même en informatique, y a du suspense !).

Sur mon pixel 57, je vais appliquer 1-0.38 soit 0.62 de couleur du trait (comme ça, j'ai toujours 100 % de la couleur du trait) et, comme il faut bien compléter à 100 % la couleur du pixel , 1-0.62 = 0.38 de couleur de fond. Puis on mixe les 2.

Avec une formule mathématique, on aurait :

Citation : Mathématiques

$frac_y = y - E(y)$
(partie fractionnaire, avec E() partie entière !).

$couleur(x;E(y)) = couleur1(x;E(y)).frac_y+ couleur2(x;E(y)).(1-frac_y)$
(la fraction de la couleur 1 et le complément pour la couleur 2).

$couleur(x;E(y)+1) = couleur1(x;E(y)+1).(1-frac_y)+ couleur2(x;E(y)+1).frac_y$
(le complément de la couleur 1 utilisée ci-dessus puis le complément pour la couleur 2).

Et pour finir, on set les 2 pixels (avec la fonction maison codée avant !).

Bon : cette fois, je ne cache pas le code, car c'est un peu plus compliqué ! ;)

// For the antialising 2 pixels are drawn, one on top (x,y+1), the other below (x,y)
// The color is a mix of:
// - the color of background
// - the color of the line
// The amount of each color (bg & line color), on the 2 pixels is 100% (e.g. 10% on one, 90% on the other)

r=(Uint8)(frac(yf)*r1+invfrac(yf)*r2);
g=(Uint8)(frac(yf)*g1+invfrac(yf)*g2);
b=(Uint8)(frac(yf)*b1+invfrac(yf)*b2);
a=(Uint8)(frac(yf)*a1+invfrac(yf)*a2);
colorAA1=SDL_MapRGBA(map->format,r,g,b,a); // Color for pixel one (x,y+1)

r=(Uint8)(frac(yf)*r2+invfrac(yf)*r1);
g=(Uint8)(frac(yf)*g2+invfrac(yf)*g1);
b=(Uint8)(frac(yf)*b2+invfrac(yf)*b1);
a=(Uint8)(frac(yf)*a2+invfrac(yf)*a1);
colorAA2=SDL_MapRGBA(map->format,r,g,b,a); // Color for the 2nd pixel (x,y)

// Blitting
setPixel(x, (int)yf, colorAA2, map);
setPixel(x, (int)yf+1, colorAA1, map);

À présent, reste à trouver la quantité de couleur (le frac(yf) dans le bout de code au-dessus) ; c'est le 0.38 dans l'exemple… En fait, tout simplement, on part de notre condition de départ, à savoir x = x1 et y = y1, et, dans la boucle suivante, on cherche à savoir quelles coordonnées devront avoir ces points…

Pour x, c'est facile, c'est x+1, mais pour y ? Toujours la dérivée ! y => y+grad, où grad est la pente.

Il ne reste plus qu'à coder le tout !

Vous avez cherché ? Alors voilà, au final, en bouclant, ce qu'on obtient.

// Traces an antialiased line from x1,y1 to x2,y2 on the specified color, on the map, with the dotted method
// Returns: void
void line_trace(int x1, int y1, int x2, int y2, Uint32 color, SDL_Surface *map, int dotted)
{
  int xd, yd, x, y, to_dot = 0;
  float grad,xf,yf;
  Uint8 r1,g1,b1,a1,r2,g2,b2,a2,r,g,b,a;
  Uint32 colorAA1,colorAA2;

  // Getting the r,g,b,a values of the specified color
  SDL_GetRGBA(color,map->format,&r1,&g1,&b1,&a1);

  xd = (x2-x1);
  yd = (y2-y1);

  if (abs(xd) > abs(yd)) // The line angle is smaller than 45°
  {
    if (x1 > x2) // Because of the FOR, going from the smallest to the greatest value
    {
      int_switch(&x1, &x2);
      int_switch(&y1, &y2);
      xd = (x2-x1);
      yd = (y2-y1);
    }

    grad = (float)yd/(float)xd; // Line slope
    yf = (float)y1+grad;

    // Start and arrival points
    setPixel(x1, y1, color, map);
    setPixel(x2, y2, color, map);

    for (x = x1+1; x <= x2; x++)
    {
     if((!dotted || (to_dot%dotted)) && x>0 && x<map->w && yf>0 && yf<map->h) // If not outside of the map surface
     {
         // Getting the color of current (background) pixel
         getPixelColor(x, (int)yf, map, &r2,&g2,&b2,&a2);

         // For the antialising 2 pixels are drawn, one one top (x,y+1), the other below (x,y)
         // The color is a mix of:
         // - the color of background
         // - the color of the line
         // The amount of each color (bg & line color), on the 2 pixels is 100% (e.g. 10% on one, 90% on the other)

         r=(Uint8)(frac(yf)*r1+invfrac(yf)*r2);
         g=(Uint8)(frac(yf)*g1+invfrac(yf)*g2);
         b=(Uint8)(frac(yf)*b1+invfrac(yf)*b2);
         a=(Uint8)(frac(yf)*a1+invfrac(yf)*a2);
         colorAA1=SDL_MapRGBA(map->format,r,g,b,a); // Color for pixel one (x,y+1)

         r=(Uint8)(frac(yf)*r2+invfrac(yf)*r1);
         g=(Uint8)(frac(yf)*g2+invfrac(yf)*g1);
         b=(Uint8)(frac(yf)*b2+invfrac(yf)*b1);
         a=(Uint8)(frac(yf)*a2+invfrac(yf)*a1);
         colorAA2=SDL_MapRGBA(map->format,r,g,b,a); // Color for the 2nd pixel (x,y)

         // Blitting
         setPixel(x, (int)yf, colorAA2, map);
         setPixel(x, (int)yf+1, colorAA1, map);
     }
     to_dot++;

     yf += grad; // Go to next point (x => x+1 / yf => yf + grad)
    }
  }

 else // Same thing if the line angle is greater the 45°
  {
    if (y1 > y2)
    {
      int_switch(&x1, &x2);
      int_switch(&y1, &y2);
      xd = (x2-x1);
      yd = (y2-y1);
    }

    grad = (float)xd/(float)yd;
    xf = (float)x1+grad;

    setPixel(x1, y1, color, map);
    setPixel(x2, y2, color, map);

    for (y = y1+1; y <= y2; y++)
    {
     if((!dotted || (to_dot%dotted)) && xf>0 && xf<map->w && y>0 && y<map->h)
     {
         getPixelColor((int)xf, y, map, &r2,&g2,&b2,&a2);

         r=(Uint8)(frac(xf)*r1+invfrac(xf)*r2);
         g=(Uint8)(frac(xf)*g1+invfrac(xf)*g2);
         b=(Uint8)(frac(xf)*b1+invfrac(xf)*b2);
         a=(Uint8)(frac(xf)*a1+invfrac(xf)*a2);
         colorAA1=SDL_MapRGBA(map->format,r,g,b,a);

         r=(Uint8)(frac(xf)*r2+invfrac(xf)*r1);
         g=(Uint8)(frac(xf)*g2+invfrac(xf)*g1);
         b=(Uint8)(frac(xf)*b2+invfrac(xf)*b1);
         a=(Uint8)(frac(xf)*a2+invfrac(xf)*a1);
         colorAA2=SDL_MapRGBA(map->format,r,g,b,a);

         setPixel((int)xf, y, colorAA2, map);
         setPixel((int)xf+1, y, colorAA1, map);
     }
     to_dot++;

     xf += grad;
    }
  }
}

À noter que j'ai rajouté le dotted, qui permet de faire des pointillés, etc. Pour faire des pointillés, il suffit de ne pas dessiner le trait par moments ! Pour cela, on dessine uniquement lorsque "to_dot%dotted" (logique booléenne).

J'ai également rajouté une vérification pour ne dessiner que dans la surface et non pas à l'extérieur (pour cela, on utilise map->w et map->h qui renvoient la largeur et la hauteur). Il vous faut rajouter ces constantes dans votre .h :

#define FULL   0
#define DOTTED 2
#define DASHED 5

Vous pouvez bien sûr les changer selon vos besoins…

Tracer un cercle anti-aliasé

Bon : toujours un peu plus dur, le cercle anti-aliasé. Pour l'instant, intéressons-nous uniquement à un demi-cercle. Toujours par rapport à cette histoire de dérivée, on remarque que l'on va devoir tracer uniquement des quarts de cercle, entre 45° et 135° (le "haut" d'un cercle), car au-delà, la dérivée vaut plus de 1 (en valeur absolue, donc entre 1 et -1).

Image utilisateur

On s'intéresse à la partie en couleur, car la pente de la tangente varie entre -1 et 1.
Pour un cercle de centre (x;y) et de rayon R, on va chercher à avoir l'équation des points à blitter (intersection des droites en rouge avec le cercle) en fonction de l'angle en rouge (qui va varier de 45° à 135°).

Image utilisateur

On a :

x_cercle = x + R*sin(angle-90°);
y_cercle = y + R*cos(angle-90°);

On a bien, à angle = 90°, y_cercle = y (verticale) et x_cercle = x + R.

Mais il y a un problème : x_cercle et y_cercle ne sont pas entiers… Or il faudrait par exemple à chaque boucle incrémenter x_cercle et en déduire y_cercle (comme pour la droite, où l'on avait calculé la pente). On va donc poser R*sin(angle-90°) = r. On va maintenant non plus faire varier l'angle, mais r.

Image utilisateur

On a maintenant r qui varie de R*sin(45°-90°) à R*sin(135°-90°) pour angle variant de 45° à 135° (on remarque tout de suite qu'une boucle for semble particulièrement bien adaptée).

Comme ça, on en déduit :

x_cercle = x + r;
y_cercle = y + R*cos(angle-90°)/R*sin(angle-90°)*r = r*tan(angle-90°);

C'est déjà bien mieux, car on peut incrémenter x_cercle (via r) et en déduire y_cercle, mais il faut calculer une tangente à tous les coups ! On va donc ruser.

Image utilisateur

On remarque que r*tan(…) est également égal à sqrt(R²-r²), car c'est le 3e côté d'un triangle (Pythagore). On a donc au final (et on voit que l'on a finalement ni tangente ni autres gros calculs bien lourds !) :

x_cercle = x + r;
y_cercle = y + sqrt(R²-r²)

À partir de là, on a réussi à revenir à une solution proche de la droite, avec une incrémentation selon une seule variable (ici r, dans la droite y). Après tout, quand on a déjà fait du bon boulot, autant faire un copier-coller ! Et en plus, pas besoin de vous réexpliquer comment faire les points anti-aliasés, c'est pareil… Bon, ben j'ai plus qu'à vous donner le code alors… La seule petite particularité, c'est qu'il faut faire 4 quarts de cercle, je vous laisse chercher (ou regarder - pour les fainéants :p) comment.

// Traces an antialiased circle with the specified raduis R on the center x,y on the specified color, on the map, with the dotted method
// Returns: void
void circle_trace(int x, int y, int R, Uint32 color, SDL_Surface *map, int dotted)
{
    int raduis, to_dot;
    float real_y;
    float real_x;

    Uint8 r1,g1,b1,a1,r2,g2,b2,a2,r,g,b,a;
    Uint32 colorAA1,colorAA2;

    SDL_GetRGBA(color,map->format,&r1,&g1,&b1,&a1);

    R = abs(R); // To be sure that R>0 (or with the FOR, we'll get some problems!)

    // NB: From -R*0.71 to R*0.71 because we only make 90° of the circle (from -45° to 45°)
    //     and the sin(45°) = 0.707 (=sqrt(2)/2)
    //     The same algorithme is used for the 4 quarters of the circle

    // TOP FOR X
    for(raduis=-(int)(R*0.71); raduis<=(int)(R*0.71); raduis++)
    {
        real_y = y+sqrt(R*R-raduis*raduis); // Go to next point

        if((!dotted || (to_dot%dotted)) && x>0 && x<map->w && y>0 && y<map->h) // If not outside of the map surface
        {
             // For the antialising 2 pixels are drawn, one one top (x,y+1), the other below (x,y)
             // The color is a mix of:
             // - the color of background
             // - the color of the line
             // The amount of each color (bg & line color), on the 2 pixels is 100% (e.g. 10% on one, 90% on the other)
            getPixelColor(x-raduis, (int)real_y, map, &r2,&g2,&b2,&a2);

            r=(Uint8)(frac(real_y)*r1+invfrac(real_y)*r2);
            g=(Uint8)(frac(real_y)*g1+invfrac(real_y)*g2);
            b=(Uint8)(frac(real_y)*b1+invfrac(real_y)*b2);
            a=(Uint8)(frac(real_y)*a1+invfrac(real_y)*a2);
            colorAA1=SDL_MapRGBA(map->format,r,g,b,a);

            r=(Uint8)(frac(real_y)*r2+invfrac(real_y)*r1);
            g=(Uint8)(frac(real_y)*g2+invfrac(real_y)*g1);
            b=(Uint8)(frac(real_y)*b2+invfrac(real_y)*b1);
            a=(Uint8)(frac(real_y)*a2+invfrac(real_y)*a1);
            colorAA2=SDL_MapRGBA(map->format,r,g,b,a);

            setPixel(x-raduis, (int)real_y, colorAA2, map);
            setPixel(x-raduis, (int)real_y+1, colorAA1, map);
        }
        to_dot++;
    }

    // BOTTOM FOR X
    for(raduis=-(int)(R*0.71); raduis<=(int)(R*0.71); raduis++)
    {
        real_y = y-sqrt(R*R-raduis*raduis);

        if((!dotted || (to_dot%dotted)) && x>0 && x<map->w && y>0 && y<map->h)
        {
            getPixelColor(x-raduis, (int)real_y, map, &r2,&g2,&b2,&a2);

            r=(Uint8)(frac(real_y)*r1+invfrac(real_y)*r2);
            g=(Uint8)(frac(real_y)*g1+invfrac(real_y)*g2);
            b=(Uint8)(frac(real_y)*b1+invfrac(real_y)*b2);
            a=(Uint8)(frac(real_y)*a1+invfrac(real_y)*a2);
            colorAA1=SDL_MapRGBA(map->format,r,g,b,a);

            r=(Uint8)(frac(real_y)*r2+invfrac(real_y)*r1);
            g=(Uint8)(frac(real_y)*g2+invfrac(real_y)*g1);
            b=(Uint8)(frac(real_y)*b2+invfrac(real_y)*b1);
            a=(Uint8)(frac(real_y)*a2+invfrac(real_y)*a1);
            colorAA2=SDL_MapRGBA(map->format,r,g,b,a);

            setPixel(x-raduis, (int)real_y, colorAA2, map);
            setPixel(x-raduis, (int)real_y+1, colorAA1, map);
        }
        to_dot++;
    }

    // TOP FOR Y
    for(raduis=-(int)(R*0.71); raduis<=(int)(R*0.71); raduis++)
    {
        real_x = x+sqrt(R*R-raduis*raduis);

        if((!dotted || (to_dot%dotted)) && x>0 && x<map->w && y>0 && y<map->h)
        {
            getPixelColor((int)real_x, y-raduis, map, &r2,&g2,&b2,&a2);

            r=(Uint8)(frac(real_x)*r1+invfrac(real_x)*r2);
            g=(Uint8)(frac(real_x)*g1+invfrac(real_x)*g2);
            b=(Uint8)(frac(real_x)*b1+invfrac(real_x)*b2);
            a=(Uint8)(frac(real_x)*a1+invfrac(real_x)*a2);
            colorAA1=SDL_MapRGBA(map->format,r,g,b,a);

            r=(Uint8)(frac(real_x)*r2+invfrac(real_x)*r1);
            g=(Uint8)(frac(real_x)*g2+invfrac(real_x)*g1);
            b=(Uint8)(frac(real_x)*b2+invfrac(real_x)*b1);
            a=(Uint8)(frac(real_x)*a2+invfrac(real_x)*a1);
            colorAA2=SDL_MapRGBA(map->format,r,g,b,a);

            setPixel((int)real_x, (y-raduis), colorAA2, map);
            setPixel((int)real_x+1, (y-raduis), colorAA1, map);
        }
        to_dot++;
    }

    // BOTTOM FOR Y
    for(raduis=-(int)(R*0.71); raduis<=(int)(R*0.71); raduis++)
    {
        real_x = x-sqrt(R*R-raduis*raduis);

        if((!dotted || (to_dot%dotted)) && x>0 && x<map->w && y>0 && y<map->h)
        {
            getPixelColor((int)real_x, y-raduis, map, &r2,&g2,&b2,&a2);

            r=(Uint8)(frac(real_x)*r1+invfrac(real_x)*r2);
            g=(Uint8)(frac(real_x)*g1+invfrac(real_x)*g2);
            b=(Uint8)(frac(real_x)*b1+invfrac(real_x)*b2);
            a=(Uint8)(frac(real_x)*a1+invfrac(real_x)*a2);
            colorAA1=SDL_MapRGBA(map->format,r,g,b,a);

            r=(Uint8)(frac(real_x)*r2+invfrac(real_x)*r1);
            g=(Uint8)(frac(real_x)*g2+invfrac(real_x)*g1);
            b=(Uint8)(frac(real_x)*b2+invfrac(real_x)*b1);
            a=(Uint8)(frac(real_x)*a2+invfrac(real_x)*a1);
            colorAA2=SDL_MapRGBA(map->format,r,g,b,a);

            setPixel((int)real_x, (y-raduis), colorAA2, map);
            setPixel((int)real_x+1, (y-raduis), colorAA1, map);
        }
        to_dot++;
    }
}

Autres fonctions & code complet (bonus)

Voilà le petit bonus pour avoir bien travaillé :le code complet de la bibliothèque (dont d'autres fonctions : droites perpendiculaires, parallèles, ect.

tracer.h

// Jean-Charles BADOCHE - 2010
// http://astro.estaca.free.fr

#ifndef __TRACER__
#define __TRACER__

// Dotted methods
#define FULL 0
#define DOTTED 2
#define DASHED 5

// Size of a point
#define POINT_SIZE 4

// Sets a pixel on x,y position on a color on the map:
// If the position is out of map, nothing is done
// Returns: void
void setPixel(int, int, Uint32, SDL_Surface*);

// Getter for a pixel color on x,y position on the map
// The r, g, b, a pointer are set to the red, green, blue and alpha value of the pixel
// If the position is out of map, nothing is done
// Returns: void
void getPixelColor(int, int, SDL_Surface*, Uint8*, Uint8*, Uint8*, Uint8*);

// Sets a pixel on x,y position on a color on the map:
// y is float, so antialising is done (pixel position x,y & x,y+1)
// If the position is out of map, nothing is done
// Returns: void
void setAAPixel_X_Y(int, float, Uint32, SDL_Surface*);

// Sets a pixel on x,y position on a color on the map:
// x is float, so antialising is done (pixel position x,y & x+1,y)
// If the position is out of map, nothing is done
// Returns: void
void setAAPixel_Y_X(float, int, Uint32, SDL_Surface*);

// Sets a point on x,y position on the map on a color, of the map
// If the position is out of map, nothing is done
// Returns: void
void setPoint(int, int, Uint32, SDL_Surface*);

// Switchs the values of the x and y integers
// Returns: void
void int_switch(int*, int*);

// Returns the fractionary part of the x float
// Returns: the frav value (float) [0,1]
float frac(float);

// Returns the missing part to 1 from the fract. part of the x float
// Returns: the invfrac value (float) [0,1]
float invfrac(float);

// Traces an antialiased line from x1,y1 to x2,y2 on the specified color, on the map, with the dotted method
// Returns: void
void line_trace(int, int, int, int, Uint32, SDL_Surface*, int);

// Traces an antialiased circle with the specified raduis R on the center x,y on the specified color, on the map, with the dotted method
// Returns: void
void circle_trace(int, int, int, Uint32, SDL_Surface*, int);

// Traces a line perpendicular to the (x1,y1);(x2;y2) line, on point (x0,y0), on the spedicifed color, on the map surface, with the dotted method
// If x0 or y0 is UNSET, then the perpendicular line is drawn from point 2
// Length of the line is d1 in 1 direction (than direction than (x1,y1)->(x2;y2), d2 in the 2nd direction (opposite direction).
// If the d1 is UNSET, then the line is drawn on the whole half plan surface
// Same thing for d2
// Returns: void
void perdendicular_trace(int, int, int, int, int, int, int, int, Uint32, SDL_Surface*, int);

// Traces a line parallele to the (x1,y1);(x2;y2) line, on point (x0,y0), on the spedicifed color, on the map surface, with the dotted method
// If x0 or y0 is UNSET, then the parallele line is drawn from point 2
// Length of the line is d1 in 1 direction (clockwise), d2 in the 2nd direction (anticlockwise).
// If the d1 is UNSET, then the line is drawn on the whole half plan surface
// Same thing for d2
// Returns: void
void parallele_trace(int, int, int, int, int, int, int, int, Uint32, SDL_Surface*, int);

// Getter for the distance between 2 points x1,y1 & x2,y2
// Returns the distance (float)
float getDistance(int, int, int, int);

#endif // __TRACER__

tracer.c

// Jean-Charles BADOCHE - 2010
// http://astro.estaca.free.fr

#ifndef __TRACERC__
#define __TRACERC__

#include "tracer.h"

// Sets a pixel on x,y position on a color on the map:
// If the position is out of map, nothing is done
// Returns: void
void setPixel(int x, int y, Uint32 color, SDL_Surface *map)
{
  if(x>0 && y>0 && x<map->w && y<map->h)
    *((Uint32*)(map->pixels) + x + y * map->w) = color;
}

// Getter for a pixel color on x,y position on the map
// The r, g, b, a pointer are set to the red, green, blue and alpha value of the pixel
// If the position is out of map, nothing is done
// Returns: void
void getPixelColor(int x, int y, SDL_Surface *map, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
{
  if(x>0 && y>0 && x<map->w && y<map->h)
    SDL_GetRGBA(*((Uint32 *)map->pixels + x + y * map->w),map->format,r,g,b,a);
}

// Sets a pixel on x,y position on a color on the map:
// y is float, so antialising is done (pixel position x,y & x,y+1)
// If the position is out of map, nothing is done
// Returns: void
void setAAPixel_X_Y(int x, float y, Uint32 color, SDL_Surface *map)
{
    Uint8 r1,g1,b1,a1,r2,g2,b2,a2,r,g,b,a;
    Uint32 colorAA1,colorAA2;

    SDL_GetRGBA(color,map->format,&r1,&g1,&b1,&a1);
    // Getting the color of current (background) pixel
    getPixelColor(x, (int)y, map, &r2,&g2,&b2,&a2);

    // For the antialising 2 pixels are drawn, one one top (x,y+1), the other below (x,y)
    // The color is a mix of:
    // - the color of background
    // - the color of the line
    // The amount of each color (bg & line color), on the 2 pixels is 100% (e.g. 10% on one, 90% on the other)

    r=(Uint8)(frac(y)*r1+invfrac(y)*r2);
    g=(Uint8)(frac(y)*g1+invfrac(y)*g2);
    b=(Uint8)(frac(y)*b1+invfrac(y)*b2);
    a=(Uint8)(frac(y)*a1+invfrac(y)*a2);
    colorAA1=SDL_MapRGBA(map->format,r,g,b,a); // Color for pixel one (x,y+1)

    r=(Uint8)(frac(y)*r2+invfrac(y)*r1);
    g=(Uint8)(frac(y)*g2+invfrac(y)*g1);
    b=(Uint8)(frac(y)*b2+invfrac(y)*b1);
    a=(Uint8)(frac(y)*a2+invfrac(y)*a1);
    colorAA2=SDL_MapRGBA(map->format,r,g,b,a); // Color for the 2nd pixel (x,y)

    // Blitting
    setPixel(x, (int)y, colorAA2, map);
    setPixel(x, (int)y+1, colorAA1, map);
}

// Sets a pixel on x,y position on a color on the map:
// x is float, so antialising is done (pixel position x,y & x+1,y)
// If the position is out of map, nothing is done
// Returns: void
void setAAPixel_Y_X(float x, int y, Uint32 color, SDL_Surface *map)
{
    Uint8 r1,g1,b1,a1,r2,g2,b2,a2,r,g,b,a;
    Uint32 colorAA1,colorAA2;

    SDL_GetRGBA(color,map->format,&r1,&g1,&b1,&a1);
    // Getting the color of current (background) pixel
    getPixelColor((int)x, y, map, &r2,&g2,&b2,&a2);

    // For the antialising 2 pixels are drawn, one one top (x+1,y), the other below (x,y)
    // The color is a mix of:
    // - the color of background
    // - the color of the line
    // The amount of each color (bg & line color), on the 2 pixels is 100% (e.g. 10% on one, 90% on the other)
    r=(Uint8)(frac(x)*r1+invfrac(x)*r2);
    g=(Uint8)(frac(x)*g1+invfrac(x)*g2);
    b=(Uint8)(frac(x)*b1+invfrac(x)*b2);
    a=(Uint8)(frac(x)*a1+invfrac(x)*a2);
    colorAA1=SDL_MapRGBA(map->format,r,g,b,a); // Color for pixel one (x+1,y)

    r=(Uint8)(frac(x)*r2+invfrac(x)*r1);
    g=(Uint8)(frac(x)*g2+invfrac(x)*g1);
    b=(Uint8)(frac(x)*b2+invfrac(x)*b1);
    a=(Uint8)(frac(x)*a2+invfrac(x)*a1);
    colorAA2=SDL_MapRGBA(map->format,r,g,b,a); // Color for pixel one (x,y)

    setPixel((int)x, y, colorAA2, map);
    setPixel((int)x+1, y, colorAA1, map);
}

// Sets a point on x,y position on the map on a color, of the map
// Point's size if 2*POINT_SIZE
// If the position is out of map, nothing is done
// Returns: void
void setPoint(int x, int y, Uint32 color, SDL_Surface *map)
{
  int i,j;

  for(i=-POINT_SIZE;i<=POINT_SIZE;i++)
      for(j=-POINT_SIZE;j<=POINT_SIZE;j++)
            setPixel(x+i, y+j, color, map);
}

// Switchs the values of the x and y integers
// Returns: void
void int_switch(int* x, int* y)
{
  int t = *x;
  *x = *y;
  *y = t;
}

// Returns the fractionary part of the x float
// Returns: the frav value (float) [0,1]
float frac(float x)
{
   return x - (int)x;
}

// Returns the missing part to 1 from the fract. part of the x float
// Returns: the invfrac value (float) [0,1]
float invfrac(float x)
{
   return 1 - frac(x);
}

// Traces an antialiased line from x1,y1 to x2,y2 on the specified color, on the map, with the dotted method
// Returns: void
void line_trace(int x1, int y1, int x2, int y2, Uint32 color, SDL_Surface *map, int dotted)
{
  int xd, yd, x, y, to_dot = 0;
  float grad,xf,yf;
  Uint8 r1,g1,b1,a1,r2,g2,b2,a2,r,g,b,a;
  Uint32 colorAA1,colorAA2;

  // Getting the r,g,b,a values of the specified color
  SDL_GetRGBA(color,map->format,&r1,&g1,&b1,&a1);

  xd = (x2-x1);
  yd = (y2-y1);

  if (abs(xd) > abs(yd)) // The line angle is smaller than 45°
  {
    if (x1 > x2) // Because of the FOR, going from the smallest to the greatest value
    {
      int_switch(&x1, &x2);
      int_switch(&y1, &y2);
      xd = (x2-x1);
      yd = (y2-y1);
    }

    grad = (float)yd/(float)xd; // Line slope
    yf = (float)y1+grad;

    // Start and arrival points
    setPixel(x1, y1, color, map);
    setPixel(x2, y2, color, map);

    for (x = x1+1; x <= x2; x++)
    {
     if((!dotted || (to_dot%dotted)) && x>0 && x<map->w && yf>0 && yf<map->h) // If not outside of the map surface
     {
         // Getting the color of current (background) pixel
         getPixelColor(x, (int)yf, map, &r2,&g2,&b2,&a2);

         // For the antialising 2 pixels are drawn, one one top (x,y+1), the other below (x,y)
         // The color is a mix of:
         // - the color of background
         // - the color of the line
         // The amount of each color (bg & line color), on the 2 pixels is 100% (e.g. 10% on one, 90% on the other)

         r=(Uint8)(frac(yf)*r1+invfrac(yf)*r2);
         g=(Uint8)(frac(yf)*g1+invfrac(yf)*g2);
         b=(Uint8)(frac(yf)*b1+invfrac(yf)*b2);
         a=(Uint8)(frac(yf)*a1+invfrac(yf)*a2);
         colorAA1=SDL_MapRGBA(map->format,r,g,b,a); // Color for pixel one (x,y+1)

         r=(Uint8)(frac(yf)*r2+invfrac(yf)*r1);
         g=(Uint8)(frac(yf)*g2+invfrac(yf)*g1);
         b=(Uint8)(frac(yf)*b2+invfrac(yf)*b1);
         a=(Uint8)(frac(yf)*a2+invfrac(yf)*a1);
         colorAA2=SDL_MapRGBA(map->format,r,g,b,a); // Color for the 2nd pixel (x,y)

         // Blitting
         setPixel(x, (int)yf, colorAA2, map);
         setPixel(x, (int)yf+1, colorAA1, map);
     }
     to_dot++;

     yf += grad; // Go to next point (x => x+1 / yf => yf + grad)
    }
  }

 else // Same thing if the line angle is greater the 45°
  {
    if (y1 > y2)
    {
      int_switch(&x1, &x2);
      int_switch(&y1, &y2);
      xd = (x2-x1);
      yd = (y2-y1);
    }

    grad = (float)xd/(float)yd;
    xf = (float)x1+grad;

    setPixel(x1, y1, color, map);
    setPixel(x2, y2, color, map);

    for (y = y1+1; y <= y2; y++)
    {
     if((!dotted || (to_dot%dotted)) && xf>0 && xf<map->w && y>0 && y<map->h)
     {
         getPixelColor((int)xf, y, map, &r2,&g2,&b2,&a2);

         r=(Uint8)(frac(xf)*r1+invfrac(xf)*r2);
         g=(Uint8)(frac(xf)*g1+invfrac(xf)*g2);
         b=(Uint8)(frac(xf)*b1+invfrac(xf)*b2);
         a=(Uint8)(frac(xf)*a1+invfrac(xf)*a2);
         colorAA1=SDL_MapRGBA(map->format,r,g,b,a);

         r=(Uint8)(frac(xf)*r2+invfrac(xf)*r1);
         g=(Uint8)(frac(xf)*g2+invfrac(xf)*g1);
         b=(Uint8)(frac(xf)*b2+invfrac(xf)*b1);
         a=(Uint8)(frac(xf)*a2+invfrac(xf)*a1);
         colorAA2=SDL_MapRGBA(map->format,r,g,b,a);

         setPixel((int)xf, y, colorAA2, map);
         setPixel((int)xf+1, y, colorAA1, map);
     }
     to_dot++;

     xf += grad;
    }
  }
}

// Traces an antialiased circle with the specified raduis R on the center x,y on the specified color, on the map, with the dotted method
// Returns: void
void circle_trace(int x, int y, int R, Uint32 color, SDL_Surface *map, int dotted)
{
    int raduis, to_dot;
    float real_y;
    float real_x;

    Uint8 r1,g1,b1,a1,r2,g2,b2,a2,r,g,b,a;
    Uint32 colorAA1,colorAA2;

    SDL_GetRGBA(color,map->format,&r1,&g1,&b1,&a1);

    R = abs(R); // To be sure that R>0 (or with the FOR, we'll get some problems!)

    // NB: From -R*0.71 to R*0.71 because we only make 90° of the circle (from -45° to 45°)
    //     and the sin(45°) = 0.707 (=sqrt(2)/2)
    //     The same algorithme is used for the 4 quarters of the circle

    // TOP FOR X
    for(raduis=-(int)(R*0.71); raduis<=(int)(R*0.71); raduis++)
    {
        real_y = y+sqrt(R*R-raduis*raduis); // Go to next point

        if((!dotted || (to_dot%dotted)) && x>0 && x<map->w && y>0 && y<map->h) // If not outside of the map surface
        {
             // For the antialising 2 pixels are drawn, one one top (x,y+1), the other below (x,y)
             // The color is a mix of:
             // - the color of background
             // - the color of the line
             // The amount of each color (bg & line color), on the 2 pixels is 100% (e.g. 10% on one, 90% on the other)
            getPixelColor(x-raduis, (int)real_y, map, &r2,&g2,&b2,&a2);

            r=(Uint8)(frac(real_y)*r1+invfrac(real_y)*r2);
            g=(Uint8)(frac(real_y)*g1+invfrac(real_y)*g2);
            b=(Uint8)(frac(real_y)*b1+invfrac(real_y)*b2);
            a=(Uint8)(frac(real_y)*a1+invfrac(real_y)*a2);
            colorAA1=SDL_MapRGBA(map->format,r,g,b,a);

            r=(Uint8)(frac(real_y)*r2+invfrac(real_y)*r1);
            g=(Uint8)(frac(real_y)*g2+invfrac(real_y)*g1);
            b=(Uint8)(frac(real_y)*b2+invfrac(real_y)*b1);
            a=(Uint8)(frac(real_y)*a2+invfrac(real_y)*a1);
            colorAA2=SDL_MapRGBA(map->format,r,g,b,a);

            setPixel(x-raduis, (int)real_y, colorAA2, map);
            setPixel(x-raduis, (int)real_y+1, colorAA1, map);
        }
        to_dot++;
    }

    // BOTTOM FOR X
    for(raduis=-(int)(R*0.71); raduis<=(int)(R*0.71); raduis++)
    {
        real_y = y-sqrt(R*R-raduis*raduis);

        if((!dotted || (to_dot%dotted)) && x>0 && x<map->w && y>0 && y<map->h)
        {
            getPixelColor(x-raduis, (int)real_y, map, &r2,&g2,&b2,&a2);

            r=(Uint8)(frac(real_y)*r1+invfrac(real_y)*r2);
            g=(Uint8)(frac(real_y)*g1+invfrac(real_y)*g2);
            b=(Uint8)(frac(real_y)*b1+invfrac(real_y)*b2);
            a=(Uint8)(frac(real_y)*a1+invfrac(real_y)*a2);
            colorAA1=SDL_MapRGBA(map->format,r,g,b,a);

            r=(Uint8)(frac(real_y)*r2+invfrac(real_y)*r1);
            g=(Uint8)(frac(real_y)*g2+invfrac(real_y)*g1);
            b=(Uint8)(frac(real_y)*b2+invfrac(real_y)*b1);
            a=(Uint8)(frac(real_y)*a2+invfrac(real_y)*a1);
            colorAA2=SDL_MapRGBA(map->format,r,g,b,a);

            setPixel(x-raduis, (int)real_y, colorAA2, map);
            setPixel(x-raduis, (int)real_y+1, colorAA1, map);
        }
        to_dot++;
    }

    // TOP FOR Y
    for(raduis=-(int)(R*0.71); raduis<=(int)(R*0.71); raduis++)
    {
        real_x = x+sqrt(R*R-raduis*raduis);

        if((!dotted || (to_dot%dotted)) && x>0 && x<map->w && y>0 && y<map->h)
        {
            getPixelColor((int)real_x, y-raduis, map, &r2,&g2,&b2,&a2);

            r=(Uint8)(frac(real_x)*r1+invfrac(real_x)*r2);
            g=(Uint8)(frac(real_x)*g1+invfrac(real_x)*g2);
            b=(Uint8)(frac(real_x)*b1+invfrac(real_x)*b2);
            a=(Uint8)(frac(real_x)*a1+invfrac(real_x)*a2);
            colorAA1=SDL_MapRGBA(map->format,r,g,b,a);

            r=(Uint8)(frac(real_x)*r2+invfrac(real_x)*r1);
            g=(Uint8)(frac(real_x)*g2+invfrac(real_x)*g1);
            b=(Uint8)(frac(real_x)*b2+invfrac(real_x)*b1);
            a=(Uint8)(frac(real_x)*a2+invfrac(real_x)*a1);
            colorAA2=SDL_MapRGBA(map->format,r,g,b,a);

            setPixel((int)real_x, (y-raduis), colorAA2, map);
            setPixel((int)real_x+1, (y-raduis), colorAA1, map);
        }
        to_dot++;
    }

    // BOTTOM FOR Y
    for(raduis=-(int)(R*0.71); raduis<=(int)(R*0.71); raduis++)
    {
        real_x = x-sqrt(R*R-raduis*raduis);

        if((!dotted || (to_dot%dotted)) && x>0 && x<map->w && y>0 && y<map->h)
        {
            getPixelColor((int)real_x, y-raduis, map, &r2,&g2,&b2,&a2);

            r=(Uint8)(frac(real_x)*r1+invfrac(real_x)*r2);
            g=(Uint8)(frac(real_x)*g1+invfrac(real_x)*g2);
            b=(Uint8)(frac(real_x)*b1+invfrac(real_x)*b2);
            a=(Uint8)(frac(real_x)*a1+invfrac(real_x)*a2);
            colorAA1=SDL_MapRGBA(map->format,r,g,b,a);

            r=(Uint8)(frac(real_x)*r2+invfrac(real_x)*r1);
            g=(Uint8)(frac(real_x)*g2+invfrac(real_x)*g1);
            b=(Uint8)(frac(real_x)*b2+invfrac(real_x)*b1);
            a=(Uint8)(frac(real_x)*a2+invfrac(real_x)*a1);
            colorAA2=SDL_MapRGBA(map->format,r,g,b,a);

            setPixel((int)real_x, (y-raduis), colorAA2, map);
            setPixel((int)real_x+1, (y-raduis), colorAA1, map);
        }
        to_dot++;
    }
}

// Traces a line perpendicular to the (x1,y1);(x2;y2) line, on point (x0,y0), on the spedicifed color, on the map surface, with the dotted method
// If x0 or y0 is UNSET, then the perpendicular line is drawn from point 2
// Length of the line is d1 in 1 direction (than direction than (x1,y1)->(x2;y2), d2 in the 2nd direction (opposite direction).
// If the d1 is UNSET, then the line is drawn on the whole half plan surface
// Same thing for d2
// Returns: void
void perdendicular_trace(int x1, int y1, int x2, int y2, int x0, int y0, int d1, int d2, Uint32 color, SDL_Surface *map, int dotted)
{
    int x_1, y_1, x_2, y_2;
    float distance1, distance2, d;

    if(d1==UNSET && d2==UNSET)
    {
        d1 = getDistance(0, 0, map->w, map->h);
        d2 = d1; // less calculation
    }
    else if(d1==UNSET)
        d1 = getDistance(0, 0, map->w, map->h);
    else if(d2==UNSET)
        d2 = getDistance(0, 0, map->w, map->h);

    d = getDistance(x1, y1, x2, y2);
    distance1 = (float)d1/d;
    distance2 = (float)d2/d;

    if(x0==UNSET||y0==UNSET)
    {
        x0 = x2;
        y0 = y2;
    }

    x_1 = x0 - distance1*(y2 - y1);
    y_1 = y0 + distance1*(x2 - x1);

    x_2 = x0 + distance2*(y2 - y1);
    y_2 = y0 - distance2*(x2 - x1);

    line_trace(x_1, y_1, x_2, y_2, color, map, dotted);
}

// Traces a line parallele to the (x1,y1);(x2;y2) line, on point (x0,y0), on the spedicifed color, on the map surface, with the dotted method
// If x0 or y0 is UNSET, then the parallele line is drawn from point 2
// Length of the line is d1 in 1 direction (clockwise), d2 in the 2nd direction (anticlockwise).
// If the d1 is UNSET, then the line is drawn on the whole half plan surface
// Same thing for d2
// Returns: void
void parallele_trace(int x1, int y1, int x2, int y2, int x0, int y0, int d1, int d2, Uint32 color, SDL_Surface *map, int dotted)
{
    int x_1, y_1, x_2, y_2;
    float distance1, distance2, d;

    if(d1==UNSET && d2==UNSET)
    {
        d1 = getDistance(0, 0, map->w, map->h);
        d2 = d1; // less calculation
    }
    else if(d1==UNSET)
        d1 = getDistance(0, 0, map->w, map->h);
    else if(d2==UNSET)
        d2 = getDistance(0, 0, map->w, map->h);

    d = getDistance(x1, y1, x2, y2);
    distance1 = (float)d1/d;
    distance2 = (float)d2/d;

    if(x0==UNSET||y0==UNSET)
    {
        x0 = x2;
        y0 = y2;
    }

    x_1 = x0 - distance1*(x2 - x1);
    y_1 = y0 - distance1*(y2 - y1);

    x_2 = x0 + distance2*(x2 - x1);
    y_2 = y0 + distance2*(y2 - y1);

    line_trace(x_1, y_1, x_2, y_2, color, map, dotted);
}

// Getter for the distance between 2 points x1,y1 & x2,y2
// Returns the distance (float)
float getDistance(int x1, int y1, int x2, int y2)
{
    return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2));
}

#endif // __TRACERC__

Voilà, j'espère que cela vous aura aidé à comprendre la principe de l'anti-aliasing!

… Et surtout donné la vocation à d'autres de créer des bibliothèques:D !

Exemple de certificat de réussite
Exemple de certificat de réussite