Exemplo n.º 1
0
 public CollisionRule(PhysicalObject obj, CollisionAction action, Action <PhysicalObject> method = null)
 {
     Type   = CollisionRuleType.Object;
     Target = obj;
     Action = action;
     Method = method;
 }
Exemplo n.º 2
0
        public List <PhysicalObject> GetCollisionCandidates(PhysicalObject obj)
        {
            List <PhysicalObject> targets = new List <PhysicalObject>(Objects);

            //check in the child trees this object overlaps with
            if (Children[0] != null)
            {
                bool[] fits = FitObject(obj);
                if (fits[0])
                {
                    targets.AddRange(Children[0].GetCollisionCandidates(obj));
                }
                if (fits[1])
                {
                    targets.AddRange(Children[1].GetCollisionCandidates(obj));
                }
                if (fits[2])
                {
                    targets.AddRange(Children[2].GetCollisionCandidates(obj));
                }
                if (fits[3])
                {
                    targets.AddRange(Children[3].GetCollisionCandidates(obj));
                }
            }

            targets.Remove(obj);

            return(targets);
        }
Exemplo n.º 3
0
 public CollisionRule(PhysicalObject obj, CollisionAction action, Action<PhysicalObject> method = null)
 {
     Type = CollisionRuleType.Object;
     Target = obj;
     Action = action;
     Method = method;
 }
Exemplo n.º 4
0
        /// <summary>
        /// Returns the childtrees the given object fits in.
        /// 0-3, left-to-right, top-to-bottom.
        /// 4 is true when the object doesn't fit in just one quadrant.
        /// </summary>
        private bool[] FitObject(PhysicalObject obj)
        {
            bool[] fits      = new bool[5];
            byte   quadrants = 0;

            if (obj.CoverableArea.Position.X <= Center.X)
            {
                if (obj.CoverableArea.Position.Y <= Center.Y)
                {
                    fits[0] = true;
                    quadrants++;
                }
                if (obj.CoverableArea.Position2.Y >= Center.Y)
                {
                    fits[2] = true;
                    quadrants++;
                }
            }
            if (obj.CoverableArea.Position2.X >= Center.X)
            {
                if (obj.CoverableArea.Position.Y <= Center.Y)
                {
                    fits[1] = true;
                    quadrants++;
                }
                if (obj.CoverableArea.Position2.Y >= Center.Y)
                {
                    fits[3] = true;
                    quadrants++;
                }
            }

            if (quadrants > 1)
            {
                fits[4] = true;
            }

            return(fits);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Performs the calculated collision.
        /// pair determines whether both object's involved (if they are) will be performed, second one will be called with false to prevent loopdeeloops.
        /// </summary>
        internal void PerformClosestCollision(bool pair = true)
        {
            //what do you mean perform?
            if (SpeedLeft == 0f)
            {
                return;
            }

            //if no collision was found move the remaining distance
            if (ClosestCollisionSpeedFraction == float.PositiveInfinity)
            {
                Position += Speed * SpeedLeft;
                SpeedLeft = 0f;
                return;
            }

            //move to touching point
            Position  += Speed * ClosestCollisionSpeedFraction;
            SpeedLeft -= ClosestCollisionSpeedFraction;

            switch (ClosestCollisionRule.Action)
            {
            case CollisionAction.Block:
                Speed     = 0f;
                SpeedLeft = 0f;
                break;

            case CollisionAction.Bounce:
                float speedDirection  = SpeedDirection;
                float angleDifference = Misc.GetRelativeAngle(ClosestCollisionRelativeSpeed.GetAngleFromOrigin(), speedDirection);

                //prevent from bouncing if it is getting hit from around the side or back (another object just hit this one)
                if (angleDifference > -60f && angleDifference < 60f)
                {
                    SpeedDirection = speedDirection - 180f + (ClosestCollisionTouchingAxis.GetAngleFromOrigin() - speedDirection - 90f) * 2;
                }
                break;
            }

            ClosestCollisionRule.CallMethod(ClosestCollisionMethodArg);

            if (ClosestCollisionRule.DeactivateAfterCollision)
            {
                ClosestCollisionRule.Active = false;
            }

            //make sure the other object (if any) performs his collision too before it gets rechecked
            if (pair && (ClosestCollisionRule.Type == CollisionRuleType.Object ||
                         ClosestCollisionRule.Type == CollisionRuleType.Objectmap ||
                         ClosestCollisionRule.Type == CollisionRuleType.ObjectType))
            {
                //do not blindly assume the other object will collide against this one as well
                PhysicalObject otherObj = ((PhysicalObject)ClosestCollisionMethodArg);
                if (otherObj.ClosestCollisionRule != null &&
                    (otherObj.ClosestCollisionRule.Type == CollisionRuleType.Object ||
                     otherObj.ClosestCollisionRule.Type == CollisionRuleType.Objectmap ||
                     otherObj.ClosestCollisionRule.Type == CollisionRuleType.ObjectType) &&
                    otherObj.ClosestCollisionMethodArg == this)
                {
                    otherObj.PerformClosestCollision(false);
                }
            }
        }
Exemplo n.º 6
0
        private static void Step()
        {
            //push input state
            Input.PushState();

            //process all SDL events
            SDL.Event e;
            while (SDL.PollEvent(out e) == 1)
            {
                switch (e.type)
                {
                //let Input handle input related events
                case SDL.EventType.MOUSEBUTTONDOWN:
                case SDL.EventType.MOUSEBUTTONUP:
                case SDL.EventType.MOUSEWHEEL:
                case SDL.EventType.MOUSEMOTION:
                case SDL.EventType.KEYDOWN:
                case SDL.EventType.KEYUP:
                case SDL.EventType.TEXTINPUT:
                case SDL.EventType.CONTROLLERDEVICEADDED:
                case SDL.EventType.CONTROLLERDEVICEREMOVED:
                case SDL.EventType.CONTROLLERBUTTONDOWN:
                case SDL.EventType.CONTROLLERBUTTONUP:
                case SDL.EventType.CONTROLLERAXISMOTION:
                    Input.InputEvent(e);
                    break;

                //let Window handle window related events
                case SDL.EventType.WINDOWEVENT:
                    Window.WindowEvent(e);
                    break;

                //global quit, not only the window's exit button
                case SDL.EventType.QUIT:
                    Exit();
                    break;
                }
            }

            Input.UpdateMousePosition();
            Input.ApplyButtonMaps();

            //update the weakreferences if they still exist
            Resources.UpdateManagedSprites();

            foreach (LogicalObject obj in Resources.Objects)
            {
                if (!obj.Destroyed)
                {
                    obj.Step();
                }
            }

            //collision time!
            float minX = float.PositiveInfinity;
            float minY = float.PositiveInfinity;
            float maxX = float.NegativeInfinity;
            float maxY = float.NegativeInfinity;

            foreach (PhysicalObject obj in Resources.PhysicalObjects)
            {
                obj.UpdateCoverableArea();

                if (obj.CoverableArea.Position.X < minX)
                {
                    minX = obj.CoverableArea.Position.X;
                }
                if (obj.CoverableArea.Position2.X > maxX)
                {
                    maxX = obj.CoverableArea.Position2.X;
                }
                if (obj.CoverableArea.Position.Y < minY)
                {
                    minY = obj.CoverableArea.Position.Y;
                }
                if (obj.CoverableArea.Position2.Y > maxY)
                {
                    maxY = obj.CoverableArea.Position2.Y;
                }

                //set before the actual collision check phase
                obj.SpeedLeft           = 1f;
                obj.CollisionCandidates = null;
            }

            //create and fill quadtree for this step
            QuadTree = new QuadTree(new Rectangle(minX, minY, maxX - minX, maxY - minY));

            //create list of objects to process and calculate all first collision speedfractions for those objects
            List <PhysicalObject> processingObjects = new List <PhysicalObject>(Resources.PhysicalObjects);

            foreach (PhysicalObject obj in Resources.PhysicalObjects)
            {
                if (obj.Speed == Point.Zero)
                {
                    continue;
                }

                processingObjects.Add(obj);
                obj.CalculateClosestCollision();
            }

            while (processingObjects.Count > 0)
            {
                //get closest collision, process it/the pair of objects
                PhysicalObject obj = processingObjects.MinBy(o => o.ClosestCollisionSpeedFraction + 1 - o.SpeedLeft);

                obj.PerformClosestCollision();

                //remove/recalculate collisions
                if (obj.SpeedLeft == 0f)
                {
                    processingObjects.Remove(obj);
                }
                else
                {
                    obj.CalculateClosestCollision();
                }

                //recalculate for all possibly influenced objects (if needed)
                if (obj.CollisionCandidates != null)
                {
                    foreach (PhysicalObject influencedObj in obj.CollisionCandidates)
                    {
                        influencedObj.CalculateClosestCollision();
                    }
                }
            }

            Resources.ObjectAdditionAndRemoval();
            Resources.CleanupFontTextures();
        }
Exemplo n.º 7
0
        public List<PhysicalObject> GetCollisionCandidates(PhysicalObject obj)
        {
            List<PhysicalObject> targets = new List<PhysicalObject>(_objects);

            //check in the child trees this object overlaps with
            if (_children[0] != null)
            {
                bool[] fits = FitObject(obj);
                if (fits[0])
                    targets.AddRange(_children[0].GetCollisionCandidates(obj));
                if (fits[1])
                    targets.AddRange(_children[1].GetCollisionCandidates(obj));
                if (fits[2])
                    targets.AddRange(_children[2].GetCollisionCandidates(obj));
                if (fits[3])
                    targets.AddRange(_children[3].GetCollisionCandidates(obj));
            }

            targets.Remove(obj);

            return targets;
        }
Exemplo n.º 8
0
        /// <summary>
        /// Returns the childtrees the given object fits in.
        /// 0-3, left-to-right, top-to-bottom.
        /// 4 is true when the object doesn't fit in just one quadrant.
        /// </summary>
        private bool[] FitObject(PhysicalObject obj)
        {
            bool[] fits = new bool[5];
            byte quadrants = 0;

            if (obj.CoverableArea.Position.X <= _center.X)
            {
                if (obj.CoverableArea.Position.Y <= _center.Y)
                {
                    fits[0] = true;
                    quadrants++;
                }
                if (obj.CoverableArea.Position2.Y >= _center.Y)
                {
                    fits[2] = true;
                    quadrants++;
                }
            }
            if (obj.CoverableArea.Position2.X >= _center.X)
            {
                if (obj.CoverableArea.Position.Y <= _center.Y)
                {
                    fits[1] = true;
                    quadrants++;
                }
                if (obj.CoverableArea.Position2.Y >= _center.Y)
                {
                    fits[3] = true;
                    quadrants++;
                }
            }

            if (quadrants > 1)
                fits[4] = true;

            return fits;
        }