怎样做小游戏挖金子(VC,源码5)

本文详细介绍了如何在游戏开发中实现碰撞检测及简单的交互功能,包括矿石抓取、移动与金钱增加的过程。通过具体代码示例展示了如何判断叉子与矿石之间的碰撞,并解释了如何利用线段和圆形的简化模型来实现这一功能。

今天的程序讲课,开始。

前面几讲,涉及程序框架、地图文件、叉子的摆动、旋转拉伸,这几方面都可以归纳为基本数据处理,今天讲“交互”,很简单,判断叉子抓到物品,当拉回后,增加金钱数量。核心是碰撞检测。

网上的这个游戏是FLASH作的,FLASH的碰撞检测就一个函数,即可实现各式各样的图形检测。VC中,就用自己动手。最初的想法,是把叉子看成一个圆形,各种矿石也看成圆形,做两个圆形的检测,只要检测圆心距离就可以了。看起来很好,我还是用了另外一个方法,叉子口的连线是一个线段,矿石看成圆形,检测线段和圆是否相交。代码如下:

int GAMEMAP::DetectCatch(int x,int y,int iangle)
{
    
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个等分点,然后判断各点和矿石的距离是否小于矿石的半径。这个计算过程通过一个宏和一个函数实现:

#define DISTANCE(x,y,x2,y2) (((x)-(x2))*((x)-(x2))+((y)-(y2))*((y)-(y2)))

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};

至此,游戏的主要功能就完成了。

附加功能:道具使用

提供了两种道具:炮和药水。点击“炮”,增加炮的数量;点击“药水”,设置叉子的拉回速度。代码为:

void GAMEMAP::UseEquip(int money,int iequip,GAMECATCH &c)
{
    iMoneyNow
-=money;
    
if(iMoneyNow<0)
    {
        iMoneyNow
=0;
    }

    
switch(iequip)
    {
    
case 0:
        
//增加炮的数量
        iFireNum++;
        
break;
    
case 1:
        
//增加拉动速度
        c.iSpeedMore=2;
        
break;
    }
}

炮的使用也很简单,在用户按“上”时,清除当前抓到的物品:代码为:

void GAMEMAP::KeyProc(int iKey)
{
    
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版源码”(在优快云下载频道)。

谢谢!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值