CollisionManager::CollisionManager()

{

numBoxes = 0;

numEncounters = 0;

}

void CollisionManager::InitMap(unsigned int map[][COLLISION_MAP_SIZE],unsigned int mapSize)

{

for(int y = 0; y < COLLISION_MAP_SIZE; y++)

{

for(int x = 0; x < COLLISION_MAP_SIZE; x++)

{

collisionMap[x][y] = map[x][y];

}

}

}

void CollisionManager::Update()

{

//sort through lists on the x and y axis to employ the sweep and prune strategy

for(int axis = 0; axis < 2; axis++)

{

//go through each box, and go through both the max and min

//endpoints for each box in the current axis so this will need

//twice the amount of normal tests

for(int box = 1; box < numBoxes * 2; box++)

{

int keyType = endpoints[box][axis].type;

int keyBoxId = endpoints[box][axis].boxID;

float keyVal = AABBs[keyBoxId].vals[keyType][axis];

//use the above keyval to the value before it in the array - swap if necessary

//it's basically a bubblesort

int index = box-1;

//now go backwards to the start of the array to make sure it is all in the right

//order

while(index >= 0)

{

int compType = endpoints[index][axis].type;

int compBoxId = endpoints[index][axis].boxID;

int compVal = AABBs[compBoxId].vals[compType][axis];

int objType1 = AABBs[compBoxId].type;

int objType2 = AABBs[keyBoxId].type;

if(compVal < keyVal)

{

//this is in order so break the loop

break;

}

//if an endpoint is leaving to the left of the an endpoint this is an

//encounter not happening anymore

if((compType == 0) && (keyType == 1))

{

if(CheckMap(objType1,objType2))

{

RemoveEncounter(AABBs[compBoxId].objID, AABBs[keyBoxId].objID);

}

}

//otherwise this is a new encounter

else

{

if((compType == 1) && (keyType == 0))

{

//is this an encounter we're interested in?

if(CheckMap(objType1,objType2))

{

if(Collide(AABBs[compBoxId],AABBs[keyBoxId]))

{

AddEncounter(AABBs[compBoxId].objID,

AABBs[keyBoxId].objID);

}

}

}//end if

}

//swap the points

endpoints[index+1][axis].type = compType;

endpoints[index][axis].type = keyType;

endpoints[index+1][axis].boxID = compBoxId;

endpoints[index][axis].boxID = keyBoxId;

index--;

}//end while

}//end inner for loop

}

ResolveEncounters();

}

void CollisionManager::ResolveEncounters()

{

//will have to be done later - pass the owner entities of these rects to the

//collision resolution code in the actual game - call this code by going

//through the list of encounters one by one

for(int encounter = 0; encounter < numEncounters; encounter++)

{

int id1 = encounters[encounter].objIds[0];

int id2 = encounters[encounter].objIds[1];

g_engine->DealWithCollision(id1,id2);

RemoveEncounter(id1,id2);

}

}

void CollisionManager::AddEncounter(int objID1,int objID2)

{

for(int encounter = 0; encounter < numEncounters; encounter++)

{

//add a new encounter to a list

//make sure it doesn't sit in the list already

if((encounters[encounter].objIds[0] == objID1 && encounters[encounter].objIds[1] == objID2) ||

(encounters[encounter].objIds[0] == objID2 && encounters[encounter].objIds[1] == objID1))

{

//if it does exist return from the function

return;

}

}

//otherwise it obviously doesn't sit in the encounters list yet, so add it!

encounters[numEncounters].objIds[0] = objID1;

encounters[numEncounters].objIds[1] = objID2;

numEncounters++;

}

void CollisionManager::RemoveEncounter(int objID1,int objID2)

{

//remove the encounter

//search through and look for it

for(int encounter = 0; encounter < numEncounters; encounter++)

{

//if encounter found, remove it

if((encounters[encounter].objIds[0] == objID1 && encounters[encounter].objIds[1] == objID2) ||

(encounters[encounter].objIds[0]== objID2 && encounters[encounter].objIds[1] == objID1))

{

for(int index = encounter; index < numEncounters-1; index++)

{

encounters[index] = encounters[index+1];

}

numEncounters--;

return;

}

}

}

int CollisionManager::AddBox(int objID,int left,int top, int right,int bottom,int type)

{

//will need to add some code re obj id

//may have to get entities involved

//add AABB

//add the aabb

AABBs[numBoxes].vals[0][0] = left;

AABBs[numBoxes].vals[1][0] = right;

AABBs[numBoxes].vals[0][1] = top;

AABBs[numBoxes].vals[1][1] = bottom;

AABBs[numBoxes].objID = objID;

AABBs[numBoxes].type = type;

AABBs[numBoxes].boxID = numBoxes;

//add endpoints

endpoints[2 * numBoxes][0].type = 0;

endpoints[2 * numBoxes][0].boxID = numBoxes;

endpoints[2 * numBoxes + 1][0].type = 1;

endpoints[2 * numBoxes + 1 ][0].boxID = numBoxes;

endpoints[2 * numBoxes][1].type = 0;

endpoints[2 * numBoxes][1].boxID = numBoxes;

endpoints[2 * numBoxes + 1][1].type = 1;

endpoints[2 * numBoxes + 1 ][1].boxID = numBoxes;

numBoxes++;

return numBoxes-1;

}

void CollisionManager::RemoveBox(int boxID)

{

//this removes the box with the passed in id from the list - from the encounters list,

//the endpoints list and also the AABB list itself

//this is done simply by swapping the contents of a 'dead' entry with the currently highest indexed

//entry, then decrementing the current number of entries by 1.

int objId = -1;

for(int box = 0; box < numBoxes; box++)

{

if(AABBs[box].boxID == boxID)

{

//get the obj id

objId = AABBs[box].objID;

//shuffle the rest of the array

for(int index = box; index < numBoxes - 1; index++)

{

AABBs[index] = AABBs[index + 1];

}

break;

}

}

for(int box = 0; box < numBoxes * 2; box += 2)

{

if(endpoints[box][0].boxID == boxID)

{

for(int index = box; index < numBoxes * 2; index += 2)

{

//x axis

endpoints[index][0] = endpoints[index+2][0];

endpoints[index][1] = endpoints[index+2][1];

//y axis

endpoints[index+1][0] = endpoints[index+3][0];

endpoints[index+1][1] = endpoints[index+3][1];

}

}

break;

}

//do the same for the encounters

for(int encounter = 0; encounter < numEncounters; encounter++)

{

if(encounters[encounter].objIds[0] == objId || encounters[encounter].objIds[1] == objId)

{

for(int index = encounter; index < numEncounters - 1; index++)

{

encounters[index] = encounters[index+1];

}

numEncounters--;

}

}

numBoxes--;

}

bool CollisionManager::Collide(const Rect& rect1,const Rect& rect2)

{

if(rect1.vals[0][0] > rect2.vals[1][0]) return false;

if(rect1.vals[1][0] < rect2.vals[0][0]) return false;

if(rect1.vals[0][1] > rect2.vals[1][1]) return false;

if(rect1.vals[1][1] < rect2.vals[0][1]) return false;

return true;

}

void CollisionManager::UpdateBox(unsigned int boxID,int left,int right, int top,int bottom)

{

for(int box = 0; box < numBoxes; box++)

{

if(AABBs[box].boxID == boxID)

{

//update the box

AABBs[box].vals[0][0] = left;

AABBs[box].vals[1][0] = right;

AABBs[box].vals[0][1] = top;

AABBs[box].vals[1][1] = bottom;

}

}

}

bool CollisionManager::CheckMap(int type1,int type2)

{

return (collisionMap[type1][type2] == 1);

}

As stated previously, the main problem is that entities that should collide 'pass through' one another. The main important parts of the client code is below (as if this hasn't been overloaded with code already!)

//constant values for 'types'

const int PLAYER_BULLET = 0;

const int PLAYER = 1;

const int ENEMY = 2;

const int ENEMY_BULLET = 3;

const int POWER_UP = 4;

unsigned int collisionMap[COLLISION_MAP_SIZE][COLLISION_MAP_SIZE] = { {0,0,1,0,0},

{0,0,1,1,1},

{1,1,0,0,0},

{0,1,0,0,0},

{0,1,0,0,0}};

.

.

.

Rect enemyAABB(0,0,32,32);

Behaviour* straightBullet = new StraightBehaviour;

Behaviour* staticEnemy = new StaticBehaviour;

entityManagement = new EntityManager(1000);

bulletDescription1.behaviour = straightBullet;

bulletDescription1.movement.velocity = Vector2(gameScript.GetGlobalNumber("PLAYERBULLETXSPEEDUP"),

gameScript.GetGlobalNumber("PLAYERBULLETYSPEED"));

bulletDescription1.AABB = enemyAABB;

bulletDescription1.type = PLAYER_BULLET;

enemyDescription1 = bulletDescription1;

enemyDescription1.sprite.SetPosition(240,30);

enemyDescription1.AABB = enemyAABB;

enemyDescription1.type = ENEMY;

enemyDescription1.movement.velocity.SetY(0.1f);

enemyDescription1.behaviour = straightBullet;

.

.

.

entityManagement->SetCollisionHandler(g_engine->p_collisionManager);

enemyId = entityManagement->CreateEntity(enemyDescription1);

g_engine->p_collisionManager->InitMap(collisionMap,COLLISION_MAP_SIZE);

.

.

.

entityManagement->Update();

.

.

.

void GameEntityCollision(unsigned int id1,unsigned int id2)

{

unsigned int type1 = entityManagement->GetEntity(id1).type;

unsigned int type2 = entityManagement->GetEntity(id2).type;

if((type1 == ENEMY && type2 == PLAYER_BULLET) ||

(type2 == ENEMY && type1 == PLAYER_BULLET))

{

entityManagement->GetEntity(id1).active = false;

entityManagement->GetEntity(id2).active = false;

}

}

//when bullets added to the entity manager the code is called like this...

Vector2 pos = player->GetPosition();

bulletDescription1.sprite.SetPosition(pos + Vector2(0,-30));

entityManagement->CreateEntity(bulletDescription1);

I've spent hours pouring over the code, found a few gotchas and corrected them but still no joy.

If anyone has any suggestions at all, thanks in advance

Respect

Lloyd