Texel |
|
Introduction à Direct Draw
Du chargement des images aux rendus Sources: Ouvrir dans une fenêtre Télécharger I. Chargement des images A la fin de l'initialisation, la fonction load_image est appelée. Nous utilisons dans celle-ci une fonction appelée DDloadBitmap qui retourne une surface qu'elle a créer et sur laquelle elle a charger une image bitmap . Nous n'avons donc pas besoin de créer les surfaces secondaires. Une égalité suffit.
Le premier argument de cette fonction est l'objet DirectDraw (lpDD). Le deuxième est le nom du bitmap à charger. Et les deux derniers arguments sont la largeur et la hauteur souhaité de l'image une fois transférer sur la surface. Si ces deux arguments sont 0, l'image chargée aura sa taille par défaut. Cette fonction n'appartient pas à la librairie ddraw mais à un fichier disponible gratuitement dans le SDK appelé "ddutil.cpp" accompagné de son header "ddutil.h". Si vous regardez le code source de ce fichier (ce que je vous conseil vivement de faire) vous verrez que la fonction DDloadBitmap (et les autres fonctions qu'elle appel) utilise le GDI pour le chargement les bitmaps. Elle est vraiment très simple à comprendre. II. Définition d'une couleur transparente Pour afficher des images qui ne sont pas rectangulaire (comme une balle), il faut définir une clé de couleur transparente pour certaines de nos surfaces secondaires. Les clés de couleur représentent une ou plusieurs couleurs. Lorsque les images de ces surfaces sont transférées vers la surface primaire, les pixels de la couleur de la clé de couleurs ne sont pas transférés. C'est le même principe qui est utilisé à la télé pour incruster un présentateur météo devant une carte.
Pour la clé, il faut donc utiliser une couleur qui n'est pas utilisé par les partie des images que l'on veut afficher. C'est pourquoi le vert et le bleu sont très souvent utilisé. Pour VRpong, j'ai choisi le vert le plus saturé. En mode 16 bits, les couleurs ne sont pas toujours codées en 16 bits. Elles peuvent être en faites codées en 15 bits sur certaines cartes graphiques. En conséquence de quoi on ne connaît pas la valeur des couleurs chez l'utilisateur du programme. C'est pourquoi, pour résoudre le problème, on utilise la méthode IDIRECTDRAWSURFACE7::GetPixelFormat pour connaître la valeur du vert le plus saturé sur la surface primaire de chaques utilisateurs. Cette méthode prend en argument et rempli une structure de type DDPIXELFORMAT. Comme vous le voyez, le champ dwSize doit contenir la taille de la structure .Voici les cinq autres champs les plus important que vous n'aurez pas à remplir (GetPixelFormat s'en occupe) mais que vous pouvez avoir à utiliser: _ dwRGBBitCount nombre de bits par pixel _ dwRBitMask masque de bits pour les bits rouges _ dwGBitMask masque de bits pour les bits verts _ dwBBitMask masque de bits pour les bits bleus _ dwAlphaBitDepth masque de bits pour les bits alpha Les masques de bits sont des mots double 32 bits de type DWORD. Ils représentent la valeur la plus saturé de chacune des trois couleurs primaires (rouge, vert, bleu). Chaques couleur est l'addition des trois masques de couleurs multiplier chacun par un pourcentage (de la couleur maximale). Pour vous éclaircir les idées, voici la formule pour obtenir une clé de couleur constituée de rouge, vert et bleu saturé respectivement à 20, 80, et 40 pour-cent avec notre structure ddpf de pong:
Dans notre VRpong, c'est beaucoup plus court puisque l'on souhaite une couleur uniquement constituée de vert. Les masque de bits rouge et bleu ont un pourcentage de 0.
On associe une clé de couleur à une surface en utilisant la méthode IDIRECTDRAWSURFACE7::SetColorKey. Le deuxième paramètre de la méthode reçoit l'adresse d'une structure de type DDCOLORKEY. Cette structure contient la valeur de la clé de couleur grâce à deux champs: dwColorSpaceLowValue et dwColorSpaceHighValue. Ces deux champs permettent d'avoir comme couleur transparente un dégradé de couleur. Vous pouvez ainsi choisir de rendre transparente toutes les couleurs qui ont un pourcentage de bleu compris entre 80 et 100 pour-cent. Les deux champs prennent donc en argument la première et la dernière couleur de dégradé. Pour VRpong, ces deux valeurs sont identiques car nous n'utilisons qu'une seule couleur pour la clé. Le premier argument de la méthode est un drapeau donnant des indications sur la clé de couleur. Voici les drapeaux les plus utilisé: _ DDCKEY_COLORSPACE : Ce drapeau permet d'utiliser non pas une mais un dégradé de couleur pour la clé. _ DDCKEY_DESTBLT : Lors du transfert d'une image vers une surface de destination, les pixels de cette surface qui ont la couleur de la clé de couleur seront remplacer par les pixels de l'image transférée. Attention: Si le matériel de l'utilisateur ne prend pas en charge cette fonctionnalité, elle ne sera pas émmulé. _ DDCKEY_SRCBLT : Lors du transfert d'une image entre deux surfaces, seul les pixels de couleurs différentes de la clé de couleur sur la surface source seront transférées sur la surface cible. Cette fonctionnalité peut être émmulé. III. Libération des objets Si notre initialisation pose problème, nous appelons la fonction cleanup qui libère tous les objets grâce à la méthode Release. Attention: La libération des objets DirectX est absolument indispensable et doit être appeler avant la fermeture de tout programme DirectX pour éviter de gros bugs. Nous appelons aussi la fonction cleanup lors du traitement du message WM_DESTROY de la procédure de fenêtre.
IV. Le rendu de l'image Maintenant que les images sont chargées en mémoire sur des surfaces secondaires, il faut les transférer sur la surface primaire aux positions requises par le jeu.
Dans la boucle de jeu de la fonction WinMain, la position de chaque objet graphique est calculé en fonction du temps ( cf tutorial sur les compteurs) et des entrés claviers. Comme je vous l'ai déjà dis, je ne vais pas vous expliquer l'algorithme du jeu. Je vais donc simplement vous parler de la procédure render_frame.
Comme je l'ai expliqué précédemment, il faut d'abord transférer les images des surfaces secondaires vers le back buffer. Cette opération est effectuée par des méthodes à appelé depuis la surface primaires et qui ont le même nom que les fonctions GDI : IDIRECTDRAW7::BltFast IDIRECTDRAW7::Blt IDIRECTDRAW7::StretchBlt Les deux dernières fonctions peuvent agrandir ou réduire la taille des images pendant le transfert. Dans VRpong, nous utilisons d'abord la méthode Blt pour transférer l'image de fond en l'agrandissant (on transfert bien sûr les images du dernier plan avant celles du premier plan):
Le premier et le troisième argument de la méthode blt sont respectivement des rectangles destinations et sources pour le transfert. Ce sont des structures de type RECT avec les quatre coordonnées des sommets d'un rectangle (left, right, top, bottom). Le rectangle source délimite la zone à transférer. Le rectangle de destination indique les coordonné ou transférer l'image, avec sa largeur et sa hauteur (qui peuvent être modifiées). Dans VRpong, on passe l'argument NULL pour transférer l'image de toute la surface source vers toute la superficie de la surface primaire.
Les surfaces sources sont les surfaces secondaires pour nous.
Le drapeau DDBLT_WAIT oblige le programme à attendre la fin du transfert avant de continuer son exécution. Les structure DDBLTFX permettent quelques effets spéciaux (cf. doc du SDK). Nous n'en utilisons pas. Pour transférer les objets actifs comme la balle et le stick, on utilise la méthode BltFast car nous n'avons pas besoin d'agrandir les images.
Le stick et la balle sont sur la même surface. Le rectangle nous permet de transférer la bonne zone de l'image au bon endroit.
Le drapeau DDBLTFAST_SRCCOLORKEY permet d'utiliser les couleurs transparentes (que nous n'avions pas utiliser pour l'image de fond). Vous remarquez que nous avons afficher du texte sur le back buffer avec des fonctions GDI. En effet, la plus part d'entre elles fonctionnent avec DirectX. GetDC et ReleaseDC ne sont alors plus des fonctions mais des méthodes de surface DirectDraw. Une fois le transfert terminé, il ne reste plus qu'à afficher le back buffer en intervertissant les pointeurs de la surface primaire avec le back buffer. Le back buffer devient la surface primaire et la surface primaire devient le back buffer grâce à la méthode IDIRECTDRAWSURFACE7::Flip. Son premier argument est la surface à permuter avec la surface primaire. 0 désigne le back buffer. Le deuxième argument est un drapeau. DDFLIP_WAIT met en pause la fonction jusqu'à la fin de la permutation. Conclusion: Vous avez appris les bases de la programmation en DirectDraw. Vous pouvez maintenant vous améliorer tout seul en lisant la documentation et les exemples du SDK. VRpong est loin d'être finit puisque ce n'est même pas encore un jeu. Il y a aussi pas mal de problèmes à résoudre. Essayez d'appuyer sur "Alt + Tab" pour sortir puis revenir dans l'application : Les surfaces seront perdues. Il faut pouvoir les restaurer (cf exemple SDK). Alors à vos claviers!
|