コード例 #1
0
 private static void SendCollision(BoundSetAspect boundSet1, BoundSetAspect boundSet2)
 {
     if (boundSet1.GetOwner().GetType() == typeof(Shell) && boundSet2.GetOwner().GetType() != typeof(Shell))
     {
         Shell shell = (Shell)boundSet1.GetOwner();
         if (shell.ShellOwner != boundSet2.GetOwner())
         {
             Ship target = (Ship)boundSet2.GetOwner();
             //target.RearCannon.PerformShoot();
             MessageDispatcher.Post(new BoundSetCollision(boundSet1, boundSet2));
         }
     }
     else
         if (boundSet2.GetOwner().GetType() == typeof(Shell) && boundSet1.GetOwner().GetType() != typeof(Shell))
         {
             Shell shell = (Shell)boundSet2.GetOwner();
             if (shell.ShellOwner != boundSet1.GetOwner())
             {
                 Ship target = (Ship)boundSet1.GetOwner();
                 //target.RearCannon.PerformShoot();
                 MessageDispatcher.Post(new BoundSetCollision(boundSet1, boundSet2));
             }
         }
         else
             MessageDispatcher.Post(new BoundSetCollision(boundSet1, boundSet2));
 }
コード例 #2
0
 internal static void CheckIntersection(BoundSetAspect boundSet1, BoundSetAspect boundSet2)
 {
     Pair<BoundSetAspect> pair = new Pair<BoundSetAspect>(boundSet1, boundSet2);
     // если объекты пересекаются, то ищем их в словаре.
     // если нашли, то НЕ генерируем событие Collision
     // если не нашли, то генерируем событие Collision и заносим их в словарь
     if (boundSet1.IntersectsWith(boundSet2))
     {
         if (!collisions.ContainsKey(pair))
         {
             collisions.Add(pair, 0);
             SendCollision(boundSet1, boundSet2);
         }
     }
     // объекты не пересекаются.
     // нужно удалить их из словарей, если они там есть,
     // и сгенерировать событие NotCollision, если они там были
     else
     {
         if (collisions.ContainsKey(pair))
         {
             collisions.Remove(pair);
             SendNotCollision(boundSet1, boundSet2);
         }
     }
 }
コード例 #3
0
 internal static void RemoveAspect(BoundSetAspect boundSetAspect)
 {
     Pair<BoundSetAspect>[] pairs = new Pair<BoundSetAspect>[collisions.Keys.Count];
     collisions.Keys.CopyTo(pairs, 0);
     foreach (Pair<BoundSetAspect> pair in pairs)
     {
         if (pair.First == boundSetAspect)
         {
             Pair<BoundSetAspect> newPair = new Pair<BoundSetAspect>(null, pair.Second);
             collisions.Remove(pair);
             if (pair.Second != null)
                 collisions.Add(pair, 0);
             SendNotCollision(boundSetAspect, pair.Second);
         }
         else
             if (pair.Second == boundSetAspect)
             {
                 Pair<BoundSetAspect> newPair = new Pair<BoundSetAspect>(pair.First, null);
                 collisions.Remove(pair);
                 if (pair.First != null)
                     collisions.Add(pair, 0);
                 SendNotCollision(boundSetAspect, pair.First);
             }
     }
 }
コード例 #4
0
ファイル: Ship.cs プロジェクト: Skybladev2/Sea-battles
        /// <summary>
        /// Конструктор
        /// </summary>
        /// <param name="shipVerts"></param>
        private Ship(PointF position, float length, float width)
        {
            float depth = 0;
            List<Vector3> shipVerts = new List<Vector3>();
            shipVerts.Add(new Vector3(-1f * width / 2 + position.X, -1f * length / 2 + position.Y, depth));
            shipVerts.Add(new Vector3(-1f * width / 2 + position.X, 0.25f * length / 2 + position.Y, depth));
            shipVerts.Add(new Vector3(0 * width / 2 + position.X, 1f * length / 2 + position.Y, depth));
            shipVerts.Add(new Vector3(1f * width / 2 + position.X, 0.25f * length / 2 + position.Y, depth));
            shipVerts.Add(new Vector3(1f * width / 2 + position.X, -1f * length / 2 + position.Y, depth));
            shipVerts.Add(new Vector3(-1f * width / 2 + position.X, -1f * length / 2 + position.Y, depth));

            //mechanics = VehicleWithGearboxAspect.Create(this);
            physics = PhysicsAspect.Create(this);
            mass = MassAspect.Create(this);
            Thruster thruster1 = Thruster.Create(this, physics.Facing);
            Thruster thruster2 = Thruster.Create(this, physics.Facing);
            IList<Thruster> thrusters = new List<Thruster>(2);
            thrusters.Add(thruster1);
            thrusters.Add(thruster2);
            thrusterController = ThrusterController.Create(this, thrusters);
            graphics = GraphicsAspect.Create(this, shipVerts, 3, Color.White, Color.Red);
            bounds = BoundSetAspect.Create(this, shipVerts);
            //bounds.GetOuterContour();
            bounds.SetAttribute(Strings.CollisionDetectionSpeedType, Strings.CollisionDetectionSpeedTypeSlowOrStatic);

            rearCannon = Weapon.Create(this, Side.Rear);
            leftCannon = Weapon.Create(this, Side.Left);
            rightCannon = Weapon.Create(this, Side.Right);
            damage = DamageAspect.Create(this, 100);

            messageHandler.Handlers.Add(typeof(Kill), HandleKill);
            messageHandler.Handlers.Add(typeof(BoundSetCollision), HandleBoundSetCollision);
        }
コード例 #5
0
ファイル: Shell.cs プロジェクト: Skybladev2/Sea-battles
        public Shell(Vector3 position, Vector3 cannonFacing, Vector3 cannonVelocity, float startSpeed, object shellOwner)
        {
            int segments = 8;
            List<Vector3> vertices = new List<Vector3>(segments + 1);

            //float unitradius = (float)Math.Sqrt(8);
            float angleStep = (float)(2 * Math.PI / segments);
            for (int i = 0; i < segments; i++)
            {
                vertices.Add(new Vector3((float)Math.Cos(angleStep * i) * radius, (float)Math.Sin(angleStep * i) * radius, 0));
            }
            vertices.Add(new Vector3(radius, 0, 0));

            graphics = GraphicsAspect.Create(this, vertices, position, 1, Color.White, Color.Red);

            // вычисляем вектор полёта снаряда - сумма импульса выстрела и собственной скорости оружия
            cannonFacing.NormalizeFast();
            Vector3 shootVelocity = cannonFacing * startSpeed + cannonVelocity;
            Vector2 shootDirection = shootVelocity.Xy;
            shootDirection.NormalizeFast();
            //physics = new PhysicsAspect(this, position, shootVelocity.Xy, startSpeed);

            physics = PhysicsAspect.Create(this, position, shootDirection, shootVelocity.LengthFast);
            bounds = BoundSetAspect.Create(this, null);
            BoundsAspect bound = CircleBoundsAspect.Create(bounds, position.Xy, radius);
            bounds.AddBound(bound);
            // снаряд будет быстродвижущимся объектом, для него особый алгоритм определения столкновений
            bounds.SetAttribute(Strings.CollisionDetectionSpeedType, Strings.CollisionDetectionSpeedTypeFast);
            damage = DamageAspect.Create(this, 1);

            //physics = new PhysicsAspect(this, position, Vector2.Zero, 0);
            //timer = DestroyByTimerAspect.Create(this, new TimeSpan(0, 0, 0, 2, 500));
            timer = DestroyByTimerAspect.Create(this, new TimeSpan(0, 0, 0, 1, 0));

            this.shellOwner = shellOwner;
            this.name = "shell";

            MessageDispatcher.RegisterHandler(typeof(SetPosition), bounds);
            MessageDispatcher.RegisterHandler(typeof(SetPosition), graphics);
            MessageDispatcher.RegisterHandler(typeof(DestroyChildrenOf), this);
            MessageDispatcher.RegisterHandler(typeof(Kill), this);

            messageHandler.Handlers.Add(typeof(Kill), HandleKill);
        }
コード例 #6
0
 private static void SendNotCollision(BoundSetAspect boundSet1, BoundSetAspect boundSet2)
 {
     MessageDispatcher.Post(new BoundSetNotCollision(boundSet1, boundSet2));
 }
コード例 #7
0
 private static bool SlowWithFastCollisionDetection(BoundSetAspect slowBoundSet, BoundSetAspect fastBoundSet)
 {
     foreach (BoundsAspect bound in slowBoundSet.bounds)
     {
         foreach (Triangle<Vector2> stretchedOutlinePart in fastBoundSet.stretchedOutline)
         {
             // где-то тут должна быть проверка на пересечение с самим собой, но это вроде бы не возможно
             if (bound.IntersectsWith(stretchedOutlinePart))
                 return true;
         }
     }
     return false;
 }
コード例 #8
0
        protected bool IntersectSlowAndFastBounds(BoundSetAspect slowBoundSet, BoundSetAspect fastBoundSet)
        {
            // для круглых быстрых объектов границами является вытянутая часть + круг
            if (fastBoundSet.IAmCircle)
            {
                // сначала проверяем вытянутый след
                if (SlowWithFastCollisionDetection(slowBoundSet, fastBoundSet))
                    return true;

                // потом - новое положение круга
                foreach (BoundsAspect bound in slowBoundSet.bounds)
                {
                    foreach (BoundsAspect bound2 in fastBoundSet.bounds)
                    {
                        if (bound != bound2)
                            if (bound.IntersectsWith(bound2))
                                return true;
                    }
                }

                return false;
            }
            else
            {
                return SlowWithFastCollisionDetection(slowBoundSet, fastBoundSet);
            }
        }
コード例 #9
0
        protected bool IntersectFastAndFastBounds(BoundSetAspect fastBoundSet1, BoundSetAspect fastBoundSet2)
        {
            // проверка вытянутых частей
            //
            foreach (Triangle<Vector2> stretchedOutlinePart1 in fastBoundSet1.stretchedOutline)
            {
                foreach (Triangle<Vector2> stretchedOutlinePart2 in fastBoundSet2.stretchedOutline)
                {
                    if (Misc.TriangleIntersectsWithTriangle(stretchedOutlinePart1, stretchedOutlinePart2))
                        return true;
                }
            }

            // для круглых быстрых объектов границами является вытянутая часть + круг
            if (fastBoundSet1.IAmCircle)
            {
                // в данной ситуации у fastBoundSet1 проверяется только его круг со следом fastBoundSet2
                if (SlowWithFastCollisionDetection(fastBoundSet1, fastBoundSet2))
                    return true;
            }

            if (fastBoundSet2.IAmCircle)
            {
                // в данной ситуации у fastBoundSet2 проверяется только его круг со следом fastBoundSet1
                if (SlowWithFastCollisionDetection(fastBoundSet2, fastBoundSet1))
                    return true;
            }

            // прроверка столкновения кругов у обоих объектов
            //
            if (fastBoundSet1.IAmCircle && fastBoundSet2.IAmCircle)
            {
                // ! всегда считаем, что первый параметр - это this
                return DiscreteCollisionDetection(fastBoundSet2);
            }

            return false;
        }
コード例 #10
0
        protected bool DiscreteCollisionDetection(BoundSetAspect boundSet)
        {
            if ((this.position - boundSet.position).LengthFast > this.radius + boundSet.radius)
                return false;

            foreach (BoundsAspect bound in this.bounds)
            {
                foreach (BoundsAspect bound2 in boundSet.bounds)
                {
                    if (bound != bound2)
                        if (bound.IntersectsWith(bound2))
                            return true;
                }
            }

            return false;
        }
コード例 #11
0
        public bool IntersectsWith(BoundSetAspect boundSet)
        {
            // первый тик - стандартное определение столкновения
            if (this.previousContour == null && boundSet.previousContour == null)
            {
                return DiscreteCollisionDetection(boundSet);
            }
            else
            {
                string otherCdSpeedType = null;
                string thisCdSpeedType = null;
                BoundSetAspect fastBoundSet = null;
                BoundSetAspect slowBoundSet = null;

                if (boundSet.ReflectionAttributes.GetAttribute(Strings.CollisionDetectionSpeedType, out otherCdSpeedType)
                    &&
                    this.ReflectionAttributes.GetAttribute(Strings.CollisionDetectionSpeedType, out thisCdSpeedType))
                {
                    // медленный - быстрый
                    //
                    if (otherCdSpeedType == Strings.CollisionDetectionSpeedTypeFast
                        &&
                        thisCdSpeedType == Strings.CollisionDetectionSpeedTypeSlowOrStatic)
                    {
                        slowBoundSet = this;
                        fastBoundSet = boundSet;

                        bool result = IntersectSlowAndFastBounds(slowBoundSet, fastBoundSet);
                        return result;
                    }

                    // быстрый - медленный
                    //
                    if (otherCdSpeedType == Strings.CollisionDetectionSpeedTypeSlowOrStatic
                        &&
                        thisCdSpeedType == Strings.CollisionDetectionSpeedTypeFast)
                    {
                        slowBoundSet = boundSet;
                        fastBoundSet = this;

                        bool result = IntersectSlowAndFastBounds(slowBoundSet, fastBoundSet);
                        return result;
                    }

                    // медленный - медленный
                    //
                    if (otherCdSpeedType == Strings.CollisionDetectionSpeedTypeSlowOrStatic
                        &&
                        thisCdSpeedType == Strings.CollisionDetectionSpeedTypeSlowOrStatic)
                    {
                        return DiscreteCollisionDetection(boundSet);
                    }

                    // быстрый - быстрый
                    //
                    return IntersectFastAndFastBounds(this, boundSet);
                }
                else // непонятно, какой тип - считаем обычными дискретными объектами
                {
                    return DiscreteCollisionDetection(boundSet);
                }

                #region Old
                //ICollection<ICollection<Vector2>> myNotExcludedParts = new LinkedList<ICollection<Vector2>>();
                //ICollection<ICollection<Vector2>> otherNotExcludedParts = new LinkedList<ICollection<Vector2>>();

                //foreach (Triangle<Vector2> stretchedOutlinePart in stretchedOutline)
                //{
                //    // каждый раз получаем массив контуров, из которых состоит разница нового и старого контуров
                //    // stretchedOutline - это набор треугольников, поэтому их разность с исходным контуром не должна, по идее, давать полигоны с дырками
                //    // поэтому каждую полученную часть можно триангулировать

                //    foreach (var triangle in this.Triangulated)
                //    {
                //        // возвращается коллекция полигонов
                //        ICollection<ICollection<Vector2>> differencePart =
                //            WeilerAtherton.Process(
                //                new CircularLinkedList<Vector2>(stretchedOutlinePart),
                //                new CircularLinkedList<Vector2>(previousContour, true),
                //                Operation.Difference);

                //        if (differencePart.Count != 0)
                //            foreach (var part in differencePart)
                //                myNotExcludedParts.Add(part);
                //    }
                //}

                //foreach (Triangle<Vector2> stretchedOutlinePart in boundSet.stretchedOutline)
                //{
                //    // каждый раз получаем массив контуров, из которых состоит разница нового и старого контуров
                //    // stretchedOutline - это набор треугольников, поэтому их разность с исходным контуром не должна, по идее, давать полигоны с дырками
                //    // поэтому каждую полученную часть можно триангулировать

                //    // возвращается коллекция полигонов
                //    ICollection<ICollection<Vector2>> differencePart =
                //        WeilerAtherton.Process(
                //            new CircularLinkedList<Vector2>(stretchedOutlinePart),
                //            new CircularLinkedList<Vector2>(boundSet.previousContour, true),
                //            Operation.Difference);

                //    if (differencePart.Count != 0)
                //        foreach (var part in differencePart)
                //            otherNotExcludedParts.Add(part);

                //}

                ////stretchedOutline - previousContour
                #endregion
            }

            return false;
        }
コード例 #12
0
 public static BoundSetAspect Create(object owner, IList<Vector3> vertices)
 {
     BoundSetAspect aspect = new BoundSetAspect(owner, vertices);
     aspect.RegisterAllStuff();
     aspect.SetAttribute(Strings.CollisionDetectionSpeedType, Strings.CollisionDetectionSpeedTypeSlowOrStatic);
     return aspect;
 }