优化科里森检测code在AS3科里、code

2023-09-08 14:01:24 作者:旧城不暖少年心

我有两个MC的舞台上,第一个被称为导弹和第二个叫做框。

I have two mc's on the stage, the first one is called missiles and the second one is called boxes.

所以我相应的框中MC和导弹在导弹MC把纸箱。我的问题是如何检测是否有任何的导弹碰撞盒,使损坏的框。

So accordingly I put boxes in the boxes mc and missiles in the missiles mc. My problem is how to detect whether any of the missiles collide with boxes and make damage to the box.

我使用的简单而有效的算法,它的工作原理,但它是当有许多导弹和箱子在舞台上非常缓慢。我使用两个嵌套的周期这是一个不好的做法,但我没有在目前其他的想法。

I am using simple and effective algorithm which works but it is very slow when there are many missiles and boxes on stage. I am using two nested "for" cycles which is a bad practice, but I don't have other idea at the moment.

下面是code

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 - 盒movieclip中

boxesLayer_mc - boxes movieclip

bmLayer_mc - 导弹movieclip中

bmLayer_mc - missiles movieclip

还有没有其他的方法来解决这个问题。我已经尝试添加检测code在每一个导弹,但它也慢用对。

Are there other techniques to solve this problem. I have already tried to add detection code in every missile but it is also slow with "for".

也许树或哈希映射搜索我不知道吗?或者,也许图表:)

Maybe trees or hash mapped search I don't know? Or maybe graphs :)

任何想法将是有益的。

推荐答案

有关类似的任务(2D),我所做的就是创建一个简单的四叉树一样的结构,其中每个节点都可以包含其他子节点或列表显示对象碰撞检测。请注意,如果对象(在你的案件框)身边有很多这样的举动会不会有效,因为你需要将其移动到合适的节点每次移动。

For a similar task (2D), what I did was to create a simple quadtree-like construct where each node can either contain other child nodes or a list of display objects for collision detection. Note that the if the objects (boxes in your case) move around a lot this will not be efficient as you will need to move them into the right node everytime the move.

一个简单的例子类是:

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 总水平。

Instances of this class will divide itself into four rectangular sections (two rows, two columns) if childLevels > 0, and create instances of the same class for each of those nodes. Those nodes will in turn divide their space up the same way until there are childLevels levels in total.

可以由此创建一个三级四叉树(64分区叶节点),其中每个节点是原始空间的刚1/64的大小。当你用 ADDOBJECT()添加对象的对象将被添加到它对应于它位于广场上的分区节点。

You can thereby create a three-level quad-tree (with 64 partition leaf nodes) where each node is just 1/64 the size of the original space. As you add objects with addObject() the object will be added to the partition node which corresponds to the square in which it is located.

当您执行 checkCollision(),它会重复 childLevels 次,直到找到正确的分区,然后仅在该分区中的对象执行常规碰撞检测环

When you execute checkCollision(), it will recurse childLevels times until it finds the right partition, and then perform a regular collision detection loop only for the objects in that partition.

要创建一个三层次的树,它涵盖了空间,1024×1024像素:

To create a three-level tree, which covers a space that is 1024x1024 pixels:

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

和检查在树中的导弹和物体之间的碰撞:

And to check for collisions between your missiles and the objects in the tree:

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
}

这将有可能加快碰撞检测显著,但依赖于拖曳是静态的(或很少的移动),因为如果它们移动它们将不再是在正确的分区节点,如果它们不是树将失败它们之间找到的碰撞。

This will likely speed up the collision detection significantly, but relies on the boxes being static (or rarely moving), because if they move they will no longer be in the correct partition node and if they're not the tree will fail to find collisions between them.

有任何疑问,聪明分区系统在那里,但在我需要分散皮卡(等Ç硬币)在一个大的空间,在这里玩家将绕飞,收集他们的一个项目这个工作对我非常好。每一帧我会再让树检查的静态皮卡和球员之间的碰撞。

There are no doubt smarter partitioning systems out there, but this worked very well for me in a project where I needed to scatter pick-ups (coins et c) in a large space and where the player would fly around to collect them. Each frame I would then let the tree check for collisions between the static pick-ups and the player.