Пример #1
0
        /// <summary>
        /// gets a list of all the tiles intersecting bounds. The returned list is ordered for collision detection based on the
        /// direction passed in so they can be processed in order.
        /// </summary>
        /// <returns>The colliding tiles.</returns>
        /// <param name="bounds">Bounds.</param>
        /// <param name="direction">Direction.</param>
        void populateCollidingTiles(Rectangle bounds, Edge direction)
        {
            _collidingTiles.Clear();
            var isHorizontal = direction.isHorizontal();
            var primaryAxis  = isHorizontal ? Axis.X : Axis.Y;
            var oppositeAxis = primaryAxis == Axis.X ? Axis.Y : Axis.X;

            var oppositeDirection = direction.oppositeEdge();
            var firstPrimary      = worldToTilePosition(bounds.getSide(oppositeDirection), primaryAxis);
            var lastPrimary       = worldToTilePosition(bounds.getSide(direction), primaryAxis);
            var primaryIncr       = direction.isMax() ? 1 : -1;

            var min = worldToTilePosition(isHorizontal ? bounds.Top : bounds.Left, oppositeAxis);
            var mid = worldToTilePosition(isHorizontal ? bounds.getCenter().Y : bounds.getCenter().X, oppositeAxis);
            var max = worldToTilePosition(isHorizontal ? bounds.Bottom : bounds.Right, oppositeAxis);

            var isPositive     = mid - min < max - mid;
            var secondaryIncr  = isPositive ? 1 : -1;
            var firstSecondary = isPositive ? min : max;
            var lastSecondary  = !isPositive ? min : max;

            for (var primary = firstPrimary; primary != lastPrimary + primaryIncr; primary += primaryIncr)
            {
                for (var secondary = firstSecondary;
                     secondary != lastSecondary + secondaryIncr;
                     secondary += secondaryIncr)
                {
                    var col = isHorizontal ? primary : secondary;
                    var row = !isHorizontal ? primary : secondary;
                    _collidingTiles.Add(collisionLayer.getTile(col, row));

#if DEBUG_MOVER
                    if (direction.isHorizontal())
                    {
                        var pos = tiledMap.tileToWorldPosition(new Point(col, row));
                        _debugTiles.Add(new Rectangle((int)pos.X, (int)pos.Y, 16, 16));
                    }
                                        #endif
                }
            }
        }
Пример #2
0
        public override void draw(Batcher batcher, Vector2 position, float layerDepth, RectangleF cameraClipBounds)
        {
            // offset it by the entity position since the tilemap will always expect positions in its own coordinate space
            cameraClipBounds.location -= (position + offset);

            int minX, minY, maxX, maxY;

            if (tiledMap.requiresLargeTileCulling)
            {
                // we expand our cameraClipBounds by the excess tile width/height of the largest tiles to ensure we include tiles whose
                // origin might be outside of the cameraClipBounds
                minX = tiledMap.worldToTilePositionX(cameraClipBounds.left - (tiledMap.largestTileWidth - tiledMap.tileWidth));
                minY = tiledMap.worldToTilePositionY(cameraClipBounds.top - (tiledMap.largestTileHeight - tiledMap.tileHeight));
                maxX = tiledMap.worldToTilePositionX(cameraClipBounds.right + (tiledMap.largestTileWidth - tiledMap.tileWidth));
                maxY = tiledMap.worldToTilePositionY(cameraClipBounds.bottom + (tiledMap.largestTileHeight - tiledMap.tileHeight));
            }
            else
            {
                minX = tiledMap.worldToTilePositionX(cameraClipBounds.left);
                minY = tiledMap.worldToTilePositionY(cameraClipBounds.top);
                maxX = tiledMap.worldToTilePositionX(cameraClipBounds.right);
                maxY = tiledMap.worldToTilePositionY(cameraClipBounds.bottom);
            }

            // loop through and draw all the non-culled tiles
            for (var y = minY; y <= maxY; y++)
            {
                for (var x = minX; x <= maxX; x++)
                {
                    var tile = getTile(x, y);
                    if (tile == null)
                    {
                        continue;
                    }

                    var tileRegion = tile.textureRegion;

                    // culling for arbitrary size tiles if necessary
                    if (tiledMap.requiresLargeTileCulling)
                    {
                        // TODO: this only checks left and bottom. we should check top and right as well to deal with rotated, odd-sized tiles
                        var tileworldpos = tiledMap.tileToWorldPosition(new Point(x, y));
                        if (tileworldpos.X + tileRegion.sourceRect.Width < cameraClipBounds.left || tileworldpos.Y - tileRegion.sourceRect.Height > cameraClipBounds.bottom)
                        {
                            continue;
                        }
                    }

                    // for the y position, we need to take into account if the tile is larger than the tileHeight and shift. Tiled uses
                    // a bottom-left coordinate system and MonoGame a top-left
                    var tx       = tile.x * tiledMap.tileWidth + (int)position.X;
                    var ty       = tile.y * tiledMap.tileHeight + (int)position.Y;
                    var rotation = 0f;

                    var spriteEffects = SpriteEffects.None;
                    if (tile.flippedHorizonally)
                    {
                        spriteEffects |= SpriteEffects.FlipHorizontally;
                    }
                    if (tile.flippedVertically)
                    {
                        spriteEffects |= SpriteEffects.FlipVertically;
                    }
                    if (tile.flippedDiagonally)
                    {
                        if (tile.flippedHorizonally && tile.flippedVertically)
                        {
                            spriteEffects ^= SpriteEffects.FlipVertically;
                            rotation       = MathHelper.PiOver2;
                            tx            += tiledMap.tileHeight + (tileRegion.sourceRect.Height - tiledMap.tileHeight);
                            ty            -= (tileRegion.sourceRect.Width - tiledMap.tileWidth);
                        }
                        else if (tile.flippedHorizonally)
                        {
                            spriteEffects ^= SpriteEffects.FlipVertically;
                            rotation       = -MathHelper.PiOver2;
                            ty            += tiledMap.tileHeight;
                        }
                        else if (tile.flippedVertically)
                        {
                            spriteEffects ^= SpriteEffects.FlipHorizontally;
                            rotation       = MathHelper.PiOver2;
                            tx            += tiledMap.tileWidth + (tileRegion.sourceRect.Height - tiledMap.tileHeight);
                            ty            += (tiledMap.tileWidth - tileRegion.sourceRect.Width);
                        }
                        else
                        {
                            spriteEffects ^= SpriteEffects.FlipHorizontally;
                            rotation       = -MathHelper.PiOver2;
                            ty            += tiledMap.tileHeight;
                        }
                    }

                    // if we had no rotations (diagonal flipping) shift our y-coord to account for any non-tileSized tiles to account for
                    // Tiled being bottom-left origin
                    if (rotation == 0)
                    {
                        ty += (tiledMap.tileHeight - tileRegion.sourceRect.Height);
                    }

                    batcher.draw(tileRegion, new Vector2(tx, ty) + offset, color, rotation, Vector2.Zero, 1 + _flickerFix, spriteEffects, layerDepth);
                }
            }
        }