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

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天的程序讲课,开始。

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

网上的这个游戏是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版源码”(在CSDN下载频道)。

谢谢!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值