将与画面同样大小的图象上下分割,使用计时器纵向卷轴。
这是在 Full Screen Mode(全屏模式) 下应用 mydx8.lib 的一个例子。
以前程序的开头必须要记述的 #define 语句,现在已经在 mydx8.h 中定义好了,所以从程序中把它去掉,别的就没有什么变化了。
使用私有库,如果编译的时候出现如下的错误信息,不必理会。(你再编译一遍,错误信息就没有了。)
LINK : warning LNK4098: defaultlib "LIBC" conflicts with use of other libs; use /NODEFAULTLIB:library
这个程序基本上跟 §13. 背景卷轴 差不多,重写一遍没意思,这回我们把 640*480 的图象上下分割来卷轴。
这个程序的卷轴方法:
1.
准备一张图片,要求它的上端和下端能够自然地拼接。
(下面是我用的图片, 320*240 ,命名为 Flowers.bmp ,放在 G:\DirectX 8\ 下。)
这样的图片上下连续拼接在一起,接合处不会有不自然的感觉:
这样的图片通常在网页中用来铺背景,即所谓的"无缝贴图"。
2.
因为画面的大小是 640*480 ,所以把上面的图片扩展到这个大小,储存在 BmpSurface :
if (FAILED(hr= g_pDisplay-CreateSurfaceFromBitmap(&g_pBmpSurface,
"G:\\DirectX 8\\Flowers.bmp",640,480)))
return hr;
3.
启动计时器控制卷轴速度。
指定计时间隔 20 毫秒:
#define
ID_TIMER
32767
:
SetTimer(hWnd,ID_TIMER,20,NULL);
4.
在计时器(WM_TIMER)中计数 g_cnt :
int
g_cnt
= 0;
:
case WM_TIMER:
g_cnt++;
break;
5.
把背景图象上下分割、卷轴描绘。
清空 BackBuffer ,对 RECT 结构体设定左右坐标。
因为画面大小是 640*480 ,设定如下:
RECT
rt;
int
dt;
g_pDisplay-Clear(0);
rt.left= 0;
rt.right= 640;
上部分的描绘。
上部分描绘图片的纵坐标从 dt 到底部(rt.bottom= 480)之间的部分,dt 的值在 0~479 之间循环, dt 越大,描绘的上部分的高度就越小:
dt= g_cnt%480;
rt.top= dt;
rt.bottom= 480;
g_pDisplay-Blt(0,0,g_pBmpSurface,&rt);
下部分的描绘。
下部分描绘图片的纵坐标从顶部(rt.top= 0)到 dt 之间的部分,dt 越大,描绘的下部分的高度也越大:
rt.top= 0;
rt.bottom= dt;
g_pDisplay-Blt(0,480-dt,g_pBmpSurface,&rt);
6.
上部分的描绘范围慢慢变窄、下部分的描绘范围慢慢变高,就这样循环下去。
如果你准备的背景图片不合适,上端和下端不能自然地衔接,卷轴的时候就不好看,
7.
退出程序时关闭计时器:
case WM_DESTROY:
KillTimer(hWnd, ID_TIMER);
创建窗口的代码。
640*480 是窗口的初始大小,但在全屏模式下这个数值没有意义,我们还用 CreateFullScreenDisplay() 来设定画面大小:
HWND hWnd = CreateWindow(NAME,NAME,WS_OVERLAPPEDWINDOW,0,0,640,480,
GetDesktopWindow(),NULL,wc.hInstance,NULL);
if (hWnd==NULL)
return FALSE;
决定全屏模式下画面大小(画面的解析度)的代码。
640,480,16 三个值分别表示画面的宽度、高度和颜色模式。
只能指定为你的显示器支持的显示模式。
g_pDisplay = new CDisplay();
if (FAILED(hr= g_pDisplay-CreateFullScreenDisplay(hWnd, 640, 480, 16)))
{
ERMSG("This display card does not support 640x480x16.");
return hr;
}
下面说明工程的创建方法。
首先请确认你的 mydx8.lib 和 mydx8.h 已经安放在 \Mssdk\ 下的指定位置。
私有库的引入进一步简化了工程的创建。
1.
新建一个 Win32 Application 空白工程,命名为 "VScrool"。
2.
准备合适的图象文件(我是在 G:\DirectX 8\ 下放了张 "Flowers.bmp" ,参见本章开头)。
3.
向工程中新建一个 C++ Source File ,命名为 "vscrool" ,向其中键入篇末附带的源程序。
4.
选择菜单 [Project|工程]-[Settings...|设定...] 打开[Project Settings|工程设定] 面板,点击 [Link|链接] 标签,向 [Object/library modules|对象、库模块] 栏内添加下面4个库文件:
mydx8.lib
dxguid.lib
ddraw.lib
dxerr8.lib
5.
编译并执行!
源程序:
/****************************************************************************/
/*★ Full Screen Mode(全屏模式) 下纵卷轴背景图象
2001-01-21
前田 稔 ★*/
/****************************************************************************/
#define
NAME
"Scrool"
#define
STRICT
#include
// Defines, constants, and global variables
CDisplay*
g_pDisplay
= NULL;
CSurface*
g_pBmpSurface = NULL;
BOOL
g_bActive
= FALSE;
int
g_cnt= 0;
// Function-prototypes
LRESULT
CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HRESULT
InitDraw(HWND hWnd);
VOID
FreeDirectDraw();
HRESULT
DisplayFrame();
//★ Windows Main
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow)
{
MSG
msg;
WNDCLASS wc = { CS_CLASSDC,WndProc,0L,0L,hInst,
NULL,NULL,NULL,NULL,NAME };
if (RegisterClass(&wc)==0)
return FALSE;
HWND hWnd = CreateWindow(NAME,NAME,WS_OVERLAPPEDWINDOW,0,0,640,480,
GetDesktopWindow(),NULL,wc.hInstance,NULL);
if (hWnd==NULL)
return FALSE;
if (FAILED(InitDraw(hWnd)))
{
if (g_pDisplay)
g_pDisplay-GetDirectDraw()-SetCooperativeLevel(NULL, DDSCL_NORMAL);
ERMSG("DirectDraw init failed. The sample will now exit.");
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
SetTimer(hWnd,0,20,NULL);
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");
return FALSE;
}
}
else
WaitMessage();
}
}
}
//★ WndProc()
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_KEYDOWN:
PostMessage(hWnd, WM_CLOSE, 0, 0);
return 0L;
case WM_TIMER:
g_cnt++;
break;
case WM_SIZE:
if (SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam)
g_bActive = FALSE;
else
g_bActive = TRUE;
break;
case WM_SETCURSOR:
//隐藏光标
SetCursor(NULL);
return TRUE;
case WM_SYSCOMMAND:
switch(wParam)
{
case SC_MOVE:
case SC_SIZE:
case SC_MAXIMIZE:
case SC_MONITORPOWER:
return TRUE;
}
break;
case WM_DESTROY:
KillTimer(hWnd, 0);
FreeDirectDraw();
PostQuitMessage(0);
return 0L;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
//★ InitDraw()
HRESULT InitDraw(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;
}
if (FAILED(hr= g_pDisplay-CreateSurfaceFromBitmap(&g_pBmpSurface,
"G:\\DirectX 8\\Flowers.bmp",640,480)))
return hr;
return S_OK;
}
//★ DisplayFrame()
HRESULT DisplayFrame()
{
HRESULT hr;
RECT
rt;
int
dt;
g_pDisplay-Clear(0);
rt.left= 0;
rt.right= 640;
dt= g_cnt%480;
rt.top= dt;
rt.bottom= 480;
g_pDisplay-Blt(0,0,g_pBmpSurface,&rt);
rt.top= 0;
rt.bottom= dt;
g_pDisplay-Blt(0,480-dt,g_pBmpSurface,