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 / ddex5 / ddex5.cpp < prev    next >
C/C++ Source or Header  |  1997-07-14  |  11KB  |  502 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File:    ddex5.cpp
  6.  *  Content:    Direct Draw example program 5.    Adds functionality to
  7.  *        example program 4.  Uses GetEntries() to read a palette,
  8.  *        modifies the entries, and then uses SetEntries() to update
  9.  *        the palette.  This program requires 1.2 Meg of video ram.
  10.  *
  11.  ***************************************************************************/
  12.  
  13. #define NAME "DDExample5"
  14. #define TITLE "Direct Draw Example 5"
  15.  
  16. #define WIN32_LEAN_AND_MEAN
  17. #include <windows.h>
  18. #include <windowsx.h>
  19. #include <ddraw.h>
  20. #include "resource.h"
  21. #include "ddutil.h"
  22.  
  23. char szBitmap[] = "ALL";
  24.  
  25. LPDIRECTDRAW        lpDD;        // DirectDraw object
  26. LPDIRECTDRAWSURFACE    lpDDSPrimary;    // DirectDraw primary surface
  27. LPDIRECTDRAWSURFACE    lpDDSBack;    // DirectDraw back surface
  28. LPDIRECTDRAWSURFACE    lpDDSOne;    // Offscreen surface 1
  29. LPDIRECTDRAWPALETTE    lpDDPal;    // The primary surface palette
  30. BOOL            bActive;    // is application active?
  31.  
  32. BYTE torusColors[256];    // Marks the colors used in the torus
  33.  
  34. /*
  35.  * restoreAll
  36.  *
  37.  * restore all lost objects
  38.  */
  39. HRESULT restoreAll( void )
  40. {
  41.     HRESULT    ddrval;
  42.     DDSURFACEDESC    ddsd;
  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.  
  54.     //Loose the old palette
  55.     lpDDPal->Release();
  56.     // create and set the palette (restart cycling from the same place)
  57.     lpDDPal = DDLoadPalette(lpDD, szBitmap);
  58.  
  59.     if (lpDDPal)
  60.         lpDDSPrimary->SetPalette(lpDDPal);
  61.     //
  62.     // Mark the colors used in the torus frames
  63.     //
  64.     int i,x,y;
  65.  
  66.     // First, set all colors as unused
  67.     for(i=0; i<256; i++)
  68.     {
  69.         torusColors[i] = 0;
  70.     }
  71.  
  72.     // lock the surface and scan the lower part (the torus area)
  73.     // and remember all the index's we find.
  74.     ddsd.dwSize = sizeof(ddsd);
  75.     while (lpDDSOne->Lock(NULL, &ddsd, 0, NULL) == DDERR_WASSTILLDRAWING)
  76.         ;
  77.  
  78.     // Now search through the torus frames and mark used colors
  79.     for( y=480; y<480+384; y++ )
  80.     {
  81.         for( x=0; x<640; x++ )
  82.         {
  83.             torusColors[((BYTE *)ddsd.lpSurface)[y*ddsd.lPitch+x]] = 1;
  84.         }
  85.     }
  86.  
  87.     lpDDSOne->Unlock(NULL);
  88.  
  89.     return ddrval;
  90.  
  91. } /* restoreAll */
  92.  
  93. /*
  94.  * updateFrame
  95.  * 
  96.  * Decide what needs to be blitted next, wait for flip to complete,
  97.  * then flip the buffers.
  98.  */
  99. void updateFrame( void )
  100. {
  101.     static DWORD    lastTickCount[4] = {0,0,0,0};
  102.     static int        currentFrame[3] = {0,0,0};
  103.     DWORD        thisTickCount;
  104.     RECT        rcRect;
  105.     DWORD        delay[4] = {50, 78, 13, 93};
  106.     int            i;
  107.     int            xpos[3] = {288, 190, 416};
  108.     int            ypos[3] = {128, 300, 256};
  109.     PALETTEENTRY    pe[256];
  110.     HRESULT        ddrval;
  111.  
  112.     // Decide which frame will be blitted next
  113.     thisTickCount = GetTickCount();
  114.     for(i=0; i<3; i++)
  115.     {
  116.     if((thisTickCount - lastTickCount[i]) > delay[i])
  117.     {
  118.         // Move to next frame;
  119.         lastTickCount[i] = thisTickCount;
  120.         currentFrame[i]++;
  121.         if(currentFrame[i] > 59)
  122.         currentFrame[i] = 0;
  123.     }
  124.     }
  125.  
  126.     // Blit the stuff for the next frame
  127.     rcRect.left = 0;
  128.     rcRect.top = 0;
  129.     rcRect.right = 640;
  130.     rcRect.bottom = 480;
  131.     while( 1 )
  132.     {
  133.         ddrval = lpDDSBack->BltFast( 0, 0, lpDDSOne,
  134.             &rcRect, DDBLTFAST_NOCOLORKEY );
  135.  
  136.     if( ddrval == DD_OK )
  137.     {
  138.         break;
  139.     }
  140.     if( ddrval == DDERR_SURFACELOST )
  141.     {
  142.         ddrval = restoreAll();
  143.         if( ddrval != DD_OK )
  144.         {
  145.         return;
  146.         }
  147.     }
  148.     if( ddrval != DDERR_WASSTILLDRAWING )
  149.     {
  150.         return;
  151.     }
  152.     }
  153.     if(ddrval != DD_OK)
  154.     {
  155.         return;
  156.     }
  157.  
  158.     for(i=0; i<3; i++)
  159.     {
  160.         rcRect.left   = currentFrame[i]%10*64;
  161.         rcRect.top    = currentFrame[i]/10*64 + 480;
  162.         rcRect.right  = currentFrame[i]%10*64 + 64;
  163.         rcRect.bottom = currentFrame[i]/10*64 + 64 + 480;
  164.  
  165.     while( 1 )
  166.     {
  167.         ddrval = lpDDSBack->BltFast( xpos[i], ypos[i], lpDDSOne,
  168.                                  &rcRect, DDBLTFAST_SRCCOLORKEY );
  169.  
  170.         if( ddrval == DD_OK )
  171.         {
  172.         break;
  173.         }
  174.         if( ddrval == DDERR_SURFACELOST )
  175.         {
  176.         ddrval = restoreAll();
  177.         if( ddrval != DD_OK )
  178.         {
  179.             return;
  180.         }
  181.         }
  182.         if( ddrval != DDERR_WASSTILLDRAWING )
  183.         {
  184.         return;
  185.         }
  186.     }
  187.     }
  188.  
  189.     if( (thisTickCount - lastTickCount[3]) > delay[3] )
  190.     {
  191.     // Change the palette
  192.     if(lpDDPal->GetEntries( 0, 0, 256, pe ) != DD_OK)
  193.     {
  194.         return;
  195.     }
  196.     
  197.     for(i=1; i<256; i++)
  198.     {
  199.         if(!torusColors[i])
  200.         {
  201.         continue;
  202.         }
  203.         pe[i].peRed = (pe[i].peRed+2) % 256;
  204.         pe[i].peGreen = (pe[i].peGreen+1) % 256;
  205.         pe[i].peBlue = (pe[i].peBlue+3) % 256;
  206.     }
  207.     if(lpDDPal->SetEntries( 0, 0, 256, pe) != DD_OK)
  208.     {
  209.         return;
  210.     }
  211.     
  212.     lastTickCount[3] = thisTickCount;
  213.     }
  214.     
  215.     // Flip the surfaces
  216.     while( 1 )
  217.     {
  218.     ddrval = lpDDSPrimary->Flip( NULL, 0 );
  219.     if( ddrval == DD_OK )
  220.     {
  221.         break;
  222.     }
  223.     if( ddrval == DDERR_SURFACELOST )
  224.     {
  225.         ddrval = restoreAll();
  226.         if( ddrval != DD_OK )
  227.         {
  228.         break;
  229.         }
  230.     }
  231.     if( ddrval != DDERR_WASSTILLDRAWING )
  232.     {
  233.         break;
  234.     }
  235.     }
  236.  
  237. } /* updateFrame */
  238.  
  239. /*
  240.  * finiObjects
  241.  *
  242.  * finished with all objects we use; release them
  243.  */
  244. static void finiObjects( void )
  245. {
  246.     if( lpDD != NULL )
  247.     {
  248.     if( lpDDSPrimary != NULL )
  249.     {
  250.         lpDDSPrimary->Release();
  251.         lpDDSPrimary = NULL;
  252.     }
  253.     if( lpDDSOne != NULL )
  254.     {
  255.         lpDDSOne->Release();
  256.         lpDDSOne = NULL;
  257.     }
  258.     if( lpDDPal != NULL )
  259.     {
  260.         lpDDPal->Release();
  261.         lpDDPal = NULL;
  262.     }
  263.     lpDD->Release();
  264.     lpDD = NULL;
  265.     }
  266.  
  267. } /* finiObjects */
  268.  
  269. long FAR PASCAL WindowProc( HWND hWnd, UINT message, 
  270.                 WPARAM wParam, LPARAM lParam )
  271. {
  272.     switch( message )
  273.     {
  274.     case WM_ACTIVATEAPP:
  275.         bActive = wParam;
  276.     break;
  277.  
  278.     case WM_SETCURSOR:
  279.         SetCursor(NULL);
  280.         return TRUE;
  281.  
  282.     case WM_CREATE:
  283.     break;
  284.  
  285.     case WM_KEYDOWN:
  286.     switch( wParam )
  287.     {
  288.     case VK_ESCAPE:
  289.         case VK_F12:
  290.             PostMessage(hWnd, WM_CLOSE, 0, 0);
  291.         break;
  292.     }
  293.     break;
  294.  
  295.     case WM_DESTROY:
  296.         finiObjects();
  297.     PostQuitMessage( 0 );
  298.     break;
  299.     }
  300.  
  301.     return DefWindowProc(hWnd, message, wParam, lParam);
  302.  
  303. } /* WindowProc */
  304.  
  305.  
  306.  
  307. /*
  308.  * This function is called if the initialization function fails
  309.  */
  310. BOOL initFail( HWND hwnd )
  311. {
  312.     finiObjects();
  313.     MessageBox( hwnd, "DirectDraw Init FAILED", TITLE, MB_OK );
  314.     DestroyWindow( hwnd );
  315.     return FALSE;
  316.  
  317. } /* initFail */
  318.  
  319. /*
  320.  * doInit - do work required for every instance of the application:
  321.  *          create the window, initialize data
  322.  */
  323. static BOOL doInit( HINSTANCE hInstance, int nCmdShow )
  324. {
  325.     HWND        hwnd;
  326.     WNDCLASS        wc;
  327.     DDSURFACEDESC    ddsd;
  328.     DDSCAPS        ddscaps;
  329.     HRESULT        ddrval;
  330.  
  331.     /*
  332.      * set up and register window class
  333.      */
  334.     wc.style = CS_HREDRAW | CS_VREDRAW;
  335.     wc.lpfnWndProc = WindowProc;
  336.     wc.cbClsExtra = 0;
  337.     wc.cbWndExtra = 0;
  338.     wc.hInstance = hInstance;
  339.     wc.hIcon = LoadIcon( hInstance, IDI_APPLICATION );
  340.     wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  341.     wc.hbrBackground = GetStockBrush(BLACK_BRUSH);
  342.     wc.lpszMenuName = NAME;
  343.     wc.lpszClassName = NAME;
  344.     RegisterClass( &wc );
  345.  
  346.     /*
  347.      * create a window
  348.      */
  349.     hwnd = CreateWindowEx(
  350.         0,
  351.     NAME,
  352.     TITLE,
  353.     WS_POPUP,
  354.     0,
  355.     0,
  356.         GetSystemMetrics(SM_CXSCREEN),
  357.         GetSystemMetrics(SM_CYSCREEN),
  358.     NULL,
  359.     NULL,
  360.     hInstance,
  361.         NULL );
  362.  
  363.     if( !hwnd )
  364.     {
  365.     return FALSE;
  366.     }
  367.  
  368.     ShowWindow( hwnd, nCmdShow );
  369.     UpdateWindow( hwnd );
  370.     SetFocus( hwnd );
  371.  
  372.     /*
  373.      * create the main DirectDraw object
  374.      */
  375.     ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
  376.     if( ddrval != DD_OK )
  377.     {
  378.     return initFail(hwnd);
  379.     }
  380.  
  381.     // Get exclusive mode
  382.     ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
  383.     if( ddrval != DD_OK )
  384.     {
  385.     return initFail(hwnd);
  386.     }
  387.  
  388.     // Set the video mode to 640x480x8
  389.     ddrval = lpDD->SetDisplayMode( 640, 480, 8);
  390.     if(ddrval != DD_OK)
  391.     {
  392.     return initFail(hwnd);
  393.     }
  394.  
  395.     // Create the primary surface with 1 back buffer
  396.     ddsd.dwSize = sizeof( ddsd );
  397.     ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  398.     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
  399.               DDSCAPS_FLIP |
  400.               DDSCAPS_COMPLEX;
  401.     ddsd.dwBackBufferCount = 1;
  402.     ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
  403.     if( ddrval != DD_OK )
  404.     {
  405.     return initFail(hwnd);
  406.     }
  407.  
  408.     ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  409.     ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps, &lpDDSBack);
  410.     if( ddrval != DD_OK )
  411.     {
  412.     return initFail(hwnd);
  413.     }
  414.  
  415.     // create and set the palette
  416.     lpDDPal = DDLoadPalette(lpDD, szBitmap);
  417.  
  418.     if (lpDDPal)
  419.         lpDDSPrimary->SetPalette(lpDDPal);
  420.  
  421.     // Create the offscreen surface, by loading our bitmap.
  422.     lpDDSOne = DDLoadBitmap(lpDD, szBitmap, 0, 0);
  423.  
  424.     if( lpDDSOne == NULL )
  425.     {
  426.     return initFail(hwnd);
  427.     }
  428.  
  429.     // set the color key to black
  430.     DDSetColorKey(lpDDSOne, RGB(0,0,0));
  431.  
  432.     //
  433.     // Mark the colors used in the torus frames
  434.     //
  435.     int i,x,y;
  436.  
  437.     // First, set all colors as unused
  438.     for(i=0; i<256; i++)
  439.     {
  440.         torusColors[i] = 0;
  441.     }
  442.  
  443.     // lock the surface and scan the lower part (the torus area)
  444.     // and remember all the index's we find.
  445.     ddsd.dwSize = sizeof(ddsd);
  446.     while (lpDDSOne->Lock(NULL, &ddsd, 0, NULL) == DDERR_WASSTILLDRAWING)
  447.         ;
  448.  
  449.     // Now search through the torus frames and mark used colors
  450.     for( y=480; y<480+384; y++ )
  451.     {
  452.         for( x=0; x<640; x++ )
  453.         {
  454.             torusColors[((BYTE *)ddsd.lpSurface)[y*ddsd.lPitch+x]] = 1;
  455.         }
  456.     }
  457.  
  458.     lpDDSOne->Unlock(NULL);
  459.  
  460.     return TRUE;
  461.  
  462. } /* doInit */
  463.  
  464. /*
  465.  * WinMain - initialization, message loop
  466.  */
  467. int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
  468.             LPSTR lpCmdLine, int nCmdShow)
  469. {
  470.     MSG        msg;
  471.  
  472.     lpCmdLine = lpCmdLine;
  473.     hPrevInstance = hPrevInstance;
  474.  
  475.     if( !doInit( hInstance, nCmdShow ) )
  476.     {
  477.     return FALSE;
  478.     }
  479.  
  480.     while( 1 )
  481.     {
  482.     if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
  483.     {
  484.         if( !GetMessage( &msg, NULL, 0, 0 ) )
  485.         {
  486.         return msg.wParam;
  487.         }
  488.         TranslateMessage(&msg); 
  489.         DispatchMessage(&msg);
  490.     }
  491.     else if( bActive )
  492.     {
  493.         updateFrame();
  494.         }
  495.         else
  496.         {
  497.             // make sure we go to sleep if we have nothing else to do
  498.             WaitMessage();
  499.         }
  500.     }
  501. } /* WinMain */
  502.