Пример #1
0
        public static List <AbstractGameObject> ProcessFrame(GameTime gameTime, List <AbstractGameObject> collidables, GameGrid grid)
        {
            float percentCompleted = 0;
            List <Tuple <float, Side, AbstractGameObject, AbstractGameObject> > completedCollisions
                = new List <Tuple <float, Side, AbstractGameObject, AbstractGameObject> >();
            List <AbstractGameObject> removedGameObjects = new List <AbstractGameObject>();

            while (percentCompleted < 1)
            {
                List <AbstractGameObject> neighbours = new List <AbstractGameObject>();
                List <Tuple <float, Side, AbstractGameObject, AbstractGameObject> > collisions
                    = new List <Tuple <float, Side, AbstractGameObject, AbstractGameObject> >();

                foreach (AbstractGameObject obj in collidables)
                {
                    if (obj.BoundingBox == null)
                    {
                        continue;
                    }
                    neighbours = grid.FindNeighbours(obj);
                    foreach (AbstractGameObject neighbour in neighbours)
                    {
                        if (neighbour.BoundingBox == null)
                        {
                            continue;
                        }

                        if (collided(obj, neighbour))
                        {
                            Side  side    = Side.None;
                            float percent = WhenCollisionCheck(obj, neighbour, percentCompleted, out side);

                            if (!(obj is AbstractBlock && neighbour is AbstractBlock))
                            {
                                if (!(obj is Mario && neighbour is HiddenBrickObject) ||
                                    ((obj is Mario && neighbour is HiddenBrickObject) && !neighbour.Visible &&
                                     obj.BoundingBox.Dimensions.Top >= neighbour.BoundingBox.Dimensions.Bottom))
                                {
                                    collisions.Add(new Tuple <float, Side, AbstractGameObject, AbstractGameObject>(percent, side, obj, neighbour));
                                }
                                else if ((obj is HiddenBrickObject && obj.Visible) || (neighbour is HiddenBrickObject && neighbour.Visible))
                                {
                                    collisions.Add(new Tuple <float, Side, AbstractGameObject, AbstractGameObject>(percent, side, obj, neighbour));
                                }
                            }
                        }
                    }
                }

                float earliestCollisionPercent;
                if (collisions.Count == 0)
                {
                    earliestCollisionPercent = 1;
                }
                else
                {
                    collisions.Sort((x, y) => (x.Item1.CompareTo(y.Item1)));
                    filterCollisions(completedCollisions, collisions, out earliestCollisionPercent);
                }

                if ((earliestCollisionPercent - percentCompleted) != 0)
                {
                    int numRemoved = 1;
                    while (numRemoved != 0)
                    {
                        removedGameObjects.AddRange(UpdateObjects(collidables, grid, gameTime, earliestCollisionPercent - percentCompleted));
                        percentCompleted += (earliestCollisionPercent - percentCompleted);
                        collidables.RemoveAll((x) => removedGameObjects.Contains(x));

                        numRemoved = collisions.RemoveAll((x) => (removedGameObjects.Contains(x.Item3) || removedGameObjects.Contains(x.Item4)));
                        filterCollisions(completedCollisions, collisions, out earliestCollisionPercent);
                        collisions.Sort((x, y) => (x.Item1.CompareTo(y.Item1)));
                    }
                }

                bool anySignificantCollision = false;
                for (int i = 0; i < collisions.Count && collisions[i].Item1 == earliestCollisionPercent; i++)
                {
                    Tuple <float, Side, AbstractGameObject, AbstractGameObject> collision = collisions[i];
                    Side side = collision.Item2;
                    AbstractGameObject obj1 = collision.Item3;
                    AbstractGameObject obj2 = collision.Item4;


                    anySignificantCollision = true;

                    if (obj2 is Mario)
                    {
                        obj2.CollisionResponse(obj1, GetOppositeSide(side), gameTime);
                        obj1.CollisionResponse(obj2, side, gameTime);
                    }
                    else
                    {
                        obj1.CollisionResponse(obj2, side, gameTime);
                        obj2.CollisionResponse(obj1, GetOppositeSide(side), gameTime);
                    }

                    if (obj1.BoundingBox != null)
                    {
                        if ((obj2.BoundingBox != null) &&
                            !(obj1 is AbstractBlock || obj1 is CoinObject || obj1 is FireFlowerObject) &&
                            (obj2 is AbstractEnemy || (obj2 is AbstractBlock && obj2.Visible)))
                        {
                            if (RectangleSidesTouching(obj1.BoundingBox.Dimensions, obj2.BoundingBox.Dimensions) ||
                                obj1.BoundingBox.Dimensions.Intersects(obj2.BoundingBox.Dimensions))
                            {
                                obj1.FixClipping(FindClippingCorrection(obj1, obj2), obj1, obj2);
                            }
                        }
                    }

                    if (obj2.BoundingBox != null)
                    {
                        if ((obj1.BoundingBox != null) &&
                            !(obj2 is AbstractBlock || obj2 is CoinObject || obj2 is FireFlowerObject) &&
                            (obj1 is AbstractEnemy || (obj1 is AbstractBlock && obj1.Visible)))
                        {
                            if (RectangleSidesTouching(obj2.BoundingBox.Dimensions, obj1.BoundingBox.Dimensions) ||
                                (obj2.BoundingBox.Dimensions.Intersects(obj1.BoundingBox.Dimensions)))
                            {
                                obj2.FixClipping(FindClippingCorrection(obj2, obj1), obj1, obj2);
                            }
                        }
                    }

                    completedCollisions.Add(collision);
                }

                if (!anySignificantCollision && !(earliestCollisionPercent == 1))
                {
                    earliestCollisionPercent = 1;
                    removedGameObjects.AddRange(UpdateObjects(collidables, grid, gameTime, earliestCollisionPercent - percentCompleted));
                    collidables.RemoveAll((x) => removedGameObjects.Contains(x));
                }
                percentCompleted += (earliestCollisionPercent - percentCompleted);
            }

            return(removedGameObjects);
        }
Пример #2
0
        private static List <AbstractGameObject> UpdateObjects(List <AbstractGameObject> objects, GameGrid grid,
                                                               GameTime gameTime, float percentToUpdate)
        {
            var removed = new List <AbstractGameObject>();

            foreach (AbstractGameObject obj in objects)
            {
                HitBox oldHitbox = (obj.BoundingBox != null) ? new HitBox(obj.BoundingBox) : null;
                if (obj.Update(gameTime, percentToUpdate))
                {
                    removed.Add(obj);
                }

                if (oldHitbox != null && obj.BoundingBox != null)
                {
                    grid.UpdateObjectGridPosition(obj, oldHitbox);
                }
            }

            return(removed);
        }