GAPI编程实践
(发布时间2000年6月2日)
尽管在Pocket PC平台上,游戏开发人员不能使用DirectDraw 来开发游戏,但最近有一个好消息,就是 Microsoft 专门为Pocket PC新开发了一个名叫“GAPI”的游戏API (Game Application Interface)。它不仅可以直接访问显示内存,而且可以访问Pocket PC硬件按键。
您需要具备GAPI SDK、运行动态链接库(Runtime DLLs),以及 位于EVTools 第二张光盘“PocketPCSDK/Program Files/Support/GameAPI”目录下的一个示例程序。
步骤1:创建一个示例程序“Hello World” GAPI 没有集成在Pocket PC SDK之中。所以要进行一些预备步骤:
手动地把“GX.H”包含文件复制到Pocket PC SDK的“Include”目录下。 把依赖CPU类型“GX.LIB”文件复制到Pocket PC SDK的相应“Lib”目录下。 最后,把依赖CPU类型的“GX.DLL” 文件复制到Pocket PC的“Windows”目录。
现在,您可以开始建立您的第一个简单的“Hello World” 程序了。 启动eMbedded Visual C++,创建一个新的Pocket PC应用程序,然后把它命名为“FirstGX”。 在向导创建了新工程后,让我们添加GAPI初始化调用。 把下面的代码行添加到InitInstance 函数的末尾:
// Try opening the Display for Full screen access
if (GXOpenDisplay(hWnd, GX_FULLSCREEN) == 0) {
return FALSE; // we won't be able to draw.
}
// Initialize the Hardware Buttons
GXOpenInput();
// Get the Display properties
g_gxdp = GXGetDisplayProperties();
// Get information about the Hardware Keys and fills
// the g_gxkl structure
g_gxkl = GXGetDefaultKeys(GX_NORMALKEYS);
return TRUE;
这段代码使用了必须在FirstGX.cpp 源文件的全局空间里定义的两个变量。为避免编译错误,我们还必须我们的代码里包含进GX.H 文件:
直接在eMbedded Visual C++ 向导创建的包含文件中添加以下行:
#include "gx.h"
GXDisplayProperties g_gxdp; // GX struct
GXKeyList g_gxkl; // GX struct
我们应该在关闭应用程序之前将Game API 清理干净。 在WinMain 函数的末尾插入下面两行代码:
GXCloseDisplay();
GXCloseInput();
步骤2:直接在显示内存中进行写操作
在我们开始编写代码之前,我们必须回忆一下。根据Pocket PC硬件的不同,您可能有16位的彩色显示器(Casio、HP、或Compaq)或者8位的显示器(黑白或彩色,例如Compaq Aero 1550)。为了断定您的Pocket PC显示器是什么样的,您可以检查一下g_gxdp 结构的cBPP成员。它会告诉您您的显示器究竟是多少位的。
在直接访问16位显示的显示内存之前,您必须要知道显示控制器是如何来解释16位色彩掩码的。有两种可能的标志设置:KfDirect555 和 kfDirect565。555 把一个 XRRRRRGG.GGGBBBBB色彩掩码转换成Red-Green-Blue形式的短变量,而565 会把它转换成RRRRRXGG.GGGBBBBB的形式。
在8位的彩色显示设备上,您可以使用一个字节来表示256种颜色。 现在,我们可以直接写屏了。我们想在这些键中的一个键被按下的时候,用一种颜色填充整个屏幕。 在FirstGX.cpp 源文件的顶部添加以下函数:
bool ClearScreen(int colRed,int colGreen, int colBlue)
{
// 16 bit per pixel code. Note 2 different pixel formats.
switch (g_gxdp.cBPP)
{
case 16: {
unsigned short PixelCol = 0;
if (g_gxdp.ffFormat | kfDirect565) {
PixelCol = (unsigned short)
((colRed & 0xff)<< 11 |
(colGreen & 0xff) << 5 |
(colBlue & 0xff));
} else if (g_gxdp.ffFormat | kfDirect555) {
PixelCol = (unsigned short)
((colRed & 0xff)<< 10 |
(colGreen & 0xff) << 5 |
(colBlue & 0xff));
}
unsigned short * pusLine = (unsigned short *)GXBeginDraw();
if (pusLine == NULL) return false; // NOT OK TO DRAW
for (unsigned int y = 0; y < g_gxdp.cyHeight; y++) {
unsigned short * pusDest = pusLine;
for (unsigned int x = 0;
x < g_gxdp.cxWidth; x++) {
*pusDest = PixelCol;
pusDest += g_gxdp.cbxPitch >> 1;
}
pusLine += g_gxdp.cbyPitch >> 1;
}
GXEndDraw();
break;
}
case 8: {
// Get a Random Color
// IMPORTANT:
// 8Bit are using a palette and the formular
// below does not compute a read RGB color
unsigned char bPixel = (colRed &0xf)<<5 |
(colGreen&0x3)<<3 |
(colBlue&0xF);
unsigned char * pbLine = (unsigned char *)GXBeginDraw();
if (pbLine == NULL) return false;// NOT OK TO DRAW
for (unsigned int y = 0; y < g_gxdp.cyHeight; y++) {
unsigned char * pbDest = pbLine;
for (unsigned int x = 0;
x < g_gxdp.cxWidth; x++) {
*pbDest = bPixel;
pbDest += g_gxdp.cbxPitch;
}
pbLine += g_gxdp.cbyPitch;
}
GXEndDraw();
break;
}
}
return false;
}
步骤3:访问硬件按键
这是个很简单的任务。您应该很熟悉Windows的“WM_messages” ,并且知道如何使用它们。了解了这些知识,您就知道了如何来使用Pocket PC硬件按键。只要分析一下Windows过程中的WM_KEYUP 或 WM_KEYDOWN 消息即可。
这里是我的FirstGX 程序的WM_KEYDOWN 分支:
case WM_KEYDOWN:
vkKey = (short)wParam;
if (vkKey == g_gxkl.vkUp) {
ClearScreen(0,0,0); // Black
break;
}
if (vkKey == g_gxkl.vkDown) {
ClearScreen(255,0,0); // Red
break;
}
if (vkKey == g_gxkl.vkLeft) {
ClearScreen(0,255,0); // Green
break;
}
if (vkKey == g_gxkl.vkRight) {
ClearScreen(0,0,255); // Blue
break;
}
if (vkKey == g_gxkl.vkStart) {
SendMessage(hWnd, WM_CLOSE, 0, 0);
break;
}
所有可能的按键名称列表可以在gx.h 包含文件的GXKeyList 结构中找到。
步骤3:准备运行!
在我们开始编译并把我们的FirstGX 程序下载到Pocket PC上之前,我们必须在工程的库文件列表中添加gx.lib 文件。然后,我们可以编译这个程序,并把它下载到我们的Pocket PC上。运行它,按一下键,看看会发生什么?
结论
正如您看见的,Game API很简单,但是已经足够强大了,它能满足我们编写快速动作游戏的全部需要。本示例展示了如何使用GAPI的一些细节和技巧。如果愿意,您可以下载本示例的所有源代码。