2011-08-09 52 views
0

我在舞臺上有兩個mc,第一個叫做導彈,第二個叫做導彈。優化AS3中的碰撞檢測代碼

因此,我把箱子放在導彈mc的箱子mc和導彈裏。我的問題是如何檢測是否有任何導彈與箱子碰撞並損壞箱子。

我正在使用簡單有效的算法,但在舞臺上有許多導彈和箱子時,它運行速度非常緩慢。我正在使用兩個嵌套的「for」循環,這是一個糟糕的做法,但目前我沒有其他想法。

下面是代碼

public function onEnterFrame(e:Event) { 
     for(var i:int=0;i<ground_mc.boxesLayer_mc.numChildren;i++){ 
      mc1=ground_mc.boxesLayer_mc.getChildAt(i); 
      for(var j:int=0;j<ground_mc.bmLayer_mc.numChildren;j++){ 
       mc2=ground_mc.bmLayer_mc.getChildAt(j); 
       if(mc1.hitTestObject(mc2)){ 
        se=new SmallExplosion(); 
        se.x=mc1.x+randNumber(-20,20); 
        se.y=mc1.y+randNumber(-20,20); 
        ground_mc.addChild(se); 
        mc1.decreaseHealth(mc2.getDamage()); 
       } 
      } 
     } 

    } 

boxesLayer_mc - 箱子影片剪輯

bmLayer_mc - 導彈影片剪輯

是否還有其他的技術來解決這個問題。我已經試圖在每個導彈中增加檢測代碼,但是它對於「for」也很慢。

也許樹或散列映射搜索我不知道?或者,也許圖表:)

任何想法將是有益的

回答

0

最好的解決辦法是使用一些物理引擎(如box2d)。並利用遊戲引擎(如pushButtonEngine)的遊戲開發,甚至更好:) 儘管如此,如果你想自己做這一切,R-tree狀結構是您的choise :)

+0

好主意,必須檢查一下。謝謝 – Vlad

0

使用的每次稍微整潔代碼並減少分配

也可以將onEnterFrame更改爲計時器事件,如果需要,可以減慢計時器事件的速度。

public function onEnterFrame(e:Event) { 
    for each(var box:MovieClip in ground_mc.boxesLayer_mc){ 
    for each(var missle:MovieClip in <ground_mc.bmLayer_mc){ 
     if(box.hitTestObject(missle)){ 
     se=new SmallExplosion(); 
     se.x=box.x+randNumber(-20,20); 
     se.y=box.y+randNumber(-20,20); 
     ground_mc.addChild(se); 
     box.decreaseHealth(missle.getDamage()); 
     } 
    } 
    } 
} 
+0

哇,不知道有AS3的foreach語句。必須試試這個,謝謝 – Vlad

1

對於類似的任務(2D),我所做的就是創建一個簡單的四叉樹樣結構,每個節點可以包含其他子節點或碰撞檢測顯示對象的列表。請注意,如果對象(您的案例中的對象)移動很多,這將不會有效,因爲您每次移動時都需要將它們移動到正確的節點中。

一個簡單的例子類將是:

public class WorldPartitionNode { 
    private var minX : Number; 
    private var minY : Number; 
    private var maxX : Number; 
    private var maxY : Number; 
    private var width : Number; 
    private var height : Number; 

    private var _children : Vector.<WorldPartitionNode>; 
    private var _objects : Vector.<GameObject>; 

    public function WorldPartitionNode(x : Number, y : Number, 
     w : Number, h : Number, childLevels : int) 
    { 
    minX = x; 
    minY = y; 
    maxX = x + w; 
    maxY = y + h; 
    width = h; 
    height = h; 

    if (childLevels == 0) { 
     // This node should have no children, so instead it should 
     // contain display objects 
     _objects = new Vector.<GameObject>; 
    } 
    else { 
     _children = new Vector.<WorldPartitionNode>(4,true); 
    _children[0] = new WorldPartitionTreeNode(minX, minY, width/2, height/2, childLevels-1); 
    _children[1] = new WorldPartitionTreeNode(minX+width/2, minY, width/2, height/2, childLevels-1); 
    _children[2] = new WorldPartitionTreeNode(minX, minY+height/2, width/2, height/2, childLevels-1); 
    _children[3] = new WorldPartitionTreeNode(minX+width/2, minY+height/2, width/2, height/2, childLevels-1); 
    } 
    } 


    public function addObject(obj : GameObject) : void 
    { 
    if (_children) { 
     // This is not a leaf node, so add it to that of the child 
     // nodes in which it belongs. 
     var i : uint; 
     for (i=0; i<4; i++) { 
     var c : WorldPartitionNode = _children[i]; 
     if (obj.x > c.minX && obj.y > c.minY && obj.x < c.maxX && obj.y < c.maxY) { 
      c.addObject(obj); 
      return; // Found node, so bail 
     } 
     } 
    } 
    else { 
     // This is a leaf node, so just add to the internal objects vector 
     _objects.push(obj); 
    } 
    } 

    public function checkCollisions(x : Number, y : Number) : GameObject 
    { 
    if (_children) { 
     // This node has children, so delegate to the right child 
     var i : uint; 
     for (i=0; i<4; i++) { 
     var c : WorldPartitionNode = _children[i]; 
     if (x > c.minX && y > c.minY && x < c.maxX && y < c.maxY) { 
      return c.checkCollisions(x, y); 
     } 
     }   
    } 
    else { 
     // This is a leaf node (with objects directly in it) so loop through 
     // them all and check collision 
     var obj : GameObject; 
     for each (obj in _objects) { 
     if (obj.collidesWith(x, y)) 
      return obj; 
     } 

     return null; //None if reached 
    } 
    } 
} 

這個類的實例將自身分爲四個矩形部分(兩行,兩列)如果childLevels > 0,並創建相同類的實例爲每個的節點。這些節點將依次以相同的方式劃分它們的空間,直到總共有childLevels個級別。

因此,您可以創建一個三級四叉樹(帶有64個分區葉節點),其中每個節點只是原始空間大小的1/64。當您使用addObject()添加對象時,該對象將被添加到與其所在的平方對應的分區節點。

當您執行checkCollision()時,它會遞歸childLevels次直到找到正確的分區,然後僅爲該分區中的對象執行常規衝突檢測循環。

要建立三級樹,其中涵蓋了空間,也就是1024×1024像素:

var treeRoot : WorldPartitionNode = new WorldPartitionNode(0, 0, 1024, 1024, 3); 

,並檢查您的導彈,並在樹中的對象之間的碰撞:

var missile : GameObject; 
for each (missile in _missiles) { 
    var obj : GameObject = treeRoot.checkCollisions(missile.x, missile.y); 
    if (obj != null) 
    obj.kill(); // Was hit by missile 
} 

這可能會顯着加速碰撞檢測,但依賴於靜態(或很少移動)框,因爲如果它們移動,它們將不再位於正確的分區節點中,並且如果它們不是,則樹將無法找到衝突它們之間。

毫無疑問,智能化的分區系統在那裏,但是對於我需要在大空間分散拾取器(硬幣和c)以及玩家可以四處飛行以收集信息的項目,這對我來說非常有效他們。然後,我會讓樹檢查靜態拾取器和播放器之間的碰撞。

+0

嗯,我有幾種類型的盒子,所以其中一些盒子是站着的,其中一些盒子的移動速度很慢或者非常快:)如果我一次至少在舞臺上至少有六個盒子,這個代碼是否有效? ?其中一些正在移動,其中一些正在站立。 – Vlad