📄 roidscontainer.cpp
字号:
/*
* ============================================================================
* Name : CRoidsContainer from RoidsContainer.h
* Part of : roids
* Created : 05/12/2001 by Twm Davies
* Implementation notes:
* Initial content was generated by Nokia Series 60 AppWizard.
* Version :
* Copyright: Twm Davies
* ============================================================================
*/
// INCLUDE FILES
#include "RoidsContainer.h"
#include <eiklabel.h> // for example label control
#include <e32keys.h>
#include <coemain.h>
#include <eikenv.h>
#include <eikdef.h>
#include <roidsS60.rsg>
#include <nebula.mbg>
#include "roids.hrh"
#include "roidscontainer.h"
#include "polygon.h"
#include "casteroidpool.h"
#include <E32MATH.h>
#include "CGfxTimer.h"
const TInt KOneSecondInMicroSeconds = 1000000;
const TInt KFramesPerSecond = KOneSecondInMicroSeconds/35;
const TInt KScoreForAsteroidHit = 100;
const TInt KScoreForBonusLife = 6000;
const TInt KFrameTicksForGracePeriod = 50;
const TInt KFrameTicksTillReincarnation = 50;
const TInt KFragMentAgeIncrement = 10;
const TInt KFragmentAgeEndOfLife = 255;
const TInt KStarBurstRadiusIncrement =5;
const float KStarBurstRadiusMax = 255.0;
const TInt KStarBurstDensity = 1000;
_LIT(KRoidsLogoText, "-= R O I D S =- ");
_LIT(KRoidsAuthorLogo, "by TwmDesign");
_LIT(KLevelText, "Level");
_LIT(KGameOverText, "G A M E O V E R");
void Panic(TInt aPanic)
{
User::Panic(_L("Roids App"),aPanic);
}
// Class CRoidsContainer
void CRoidsContainer::FocusChanged(TDrawNow aDrawNow)
{
SetPaused(!IsFocused());
if(aDrawNow)
DrawNow();
}
void CRoidsContainer::SetPaused(TBool aState)
{
if(aState)
iGfxTimer->Pause();
else
iGfxTimer->ReStart();
}
/*
* DrawBackgroundStars
* Fast pixel plot of starfild
*/
void CRoidsContainer::DrawBackgroundStars(CWsBitmap& aBitmap) const
{
TBitmapUtil bUtil(&aBitmap);
TDisplayMode display = iEikonEnv->DefaultDisplayMode();
bUtil.Begin(TPoint(0,0));
for(TInt i=0; i<EMaxStars; i++)
{
TPoint point(iStars[i].iX, iStars[i].iY);
bUtil.SetPos(point);
TInt gray = i%200 + 55;
TRgb rgb(gray,gray,gray);
switch(display)
{
case EColor64K:
bUtil.SetPixel(rgb._Color64K());
break;
case EColor4K:
bUtil.SetPixel(rgb._Color4K());
break;
default:
bUtil.SetPixel(rgb._Color16M());
}
}
bUtil.End();
}
CWsBitmap* CRoidsContainer::LoadBitmapToFullScreenL(TRect aRect)
{
CWsBitmap* bitmap = new(ELeave)CWsBitmap(iCoeEnv->WsSession());
CleanupStack::PushL(bitmap);
User::LeaveIfError(bitmap->Create(Rect().Size(), iEikonEnv->DefaultDisplayMode()));
CFbsBitmapDevice* bitmapDevice=CFbsBitmapDevice::NewL(bitmap);
CleanupStack::PushL(bitmapDevice);
CFbsBitGc* gc;
User::LeaveIfError(bitmapDevice->CreateContext(gc));
CleanupStack::PushL(gc);
CWsBitmap* neb = iEikonEnv->CreateBitmapL(_L("\\resource\\apps\\nebula.mbm"), EMbmNebulaNebula );
gc->Reset();
gc->SetBrushColor(KRgbBlack);
gc->Clear();
TPoint offset = bitmap->SizeInPixels().AsPoint() - neb->SizeInPixels().AsPoint();
gc->BitBlt(offset, neb);
//gc->DrawBitmap(aRect,neb);
delete neb;
CleanupStack::PopAndDestroy(2, bitmapDevice);
CleanupStack::Pop(bitmap);
return bitmap;
}
void CRoidsContainer::ConstructL(const TRect& aRect)
{
CreateWindowL();
SetBlank();
SetRect(aRect);
iBackupBitmap = new(ELeave)CWsBitmap(iCoeEnv->WsSession());
iBackupBitmap->Create(Rect().Size(), iEikonEnv->DefaultDisplayMode());
iBitmapDevice=CFbsBitmapDevice::NewL(iBackupBitmap);
User::LeaveIfError(iBitmapDevice->CreateContext(iBitmapGc));
// Start the game heartbeat
iGfxTimer = new(ELeave)CGfxTimer(*this, NULL);
iGfxTimer->ConstructL();
iGfxTimer->StartPulse(KFramesPerSecond);
iAsteroidPool = new(ELeave) CAsteroidPool();
iCapsulePool = new(ELeave) CCapsulePool();
iProjectilePool = new(ELeave) CProjectilePool();
ResetGame();
iInvinsibleTicker = 0;
iLineWidth =1;
// Pregenerate background stars
for(TInt i=0; i< EMaxStars; i++)
{
iStars[i].iX = Math::Random()%Size().iWidth;
iStars[i].iY = Math::Random()%Size().iHeight;
}
// Construct lives indicator Shape
iLivesShape[0] = TPoint(0, -6);
iLivesShape[1] = TPoint(+3, +6);
iLivesShape[2] = TPoint(-3, +6);
iGameState = EIntro;
ResetRoids(4);
TRAPD(err, iNebula= LoadBitmapToFullScreenL(aRect));
ActivateL();
}
CRoidsContainer::~CRoidsContainer()
{
delete iAsteroidPool;
delete iCapsulePool;
delete iProjectilePool;
delete iBackupBitmap;
delete iGfxTimer;
delete iBitmapDevice;
delete iBitmapGc;
delete iNebula;
}
void CRoidsContainer::SizeChanged()
{
}
TInt CRoidsContainer::CountComponentControls() const
{
return 0;
}
CCoeControl* CRoidsContainer::ComponentControl(TInt /*aIndex*/) const
{
return NULL;
}
void CRoidsContainer::Draw(const TRect& aRect) const
{
CWindowGc& gc=SystemGc();
gc.BitBlt(aRect.iTl, iBackupBitmap, aRect);
}
void CRoidsContainer::UpdateFromKeyStates()
{
if( (iShip.State()==TShip::EAlive) ||
(iShip.State()==TShip::EInvinsible))
{
if(KeyDown(EKeyRotateLeft))
iShip.DecAngle();
if(KeyDown(EKeyRotateRight))
iShip.IncAngle();
if(KeyDown(EKeyThrust))
iShip.Accelerate();
if(KeyDown(EKeyFireGun))
{
ClearKeyDown(EKeyFireGun); // We don't want any repeats for fire;
LaunchProjectile();
}
}
}
void CRoidsContainer::HandleShipHitAsteroid(TAsteroid& /*aAsteroid*/)
{
if(iShip.State() == TShip::EExploding)
return;
SplitShip();
iShip.SetState(TShip::EExploding);
iDeadTicker =0;
iLives--;
if(iLives==0)
{
iGameState = EGameOver;
}
}
void CRoidsContainer::ResetGame()
{
iGameState = EPlaying;
ResetShip();
iLives=3;
iLevel=1;
iScore=0;
iNextLevelTicker = -1;
iInvinsibleTicker = 0;
HandleNextLevel(0);
iProjectilePool->Reset();
}
void CRoidsContainer::ResetShip()
{
iShip.Construct();
iShip.SetState(TShip::EInvinsible);
// Center point
iShip.SetWorldPoint(TPoint(Size().iWidth/2, Size().iHeight/2));
iShip.SetSpeedAndDirection(0,0.0);
}
void CRoidsContainer::DrawExplosionParticle(CGraphicsContext& aGc, const TExplosionFragment& aFragment) const
{
const MPolygon& shape = aFragment.DrawableShape();
TInt gray = 255-aFragment.Age();
aGc.SetPenColor(TRgb(gray, gray, gray));
aGc.DrawLine(shape.PolyPoint(0), shape.PolyPoint(1) );
}
// Translates and draws the shape
void CRoidsContainer::DrawShape(CGraphicsContext& aGc, const MPolygon& aPolygon, TRgb aColor) const
{
if(iShowBoundinBox)
{
aGc.Reset();
aGc.SetPenColor(KRgbGreen);
TRect bound;
aPolygon.GetBoundingRect(bound);
aGc.DrawRect(bound);
}
aGc.Reset();
aGc.SetPenColor(aColor);
aGc.SetPenSize(TSize(iLineWidth,iLineWidth));
for(TInt i=0; i<aPolygon.PolyLineCount(); i++)
{
TPoint start;
TPoint end;
aPolygon.GetPolyLine(i, start, end);
aGc.DrawLine(start, end);
}
}
void CRoidsContainer::DrawLivesAndScoreIndicator(CGraphicsContext& aGc) const
{
TPoint center(Size().iWidth-12, Size().iHeight-12);
TFixedPolygon<3> shapeBuffer;
for(TInt i=0; i<iLives;i++)
{
iLivesShape.Offset(center, shapeBuffer);
DrawShape(aGc, shapeBuffer, KRgbGreen);
center+=TPoint(-18,0);
}
aGc.UseFont(iEikonEnv->NormalFont());
TBuf<20> text;
text.Num(iScore);
aGc.DrawText(text,TPoint(Size().iWidth-iEikonEnv->NormalFont()->TextWidthInPixels(text)-6, Size().iHeight-23) );
aGc.DiscardFont();
};
void CRoidsContainer::DrawGameOver(CGraphicsContext& aGc) const
{
aGc.UseFont(iEikonEnv->TitleFont());
aGc.DrawText(KGameOverText,
TPoint(Size().iWidth/2 - (iEikonEnv->TitleFont()->TextWidthInPixels(KGameOverText)/2),
Size().iHeight/2) );
aGc.DiscardFont();
}
void CRoidsContainer::DrawIntro(CGraphicsContext& aGc) const
{
aGc.SetPenColor(KRgbGreen);
aGc.UseFont(iEikonEnv->TitleFont());
aGc.SetPenColor(KRgbBlack);
aGc.DrawText(KRoidsLogoText,
TPoint(Size().iWidth/2 - (iEikonEnv->TitleFont()->TextWidthInPixels(KRoidsLogoText)/2)+2,
Size().iHeight/2-18) );
aGc.SetPenColor(TRgb(0,150,0) );
aGc.DrawText(KRoidsLogoText,
TPoint(Size().iWidth/2 - (iEikonEnv->TitleFont()->TextWidthInPixels(KRoidsLogoText)/2),
Size().iHeight/2-20) );
aGc.SetPenColor(KRgbGreen);
aGc.DrawText(KRoidsAuthorLogo,
TPoint(Size().iWidth/2 - (iEikonEnv->TitleFont()->TextWidthInPixels(KRoidsAuthorLogo)/2),
Size().iHeight/2+30) );
aGc.DiscardFont();
}
void CRoidsContainer::DrawLevelIndicator(CGraphicsContext& aGc) const
{
aGc.UseFont(iEikonEnv->TitleFont());
TInt green = (iNextLevelTicker%8)*32 -1;
aGc.SetPenColor(TRgb(0x0,green,0x0));
TBuf<20> text(KLevelText);
text.AppendNum(iLevel);
aGc.DrawText(text,TPoint(Size().iWidth/2 - (iEikonEnv->TitleFont()->TextWidthInPixels(text)/2), Size().iHeight/2) );
aGc.DiscardFont();
}
void CRoidsContainer::DrawAsteroids(CBitmapContext& aGc) const
{
TRgb color;
TAsteroidIterator iterator(iAsteroidPool->Iterator());
TAsteroid* a(iterator.First());
while(a)
{
DrawShape(aGc, a->DrawableShape(), a->Color());
a = iterator.Next();
};
}
void CRoidsContainer::DrawProjectiles(CBitmapContext& aGc) const
{
TProjectileIterator iterator= iProjectilePool->Iterator();
TProjectile* proj(iterator.First());
while(proj)
{
if(proj->IsActive())
{
aGc.Reset();
aGc.SetPenColor(KRgbYellow);
aGc.SetBrushStyle(CGraphicsContext::ESolidBrush);
TPoint pointCenter = proj->WorldPointAsPoint();
TRect rect(pointCenter-TPoint(1,1), pointCenter+TPoint(1,1));
aGc.DrawRect(rect);
}
proj=iterator.Next();
}
}
void CRoidsContainer::DrawShip(CBitmapContext& aGc) const
{
if(iGameState == EPlaying)
{
if( (iShip.State()==TShip::EAlive) ||
(iShip.State()==TShip::EInvinsible))
{
TRgb color(KRgbWhite);
if(iShip.State()==TShip::EInvinsible)
{
TInt gray = (iInvinsibleTicker%8)*32 -1;
color = TRgb(gray,gray,gray);
}
DrawShape(aGc, iShip.DrawableShape(), color);
}
}
}
void CRoidsContainer::DrawFragments(CBitmapContext& aGc) const
{
// Draw fragments behind the action.
for(TInt i=0; i<KMaxExplosionFragments; i++)
{
if(iExplosionFragments[i].IsActive())
DrawExplosionParticle(aGc, iExplosionFragments[i]);
}
}
void CRoidsContainer::DrawGame(CBitmapContext& aGc) const
{
// Clear offscreen bitmap to Nebula pattern
// or if that failed to load (due to OMM) then draw some background stars.
if(iNebula)
{
aGc.BitBlt(TPoint(0,0),iNebula, iNebula->SizeInPixels());
}
else
{
aGc.SetBrushColor(KRgbBlack);
aGc.Clear();
DrawBackgroundStars(*iBackupBitmap);
}
// Z order for drawing starting from backmost objects
if(iDrawStarbust)
DrawStarBust();
DrawFragments(aGc);
DrawProjectiles(aGc);
DrawAsteroids(aGc);
DrawLivesAndScoreIndicator(aGc);
if(iGameState == EGameOver)
DrawGameOver(aGc);
else
if(iGameState == EIntro)
DrawIntro(aGc);
if(iNextLevelTicker!=-1)
DrawLevelIndicator(aGc);
DrawShip(aGc);
DrawCapsule(aGc);
}
void CRoidsContainer::DrawCapsule(CBitmapContext& aGc) const
{
TCapsuleIterator iterator(iCapsulePool->Iterator());
TCapsule* cap(iterator.First());
while(cap)
{
if(cap->IsActive())
{
DrawShape(aGc, cap->DrawableShape(), KRgbBlue);
}
cap = iterator.Next();
}
}
/*
* ClipObject - Apply mobius strip
*/
void CRoidsContainer::ClipObject(TWorldObject &aObject)
{
// Translate to screen point;
TWorldPoint wp = aObject.WorldPoint();
if(wp.X()<= -1 )
wp.SetX(Size().iWidth);
else
if(wp.X()> Size().iWidth)
wp.SetX(1);
if(wp.Y()> Size().iHeight)
wp.SetY(1);
else
if(wp.Y()<= -1)
wp.SetY(Size().iHeight);
aObject.SetWorldPoint(wp);
}
/* CalculateProjectileCollisions
* Returns true if any of the active projectiles have collided with a given asteroid
*/
TBool CRoidsContainer::CalculateProjectileCollisions(TAsteroid& aRoid, const TRect& aBoundingRect)
{
TProjectileIterator iterator= iProjectilePool->Iterator();
TProjectile* proj(iterator.First());
while(proj)
{
if(proj->IsActive())
{
TPoint point(proj->WorldPointAsPoint());
TPoint lastPoint(proj->LastPointAsPoint());
// Do rough calculation first
if( aBoundingRect.Contains(point) || aBoundingRect.Contains(lastPoint) )
{
// If asteroid is small, treat it as a square otherwise point in polygon
if( (aRoid.MaxRadius()<5) ||
(aRoid.Intersects(point, lastPoint)))
{
proj->SetActive(EFalse);
iProjectilePool->FreeObject(proj);
return ETrue;
}
}
}
proj=iterator.Next();
}
return EFalse;
}
void CRoidsContainer::HandleShipHitCapsule(TCapsule& aCapsule)
{
iCapsulePool->FreeObject(&aCapsule);
iScore+=500;
}
void CRoidsContainer::CalculateCapsuleCollisions(const TRect& aBoundingRect)
{
TCapsuleIterator iterator(iCapsulePool->Iterator());
TCapsule* cap(iterator.First());
while(cap)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -