HT for Web visual QuadTree quad-Tree Collision Detection and quadtree Collision Detection
A QuadTree tree is a tree-like data structure. Each node has four child nodes, which can recursively split two-dimensional planes into subareas. QuadTree is often used for spatial database indexing, 3D visible area cropping of vertebral bodies, and even image analysis. Today we are introducing the collision detection that QuadTree is most commonly used in the gaming field. The QuadTree algorithm is used to greatly reduce the number of collision tests and improve the game refresh performance. In this example, the graphic engine based on HT for Web shares the same data model DataModel through GraphView and Graph3dView, the 2D and 3D collision views under the QuadTree algorithm are displayed at the same time:
QuadTree implementation has a lot of mature versions, I chose the https://github.com/timohausmann/quadtree-js/ quad-tree algorithm is very simple, so this open source library is also two hundred to line of code. It is also very easy to use. Construct A Quadtree object. The first parameter is used to input rect information to specify the game space range. Each time requestAnimationFrame refreshes frames, it uses quadtree. clear () to clear old data and use quadtree. insert (rect) inserts a new rectangular area of the node, so that the quadtree is initialized. The rest is to call the quadtree as needed. retrieve (rect) obtains the array of rectangular objects that may be located at the intersection of a specified rectangle.
I have built two HT GraphView and Graph3dView components through ht. widget. split the SplitView left and right. Because both views share the same DataModel, we focus only on DataModel data operations and constructed 200 ht records. node object. The attr attributes of each object store random motion direction vx and vy, And the rectangular object that will be inserted into the quadtree repeatedly. This avoids repeated object creation when each frame is updated, at the same time, the rectangle object also references ht. node object, used when the quadtree. when retrieve (rect) obtains the rectangle object to be checked, we can specify the associated ht. node object, because we need to set the red color effect for the final collision elements, that is, ht. node usually displays the default blue color, which will change to red when they collide with each other.
You need to note from quadtree. retrieve (rect) obtains the array of rectangular objects to be checked and contains its own elements. At the same time, these elements may only conflict with each other and do not mean they have already been collided. Because we use a rectangle in this example, therefore, ht is used. default. intersectsRect (r1, r2) determines whether the two centers are intersecting. If your example is a circle, you can calculate whether the distance between the two centers is smaller than two radius to determine whether the two centers are intersecting, therefore, the final judgment criteria vary according to the game type.
QuadTree greatly improves the computing performance. Otherwise, 100 elements need to be monitored 100*100 times. In this case, 100*(10 ~ 30) Quantity:
In addition to collision detection QuadTree algorithm also has a lot of interesting application areas, interested can play with this https://github.com/fogleman/Quads
All the code is as follows:
function init(){ d = 200;speed = 8;dataModel = new ht.DataModel(); g3d = new ht.graph3d.Graph3dView(dataModel); g2d = new ht.graph.GraphView(dataModel); mainSplit = new ht.widget.SplitView(g3d, g2d); mainSplit.addToDOM(); g2d.translate(300, 220); g2d.setZoom(0.8, true); for(var i=0; i<100; i++) {var node = new ht.Node();node.s3(randMinMax(5, 30), 10, randMinMax(5, 30));node.p3(randMinMax(-d/2, d/2), 0, randMinMax(-d/2, d/2));node.s({'batch': 'group','shape': 'rect','shape.border.width': 1,'shape.border.color': 'white','wf.visible': true,'wf.color': 'white'});node.a({vx: randMinMax(-speed, speed),vy: randMinMax(-speed, speed),obj: {width: node.getWidth(),height: node.getHeight(),data: node}}); dataModel.add(node);} createShape([{x: -d, y: d},{x: d, y: d},{x: d, y: -d},{x: -d, y: -d},{x: -d, y: d}]); quadtree = new Quadtree({ x: -d, y: -d, width: d, height: d }); requestAnimationFrame(update);} function update() { quadtree.clear(); dataModel.each(function(data){if(!(data instanceof ht.Shape)){var position = data.getPosition();var vx = data.a('vx');var vy = data.a('vy');var w = data.getWidth()/2;var h = data.getHeight()/2;var x = position.x + vx;var y = position.y + vy;if(x - w < -d){data.a('vx', -vx);x = -d + w;}if(x + w > d){data.a('vx', -vx);x = d - w;}if(y - h < -d){data.a('vy', -vy);y = -d + h;}if(y + h > d){data.a('vy', -vy);y = d - h;}data.setPosition(x, y); var obj = data.a('obj');obj.x = x - w;obj.y = y - h;quadtree.insert(obj);setColor(data, undefined);}}); dataModel.each(function(data){if(!(data instanceof ht.Shape)){ var obj = data.a('obj');var objs = quadtree.retrieve(obj);if(objs.length > 1){ for(var i=0; i<objs.length; i++ ) {var data2 = objs[i].data;if(data === data2){continue;}if(ht.Default.intersectsRect(obj, data2.a('obj'))){setColor(data, 'red');setColor(data2, 'red');} } }}});requestAnimationFrame(update); } function randMinMax(min, max) {return min + (Math.random() * (max - min));} function createShape(points){shape = new ht.Shape();shape.setPoints(points);shape.setThickness(4);shape.setTall(10); shape.s({'all.color': 'red','shape.background': null,'shape.border.width': 2,'shape.border.color': 'red' }); dataModel.add(shape); return shape;}function setColor(data, color){data.s({'all.color': color,'shape.background': color});}