太空入侵者游戏
转载请注明出处
入侵者是一个简单的射击游戏。游戏运行的初始界面如图3.14所示,游戏的战斗场面如图3.15所示。
图3.14入侵者程序初始运行图
图3.15入侵者作战运行图
在游戏中,玩家控制飞船,一方面要向敌机射击,另外还需要躲避敌人的子弹。直到当前关卡中
所有敌机被消灭,玩家才能进入下一关卡。
要编译这个游戏,需要安装DirectX 8.0 SDK或以上版本。
在这个例子中要着重强调子弹、奖子(弹药、奖金等)、卷屏等设计技巧,以及射击过程是如何开
展的。相信通过对这个游戏的理解,读者对射击游戏的构建会有更深刻的认识。
3.7.1 奖子的设计
奖子是射击类游戏中必有的精灵,奖子实际就是玩家操作的飞船打掉敌机后,电脑奖赏的奖金、
弹药、防弹服等。不过要想真正拥有这些奖子,玩家操纵的精灵必须在奖子消失(掉落到屏幕之外或
者在规定时间内消失)之前“吃”掉它。“吃”实际上是一种碰撞检测行为。而在吃掉奖子之前,奖子
通常会自动下落。
如图3.16 所示是入侵者游戏中的奖子原始图。Extras.bmp图片的分辨率是125×500。
图3.16入侵者中的奖子源视图extras.bmp
从图中不难看出入侵者中有5 种奖子,每种奖子有20 帧动画。由于extras的分辨率是125×500,
所以平均每个奖子的每一帧是一幅25×25分辨率的图像。
在入侵者中,单独设计了一个奖子类Extra:
classExtra
{
private:
int x;//奖子在屏幕中的位置
int y;
RECTrcLastPos; //奖子上次出现在屏幕中的包围盒坐标
intiType; //奖子类型,从extras.bmp中可以看出共有5 种类型
Extra*pNext; //奖子链表
Extra*pPrev;
public:
intframe; //帧编号,从extras.bmp中可以看出共有20 帧
Extra()
{
x = 0;
y = 0;
pNext= NULL;
pPrev= NULL;
frame= 0;
iType= 0;
rcLastPos.left= 0;
rcLastPos.top= 0;
第3 章2D 游戏开发121
rcLastPos.right= 0;
rcLastPos.bottom= 0;
};
intGetType()
{
returniType;
}
voidSetType(int iNewType)
{
iType= iNewType;
}
intGetX()
{
returnx;
}
intGetY()
{
returny;
}
voidMove(int Qtde)
{
rcLastPos.left= x;
rcLastPos.top= y;
rcLastPos.right= x + 25;
rcLastPos.bottom= y + 25;
if(rcLastPos.bottom > 455)
rcLastPos.bottom= 455;
//Qtde是一个负值,因为这种奖子都是垂直下落的,即y 值需要不断增加
y -=Qtde;
}
voidSetXY(int nx, int ny)
{
rcLastPos.left= nx;
rcLastPos.top= ny;
rcLastPos.right= nx + 25;
rcLastPos.bottom= ny + 25;
x =nx;
y =ny;
}
Extra*GetNext()
{
returnpNext;
}
122 Visual C++游戏开发技术与实例
Extra*GetPrev()
{
returnpPrev;
}
voidSetNext(Extra* nNext)
{
pNext= nNext;
}
voidSetPrev(Extra* nPrev)
{
pPrev= nPrev;
}
BOOLDraw(LPDIRECTDRAWSURFACE7 lpOrigin, LPDIRECTDRAWSURFACE7 lpSource)
{
RECTrcRect;
HRESULThRet;
intiClipTop;
intiClipBottom;
//子弹在超出屏幕上方(y 值小于0)和跨过屏幕下方(y+255>455)的时候需要进行裁剪
if (y< 0)
iClipTop= y * -1;
else
iClipTop= 0;
if(y+25 > 455)
iClipBottom= y+25-455;
else
iClipBottom= 0;
rcRect.left= frame * 25;
rcRect.top= ((iType - 1) * 25) + iClipTop;
rcRect.right= frame * 25 + 25;
rcRect.bottom= ((iType - 1) * 25) + 25 - iClipBottom;
//帧数编号加1
frame++;
if(frame == 20)
frame= 0;
while(1)
{
hRet=lpOrigin->BltFast(x,y,lpSource,&rcRect,DDBLTFAST_SRCCOLORKEY);
if(hRet == DD_OK)
{
break;
}
if(hRet == DDERR_SURFACELOST)
第3 章2D 游戏开发123
{
returnFALSE;
}
if(hRet != DDERR_WASSTILLDRAWING)
break;
}
returnTRUE;
}
};
很显然,Extra 中私有成员变量x、y表示奖子方块左上角在屏幕上的像素坐标(事实上这两个变
量并不是必需的);而矩形结构rcLastPos表示奖子上次出现在屏幕时的坐标;整形的iType表示奖子
类型,这里共有5 种类型的奖子。公有变量frame表示帧编号,每种奖子都有20帧。在Extra中__________读者
可能有疑惑的地方就是成员变量pNext和pPrev,因为从名称上读者就能猜出Extra变成了一种链表结