⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 directdraw

📁 Delphi技巧
💻
📖 第 1 页 / 共 2 页
字号:
DirectDraw 游戏编程基础(2)

游戏使计算机的发展超越了晶体管时代
       
      微软公司供稿

例程1(DDEX1):DirectDraw 的基本知识
在使用 DirextDraw时,需要首先创建一个对象DirectDraw 的实体,该对象实体代表了微机显示适配器。然后,使用接口所提供的方法来操作该对象实体,使之完成有关命令和任务。接着,你还需要创建一个或多个 DirectDraw-surface对象的实体,以便能在图形表面(Surface)上展示你的游戏画面。
下面,在例程 DDEX1 中展示如何使用Directx 3 SDK来 DirectDraw对象实体,如何创建一个带有后台缓冲区的基本表面(Surface),以及如何弹出表面(Surface)。

注意:所有的例程都是用C++写成的,如果你的编辑器是C,你需要在文件中作出某些改动(至少,你要加入 Vtable 和指向各种接口方法的 this 指针)。
DirectDraw 初始化:
     DirectDraw 初始化代码写在例程 DDEX1 的 doInit 函数中。

        /*
         * Create the main DirectDraw object.
         */
     ddrval = DirectDrawCreate(NULL,&lpDD,NULL);
     if(ddrval==DD_OK)
       {
         //Get exclusive mode.
         Ddrval=lpdd->SetCooperativeLevel(hwnd,
                              DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN);
         if(ddrval==DD_OK)
           {
             //Create the primary surface with 1 back buffer.
             Ddsd.dwSize = sizeof(ddsd);
             ddsd.dwFlags = DDSD_CAPS \ DSD_BACKBUFFERCOUNT;
             ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | 
                                       DDSCAPS_FLIP |
                                       DDSCAPS_COMPLEX;
             ddsd.dwBackBufferCount = 1;
             ddrval = lpDD->CreateSurfae(&ddsd, &lpDDSPrimary,
           NULL);
             if(ddrval == DD_OK)
              {
               //Cet a pointer to the back buffer.
               Ddscaps.dwCaps = DDSCAPS_BACKBUFFER; 
               ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps,
                                                        &lpDDSBack);
               if( ddrval == DD_OK)
               { // Draw some text.
               If(lpDDSPrimary->GetDC(&hdc) == DD_OK)
               { 
                 SetBkColor(hdc, RGB(0,0,255));
                 SetTextColor( hdc,RGB(255,255,0 ) );
                 TextOut( hdc, 0, 0, sxFrontMsg, lstrlen(szFrontMsg ));
                 lpDDSPrimary->ReleaseDC(hdc);
                 }
                 if(lpDDSBack->GetDC(&hdc) == DD_OK)
                 {
                   SetBkColor( hdc, RGB(0, 0, 255 ) );
                   SetTextColor( hdc, RGB( 255,255, 0 ) ):
                   TexOut( hdc, 0, 0, szBackMsg, lstrlen( szBackMsg ) );
                   lpDDSBack->ReleaseDC(hdc);
                   }
                 // Create a timer to flop the pages.
                 If(SetTimer( hwnd, TIMER_ID, TIMER_RATE, NULL))
                   {
                    return TRUE;
                    }
                 }
              }
            }
          }
        }
        wsprintf(buf,"Direct Draw Init Failed (%08lx)\n",ddrval);
          .
          .
          .

以下针对初始化 DirectDraw 对象和准备表面(Surface)集的各个步骤分别进行讨论:

创建一个 DirectDraw 对象
    为了创建一个 DirecDraw 对象实体,你应该在程序中使用DirectDrawCreate API 函数(注意:这里我所说的是应该,而不是必须), 这是因为使用 OLE 中的 CoCreatelnstance 函数也能创建一个 DirectDraw 对象实体,但这不在我们的讨论范围之中)。DirectDrawCreate 采用全球统一的标准,它代表显示设备,这些显示设备在大多数情况下被定为 NULL (即:系统使用缺省的显示设备)。 当DirectDraw对象实体创建好后,就会有一个指针指向该对象实体。而且,在调色板中有三分之一的指针指向 NULL (这样做的目的是为了今后的扩展)。
接下来的例子说明如何创建一个DirectDraw 对象,并判别该对象是否创建成功:
    ddrval = directDrawCreat( NULL, &lpDD, NULL );
    if( ddrval == DD_OK )
    {
      //lpDD is a valid DirectDraw object.
      }
      else
      {
        //DirectDraw object could not be created.
        }

使用 IDirectDraw2 和 IDirectDrawSurface2 接口

在你读本文的其他部分时,你会注意到所有的例程都使用的是 IDirectDraw和 IDirectDrawSurface 的老版本接口。这是因为 DirectX 3 SDK 所给出的例程还没有来及使用 IDirectDraw 和 IDirectDrawSurface 更新后的接口。你可以通过调用 IDirectDraw::QueryInterface 方法来得到 IDirectDraw2 和IDirectDrawSurface2 接口。
    下面的代码给出如何得到 IDirectDraw2 接口:

       // Create an IDirectDraw2 interface.
       LPDIRECTDRAW lpDD;

       ddrval = DirectDrawCreate( NULL, &lpDD, NULL);
       if(ddrval != DD_OK)
           return;
       ddrval = lpDD->SetCooperativeLevel(hwnd, DDSCL_NORMAL);
       if(ddrval != DD_OK)
           return;
       ddrval = lpDD->QueryInterfave(IID_IDirectDraw2, (lPVOID *)&lpDD2);
       if(ddrval !=DD_OK)
           return;

下面的代码给出如何得到 IDirectDrawSurface2 接口:
       LPDIRECTDRAWSURFACE lpSurf;
       LPDIRECTDRAWSURFACE lpSurf2;

       // Create surfaces.
       Memset( &ddsd, 0, sizeof(ddsd ));
       ddsd.dwSize = sizeof(ddsd);
       ddsd.dwFlags = DDSD_CAPS |DDSD_WIDTH |DDSD_HEIGHT;
       ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | 
                          DDSCAPS_SYSTEMMEMORY;
       ddsd.dwWidth = 10;
       ddsd.dwHeight = 10;

       ddrval = lpDD2->CreateSurface( &ddsd, &lpSurf, NULL);
       if(ddrval != DD_OK)
              return;

       ddrval = lpSurf->QueryInterface( 
              IID_IDirectDrawSurface2, ( LPVOID *(&lpSurf2);

       if(ddrval !=DD_OK)
              return;
设置显示模式
安装DirectDraw 的下一步是设置显示模式。在DirectDraw应用程序中设置显示模式关键有两个步骤:第一,调用Idirectdraw::SetCooperativelevel方法设置底层参数。设置好底层参数后,再调用 IDirectDraw::SetdisplayMode方法来设置显示方式。

确定应用程序的运行特征:
如果你想改变你的显示方式 ,  你必须先在调色板的 dwFlags 中设置    DDSCL_ EXCLUSIVE  和 DDSCL_FULLSCREEN 标志。其中,调色板的dwFlags包含在IDirectDraw::SetCooperativelLevel 方法中。这样一来,你的应用程序就可以单独占用显示设备,而使其它进程不能共享显示设备。 另外 , 标志DDSCL_FULLSCREEN 把显示设备置为全屏幕方式。正如在运行DDWX1时见到的那样,当同时按下ALT键和TAB键后,最初的表面(Surface)(尽管仍然有效)会被你的表面(Surface)所覆盖,且只有你的表面(Surface)能够进行写屏操作。
下面的例子说明如何使用 IDirectDraw::SetCooperativeLevel:
         HRESULT    ddrval;
         LPDIRECTDRAW  lpDD;  // already created by DirectDrawCreate

         ddrval = lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE |
                         DDSCL_FULLSCREEN);
         if(ddrval == DD_OK)
         {
           // exclusive mode was successful
         }
         else
         {
           // not successful
           // however, the application can still run
           }

如果 IDirectDraw::SetCooperativeLevel 不返回 DD_OK,你的应用程序仍能继续执行,但是我不主张这样做。因为这样会使你的程序无法工作在全屏幕模式下,而且可能不按照你预先的要求工作。如果你确实想使你的应用程序继续运行下去,你应该显示一个错误信息,以便使终端用户知道 IDirectDraw ::SetCooperativeLevel 没有返回DD_OK,然后由用户自己去决定是否继续执行该程序。
使用IDirectDraw::SetCooperativeLevel 时,有一个要求:给每一个窗口赋一个句柄。这样当你的应用程序被异常中止时,Windows 能够知道。例如:
    当发生GP错误时,GDI被推入缓冲区,终端用户就再也不能返回到Windows界面。为防止这种情况的发生,DirectDraw 能够在关键时刻执行一个后台过程向前台弹出一定的信息,利用这些信息可以确定应用程序是何时被中止的。这就给应用程序强加了一个限制。首先,你必须给每个窗口赋一个特殊的句柄。通过这些句柄,可以知道应用程序的运行信息。也就是说,要创建一个窗口,你必须设置一个处于活动状态的句柄。否则,无法很好执行许多功能。诸如:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -