/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
#include "graphique.h"
////////////////////////////////////////////////////////////////////////////////
/**
* initWindow initialise la SDL, crée une fenêtre et initialise un
* Timer pour scruter les évènements.
* @author SD
* @param title : Le titre de la fenêtre
* @param width : La largeur de la fenêtre en pixels
* @param height : La hauteur de la fenêtre en pixels
* @return 0 en cas de succès, -1 sinon
*/
int initWindow(const char* title, unsigned width, unsigned height) {
/* Initialisation de la DSL */
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0 )
{
fprintf(stdout,"Échec de l'initialisation de la SDL (%s)\n",SDL_GetError());
return -1;
}
/* Création de la fenêtre */
__graphique.pWindow = SDL_CreateWindow(title,
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
width,
height,
SDL_WINDOW_SHOWN);
if(__graphique.pWindow) {
__graphique.screen = SDL_GetWindowSurface(__graphique.pWindow);
__graphique.fill_red = 0;
__graphique.fill_green = 0;
__graphique.fill_blue = 0;
// Timer pour appeler la fonction _poolEvent toutes les 25ms
Uint32 delay = 25;
SDL_TimerID my_timer_id = SDL_AddTimer(delay, _poolEvent, 0);
}
else {
fprintf(stderr,"Erreur de création de la fenêtre: %s\n",SDL_GetError());
return -1;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/**
* exitWindow Ferme la fenêtre créé avec initWindow().
* @author SD
*/
void exitWindow() {
SDL_DestroyWindow(__graphique.pWindow);
SDL_Quit();
}
////////////////////////////////////////////////////////////////////////////////
/**
* backgroundWhite Efface la fenêtre avec un fond blanc.
* @author SD
*/
void backgroundWhite() {
SDL_FillRect(__graphique.screen,
NULL,
SDL_MapRGB(__graphique.screen->format, 255, 255, 255));
}
////////////////////////////////////////////////////////////////////////////////
/**
* background Efface la fenêtre avec un fond selon les composantes RVB
* passées en paramètres.
* @author SD
* @param red : Composante rouge (0 - 255)
* @param green : Composante verte (0 - 255)
* @param blue : Composante bleue (0 - 255)
*/
void background(Uint8 red, Uint8 green, Uint8 blue) {
SDL_FillRect(__graphique.screen,
NULL,
SDL_MapRGB(__graphique.screen->format, red, green, blue));
}
////////////////////////////////////////////////////////////////////////////////
/**
* rect Dessine un rectangle plein. La couleur par défaut est noire.
* Pour changer la couleur appeler au préalable la fonction fill.
* @see #fill(Uint8, Uint8, Uint8)
* @author SD
* @param posx : Position x en pixels du coin supérieur gauche
* @param posy : Position y en pixels du coin supérieur gauche
* @param width : Largeur en pixels
* @param height : Hauteur en pixels
*/
void rect(unsigned posx, unsigned posy, unsigned width, unsigned height) {
SDL_Surface *s;
/* Creating the surface. */
s = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0);
/* Filling the surface with red color. */
SDL_FillRect(s, NULL, SDL_MapRGB(s->format, __graphique.fill_red,
__graphique.fill_green,
__graphique.fill_blue));
SDL_Rect position;
position.x = posx;
position.y = posy;
SDL_BlitSurface(s, NULL, __graphique.screen, &position);
}
////////////////////////////////////////////////////////////////////////////////
/**
* refresWindow Met à jour l'affichage de la fenêtre.
* @author SD
*/
void refreshWindow() {
SDL_UpdateWindowSurface(__graphique.pWindow);
}
////////////////////////////////////////////////////////////////////////////////
/**
* fill Change la couleur dans laquelle sont dessinées les formes selon
* les composantes RVB passées en paramètres.
* @author SD
* @param red : Composante rouge (0 - 255)
* @param green : Composante verte (0 - 255)
* @param blue : Composante bleue (0 - 255)
*/
void fill(Uint8 red, Uint8 green, Uint8 blue) {
__graphique.fill_red = red;
__graphique.fill_green = green;
__graphique.fill_blue = blue;
__graphique.fill_color = blue + green * 256 + red * 65536;
}
////////////////////////////////////////////////////////////////////////////////
/**
* ligneHorizontale Dessine une ligne horizontale. La couleur par défaut est noire.
* Pour changer la couleur appeler au préalable la fonction fill.
* @author SD
* @param posx : Position x en pixels du point gauche
* @param posy : Position y en pixels du point gauche
* @param width : Largeur en pixels
*/
void ligneHorizontale(unsigned posx, unsigned posy, unsigned width)
{
SDL_Rect r;
r.x = posx;
r.y = posy;
r.w = width;
r.h = 1;
SDL_FillRect(__graphique.screen, &r, __graphique.fill_color);
}
////////////////////////////////////////////////////////////////////////////////
/**
* ligneVerticale Dessine une ligne verticale. La couleur par défaut est noire.
* Pour changer la couleur appeler au préalable la fonction fill.
* @author SD
* @param posx : Position x en pixels du point gauche
* @param posy : Position y en pixels du point gauche
* @param height : Hauteur en pixels
*/
void ligneVerticale(unsigned posx, unsigned posy, unsigned height)
{
SDL_Rect r;
r.x = posx;
r.y = posy;
r.w = 1;
r.h = height;
SDL_FillRect(__graphique.screen, &r, __graphique.fill_color);
}
////////////////////////////////////////////////////////////////////////////////
/**
* cercle Dessine un cercel. La couleur par défaut est noire.
* Pour changer la couleur appeler au préalable la fonction fill.
* @author SD
* @param posx : Position x en pixels du centre du cercle
* @param posy : Position y en pixels du centre du cercle
* @param rayon : Rayon du cercle en pixels
*/
void cercle(unsigned posx, unsigned posy, unsigned rayon)
{
int d, y, x;
d = 3 - (2 * rayon);
x = 0;
y = rayon;
while (y >= x) {
_setPixelVerif(posx + x, posy + y, __graphique.fill_color);
_setPixelVerif(posx + y, posy + x, __graphique.fill_color);
_setPixelVerif(posx - x, posy + y, __graphique.fill_color);
_setPixelVerif(posx - y, posy + x, __graphique.fill_color);
_setPixelVerif(posx + x, posy - y, __graphique.fill_color);
_setPixelVerif(posx + y, posy - x, __graphique.fill_color);
_setPixelVerif(posx - x, posy - y, __graphique.fill_color);
_setPixelVerif(posx - y, posy - x, __graphique.fill_color);
if (d < 0)
d = d + (4 * x) + 6;
else {
d = d + 4 * (x - y) + 10;
y--;
}
x++;
}
}
////////////////////////////////////////////////////////////////////////////////
/**
* disque Dessine un cercel. La couleur par défaut est noire.
* Pour changer la couleur appeler au préalable la fonction fill.
* @author SD
* @param posx : Position x en pixels du centre du disque
* @param posy : Position y en pixels du centre du disque
* @param rayon : Rayon du disque en pixels
*/
void disque(unsigned posx, unsigned posy, unsigned rayon)
{
int d, y, x;
d = 3 - (2 * rayon);
x = 0;
y = rayon;
while (y >= x) {
ligneHorizontale(posx - x, posy - y, 2 * x + 1);
ligneHorizontale(posx - x, posy + y, 2 * x + 1);
ligneHorizontale(posx - y, posy - x, 2 * y + 1);
ligneHorizontale(posx - y, posy + x, 2 * y + 1);
if (d < 0)
d = d + (4 * x) + 6;
else {
d = d + 4 * (x - y) + 10;
y--;
}
x++;
}
}
////////////////////////////////////////////////////////////////////////////////
/**
* ligne Dessine une ligne entre deux points. La couleur par défaut est
* noire. Pour changer la couleur appeler au préalable la fonction fill.
* @author SD
* @param x1 : Position x en pixels d'une extrémité de la ligne
* @param y1 : Position y en pixels d'une extrémité de la ligne
* @param x2 : Position x en pixels de l'autre extrémité de la ligne
* @param y2 : Position y en pixels de l'autre extrémité de la ligne
*/
void ligne(unsigned x1, unsigned y1, unsigned x2, unsigned y2)
{
int d, dx, dy, aincr, bincr, xincr, yincr, x, y;
if (abs(x2 - x1) < abs(y2 - y1)) {
/* parcours par l'axe vertical */
if (y1 > y2) {
_echangerEntiers(&x1, &x2);
_echangerEntiers(&y1, &y2);
}
xincr = x2 > x1 ? 1 : -1;
dy = y2 - y1;
dx = abs(x2 - x1);
d = 2 * dx - dy;
aincr = 2 * (dx - dy);
bincr = 2 * dx;
x = x1;
y = y1;
_setPixelVerif(x, y, __graphique.fill_color);
for (y = y1+1; y <= y2; ++y) {
if (d >= 0) {
x += xincr;
d += aincr;
} else
d += bincr;
_setPixelVerif(x, y, __graphique.fill_color);
}
} else {
/* parcours par l'axe horizontal */
if (x1 > x2) {
_echangerEntiers(&x1, &x2);
_echangerEntiers(&y1, &y2);
}
yincr = y2 > y1 ? 1 : -1;
dx = x2 - x1;
dy = abs(y2 - y1);
d = 2 * dy - dx;
aincr = 2 * (dy - dx);
bincr = 2 * dy;
x = x1;
y = y1;
_setPixelVerif(x, y, __graphique.fill_color);
for (x = x1+1; x <= x2; ++x) {
if (d >= 0) {
y += yincr;
d += aincr;
} else
d += bincr;
_setPixelVerif(x, y, __graphique.fill_color);
}
}
}
////////////////////////////////////////////////////////////////////////////////
/**
* setPixel Dessine un pixel. La couleur par défaut est noire. Pour
* changer la couleur appeler au préalable la fonction fill.
* @author SD
* @param posx : Postion x en pixels du pixel
* @param posy : Postion y en pixels du pixel
*/
void setPixel(unsigned posx, unsigned posy) {
_setPixelVerif(posx, posy, __graphique.fill_color);
}
////////////////////////////////////////////////////////////////////////////////
void _setPixel(unsigned x, unsigned y, Uint32 coul)
{
*((Uint32*)(__graphique.screen->pixels) + x + y * __graphique.screen->w) = coul;
}
////////////////////////////////////////////////////////////////////////////////
void _setPixelVerif(unsigned x, unsigned y, Uint32 coul)
{
if (x >= 0 && x < __graphique.screen->w &&
y >= 0 && y < __graphique.screen->h)
_setPixel(x, y, coul);
}
////////////////////////////////////////////////////////////////////////////////
void _echangerEntiers(unsigned* x, unsigned* y)
{
int t = *x;
*x = *y;
*y = t;
}
////////////////////////////////////////////////////////////////////////////////
Uint32 _poolEvent(Uint32 interval, void *param)
{
SDL_Event event;
SDL_UserEvent userevent;
userevent.type = SDL_USEREVENT;
userevent.code = 0;
userevent.data1 = NULL;
userevent.data2 = NULL;
event.type = SDL_USEREVENT;
event.user = userevent;
SDL_PushEvent(&event);
//printf("Dans le thread\n");
return interval;
}