Exemplo n.º 1
0
void PhysicsEngine::CollisionMapResponse(PowerBall* b, Map* map, Vector3 normalPlane, float dt)
{
	
	/* simple response
	Vector3 normal = Vector3(0,1,0);
	Vector3 vn = normal*(this->mVelocity.GetDotProduct(normal));
	Vector3 vp = this->mVelocity - vn;
	Vector3 vAfter = vp - vn;
	this->mVelocity = vAfter;
	*/
	// normal of the "collision plane"
	
	//Vector3 nColl = Vector3(0,-1,0); //this->GetPositionVector3() - p->GetPositionVector3();
	Vector3 nColl = normalPlane;
	// for easy projecting of vector, no div by |n|^2 in proj formula
	nColl.normalize();

	// savning the important stuff for easy acc
	float m1 = b->GetMass();
	float m2 = map->GetMass();
	float mSum = m1+m2;
	Vector3 v1 = b->GetVelocity();
	Vector3 v2 = Vector3(0,0,0);//the platform is not moving b1->mVelocity;

	// projecting the vector v1 on nColl
	float x1 = nColl.GetDotProduct(v1);		// factor in nColl dir
	Vector3 v1x = nColl*x1;					// projetion done
	Vector3 v1y = v1 - v1x;					// perpendicular vector 

	// projecting the vector v2 on nColl
	nColl = nColl*(-1);						// switching direction of "plane normal"
	float x2 = nColl.GetDotProduct(v2);		// factor in nColl dir
	Vector3 v2x = nColl*x2;					// projetion done
	Vector3 v2y = v2 - v2x;					// perpendicular vector 
	
	
	if((v1x.GetLength() >1.5f) && b->SoundEnabled())
		this->mCollisionWithWall->Play();
	
	//float e = this->mRestitution;
	float e = map->GetRestitution();
	float newdt = dt*0.001f;
	//v1y -= v1y*pow(this->mFriction, 2)*newdt;
	if( b->GetPreviousVelocity().GetLength() < b->GetVelocity().GetLength() )
	{
		if( (v1y.GetLength() < 2.0f) && (v1y.GetLength() > 0.0f) )
			v1y -= v1y*b->GetFriction()*newdt;
		if( v1y.GetLength() < 0.1f && (v1y.GetLength() > 0.0f) )
			v1y *= b->GetFriction()*newdt;
	}	
	
	

	b->SetVelocity(Vector3( v1x*(m1-e*m2)/(mSum) + v2x*((1+e)*m2)/(mSum) + v1y));
	//this->mAcceleration = Vector3(0,0,0);
	//this->mSumAddedForce += this->mAcceleration*(-1);
	// use this line if the platform also has a speed.
	//b1->mVelocity = Vector3( v1x*(2*m1)/(mSum) + v2x*(m2-m1)/(mSum) + v2y );
	return;
}
Exemplo n.º 2
0
bool PhysicsEngine::RayTriIntersect(Vector3 origin, Vector3 direction, Vector3 p0, Vector3 p1, Vector3 p2, float &u, float &v, float &t)
{
	Vector3 e1, e2, q, s, r;
	u = v = t = 0;
	float a,f, eps = 0.00001f;
	e1 = p1 - p0;
	e2 = p2 - p0;
	//q  = direction.GetCrossProduct(e2);
	q  = e2.GetCrossProduct(direction);
	a = e1.GetDotProduct(q);
	if( a > - eps && a < eps)
		return false;
	f = 1/a;
	s = origin - p0;
	u = f*(s.GetDotProduct(q));
	if( u < 0.0f)
		return false;
	//r = s.GetCrossProduct(e1);
	r = e1.GetCrossProduct(s);
	v = f*(direction.GetDotProduct(r));
	if( v < 0.0f || u+v > 1.0f)
		return false;
	t = f*(e2.GetDotProduct(q));
	return true;
}
Exemplo n.º 3
0
void CCollisionBody::FindSATMinMax( const std::vector< Vector3< float > > & colOffset, Vector3< float > & pos, Vector3< float > & axis, float * min, float * max ) {
    
    
    unsigned long int offsetCount = colOffset.size();
    float * d = new float[offsetCount];
    
    for( int j = 0; j < offsetCount; j++ ) {
        
        Vector3< float > np = colOffset[j] + pos;
        d[j] = np.GetDotProduct( axis );
        
    }
    
    *min = d[0];
    *max = d[0];
    
    for( int j = 1; j < offsetCount; j++ ) {
        
        if( d[j] < *min )
            *min = d[j];
        else if( d[j] > *max )
            *max = d[j];
        
    }
    
    delete [] d;
    

    
}
Exemplo n.º 4
0
void Helicopter::Update(float dt)
{
	// Gravity
	this->direction.y -= GRAVITY * dt;

	// Air friction
	float velocity = this->GetVelocity();
	float newVelocity = velocity - ((AIR_FRICTION_CONSTANT * (velocity * velocity)) / this->mass) * dt;
	float dv = newVelocity / velocity;
	this->direction *= dv;
	
	
	// Collision against terrain
	float terrY = this->terrain->GetYPositionAt(this->pos.x, this->pos.z);
	if(this->pos.y + this->direction.y * dt <= terrY)
	{
		// Bounce
		this->direction.y = 0 - this->direction.y * this->elacticity;

		// Take damage
		float damage = (abs(this->direction.y * 5) + abs(this->direction.x) + abs(this->direction.z)); 
		if(damage > 5.0f)
			this->health -= damage;
	}


	// Regen health:
	this->health += dt;
	if(this->health > 100.0f)
		this->health = 100.0f;
	
	
	// Friction against terrain here if close to it, simplified calculating only in the XZ plane and not angled terrain.
	if(this->pos.y - 0.5f < terrY)
	{
		float frictionForce = GROUND_FRICTION_CONSTANT * this->mass * GRAVITY;
		float frictionAcc = (frictionForce / this->mass) * dt;
		if(frictionAcc > this->GetXZVelocity())
		{
			this->direction.x = 0;
			this->direction.z = 0;
		}
		else
		{
			velocity = this->GetVelocity();
			newVelocity = velocity - frictionAcc;
			dv = newVelocity / velocity;
			this->direction *= dv;
		}

		// Reset rolling when touching ground.
		Vector3 defup = Vector3(0, 1, 0);
		defup.Normalize();
		Vector3 cross = this->up.GetCrossProduct(this->forward);
		cross.Normalize();
		float dotCrossDefup = cross.GetDotProduct(defup);
		// Roll left
		if(dotCrossDefup < 0.0f)
		{
			this->RollLeft(true);
			this->RollRight(false);
		}
		// Roll right
		else if(dotCrossDefup > 0.0f)
		{
			this->RollLeft(false);
			this->RollRight(true);
		}

		float dotForUp = this->forward.GetDotProduct(defup);
		// Roll forward
		if(dotForUp > 0.0f)
		{
			this->RollForward(true);
			this->RollBackward(false);
		}
		// Roll backward
		else if(dotForUp < 0.0f)
		{
			this->RollForward(false);
			this->RollBackward(true);
		}
	}
	
	if(this->health > 95.0f)
		this->UpdateChopperSpec(dt);


	// For funness we need to reset the direction.y a little, it's too hard to handle up&downs otherwise
	//direction.y *= 1.0f - dt;

	// AutoHoverEffect
	this->AutoHover(dt);

	if(this->health > 95.0f)
	{
		this->pos += this->direction * dt;
		this->chopper->SetPosition(this->pos);
		this->rotor->SetPosition(this->pos);
		this->secrotor->SetPosition(this->pos - this->forward * 28 + this->up * 11);	// Adding offset for the second rotor.

		Vector3 lookAt = this->forward;
		lookAt.y = 0.0f;
		GetGraphics()->GetCamera()->SetPosition(this->pos + Vector3(0, this->camOffsetHeight, 0) - lookAt * this->camOffsetDistance);
		GetGraphics()->GetCamera()->LookAt(this->pos + lookAt * 30 + Vector3(0, 10, 0));


		// Attune forward to direction.
		Vector3 xzdir = this->direction;
		xzdir.y = 0.0f;
		float xzlen = xzdir.GetLength();
		xzdir.Normalize();
		Vector3 xzfor = this->forward;
		xzfor.y = 0.0f;
		xzfor.Normalize();
		float dotDirFor = xzdir.GetDotProduct(xzfor);
		Vector3 vecRight = xzfor.GetCrossProduct(Vector3(0, 1, 0));
		vecRight.y = 0.0f;
		vecRight.Normalize();
		float dotDirRight = xzdir.GetDotProduct(vecRight);

		// When flying backwards remove the "BAM SNAP" effect when dot product gets 0.0f at the sides.
		if(dotDirFor < 0.0f)
			dotDirFor = 0.0f;

		float angle = dt * xzlen * xzlen * xzlen * xzlen * (1 - abs(dotDirFor)) * 0.000001f;
		if(dotDirRight < 0.0f)
			angle *= -1.0f;
		this->forward.RotateAroundAxis(this->up, -angle);
		this->chopper->RotateAxis(this->up, -angle);
		this->rotor->RotateAxis(this->up, angle);
	}
}
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.º 6
0
bool PhysicsEngine::CollisionWithMapSimple(PowerBall* b, Map* map, Vector3 &normalPlane)
{
	
	MaloW::Array<MeshStrip*>* temp = map->GetMesh()->GetStrips();
	//int sizeMstrip = temp->size();
	int sizeVertexS0 = temp->get(0)->getNrOfVerts();
	Vertex* verts;
	//Vector3 origin = this->GetPositionVector3();
	Vector3 origin = b->GetTempPosition();
	Vector3 dir = b->GetVelocity();
	Vector3 dirN = dir/dir.GetLength();
	verts = temp->get(0)->getVerts();
	/*
	for(int i = 0;i<sizeMstrip;i++)
	{
		
	}
	*/
	Vector3 p0,p1,p2, normal, v1,v2;
	float smalestTime = -1;
	bool firstHit = false;
	float u, v,t;
	float lengthProjN = 0;
	Vector3 p0Store, p1Store,p2Store, normalStore;
	Vector3 pos = Vector3(map->GetMesh()->GetPosition());
	Vector3 posS = b->GetTempPosition();//this->GetPositionVector3();
	Vector3 rayDirection;
	Vector3 scalingMesh = map->GetMesh()->GetScaling();

	D3DXMATRIX quat;
	D3DXMatrixRotationQuaternion(&quat, &map->GetMesh()->GetRotation()); 
	Matrix4 rotate(quat);
	rotate.TransposeThis();

	Matrix4 scaling;
	scaling.SetScale(scalingMesh);

	Matrix4 translate;
	translate.SetTranslate(pos);
	
	Matrix4 world = translate*rotate*scaling;
	
	for(int i =0; i< sizeVertexS0; i+=3)
	{
		
		/*
		p0 = Vector3(verts[i].pos).GetComponentMultiplication(scalingMesh) + pos;
		p1 = Vector3(verts[i+1].pos).GetComponentMultiplication(scalingMesh) +pos;
		p2 = Vector3(verts[i+2].pos).GetComponentMultiplication(scalingMesh) + pos;
		*/
		p0 = world*Vector3(verts[i].pos);
		p1 = world*Vector3(verts[i+1].pos);
		p2 = world*Vector3(verts[i+2].pos);

		v1 = p1-p0;
		v2 = p2-p0;
		rayDirection = v1.GetCrossProduct(v2);
		rayDirection.normalize();
		float tempLength;
		Vector3 ny;
		Vector3 projN;
		if(RayTriIntersect(origin , rayDirection, p0, p1, p2, u, v, t) )
		{
			normal = rayDirection;
			ny = origin - p0;
			projN = normal*ny.GetDotProduct(normal);
			tempLength = projN.GetLength();
			if(!firstHit)
			{
				firstHit = true;
				smalestTime = t;
				lengthProjN = tempLength;
				p0Store = p0;
				p1Store = p1;
				p2Store = p2;
				normalStore = normal;
			}
			else
			{
				if( tempLength < lengthProjN )
				{
					smalestTime = t;
					lengthProjN = tempLength;
					p0Store = p0;
					p1Store = p1;
					p2Store = p2;
					normalStore = normal;
				}
			}			
		}
		// check agains all edges
		Vector3 lineDirection;
		float scalarProj;
		Vector3 projOnLine;
		Vector3 normalToLine;
		// edge 1:
		ny = origin - p0;
		lineDirection = p1 - p0;
		scalarProj = (ny.GetDotProduct(lineDirection)/lineDirection.GetLengthSquared());
		projOnLine = lineDirection * scalarProj;
		if( (scalarProj >= 0.0f) && (scalarProj <= 1) )
		{
			normalToLine = ny - projOnLine;
			tempLength = normalToLine.GetLength();
			if(!firstHit)
			{
				firstHit = true;
				lengthProjN = tempLength;
				p0Store = p0;
				p1Store = p1;
				p2Store = p2;
				normalStore = normalToLine;
				normalStore.normalize();
			}
			else
			{
				if( tempLength < lengthProjN )
				{
					lengthProjN = tempLength;
					p0Store = p0;
					p1Store = p1;
					p2Store = p2;
					normalStore = normalToLine;
					normalStore.normalize();
				}
			}	

		}
		// edge 2:
		ny = origin - p1;
		lineDirection = p2 - p1;
		scalarProj = (ny.GetDotProduct(lineDirection)/lineDirection.GetLengthSquared());
		projOnLine = lineDirection * scalarProj;
		if( (scalarProj >= 0.0f) && (scalarProj <= 1) )
		{
			normalToLine = ny - projOnLine;
			tempLength = normalToLine.GetLength();
			if(!firstHit)
			{
				firstHit = true;
				lengthProjN = tempLength;
				p0Store = p0;
				p1Store = p1;
				p2Store = p2;
				normalStore = normalToLine;
				normalStore.normalize();
			}
			else
			{
				if( tempLength < lengthProjN )
				{
					lengthProjN = tempLength;
					p0Store = p0;
					p1Store = p1;
					p2Store = p2;
					normalStore = normalToLine;
					normalStore.normalize();
				}
			}	

		}
		// edge 3:
		ny = origin - p2;
		lineDirection = p0 - p2;
		scalarProj = (ny.GetDotProduct(lineDirection)/lineDirection.GetLengthSquared());
		projOnLine = lineDirection * scalarProj;
		if( (scalarProj >= 0.0f) && (scalarProj <= 1) )
		{
			normalToLine = ny - projOnLine;
			tempLength = normalToLine.GetLength();
			if(!firstHit)
			{
				firstHit = true;
				lengthProjN = tempLength;
				p0Store = p0;
				p1Store = p1;
				p2Store = p2;
				normalStore = normalToLine;
				normalStore.normalize();
			}
			else
			{
				if( tempLength < lengthProjN )
				{
					lengthProjN = tempLength;
					p0Store = p0;
					p1Store = p1;
					p2Store = p2;
					normalStore = normal;
				}
			}	

		}
	}
	if(firstHit)
	{
		// for checking if the ball are in the air not turned on at the moment, 
		float eps = 0.5f; //0.001
		if( (lengthProjN < (b->GetRadius() + eps)) && (lengthProjN > (b->GetRadius() - eps)) )
		{
			b->SetNormalContact(normalStore);
			b->SetHasContact(true);
		}
		else 
		{
			b->SetNormalContact(normalStore);
			b->SetHasContact(false);
		}

		if( lengthProjN <= b->GetRadius())
		{
			Vector3 velNorm = b->GetVelocity();
			velNorm.normalize();
			
			if(normalStore.GetDotProduct(velNorm) >=0)
				return false;
	
			float diff = abs(lengthProjN- b->GetRadius());
			
			//Vector3 newPo = origin -dirN*diff;
			//Vector3 projVel = normalStore * this->mVelocity.GetDotProduct(normalStore);
			Vector3 newPo = origin + normalStore*diff;
			/*
			if( projVel.GetDotProduct(normalStore) < 0.0f)
			{
				newPo = origin - normalStore*diff;
				return false;
			}
			else
				newPo = origin + normalStore*diff;
			*/
			
			//this->SetPosition(newPo);
			b->SetTempPosition(newPo);
			normalPlane = normalStore;
			//this->mNormalContact = normalPlane;
			//this->mHasContact  = true;
			return true;
		}
		else
		{
			normalPlane = Vector3(0,0,0);
			//this->mNormalContact = normalPlane;
			//this->mHasContact  = false;
			return false;
		}
		
	}
	normalPlane = Vector3(0,0,0);
	b->SetNormalContact(normalPlane);
	//this->mHasContact  = false;
	return false;
}
Exemplo n.º 7
0
void PhysicsEngine::CollisionSphereResponse(PowerBall* b, PowerBall* b1)
{
	// normal of the "collision plane"
	//Vector3 nColl = this->GetPositionVector3() - b1->GetPositionVector3();
	Vector3 nColl = b->GetTempPosition() - b1->GetTempPosition();
	// for easy projecting of vector, no div by |n|^2 in proj formula
	Vector3 tempa = nColl;
	nColl.normalize();

	// savning the important stuff for easy acc
	float m1 = b->GetMass();
	float m2 = b1->GetMass();
	float mSum = m1+m2;
	Vector3 v1 = b->GetVelocity();
	Vector3 v2 = b1->GetVelocity();

	// projecting the vector v1 on nColl
	float x1 = nColl.GetDotProduct(v1);		// factor in nColl dir
	Vector3 v1x = nColl*x1;					// projetion done
	Vector3 v1y = v1 - v1x;					// perpendicular vector 

	// projecting the vector v2 on nColl
	nColl = nColl*(-1);						// switching direction of "plane normal"
	float x2 = nColl.GetDotProduct(v2);		// factor in nColl dir
	Vector3 v2x = nColl*x2;					// projetion done
	Vector3 v2y = v2 - v2x;					// perpendicular vector 

	float e1 = b->GetRestitution();
	float e2 = b1->GetRestitution();
	float e = (e1 + e2)/2.0f;

	if(((v1x-v2x).GetLength() > 0.6f) && b->SoundEnabled())
		this->mCollisionWithBall->Play();
	

	/*
	this->mVelocity = Vector3( v1x*(m1-m2)/(mSum) + v2x*(2*m2)/(mSum) + v1y );
	b1->mVelocity = Vector3( v1x*(2*m1)/(mSum) + v2x*(m2-m1)/(mSum) + v2y );
	*/
	b->SetVelocity(Vector3( v1x*(m1-m2*e)/(mSum) + v2x*((1+e)*m2)/(mSum) + v1y ));
	b1->SetVelocity(Vector3( v1x*((1+e)*m1)/(mSum) + v2x*(m2-m1*e)/(mSum) + v2y ));

	
	/* calculating damage. */
	if(b->WarlockMode())
	{
		Vector3 ve1 = b->GetVelocity();
		Vector3 ve2 = b1->GetVelocity();
		Vector3 relativeV = ve1 - ve2;
		if( relativeV.GetLength() > 0.6f)
		{
			float v1 = ve1.GetLength();
			float v2 = ve2.GetLength();
			float mass1 = b->GetMass();
			float mass2 = b1->GetMass();
			float momentum1 = v1 * mass1;
			float momentum2 = v2 * mass2;
			float sumMomentum = momentum1 + momentum2;
			/* to make it clear. if ball 1 has the speed of 10 m/s and ball 2 has
			** the speed 0 m/s, ball 1 will not get any damage but ball 2 gets
			** his health minus 10* (10 / 10) = 10 so ball 2 has lost 10 in hp.
			** this works good because we using momentum as a weighted value. 
			*/
			float damage1 = 10.0f* (momentum2 / sumMomentum); 
			float damage2 = 10.0f* (momentum1 / sumMomentum);
			float health1 = b->GetHealth();
			health1 -= damage1;
			b->SetHealth(health1);
			float health2 = b1->GetHealth();
			health2 -= damage2;
			b1->SetHealth(health2);
		}
	}
	
	/* informing the spells to the balls that it has been a collision */
	Spell** spells = b->GetSpells();
	for(int i = 0;i<b->GetNrOfSpells();i++)
		spells[i]->InformCollision();
	spells = b1->GetSpells();
	for(int i = 0;i<b1->GetNrOfSpells();i++)
		spells[i]->InformCollision();

}
Exemplo n.º 8
0
bool PhysicsEngine::CollisionWithSphereSimple(PowerBall* b, PowerBall* b1)
{
	Vector3 r = b->GetPositionVector3() - b1->GetPositionVector3();
	r = b->GetTempPosition() - b1->GetTempPosition();

	float distanceBalls = r.GetLength();
	float sumRadius = b->GetRadius() + b1->GetRadius();
	if(distanceBalls > sumRadius)
		return false;

	/*  we have collision but we need to move the balls so they are not inside each other
	*	solve this equation: ((pos1 - t*vel1) - (pos2 - t*vel2)).length = radie1 + radie2
	*
	*	this gives ut the following:
	*	d	 = distance = p1-p2
	*	rV	 = relative velocity = v2-v1
	*	sumR = sumRadius = r1 + r2 
	*
	*	t    = - rV.dot(d)/|rV|^2 +- sqrt( rV.dot(d)^2/|rV|^4 - (sumR^2 - |d|^2) / |rV|^2
	*
	*/
	Vector3 d = b->GetPositionVector3() - b1->GetPositionVector3();
	d = b->GetTempPosition() - b1->GetTempPosition();

	Vector3 rV = b1->GetVelocity() - b->GetVelocity();
	float sumR = b->GetRadius() + b1->GetRadius();
	float tempA = rV.GetDotProduct(d) / rV.GetLengthSquared();
	float tempB = tempA*tempA;
	float tempC = (d.GetLengthSquared() - sumR*sumR) / rV.GetLengthSquared();
	float tempSq = tempB - tempC;
	if( tempSq < 0) // no real solutions
		return false;
	else
	{
		float t1 = - tempA - sqrt(tempSq);
		float t2 = - tempA + sqrt(tempSq);
		Vector3 newPos1, newPos2;
		if(t1 >= 0)
		{
			/*
			newPos1 = this->GetPositionVector3() - this->mVelocity*t1;
			newPos2 = b1->GetPositionVector3() - b1->mVelocity*t1;
								
			this->SetPosition(newPos1);
			b1->SetPosition(newPos2);
			*/

			newPos1 = b->GetTempPosition() - b->GetVelocity()*t1;
			newPos2 = b1->GetTempPosition() - b1->GetVelocity()*t1;
			b->SetTempPosition(newPos1);
			b1->SetTempPosition(newPos2);
		}
		else if(t2 >= 0)
		{
			/*
			newPos1 = this->GetPositionVector3() - this->mVelocity*t2;
			newPos2 = b1->GetPositionVector3() - b1->mVelocity*t2;
			
			this->SetPosition(newPos1);
			b1->SetPosition(newPos2);
			*/
			newPos1 = b->GetTempPosition() - b->GetVelocity()*t2;
			newPos2 = b1->GetTempPosition() - b1->GetVelocity()*t2;
			b->SetTempPosition(newPos1);
			b1->SetTempPosition(newPos2);
		}
		else 
			return false;
	}
	return true;
}
Exemplo n.º 9
0
void Game::PlayGameMode2()
{
	GraphicsEngine* mGe = GetGraphics();
	
	GetGraphics()->ShowLoadingScreen("Media/LoadingScreen/LoadingScreenBG2.png", "Media/LoadingScreen/LoadingScreenPB.png", 1.0f, 1.0f);
	GetGraphics()->ChangeSkyBox("Media/StarMap.dds"); 

	GetGraphics()->GetCamera()->SetUpVector(Vector3(0, 1, 0));
	GetGraphics()->GetCamera()->SetForward(Vector3(1, 0, 0));
	GetGraphics()->GetCamera()->SetPosition(Vector3(-17.0f, 56.0f, 0));
	GetGraphics()->GetCamera()->LookAt(GetGraphics()->GetCamera()->GetPosition() - Vector3(1, 0.3f, 0));

	iLight* mLights[5];
	mLights[0] = mGe->CreateLight(Vector3(0, 50, 0));
	mLights[1] = mGe->CreateLight(Vector3(0, 50, -20)); 
	mLights[2] = mGe->CreateLight(Vector3(0, 50, 20));
	mLights[3] = mGe->CreateLight(Vector3(10, 50, 0));
	mLights[4] = mGe->CreateLight(Vector3(-10, 50, 0));
	for(int i = 0; i < 5; i++)
		mLights[i]->SetIntensity(30.0f);

	GetGraphics()->SetSunLightDisabled();
	GetGraphics()->SetSceneAmbientLight(Vector3(0.4f, 0.4f, 0.4f));

	Vector3 centerPlatform = Vector3(0,20,0);
	Map* mPlatform = new Map("Media/MazeMapFixed.obj", centerPlatform);
	Map* mBox = new Map("Media/MazeMapFrame.obj", centerPlatform + Vector3(0,1,0) );
	mPlatform->SetShrinkValue(0.0f);

	/* set so we cant tilt it more than these angles. */
	mPlatform->SetMaxAngleX(10.0f*(PI/180.0f));
	mPlatform->SetMaxAngleZ(10.0f*(PI/180.0f));
	mPlatform->SetRotate(false);
	mPlatform->SetTargetAngleX(0.5f);
	mPlatform->SetTargetAngleZ(-0.5f);

	PowerBall* mBalls = new PowerBall("Media/Ball.obj", START_POS);
	mBalls->SetForwardVector(Vector3(0,0,1));
	mBalls->SetKnockoutMode();
	mBalls->SetAcceleration(mBalls->GetAcceleration()*30.0f);


	iText* timeTxt = GetGraphics()->CreateText("", Vector2(50, 60), 1.0f, "Media/fonts/new");
	iText* scoreTxt = GetGraphics()->CreateText("", Vector2(50, 95), 1.0f, "Media/fonts/new");

	iImage* guiStar = GetGraphics()->CreateImage(Vector2(200, 90), Vector2(75, 75), "Media/star.png");
	guiStar->SetOpacity(0.0f);
	float starTimer = 0.0f;


	GetGraphics()->LoadingScreen("Media/LoadingScreen/LoadingScreenBG2.png", "Media/LoadingScreen/LoadingScreenPB.png", 1.0f, 1.0f, 1.0f, 1.0f);
	this->FlushQueue();

	mGe->GetCamera()->SetPosition(centerPlatform + Vector3(0.0f, 30.0f, 20.0f));
	mGe->GetCamera()->LookAt(centerPlatform);

	// Score / results:
	float time = 0.0f;
	bool started = false;
	int score = 0;

	float delayTimer = 1000.0f;

	GetGraphics()->GetKeyListener()->SetCursorVisibility(false);

	go = true;
	const Vector3 DefaultDir = Vector3(0.0f, 1.0f, 0.0f);
	int currentPrev = 0;
	Vector3 prevVectors[NROFPREV];
	for(int i = 0; i < NROFPREV; i++)
	{
		prevVectors[i] = DefaultDir;
	}

	while(delayTimer > 0)
	{
		float diff = GetGraphics()->Update();
		delayTimer -= diff;
	}

	while(GetGraphics()->IsRunning() && go)
	{
		if(mGe->GetKeyListener()->IsPressed('1'))
		{
			mGe->GetCamera()->SetPosition(centerPlatform+ Vector3(20.0f, 30.0f, 20.0f));
			mGe->GetCamera()->LookAt(centerPlatform );
		}
		if(mGe->GetKeyListener()->IsPressed('2'))
		{
			mGe->GetCamera()->SetPosition(centerPlatform+ Vector3(20.0f, 30.0f, -20.0f));
			mGe->GetCamera()->LookAt(centerPlatform );
		}
		if(mGe->GetKeyListener()->IsPressed('3'))
		{
			mGe->GetCamera()->SetPosition(centerPlatform+ Vector3(-20.0f, 30.0f, 20.0f));
			mGe->GetCamera()->LookAt(centerPlatform );
		}
		if(mGe->GetKeyListener()->IsPressed('4'))
		{
			mGe->GetCamera()->SetPosition(centerPlatform+ Vector3(-20.0f, 30.0f, -20.0f));
			mGe->GetCamera()->LookAt(centerPlatform );
		}

		// Updates GFX
		float diff = GetGraphics()->Update();

		// Handle events such as network packets and client connections
		this->HandleEvent(diff);
	
		if(GetGraphics()->GetKeyListener()->IsPressed(VK_ESCAPE))
			go = false;
		if(GetGraphics()->GetKeyListener()->IsPressed('R') || (this->networkController != NULL && this->networkController->needRestart == true))
		{
			if(this->networkController != NULL)
			{
				this->networkController->needRestart = false;
			}
			delete mBalls;

			// Spawn at last score - 1;
			if(score == 0)
				mBalls = new PowerBall("Media/Ball.obj", scorePos[0]);
			else
				mBalls = new PowerBall("Media/Ball.obj", scorePos[score - 1]);

			mBalls->SetForwardVector(Vector3(0,0,1));
			mBalls->SetKnockoutMode();
			mBalls->SetAcceleration(mBalls->GetAcceleration()*15.0f);

			mPlatform->ResetXZAngles();
			mPlatform->RotateX(0);
		}
		iPhysicsEngine* pe = GetGraphics()->GetPhysicsEngine();
		mBalls->UpdateBallParentMode(mPlatform);
		mBalls->Update(diff);
		Vector3 normalPlane;
		if(pe->DoSpecialPhoneCollisionGame(mBalls, mPlatform, normalPlane, diff))
			mBalls->collisionPlatformResponse(mPlatform, normalPlane, diff);
		mBalls->UpdatePost();
		mPlatform->Update(diff);

		if(this->networkController)
		{
			mPlatform->SetRotate(true);
			Vector3 phoneDirr = Vector3(this->networkController->direction.y, this->networkController->direction.z, -this->networkController->direction.x);
			//Vector3 phoneDirr = this->networkController->direction;
			phoneDirr.Normalize();
			prevVectors[currentPrev] = phoneDirr;
			float angle = CalcAngle(phoneDirr, DefaultDir, prevVectors, currentPrev);

			float angleX = acos(DefaultDir.GetDotProduct(Vector3(0, phoneDirr.y , phoneDirr.z).Normalize()));
			float angleZ = acos(DefaultDir.GetDotProduct(Vector3(phoneDirr.x, phoneDirr.y, 0).Normalize()));
			if(phoneDirr.z > 0)
			{
				angleX *= -1;
			}
			if(phoneDirr.x < 0)
			{
				angleZ *= -1;
			}
			mPlatform->SetTargetAngleX(angleX/4);
			mPlatform->SetTargetAngleZ(angleZ/4);

			angle /= 4;
			currentPrev++;
			if(currentPrev >= NROFPREV)
				currentPrev = 0;
		}
		if(mGe->GetKeyListener()->IsPressed('W'))
		{
			mPlatform->RotateX(-diff);

			Vector3 tempPos = mBalls->GetPosition() - mPlatform->GetMesh()->GetPosition();
			tempPos.RotateAroundAxis(Vector3(1,0,0), (PI/8.0f)*-diff*0.001f);
			mBalls->SetPosition(mPlatform->GetMesh()->GetPosition() + tempPos);
		}
		if(mGe->GetKeyListener()->IsPressed('S'))
		{
			mPlatform->RotateX(diff);

			Vector3 tempPos = mBalls->GetPosition() - mPlatform->GetMesh()->GetPosition();
			tempPos.RotateAroundAxis(Vector3(1,0,0), (PI/8.0f)*diff*0.001f);
			mBalls->SetPosition(mPlatform->GetMesh()->GetPosition() + tempPos);
		}
		if(mGe->GetKeyListener()->IsPressed('A'))
		{
			mPlatform->RotateZ(-diff);

			Vector3 tempPos = mBalls->GetPosition() - mPlatform->GetMesh()->GetPosition();
			tempPos.RotateAroundAxis(Vector3(0,0,1), (PI/8.0f)*-diff*0.001f);
			mBalls->SetPosition(mPlatform->GetMesh()->GetPosition() + tempPos);
		}
		if(mGe->GetKeyListener()->IsPressed('D'))
		{
			mPlatform->RotateZ(diff);

			Vector3 tempPos = mBalls->GetPosition() - mPlatform->GetMesh()->GetPosition();
			tempPos.RotateAroundAxis(Vector3(0,0,1), (PI/8.0f)*diff*0.001f);
			mBalls->SetPosition(mPlatform->GetMesh()->GetPosition() + tempPos);
		}
		
		//////////////////////////////////////////////////////////////////////////
		static bool posb = true;
		if(GetGraphics()->GetKeyListener()->IsPressed('Q'))
		{
			if(posb)
			{
				MaloW::Debug(mBalls->GetPosition());
				posb = false;
			}			
		}
		else
			posb = true;
		//////////////////////////////////////////////////////////////////////////

		if(started)
		{
			for(int i = score + 1; i < 15; i++)
			{
				Vector3 toScore = scorePos[i] - mBalls->GetPosition();
				toScore.y = 0.0f;
				float distanceToScore = toScore.GetLength();
				if(distanceToScore < 2.0f)
				{
					score = i;
					starTimer = 2.0f;

					// Do Vibration
					if(this->networkController)
					{
						this->networkController->cc->sendData("VIB: 100");
					}
				}
			}

			time += diff * 0.001f;
		}
		else
		{
			if((mBalls->GetPosition() - Vector3(-13.0f,25,-13)).GetLength() > 3)
			{
				started = true;
			}
		}

		starTimer -= diff * 0.001f;
		if(starTimer < 0.0f)
			starTimer = 0.0f;
		guiStar->SetOpacity(starTimer);

		// print score and time text
		scoreTxt->SetText(string("SCORE: " + MaloW::convertNrToString(score)).c_str());
		timeTxt->SetText(string("TIME: " + MaloW::convertNrToString(time)).c_str());


		// End game after 2 mins
		if(time > 120.0f || score > 13)
		{
			this->FinishScreen(score, "2, Labyrinth", time);
			go = false;
		}
	}

	if(this->networkController)
	{
		this->networkController->cc->sendData("QUITTING");
	}

	for(int i = 0; i < 5; i++)
		mGe->DeleteLight(mLights[i]);

	delete mPlatform;
	delete mBalls;
	delete mBox;

	mGe->DeleteText(timeTxt);
	mGe->DeleteText(scoreTxt);
	GetGraphics()->DeleteImage(guiStar);
}
Exemplo n.º 10
0
bool AIDeerBehavior::Update( float dt )
{
	if ( Behavior::Update(dt) )
		return true;

	DeerActor* dActor = dynamic_cast<DeerActor*>(this->zActor);

	//static float testInterval = 0; //Just for debugging.
	//testInterval += dt;
	this->zIntervalCounter += dt;
	//this->zIntervalCounter += dt;
	this->zFearIntervalCounter += dt;
	//this->zAlertnessIntervalCounter += deltaTime;
	
	int nrOfPredators = 0;
	bool nearbyPredatorsExist = false;
		
	//Perform checking for entities here.
	float shortestDistance = 99999;

	float finalDistance = 0;

	int maximumNodesTest = 5;

	//Determine closest threat/target
	
	//std::set<Actor*> aSet = this->GetTargets();

	for(auto i = this->zNearDynamicActors.cbegin(); i != this->zNearDynamicActors.cend(); i++)//for(auto i = aSet.cbegin(); i != aSet.cend(); i++)
	{
		finalDistance = (dActor->GetPosition().GetXZ() - (*i)->GetPosition().GetXZ()).GetLength();

		if( finalDistance < this->zMinimumDistance && !dynamic_cast<DeerActor*>((*i)) && dynamic_cast<BioActor*>((*i)) && dynamic_cast<BioActor*>((*i))->IsAlive() ) 
		{
			dynamic_cast<BioActor*>(*i)->zValid = true;
			if(finalDistance < shortestDistance)
			{
				shortestDistance = finalDistance;
				this->zMainActorTarget = (*i); //Decide which is the biggest threat here, i.e. the main target. For the moment, proximity is the deciding factor. Could use some more complexity.
			}
			nrOfPredators++;
		}
		else if( BioActor* bioActor = dynamic_cast<BioActor*>(*i) )
		{
			bioActor->zValid = false;
		}
	}

	
	//for(int i = 0; i < this->GetCurrentTargets(); i++)
	//{
	//	xDistance = dActor->GetPosition().x - this->zTargets[i].position.x; //Math, could use optimization, I think.
	//	//yDistance = this->GetPosition().y - this->zTargets[i].position.y;
	//	zDistance = dActor->GetPosition().z - this->zTargets[i].position.z;
	//	finalDistance = sqrt(xDistance * xDistance + zDistance * zDistance);
	//	if( finalDistance < this->zMinimumDistance && this->zTargets[i].kind != DEER) 
	//	{
	//		this->zTargets[i].valid = true;
	//		if(finalDistance < shortestDistance)
	//		{
	//			shortestDistance = finalDistance;
	//			this->zMainTarget = this->zTargets[i]; //Decide which is the biggest threat here, i.e. the main target. For the moment, proximity is the deciding factor. Could use some more complexity.
	//		}
	//		nrOfPredators++;
	//	}
	//	else
	//	{
	//		this->zTargets[i].valid = false;
	//	}
	//}
	if(nrOfPredators > 0)
	{
		nearbyPredatorsExist = true;
	}
	else
	{
		nearbyPredatorsExist = false;
	}

	//Time to assess threats.

	if( dActor->GetHealth() < this->GetPreviousHealth() ) //In theory, used to check if the animal has been attacked.
	{
		this->SetFearLevel( this->GetFearLevel() + this->zFearAtDamageDone);
	}
	this->SetPreviousHealth( dActor->GetHealth() );
	
	if(this->zFearIntervalCounter > this->zFearInterval) //Basically, each amount of fearinterval seconds the fear increases or decreases.
	{
		this->zFearIntervalCounter = 0;
		
		if(nearbyPredatorsExist)
		{
			//Getting values and such, comparing animal health against that of other entities, types and more.

			//calculate current fear level:
			float fear = 0;
			//- for each dangerous entity detected, add some fear, fear could be based on type. Deers are afraid of humans for example.
			fear += this->zExtraFearWithNumberOfPlayers * nrOfPredators;
			
			if(shortestDistance < this->zTooCloseInDistance) //The target is too close. Could expand this to incorporate more than one target.
			{
				fear += zExtraFearWithCloseProximity;
			}

			//std::set<Actor*> aSet = this->GetTargets();
			for(auto i = this->zNearDynamicActors.cbegin(); i != this->zNearDynamicActors.cend(); i++)//for(auto i = aSet.cbegin(); i != aSet.cend(); i++)
			{
				if(dynamic_cast<BioActor*>((*i)))
				{
					if(dynamic_cast<BioActor*>((*i))->zValid == true)
					{
						//Do a mathematical check, see if anyone is right in front of the deer. But... how? http://www.youtube.com/watch?v=gENVB6tjq_M
						Vector3 actorPosition = dActor->GetPosition();
						float dotProduct = dActor->GetDir().GetDotProduct( (*i)->GetPosition() - actorPosition );
						if(dotProduct > this->zFieldOfView)//This sight is relatively wide, since it is a deer. If this is true, then the deer sees a player.
						{
							//Which means, it is even more afraid.
							fear += zExtraFearAtSight;
						}
						if(dynamic_cast<BioActor*>((*i))->GetVelocity() > this->zThreatMovementSpeedThreshold)
						{
							fear += this->zExtraFearAtThreatMovementSpeed;
						}

						if(dynamic_cast<BioActor*>((*i))->GetHealth() != 0) // No dbz here!
						{
							fear -= (dActor->GetHealth() / dynamic_cast<BioActor*>((*i))->GetHealth()) / nrOfPredators; //If the animal is faced with a very weak player(s), it gets some confidence. This is reduced with each player present.
						}
					}
				}	
			}			
			this->SetFearLevel( this->GetFearLevel() + fear * this->zConfidenceKoef); //5 is unrelated to the movementNoise. Probably not good enough math. The theory is that the animal is constantly getting more afraid.
		}
		else //No threat detected. Calming down.
		{
			this->SetFearLevel( this->GetFearLevel() - this->zFearDecrease);
		}
	}

	//Change state of mind.
	if(this->GetFearLevel() == 0.0f && !nearbyPredatorsExist)
	{
		this->SetMentalState(CALM);
		//this->SetScale(Vector3(0.01f, 0.01f, 0.01f));
	}
	else if(this->GetFearLevel() > 0.0f && this->GetFearLevel() <= this->zSupspiciousToAggressiveThreshold)
	{
		this->SetMentalState(SUSPICIOUS);
		//this->SetScale(Vector3(0.03f, 0.03f, 0.03f));
	}
	else if(this->GetFearLevel() > this->zSupspiciousToAggressiveThreshold && this->GetFearLevel() <= zAggressiveToAfraidThreshold && nearbyPredatorsExist)
	{
		if(this->GetMentalState() != AGGRESSIVE)
		{
			this->zCurrentPath.clear();
			this->SetIfNeedPath(true);
			this->SetMentalState(AGGRESSIVE);
			//this->SetScale(Vector3(0.05f, 0.05f, 0.05f));
		}
	}
	else if(this->GetFearLevel() > zAggressiveToAfraidThreshold && this->GetFearLevel() <= this->GetFearMax())
	{
		if(this->GetMentalState() != AFRAID)
		{
			this->zCurrentPath.clear();
			this->SetIfNeedPath(true);
			this->SetMentalState(AFRAID);
			//this->SetScale(Vector3(3.09f, 3.09f, 3.09f));
		}
	}
	else
	{
		this->SetMentalState(SUSPICIOUS);
	}
	
	//Act based on state of mind.
	if(this->GetMentalState() == CALM) //Relaxed behaviour. No threat detected.
	{
		this->zCurrentDistanceFled = 0;
		this->zPanic = false;
		if(this->zIntervalCounter > this->zCalmActionInterval && this->GetIfNeedPath())
		{
			this->zIntervalCounter = 0;
			srand((unsigned int)time(0));
			this->zCalmActionInterval = (float)(rand() % this->zCalmRandomInterval + this->zCalmRandomAddition); 
			this->zCurrentPath.clear(); //Since a new path is gotten, and the old one might not have been completed, we clear it just in case.
			//this->zPathfinder.Pathfinding(this->GetPosition().z, this->GetPosition().x, this->GetPosition().x + rand() % 14 - 7, this->GetPosition().z + rand() % 14 - 7, this->zCurrentPath, 20); //Get a small path to walk, short and does not have to lead anywhere.
			this->zPathfinder.Pathfinding(dActor->GetPosition().x, dActor->GetPosition().z, dActor->GetPosition().x + rand() % zDistanceToWalkWhenCalm - zDistanceToWalkWhenCalm/2, dActor->GetPosition().z + rand() % zDistanceToWalkWhenCalm - zDistanceToWalkWhenCalm/2, this->zCurrentPath, maximumNodesTest);
			this->SetIfNeedPath(false);
		}
	}
	else if(this->GetMentalState() == SUSPICIOUS) //Might have heard something, is suspicious.
	{
		this->zCurrentDistanceFled = 0;
		this->zPanic = false;
		if(this->zIntervalCounter > this->zCalmActionInterval && this->GetIfNeedPath()) //The increase in time is supposed to represent listening, waiting for something to happen.
		{
			this->zIntervalCounter = 0;
			srand((unsigned int)time(0));
			this->zCalmActionInterval = (float)(rand() % this->zSupsiciousRandomInterval + this->zSupsiciousAddition);
			this->zCurrentPath.clear();
			//this->zPathfinder.Pathfinding(this->GetPosition().z, this->GetPosition().x, this->GetPosition().x + rand() % 8 - 4, this->GetPosition().z + rand() % 8 - 4, this->zCurrentPath, 20); //Get a small path to walk, quite short (since the animal is nervous) and does not have to lead anywhere.
			this->zPathfinder.Pathfinding(dActor->GetPosition().x, dActor->GetPosition().z, dActor->GetPosition().x + rand() % zDistanceToWalkWhenSuspicious - zDistanceToWalkWhenSuspicious/2, dActor->GetPosition().z + rand() % zDistanceToWalkWhenSuspicious - zDistanceToWalkWhenSuspicious/2, this->zCurrentPath, maximumNodesTest);
			this->SetIfNeedPath(false);
		}
	}
	else if(this->GetMentalState() == AGGRESSIVE) //Is outright trying to harm the target.
	{
		this->zCurrentDistanceFled = 0;
		this->zPanic = false;
		float lastDistance = (dActor->GetPosition().GetXZ() - this->zMainActorTarget->GetPosition().GetXZ()).GetLength();
		if( this->GetIfNeedPath() == true )
		{
			this->SetIfNeedPath(false);
			this->zCurrentPath.clear();
			if( !this->zPathfinder.Pathfinding(dActor->GetPosition().x, dActor->GetPosition().z, this->zMainActorTarget->GetPosition().x,  this->zMainActorTarget->GetPosition().z, this->zCurrentPath, maximumNodesTest) == false ) //Get the path, with the target that is to be attacked as the goal position. Depending on the animal, make the distance slightly large. //!this->zPathfinder.Pathfinding(this->GetPosition().z, this->GetPosition().x, this->zMainTarget.position.x, this->zMainTarget.position.z, this->zCurrentPath, 40) == false
			{
				this->SetIfNeedPath(true);
			}
			this->SetLastDistanceCheck( lastDistance );
		}
		if( this->zIntervalCounter > 1.5 && this->GetIfNeedPath() == false )
		{
			this->zIntervalCounter = 0;

			if( lastDistance < this->GetLastDistanceCheck() / 2) // The animal has traveled towards its goal halfway, at this point, it is safe to asume the goal has moved.
			{
				this->zCurrentPath.clear();
				this->zPathfinder.Pathfinding(dActor->GetPosition().x, dActor->GetPosition().z,  this->zMainActorTarget->GetPosition().x,  this->zMainActorTarget->GetPosition().z, this->zCurrentPath, maximumNodesTest);
				//this->zPathfinder.Pathfinding(this->GetPosition().z, this->GetPosition().x, this->zMainTarget.position.x, this->zMainTarget.position.z, this->zCurrentPath, 40);
			}

			float distance;
			float shortestDistance = 99999;
			Actor* mostLikelyTarget = this->zMainActorTarget;

			//std::set<Actor*> aSet = this->GetTargets();
			for(auto i = this->zNearDynamicActors.cbegin(); i != this->zNearDynamicActors.cend(); i++)//for(auto i = aSet.cbegin(); i != aSet.cend(); i++)
			{
				if(dynamic_cast<BioActor*>((*i)))
				{
					if(dynamic_cast<BioActor*>((*i))->zValid == true)
					{
						distance = (dActor->GetPosition().GetXZ() - (*i)->GetPosition().GetXZ()).GetLength();
					
						if(distance < shortestDistance) //Something that is a larger threat is based on distance.
						{
							shortestDistance = distance;
							mostLikelyTarget = (*i);
						}
					}
				}
			}
			if(shortestDistance < this->GetLastDistanceCheck() / this->zNewTargetCloseByAFactorOf) // The animal has gotten closer to a larger threat, and is now following that target instead.
			{
				this->SetIfNeedPath(true);
				this->zMainActorTarget = mostLikelyTarget;
			}
		}
	}
	else if(this->GetMentalState() == AFRAID) //Is afraid, need to run.
	{
		//if( this->zIntervalCounter > 1.5 && this->GetIfNeedPath() == false )
		if(this->GetIfNeedPath() == true)
		{
			this->SetIfNeedPath(false);
			
			if(nearbyPredatorsExist && this->zIntervalCounter > 2.5)
			{
				this->zIntervalCounter = 0.0f;
				this->zDestination = this->ExaminePathfindingArea();
				
				//this->zCurrentPath.clear();
				//if(!this->zPathfinder.Pathfinding(dActor->GetPosition().x, dActor->GetPosition().z, this->zDestination.x, this->zDestination.z,this->zCurrentPath, maximumNodesTest) ) //!this->zPathfinder.Pathfinding(this->GetPosition().z, this->GetPosition().x, awayFromThreatX, awayFromThreatZ,this->zCurrentPath,80)
				//{
				//	this->SetIfNeedPath(true);
				//}
			}
			else if(this->zPanic == true)
			{
				//Get random direction and run there.
				float awayFromThreatX;
				float awayFromThreatZ;
				int directionX = rand() % 2; 
				int directionZ = rand() % 2; 
				if(directionX == 0)
				{
					awayFromThreatX = dActor->GetPosition().x + this->zFleeDistance;
				}
				else
				{
					awayFromThreatX = dActor->GetPosition().x - this->zFleeDistance;
				}
				if(directionZ == 0)
				{
					awayFromThreatZ = dActor->GetPosition().z + this->zFleeDistance;
				}
				else
				{
					awayFromThreatZ = dActor->GetPosition().z - this->zFleeDistance;
				}
				
				this->zDestination.x = awayFromThreatX;
				this->zDestination.z = awayFromThreatZ;

				//this->zCurrentPath.clear();
				//if( !this->zPathfinder.Pathfinding(dActor->GetPosition().x, dActor->GetPosition().z, awayFromThreatX, awayFromThreatZ,this->zCurrentPath, maximumNodesTest) ) //!this->zPathfinder.Pathfinding(this->GetPosition().z, this->GetPosition().x, awayFromThreatX, awayFromThreatZ,this->zCurrentPath,80)
				//{
				//	this->SetIfNeedPath(true);
				//}
			}
			else //It has started to run, but still need to go further.
			{
				Vector3 direction = dActor->GetDir();

				direction.Normalize();

				this->zDestination.x += ( direction.x * this->zFleeDistance );
				this->zDestination.z += ( direction.z * this->zFleeDistance );
				
				//this->zCurrentPath.clear();
				//if( !this->zPathfinder.Pathfinding(dActor->GetPosition().x, dActor->GetPosition().z, this->zDestination.x, this->zDestination.z,this->zCurrentPath, maximumNodesTest) ) //!this->zPathfinder.Pathfinding(this->GetPosition().z, this->GetPosition().x, awayFromThreatX, awayFromThreatZ,this->zCurrentPath,80)
				//{
				//	this->SetIfNeedPath(true);
				//}
			}
		}
		else//It is already running.
		{
			//one or more entities should not collide with each other and stop. (I am not sure this is something to be handled here or elsewhere.	
		}
	}

	//Move the animal along path.
		this->zPreviousVelocity = dActor->GetVelocity();
		Vector3 oldPos = dActor->GetPosition();
		this->zPanic = false;
		
		//this->zPreviousPos = this->GetPosition();
	
		if(this->GetMentalState() == CALM && this->zCurrentPath.size() > 0 || this->GetMentalState() == SUSPICIOUS && this->zCurrentPath.size() > 0)
		{
			
			bool reachedNode = false;
			if( (dActor->GetPosition().x > this->zCurrentPath.back().x - 0.2 && dActor->GetPosition().x < this->zCurrentPath.back().x + 0.2) && ( dActor->GetPosition().z > this->zCurrentPath.back().y - 0.2 && dActor->GetPosition().z < this->zCurrentPath.back().y + 0.2 ) )
			{
				reachedNode = true;
			}

			if(reachedNode)
			{
				this->zCurrentPath.pop_back();
				//reachedNode = false;
			}
			/*double result = atan2( (this->zCurrentPath.back().y - this->GetPosition().z), (this->zCurrentPath.back().x - this->GetPosition().x) );

			result = result;
			this->SetDirection( Vector3( cos(result), 0.0f, sin(result) )); */

			if(this->zCurrentPath.size() > 0)
			{
				
			
				Vector3 goal(this->zCurrentPath.back().x, 0, this->zCurrentPath.back().y);
				Vector3 direction = goal - dActor->GetPosition();
				direction.Normalize();
				dActor->SetDir( direction ); 

				Vector2 testProperDirection;
				testProperDirection.x = dActor->GetDir().x;
				testProperDirection.y = dActor->GetDir().z;
				testProperDirection.Normalize();
				dActor->SetDir(Vector3(testProperDirection.x, 0.0f, testProperDirection.y));

			}
			/*if(dActor->GetVelocity() > this->zWalkingVelocity)
			{
				dActor->SetVelocity(this->zPreviousVelocity - 100 * dt);
			}
			else if(dActor->GetVelocity() < this->zWalkingVelocity)
			{
				dActor->SetVelocity(this->zPreviousVelocity + 100 * dt);
			}*/
			dActor->SetVelocity(this->zWalkingVelocity);
			
			//if(testInterval > 2.0) //Mainly for testing purposes.
			//{
			//	testInterval = 0;
			//	dActor->SetPosition(Vector3(this->zCurrentPath.back().x, 0, this->zCurrentPath.back().y) );
			//}
			dynamic_cast<BioActor*>(this->GetActor())->SetState(STATE_WALKING);
			dActor->SetPosition(dActor->GetPosition() + dActor->GetDir() * dt * dActor->GetVelocity());

		}
		else if(this->GetMentalState() == AGGRESSIVE  && this->zCurrentPath.size() > 0)
		{
			

			bool reachedNode = false;
			if( (dActor->GetPosition().x > this->zCurrentPath.back().x - 0.2 && dActor->GetPosition().x < this->zCurrentPath.back().x + 0.2) && ( dActor->GetPosition().z > this->zCurrentPath.back().y - 0.2 && dActor->GetPosition().z < this->zCurrentPath.back().y + 0.2 ) )
			{
				reachedNode = true;
			}

			if(reachedNode)
			{
				this->zCurrentPath.pop_back();
				//reachedNode = false;
			}
			/*double result = atan2( (this->zCurrentPath.back().y - this->GetPosition().z), (this->zCurrentPath.back().x - this->GetPosition().x) );

			result = result;
			this->SetDirection( Vector3( cos(result), 0.0f, sin(result) )); */


			if(this->zCurrentPath.size() > 0)
			{
				Vector3 goal(this->zCurrentPath.back().x, 0, this->zCurrentPath.back().y);
				Vector3 direction = goal - dActor->GetPosition();
				direction.Normalize();
				dActor->SetDir( direction ); 


				Vector2 testProperDirection;
				testProperDirection.x = dActor->GetDir().x;
				testProperDirection.y = dActor->GetDir().z;
				if(testProperDirection.GetLength() > 0.0f)
				{
					testProperDirection.Normalize();
				}
				dActor->SetDir(Vector3(testProperDirection.x, 0.0f, testProperDirection.y));
			
			}
		/*	if(dActor->GetVelocity() > this->zAttackingVelocity)
			{
				dActor->SetVelocity(this->zPreviousVelocity - 100 * dt);
			}
			else if(dActor->GetVelocity() < this->zAttackingVelocity)
			{
				dActor->SetVelocity(this->zPreviousVelocity + 100 * dt);
			}*/
			dActor->SetVelocity(this->zAttackingVelocity);
			dynamic_cast<BioActor*>(this->GetActor())->SetState(STATE_RUNNING);
			dActor->SetPosition(dActor->GetPosition() + dActor->GetDir() * dt * dActor->GetVelocity());

			

		}
		else if(this->GetMentalState() == AFRAID /*&& this->zCurrentPath.size() > 0*/)
		{
			/*double result = atan2( (this->zCurrentPath.back().y - this->GetPosition().z), (this->zCurrentPath.back().x - this->GetPosition().x) );

			result = result;
			this->SetDirection( Vector3( cos(result), 0.0f, sin(result) )); */

			dynamic_cast<BioActor*>(this->GetActor())->SetState(STATE_RUNNING);
			
			//Vector3 goal(this->zCurrentPath.back().x, 0, this->zCurrentPath.back().y);
			//Vector3 direction = goal - dActor->GetPosition();
			
			if(this->zCurrentPath.size() > 0)
			{
				bool reachedNode = false;
				if( (dActor->GetPosition().x > this->zCurrentPath.back().x - 0.2 && dActor->GetPosition().x < this->zCurrentPath.back().x + 0.2) && ( dActor->GetPosition().z > this->zCurrentPath.back().y - 0.2 && dActor->GetPosition().z < this->zCurrentPath.back().y + 0.2 ) )
				{
					reachedNode = true;
				}

				if(reachedNode)
				{
					this->zCurrentPath.pop_back();
					//reachedNode = false;
				}
			}

			if(this->zCurrentPath.size() > 0)
			{
				Vector3 goal(this->zCurrentPath.back().x, 0, this->zCurrentPath.back().y);
				Vector3 direction = goal - dActor->GetPosition();
				direction.Normalize();
				dActor->SetDir( direction ); 
			}
			else
			{
				Vector3 direction = this->zDestination - dActor->GetPosition();
				direction.Normalize();
				dActor->SetDir( direction ); 
			}

			dActor->SetVelocity(this->zFleeingVelocity);

			Vector3 nextPos = dActor->GetPosition() + dActor->GetDir() * dt * dActor->GetVelocity();


			

			if(!this->zWorld->IsBlockingAt(Vector2(nextPos.x,nextPos.z)) && this->zCurrentPath.size() == 0)
			{
				Vector2 testProperDirection;
				testProperDirection.x = dActor->GetDir().x;
				testProperDirection.y = dActor->GetDir().z;
				testProperDirection.Normalize();
				dActor->SetDir(Vector3(testProperDirection.x, 0.0f, testProperDirection.y));
				dynamic_cast<BioActor*>(this->GetActor())->SetState(STATE_RUNNING);
				dActor->SetPosition(dActor->GetPosition() + dActor->GetDir() * dt * dActor->GetVelocity());
				this->zCurrentDistanceFled += dt * dActor->GetVelocity();

			}
			else if(this->zCurrentPath.size() > 0)
			{
				Vector2 testProperDirection;
				testProperDirection.x = dActor->GetDir().x;
				testProperDirection.y = dActor->GetDir().z;
				testProperDirection.Normalize();
				dActor->SetDir(Vector3(testProperDirection.x, 0.0f, testProperDirection.y));
				dynamic_cast<BioActor*>(this->GetActor())->SetState(STATE_RUNNING);
				dActor->SetPosition(dActor->GetPosition() + dActor->GetDir() * dt * dActor->GetVelocity());
				this->zCurrentDistanceFled += dt * dActor->GetVelocity();

			}
			else if(this->zCurrentPath.size() == 0)
			{
				this->zCurrentPath.clear();
				this->zPathfinder.Pathfinding(dActor->GetPosition().x, dActor->GetPosition().z,  dActor->GetPosition().x + dActor->GetDir().x * 5.0f,  dActor->GetPosition().z + dActor->GetDir().z * 5.0f, this->zCurrentPath, 40);

				//dActor->SetPosition(Vector3(50,0,50));
			}
		}
		
		if(this->GetMentalState() == AFRAID && this->zCurrentDistanceFled < this->zFleeDistance)
		{
			this->SetIfNeedPath(true);
		}
		else
		{
			this->SetIfNeedPath(true);
		}
		
		float groundHeight = 0.0f;
		try
		{
			groundHeight = this->zWorld->CalcHeightAtWorldPos( Vector2(dActor->GetPosition().x, dActor->GetPosition().z));
		}
		catch(...)
		{

		}
		
		Vector3 actorPosition = dActor->GetPosition();
		Vector3 currentPos = actorPosition;
		actorPosition.y = groundHeight;
		dActor->SetPosition(actorPosition);
	
	if(oldPos == currentPos)
	{
		dynamic_cast<BioActor*>(this->GetActor())->SetState(STATE_IDLE);		
	}

	//Rotate Animal
	static Vector3 defaultMeshDir = Vector3(0.0f, 0.0f, 1.0f);
	Vector3 meshDirection = dActor->GetDir();
	meshDirection.y = 0;
	meshDirection.Normalize();

	Vector3 around = Vector3(0.0f, 1.0f, 0.0f);
	float angle = -acos(meshDirection.GetDotProduct(defaultMeshDir));

	if (meshDirection.x > 0.0f)
	 angle *= -1;

	dActor->SetRotation(Vector4(0.0f, 0.0f, 0.0f, 1.0f));
	dActor->SetRotation(around, angle);

	return false;
}