/// <summary> /// Checks collisons with every object in the tree /// against only the root of the other tree /// </summary> /// <param name="treeTvr"> /// The tree to narrow down (as a PCS traverser) /// </param> /// <param name="otherRoot"> /// The other tree to check against /// </param> /// <returns>A GameObject that collides with other tree, otherwise null</returns> private GameObject NarrowDownCollisonTree(PCSTraverser treeTvr, GameObject otherRoot) { // Make sure the traverser starts at the root treeTvr.StartOver(); // Loop through (almost) every object in this tree (pointed by the traverser) while (treeTvr.IsValid()) { GameObject current = treeTvr.GetCurrent() as GameObject; // Check if the current object collides with the other root if (Collider.Intersect(current.Collider, otherRoot.Collider)) { // If the current object has children if (treeTvr.IsThereChild()) { // Check collisons with the children treeTvr.NextChild(); } // The current object is at the bottom of the // collison hierarchy (it is a last-child node) else { // A collison was found! break; } } // No collision else { // Go to the next sibling // If there are no more siblings, this loop breaks treeTvr.NextSibling(); } } // Return the current object. This can be null. return(treeTvr.GetCurrent() as GameObject); }
// // Methods // /// <summary> /// Check all collisions /// </summary> public void Update() { // Iterate through the entire first tree... if (this.ShouldScanEntireFirstTree) { // ... But only if the two roots collide // Disclaimer: This loop only works if nothing from // the first tree will ever be deleted. This is true // for Aliens vs Shields (Aliens don't get deleted) firstTvr.Reassign(this.collisionTreeRootFirst); secondTvr.Reassign(this.collisionTreeRootSecond); // Leave if either roots are null if (firstTvr.IsValid() == false || secondTvr.IsValid() == false) { return; } if (Collider.Intersect(collisionTreeRootFirst.Collider, collisionTreeRootSecond.Collider)) { this.iterator.Reassign(this.collisionTreeRootFirst); // For every collision check allowed... for (int i = 0; i < this.collisionChecks; i++) { // For every node in the first tree... for (this.iterator.StartOver(); this.iterator.IsDone() == false; this.iterator.GetNext()) { // Collisions must be checked against a leaf node var currentNode = this.iterator.GetCurrent() as GameObject; if (currentNode.Child == null) { // Move second tree's traverser to the root this.secondTvr.StartOver(); // Scan the second tree against the first collidee GameObject secondCollidee = this.NarrowDownCollisonTree(secondTvr, currentNode); // A collision occurred if (secondCollidee != null) { // If we are here, there was a collision! this.DeclareCollision(currentNode, secondCollidee); } } } } } } // Don't iterate through the entire first tree. Just narrow it down. else { for (int i = 0; i < this.collisionChecks; i++) { firstTvr.Reassign(this.collisionTreeRootFirst); secondTvr.Reassign(this.collisionTreeRootSecond); // Leave if either roots are null if (firstTvr.IsValid() == false || secondTvr.IsValid() == false) { return; } // Scan the first tree against the entire second root GameObject firstCollidee = this.NarrowDownCollisonTree(firstTvr, this.collisionTreeRootSecond); if (firstCollidee == null) { // Leave if no collison was found return; } // Scan the second tree against the first collidee GameObject secondCollidee = this.NarrowDownCollisonTree(secondTvr, firstCollidee); if (secondCollidee == null) { // Leave if no collison was found return; } // If we are here, there was a collision! this.DeclareCollision(firstCollidee, secondCollidee); } } }