这三天假期的成果:A Shooting Game

假期来了,如其玩CS堕落,不如自己写一个小游戏玩一玩!这三天很卖力地在敲代码,到现在有点成绩了,发个临时版本上来。

http://home.xxsyzx.com/upfiles/killall.zip (Windows Only) 游戏很简单,开枪杀死所有的对手即可。

 

5月1日:大致地设计了一个C++游戏的结构,用了大量的类继承和多态,简直把++的特性发挥到极致。之前我是如此厌恶C++的面向对象编程,最近突然感觉到有点用途了!!大体地建造了一个物理运动系统,有加速度、重力、动量以及各种量的矢量合成与运算。

 

5月2日:弄了一天碰撞检测算法,请教了好几位朋友同学,还花了好几个小时上网看资料,最终还是没有满意的解决方案。挑灯夜战,最后把这个问题解决了才睡觉。。。临时的解决方法是:

1、对于子弹这类可以看成质点的物体,把运动轨迹当成直线来处理。在平面上,给每个对象都画一个矩形(颜色可以一致,如果是可以看作同一类碰撞的话),然后从子弹的开始处往目的地模拟画线,当遇到一个不同颜色的点时,则碰撞发生了,而且也得到了碰撞位置。这种方法的速度很快,而且仅是画直线和重画位置改变了的矩形而已,属于线性的时间复杂度。

2、对于人与障碍物的碰撞,要看成矩形和矩形之间的碰撞。假设矩形运动速度在一定限度内的话,可以在运动的每一瞬间检测是否和另一个矩形发生相交。如果相交了,则说明发生碰撞。同时计算碰撞所在的面,并修正碰撞物体的位置,恢复到碰撞之前的状态。

对于a和b两个矩形,判断是否发生碰撞:

 if (b.x1> a.x2 || b.y1 > a.y2 || b.x2 < a.x1 || b.y2 < a.y1){
     return false; //没有发生碰撞
 }
 //Handle intersection problem!  //发生了碰撞!
 int dy1 = abs(a.y1-b.y2), dy2=abs(a.y2-b.y1);
 int dx1 = abs(a.x1-b.x2), dx2=abs(a.x2-b.x1);
 int dh = min(dy1, dy2), dw = min(dx1, dx2);

//看看是调整左右位置还是调整上下位置。取最小改动的那一个。
 if(dh < dw){ //adjust y
  if(dy1    this->position.y = b.y2;
   this->handleCollision(DIR_TOP, o);
   o->handleCollision(DIR_BOTTOM, this);
  }else{ //collid the top of o
   this->position.y = b.y1 – a.y2 + a.y1 + 1;
   this->handleCollision(DIR_BOTTOM, o);
   o->handleCollision(DIR_TOP, this);
  }
 }else { //adjust x
  if(dx1    this->position.x = b.x2+1;
   this->handleCollision(DIR_LEFT, o);
   o->handleCollision(DIR_RIGHT, this);
  }else{ //collid the left of o
   this->position.x = b.x1 – a.x2 + a.x1 -1;
   this->handleCollision(DIR_RIGHT, o);
   o->handleCollision(DIR_LEFT, this);
  }
 }

这种方法比较典型,我相信很多游戏也这么解决碰撞问题。

但是一个很明显的缺点就是,复杂度会随着矩形数量的增加而非线性增加!!!很容易证明复杂度是n^2的,如果地图上有5000个对象,在1秒时间里也不可能完成检测。这样玩家不用玩游戏了,看幻灯片算了。

我用了某些3D游戏里用的方法来解决这个问题,把地图分为m*n个区域,记录下在任意一个区域内的物体,如果物体存在于多个区域上,那么在多个区域进行标记。这样检测在某个位置的碰撞,只需要把在那个位置的物体拿出来进行检测即可。用空间换回了时间!速度很快,真的很有效果!!

 

5月3日:实现了动画效果,地图随着人物移动而滚动。花了一个下午,做好了一个可以玩的小游戏。因为还没有实现AI功能,所以电脑控制的人物不能走动了!

下载试试吧!

 

 

点击查看大图

这三天假期的成果:A Shooting Game》有18个想法

  1. Xiaoxia

    之前没有全屏在一些电脑上居然会很卡。。。特别是XP,还有鼠标的问题。
    现在改为全屏后,这些问题估计都能解决了吧!
    正常情况,游戏一直是60FPS的或者更高。否则就应该是显卡问题。我本机运行的时候CPU才占用10%

    回复
  2. Xiaoxia

    to Kiming,有什么好方法解决这个问题呢?
    如果子弹有惯性,是不是可以无限远了? 还是只能到达屏幕边沿的位置?

    回复
  3. to_be

    我在google reader看到的feed只有标题和第一句话,所以不知道这个帖子是关于上次的那个问题的解答的。

    回复
  4. Xiaoxia

    哦,其实不算是解答呢,我只是换了一种方法来达到同样的效果。
    但是我仍然很想解决那个难题。我看网上很少有人研究这个?搜出来的都是简单的矩形相交检查,没多大意义。

    回复
  5. 能不填么

    好吧。。碰触。。有次做了个类弹幕的游戏我拿数个圆形填满物体算碰撞的,感觉矩形对于旋转物体计算很麻烦,圆形的话只要知道圆心就行,再者屏幕一次要出现5000个单位,这个么。。。什么BT游戏啊,那次做弹幕想试下VB效率同时计算1000架飞机我键盘按得都泪流满面了,哎,某只菜鸟看后有感~

    回复

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据