设为首页 收藏本站
查看: 3727|回复: 0

Windows Phone 7范例游戏Platformer实战4——冲突检测的实现

[复制链接]

尚未签到

发表于 2015-5-10 05:59:20 | 显示全部楼层 |阅读模式
  本小节我们就开始真正的XNA游戏编程实践了。前面三节解决了游戏的规则和大部分游戏对象,接下来轩辕对游戏中需要的一些基础类进行讲解和逐步实现。当遇到XNA游戏开发的一些专有名词时,我也会穿插着讲解。
  
正所谓画龙画虎难画骨,在游戏开发中,最难的不是场景的画面实现,而是一些底层的游戏算法或者基础类。只有将地基夯实了,我们才能在这个基础上构建出高楼大厦。同样的道理,我们也需要将Platformer游戏需要的基础类先实现了,才能在以后的开发中构造出需要的效果。
  
  何谓Platformer的基础类呢,比如说冲突检测、动画实现、加速度传感器状态读取、触摸屏输入等等都是需要我们事先考虑的。毕竟所有的游戏场景、英雄和僵尸怪的移动都是构建于这些类之上的。
  
在Platformer场景中,程序无时无刻不在对冲突进行检测和判定。比如说当英雄落下时,需要和踏脚石进行冲突检测,以便确定是继续下落还是停留在踏脚石上。英雄还需要和僵尸怪进行冲突检测,如果发生了碰撞,那么很不幸,关卡立马终止。此外,英雄还需要和宝石进行冲突检测,以便确认是否可以将宝石收入囊中。
  
  下图就是将发生碰撞的临界状态:

DSC0000.jpg
  
  目前2D或3D场景中的冲突检测存在成百上千种实现和描述,所谓的冲突检测大体的描述就是游戏中两个精灵图元是否存在相交周末一个判定过程。现在游戏中常用的冲突检测方法就是使用边界,顾名思义,就是使用一个特定的、可用数学描述的形状将精灵图元进行大概的轮廓确认。
  
  比如下面这个飞机图片,它本身是一个不规则的图元,我们需要在子弹碰到飞机的任何一个部位发生爆炸,那么我们可以将飞机用两个矩形进行囊括。虽然这样没有精确到飞机本身的每个像素,但是大体来说还是可以实现我们需要的效果。
  
DSC0001.jpg
  
  同样在Platformer游戏中,我们也是采用类似的方法实现各种可视对象的边界,比如说英雄、踏脚石、僵尸怪,都是使用一个刚好包含自身图元的矩形来作为其边界。但是宝石例外,它的边界形状是一个圆。下图将这些对象的边界形状用圆形和矩形进行了描绘,让你一目了然。
  
DSC0002.jpg
  
  就那英雄和踏脚石的碰撞来说,我们可以转换为两个矩形的是否相交。这个判定需要一些简单的数学知识,希望你还没有还给老师。下面是两个矩形是否相交的示意图,以便你可以更加清楚地理解这个判定过程。
  
DSC0003.jpg
  
我们可以选取两个矩形的中心点centerA和centerB,而后用centerA.X - centerB.X和centerA.Y - centerB.Y即可得到这两个矩形在X和Y坐标上的距离。如果两个矩形的中心点在X和Y坐标上的距离大于等于各自坐标上的“半径”相加距离的话,那么很显然这两个矩形还未相交,反之则是发生了碰撞。
  
DSC0004.jpg
  
  
由此可得两个矩形是否冲突的代码如下:
  


1     ///
2     /// 矩形扩展类
3     ///
4     public static class RectangleExtensions
5     {
6         ///
7         /// 计算两个矩形见的相交深度
8         ///
9         ///
10         public static Vector2 GetIntersectionDepth(this Rectangle rectA, Rectangle rectB)
11         {
12             // 计算两个矩形的“半径”大小
13             float halfWidthA = rectA.Width / 2.0f;
14             float halfHeightA = rectA.Height / 2.0f;
15             float halfWidthB = rectB.Width / 2.0f;
16             float halfHeightB = rectB.Height / 2.0f;
17
18             // 计算矩形的中心点
19             Vector2 centerA = new Vector2(rectA.Left + halfWidthA, rectA.Top + halfHeightA);
20             Vector2 centerB = new Vector2(rectB.Left + halfWidthB, rectB.Top + halfHeightB);
21
22             // 计算两个矩形当前在X和Y轴上的的中心点距离,以及未相交时的X和Y轴的最小距离
23             float distanceX = centerA.X - centerB.X;
24             float distanceY = centerA.Y - centerB.Y;
25             float minDistanceX = halfWidthA + halfWidthB;
26             float minDistanceY = halfHeightA + halfHeightB;
27
28             // 如果没有相交, 返回 (0, 0).
29             if (Math.Abs(distanceX) >= minDistanceX || Math.Abs(distanceY) >= minDistanceY)
30                 return Vector2.Zero;
31
32             // 计算相交的深度
33             float depthX = distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX;
34             float depthY = distanceY > 0 ? minDistanceY - distanceY : -minDistanceY - distanceY;
35             return new Vector2(depthX, depthY);
36         }
37
38         ///
39         /// 获得矩形下边缘中心点的坐标
40         ///
41         public static Vector2 GetBottomCenter(this Rectangle rect)
42         {
43             return new Vector2(rect.X + rect.Width / 2.0f, rect.Bottom);
44         }
45     }  
  至于宝石和英雄的碰撞检测,可以抽象为一个矩形和圆是否相交的过程。这里轩辕不再详细阐述了,大家可以多思考下,下面是碰撞判定的代码,写是极其精湛。
  


1     ///
2     /// 2D圆边界
3     ///
4     struct Circle
5     {
6         ///
7         /// 圆的中点
8         ///
9         public Vector2 Center;
10
11         ///
12         /// 圆的半径
13         ///
14         public float Radius;
15
16         ///
17         /// 构造一个新的圆
18         ///
19         public Circle(Vector2 position, float radius)
20         {
21             Center = position;
22             Radius = radius;
23         }
24
25         ///
26         /// 确定圆是否和矩形相交
27         ///
28         /// 相交返回true,反之返回false.
29         public bool Intersects(Rectangle rectangle)
30         {
31             Vector2 v = new Vector2(MathHelper.Clamp(Center.X, rectangle.Left, rectangle.Right),
32                                     MathHelper.Clamp(Center.Y, rectangle.Top, rectangle.Bottom));
33
34             Vector2 direction = Center - v;
35             float distanceSquared = direction.LengthSquared();
36
37             return ((distanceSquared > 0) && (distanceSquared < Radius * Radius));
38         }
39     }  
  冲突检测完成之后,轩辕将对WP7中的加速度感应器和触控操作两大新概念的编程进行探索,敬请期待。
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-65350-1-1.html 上篇帖子: Windows Phone 7 异步编程模型 下篇帖子: Windows 7上IIS出现http 500错误
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表