bool World::isInsideCollidableTile(int centerX, int centerY)
{
	vector<WorldLayer*>::iterator it = layers->begin();
	while (it != layers->end())
	{
		WorldLayer *layer = (*it);
		if (layer->hasCollidableTiles())
		{
			if (layer->isInsideCollidableTile(centerX, centerY))
				return true;
		}
		it++;
	}
	return false;}
void Physics::getAllTileCollisionsForAGivenSprite(	World *world,  
													CollidableObject *sprite,
													float percentageOfFrameRemaining)
{
	vector<WorldLayer*> *layers = world->getLayers();
	AABB *boundingVolume = sprite->getBoundingVolume();
	PhysicalProperties *pp = sprite->getPhysicalProperties();

	for (int i = 0; i < world->getNumLayers(); i++)
	{
		WorldLayer *layer = layers->at(i);
		if (layer->hasCollidableTiles())
			layer->findTileCollisionsForSprite(this, sprite);
	}
}
int World::getCollidableGridRows()
{
	int maxRows = 0;
	vector<WorldLayer*>::iterator it = layers->begin();
	while (it != layers->end())
	{
		WorldLayer *layer = (*it);
		if (layer->hasCollidableTiles())
		{
			int numRows = layer->getRows();
			if (numRows > maxRows)
				maxRows = numRows;
		}
		it++;
	}
	return maxRows;
}
/*
	Done each frame before collision testing, it updates the "on tile" states
	and then applies acceleration and gravity to the sprite's velocity. Then it
	initializes the swept shape for the sprite.
*/
void Physics::prepSpriteForCollisionTesting(World *world, CollidableObject *sprite)
{
	// THIS GUY HAS ALL THE PHYSICS STUFF FOR THE SPRITE
	PhysicalProperties *pp = sprite->getPhysicalProperties();

	// APPLY ACCELERATION
	pp->applyAcceleration();

	// APPLY GRAVITY
	pp->incVelocity(0.0f, gravity);

	// NOW, IF THE SPRITE WAS ON A TILE LAST FRAME LOOK AHEAD
	// TO SEE IF IT IS ON A TILE NOW. IF IT IS, UNDO GRAVITY.
	// THIS HELPS US AVOID SOME PROBLEMS
	if (sprite->wasOnTileLastFrame())
	{
		// FIRST MAKE SURE IT'S SWEPT SHAPE ACCOUNTS FOR GRAVITY
		sprite->updateSweptShape(1.0f);

		// WE'LL LOOK THROUGH THE COLLIDABLE LAYERS
		vector<WorldLayer*> *layers = world->getLayers();
		for (int i = 0; i < world->getNumLayers(); i++)
		{
			WorldLayer *layer = layers->at(i);
			if (layer->hasCollidableTiles())
			{
				bool test = layer->willSpriteCollideOnTile(this, sprite);
				if (test)
				{
					sprite->setOnTileThisFrame(true);
					pp->setVelocity(pp->getVelocityX(), 0.0f);
					sprite->updateSweptShape(1.0f);
					return;
				}
				else
					cout << "What Happened?";
			}
		}
	}

	// INIT THE SWEPT SHAPE USING THE NEWLY APPLIED
	// VELOCITY. NOTE THAT 100% OF THE FRAME TIME
	// IS LEFT, DENOTED BY 1.0f
	sprite->updateSweptShape(1.0f);
}
bool World::overlapsCollidableTiles(int centerX, int centerY, int nodeWidth, int nodeHeight)
{
	vector<WorldLayer*>::iterator it = layers->begin();
	while (it != layers->end())
	{
		WorldLayer *layer = (*it);
		if (layer->hasCollidableTiles())
		{
			AABB aabb;
			aabb.setCenterX((float)centerX);
			aabb.setCenterY((float)centerY);
			aabb.setWidth((float)nodeWidth);
			aabb.setHeight((float)nodeHeight);
			bool overlaps = layer->overlapsCollidableTile(aabb);
			if (overlaps)
				return true;
		}
		it++;
	}
	return false;
}
Exemple #6
0
void Physics::update(Game *game)
{
	// REMEMBER, AT THIS POINT, ALL PLAYER INPUT AND AI
	// HAVE ALREADY BEEN PROCESSED AND BOT AND PLAYER
	// STATES, VELOCITIES, AND ACCELERATIONS HAVE ALREADY
	// BEEN UPDATED. NOW WE HAVE TO PROCESS THE PHYSICS
	// OF ALL THESE OBJECTS INTERACTING WITH EACH OTHER
	// AND THE STATIC GAME WORLD. THIS MEANS WE NEED TO
	// DETECT AND RESOLVE COLLISIONS IN THE ORDER THAT
	// THEY WILL HAPPEN, AND WITH EACH COLLISION, EXECUTE
	// ANY GAMEPLAY RESPONSE CODE, UPDATE VELOCITIES, AND
	// IN THE END, UPDATE POSITIONS

	// FIRST, YOU SHOULD START BY ADDING ACCELERATION TO ALL 
	// VELOCITIES, WHICH INCLUDES GRAVITY, NOTE THE EXAMPLE
	// BELOW DOES NOT DO THAT


	// FOR NOW, WE'LL JUST ADD THE VELOCITIES TO THE
	// POSITIONS, WHICH MEANS WE'RE NOT APPLYING GRAVITY OR
	// ACCELERATION AND WE ARE NOT DOING ANY COLLISION 
	// DETECTION OR RESPONSE
	float timer = 0;

	GameStateManager *gsm = game->getGSM();
	SpriteManager *sm = gsm->getSpriteManager();
	World *w = gsm->getWorld();
	GameRules* gR = game->getGameRules();
	vector<WorldLayer*> *layers = w->getLayers();

	AnimatedSprite *player;
	PhysicalProperties *pp;
	TiledLayer *tL;
	list<Collision*> collisions;
	
	//finding TileLayer
	for(unsigned int i = 0; i < layers->size(); i++)
	{
		WorldLayer *currentLayer = (*layers)[i];
		if(currentLayer->hasCollidableTiles() == true)
		{
			tL = dynamic_cast<TiledLayer*>(currentLayer);
			if(tL != 0)
			{
				i = layers->size();
			}//end if
		}//end if
	}


	player = sm->getPlayer();
	pp = player->getPhysicalProperties();

	//UPDATING ALL VELOCITIES AND DOING TILE COLLISION
	pp->incVelocity(this,pp->getAccelerationX(), pp->getAccelerationY() + gravity); 
	collideTestWithTiles(player, tL, &collisions);

	list<Bot*>::iterator botIterator = sm->getBotsIterator();
	while (botIterator != sm->getEndOfBotsIterator())
	{			
		Bot *bot = (*botIterator);
		pp = bot->getPhysicalProperties();
		pp->incVelocity(this, pp->getAccelerationX(), pp->getAccelerationY());
		if(pp->isGravAffected() == true)
			pp->incVelocity(this, 0, gravity);
		collideTestWithTiles(bot, tL, &collisions);
		botIterator++;
	}

	//HERE, COLLIDE SPRITES WITH OTHER SPRITES
	collideTestWithSprites(game, player, &collisions);
	botIterator = sm->getBotsIterator();
	while (botIterator != sm->getEndOfBotsIterator())
	{			
		Bot *bot = (*botIterator);
		if(bot->isCurrentlyCollidable() == true);
			collideTestWithSprites(game, bot, &collisions);
		botIterator++;
	}

	//SORT COLLISIONS
	collisions.sort(compare_collisionTime);

	//RESOLVING ALL THE COLLISIONS
	while(collisions.empty() == false)
	{
		Collision* currentCollision = collisions.front();
		collisions.pop_front();
		float colTime = currentCollision->getTOC();
		CollidableObject* co1 = currentCollision->getCO1();
		CollidableObject* co2 = currentCollision->getCO2();

		if(colTime >= 0 && colTime <= 1)
		{
			
			pp = co1->getPhysicalProperties();
			//pp->setVelocity(pp->getVelocityX()*9.99f,pp->getVelocityY()*9.99f);
			pp = co2->getPhysicalProperties();
			//pp->setVelocity(pp->getVelocityX()*9.99f,pp->getVelocityY()*9.99f);

			pp = player->getPhysicalProperties();
			pp->setPosition(pp->getX() + (pp->getVelocityX()*(colTime-timer)),pp->getY() + (pp->getVelocityY()*(colTime-timer)));
			botIterator = sm->getBotsIterator();
			while (botIterator != sm->getEndOfBotsIterator())
			{			
				Bot *bot = (*botIterator);
				pp = bot->getPhysicalProperties();
				pp->setPosition(pp->getX() + (pp->getVelocityX()*(colTime-timer)), pp->getY() + (pp->getVelocityY()*(colTime-timer)));
				botIterator++;
			}

			gsm->updateViewport(game, colTime-timer);

			resolveCollision(game, currentCollision);
			gR->gameSpecificResolve(game, currentCollision);
			
			boolean deleteLast = false;
			list<Collision*>::iterator cIterator = collisions.begin();
			list<Collision*>::iterator lastIterator;
			while(cIterator != collisions.end())
			{
				if(deleteLast == true)
				{
					collisions.erase(lastIterator);
				}
				deleteLast = false;
				Collision* check = (*cIterator);
				if(check->contains(co1) || check->contains(co2))
				{
					CollidableObject* checkStatic = check->getCO2();
					if(checkStatic->isStaticObject())
					{
						coStackCounter ++;
						coStack[coStackCounter] = checkStatic;
					}

					collisionStackCounter ++;
					collisionStack[collisionStackCounter] = check;

					lastIterator = cIterator;
					deleteLast = true;
				}
				else
				{
					//check->calculateTimes();
				}

				cIterator++;
			}

			if(deleteLast == true)
			{
				collisions.erase(lastIterator);
			}

			collideTestWithTiles(co1, tL, &collisions);
			collideTestWithSprites(game, co1, &collisions);

			if(co2->isStaticObject() == false)
			{
				collideTestWithTiles(co2, tL, &collisions);
				collideTestWithSprites(game, co2, &collisions);
			}

			collisions.sort(compare_collisionTime);

			timer += (colTime-timer);
		}//end if


		if(co2->isStaticObject() == true)
		{
			coStackCounter ++;
			coStack[coStackCounter] = co2;
		}

		collisionStackCounter ++;
		collisionStack[collisionStackCounter] = currentCollision;
	
	}
	
	if(timer < 1)
	{
		gsm->updateViewport(game, 1-timer);
		pp = player->getPhysicalProperties();
		pp->setPosition(pp->getX() + (pp->getVelocityX()*(1-timer)),pp->getY() + (pp->getVelocityY()*(1-timer)));
		//pp->setVelocity(0.0f, pp->getVelocityY());
		botIterator = sm->getBotsIterator();
		while (botIterator != sm->getEndOfBotsIterator())
		{			
			Bot *bot = (*botIterator);
			pp = bot->getPhysicalProperties();
			pp->setPosition(pp->getX() + (pp->getVelocityX()*(1-timer)), pp->getY() + (pp->getVelocityY()*(1-timer)));
			botIterator++;
		}
		gsm->updateViewport(game, 1-timer);
	}
	
	pp = player->getPhysicalProperties();
	if(pp->getX() < 0)
	{
		pp->setX(0);
	}
	if(pp->getY() < 0)
	{
		pp->setY(0);
	}
	//pp->setVelocity(0.0f, pp->getVelocityY());
	/*pp->setPosition(pp->getX() + pp->getVelocityX(), pp->getY() + pp->getVelocityY());

	// FOR NOW THE PLAYER IS DIRECTLY CONTROLLED BY THE KEYBOARD,
	// SO WE'LL NEED TO TURN OFF ANY VELOCITY APPLIED BY INPUT
	// SO THE NEXT FRAME IT DOESN'T GET ADDED
	pp->setVelocity(0.0f, pp->getVelocityY());

	// AND NOW MOVE ALL THE BOTS
	list<Bot*>::iterator botIterator = sm->getBotsIterator();
	while (botIterator != sm->getEndOfBotsIterator())
	{			
		Bot *bot = (*botIterator);
		pp = bot->getPhysicalProperties();
		pp->setPosition(pp->getX() + pp->getVelocityX(), pp->getY() + pp->getVelocityY());
		botIterator++;
	}*/

	
}
/*
	This is where all game physics starts each frame. It is called each frame 
	by the game statem manager after player input and AI have been processed. It
	updates the physical state of all dynamic objects in the game and
	moves all objects to their end of frame positions, updates all necessary
	object velocities, and calls all collision event handlers.
*/
void Physics::update(Game *game)
{

	GameStateManager *gsm = game->getGSM();
	SpriteManager *spm = gsm->getSpriteManager();
	AnimatedSprite *player = spm->getPlayer();

	if (once == 0) {

	
	/*	b2PolygonShape groundBox;
		groundBox.SetAsBox(50.0f, 10.0f);

		groundBody->CreateFixture(&groundBox, 0.0f);
*/
		b2BodyDef bodyDef;
		bodyDef.type = b2_dynamicBody;
		bodyDef.position.Set(600, 9280);
		body = world->CreateBody(&bodyDef);

		b2PolygonShape dynamicBox;
		dynamicBox.SetAsBox(32.0f, 32.0f);

		b2FixtureDef fixtureDef;
		fixtureDef.shape = &dynamicBox;


		// Set the box density to be non-zero, so it will be dynamic.
		fixtureDef.density = 1.0f;

		// Override the default friction.
		fixtureDef.friction = 0.3f;

		// Add the shape to the body.
		body->CreateFixture(&fixtureDef);
		//body->SetLinearVelocity(b2Vec2(0,-1000));

		//body->SetUserData(player);
		player->setBody(body);
		// This is our little game loop.

		


		once += 1;
	}

	body->ApplyForce( world->GetGravity(), body->GetWorldCenter(), true );

			float32 timeStep = 1.0f / 60.0f;
			int32 velocityIterations = 6;
			int32 positionIterations = 2;

			world->Step(timeStep, velocityIterations, positionIterations);

			// Now print the position and angle of the body.
			b2Vec2 position = body->GetPosition();
			//b2Vec2 position2 = body2->GetPosition();

			float32 angle = body->GetAngle();

			printf("%4.2f %4.2f %4.2f\n", position.x, position.y, angle);
		
			if (f == 0) {
				World *woorld = gsm->getWorld();
				vector<WorldLayer*> *layers = woorld->getLayers();
				CollidableObject *sprite = NULL;
				for (int i = 0; i < woorld->getNumLayers(); i++)
				{
					WorldLayer *layer = layers->at(i);
					if (layer->hasCollidableTiles())
					{
						layer->findTileCollisionsForSprite(this,sprite);
					}
				}
				f++;
			}
			
			if (player->getinvincible() == true) {
				if (invincibletimer == 0) {
					invincibletimer = 100;
				}
				invincibletimer -= 1;
				if (invincibletimer == 0) {
					player->setinvincible(false);
				}
			}
			
				 
			if (z!=0)z--;
			if (z==0)
			if (player->getinvincible() == false)
			for (b2ContactEdge* edge = body->GetContactList(); edge; edge = edge->next)
				if (edge->contact->IsTouching()) {
					z=50;

					if(game->getPlayerLife() > 0)
						{game->decreasePlayerLife();
					PlaySound(L"data/sounds/explosion.wav", NULL, SND_FILENAME|SND_SYNC);}
					else 
					{
					if(game->getLives() > 1) {
						game->decreaseLives();
					}						
					else if(game->getLives() == 1 && game->getPlayerLife() == 0)
					{
						GameStateManager *gsm = game->getGSM();
						once = 0;
						//body->SetTransform(b2Vec2((600-position.x),(9280-position.y)),body->GetAngle());
						Viewport *viewport = game->getGUI()->getViewport();
						viewport->setViewportX(0);
						viewport->setViewportY(8880);

						gsm->gameOver();
						PlaySound(L"data/sounds/end.wav", NULL, SND_FILENAME|SND_SYNC);
					}
	
					game->setPlayerLife();
				}

			}

			/*if (f > 0)
			{
				if(game->getPlayerLife() > 0)
				game->decreasePlayerLife();
		
				else 
				{
					if(game->getLives() > 1)
						game->decreaseLives();
					else if(game->getLives() == 1 && game->getPlayerLife() == 0)
					{
						GameStateManager *gsm = game->getGSM();
						gsm->setCurrentGameState(GS_GAME_OVER);
					}
	
					game->setPlayerLife();
				}	
			}*/
			//OutputDebug(L"My output string.");


	//		activatedForSingleUpdate = false;

	//// WE'LL NEED THE WORLD TO ACCESS THE SPRITES AND WORLD LAYERS
	//World *woorld = gsm->getWorld();

	//currentCollisionTime = 0.0f;


	//// FOR ALL SPRITES, INCLUDING THE BOTS AND PLAYER
	//vector<CollidableObject*>::iterator spritesIt = sortedSweptShapes[LEFT_EDGE]->begin();
	//while (spritesIt != sortedSweptShapes[LEFT_EDGE]->end())
	//{
	//	CollidableObject *sprite = (*spritesIt);
	//	prepSpriteForCollisionTesting(woorld, sprite);
	//	getAllTileCollisionsForAGivenSprite(woorld, sprite, 1.0f);
	//	spritesIt++;
	//}

	//// PREPARE FOR SPRITE-SPRITE COLLISION TESTING

	//	// SWEEP AND PRUNE DATA STRUCTURES PREP WORK
	//		// SORT S_AND_P VECTOR SORTED BY START X OF SWEPT SHAPE
	//		// SORT S_AND_P VECTOR SORTED BY END X OF SWEPT SHAPE
	//		// WE DON'T NEED THE Y-AXIS SORTED, BUT WOULD IF THIS
	//		// WERE A 3D SYSTEM TO SAVE ON COMPARISONS.

	//// WE'RE USING C++'s STL sort METHOD AND ARE PROVIDING
	//// A CUSTOM MEANS FOR COMPARISON
	//sort(sortedSweptShapes[LEFT_EDGE]->begin(),		sortedSweptShapes[LEFT_EDGE]->end(),	SweptShapesComparitorByLeft());
	//sort(sortedSweptShapes[RIGHT_EDGE]->begin(),	sortedSweptShapes[RIGHT_EDGE]->end(),	SweptShapesComparitorByRight());
	//	
	//// RECORD SORTED POSITIONS WITH EACH SPRITE. THEY NEED TO KNOW WHERE
	//// THEY ARE IN THOSE DATA STRUCTURES SUCH THAT WE CAN JUMP INTO
	//// THOSE DATA STRUCTURES TO TEST COLLISIONS WITH NEIGHBORS
	//updateSweptShapeIndices();

	//// YOU'LL NEED TO TEST FOR SPRITE-TO-SPRITE COLLISIONS HERE

	//// *** LOOP STARTS HERE. WE'LL DO THIS UNTIL THERE ARE NO
	//// MORE COLLISIONS TO RESOLVE FOR THIS FRAME
	//while (activeCollisions.size() > 0)
	//{
	//	// SORT COLLISION OBJECTS BY TIME OF COLLISION
	//	// NOTE THAT I'M JUST EMPLOYING THE STL'S List
	//	// CLASS' SORT METHOD BY PROVIDING MY OWN
	//	// MEANS FOR COMPARING Collision OBJECTS
	//	activeCollisions.sort(CollisionComparitor());

	//	// GET FIRST COLLISION - NOTE THAT WE HAVE THE COLLISIONS SORTED
	//	// IN DESCENDING ORDER, SO TO TAKE THE EARLIEST ONE, WE REMOVE IT
	//	// FOM THE BACK OF THE SORTED LIST
	//	Collision *earliestCollision = activeCollisions.back();
	//	activeCollisions.pop_back();
	//	float collisionTime = earliestCollision->getTimeOfCollision();

	//	// MOVE ALL SPRITES UP TO TIME OF FIRST COLLISION USING
	//	// APPROPRIATELY SCALED VELOCITIES
	//	moveAllSpritesUpToBufferedTimeOfCollision(earliestCollision);

	//	// AND ADVANCE COLLISION TIME
	//	currentCollisionTime = collisionTime;

	//	// AND UPDATE THE VELOCITIES OF THE SPRITE(S) INVOLVED IN THE COLLISION
	//	performCollisionResponse(earliestCollision);

	//	// EXECUTE COLLISION EVENT CODE
	//	// TEST TO SEE TYPES OF OBJECTS AND APPROPRIATE RESPONSE
	//	// ACCORDING TO CUSTOMIZED COLLISION EVENT HANDLER
	//	collisionListener->respondToCollision(game, earliestCollision);

	//	CollidableObject *co1 = earliestCollision->getCO1();
	//	CollidableObject *co2 = earliestCollision->getCO2();
	//	removeActiveCOCollisions(co1);
 //		co1->updateSweptShape(1.0f - currentCollisionTime);
	//	getAllTileCollisionsForAGivenSprite(woorld, co1, 1.0f - currentCollisionTime);

	//	// ONLY DO IT FOR THE SECOND ONE IF IT'S NOT A TILE
	//	if (!earliestCollision->isCollisionWithTile())
	//	{
	//		removeActiveCOCollisions(co2);
	//		co2->updateSweptShape(1.0f - currentCollisionTime);
	//		getAllTileCollisionsForAGivenSprite(woorld, co2, 1.0f - currentCollisionTime);
	//	}
	//	else
	//	{
	//		spriteToTileCollisionsThisFrame[co1].insert(earliestCollision->getTile());
	//		recycledCollidableObjectsList.push_back(co2);
	//	}
	//	
	//	// IF IT WAS ONLY ONE SPRITE WITH A TILE THIS IS EASY TO DO
	//	if (earliestCollision->isCollisionWithTile())
	//	{
	//		reorderCollidableObject(co1);
	//	}
	//	// YOU'LL HAVE TO WORRY ABOUT REORDERING STUFF FOR COLLISIONS
	//	// BETWEEN TWO SPRITES
	//	
	//	// NOW TEST NEIGHBORS OF SPRITES INVOLVED IN RESOLVED COLLISION
	//	// AGAINST NEIGHBORS IN SWEPT SHAPE DATA STRUCTURES. YOU'LL HAVE
	//	// TO FIGURE OUT HOW TO DO THIS AND HOW TO RESOLVE SUCH COLLISIONS
	//		
	//	// RECYCLE THE COLLISION SINCE WE'RE NOW DONE WITH IT
	//	recycledCollisions.push_back(earliestCollision);
	//}

	//// APPLY THE REMAINING TIME TO MOVE THE SPRITES. NOTE THAT
	//// THIS IS ACTUALLY A VERY RISKY, TRICKY STEP BECAUSE IT COULD
	//// MOVE OBJECTS ALMOST TO THE POINT OF COLLISION, WHICH MAY THEN
	//// BE DETECTED ALMOST AT TIME 0 NEXT FRAME. THERE ARE OTHER TRICKY
	//// ISSUES RELATED TO OUR BUFFER AS WELL, SO WE CHEAT A LITTLE HERE
	//// AND SCALE THE TIME REMAINING DOWN A LITTE
	//if (currentCollisionTime < 1.0f)
	//	moveAllSpritesToEndOfFrame();

	//// INIT TILE COLLISION INFO
	//// SET ON TILE LAST FRAME USING ON TILE THIS FRAME
	//// SET ON TILE THIS FRAME TO FALSE
	//spritesIt = sortedSweptShapes[LEFT_EDGE]->begin();
	//while (spritesIt != sortedSweptShapes[LEFT_EDGE]->end())
	//{
	//	CollidableObject *sprite = (*spritesIt);
	//	sprite->advanceOnTileStatus();
	//	spritesIt++;
	//}

	//// WE'RE NOT GOING TO ALLOW MULTIPLE COLLISIONS TO HAPPEN IN A FRAME
	//// BETWEEN THE SAME TWO OBJECTS
	//spriteToTileCollisionsThisFrame.clear();
	//


}