⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 roidscontainer.cpp

📁 rps game symbian os application development
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		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 + -