游戏编程最基本的还是图象,下面就试着来显示真彩(24位)图象。
随便什么图象都行,我们用 SDK 的样品位图,图个省事。
基本上跟上节的显示文本文字("Hello DirectX 8 !")类似,借助 Common 文件夹内的4个文件,大大简化了源代码。看看那4个文件吧,以前需要辛辛苦苦动手编出来的代码现在都在那里摆着,现成的。真高兴微软肯公布这样的源代码。
程序的执行过程如下:
1.
创建窗口;
2.
初始化 DirectDraw ;
3.
创建 Surface(表面) 储存位图;
4.
进入消息循环;
5.
于循环中反复描绘位图;
6.
按任意键退出。
DirectDraw 的 global(全局) 领域。
Display 和储存图象的 Sueface(用于描绘的内存区域),
g_bActive 是 DirectDraw 初始化成功的标志。
CDisplay*
g_pDisplay
= NULL;
CSurface*
g_pBmpSurface = NULL;
BOOL
g_bActive
= FALSE;
初始化 DirectDraw 代码。
"640, 480, 16" 分别是画面的宽度、高度和颜色模式;
若初始化失败就显示错误信息并返回;
然后创建 BMP Sueface(用于描绘的内存区域) 并储存图象;
图象直接指定为保存在同一目录下的位图文件(animate.bmp);
""*.bmp", 0, 0" 中的 "0, 0" 分别指定储存图象的 Surface 的宽度和高度,但是输入0的时候表示自动适合图象大小。
HRESULT InitDirectDraw(HWND hWnd)
{
HRESULT
hr;
g_pDisplay = new CDisplay();
if (FAILED(hr = g_pDisplay-CreateFullScreenDisplay(hWnd, 640, 480, 16)))
{
ERMSG("This display card does not support 640x480x16.");
return hr;
}
// Create a surface, and draw a bitmap resource on it.
if (FAILED(hr = g_pDisplay-CreateSurfaceFromBitmap(&g_pBmpSurface,
"animate.bmp",0,0)))
return hr;
return S_OK;
}
消息循环。
没有收到消息时用 DisplayFrame() 函数进行画面描绘;
DirectX 即使每次都显示同样的内容也都要先清空了 Sueface 再重新描绘、配合垂直同期信号来切换画面。
while(TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (0 == GetMessage(&msg, NULL, 0, 0))
return (int)msg.wParam;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
if (g_bActive)
{
if (FAILED(DisplayFrame()))
{
SAFE_DELETE(g_pDisplay);
ERMSG("Displaying the next frame failed. The sample will now exit.");
return FALSE;
}
}
else
WaitMessage();
}
}
描绘代码。
用 Clear() 清空 DisplaySurface ;
也可以象 Clear(RGB(255,0,0)) 这种格式,用 R,G,B(0~255) 来指定要清除的颜色;
用 Blt() 描绘图象;
用 Present() 换帧。
HRESULT DisplayFrame()
{
HRESULT hr;
// Fill the back buffer with black, ignoring errors until the flip
g_pDisplay-Clear(0);
// Blt all the sprites onto the back buffer.
g_pDisplay-Blt(0, 0, g_pBmpSurface, NULL);
// We are in fullscreen mode, so perform a flip and return
if (FAILED(hr = g_pDisplay-Present())) return hr;
return S_OK;
}
下面说明建立工程的步骤:
1.
新建一个 Win32 Application 空白工程,命名为 "Bmp"。
2.
向工程中新建一个 C++ Source File ,命名为 "bmp" ,向其中键入篇末附带的源程序。
3.
从 DirectX 样品文件夹(E:\Mssdk\samples\Multimedia\DirectDraw\SpriteAnimate)复制文件 animate.bmp 到 Bmp 文件夹(G:\DirectX 8\Bmp) :
4.
选择菜单 [Project|工程]-[Settings...|设定] 打开[Project Settings|工程设定] 面板,点击 [Link|链接] 标签,向 [Object/library modules|对象、库模块] 栏内添加下面四个库文件:
dxguid.lib
ddraw.lib
dxerr8.lib
winmm.lib
(参见 §08. 显示 Hello DirectX 8 !)
5.
点击 [C/C++] 标签,设定 include 文件的路径(参见 §04. 移动样品到另外的文件夹):
6.
新建 Common 文件夹并向其中添加下面4个文件:
ddutil.h
dxutil.h
ddutil.cpp
dxutil.cpp
(参见 §04. 移动样品到另外的文件夹)
7.
编译并执行!
源程序:
/**********************************************************/
/*★ 用 DirectX 8 显示 BMP 图象
2000-12-21
前田 稔 ★*/
/**********************************************************/
#define
STRICT
#include
#include
#include
#include
"ddutil.h"
// Defines, constants, and global variables
#define SAFE_DELETE(p)
{ if (p) { delete (p);
(p)=NULL; } }
#define SAFE_RELEASE(p) { if (p) { (p)-Release(); (p)=NULL; } }
#define ERMSG(x)
MessageBox(hWnd, x, "DirectDraw", MB_OK);
CDisplay*
g_pDisplay
= NULL;
CSurface*
g_pBmpSurface = NULL;
BOOL
g_bActive
= FALSE;
// Function-prototypes
LRESULT
CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
HRESULT
WinInit(HINSTANCE hInst, int nCmdShow, HWND* phWnd);
HRESULT
InitDirectDraw(HWND hWnd);
VOID
FreeDirectDraw();
HRESULT
DisplayFrame();
//★ Windows Main
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow)
{
MSG
msg;
HWND
hWnd;
if (FAILED(WinInit(hInst, nCmdShow, &hWnd)))
return FALSE;
if (FAILED(InitDirectDraw(hWnd)))
{
if (g_pDisplay)
g_pDisplay-GetDirectDraw()-SetCooperativeLevel(NULL, DDSCL_NORMAL);
ERMSG("DirectDraw init failed. The sample will now exit.");
return FALSE;
}
while(TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (0 == GetMessage(&msg, NULL, 0, 0))
return (int)msg.wParam;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
if (g_bActive)
{
if (FAILED(DisplayFrame()))
{
SAFE_DELETE(g_pDisplay);
ERMSG("Displaying the next frame failed. The sample will now exit.");
return FALSE;
}
}
else
WaitMessage();
}
}
}
//★ WinInit()
HRESULT WinInit(HINSTANCE hInst, int nCmdShow, HWND* phWnd)
{
WNDCLASS wc;
HWND
hWnd;
// Register the Window Class
wc.lpszClassName = TEXT("BMP View");
wc.lpfnWndProc
= MainWndProc;
wc.style
= CS_VREDRAW | CS_HREDRAW;
wc.hInstance
= hInst;
wc.hIcon
= LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor
= LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wc.lpszMenuName
= NULL;
wc.cbClsExtra
= 0;
wc.cbWndExtra
= 0;
if (RegisterClass(&wc) == 0)
return E_FAIL;
// Create and show the main window
hWnd = CreateWindowEx(0, TEXT("BMP View"), TEXT("DirectDraw BMP View"),
WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL);
if (hWnd==NULL)
return E_FAIL;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
*phWnd = hWnd;
return S_OK;
}
//★ InitDirectDraw()
HRESULT InitDirectDraw(HWND hWnd)
{
HRESULT
hr;
g_pDisplay = new CDisplay();
if (FAILED(hr = g_pDisplay-CreateFullScreenDisplay(hWnd, 640, 480, 16)))
{
ERMSG("This display card does not support 640x480x16.");
return hr;
}
// Create a surface, and draw a bitmap resource on it.
if (FAILED(hr = g_pDisplay-CreateSurfaceFromBitmap(&g_pBmpSurface,
"animate.bmp",0,0)))