Пример #1
0
        internal static FormState Load(XElement a_node)
        {
            if (a_node.Name != XML_FORMSTATE)
            {
                throw new Exception();
            }

            return(new FormState()
            {
                m_window_state = (FormWindowState)Enum.Parse(
                    typeof(FormWindowState), a_node.Element(XML_WINDOWSTATE).Value),
                m_bounds = RectangleExtensions.FromXml(a_node.Element(XML_BOUNDS))
            });
        }
Пример #2
0
        /// <summary>
        /// Move this object on it's X-coordinate.
        /// </summary>
        /// <param name="value">Value for this object to move.</param>
        public void MoveX(int value)
        {
            //Padded boundary for safe collision checks on smaller movements.
            var territoryBoundary = new Rectangle((int)X, (int)Y, Boundary.Width + 2, Boundary.Height + 2);

            //Determine if this movement can or cannot be made.
            bool canMoveRight = true;
            bool canMoveLeft  = true;

            //Checks if this object will be prevented by any solid game object neighbors.
            foreach (var no in NeighboringObjects.ToList())
            {
                if (territoryBoundary.Intersects(no.Boundary))
                {
                    var depth = RectangleExtensions.GetIntersectionDepth(territoryBoundary, no.Boundary);

                    if (depth.Y < -8 || depth.Y > 8)
                    {
                        if (depth.X < 0 && depth.X > -8)
                        {
                            canMoveRight = false;
                            OnRightCollided(no, new CollisionEventArgs()
                            {
                                Depth = depth
                            });
                        }
                        if (depth.X > 0 && depth.X < 8)
                        {
                            canMoveLeft = false;
                            OnLeftCollided(no, new CollisionEventArgs()
                            {
                                Depth = depth
                            });
                        }
                    }
                }
            }

            if (value > 0 && canMoveRight)
            {
                X += value;
            }
            if (value < 0 && canMoveLeft)
            {
                X += value;
            }

            VelocityX = value;
        }
Пример #3
0
        /// <param name="celAlphaMasks">Fill with masks created from Cels</param>
        /// <param name="allMasks">Fill with all created masks</param>
        public void RegenerateAlphaMask()
        {
            masks.TryRemoveBaseFallBack(); // <- it is about to be regenerated

            // If this frame has a single sprite-containing Cel, generate it directly
            if (firstLayer != null && firstLayer.next == null)
            {
                Mask mask = new Mask
                {
                    data = firstLayer.spriteRef.ResolveRequire().GetAlphaMask(),
                    isGeneratedAlphaMask = true,
                };

                masks.Add(new TagSet(), mask);
            }
            else // ... Otherwise, try to create a mask merged from the frame's layers
            {
                List <MaskData> layerMasks = new List <MaskData>();
                foreach (var cel in layers)
                {
                    MaskData maskData = cel.spriteRef.ResolveRequire().GetAlphaMask();
                    if (maskData.Width != 0 && maskData.Height != 0)
                    {
                        layerMasks.Add(maskData);
                    }
                }

                Rectangle maxBounds = Rectangle.Empty;
                foreach (var maskData in layerMasks)
                {
                    maxBounds = RectangleExtensions.UnionIgnoreEmpty(maxBounds, maskData.Bounds);
                }

                Mask mask = new Mask()
                {
                    isGeneratedAlphaMask = true
                };
                mask.data = new MaskData(maxBounds);
                foreach (var layerMask in layerMasks)
                {
                    Debug.Assert(!Asserts.enabled || mask.data.Bounds.Contains(layerMask.Bounds));
                    mask.data.SetBitwiseOrFrom(layerMask);
                }

                masks.Add(new TagSet(), mask);
            }
        }
Пример #4
0
        public WorldArea(XmlElement area, XmlNamespaceManager xnm)
        {
            this.Area = RectangleExtensions.GetRectangleFromDefinition(area);

            string worldStart = area.GetAttribute("WorldStart");

            this.IsInitialArea = !string.IsNullOrWhiteSpace(worldStart) && bool.Parse(worldStart);

            var startPos = (XmlElement)area.SelectSingleNode("ns:PlayerStartState", xnm);

            if (startPos != null)
            {
                var pss = PlayerStartState.FromXml(startPos);
                if (!this.Area.ContainsTile(pss.Position))
                {
                    throw new InvalidOperationException("Invalid player start position - co-ordinate is not within the area.");
                }
                this.PlayerStartState = pss;
            }

            var tileDefinitions = area.SelectNodes("ns:TileDefinitions/ns:*", xnm);

            if (tileDefinitions != null)
            {
                var td = TileDefinitionCollection.FromXml(tileDefinitions);
                td.Area = this.Area;
                this.TileDefinitionCollection = td;
            }

            var fruitPopulation = area.SelectNodes("ns:FruitDefinitions/ns:FruitDef", xnm);

            if (fruitPopulation != null)
            {
                var fd = RandomFruitDistribution.FromXml(fruitPopulation);
                fd.Area = this.Area;
                this.FruitDefinitions = fd;
            }

            var randomMonsterDistribution = (XmlElement)area.SelectSingleNode("ns:RandomMonsterDistribution", xnm);

            if (randomMonsterDistribution != null)
            {
                var md = RandomMonsterDistribution.FromXml(randomMonsterDistribution, xnm);
                md.Area = this.Area;
                this.RandomMonsterDistribution = md;
            }
        }
Пример #5
0
        /// <summary>EDITOR ONLY!</summary>
        public Rectangle GetSoftRenderBounds()
        {
            Rectangle output = Rectangle.Empty;

            foreach (var cel in layers)
            {
                if (cel.shadowReceiver != null)
                {
                    continue; // Skip shadow receivers
                }
                Sprite    sprite = cel.spriteRef.ResolveRequire();
                Rectangle bounds = new Rectangle(-sprite.origin.X, -sprite.origin.Y, sprite.sourceRectangle.Width, sprite.sourceRectangle.Height);

                output = RectangleExtensions.UnionIgnoreEmpty(output, bounds);
            }
            return(output);
        }
Пример #6
0
        /// <summary>
        /// Updates neighbor collection and checks for colision.
        /// </summary>
        private void UpdateNeighbors()
        {
            foreach (var gameObject in NeighboringObjects.ToList())
            {
                if (ValidateAsNeighbor(gameObject))
                {
                    var depth         = RectangleExtensions.GetIntersectionDepth(Boundary, gameObject.Boundary);
                    var collisionArgs = new CollisionEventArgs()
                    {
                        Depth = depth
                    };

                    OnCollisionDetected(gameObject, collisionArgs);
                    CheckCollision(gameObject, collisionArgs);
                }
            }
        }
Пример #7
0
        public void Draw(GameTime time, Matrix parent, Rectangle scissor)
        {
            Matrix    transform  = this.Transform * parent;
            Rectangle newScissor = scissor;

            if (this.EnableScissor)
            {
                newScissor = scissor.Intersect(RectangleExtensions.Create(Vector2.Transform(Vector2.Zero, transform), Vector2.Transform(this.Size, transform)));
            }

            if (newScissor.Width > 0 && newScissor.Height > 0)
            {
                if (this.EnableScissor)
                {
                    this.renderer.Batch.End();
                    this.renderer.Batch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.None, this.renderer.RasterizerState, null, Matrix.Identity);
                    this.main.GraphicsDevice.ScissorRectangle = newScissor;
                }

                this.draw(time, parent, transform);
                for (int i = 0; i < this.Children.Count; i++)
                {
                    UIComponent child = this.Children[i];
                    if (child.Visible)
                    {
                        if (this.main.GraphicsDevice.ScissorRectangle != newScissor || child.requiresNewBatch)
                        {
                            this.renderer.Batch.End();
                            this.renderer.Batch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.None, this.renderer.RasterizerState, null, Matrix.Identity);
                            this.main.GraphicsDevice.ScissorRectangle = newScissor;
                        }
                        child.Draw(time, transform, newScissor);
                    }
                }
            }

            if (this.EnableScissor)
            {
                // Restore original scissor
                this.renderer.Batch.End();
                this.renderer.Batch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.None, this.renderer.RasterizerState, null, Matrix.Identity);
                this.main.GraphicsDevice.ScissorRectangle = scissor;
            }
        }
Пример #8
0
        public Rectangle PutNextRectangle(Size rectangleSize)
        {
            if (rectangleSize.Width <= 0 || rectangleSize.Height <= 0)
            {
                throw new ArgumentException("Width and height of the rectangle must be positive");
            }

            Rectangle rectangle;

            do
            {
                var possiblePoint = _spiral.GetNextPoint();
                rectangle = RectangleExtensions.CreateRectangleFromMiddlePointAndSize(possiblePoint, rectangleSize);
            } while (rectangle.IntersectsWith(_rectangles));

            var result = MoveToCanvasCenter(rectangle);

            _rectangles.Add(result);
            return(result);
        }
Пример #9
0
        /// <summary>
        /// Used for the movable platforms to push player
        /// </summary>
        /// <param name="bounds"></param>
        /// <param name="collision"></param>
        /// <param name="tileBounds"></param>
        /// <returns></returns>
        private Rectangle HandleCollision(Rectangle bounds, TileCollision collision, Rectangle tileBounds, Character character)
        {
            Vector2 depth = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds);

            if (depth != Vector2.Zero)
            {
                float absDepthX = Math.Abs(depth.X);
                float absDepthY = Math.Abs(depth.Y);

                // Resolve the collision along the shallow axis.
                if (absDepthY < absDepthX || collision == TileCollision.Platform)
                {
                    // If we crossed the top of a tile, we are on the ground.
                    if (character.previousBottom <= tileBounds.Top)
                    {
                        character.IsOnGround = true;
                    }

                    // Ignore platforms, unless we are on the ground.
                    if (collision == TileCollision.Impassable || character.IsOnGround)
                    {
                        // Resolve the collision along the Y axis.
                        character.Position = new Vector2(character.Position.X, character.Position.Y + depth.Y);

                        // Perform further collisions with the new bounds.
                        bounds = character.BoundingRectangle;
                    }
                }
                else if (collision == TileCollision.Impassable) // Ignore platforms.
                {
                    // Resolve the collision along the X axis.
                    character.Position = new Vector2(character.Position.X + depth.X, character.Position.Y);

                    // Perform further collisions with the new bounds.
                    bounds = character.BoundingRectangle;
                }
            }
            return(bounds);
        }
Пример #10
0
        /// <summary>EDITOR ONLY!</summary>
        public Rectangle GetSoftRenderBounds(bool accountForGameplayMotion)
        {
            Rectangle output            = Rectangle.Empty;
            Position  accumulatedMotion = Position.Zero;

            foreach (var frame in Frames)
            {
                Rectangle bounds = frame.GetSoftRenderBounds();

                if (accountForGameplayMotion)
                {
                    accumulatedMotion += frame.positionDelta;

                    Point offset = accumulatedMotion.ToWorldZero().FlipY(); // Flip because we're outputting in texture space
                    bounds.X += offset.X;
                    bounds.Y += offset.Y;
                }

                output = RectangleExtensions.UnionIgnoreEmpty(output, bounds);
            }
            return(output);
        }
Пример #11
0
        public virtual void HandleCollisions(CVGameTime gameTime)
        {
            if (this.WorldPosition.Y > Game.iScreenModelWidth && IsDying == false)
            {
                Die(gameTime);
            }

            Rectangle actorbounds = this.BoundingBox();

            bool wasonground = this.IsOnGround;

            // get nearest tile below player.
            this.IsOnGround = false;

            int leftTile   = (int)Math.Floor((float)actorbounds.Left / CurrentStage.TileWidth);
            int rightTile  = (int)Math.Ceiling(((float)actorbounds.Right / CurrentStage.TileWidth)) - 1;
            int topTile    = (int)Math.Floor((float)actorbounds.Top / CurrentStage.TileHeight);
            int bottomTile = (int)Math.Ceiling(((float)actorbounds.Bottom / CurrentStage.TileHeight)) - 1;

            // For each potentially colliding platform tile,
            for (int y = topTile; y <= bottomTile; ++y)
            {
                for (int x = leftTile; x <= rightTile; ++x)
                {
                    StageTile stageTile = CurrentStage.getStageTileByGridPosition(x, y);
                    if (stageTile != null)
                    {
                        if (stageTile.IsImpassable())
                        {
                            Rectangle tilebounds = CurrentStage.getTileBoundsByGridPosition(x, y);
                            Vector2   depth      = RectangleExtensions.GetIntersectionDepth(actorbounds, tilebounds);

                            if (actorbounds.Intersects(tilebounds))
                            {
                                WorldPosition = new Vector2(WorldPosition.X + depth.X, WorldPosition.Y);
                                actorbounds   = this.BoundingBox();
                            }
                        }

                        else if (stageTile.IsPlatform() && y == bottomTile)
                        {
                            List <Platform> tileboundsList = CurrentStage.getTilePlatformBoundsByGridPosition(x, bottomTile);
                            foreach (Platform platformbounds in tileboundsList)
                            {
                                Rectangle tilebounds = platformbounds.PlatformBounds;
                                Vector2   depth      = RectangleExtensions.GetIntersectionDepth(actorbounds, tilebounds);


                                if (this.PreviousBottom <= tilebounds.Top && Velocity.Y >= 0 && actorbounds.Intersects(tilebounds))
                                //if (Velocity.Y >= 0 && (depth.Y < 0)) // || this.IgnoreNextPlatform))
                                {
                                    this.IsOnGround     = true;
                                    this.JumpInProgress = false;
                                    //this.Velocity.X = 0f;

                                    this.WorldPosition.Y += depth.Y;
                                    // perform further collisions with the new bounds
                                    actorbounds = this.BoundingBox();
                                }
                            }
                        }
                    }
                }
            }

            if (wasonground && !IsOnGround)
            {
                Velocity.Y = 0;
            }

            this.PreviousBottom = actorbounds.Bottom;
        }
Пример #12
0
        /// <summary>
        /// Detects and resolves all collisions between the character and his neighboring
        /// tiles. When a collision is detected, the character is pushed away along one
        /// axis to prevent overlapping. There is some special logic for the Y axis to
        /// handle platforms which behave differently depending on direction of movement.
        /// </summary>
        public void CharacterAndTiles(Character character)
        {
            // Get the player's bounding rectangle and find neighboring tiles.
            Rectangle bounds     = character.BoundingRectangle;
            int       leftTile   = (int)Math.Floor((float)bounds.Left / LevelTile.Width);
            int       rightTile  = (int)Math.Ceiling(((float)bounds.Right / LevelTile.Width)) - 1;
            int       topTile    = (int)Math.Floor((float)bounds.Top / LevelTile.Height);
            int       bottomTile = (int)Math.Ceiling(((float)bounds.Bottom / LevelTile.Height)) - 1;


            // Reset flag to search for ground collision.
            character.IsOnGround = false;

            //For each potentially colliding movable tile.
            foreach (var movableTile in Statics.Level.TileEngine.movableTiles)
            {
                // Reset flag to search for movable tile collision.
                movableTile.PlayerIsOn = false;

                //check to see if player is on tile.
                if ((character.BoundingRectangle.Bottom == movableTile.BoundingRectangle.Top + 1) &&
                    (character.BoundingRectangle.Left >= movableTile.BoundingRectangle.Left - (character.BoundingRectangle.Width / 2) &&
                     character.BoundingRectangle.Right <= movableTile.BoundingRectangle.Right + (character.BoundingRectangle.Width / 2)))
                {
                    movableTile.PlayerIsOn = true;
                }

                bounds = HandleCollision(bounds, movableTile.Collision, movableTile.BoundingRectangle, character);
            }

            // For each potentially colliding tile,
            for (int y = topTile; y <= bottomTile; ++y)
            {
                for (int x = leftTile; x <= rightTile; ++x)
                {
                    // If this tile is collidable,
                    TileCollision collision = Statics.Level.TileEngine.GetCollision(x, y);
                    if (collision != TileCollision.Passable)
                    {
                        // Determine collision depth (with direction) and magnitude.
                        Rectangle tileBounds = Statics.Level.TileEngine.GetBounds(x, y);
                        Vector2   depth      = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds);

                        if (collision == TileCollision.Spike)
                        {
                            character.Health--;
                        }
                        if (depth != Vector2.Zero)
                        {
                            float absDepthX = Math.Abs(depth.X);
                            float absDepthY = Math.Abs(depth.Y);

                            // Resolve the collision along the shallow axis.
                            if (absDepthY < absDepthX || collision == TileCollision.Platform)
                            {
                                // If we crossed the top of a tile, we are on the ground.
                                if (character.previousBottom <= tileBounds.Top)
                                {
                                    character.IsOnGround = true;
                                }

                                // Ignore platforms, unless we are on the ground.
                                if (collision == TileCollision.Impassable || character.IsOnGround)
                                {
                                    // Resolve the collision along the Y axis.
                                    character.Position = new Vector2(character.Position.X, character.Position.Y + depth.Y);

                                    // Perform further collisions with the new bounds.
                                    bounds = character.BoundingRectangle;
                                }
                            }
                            else if (collision == TileCollision.Impassable || collision == TileCollision.Spike) // Ignore platforms.
                            {
                                float temp;
                                // Resolve the collision along the X axis.
                                if (character.direction == Enums.FaceDirection.Left && character != Statics.LevelPlayer)
                                {
                                    temp = character.Position.X;
                                }
                                else
                                {
                                    temp = character.Position.X + depth.X;
                                }

                                character.Position = new Vector2(temp, character.Position.Y);

                                // Perform further collisions with the new bounds.
                                bounds = character.BoundingRectangle;
                            }
                        }
                    }
                }
            }

            // Save the new bounds bottom.
            character.previousBottom = bounds.Bottom;
        }
Пример #13
0
        /// <summary>
        /// Animates each enemy and allow them to kill the player.
        /// </summary>
        public void PlayerAndEnemy(LevelPlayer player, Character enemy, GameTime gameTime)
        {
            if (player.oneFrame.Intersects(enemy.BoundingRectangle))
            {
                //Enemy will stop walking, if their bounding box intersect with player and they are not doing some speical animation
                if (enemy.SpecialAnimationDone || enemy == Statics.Level.Boss)
                {
                    if (enemy.MoveState != Enums.MoveState.Fall && enemy.MoveState != Enums.MoveState.FireFall && enemy.MoveState != Enums.MoveState.FireReaction)
                    {
                        enemy.movement = 0;
                    }
                }

                // Resolve the collision along the X axis between player and enemy, player is not allow to go through the enemy.
                Vector2 depth = RectangleExtensions.GetIntersectionDepth(player.BoundingRectangle, enemy.BoundingRectangle);
                player.Position = new Vector2(player.Position.X + depth.X, player.Position.Y);

                if (player.MoveState == Enums.MoveState.SpecialCombo)
                {
                    if (enemy == Statics.Level.Boss)
                    {
                        enemy.MoveState = Enums.MoveState.Fall;
                    }
                    else
                    {
                        enemy.MoveState = Enums.MoveState.FireFall;
                    }

                    enemy.SpecialAnimationDone = false;
                    if (!player.AttackOnce)
                    {
                        enemy.Health     -= player.AttackStrength;
                        player.Health    -= 3;
                        player.AttackOnce = true;
                    }
                    player.movement = 0;
                }

                if (PerPixel.Collision(player.oneFrame, player.ColorData, enemy.oneFrame, enemy.ColorData))
                {
                    //Placing this test outside of the Intersects test ensures the player will be capable of damage from every enemy punch
                    //This resolves the problem of only once damage per time the player entered the bounding Rectangle of the enemy.

                    if (!player.AttackOnce &&
                        enemy.MoveState != Enums.MoveState.FinalCombo2 &&
                        (player.ComboCount > 0 ||
                         player.Health <= 0.2 * player.fullHealth))
                    {
                        switch (player.MoveState)
                        {
                        case Enums.MoveState.Punch:
                            enemy.MoveState = Enums.MoveState.Reaction;
                            enemy.Health   -= player.AttackStrength;
                            enemy.hurtCount++;
                            player.CountActions += 6;
                            player.punchHurtCount++;
                            break;

                        case Enums.MoveState.PunchUp:
                            enemy.MoveState      = Enums.MoveState.Fall;
                            enemy.Health        -= player.AttackStrength;
                            enemy.hurtCount     += 2;
                            player.CountActions += 6;
                            break;

                        case Enums.MoveState.Kick:
                            enemy.MoveState = Enums.MoveState.Reaction;
                            enemy.Health   -= player.AttackStrength;
                            enemy.hurtCount++;
                            player.kickHurtCount++;
                            player.CountActions += 10;
                            break;

                        case Enums.MoveState.ComboKick:
                            enemy.MoveState      = Enums.MoveState.Fall;
                            enemy.Health        -= 2 * player.AttackStrength;
                            enemy.hurtCount     += 2;
                            player.CountActions += 20;
                            break;

                        case Enums.MoveState.FirePunch1:
                            enemy.MoveState      = Enums.MoveState.FireReaction;
                            enemy.Health        -= 2 * player.AttackStrength;
                            player.CountActions += 15;
                            break;

                        case Enums.MoveState.FirePunch2:
                            enemy.MoveState      = Enums.MoveState.FireReaction;
                            enemy.Health        -= 2 * player.AttackStrength;
                            player.CountActions += 15;
                            break;

                        case Enums.MoveState.FirePunch3:
                            enemy.MoveState      = Enums.MoveState.FireFall;
                            enemy.Health        -= 2 * player.AttackStrength;
                            player.CountActions += 15;
                            break;

                        case Enums.MoveState.FinalCombo2:
                            enemy.MoveState = Enums.MoveState.FireFall;
                            enemy.Health   -= 4 * player.AttackStrength;
                            player.ComboCount--;
                            break;
                        }

                        enemy.hurtSound.Play();
                        player.AttackOnce          = true;
                        enemy.SpecialAnimationDone = false;
                        HitTime = gameTime.TotalRealTime;
                    }

                    if (!enemy.AttackOnce && player.SpecialAnimationDone)
                    {
                        if (enemy == Statics.Level.Boss)
                        {
                            switch (enemy.MoveState)
                            {
                            case Enums.MoveState.Punch:
                                player.MoveState = Enums.MoveState.Fall;
                                player.Health   -= enemy.AttackStrength;
                                enemy.hitCount++;
                                break;

                            case Enums.MoveState.FinalCombo2:
                                player.MoveState = Enums.MoveState.Fall;
                                player.Health   -= 2 * enemy.AttackStrength;
                                break;
                            }
                        }
                        else
                        {
                            switch (enemy.MoveState)
                            {
                            case Enums.MoveState.FinalCombo1:
                                player.MoveState = Enums.MoveState.Reaction;
                                player.Health   -= enemy.AttackStrength;
                                enemy.hitCount++;
                                break;

                            case Enums.MoveState.FinalCombo2:
                                player.MoveState = Enums.MoveState.Fall;
                                player.Health   -= 2 * enemy.AttackStrength;
                                break;
                            }
                        }

                        player.SpecialAnimationDone = false;
                        enemy.hurtSound.Play();
                        enemy.AttackOnce = true;
                    }
                }
            }
            //If no intersection between player rectangle and enemy rectangle frame
            //Add enemy movement towards player here...
            else
            {
                if (enemy.SpecialAnimationDone)
                {
                    if (enemy == Statics.Level.Boss)
                    {
                        enemy.movement = 200;
                    }
                    else
                    {
                        enemy.movement = 65f;
                    }
                    enemy.MoveState = Enums.MoveState.Walk;
                }
            }
        }
        /// <summary>
        /// Detects and resolves all collisions between the player and his neighboring
        /// tiles. When a collision is detected, the player is pushed away along one
        /// axis to prevent overlapping. There is some special logic for the Y axis to
        /// handle platforms which behave differently depending on direction of movement.
        /// </summary>
        private void HandleCollisions()
        {
            // Get the player's bounding rectangle and find neighboring tiles.
            Rectangle bounds     = BoundingRectangle;
            int       leftTile   = (int)Math.Floor((float)bounds.Left / Tile.Width);
            int       rightTile  = (int)Math.Ceiling(((float)bounds.Right / Tile.Width)) - 1;
            int       topTile    = (int)Math.Floor((float)bounds.Top / Tile.Height);
            int       bottomTile = (int)Math.Ceiling(((float)bounds.Bottom / Tile.Height)) - 1;

            // Reset flag to search for ground collision.
            isOnGround = false;

            // For each potentially colliding tile,
            for (int y = topTile; y <= bottomTile; ++y)
            {
                for (int x = leftTile; x <= rightTile; ++x)
                {
                    // If this tile is collidable,
                    TileCollision collision = Level.GetCollision(x, y);
                    if (collision != TileCollision.Passable)
                    {
                        // Determine collision depth (with direction) and magnitude.
                        Rectangle tileBounds = Level.GetBounds(x, y);
                        Vector2   depth      = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds);
                        if (depth != Vector2.Zero)
                        {
                            float absDepthX = (float)Math.Abs(depth.X);
                            float absDepthY = (float)Math.Abs(depth.Y);

                            // Resolve the collision along the shallow axis.
                            if (absDepthY < absDepthX || collision == TileCollision.Platform)
                            {
                                // If we crossed the top of a tile, we are on the ground.
                                if (previousBottom <= tileBounds.Top)
                                {
                                    isOnGround = true;
                                }

                                // Ignore platforms, unless we are on the ground.
                                if (collision == TileCollision.Impassable || IsOnGround)
                                {
                                    // Resolve the collision along the Y axis.
                                    Position = new Vector2(Position.X, Position.Y + depth.Y);

                                    // Perform further collisions with the new bounds.
                                    bounds = BoundingRectangle;
                                }
                            }
                            else if (collision == TileCollision.Impassable) // Ignore platforms.
                            {
                                // Resolve the collision along the X axis.
                                Position = new Vector2(Position.X + depth.X, Position.Y);

                                // Perform further collisions with the new bounds.
                                bounds = BoundingRectangle;
                            }
                        }
                    }
                }
            }

            // Save the new bounds bottom.
            previousBottom = bounds.Bottom;
        }
Пример #15
0
        /// <summary>
        /// Instantiates a player, puts him in the level, and remembers where to put him when he is resurrected.
        /// </summary>
        private Tile LoadStartTile(int x, int y)
        {
            StartLocation = RectangleExtensions.GetBottomCenter(GetBounds(x, y));

            return(LoadTile("Exit", new Vector2(x, y) * Tile.Size, TileCollision.Passable));
        }