First of all, I've only been writing my own game logic for a short while, so I apologize if this might seem straight forward.
I've been reading a lot about quad trees and grid based collision detection. I understand the logic - basically don't check for collision unless objects are near basically. But it never is mentioned how the actually execute this.
I have a couple of possibile methods in my head but am not sure which is best
General collision test - no optimisation
for(var i:int = 0; i < objects.length; i++){
//find object A
var objectA = objects[i];
for(var j:int = i + 1; j < objects.length; j++){
//find object B
var objectB = objects[j];
if(objectA.collidesWith(objectB){
//handle collision logic
}
}
store neighbours (method 1) But what if we want to optimise the collisions to only check objects that are near. Do we still run through all the objects, or do we create an array with near objects to check through?
var objects:Array = new Array();
var neighbours:Array = new Array();
for(var i:int = 0; i < objects.length; i++){
//find object A
var objectA = objects[i];
for(var j:int = i + 1; j < objects.length; j++){
//find object B
var objectB = objects[j];
if(objectA.isNear(objectB){
neighbours.push(objectA, objectB);
}
}
}
//somewhere else
for(i:int = 0; i < neighbours.length; i++){
//only check neighbours
for(j:int = i + 1; j < neighbours.length; j++){
if(objectA.collidesWith(objectB){
//handle collision logic
}
}
}
loop all objects but only check neighbours for collision (method 3) The other possibillity is that we still loop through everything but check if the objects are near before testing the collision.
for(var i:int = 0; i < objects.length; i++){
//find object A
var objectA = objects[i];
for(var j:int = i + 1; j < objects.length; j++){
//find object B
var objectB = objects[j];
if(objectA.isNear(objectB){
//they are near - check collision!
if(objectA.collidesWith(objectB){
//handle collision logic
}
}
}
}
Store objects in tile data (method 3) Using a tile based sytem allow for another option; Store the objects that are on a specific tile in the tile data itself. Check to see on which tile the object is the surrounding tiles contain any objects it could collide with:
var ObjectA;
for(var i:int = 0; i < 4; i ++){
//check 4 surrounding tiles from object A
if(Object.currentTile + surroundingTile[i] CONTAINS collidable object){
//check collision!
if(objectA.collidesWith(surroundingTile.object){
//handle collision logic
}
}
}
I always try to look at the real world as an example. If I wanted to compare items with the same colour it would seem illogical to check every entire item even if they don't match colour (Method 2, check each item). I would probably collect the items with the same colour (objects that are near each other) and check those (method 1), instead of checking everything.
This isn't an appropiate comparison since the items in collision checking are constantly moving so the order gets mixed up. That whats confusing me.
Would it be more efficient to check each item, thus removing the strain of keep generating an array of neighbours.
Or is it more efficient to find neighbours thus not having to loop through so many objects to check the collision?
Keep changing the data on each tile seems very intensive aswell, so i'm not sure if that a good idea..
I've been thinking of a tower defense game where the tower needs to detect objects if objects are in range before it shoots at it. And it just seems silly to check all items while at some times there won't be any objects near at all.
I apologize for the long post, always having trouble explaining myself!