今天的程序讲课,开始。
前面几讲,涉及程序框架、地图文件、叉子的摆动、旋转拉伸,这几方面都可以归纳为基本数据处理,今天讲“交互”,很简单,判断叉子抓到物品,当拉回后,增加金钱数量。核心是碰撞检测。
网上的这个游戏是FLASH作的,FLASH的碰撞检测就一个函数,即可实现各式各样的图形检测。VC中,就用自己动手。最初的想法,是把叉子看成一个圆形,各种矿石也看成圆形,做两个圆形的检测,只要检测圆心距离就可以了。看起来很好,我还是用了另外一个方法,叉子口的连线是一个线段,矿石看成圆形,检测线段和圆是否相交。代码如下:
{
int i;
int j;
int x0,y0; //中点
int tempx,tempy;
int xoff,yoff;
//将爪子边上的直线5等分,依次取点比较
int point[]={0,2,4,-2,-4};
if(iCatchId!=-1)
{
return 0;//当前已经获得了物品
}
xoff=8*cos(10*iangle*1.57/90);
yoff=8*sin(10*iangle*1.57/90);
x0=x+8*xoff;//中点坐标
y0=y+8*yoff;
for(i=0;i<iObjectNum;i++)
{
//如果当前物品已经取走,继续判断下一个
if(0==objectarray[i].id)
continue;
for(j=0;j<5;j++)
{
tempx=x0+point[j]*yoff;
tempy=y0-point[j]*xoff;
if(CmpDistance(objectarray[i].x+objecthit[objectarray[i].id-1].x,
objectarray[i].y+objecthit[objectarray[i].id-1].y,
tempx,tempy,
objecthit[objectarray[i].id-1].id))
{
iCatchId=i;
return 1;
}
}
}
return 0;
}
是不是不像线段和圆的判断?这不是严格的数学检测,我只取了线段的5个等分点,然后判断各点和矿石的距离是否小于矿石的半径。这个计算过程通过一个宏和一个函数实现:
int CmpDistance(int x,int y,int x2,int y2,int l)
{
if(DISTANCE(x,y,x2,y2)<=l*l)
{
return 1;
}
return 0;
}
有了数学模型,那么,矿石的“圆心”和“半径”怎样获得呢?需要设置一个数组:
//各个物体的检测半径,检测圆心坐标(偏移量)
GAMEOBJECT temp[]={
{14,14,14},
{25,25,25},
{30,30,30},
{23,23,23},
{14,14,14}
};
这是半径、圆心坐标(相对于图形左上角的偏移量)。碰撞检测完成。
矿石的移动
需要把叉子移动的状态、代码,赋予 各个矿石吗?不需要。只要在WM_TIMER消息中,根据叉子的坐标刷新物体的坐标即可。代码为:
void GAMEMAP::MoveObject(int x,int y,int iangle)
{
if(-1==iCatchId)
return;
objectarray[iCatchId].x=x+20*cos(iangle*10*1.59/90);
objectarray[iCatchId].y=y+20*sin(iangle*10*1.59/90);
if(y<=58)
{
//增加钱币
iMoneyNow+=object_value[objectarray[iCatchId].id-1];
//一个物品拉到目的地
objectarray[iCatchId].id=0;
iCatchId=-1;
}
}
拉回矿石,增加金钱
这个小游戏核心的逻辑就是“拉回矿石,增加金钱”。如同上方的代码,当叉子的坐标小于58(初始的纵坐标),认为拉回了矿石,金钱增加。同时把物品数组objectarray的ID域清零,即从画面中消除了该物品。
各种物品的金钱值放在一维数组中: int tempvalue[]={50,150,500,15,600};
至此,游戏的主要功能就完成了。
附加功能:道具使用
提供了两种道具:炮和药水。点击“炮”,增加炮的数量;点击“药水”,设置叉子的拉回速度。代码为:
{
iMoneyNow-=money;
if(iMoneyNow<0)
{
iMoneyNow=0;
}
switch(iequip)
{
case 0:
//增加炮的数量
iFireNum++;
break;
case 1:
//增加拉动速度
c.iSpeedMore=2;
break;
}
}
炮的使用也很简单,在用户按“上”时,清除当前抓到的物品:代码为:
{
switch(iKey)
{
case VK_UP:
if(iFireNum>0 && iCatchId>=0)
{
iFireNum--;
bBombAni.SetAni(objectarray[iCatchId].x,objectarray[iCatchId].y);
//一个物销毁
objectarray[iCatchId].id=0;
iCatchId=-1;
}
break;
}
}
至此,所有的交互功能已全部介绍完,游戏制作完成。还有几个部分,像按钮、道具选择界面、动画播放,定时器。概括起来是两项:位图操作、时间控制,应该有很大的优化空间,我就不介绍了。欢迎参考原工程“挖金子VC版源码”(在优快云下载频道)。
谢谢!
本文详细介绍了如何在游戏开发中实现碰撞检测及简单的交互功能,包括矿石抓取、移动与金钱增加的过程。通过具体代码示例展示了如何判断叉子与矿石之间的碰撞,并解释了如何利用线段和圆形的简化模型来实现这一功能。
3176

被折叠的 条评论
为什么被折叠?



