📄 roidscontainer.cpp
字号:
TCapsule& capsule = *cap;
if(capsule.IsActive() && aBoundingRect.Contains(capsule.WorldPointAsPoint()))
{
if(capsule.Intersects(iShip))
{
HandleShipHitCapsule(*cap);
}
}
cap = iterator.Next();
}
}
void CRoidsContainer::CalculateCollisions()
{
TRect shipBoundingRect;
iShip.DrawableShape().GetBoundingRect(shipBoundingRect);
CalculateCapsuleCollisions(shipBoundingRect);
TAsteroidIterator iterator(iAsteroidPool->Iterator());
TAsteroid* roid(iterator.First());
while(roid)
{
TInt maxRad = roid->MaxRadius();
TPoint astPoint(roid->WorldPointAsPoint());
// Really rough approximation of the bounding area
TPoint square(maxRad,maxRad);
TRect boundingRect(astPoint-square, astPoint+square);
if(CalculateProjectileCollisions(*roid, boundingRect))
{
if(roid->Hit())
{
// Split roid into fragment objects - the asteroid ceases to be
SplitRoid(*roid);
iAsteroidPool->FreeObject(roid), roid=NULL;
iScore +=KScoreForAsteroidHit;
if(iScore%KScoreForBonusLife==0)
iLives++;
continue;
}
}
if((iShip.State()==TShip::EAlive) && roid)
{
if(shipBoundingRect.Intersects(boundingRect))
{
if(iShip.Intersects(*roid))
{
HandleShipHitAsteroid(*roid);
}
}
}
roid = iterator.Next();
}
}
void CRoidsContainer::UpdateShip()
{
if(iShip.State()==TShip::EInvinsible)
{
iInvinsibleTicker++;
if(iInvinsibleTicker == KFrameTicksForGracePeriod)
iShip.SetState(TShip::EAlive);
}
else
if(iShip.State()==TShip::EExploding)
{
iDeadTicker++;
if(iDeadTicker == KFrameTicksTillReincarnation)
{
iShip.SetState(TShip::EInvinsible);
iInvinsibleTicker=0;
ResetShip();
}
}
UpdateFromKeyStates();
iShip.Quantum();
iShip.CalculateDrawableShape();
ClipObject(iShip);
}
void CRoidsContainer::UpdateProjectiles()
{
TProjectileIterator iterator= iProjectilePool->Iterator();
TProjectile* proj(iterator.First());
while(proj)
{
if(proj->IsActive())
{
TPoint point(proj->WorldPointAsPoint());
proj->Quantum();
if( !Rect().Contains(point))
{
proj->SetActive(EFalse);
iProjectilePool->FreeObject(proj);
}
}
proj=iterator.Next();
}
}
void CRoidsContainer::UpdateCapsules()
{
TCapsuleIterator iterator(iCapsulePool->Iterator());
TCapsule* cap(iterator.First());
while(cap)
{
if(cap->IsActive())
{
cap->Quantum();
cap->CalculateDrawableShape();
//DrawShape(aGc, iCapsules[i].DrawableShape(), KRgbBlue);
}
cap = iterator.Next();
}
}
void CRoidsContainer::UpdateAsteroids()
{
TAsteroidIterator iterator(iAsteroidPool->Iterator());
TAsteroid* roid(iterator.First());
while(roid)
{
roid->Quantum();
ClipObject(*roid);
roid->CalculateDrawableShape();
roid = iterator.Next();
}
}
void CRoidsContainer::UpdateExplosionFragments()
{
for(TInt i=0; i<KMaxExplosionFragments; i++)
{
TExplosionFragment& frag = *&iExplosionFragments[i];
if(frag.IsActive())
{
frag.IncAge(KFragMentAgeIncrement);
if(frag.Age()>=KFragmentAgeEndOfLife)
{
frag.SetActive(EFalse);
}
else
{
frag.Quantum();
frag.CalculateDrawableShape();
}
}
}
}
void CRoidsContainer::HandleNextLevel(TInt aLevel)
{
ResetRoids(Min(aLevel, 10));
SetRoidsMaterial(aLevel);
iCapsulePool->Reset(); // Zeros memory
TInt w=Size().iWidth;
TInt h=Size().iHeight;
for(TInt ic=0; ic< aLevel; ic++)
{
TCapsule* capsule = iCapsulePool->NewObject();
capsule->SetWorldPoint(TPoint(MathUtils::Random(0,w) ,MathUtils::Random(0,h)));
capsule->SetActive(ETrue);
capsule->CalculateDrawableShape();
}
}
void CRoidsContainer::SetRoidsMaterial(TInt aLevel)
{
if(aLevel<6)
return; // leave as default material
TAsteroidIterator iterator(iAsteroidPool->Iterator());
TAsteroid* roid(iterator.First());
while(roid)
{
TInt random = MathUtils::Random(0,3);
TAsteroid::TRockMaterial material= static_cast<TAsteroid::TRockMaterial>(random);
roid->SetMaterial(material);
roid = iterator.Next();
}
}
void CRoidsContainer::GfxTimerFiredL(TInt /*aId*/)
{
// Logic which decides if we are ready for the next level
if( (iCapsulePool->Count()==0) &&
(iAsteroidPool->Count()==0) && iGameState == EPlaying)
{
// This next level ticker gives the user a bit of a break before
// starting the next level
if(iNextLevelTicker==-1)
iNextLevelTicker=60;
iNextLevelTicker--;
if(iNextLevelTicker == -1)
HandleNextLevel(iLevel++);
}
else
{
iNextLevelTicker=-1;
}
// Move each world object along one quantum
// and then calculate collisions
if(iGameState == EPlaying)
{
UpdateShip();
}
UpdateProjectiles();
UpdateAsteroids();
UpdateExplosionFragments();
UpdateShipExplosion();
UpdateCapsules();
CalculateCollisions();
// Draw new results to offscreen bitmap and flush to scren
DrawGame(*iBitmapGc);
DrawNow();
}
void CRoidsContainer::UpdateShipExplosion()
{
iStarBurstRadius+=KStarBurstRadiusIncrement;
if(iStarBurstRadius>KStarBurstRadiusMax)
{
iDrawStarbust = EFalse;
}
}
//
// Key handling methods
//
void CRoidsContainer::SetKeyDown(const TGameKey& aKey, const TKeyEvent& aKeyEvent)
{
//iKeyFlags|= (1<<aKey);
iScanCodes[aKey] = aKeyEvent.iScanCode;
}
TBool CRoidsContainer::IsKeyPressed()
{
for(TInt i=EKeyMaxVirtualKey-1; i>=0; i--)
{
if(iScanCodes[i] !=0)
{
return ETrue;
}
}
return EFalse;
}
void CRoidsContainer::ClearKeyDown(const TGameKey& aKey)
{
iScanCodes[aKey]=0;
//iKeyFlags&=~(1<<aKey);
}
TBool CRoidsContainer::KeyDown(const TGameKey& aKey)
{
return iScanCodes[aKey]!=0;
//return iKeyFlags&(1<<aKey);
}
/*
* FindFreeFragment
* Try to grab space in the fragment buffer for asteroid debris
* If there is no space free then we have reached the maxium number of
* fragments. This keeps the graphics drawing time bounded
*/
TBool CRoidsContainer::FindFreeFragment(TExplosionFragment*& aFragment)
{
for(TInt i=0; i<KMaxExplosionFragments; i++)
{
if(!iExplosionFragments[i].IsActive())
{
aFragment=&iExplosionFragments[i];
iExplosionFragments[i].SetActive(ETrue);
return ETrue;
}
}
return EFalse;
}
// This takes an object anc creates a fragment for every line in the
// polygon, it then sets each line off in the direction aObject is currently moving in
// but adds some randomess so that fragments "fly off"
void CRoidsContainer::CreateExplodeFragmentsFromObject(TWorldObject& aObject)
{
const MPolygon& poly = aObject.DrawableShape();
for(TInt i=0; i<poly.PolyLineCount(); i++)
{
TPoint start;
TPoint end;
poly.GetPolyLine(i, start, end);
TPoint midpoint((start.iX + end.iX)/2, (start.iY + end.iY)/2 );
start = midpoint-start;
end = midpoint-end;
TExplosionFragment* frag;
if(!FindFreeFragment(frag))
return; // Not enough fragments allocated for explosion...it's ok just less detail
frag->SetPoints(start,end);
// Set shape origin to midpoint on the line
frag->SetWorldPoint(midpoint);
frag->CopySpeedAndDirection(aObject);
// Add a bit of variety
frag->AccelerateInDirection(MathUtils::Random(0,360), TReal(Math::Random()%10) / (Math::Random()%10+1) );
// Let the fragment drift off and age
frag->ResetAge();
frag->CalculateDrawableShape();
frag->SetActive(ETrue);
}
}
void CRoidsContainer::SplitShip()
{
CreateExplodeFragmentsFromObject(iShip);
iStarBurstRadius = 1;
iDrawStarbust = ETrue;
}
void CRoidsContainer::SplitRoid(TAsteroid& aRoid)
{
TInt sides = aRoid.DrawableShape().PolyCount();
CreateExplodeFragmentsFromObject(aRoid);
// Split asteroids radius into two
TInt radius = aRoid.MaxRadius()/2;
// if fragments are big enough, create some smaller asteroids
const TInt KMinAsteroidRadius = 5;
if(radius>KMinAsteroidRadius)
{
//
TInt numberOfAsteroids = radius/9;
for(TInt i=0; i<numberOfAsteroids; i++)
{
TAsteroid* asteroid = iAsteroidPool->NewObject();
asteroid->Construct(sides, sides, 5, radius);
asteroid->SetActive(ETrue);
asteroid->SetWorldPoint(aRoid.WorldPoint() );
TInt speed = MathUtils::Round(6.0 - ((TReal(radius)/ 35.0) * 5.0));
speed = speed + MathUtils::Random(-2,+2);
asteroid->SetSpeedAndDirection(Math::Random()%360, speed);
asteroid->SetMaterial(aRoid.Material());
asteroid->CalculateDrawableShape();
}
}
}
void CRoidsContainer::ResetRoids(TInt aNum)
{
// ClearPool and zero array
iAsteroidPool->Reset();
for(TInt i=0; i<aNum; i++)
{
TAsteroid* asteroid = iAsteroidPool->NewObject();
asteroid->Construct(5,10,10, Size().iWidth/6);
asteroid->SetActive(ETrue);
// Lay around the edges of the screen
if(Math::Random()%2)
asteroid->SetWorldPoint(TWorldPoint(Math::Random()%Size().iWidth, 0));
else
asteroid->SetWorldPoint(TWorldPoint(0,Math::Random()%Size().iHeight));
//TInt speed = Min(Math::Random()%(iLevel+1)+1,1);
asteroid->SetSpeedAndDirection(Math::Random()%360, 1 );
}
}
void CRoidsContainer::DrawStarBust() const
{
TBitmapUtil bUtil(iBackupBitmap);
bUtil.Begin(TPoint(0,0));
TDisplayMode display = iEikonEnv->DefaultDisplayMode();
for(TInt i=0; i<KStarBurstDensity; i++)
{
TReal deviation = TReal(MathUtils::Random(-10,10));
TInt angle = i*360 / 200;
deviation += iStarBurstRadius;
TPoint p(iShip.WorldPointAsPoint());
p.iX+= MathUtils::Round(MathUtils::Sin(angle) * deviation);
p.iY+= MathUtils::Round(MathUtils::Cos(angle) * deviation);
bUtil.SetPos(p);
TInt gray = 255- MathUtils::Round(iStarBurstRadius);
TRgb rgb(gray,gray,0);
switch(display)
{
case EColor64K:
bUtil.SetPixel(rgb._Color64K());
break;
case EColor4K:
bUtil.SetPixel(rgb._Color4K());
break;
default:
bUtil.SetPixel(rgb._Color16M());
}
}
bUtil.End();
}
TKeyResponse CRoidsContainer::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
{
//TInt code = aKeyEvent.iCode & ~(EModifierCtrl|EModifierShift);
TInt code = aKeyEvent.iScanCode;
if(aKeyEvent.iScanCode == EStdKeyUpArrow)
{
if(aType == EEventKeyDown)
{
if(!KeyDown(EKeyThrust))
{
SetKeyDown(EKeyThrust, aKeyEvent);
UpdateFromKeyStates();
return EKeyWasConsumed;
}
}
else
if(aType == EEventKeyUp)
{
ClearKeyDown(EKeyThrust);
return EKeyWasConsumed;
}
}
if(aType == EEventKeyDown)
{
if((iGameState == EGameOver) && !IsKeyPressed())
{
iGameState = EIntro;
ResetGame();
return EKeyWasConsumed;
}
else
if((iGameState != EPlaying) && !IsKeyPressed())
{
iGameState = EPlaying;
ResetGame();
return EKeyWasConsumed;
}
if(code=='s')
{
SonicBoom();
}
if(code=='1')
{
iLineWidth =1 ;
return EKeyWasConsumed;
}
if(code=='2')
{
iLineWidth++;
return EKeyWasConsumed;
}
if(code=='3')
{
iShowBoundinBox = ETrue;
return EKeyWasConsumed;
}
TGameKey key;
if(code == EStdKeyLeftArrow)
key=EKeyRotateLeft;
else
if(code == EStdKeyRightArrow)
key=EKeyRotateRight;
else
if( (code == 'Z') || (code == 'Q') || (code == 'P'))
key=EKeyThrust;
else
// if(code == EStdKeyXXX || code == EStdKeyDevice0)
key=EKeyFireGun;
// We have a game key, so we must comsume it
if(!KeyDown(key))
{
SetKeyDown(key,aKeyEvent);
UpdateFromKeyStates();
}
return EKeyWasConsumed;
}
else
if(aType == EEventKeyUp)
{
// Clear the Game key associated with the scancode
for(TInt i=0; i<EKeyMaxVirtualKey; i++)
{
if(iScanCodes[i]==aKeyEvent.iScanCode)
ClearKeyDown((TGameKey)i);
}
}
return EKeyWasNotConsumed;
}
void CRoidsContainer::SonicBoom()
{
TInt len = iAsteroidPool->Count();
if(len==0)
return;
/*
for(i=0; i<len ; i++)
{
SplitRoid(*iAsteroids[i]);
iAsteroidPool->FreeObject(iAsteroids[i]);
}
for(i=len-1; len>=0; len--)
{
iAsteroids.Remove(i);
}*/
}
void CRoidsContainer::LaunchProjectile()
{
TProjectile* proj = iProjectilePool->NewObjectOrNull();
if(!proj)
return; // Ran out of projectiles
TInt direction = iShip.FacingDirection();
proj->SetActive(ETrue);
proj->SetWorldPoint(iShip.Nose());
proj->SetSpeedAndDirection(direction, 10);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -