Exemplo n.º 1
0
void WorldRenderer::UpdateWaterBoxes( WaterQuad* quad )
{
	// Create Boxes
	if ( zShowWaterBoxes )
	{
		auto i = zWaterBoxes.find(quad);

		if ( i != zWaterBoxes.end() )
		{
			// Calculate Positions
			for( unsigned int x=0; x<4; ++x )
			{
				Vector3 position;
				position = quad->GetPosition(x);

				// Terrain Height Minimum
				try
				{
					float terrainHeight = zWorld->CalcHeightAtWorldPos(position.GetXZ());
					if ( position.y < terrainHeight ) position.y = terrainHeight;
				}
				catch(...)
				{
				}

				i->second.zCubes[x]->SetPosition(position);
			}
		}
		else
		{
			// Calculate Positions
			Vector3 positions[4];
			for( unsigned int x=0; x<4; ++x )
			{
				positions[x] = quad->GetPosition(x);

				// Terrain Height Minimum
				try
				{
					float terrainHeight = zWorld->CalcHeightAtWorldPos(positions[x].GetXZ());
					if ( positions[x].y < terrainHeight ) positions[x].y = terrainHeight;
				}
				catch(...)
				{
				}
			}
			
			zWaterBoxes[quad].zCubes[0] = zGraphics->CreateMesh("Media/Models/Cube_1.obj", positions[0]);
			zWaterBoxes[quad].zCubes[1] = zGraphics->CreateMesh("Media/Models/Cube_2.obj", positions[1]);
			zWaterBoxes[quad].zCubes[2] = zGraphics->CreateMesh("Media/Models/Cube_3.obj", positions[2]);
			zWaterBoxes[quad].zCubes[3] = zGraphics->CreateMesh("Media/Models/Cube_4.obj", positions[3]);

			for( unsigned int x=0; x<4; ++x )
			{
				zWaterBoxes[quad].zCubes[x]->SetScale(1.0f/20.0f);
			}
		}
	}
}
Actor* ProjectileArrowBehavior::RayVsMeshCollision( const Actor* actor, const Vector3& rayOrigin, float& range, const std::set<Actor*>& actors )
{
	if( !actor || !actor->CanCollide() )
		return NULL;

	float rangeWithin = 1.0f + range;

	PhysicsCollisionData data;

	ProjectileActor* projActor = dynamic_cast<ProjectileActor*>(this->zActor); 
	
	if( !projActor )
		return Behavior::RayVsMeshCollision(actor, rayOrigin, range, actors);

	Actor* collide = NULL;
	Actor* owner = NULL;
	Vector3 pos = actor->GetPosition();
	Vector3 dir = actor->GetDir();

	owner = projActor->GetOwner();

	if(!owner)
		return NULL;
	
	auto it_end = actors.end();
	for (auto it = actors.begin(); it != it_end; it++)
	{
		if( *it == this->zActor )
			continue;
		if( *it == owner )
			continue;
		if( !(*it)->CanCollide() )
			continue;
		
		float distance = ( pos.GetXZ() - (*it)->GetPosition().GetXZ() ).GetLength();

		if( distance > rangeWithin )
			continue;

		PhysicsObject* targetObject = (*it)->GetPhysicsObject();
		data = GetPhysics()->GetCollisionRayMesh(rayOrigin, dir, targetObject);

		if(data.collision && data.distance < range)
		{
			range = data.distance;
			collide = (*it);
		}

	}

	return collide;
}
bool ProjectileArrowBehavior::Update( float dt )
{
	if(!zMoving)
		return true;

	Vector3 newPos;
	Vector3 newDir;
	
	// Update linear position.
	newPos =  this->zActor->GetPosition();
	zVelocity.Normalize();
	zVelocity *= zSpeed;
	newPos += (zVelocity * dt);
	newDir = zVelocity;
	newDir.Normalize();

	//Rotate Mesh
	Vector3 ProjectileStartDirection = Vector3(0,0,-1);
	Vector3 ProjectileMoveDirection = newDir;

	ProjectileStartDirection.Normalize();

	Vector3 around = ProjectileStartDirection.GetCrossProduct(ProjectileMoveDirection);
	float angle = acos(ProjectileStartDirection.GetDotProduct(ProjectileMoveDirection));

	//Set Values
	this->zActor->SetPosition(newPos, false);
	this->zActor->SetRotation(Vector4(0.0f, 0.0f, 0.0f, 1.0f));
	this->zActor->SetRotation(around, angle);
	this->zActor->SetDir(newDir);

	/**Check If the arrow is outside the world.**/
	if( !this->zWorld->IsInside(newPos.GetXZ()) )
	{
		Stop();
		this->zActor->SetPosition(newPos);

		return true;
	}
	//**Check if the projectile has hit the ground**
	float yValue = std::numeric_limits<float>::lowest();
	try
	{
		yValue = this->zWorld->CalcHeightAtWorldPos(newPos.GetXZ());
	}
	catch(...)
	{
		Stop();
		this->zActor->SetPosition(newPos);

		return true;
	}

	// If true, stop the projectile and return.
	float middle = zLength * 0.5f;
	float yTip = newPos.y - middle;
	if(yTip <= yValue )
	{
 		middle += yValue;
 		newPos.y = middle;

		this->Stop();
		this->zActor->SetPosition(newPos);
		
		return true;
	}

	//**Update Velocity for next update**

	// Update linear velocity from the acceleration.
	this->zVelocity += (GRAVITY * dt);

	// Impose drag.
	this->zVelocity *= pow(zDamping, dt);
	
	//Update-Notify Position
	this->zActor->SetPosition(newPos);

	/***Check collisions***/

	//Check if the arrow has hit a dynamic actor
	Actor* collide = RayVsMeshDynamicActorCollision(zLength, newPos);

	if(collide)
	{
		this->Stop();
		ProjectileArrowCollide PAC;
		PAC.zActor = collide;
		NotifyObservers(&PAC);

		if( BioActor* bioActor = dynamic_cast<BioActor*>(collide) )
		{
			if( bioActor->IsAlive() )
			{
				ProjectileActor* projActor = dynamic_cast<ProjectileActor*>(this->zActor);
				bioActor->TakeDamage( projActor->GetDamage(), projActor->GetOwner() );
			}
		}

		this->zHitTarget = collide;
		return true;
	}

	//Check if the arrow has hit a static actor
	collide = RayVsMeshStaticActorCollision(zLength, newPos);

	if(collide)
	{
		this->Stop();
		ProjectileArrowCollide PAC;
		PAC.zActor = collide;
		NotifyObservers(&PAC);

		this->zHitTarget = collide;
		return true;
	}

	return false;
}
Exemplo n.º 4
0
bool WorldRenderer::Update()
{
	// Update Terrain Routine
	UpdateTerrain();

	// Cam Pos
	Vector3 camPos = zGraphics->GetCamera()->GetPosition();

	// Don't update grass if we don't have a world
	if ( zWorld )
	{
		// Check if we should render grass
		zGraphics->SetGrassFilePath("Media/Grass.png");
		if ( zGraphics->GetRenderGrassFlag() )
		{
			if ( (zLastGrassUpdatePos - camPos.GetXZ()).GetLength() >= zGrassUpdateDistance )
			{
				std::map<Vector2UINT, int> grassSectors;

				// Remove Current Grass Sectors
				for( auto i = zGrass.cbegin(); i != zGrass.cend(); ++i )
				{
					grassSectors[i->first]--;
				}

				// Insert New Sectors
				std::set<Vector2UINT> newSectorsSet;
				zWorld->GetSectorsInCicle(camPos.GetXZ(), zGrassFarDistance, newSectorsSet);
				for( auto i = newSectorsSet.cbegin(); i != newSectorsSet.cend(); ++i )
				{
					grassSectors[*i]++;
				}

				// Update Sector Grasses
				for( auto i = grassSectors.cbegin(); i != grassSectors.cend(); ++i )
				{
					if ( i->second < 0 )
					{
						auto grassIt = zGrass.find(i->first);
						if ( grassIt != zGrass.cend() )
						{
							if ( grassIt->second )
							{
								zGraphics->DeleteBillboardCollection(grassIt->second);
							}

							zGrass.erase(grassIt);
						}
					}
					else if ( i->second > 0 )
					{
						GenerateGrass(i->first);
					}
				}

				zLastGrassUpdatePos = camPos.GetXZ();
			}
		}
	}

	// Check Distance
	if ( (zLastEntUpdatePos - camPos).GetLength() > 10.0f )
	{
		// Update Existing LOD
		for( auto i = zEntities.cbegin(); i != zEntities.cend(); ++i )
		{
			zEntsToUpdate.insert(i->first);
		}

		// Scan New Entities
		if ( zWorld ) 
		{
			zWorld->GetEntitiesInCircle(camPos.GetXZ(), zGraphics->GetEngineParameters().FarClip, zEntsToUpdate);
		}

		// Update Position
		zLastEntUpdatePos = camPos;
	}
	
	// Update a between 10% and a minimum of 25
	unsigned int x = zEntsToUpdate.size() / 10;
	if ( x < 25 ) x = 25;
	if ( x > 100 ) x = 100;
	auto i = zEntsToUpdate.begin();
	while( i != zEntsToUpdate.end() )
	{
		SetEntityGraphics(*i);
		i = zEntsToUpdate.erase(i);
		if ( !x || !--x ) break;
	}

	// Check if there is more to be updated
	return ( zEntsToUpdate.size() > 0 || zUpdatesRequired.size() > 0 );
}