Quadtree Algorithm for Search Optimization (3)

The content of the previous section explained how to use the recursive method to create a quad tree, and attached the specific implementation code. The recursive method is a very beautiful coding method, which is natural, concise and easy to understand.

In this section, we will bind the display object to the node, and realize the dynamic quadtree update of the node position of the display object. What is the dynamic quadtree display object node update, such as the movement of monsters in the game, from one area to another In an area, whenever the coordinates of the monster change, we need to update whether he still belongs to the current node range. If it is not within the current node range, we need to update the node he belongs to. Okay, let's take a step. Implement these steps one by one

Title: Binding and Updating Display Objects in Dynamic Quadtrees

In the last section, we created several very important classes. It doesn't matter if you don't remember. I will briefly list
NodeTree.as quadtree
NodeRect.as quadtree rectangle node class
NodeTreeManager.as quadtree manager

Through the above three classes, we have completed the creation of a quad tree. Let's create a display object class, inherit the Sprite sprite class, and implement the INodeDisplay node display object interface

//节点矩形范围接口
public interface INodeRect
{
    function get rect():Rectangle;
    function refree():void;
}
//可现实节点接口
public interface INodeDisplay extends INoder
    {
        function get node():INodeRect;
    }


public class NodeSprite extends Sprite implements INodeDisplay
{
    private var _tid:String; //该显示对象隶属的树的id
    private var _isActive:Boolean;
    private var _initialized:Boolean;

    private var _node:NodeRect;//该显示对象隶属的节点
    private var _tree:NodeTree;//该显示对象隶属的树
public function NodeSprite()
    {
        super();
        this.id = (Math.random() * int.MAX_VALUE).toString();//唯一ID
        this.mouseChildren=this.mouseEnabled=false;//禁止鼠标事件
        this.tabChildren=this.tabEnabled=false;
    }
}

First of all, an interactive object that wants to implement a quadtree node must inherit NodeSprite. Here we do not declare and implement subclasses. If there is a need, you can add it yourself. After the interactive object is instantiated, it needs to be registered so that Mark this object as belonging to that quadtree, so we need a registration method

    /**
     * 所有NodeSprite对象初始化都要执行这个方法。 
     * @param tid
     * 
     */     
    public function registNodeTree(tid:String):void{

        this._tree= TreeManager.instance.take(tid) as NodeTree;
        this._tid = tid;
        this._initialized=true;
    }

After the registration, the _initialized=true initialization flag is true, and the subsequent steps can be carried out. In order to add the display object to the corresponding node, we will spend a lot of money

First of all, we need to obtain the child node to which it belongs according to the coordinate position of the currently displayed object, and then we can justifiably add it to this node, or remove it from this node. As mentioned above, each node has a one and only

id = node.x + ”_” + node.y

Well, knowing the format of the id, we can calculate his unique id according to the coordinates (x, y) of the display object or I call him nodekey

    /**
             * 根据当前显示对象位置获取当前节点 
             * @return 
         * 
         */     
        private function get nodekey():String{
            //算出鼠标点所在的节点 起始坐标
            var nodex:int = int(this._pos_x/NodeTree.MIN_SIZE)*NodeTree.MIN_SIZE;
            var nodey:int =  int(this._pos_y/NodeTree.MIN_SIZE)*NodeTree.MIN_SIZE;

            //参考NodeSprite.as
            return nodex + '_' + nodey;
        }

NodeTree.MIN_SIZE is the minimum child node size of the quadtree

After getting the nodekey, you can get the quadtree node to which the display object belongs.

_tree.getNode(nodekey ) as NodeRect;

At this point, the success is very close. We only need to create 2 methods in the node NodeRect to add or remove the display object to the node.

public function addChild(id:String,noder:INoder):void{
            if(this._nodes[id] == null){
                this._nodes[id] = noder;
                _length++;
            }
        }

    public function removeChild(id:String):void{
        if(this._nodes[id] != null){
            this._nodes[id] =null;
            delete this._nodes[id];
            _length --;
        }
    }

After realizing the addition and removal of the display object on the node, we can continue to implement the dynamic update of the quadtree node. When the coordinates of the display object change, this requires us to rewrite the x and y methods of the display object.

    private var _pos_x:int;
    private var _pos_y:int;
    override public function set x(value:int):void{
        if(value==super.x)return;
        super.x = int(value);
        update(x,y,nodekey);
    }

    override public function set y(value:int):void{
        if( value==super.y)return;
        super.y = int(value);
        update(x,y,nodekey);
    }

    public function setXY(x:int,y:int):void{
        super.x = int(x);
        super.y = int(y);
        this._pos_x = int(x);
        this._pos_y = int(y);
        update(x,y,nodekey);

    }

When the display object moves from one node range to another node range, we need the update method to implement his specific operation

/**
         * 动态四叉树核心方法 
         * @param x
         * @param y
         * @param nodekey 该点所在的节点id 通过这个id查找到对应的noderect
         * 
         */     
        private function update(x:int, y:int, key:String):void
        {
            if(this._initialized==false)return;
            if(this._isActive==false)return;
            if(!this._tree.initialized)return;

            if(this._node==null){
                _node = _tree.getNode(key) as NodeRect; 
            }
            if(!_node.rect.contains(_pos_x,_pos_y)){//如果当前对象坐标不在所隶属的节点区间,就需要重新
                var nodeNew:NodeRect = _tree.getNode(key) as NodeRect;
                resetNode(nodeNew,_node);
                if(nodeNew!=null)
                    _node = nodeNew;
            }
        }

Updating the node resetNode() is a recursive process. It is removed from the old node and added to the new node. After the child node is updated, the parent node must be updated until the new and old nodes are the same. The implementation process is as follows

/**
     *  更新节点
     * @param nodeNew
     * @param nodeOld
     * 
     */     
    private function resetNode(nodeNew:NodeRect, nodeOld:NodeRect):void
    {
        if(nodeNew &&nodeOld){
            if(nodeNew!=nodeOld){
                nodeOld.removeChild(this.id);
                nodeNew.addChild(this.id,this);
                this._node = nodeNew;
                resetNode(nodeNew.parent,nodeOld.parent);
            }
        }
    }

Well, after the above series of suffocating operations, the addition and removal of visual objects on the quadtree nodes are finally realized, and the dynamic update is realized. This step is a significant step, which provides the search traversal in the next section. Foreshadowing, due to time constraints, I will write here today

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324952132&siteId=291194637