예제 #1
0
        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);
            }
        }
예제 #2
0
파일: Hawk.cs 프로젝트: thismarvin/morro
        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()
            });
        }
예제 #3
0
 /// <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");
     }
 }
예제 #4
0
 /// <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");
     }
 }
예제 #5
0
        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;
            }
        }
예제 #6
0
        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;
            }
        }
예제 #7
0
        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;
        }
예제 #8
0
        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;
        }
예제 #9
0
        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);
            }
        }