public override void UpdateEntity(int entity) { CPosition position = (CPosition)positions[entity]; CPredator predator = (CPredator)predators[entity]; CPhysicsBody physicsBody = (CPhysicsBody)physicsBodies[entity]; CTransform transform = (CTransform)transforms[entity]; CBoid boid = (CBoid)boids[entity]; if (!predator.Seeking) { predator.Seeking = true; predator.Target = new Vector2(Morro.Maths.Random.Range(0, (int)scene.SceneBounds.Width), Morro.Maths.Random.Range(0, (int)scene.SceneBounds.Height)); } else { Vector2 positionVector = new Vector2(position.X, position.Y); if (Vector2.Distance(positionVector, predator.Target) < 8) { predator.Seeking = false; return; } Vector2 desired = predator.Target - positionVector; desired.SetMagnitude(boid.MoveSpeed); Vector2 seek = desired - physicsBody.Velocity; seek.Limit(boid.MaxForce); physicsBody.Velocity += seek; transform.Rotation = -(float)Math.Atan2(physicsBody.Velocity.Y, physicsBody.Velocity.X); } }
public static IComponent[] Create(float x, float y) { CBoid boid = new CBoid() { ViewRadius = 16, MoveSpeed = Morro.Maths.Random.Range(60, 80), MaxForce = 0.4f }; CPhysicsBody physicsBody = new CPhysicsBody(Morro.Maths.Random.RandomVector2(boid.MoveSpeed), Microsoft.Xna.Framework.Vector2.Zero); CPosition position = new CPosition(x, y); CDimension dimension = new CDimension(4, 4); CTransform transform = new CTransform() { Scale = new Microsoft.Xna.Framework.Vector3(3, 1, 1), Rotation = -(float)Math.Atan2(physicsBody.Velocity.Y, physicsBody.Velocity.X), RotationOffset = new Microsoft.Xna.Framework.Vector2(dimension.Width / 2, dimension.Height / 2) }; CColor color = new CColor(PICO8.MidnightBlack); return(new IComponent[] { boid, physicsBody, position, dimension, transform, color, new CTriangle(), new CPartitionable(), new CPredator() }); }
/// <summary> /// Sets a new target to pursue /// </summary> /// <param name="_evader">New target</param> public void SetTarget(IEntity _evader) { evader = _evader.GetComponent <CPhysicsBody>(); if (evader == null) { throw new Exception("Evader must contain a physics body component"); } }
/// <summary> /// Sets a new chaser /// </summary> /// <param name="_chaser">Entity chasing this vehicle</param> public void SetChaser(IEntity _chaser) { chaser = _chaser.GetComponent <CPhysicsBody>(); if (chaser == null) { throw new Exception("Chaser must contain a physics body component"); } }
private void Integrate(CPosition position, CPhysicsBody physicsBody, Integrator integrator, float deltaTime) { switch (integrator) { case Integrator.SemiImplictEuler: SemiImplictEulerIntegration(deltaTime, position, physicsBody); break; case Integrator.VelocityVerlet: VelocityVerletIntegration(deltaTime, position, physicsBody); break; } }
private void Simultate(int entity) { CPosition position = (CPosition)positions[entity]; CPhysicsBody physicsBody = (CPhysicsBody)physicsBodies[entity]; physicsBody.Accumulator += (float)(Engine.TotalGameTime - physicsBody.LastUpdate).TotalSeconds; physicsBody.LastUpdate = new TimeSpan(Engine.TotalGameTime.Ticks); while (physicsBody.Accumulator >= target) { Integrate(position, physicsBody, integrator, target); physicsBody.Accumulator -= target; } }
private static void VelocityVerletIntegration(float deltaTime, CPosition position, CPhysicsBody physicsBody) { position.X += physicsBody.Velocity.X * deltaTime + 0.5f * physicsBody.Acceleration.X * deltaTime * deltaTime; position.Y += physicsBody.Velocity.Y * deltaTime + 0.5f * physicsBody.Acceleration.Y * deltaTime * deltaTime; physicsBody.Velocity += physicsBody.Acceleration * deltaTime; }
private void SemiImplictEulerIntegration(float deltaTime, CPosition position, CPhysicsBody physicsBody) { physicsBody.Velocity += physicsBody.Acceleration * deltaTime; position.X += physicsBody.Velocity.X * deltaTime; position.Y += physicsBody.Velocity.Y * deltaTime; }
public override void UpdateEntity(int entity) { CBoid boid = (CBoid)boids[entity]; CPosition position = (CPosition)positions[entity]; CDimension dimension = (CDimension)dimensions[entity]; CTransform transform = (CTransform)transforms[entity]; CPhysicsBody physicsBody = (CPhysicsBody)physicsBodies[entity]; Vector2 myCenter = new Vector2(position.X + dimension.Width / 2, position.Y + dimension.Height / 2); Vector2 cumulativeSeperation = Vector2.Zero; int totalSeperation = 0; Vector2 cumulativeAlignment = Vector2.Zero; int totalAlignment = 0; Vector2 cumulativeCohesion = Vector2.Zero; int totalCohesion = 0; float distance; CPosition theirPosition; CDimension theirDimension; CPhysicsBody theirPhysicsBody; Vector2 force; Vector2 theirCenter; List <int> queryResult = binPartitioner.Query(new Morro.Core.Rectangle(position.X - boid.ViewRadius, position.Y - boid.ViewRadius, dimension.Width + boid.ViewRadius * 2, dimension.Height + boid.ViewRadius * 2)); for (int i = 0; i < queryResult.Count; i++) { if (queryResult[i] == entity) { continue; } theirPosition = (CPosition)positions[queryResult[i]]; theirDimension = (CDimension)dimensions[queryResult[i]]; theirPhysicsBody = (CPhysicsBody)physicsBodies[queryResult[i]]; theirCenter = new Vector2(theirPosition.X + theirDimension.Width / 2, theirPosition.Y + theirDimension.Height / 2); distance = Vector2.Distance(myCenter, theirCenter); if (distance > 0) { if (distance < boid.ViewRadius) { cumulativeCohesion += theirCenter; totalCohesion++; cumulativeAlignment += theirPhysicsBody.Velocity; totalAlignment++; } if (distance < theirDimension.Width * 2) { force = myCenter - theirCenter; force /= distance * distance; cumulativeSeperation += force; totalSeperation++; } if (distance < 64 && theirDimension.Width > 2) { force = myCenter - theirCenter; force /= distance * distance; cumulativeSeperation += force * 4; totalSeperation++; } } } distance = Vector2.Distance(Morro.Input.Mouse.SceneLocation, myCenter); if (distance > 0 && distance < 32) { force = myCenter - Morro.Input.Mouse.SceneLocation; force /= distance * distance; cumulativeSeperation += force; totalSeperation++; } Vector2 seperation = CalculateSeperation(); Vector2 alignment = CalculateAlignment(); Vector2 cohesion = CalculateCohesion(); Vector2 totalForce = seperation + alignment + cohesion; physicsBody.Velocity += totalForce; transform.Rotation = -(float)Math.Atan2(physicsBody.Velocity.Y, physicsBody.Velocity.X); Vector2 CalculateSeperation() { if (totalSeperation <= 0) { return(Vector2.Zero); } cumulativeSeperation /= totalSeperation; cumulativeSeperation.SetMagnitude(boid.MoveSpeed); Vector2 result = cumulativeSeperation - physicsBody.Velocity; result.Limit(boid.MaxForce); return(result * seperationIntensity); } Vector2 CalculateAlignment() { if (totalAlignment <= 0) { return(Vector2.Zero); } cumulativeAlignment /= totalAlignment; cumulativeAlignment.SetMagnitude(boid.MoveSpeed); Vector2 result = cumulativeAlignment - physicsBody.Velocity; result.Limit(boid.MaxForce); return(result * alignmentIntensity); } Vector2 CalculateCohesion() { if (totalCohesion <= 0) { return(Vector2.Zero); } cumulativeCohesion /= totalCohesion; cumulativeCohesion -= myCenter; cumulativeCohesion.SetMagnitude(boid.MoveSpeed); Vector2 result = cumulativeCohesion - physicsBody.Velocity; result.Limit(boid.MaxForce); return(result * cohesionIntensity); } }