home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / ddex4 / ddex4.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-15  |  8.5 KB  |  406 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File:    ddex4.cpp
  6.  *  Content:    Direct Draw example program 4.    Adds functionality to 
  7.  *        example program 3.  Creates a flipping surface and loads
  8.  *        a bitmap image into an offscreen surface.  Uses BltFast to
  9.  *        copy portions of the offscreen surface to the back buffer
  10.  *        to generate an animation.  Illustrates watching return
  11.  *        code from BltFast to prevent image tearing.  This program
  12.  *        requires 1.2 Meg of video ram.
  13.  *
  14.  ***************************************************************************/
  15.  
  16. #define NAME "DDExample4"
  17. #define TITLE "Direct Draw Example 4"
  18.  
  19. #define WIN32_LEAN_AND_MEAN
  20. #include <windows.h>
  21. #include <windowsx.h>
  22. #include <ddraw.h>
  23. #include "resource.h"
  24. #include "ddutil.h"
  25.  
  26. char szBitmap[] = "ALL";
  27.  
  28. LPDIRECTDRAW        lpDD;        // DirectDraw object
  29. LPDIRECTDRAWSURFACE    lpDDSPrimary;    // DirectDraw primary surface
  30. LPDIRECTDRAWSURFACE    lpDDSBack;    // DirectDraw back surface
  31. LPDIRECTDRAWSURFACE    lpDDSOne;    // Offscreen surface 1
  32. LPDIRECTDRAWPALETTE    lpDDPal;    // DirectDraw palette
  33. BOOL            bActive;    // is application active?
  34.  
  35. /*
  36.  * restoreAll
  37.  *
  38.  * restore all lost objects
  39.  */
  40. HRESULT restoreAll( void )
  41. {
  42.     HRESULT    ddrval;
  43.  
  44.     ddrval = lpDDSPrimary->Restore();
  45.     if( ddrval == DD_OK )
  46.     {
  47.     ddrval = lpDDSOne->Restore();
  48.     if( ddrval == DD_OK )
  49.     {
  50.             DDReLoadBitmap(lpDDSOne, szBitmap);
  51.     }
  52.     }
  53.     return ddrval;
  54.  
  55. } /* restoreAll */
  56.  
  57. /*
  58.  * updateFrame
  59.  * 
  60.  * Decide what needs to be blitted next, wait for flip to complete,
  61.  * then flip the buffers.
  62.  */
  63. void updateFrame( void )
  64. {
  65.     static DWORD    lastTickCount[3] = {0,0,0};
  66.     static int        currentFrame[3] = {0,0,0};
  67.     DWORD        thisTickCount;
  68.     RECT        rcRect;
  69.     DWORD        delay[3] = {50, 78, 13};
  70.     int            i;
  71.     int            xpos[3] = {288, 190, 416};
  72.     int            ypos[3] = {128, 300, 256};
  73.     HRESULT        ddrval;
  74.  
  75.     // Decide which frame will be blitted next
  76.     thisTickCount = GetTickCount();
  77.     for(i=0; i<3; i++)
  78.     {
  79.     if((thisTickCount - lastTickCount[i]) > delay[i])
  80.     {
  81.         // Move to next frame;
  82.         lastTickCount[i] = thisTickCount;
  83.         currentFrame[i]++;
  84.         if(currentFrame[i] > 59)
  85.         {
  86.         currentFrame[i] = 0;
  87.         }
  88.     }
  89.     }
  90.  
  91.     // Blit the stuff for the next frame
  92.     rcRect.left = 0;
  93.     rcRect.top = 0;
  94.     rcRect.right = 640;
  95.     rcRect.bottom = 480;
  96.     while( 1 )
  97.     {
  98.         ddrval = lpDDSBack->BltFast( 0, 0, lpDDSOne,
  99.             &rcRect, DDBLTFAST_NOCOLORKEY );
  100.  
  101.     if( ddrval == DD_OK )
  102.     {
  103.         break;
  104.     }
  105.     if( ddrval == DDERR_SURFACELOST )
  106.     {
  107.         ddrval = restoreAll();
  108.         if( ddrval != DD_OK )
  109.         {
  110.         return;
  111.         }
  112.     }
  113.     if( ddrval != DDERR_WASSTILLDRAWING )
  114.     {
  115.         return;
  116.     }
  117.     }
  118.     if(ddrval != DD_OK)
  119.     {
  120.     return;
  121.     }
  122.  
  123.     for( i=0; i<3; i++ )
  124.     {
  125.         rcRect.left   = currentFrame[i]%10*64;
  126.         rcRect.top    = currentFrame[i]/10*64 + 480;
  127.         rcRect.right  = currentFrame[i]%10*64 + 64;
  128.         rcRect.bottom = currentFrame[i]/10*64 + 64 + 480;
  129.  
  130.     while( 1 )
  131.     {
  132.         ddrval = lpDDSBack->BltFast( xpos[i], ypos[i], lpDDSOne,
  133.                                  &rcRect, DDBLTFAST_SRCCOLORKEY );
  134.         if( ddrval == DD_OK )
  135.         {
  136.         break;
  137.         }
  138.         if( ddrval == DDERR_SURFACELOST )
  139.         {
  140.         ddrval = restoreAll();
  141.         if( ddrval != DD_OK )
  142.         {
  143.             return;
  144.         }
  145.         }
  146.         if( ddrval != DDERR_WASSTILLDRAWING )
  147.         {
  148.         return;
  149.         }
  150.     }
  151.     }
  152.  
  153.     // Flip the surfaces
  154.     while( 1 )
  155.     {
  156.     ddrval = lpDDSPrimary->Flip( NULL, 0 );
  157.     if( ddrval == DD_OK )
  158.     {
  159.         break;
  160.     }
  161.     if( ddrval == DDERR_SURFACELOST )
  162.     {
  163.         ddrval = restoreAll();
  164.         if( ddrval != DD_OK )
  165.         {
  166.         break;
  167.         }
  168.     }
  169.     if( ddrval != DDERR_WASSTILLDRAWING )
  170.     {
  171.         break;
  172.     }
  173.     }
  174.  
  175. } /* updateFrame */
  176.  
  177.  
  178. /*
  179.  * finiObjects
  180.  *
  181.  * finished with all objects we use; release them
  182.  */
  183. static void finiObjects( void )
  184. {
  185.     if( lpDD != NULL )
  186.     {
  187.     if( lpDDSPrimary != NULL )
  188.     {
  189.         lpDDSPrimary->Release();
  190.         lpDDSPrimary = NULL;
  191.     }
  192.     if( lpDDSOne != NULL )
  193.     {
  194.         lpDDSOne->Release();
  195.         lpDDSOne = NULL;
  196.     }
  197.     if( lpDDPal != NULL )
  198.     {
  199.         lpDDPal->Release();
  200.         lpDDPal = NULL;
  201.     }
  202.     lpDD->Release();
  203.     lpDD = NULL;
  204.     }
  205. } /* finiObjects */
  206.  
  207. long FAR PASCAL WindowProc( HWND hWnd, UINT message, 
  208.                 WPARAM wParam, LPARAM lParam )
  209. {
  210.     switch( message )
  211.     {
  212.     case WM_ACTIVATEAPP:
  213.         bActive = wParam;
  214.     break;
  215.  
  216.     case WM_SETCURSOR:
  217.         SetCursor(NULL);
  218.         return TRUE;
  219.  
  220.     case WM_CREATE:
  221.     break;
  222.  
  223.     case WM_KEYDOWN:
  224.     switch( wParam )
  225.     {
  226.     case VK_ESCAPE:
  227.         case VK_F12:
  228.             PostMessage(hWnd, WM_CLOSE, 0, 0);
  229.         break;
  230.     }
  231.     break;
  232.  
  233.     case WM_DESTROY:
  234.         finiObjects();
  235.     PostQuitMessage( 0 );
  236.     break;
  237.     }
  238.  
  239.     return DefWindowProc(hWnd, message, wParam, lParam);
  240.  
  241. } /* WindowProc */
  242.  
  243. /*
  244.  * This function is called if the initialization function fails
  245.  */
  246. BOOL initFail( HWND hwnd )
  247. {
  248.     finiObjects();
  249.     MessageBox( hwnd, "DirectDraw Init FAILED", TITLE, MB_OK );
  250.     DestroyWindow( hwnd );
  251.     return FALSE;
  252.  
  253. } /* initFail */
  254.  
  255. /*
  256.  * doInit - do work required for every instance of the application:
  257.  *          create the window, initialize data
  258.  */
  259. static BOOL doInit( HINSTANCE hInstance, int nCmdShow )
  260. {
  261.     HWND        hwnd;
  262.     WNDCLASS        wc;
  263.     DDSURFACEDESC    ddsd;
  264.     DDSCAPS        ddscaps;
  265.     HRESULT        ddrval;
  266.  
  267.     /*
  268.      * set up and register window class
  269.      */
  270.     wc.style = CS_HREDRAW | CS_VREDRAW;
  271.     wc.lpfnWndProc = WindowProc;
  272.     wc.cbClsExtra = 0;
  273.     wc.cbWndExtra = 0;
  274.     wc.hInstance = hInstance;
  275.     wc.hIcon = LoadIcon( hInstance, IDI_APPLICATION );
  276.     wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  277.     wc.hbrBackground = GetStockBrush(BLACK_BRUSH);
  278.     wc.lpszMenuName = NAME;
  279.     wc.lpszClassName = NAME;
  280.     RegisterClass( &wc );
  281.     
  282.     /*
  283.      * create a window
  284.      */
  285.     hwnd = CreateWindowEx(
  286.         0,
  287.     NAME,
  288.     TITLE,
  289.     WS_POPUP,
  290.     0,
  291.     0,
  292.         GetSystemMetrics(SM_CXSCREEN),
  293.         GetSystemMetrics(SM_CYSCREEN),
  294.     NULL,
  295.     NULL,
  296.     hInstance,
  297.     NULL );
  298.  
  299.     if( !hwnd )
  300.     {
  301.     return FALSE;
  302.     }
  303.  
  304.     ShowWindow( hwnd, nCmdShow );
  305.     UpdateWindow( hwnd );
  306.  
  307.     /*
  308.      * create the main DirectDraw object
  309.      */
  310.     ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
  311.     if( ddrval != DD_OK )
  312.     {
  313.     return initFail(hwnd);
  314.     }
  315.  
  316.     // Get exclusive mode
  317.     ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
  318.     if( ddrval != DD_OK )
  319.     {
  320.     return initFail(hwnd);
  321.     }
  322.  
  323.     // Set the video mode to 640x480x8
  324.     ddrval = lpDD->SetDisplayMode( 640, 480, 8);
  325.     if( ddrval != DD_OK )
  326.     {
  327.     return initFail(hwnd);
  328.     }
  329.  
  330.     // Create the primary surface with 1 back buffer
  331.     ddsd.dwSize = sizeof( ddsd );
  332.     ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  333.     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
  334.               DDSCAPS_FLIP |
  335.               DDSCAPS_COMPLEX;
  336.     ddsd.dwBackBufferCount = 1;
  337.     ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
  338.     if( ddrval != DD_OK )
  339.     {
  340.     return initFail(hwnd);
  341.     }
  342.  
  343.     ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  344.     ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps, &lpDDSBack);
  345.     if( ddrval != DD_OK )
  346.     {
  347.     return initFail(hwnd);
  348.     }
  349.  
  350.     // create and set the palette
  351.     lpDDPal = DDLoadPalette(lpDD, szBitmap);
  352.  
  353.     if (lpDDPal)
  354.         lpDDSPrimary->SetPalette(lpDDPal);
  355.  
  356.     // Create the offscreen surface, by loading our bitmap.
  357.     lpDDSOne = DDLoadBitmap(lpDD, szBitmap, 0, 0);
  358.  
  359.     if( lpDDSOne == NULL )
  360.     {
  361.     return initFail(hwnd);
  362.     }
  363.  
  364.     // Set the color key for this bitmap (black)
  365.     DDSetColorKey(lpDDSOne, RGB(0,0,0));
  366.  
  367.     return TRUE;
  368. } /* doInit */
  369.  
  370. /*
  371.  * WinMain - initialization, message loop
  372.  */
  373. int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
  374.             LPSTR lpCmdLine, int nCmdShow)
  375. {
  376.     MSG        msg;
  377.  
  378.     lpCmdLine = lpCmdLine;
  379.     hPrevInstance = hPrevInstance;
  380.  
  381.     if( !doInit( hInstance, nCmdShow ) )
  382.     {
  383.     return FALSE;
  384.     }
  385.  
  386.     while( 1 )
  387.     {
  388.     if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
  389.     {
  390.         if( !GetMessage( &msg, NULL, 0, 0 ) )
  391.         return msg.wParam;
  392.         TranslateMessage(&msg); 
  393.         DispatchMessage(&msg);
  394.     }
  395.     else if( bActive )
  396.     {
  397.         updateFrame();
  398.         }
  399.         else
  400.         {
  401.             // make sure we go to sleep if we have nothing else to do
  402.             WaitMessage();
  403.         }
  404.     }
  405. } /* WinMain */
  406.