快速业务通道

类赛车游戏 | 谈高级碰撞检测

作者 佚名技术 来源 服务器技术 浏览 发布时间 2012-07-11


周末一天没事写个游戏,好简单的,里面的亮点是碰撞检测代码,是我在国外论坛上看到的一个算法,算是很强的了.下面我贴出来,然后讲一下大致思路,关于游戏的代码就不贴了,一大串的看了也心烦 ^^"
点击浏览该文件
这个函数就是碰撞检测的关键,我给它启名叫 "描边"
首先里面两个参数,第一个pmc就是要描边的mc,第二个num是要描的级数(等下会解释到),我们先可以先看下里面的逐句解释

function doFigure(pmc, num) {
// 为pmc建立一个数组,数组的大小是num*2;
pmc.point = new Array(num*2);
// 从pmc的长和宽中取大的,然后除以2
var mx = Math.max(pmc._width, pmc._height)/2;
// 把360℃num等分
var inc = 360/num;
// 定义两个变量等下用
var n = 0;
var i = 0;
// while循环的次数为 iwhile (i<(num*2)) {
// 从下面n+=inc知道 xs和ys 就是每一个等分上x和y的所指的方向
var xs = Math.cos((n*Math.PI)/180);
var ys = Math.sin((n*Math.PI)/180);
// 以pmc的(x,y)点为定点,半径为mx的一个圆的轨迹
var x = pmc._x+(mx*xs);
var y = pmc._y+(mx*ys);
// 如果x,y没有接触到pmc上,不断循环
while (!pmc.hitTest(x, y, true)) {
// x,y分别减
x -= xs;
y -= ys;
// 如果都小于0,就break跳出循环
if (x<0 && y<0) {
break;
}
}
// 把此时的x和y,分别计入point数组中
pmc.point[i] = x-pmc._x;
pmc.point[i+1] = y-pmc._y;
n += inc;
i += 2;
}
}

他这么做到底什么意思呢?
其实point里面就是记录了,一个图形的边缘的坐标.他是怎么做到的?
我们抛开所有从最里面的while循环讲起吧.
while的条件是,当(x,y)点没有接触到pmc的时候,就不断循环,循环的内容是 x-=xs,y-=ys;
如果我们前面什么也没看,应该可以想象,一开始(x,y)点一定在pmc的右边,然后不断的减一个数值xs,ys,直到减到x,y碰到pmc为止,这样,x,y就是pmc上的一点坐标了.
但是我们目前还不知道x和y是怎么定义的,还有就是xs和ys怎么来的
往上看
var xs = Math.cos((n*Math.PI)/180);
var ys = Math.sin((n*Math.PI)/180);
var x = pmc._x+(mx*xs);
var y = pmc._y+(mx*ys);
数学好的,一看就看出来了,这是圆的极坐标公式,就是以pmc的(x,y)为定点,mx为半径的圆的轨迹.
看到这里,应该可以猜到,一定是让一些点以圆的方式出现在mc的周围,然后每个点往mc靠拢,知道每个点都靠到mc上面.
这样我们只要解决这个圆的大小问题了,也就是mx的大小,实际上,你把mx定义成一个很大的数也没问题,但是这样做,会浪费很多,对于写程序的来说,不必要的浪费是不行的^^
那么看上面的
var mx = Math.max(pmc._width, pmc._height)/2;这里就定下了 mx的大小,也就是从mc的长和宽中找一个较大的出来,这样可以保证画出来的圆把整个mc都抱在了里面,大家看到除以2了吧,所以一定能想到 mc 的注册点一定是在中心哦(这也是关键之一^^)
接着,和定义半径大小一样,我们做个360度每一度检测一下,也是可以的,但是这样做会很费资源,而且也没有必要那么精细.
所以才会有一个描边级数num,这个级数就是规定了,分num个等次来描,来记录num个点的坐标. 然后就是运用了
随便画个形状,在这个mc中写下面的代码,场景上再建立一个mc,命名为mc2
你可以看到,你的描边级数越高,每次检测的就越多,所以尽量减少就可以了,像我游戏里面只定义了10.
其实这只是一个大概的数据,并不是百分百的描边,不过这样已经够用了^^"

onClipEvent (load) {
numb = 100;
_root.doFigure(_name, numb);
}
onClipEvent (enterFrame) {
_root.hit = false;
i = 0;
while (i < (numb * 2)) {
x = points[i] + _x;
y = points[i + 1] + _y;
if (_root.mc2.hitTest(x, y, true)) {
_root.hit = true;
break;
}
i = i + 2;
}
}
onClipEvent (mouseDown) {
if (this.hitTest(_root._xmouse, _root._ymouse, true)) {
this.startDrag();
}
}
onClipEvent (mouseUp) {
this.stopDrag();
}

数学不好,解释的不太清楚,大家不懂的再发贴问,我尽量解释,当然也请高手帮忙完善^^! 关键词:

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号