MTProd > Dev4all > Articles > APIs > DirectX > Votre premier jeu Windows - C++/DirectX > 6 UpdateFrame()
Rechercher20 Personnes en-ligne
Votre premier jeu Windows - C++/DirectX

6  UpdateFrame()

Cette fonction n'est pas obligatoire mais sans elle rien ne serait affiché dans notre application, elle s'occupe de mettre à jour notre écran (ou frame). Nous aurions pû placer son contenu dans notre fonction WinMain(), or il est bien plus pratique et plus propre d'en faire une nouvelle fonction.



6.1  Listing

Listing 6.1.1 : UpdateFrame()
(
ouvrir dans une nouvelle fenêtre)

 1  UpdateFrame( void )
 2  {
 3      HRESULT        hRet;
 4      HDC            hdc;
 5      DDBLTFX        ddbltfx;
 6  
 7      // Dessine un fond bleu sur toutes la surface de l'écran
 8      ZeroMemory(&ddbltfx, sizeof(ddbltfx));
 9      ddbltfx.dwSize = sizeof(ddbltfx);
 10      ddbltfx.dwFillColor = 255;
 11      surfBack->Blt( NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx );
 12  
 13      // Dessiner le sprite
 14      srcRect = GetImage( BALLE_SIZE, BALLE_SIZE, balle.dir );
 15      surfBack->BltFast( (int)balle.posX, (int)balle.posY, surfSprite, &srcRect, DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY );
 16  
 17      // Dessiner le Curseur
 18      srcRect = GetImage( CURSOR_SIZE, CURSOR_SIZE, cursor.image );
 19      surfBack->BltFast( cursor.x, cursor.y, surfCurseur, &srcRect, DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY );
 20  
 21  
 22      // Gère quelques erreurs DirectDraw
 23      while ( TRUE )
 24      {
 25          hRet = surfBack->GetDC( &hdc );
 26          if ( hRet == DD_OK )
 27              break;
 28          if ( hRet == DDERR_SURFACELOST )
 29          {
 30              hRet = RestoreAll();
 31              if ( hRet != DD_OK )
 32                  break;
 33          }
 34          if ( hRet != DDERR_WASSTILLDRAWING )
 35              break;
 36      }
 37  
 38      // Utilise le GDI pour écrire du texte
 39      sprintf( tmpStr, "posX:%0.2f|posY:%0.2f dir:%d",
 40          balle.posX, balle.posY, balle.dir);
 41      SetBkMode( hdc, TRANSPARENT );
 42      SetTextColor( hdc, RGB( 255, 255, 255 ) );
 43      SetTextAlign( hdc, TA_CENTER );
 44      TextOut( hdc, RES_X / 2, 0, tmpStr, lstrlen(tmpStr) );
 45      surfBack->ReleaseDC( hdc );
 46  
 47  
 48      // Flip les deux surfaces (back et front)
 49      surfFront->Flip(NULL, 0);
 50  
 51  
 52      return 1;
 53  }


En ligne 1 nous déclarons notre fonction, vous remarquerez qu'aucun type n'est spécifié avant le nom de la fonction, par défaut le compilateur utilisera le type int (entier). Cette fonction ne contient pas d'arguements, nous plaçons alors le mot-clé void signifiant vide ou rien.

En ligne 3 nous déclarons une variable locale de type HRESULT, il s'agit d'un entier 32 bits (long).
Ligne 4, nous déclarons une variable locale de type HDC pour "Handle Device Context", nous l'utiliserons plus loin.
Ligne 5, une variable locale de type DDBLTFX est déclarée, il s'agit d'une structure DirectDraw utilisée pour faire des effets spéciaux, comme par exemple du Blitting...




6.2  Le blitting

Qu'est-ce que le blitting ? On peut se poser la question, il s'agit en fait d'une simple opération de copie : le contenu de la mémoire est transféré d'un emplacement à un autre. Sous DirectDraw, la source et la cible de la copie sont soit des portions d'objets LPDIRECTDRAWSURFACE7, soit des objets LPDIRECTDRAWSURFACE7 complets.
Cette technique nous permettra donc de coller de la mémoire de surface sur une autre mémoire de surface, en plus clair, dessiner nos sprites sur nos tampons !
Nous dessinons donc dans l'ordre suivant : de l'arrière plan vers le premier plan (figure 6.2.1).



Figure 6.2.1: L'ordre des blittings

Sous DirectDraw il existe deux fonctions effectuant du blitting :

  • Blt() pour dessiner des surfaces avec d'éventuels effets spéciaux (remplissage de couleur, transparance alpha, rotation, stretching, etc.). Nous utiliserons cette fonction pour dessiner des fonds ou des sprites avec effets spéciaux.

  • BltFast() dessine lui aussi des surfaces mais plus rapidement que Blt(), aucun effet spécial n'est possible, mis à part la suppression des pixels définis comme transparents.


Voyons comment procéder pour Blt() :
Ligne 8, nous effaçons le contenu de ddbltfx avec la fonction ZeroMemory().
Ligne 9, nous fixons la taille de notre strucure grace à l'opérateur sizeof().
Ligne 10, nous définissons la couleur de remplissage dwFillColor, ici du noir grâce à RGB(0, 0, 0).
Ligne 11, nous effectuons le blitting proprement dit grâce à la fonction DirectDraw Blt() que chaque objet LPDIRECTDRAWSURFACE7 hérite, les paramêtres de cette fonction sont les suivants :

  1. LPRECT lpDestRect : L'adresse d'une structure RECT indiquant le point le plus haut à gauche et le point le plus bas à droite où notre blitting s'effectura, en clair : le rectangle de destination, ici nous voulons dessiner sur toutes la surface, nous passons alors la valeur NULL

  2. LPDIRECTDRAWSURFACE7 lpDDSrcSurface : L'adresse de la surface que nous désirons "blitter" sur l'actuelle, ici nous passons NULL car aucune surface ne sera dessiné par dessus

  3. LPRECT lpSrcRect : L'adresse d'une structure RECT indiquant le point le plus haut à gauche et le point le plus bas à droite de notre surface source, en clair : quel partie allons-nous "coller" sur notre surface, ici NULL car aucune surface ne sera dessiné par dessus

  4. DWORD dwFlags : Il s'agit des options du blitting, ici DDBLT_COLORFILL afin de spécifier que la variable dwFillColor doit être utilisé pour remplir le rectangle de destination. DDBLT_WAIT attend que le blitting soit mit en place avant de rendre la main au programme

  5. LPDDBLTFX lpDDBltFx : L'adresse d'une structure DDBLTFX, ici ddbltfx définit juste avant


Voilà pour le remplissage de notre "back buffer" surfBack, nous allons maintenant y dessiner notre sprite.
Tout d'abord, en ligne 14 nous utilisons notre fonction GetImage() (décrite au chapitre 7) afin de fixer notre rectangle source.
Ligne 15, nous effectuons mainteant un blitting rapide grâce à la fonction BltFast() dont voici les arguments :

  1. DWORD dwX : Le point X (horizontal) où nous voulons dessiner (surface de destination), ici balle.posX converti en entier avec l'opérateur (int)

  2. DWORD dwY : Le point Y (vertical) où nous voulons dessiner (surface de destination), ici balle.posY converti en entier avec l'opérateur (int)

  3. LPDIRECTDRAWSURFACE7 lpDDSrcSurface : L'adresse de la surface que nous voulons dessiner (source), ici surfSprite

  4. LPRECT lpSrcRect : L'adresse d'une structure RECT spécifiant le rectangle à copier de notre surface source, ici srcRect définit à la ligne précédente (14)

  5. DWORD dwTrans : Les options du blitting, ici DDBLTFAST_SRCCOLORKEY afin de ne pas dessiner les pixels transparents (listing 4.1.1, ligne 83 et 84) de la surface source. DDBLTFAST_WAIT attend que le blitting soit mit en place avant de continuer


Nous faisons pareil pour dessiner notre curseur (surfCurseur) en ligne 18 et 19.




6.3  Quelques erreurs DirectDraw

Ligne 23, nous lançons une boucle sans fin afin d'effectuer quelques tests et gérer quelques erreurs DirectDraw.
Ligne 25, nous obtenons l'handle de contexte de périphérique (c'est son nom, et oui ) de notre surface "back buffer" grâce à la fonction GetDC() et nous le plaçons dans la variable hRet (définit ligne 3). Nous allons grâce à cette petite chose, pouvoir obtenir le status de notre surface surfBack et y dessiner du texte plus loin.
Ligne 26, si hRet vaut DD_OK, c'est tout bon, nous "cassons" notre boucle while avec l'instruction break.
Ligne 28, nous testons si nous avons perdu une surface (une ou plusieurs surfaces ont étés déchargée), si oui, ligne 30, nous rechargeons toutes les surfaces avec la fonction RestoreAll() (chapitre 7), si la valeur de retour de cette fonction n'est pas égal à DD_OK nous cassons la boucle et tentons de continuer (ligne 32), si les surfaces ont été bien rechargées nous continuons la boucle pour vérifier les autres messages.
Ligne 34, si hRet ne vaut pas DDERR_WASSTILLDRAWING cela signifie que les opérations de blitting sont terminées, nous quittons alors la boucle avec break (ligne 35).




6.4  Ecrire du texte avec le GDI

GDI signifie "Graphic Device Interface" et permet d'utiliser les fonctions de dessins de Windows, nous allons l'utiliser ici pour écrire du texte sur notre surface surfBack avec une police système.
Ligne 39, nous formatons le texte qui sera affiché, nous plaçons ce contenu dans la variable char nommé tmpStr (déclaré dans globals.h) avec la fonction sprintf(). Quelques remarques au sujet de cette fonction bien utile :
Nous devons lui passer comme premier argument la variable qui prendra le contenu formaté puis la chaine finale mis en forme, mais voyons comment insérer des valeurs dans cette chaine, prenez notre texte ligne 39 :
posX:%0.2f|posY:%0.2f dir:%d
Regardons de plus prêt la première valeur, à savoir %0.2f, toute valeur insérée doit commencer par le signe pourcent, ici il s'agit d'une variable de type float, c'est pourquoi le f à la fin, le premier nombre entre ces deux caractères est 0, il indique le nombre de décimals (chiffres après la virgule) a afficher au minimum et le deuxième : le nombre de décimals a afficher au maximum, ici 2.
Si notre nombre vaut 2.00000000, c'est à dire "entier", il sera affiché 2.
S'il vaut 2.13141516 il sera alors affiché 2.13.
Pour afficher un entier, nous utilisons %d.
Enfin nous passons à sprintf() la liste des valeurs que nous désirons afficher et que nous avons inclus avec le signe pourcent.

Passons, ligne 41, nous définissons le mode du fond (Background Mode) avec la fonction SetBKMode(), le mode peut être soit OPAQUE soit TRANSPARENT.
Ligne 42, nous fixons la couleur de notre texte, ici la couleur RGB( 255, 255, 255 ) pour blanc avec la fonction SetTextColor().
Ligne 43, nous fixons l'alignement de notre texte avec la fonction SetTextAlign() ici TA_CENTER pour centrer le texte.
Ligne 44, nous dessinons notre texte sur notre surface surfBack avec la fonction TextOut() qui prend les arguments suivant :

  1. HDC hdc : L'handle de notre contexte de périphérique

  2. int nXStart : Le point X où commençera le dessin, ici RES_X / 2 ce qui nous donnera le milieu de l'écran

  3. int nYStart : Le point Y où commencera le dessin, ici 0 ce qui signifie "tout en haut"

  4. LPCTSTR lpString : La chaine de caractères a dessiner, ici notre chaine tmpStr

  5. int cbString : La taille de la chaine de caractères (en caractères), nous utilisons la fonction lstrlen() afin d'obtenir le nombre de caractères contenus dans tmpStr


Voilà, notre chaine est dessiné sur notre surface, nous pouvons maintenant "relacher" (release) notre contexte de périphérique utilisé par notre surface avec la fonction ReleaseDC().




6.5  On Flip()

Ligne 49, nous avons fini tous nos blittings et dessins, nous allons alors "flipper" (voir § 4.5) nos deux surfaces (la primaire et le "back buffer") grâce à la fonction DirectDraw Flip() qui s'occupe de gérer cela.
Enfin si nous sommes arrivé jusqu'a la ligne 52, cela signifie que notre fonction UpdateFrame() c'est bien déroulée, nous retournons alors la valeur positive 1.





<<  5  WinMain()Sommaire7  fonctions.h  >>

 Accés rapide

1  Introduction
2  Les fichiers et répertoires
3  WindowProc()
4  InitApp()
5  WinMain()
6  UpdateFrame()

Listing

Le blitting

Quelques erreurs DirectDraw

Ecrire du texte avec le GDI

On Flip()

7  fonctions.h
8  input.h
9  Conclusion
Voir le sommaire complet

 Liens utiles

  • Publier un article
  • Envoyer cette page
  • Ecrire à l'auteur

  •  Mini-Chat

    Thienou (00h11): salut
    Thienou (00h13): Oula mon inscription date de 11 ans je me sent vieux :)
    neowolf25 (17h59): MMF2 en "pay what you want" jusqu'à demain sur
    neowolf25 (17h59): https://www.hu
    mblebundle.com/
    weekly

    Miuka (21h15): Coin coin de 2014
    Miuka (21h15): Des gens qui ont migré sur le forum Clickteam ou ailleurs ?
    Strike (09h45): Salut les vieux !
    Hikarion (12h46): Salut les djeunz
    Hikarion (13h38): A qui profite le scandale ?
    Hikarion (13h44): le chat irc est toujours actif ?

    Votre message



     Archives

     Dev4all Newsletter

    Restez à jour avec la newsletter mensuelle !

    Votre e-mail


    1800 abonnés

     Recommander Dev4all

    Recommandez Dev4all à un ami. Cela fera grandir notre communauté !

    E-mails de vos amis




    [ Accueil | S'inscrire | Mon Dev4all | Communauté | Téléchargements | Articles | Forums | Chat ]

    [ A propos de Dev4all | Aide | La charte Dev4all | Contact ]

    © 2000-2018 MTProd. Tous droits réservés.
    L'utilisation de Dev4all implique l'acceptation et le respect de la charte Dev4all.