作者:精品Flash 来源:精品Flash 文章类别:本站原创
欢迎转载本站文章,但是转载必须注明出处,并且保留文章中的所有链接,谢谢支持!
本文属于路径判断的基础知识,适合有志于游戏开发的入门者参考(其实本人也只是刚刚接触这方面知识)。文中涉及的知识包括:
基本的ActionScript,初中的一次函数知识,还有一个简单的数学模型。
在游戏里边,据说,2D游戏的碰撞检测是最成熟最稳定的,不过,我还是希望这篇文章能对一些对Flash游戏感兴趣的“闪友”能有点参考价值,如果有幸能对您有点帮助,就上我们网站来捧一捧场:)http://www.exflash.cn
一、数学模型
本人比较孤陋寡闻,不知道这种方法有没有人用过了,更不知道这种做法会不会造成效率较低、复杂度比较高,如有高人,请多加指点。
首先,在这里,我们先假设多边形都是突的,不会有凹多边形的情况。其次,我们把多边形的的边看成是有向边,假设坐标X轴正方向与边重合,定义向右,向上为正,由此可以得出,一个凸多边形里边,各点都是各坐标系的负轴。如下图所示:

这样,我们碰撞的判断可以归结为:点与有向边的距离是否为0?
这样,我们就引出了,如何求点到一直线的距离?哦,这是初中的知识,公式就在下面:
假设直线为:
A * X + B * Y + C = 0
则距离为:
d = (A * X + B * Y + C)/sqrt(A * A + B * B)
d代表距离,我们没有给右边加上绝对值是因为我们假定了距离也是有方向。
根据这个模型,对多边形的每条边做一次计算就可以得到,物体是否落在了该多边形内了。
二、实践演练
首先,我们建立两个多边形,并且根据该原理作出碰撞检测。具体代码如下:
import flash.geom.Point;
stop();
cut = 1;
var BorderArr1:Array = new Array(); //定义第一个多边形各顶点
BorderArr1[0] = new Point(10, 10);
BorderArr1[1] = new Point(180, 10);
BorderArr1[2] = new Point(180, 180);
BorderArr1[3] = new Point(10, 180);
var BorderArr2:Array = new Array(); //定义第二个多变形各顶点
BorderArr2[0] = new Point(310, 110);
BorderArr2[1] = new Point(480, 110);
BorderArr2[2] = new Point(480, 280);
var BorderArr3:Array = new Array(); //定义第三个多边形各顶点,该多边形是该Flash文档的外框。
BorderArr3[0] = new Point(0, 0);
BorderArr3[1] = new Point(550, 0);
BorderArr3[2] = new Point(550, 400);
BorderArr3[3] = new Point(0, 400);
//Begin 画出前两个多边形的形状
_root.lineStyle(1, 0xFF0000, 100);
for(i=0;i<BorderArr1.length;++i)
{
if(i==0)
{
_root.moveTo(BorderArr1[i%BorderArr1.length].x, BorderArr1[i%BorderArr1.length].y);
_root.lineTo(BorderArr1[(i+1)%BorderArr1.length].x, BorderArr1[(i+1)%BorderArr1.length].y);
}
else
_root.lineTo(BorderArr1[(i+1)%BorderArr1.length].x, BorderArr1[(i+1)%BorderArr1.length].y);
}
for(i=0;i<BorderArr2.length;++i)
{
if(i==0)
{
_root.moveTo(BorderArr2[i%BorderArr2.length].x, BorderArr2[i%BorderArr2.length].y);
_root.lineTo(BorderArr2[(i+1)%BorderArr2.length].x, BorderArr2[(i+1)%BorderArr2.length].y);
}
else
_root.lineTo(BorderArr2[(i+1)%BorderArr2.length].x, BorderArr2[(i+1)%BorderArr2.length].y);
}
//End 画出前两个多边形的形状
r = ball._width/2;
//该函数检测点与直线的距离是否比rd(小球半径)小?
function HitTest(px, py, rd, arr, isin)
{
for(i=0;i<arr.length;++i)
{
A = arr[(i+1)%arr.length].y - arr[i%arr.length].y;
B = arr[i%arr.length].x - arr[(i+1)%arr.length].x;
C = arr[(i+1)%arr.length].x * arr[i%arr.length].y -
arr[i%arr.length].x * arr[(i+1)%arr.length].y;
d = (A * px + B * py + C)/Math.sqrt(A*A + B*B);
if((d - rd) > 0)
{
return false;
}
}
return true;
}
onEnterFrame = function()
{
//先算出与各个边的距离
canmove = true;
if(Key.isDown(Key.LEFT))
{
pX = ball._x - 5;
pY = ball._y;
if(!HitTest(pX, pY, r, BorderArr1) &&
!HitTest(pX, pY, r, BorderArr2) &&
HitTest(pX, pY, -r, BorderArr3))
{
ball._x = pX;
}
}
if(Key.isDown(Key.RIGHT))
{
pX = ball._x + 5;
pY = ball._y;
if(!HitTest(pX, pY, r, BorderArr1) &&
!HitTest(pX, pY, r, BorderArr2) &&
HitTest(pX, pY, -r, BorderArr3))
{
ball._x = pX;
}
}
if(Key.isDown(Key.UP))
{
pX = ball._x;
pY = ball._y - 5;
if(!HitTest(pX, pY, r, BorderArr1) &&
!HitTest(pX, pY, r, BorderArr2) &&
HitTest(pX, pY, -r, BorderArr3))
{
ball._y = pY;
}
}
if(Key.isDown(Key.DOWN))
{
pX = ball._x;
pY = ball._y + 5;
if(!HitTest(pX, pY, r, BorderArr1) &&
!HitTest(pX, pY, r, BorderArr2) &&
HitTest(pX, pY, -r, BorderArr3))
{
ball._y = pY;
}
}
}
写好了这些,我们可以预览一下:
注:用方向键移动圆球
可以看到,小球是走不到那两个红线框里边的。其实还有一个框,大小跟影片一样,没有画出来,不过,你试试就知道,小球是走不出可视区外面的。
好的,接下来再看一个例子,看看我们学到的这些能有什么实用价值:
注:用方向健移动船
教程原文件下载:
如有任何疑问,可以到我们主站:精品Flash 上面提问。