Travaux pratiques 4H
DATE:24 /05/2018
Pré-requis
Cours de C de base , fichiers, fonctions, compilation Gcc
Usage de KDBG/ gdb
Les Structures
Installer libsdl: sudo apt update ; sudo apt install libsdl1.2-dev
Pour travailler sous windows ! il faudra utiliser Xlaunch , serveur graphique X pour windows.
But
Utilisation d'une librairie graphique , pour dessiner, tracer sur l'écran .
Outils de debug (kdbg ou gdb)
vérifier les acquis du TP précédent et les transposer
Vos tp seront rédigés au format pdf envoyés sur l' émail :
polytech1 @ workboot.fr ! y a des espaces anti bot !
La qualité de la rédaction entre dans votre note , et les initiatives apportent beaucoup de points dans la notation.
voir comment bien réaliser un projet.
Xlauch sur les machines de l'école :
Utilisation de Xlaunch
Librairie pour réaliser des jeux vidéos.
http://fr.wikipedia.org/wiki/Simple_DirectMedia_Layer
Sous Debian/Ubuntu (sur vos machines pas sur Workboot !)
Installer la SDL
libsdl: sudo apt update ; sudo apt install libsdl1.2-dev
Prise en main de la librairie et permet d' ouvrir votre première fenêtre graphique.
SDL permet de gérer l'ordinateur, depuis le clavier , la souris , le joystick et l’Écran. Multi-plateforme.
La compilation ce fera ainsi pour utiliser la SDL
gcc test0.c -o test0 `sdl-config --cflags --libs`
!! Attention ` et pas ' !! obtenu avec alt Gr 7
Verifier que sdl-config réponde bien .. (permet de simplifier la ligne de compilation... )
[bruno@localhost ~]$ sdl-config --cflags --libs
-I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
-lSDL -lpthread
Vous pourrez modifier la fonction pour changer la taille de la fenêtre. (dans initSDL)
Pour utiliser l'outil de debug kdbg:
gcc test0.c -o test0 `sdl-config --cflags --libs` -g
kdbg test0
Regarder le contenu de la structure affichage lors de l'execution du programme.
Nous allons écrire dans la mémoire écran (image)
La couleur (coul) étant codée sur 24 bits 0xRRVVBB
RR 8 bits pour le niveau de rouge
VV 8 bits pour le niveau de vert
BB 8 bits pour le niveau de bleu
La fonction est donnée , la il n'est pas encore facile pour vous de comprendre cette ligne.
Mais cela fonctionne...
Nous allons tester un nouveau code qui va placer des points de façon aléatoire sur l'image.
#include <stdlib.h>
#include <stdio.h>
#include "SDL.h"
/* structure pour surface SDL */
SDL_Surface* affichage;
/* prototypes des fonctions de bases de la lib SDL */
void initSDL(void);
void attendreTouche(void);
void setPixel(int x, int y, Uint32 coul);
void actualiser(void);
void dessinerEtoiles(void);
/* Programme principal */
int main(int argc, char** argv)
{
initSDL();
dessinerEtoiles();
actualiser();
attendreTouche();
return EXIT_SUCCESS;
}
/* Fonctions de bases pour l'usage de la lib SDL */
/*
initSDL Défini une surface SDL (fenêtre)
entrée : néant
sortie : néant
*/
void initSDL(void)
{
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "Erreur à l'initialisation de la SDL : %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
atexit(SDL_Quit);
affichage = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);
if (affichage == NULL) {
fprintf(stderr, "Impossible d'activer le mode graphique : %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
SDL_WM_SetCaption("Ciel étoilé", NULL);
}
/*
atendreTouche Permet d'attendre une touche sur le clavier
entrée : néant
sortie : néant
*/
void attendreTouche(void)
{
SDL_Event event;
do
SDL_WaitEvent(&event);
while (event.type != SDL_QUIT && event.type != SDL_KEYDOWN);
}
/*
setPixel(int x, int y, Uint32 coul) Affiche un point dans la surface
entrée : int x: position du point en abscisse
int y: position du point en ordonnée
Uint32 coul : couleur codée 0xRRVVBB 24 bits
RR : octet pour le rouge (0 a 255)
VV : octet pour le vert
BB : octet pour le bleu
sortie : néant
*/
void setPixel(int x, int y, Uint32 coul)
{
*((Uint32*)(affichage->pixels) + x + y * affichage->w) = coul;
}
/*
actualiser Permet de rafraîchir l'affichage
Pour tenir compte des points .. etc..
entrée : néant
sortie : néant
*/
void actualiser(void)
{
SDL_UpdateRect(affichage, 0, 0, 0, 0);
}
/*
dessinerEtoiles Génère des étoiles aléatoirement dans la surface
entrée : néant
sortie : néant
*/
void dessinerEtoiles(void)
{
int i;
for (i = 0; i < 100; i++)
setPixel(rand() % 800, rand() % 600,
SDL_MapRGB(affichage->format,
rand() % 128 + 128, rand() % 128 + 128, rand() % 128 + 128));
}
Tester et valider ce code
Avec l'outil kdbg , nous pouvons voir les secrets que renferme le type SDL_Surface
A quoi sert w, h ? pixels ?
Premier point à l'adresse , en haut a gauche de la fenêtre le pixel1
0xb7b19000: Adresse (pointeur) sur un entier 24 bits contenant la couleur du point...
On peut regarder le contenu de la structure.
Avez vous la même adresse ? mais pourquoi?
Le hasard .
La fonction rand()
man 3 rand
*((Uint32*)(affichage->pixels) + x + y * affichage->w) = coul;
Les couleurs sont codées sur 24 bits. (3x8) bits
La couleur peut être faite avec la fonction
SDL_MapRGB(affichage->format,0xFF, 0xFF, 0xFF) qui renvoi 0xFFFFFF
Il est donc plus simple de manipuler directement la valeur de la couleur et de se passer de cette fonction SDL_MapRGB.
L’œil humain possède 3 « types de capteurs » (dans le fond de l’œil) .. un sensible au rouge ,un autre au vert et un dernier sensible au bleu.. ce sont des batonnets.
La lumière visible est un spectre continu .. visible avec un arc en ciel à travers des gouttes d'eau ou un prisme ... donc en réalité il n'existe pas que 3 couleurs.
Mais c'est ainsi que l'on fonctionne, ensuite un "traitement des informations" par le cerveau .. interprète pour déterminer les couleurs ..intermédiaires.. (traitement de l'image par votre plus beau processeur .. "your brain!")
Si on regarde un ORANGE on retrouve de ces 3 teintes... etc..
Gimp (excellent logiciel de traitement d'image libre) nous permet de voir les couleurs .. possibles avec 24 bits.
Il faut désormais utiliser la fonction setPixel(int x, int y, Uint32 coul);
Exemple d'utilisation :
place un point noir
setPixel( 10 ,10 , 0x000000)
place un point blanc
setPixel(100,100,0xFFFFFF)
On peut utiliser en ligne ce site pour déterminer une couleur en RGB (RVB)
ou google propose
color picker
Nous allons réaliser des fonctions pour utiliser pleinement la librairie SDL , pour réaliser des points, des lignes etc..
void effacer_ecran(Uint32 coul);
en utilisant la fonction setPixel(int x, int y, Uint32 coul);
Remplir la fenêtre de la couleur qu'on lui passera en argument.
Donner un exemple avec la couleur Orange
void point(int x , int y , Uint32 coul);
en utilisant la fonction setPixel(int x, int y, Uint32 coul);
On placera un point aux coordonnées x et y sachant que le point 0,0 est en bas a gauche, pour respecter la logique du repère orthonormé des mathématiciens.
Donner un exemple plaçant un point en 10,10
void ligne_horizontale(int x,int y,int dim , Uint32 coul);
utiliser la fonction point précédente pour cette fonction.
void ligne_verticale(int x,int y,int dim , Uint32 coul);
utiliser la fonction point précédente pour cette fonction.
utiliser la fonction point précédente pour cette fonction.
void ligne( int x1,int y1, int x2,int y2, Uint32 coul)
vous trouverez l'algorithme sur ce site :
https://fr.wikipedia.org/wiki/Algorithme_de_trac%C3%A9_de_segment_de_Bresenham
help !
https://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#C
void line(int x0, int y0, int x1, int y1) {
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
int err = (dx>dy ? dx : -dy)/2, e2;
for(;;){
setPixel(x0,y0);
if (x0==x1 && y0==y1) break;
e2 = err;
if (e2 >-dx) { err -= dy; x0 += sx; }
if (e2 < dy) { err += dx; y0 += sy; }
}
}
elle est franchement illisible et dure a comprendre!
Réécrire cette fonction en utilisant des if au lieu '?'
et distinguer les definitions de variable et les tests.
Et supprimer le break ! et prevoir une sortie par un test :
Exemple:
void line(int x0, int y0, int x1, int y1,Uint32 coul)
{
int dx,dy,err,e2;
dx = abs (x1-x0);
/*
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;*/
if (x0<x1) sx=1 else sx=-1;
/* c'est quand meme plus clair non ? */
/*
int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;*/
int err = (dx>dy ? dx : -dy)/2, e2;
for(;;){
setPixel(x0,y0);
if (x0==x1 && y0==y1) break;
e2 = err;
if (e2 >-dx) { err -= dy; x0 += sx; }
if (e2 < dy) { err += dx; y0 += sy; }
}
}
void triangle( int x1, int y1, int x2,int y2,int x3, int y3, Uint32 coul);
point1, point2 et point3 permettant de déterminer la position du triangle.
void carre( int x1, int y1,int cote, int angle , Uint32 coul);
point1 (x1,y1) point du carré en bas a gauche.
cote la longueur d'un des cotés du carré.
angle , entre le carré et la base de l'image.
coul : couleur sur 24 bits
void rectangle (int x, int y, int cote_adjacent,int cote_oppose, int angle , Uint32 coul);
(x,y) point le plus en bas a gauche du rectangle , hypotenuse contenant la dimension de l'hypotenuse ,et angle contenant l'angle du rectangle.
void cercle (int x, int y , int rayon, Uint32 coul);
vous trouverez l'algorithme sur ce site :
https://fr.wikipedia.org/wiki/Algorithme_de_trac%C3%A9_d'arc_de_cercle_de_Bresenham
Écrire une fonction
void bonhomme(int x,int y,int echelle,uint32 coul);
(x,y) pied droit du bonhomme/
la tête : 20 pixels de diamètre
Le corps : 50 pixels
Les bras : 40
les jambes : 45
Le cou : 5
La variable échelle est un entier 1 pour les dimensions ci-dessus et 2 double le bonhomme.. etc