优化Actionscript 3中的碰撞检测。

时间:2011-10-25 06:59:43

标签: flash actionscript-3 collision-detection

我正在尝试在Actionscript 3中制作我的第一个游戏。它是一个简单的炮兵游戏,你在左下角有一把枪,AI飞过屏幕,你必须击落。现在,在一个分类射击游戏中,如何实现这一目标要么是通过从枪发射子弹并使用AI movieClip执行该子弹的命中测试,或者通过简单地移除(或播放死亡动画)AI动画片段。但这是问题所在。我不想做其中任何一个。我想展示一种射速很快的枪,因此没有子弹。而且我也不希望玩家完全点击AI动画片段来摧毁它们(只需指向正确方向的枪/炮塔就足够了)。所以这就是我的尝试。

这张图片可以帮助描绘整个事物。

image

  1. 尝试将“线”连接到炮塔并检查与AI夹子的碰撞。当线倾斜时,由于边界框问题,这显然失败了。

  2. 我尝试在线上放置多个微小的movieClip并在循环中迭代它们并检查与AI的任何碰撞。这种方法部分起作用,但它太慢了,似乎不是“正确的”方法。

  3. 我绘制了2条假设线。一个在p1和p2之间,另一个连接p3和p4(请参见上图)。 p3 ---- p4的lenght = AI.width是一条横穿AI MovieClip中心的水平线。在mouseClick上我检查这两行之间的任何交集。现在,如果我在屏幕上有多个AI,再次我需要遍历每个AI,绘制一个新的p3 ----- p4并检查与p1 ----- p2的交集。

  4. 我现在正在使用方法3,我觉得一旦我开始向游戏中添加更多内容,帧速率就会受到影响。我敢肯定应该有一个更简单/优化的方法(可能是非常简单的事情)。附上一些相关的代码。

    shipGame.as

    var baseAI:BaseAI;
    var AIList:Array= new Array;
    public function shipGame():void{
                trace("still connected!!");
                /*
                irrelevant code..
                */
                stage.addEventListener(Event.ENTER_FRAME, updateGame);
                var a:MovieClip = new MovieClip;
                aiTimer = setInterval(StartAI, 2000);
    }
    public function StartAI():void {
                baseAI = new BaseAI(this);
                AIList.push(baseAI);
    }
    
    public function updateGame(event:Event):void    {
                /*
                code to rotate the turret here..
                */
    
                for (var i:int = 0; i < AIList.length; i++) 
                {
                    if (AIList[i].myx < 100) {
                        AIList[i].basicAI.parent.removeChild(AIList[i].basicAI);
                        AIList.splice(i, 1);
                    }
                }
    
                if (mouseDn) {
                    basicTurret.gotoAndPlay(2);// Fire animation
                    for (var j:int = 0; j < AIList.length; j++) 
                    {
                        if ( intersection(AIList[j])) // intersection(bai:BaseAI) returns boolean. Works fine. 
                        {
                            AIList[j].shot = true;
                        }
                    }
                }
    }
    

    BaseAI.as

    var main:shipGame;
    var myy:Number;
    var myy:Number;
    public function BaseAI(doc:shipGame):void{
                main = doc;
                basicAI = new BasicAI(); // BasicAI is a movieClip in the library
                main.addChild(basicAI);
                basicAI.x = 400;
                basicAI.y = Math.abs(Math.random() * (280)) + 20;
                myy = basicAI.y;
                basicAI.addEventListener(Event.ENTER_FRAME, keepMoving);
    }
    
    public function keepMoving(evt:Event):void {
            basicAI.x -= 5;
            myx = basicAI.x;
    
            if (shot && alive) {
                alive = false;
                basicAI.gotoAndPlay(2);
            }
    }
    

1 个答案:

答案 0 :(得分:3)

您当前所有的方法基本上都依赖Flash的渲染器来了解船只和子弹线的位置。但在您的情况下,由于移动部件之间的几何关系相对简单,因此分析处理问题要快得多。

考虑船舶正好坐在枪的火线上的情况。在这种情况下,枪,船和屏幕底部形成一个直角三角形。如果我们将theta定义为枪与屏幕底部之间的角度,则以下内容将成立:

tangent(theta) = ship.y / ship.x

其中xy从枪中向右和向上测量。现在您可以对此进行概括并将其用于命中测试。当枪被射击时,首先找到theta。然后对于每艘船,您可以通过这样的方式轻松确定船舶在火线上垂直或水平的距离:

var theta = /*determine theta based on where the mouse was clicked*/
var tanTheta = tangent(theta);
for each (ship) {
    var gunX = ship.y / tanTheta;
    if ( abs(gunX - ship.x) < ship.width/2 ) {
        // a hit occurred
    }
}

这只是伪代码,但希望你能得到这个想法。无论如何,这就是我将如何做到这一点 - 这将比你使用实际命中测试所做的任何事情都要快得多,对于所描述的情况,它应该也能正常工作。