//////////////////////////////////////////////////////////////////////////////////////
//
// File: CCollisionBucket.cpp
// Date: 10/15/2008
// Creator: John Rodenburg
// Description: Implementation of the CCollisionBucket
//
//////////////////////////////////////////////////////////////////////////////////////
#ifndef _CUPDATECOLLISIONBUCKET_H_
#define _CUPDATECOLLISIONBUCKET_H_
#include "CBucket.h"
#include "CPlayer.h"
#include "CWalls.h"
class CUpdateCollisionBucket : public CBucket
{
CUpdateCollisionBucket(const CUpdateCollisionBucket &);
CUpdateCollisionBucket &operator=(const CUpdateCollisionBucket &);
public:
CUpdateCollisionBucket();
~CUpdateCollisionBucket();
void Init();
void Update(BUCKET_ID parentID);
void Shutdown();
};
#endif
######################################################## END OF FILE ##############################################
//////////////////////////////////////////////////////////////////////////////////////
//
// File: CUpdateCollisionBucket.cpp
// Date: 10/15/2008
// Creator: John Rodenburg
// Description: Implementation of the CUpdateCollisionBucket
//
//////////////////////////////////////////////////////////////////////////////////////
#include <algorithm>
using std::sort;
#include "CDispatchManager.h"
#include "CGameManager.h"
#include "CGameObject.h"
#include "CSceneObject.h"
#include "CPlayer.h"
#include "CBullet.h"
#include "CPickup.h"
#include "CAIPlayer.h"
#include "CSoundManager.h"
#include "CCollisionManager.h"
#include "CDragEffect.h"
#include "CPlayer.h"
#include "CRacer.h"
#include "CUpdateCollisionBucket.h"
bool UDGreater(CBucketItem *item1, CBucketItem *item2)
{
int value1;
int value2;
item1->SortValue(UPDATE_COLLISION_BUCKET, value1);
item2->SortValue(UPDATE_COLLISION_BUCKET, value2);
return value1 > value2;
}
bool UDLesser(CBucketItem *item1, CBucketItem *item2)
{
int value1;
int value2;
item1->SortValue(UPDATE_COLLISION_BUCKET, value1);
item2->SortValue(UPDATE_COLLISION_BUCKET, value2);
return value1 < value2;
}
CUpdateCollisionBucket::CUpdateCollisionBucket()
{
m_nID = UPDATE_COLLISION_BUCKET;
}
CUpdateCollisionBucket::~CUpdateCollisionBucket()
{
}
void CUpdateCollisionBucket::Init()
{
DispatchManager().RegisterBucket(m_nID, this);
}
void CUpdateCollisionBucket::Update(BUCKET_ID parentID)
{
if (m_bLocked)
return;
if (!m_bSorted)
{
std::sort(m_vBucketItems.begin(), m_vBucketItems.end(), UDLesser);
m_bSorted = true;
} // end if
for (size_t i = 0; i < m_vBucketItems.size() - 1; ++i)
{
for (size_t j = i + 1; j < m_vBucketItems.size(); ++j)
{
//Check what kind of object we are checking (I)
switch(((CGameObject*)m_vBucketItems[i])->GetType())
{
case OBJECT_SHIP:
//Once we have determined, Check what it is checking against
switch(((CGameObject*)m_vBucketItems[j])->GetType())
{
///////////////////////////////////////////////////////////////
///Collide with Ship, Weapon, Powerup, Wall
////////////////////////////////////////////////////////////////
case OBJECT_SHIP:
{
if(CollisionManager().Test( ((CGameObject*)m_vBucketItems[i])->Sphere(), ((CGameObject*)m_vBucketItems[j])->Sphere() ))
if (((CRacer*)m_vBucketItems[i])->ProcessCollision((CGameObject*)m_vBucketItems[j]))
continue;
}
break;
case OBJECT_WEAPON:
{
if(CollisionManager().Test( ((CGameObject*)m_vBucketItems[i])->Sphere(), ((CGameObject*)m_vBucketItems[j])->Sphere() ))
{
if(((CRacer*)m_vBucketItems[i])->IsPlayer())
{
((CPlayer*)m_vBucketItems[i])->ProcessCollision((CBullet*)m_vBucketItems[j]);
}
else
{
((CAIPlayer*)m_vBucketItems[i])->ProcessCollision((CBullet*)m_vBucketItems[j]);
}
((CBullet*)m_vBucketItems[j])->ProcessCollision((CRacer*)m_vBucketItems[i]);
}
}
break;
case OBJECT_BOOSTRING:
{
CRacer* currentShip = (CRacer*)m_vBucketItems[i];
CBoostRing* currentRing = (CBoostRing*)m_vBucketItems[j];
// Check if its the player
if (!GameManager().Player().IsStarting())
{
if (currentShip->IsPlayer())
{
CPlayer* thePlayer = (CPlayer*)m_vBucketItems[i];
// Check if the boost is active for the player - have they passed it already?
if(currentShip->GetCurrentBoostRing() == currentRing->GetID())
{
float distanceFromRing = currentShip->DistanceFrom(currentRing);
thePlayer->SetDistanceFromRing(distanceFromRing);
currentRing->SetEffectColorByDistance(distanceFromRing);
if (distanceFromRing < MAX_DISTANCEFROMBOOST && !thePlayer->IsApproachingGate())
{
thePlayer->TurnApproachingGateOn();
}
D3DXVECTOR3 toShip(currentShip->Transform().axis_pos - currentRing->Transform().axis_pos);
float result = D3DXVec3Dot(&(currentRing->Transform().axis_z), &toShip);
// Apply the boost and rating if player is at buffer zone
if (result < 0.0f)
{
thePlayer->TurnApproachingGateOff();
currentRing->FireStarEffect();
int boostPressResult = thePlayer->ResultFromBoostGate();
float applyValue;
switch(boostPressResult)
{
case (int)RESULT_POOR:
applyValue = 1.2f;
break;
case (int)RESULT_GOOD:
applyValue = 1.4f;
break;
case (int)RESULT_VERYGOOD:
applyValue = 1.7f;
break;
case (int)RESULT_PERFECT:
applyValue = 2.0f;
break;
default:
applyValue = 1.0f;
break;
}
currentRing->SetEffectColorByDistance(MAX_DISTANCEFROMBOOST);
thePlayer->SetBoostRing(thePlayer->GetCurrentBoostRing() + 1);
int maxRings = GameManager().GetMaxRings();
if (thePlayer->GetCurrentBoostRing() >= maxRings)
{
thePlayer->SetBoostRing(0);
}
thePlayer->Boost(thePlayer->BoostFactor() * applyValue);
thePlayer->AddBoost();
thePlayer->IncreaseBoostRingsRow();
}
}
}
else
{
if(currentShip->GetCurrentBoostRing() == currentRing->GetID())
{
D3DXVECTOR3 toShip(currentShip->Transform().axis_pos - currentRing->Transform().axis_pos);
float result = D3DXVec3Dot(&(currentRing->Transform().axis_z), &toShip);
if (result < 0.0f)
{
float applyValue;
int r = RAND_INT(0, 4);
switch(r)
{
case (int)RESULT_POOR:
applyValue = 1.2f;
break;
case (int)RESULT_GOOD:
applyValue = 1.4f;
currentShip->AddBoost();
break;
case (int)RESULT_VERYGOOD:
applyValue = 1.7f;
currentShip->AddBoost();
break;
case (int)RESULT_PERFECT:
applyValue = 2.0f;
currentShip->AddBoost();
currentShip->AddBoost();
break;
default:
applyValue = 1.0f;
break;
}
currentShip->SetBoostRing(currentShip->GetCurrentBoostRing() + 1);
if (currentShip->GetCurrentBoostRing() > GameManager().GetMaxRings())
{
currentShip->SetBoostRing(0);
}
currentShip->Boost(currentShip->BoostFactor());
}
}
}
}
// Check if its the second player?
//else if
// Else it is an AI Ship
//else
//{
//}
}
break;
case OBJECT_POWERUP:
{
if(CollisionManager().Test( ((CGameObject*)m_vBucketItems[i])->Sphere(), ((CGameObject*)m_vBucketItems[j])->Sphere() ))
if (((CRacer*)m_vBucketItems[i])->ProcessCollision((CGameObject*)m_vBucketItems[j]))
continue;
}
break;
case OBJECT_WALL:
{
///////////////////////
// check update line //
///////////////////////
unsigned int nCount = 0;
unsigned int nIndex = 0;
vector<tTriangle> vTris;
D3DXVECTOR3 vCollision;
D3DXVECTOR3 vBegin = ((CRacer*)m_vBucketItems[i])->OldPosition();
D3DXVECTOR3 vEnd = ((CRacer*)m_vBucketItems[i])->Transform().axis_pos;
CollisionManager().GetTriangles(((CGameObject*)m_vBucketItems[j])->Tree(), vTris, &nCount, vBegin, vEnd );
if (!vTris.empty())
{
if(CollisionManager().LineSegment2Triangle(vCollision, nIndex, vTris, nCount, vBegin, vEnd))
((CRacer*)m_vBucketItems[i])->Transform().axis_pos = vCollision;
vTris.empty();
nCount = 0;
} // end if
/////////////////////////
// check update sphere //
/////////////////////////
D3DXVECTOR3 vClosestPoint;
CollisionManager().GetTriangles(((CGameObject*)m_vBucketItems[j])->Tree(),vTris, vClosestPoint, &nCount,&((CGameObject*)m_vBucketItems[i])->Sphere() );
if (vTris.empty())
continue;
float fRadius = ((CGameObject*)m_vBucketItems[i])->Sphere().GetRadius();
int nNumTris = (int)vTris.size();
for (int k = 0; k < nNumTris; ++k)
{
D3DXVECTOR3 vBegin = ((CGameObject*)m_vBucketItems[i])->Transform().axis_pos;
D3DXVECTOR3 toSphere(vBegin - vTris[k].vCentroid);
float result = D3DXVec3Dot(&vTris[k].vNormal, &toSphere);
if (result < fRadius)
{
float fPenetration = fRadius - result;
D3DXVECTOR3 newPos = ((CGameObject*) m_vBucketItems[i])->Transform().axis_pos + vTris[k].vNormal * (fPenetration);
((CGameObject*) m_vBucketItems[i])->Transform().axis_pos = newPos;
((CGameObject*)m_vBucketItems[i])->Sphere().SetCenter(newPos);
((CRacer*)m_vBucketItems[i])->ProcessCollision((CGameObject*)m_vBucketItems[j]);
}
}
if (newSpeed <= 0.0f)
{
newSpeed = 0.0f;
}
((CRacer*)m_vBucketItems[i])->SetCurrentSpeed(newSpeed);*/
}
break;
case OBJECT_TRACK:
{
/////////////////
// orient ship //
/////////////////
if (CollisionManager().ClampRacer(*((CGameObject*)m_vBucketItems[i]), ((CGameObject*)m_vBucketItems[j])->Tree(), 10.0f))
{
string sName = ((CSceneObject*)m_vBucketItems[j])->Name();
if (sName.find("JumpTrack_") != string::npos)
((CRacer*)m_vBucketItems[i])->OnRail(true);
else
((CRacer*)m_vBucketItems[i])->OnRail(false);
CollisionManager().TerrainFollow(*((CGameObject*)m_vBucketItems[i]), ((CGameObject*)m_vBucketItems[j])->Tree(), 10.0f);
} // end if
}
break;
}
break;
case OBJECT_WEAPON:
//Once we have determined, Check what it is checking against
switch(((CGameObject*)m_vBucketItems[j])->GetType())
{
///////////////////////////////////////////////////////////////
///Collide with Ship/Wall, continue if Weapon or Powerup
////////////////////////////////////////////////////////////////
case OBJECT_SHIP:
{
if(CollisionManager().Test( ((CGameObject*)m_vBucketItems[i])->Sphere(), ((CGameObject*)m_vBucketItems[j])->Sphere() ))
{
if(((CRacer*)m_vBucketItems[j])->IsPlayer())
{
((CPlayer*)m_vBucketItems[j])->ProcessCollision((CBullet*)m_vBucketItems[i]);
}
else
{
((CAIPlayer*)m_vBucketItems[j])->ProcessCollision((CBullet*)m_vBucketItems[i]);
}
((CBullet*)m_vBucketItems[i])->ProcessCollision((CRacer*)m_vBucketItems[j]);
}
}
break;
case OBJECT_WEAPON:
{
if(CollisionManager().Test( ((CGameObject*)m_vBucketItems[i])->Sphere(), ((CGameObject*)m_vBucketItems[j])->Sphere() ))
if (((CBullet*)m_vBucketItems[i])->ProcessCollision((CGameObject*)m_vBucketItems[j]))
continue;
continue;
}
break;
case OBJECT_POWERUP:
{
continue;
}
break;
case OBJECT_BOOSTRING:
{
continue;
}
break;
case OBJECT_WALL:
{
unsigned int nCount, nIndex = 0;
vector<tTriangle> vTris;
D3DXVECTOR3 vClosestPoint;
D3DXVECTOR3 vCollision;
CollisionManager().GetTriangles(((CGameObject*)m_vBucketItems[j])->Tree(),vTris, vClosestPoint, &nCount,& ((CGameObject*)m_vBucketItems[i])->Sphere() );
if (!vTris.empty())
{ //continue;
vTris.clear();
if ( ((CBullet*)m_vBucketItems[i])->ProcessCollision( (CGameObject*)m_vBucketItems[j]) )
{
break;
}
}
vTris.clear();
}
case OBJECT_TRACK:
{
// Clamping the bullet is causing problems
// The bullet does not launch from the player correctly when facing forward
// and when it hits certain points on the track it gets stuck
if (CollisionManager().ClampRacer(*((CGameObject*)m_vBucketItems[i]), ((CGameObject*)m_vBucketItems[j])->Tree(), 10.0f))
CollisionManager().TerrainFollow(*((CGameObject*)m_vBucketItems[i]), ((CGameObject*)m_vBucketItems[j])->Tree(), 10.0f);
}
break;
}
break;
case OBJECT_POWERUP:
//Once we have determined, Check what it is checking against
switch(((CGameObject*)m_vBucketItems[j])->GetType())
{
///////////////////////////////////////////////////////////////
///Collide only with the Player Ship
////////////////////////////////////////////////////////////////
case OBJECT_SHIP:
if(CollisionManager().Test( ((CPickup*)m_vBucketItems[i])->Sphere(), ((CRacer*)m_vBucketItems[j])->Sphere() ))
{
((CPickup*)m_vBucketItems[i])->ProcessCollision((CGameObject*)m_vBucketItems[j]);
((CRacer*)m_vBucketItems[j])->ProcessCollision((CGameObject*)m_vBucketItems[i]);
}
break;
case OBJECT_WEAPON:
continue;
break;
case OBJECT_POWERUP:
continue;
break;
case OBJECT_BOOSTRING:
{
continue;
}
break;
case OBJECT_WALL:
continue;
break;
}
break;
case OBJECT_WALL:
//Once we have determined, Check what it is checking against
switch(((CGameObject*)m_vBucketItems[j])->GetType())
{
///////////////////////////////////////////////////////////////
///Collide only with the Player Ship
////////////////////////////////////////////////////////////////
case OBJECT_SHIP:
//if(CollisionManager().Test( ((CGameObject*)m_vBucketItems[i])->Sphere(), ((CGameObject*)m_vBucketItems[j])->Sphere() ))
// if (((CRacer*)m_vBucketItems[i])->ProcessCollision((CGameObject*)m_vBucketItems[j]))
continue;
break;
case OBJECT_WEAPON:
//TODO: Removed HACK!
break;
case OBJECT_POWERUP:
continue;
break;
case OBJECT_BOOSTRING:
{
continue;
}
break;
case OBJECT_WALL:
continue;
break;
}
break;
default:
break;
}
} // end for
switch(((CGameObject*)m_vBucketItems[i])->GetType())
{
case OBJECT_SHIP:
break;
} // end switch
} // end for
}
void CUpdateCollisionBucket::Shutdown()
{
m_vBucketItems.clear();
}