예제 #1
0
        /// <summary>
        /// Processes the geometry layer, creating the game representation.
        /// </summary>
        /// <param name="rawLayer">The layer.</param>
        /// <param name="map">The map.</param>
        /// <param name="tileDefinitions">A global dictionary of all tile definitions.</param>
        /// <returns>
        /// An instance of a new <see cref="GeometryTileLayer" />.
        /// </returns>
        private void ProcessGeometryLayer(TmxLayer rawLayer, GeometryTileLayer layer, Map map, IDictionary <int, TileDefinition> tileDefinitions)
        {
            if (rawLayer == null)
            {
                throw new ArgumentNullException(nameof(rawLayer));
            }

            if (layer == null)
            {
                throw new ArgumentNullException(nameof(layer));
            }

            if (map == null)
            {
                throw new ArgumentNullException(nameof(map));
            }

            if (tileDefinitions == null)
            {
                throw new ArgumentNullException(nameof(tileDefinitions));
            }

            TraceSource.TraceEvent(TraceEventType.Verbose, 0, $"Processing layer {rawLayer.Name}");

            var tiles = new List <GeometryTile>();

            foreach (var tile in rawLayer.Tiles)
            {
                if (tile.Gid != 0)
                {
                    var geoTile = new GeometryTile();
                    geoTile.GridPosition  = new Int32Point(tile.X, tile.Y);
                    geoTile.WorldPosition = new Int32Point(tile.X * map.GeometryTileWidth, tile.Y * map.GeometryTileHeight);
                    geoTile.Definition    = tileDefinitions[tile.Gid];
                    geoTile.DefinitionId  = tile.Gid;
                    tiles.Add(geoTile);
                }
            }

            layer.SetTiles(tiles);
        }
예제 #2
0
        /// <summary>
        /// Determines whether a
        /// </summary>
        /// <param name="x">The x coordinate.</param>
        /// <param name="y">The y coordinate.</param>
        /// <param name="lastTile">The last tile hit.</param>
        /// <param name="trace">The trace line parameters.</param>
        /// <param name="hitTile">The tile that was hit.</param>
        /// <returns>
        ///   <c>true</c> if point is on a solid tile; otherwise, <c>false</c>.
        /// </returns>
        private bool IsPointOnSolidTile(int x, int y, GeometryTile lastTile, TraceQuery trace, out GeometryTile hitTile)
        {
            hitTile = null;
            bool hit = false;

            var map = _mapService.CurrentMap;

            if (map == null)
            {
                return(hit);
            }

            var tileCol = (int)Math.Floor((double)x / map.GeometryTileWidth);
            var tileRow = (int)Math.Floor((double)y / map.GeometryTileHeight);

            if ((tileCol < 0) || (tileRow < 0))
            {
                return(hit);
            }

            for (var i = 0; i < map.CollisionLayers.Length; i++)
            {
                var layer = map.CollisionLayers[i];

                // if the trace has specific a collision path, ignore layers that are not on the path
                if (trace.CollisionPath != null)
                {
                    if ((layer.CollisionPath != null) && (layer.CollisionPath != trace.CollisionPath))
                    {
                        continue;
                    }
                }

                var tile = layer.GetTile(tileCol, tileRow);

                if (tile != null)
                {
                    // solidity filters
                    if (
                        (tile.Definition.SolidType == SolidType.None) &&
                        ((trace.Options & TraceLineOptions.SolidOnly) > TraceLineOptions.None))
                    {
                        continue;
                    }

                    if (
                        (tile.Definition.SolidType == SolidType.JumpThrough) &&
                        ((trace.Options & TraceLineOptions.IgnoreJumpThrough) > TraceLineOptions.None))
                    {
                        continue;
                    }

                    var collisionMap = tile.Definition.CollisionMap;
                    if (collisionMap != null)
                    {
                        var localX = x - tile.WorldPosition.X;
                        var localY = y - tile.WorldPosition.Y;

                        if (!hit)
                        {
                            if (collisionMap[localX, localY])
                            {
                                hitTile = tile;
                                hit     = true;
                            }
                        }
                    }

                    if (hit)
                    {
                        if (_varShowTracelines.Value)
                        {
                            if ((lastTile == null) || (lastTile.GridPosition.X != tile.GridPosition.X) || (lastTile.GridPosition.Y != tile.GridPosition.Y))
                            {
                                _renderService.HighlightGeometryTile(tileCol, tileRow, 0, 255, 0, 0);
                            }
                        }
                    }
                }
            }

            return(hit);
        }
예제 #3
0
        /// <summary>
        /// Fires a traceline and collects collision information.
        /// </summary>
        /// <param name="trace">Object containing the trace line parameters.</param>
        /// <returns>
        /// A value containing the result of the trace.
        /// </returns>
        public TraceResult TraceLine(TraceQuery trace)
        {
            double            x0, y0, x1, y1;
            List <GameEntity> entities = _entListPool.GetObject();

            x0 = trace.Line.Start.X;
            y0 = trace.Line.Start.Y;
            x1 = trace.Line.End.X;
            y1 = trace.Line.End.Y;

            if ((trace.Options & TraceLineOptions.IgnoreEntities) == TraceLineOptions.None)
            {
                GetPossibleCollidersForTraceline(trace, entities);
            }

            var dx = Math.Abs(x1 - x0);
            var dy = Math.Abs(y1 - y0);

            int x = (int)Math.Floor(x0);
            int y = (int)Math.Floor(y0);

            int    n = 1;
            int    x_inc, y_inc;
            double error = 0.0D;

            if (dx == 0)
            {
                x_inc = 0;
                error = double.MaxValue;
            }
            else if (x1 > x0)
            {
                x_inc = 1;
                n    += (int)Math.Floor(x1) - x;
                error = (Math.Floor(x0) + 1 - x0) * dy;
            }
            else
            {
                x_inc = -1;
                n    += x - (int)Math.Floor(x1);
                error = (x0 - Math.Floor(x0)) * dy;
            }

            if (dy == 0)
            {
                y_inc  = 0;
                error -= double.MaxValue;
            }
            else if (y1 > y0)
            {
                y_inc  = 1;
                n     += (int)Math.Floor(y1) - y;
                error -= (Math.Floor(y0) + 1 - y0) * dx;
            }
            else
            {
                y_inc  = -1;
                n     += y - (int)Math.Floor(y1);
                error -= (y0 - Math.Floor(y0)) * dx;
            }

            var          hit    = false;
            GeometryTile tile   = null;
            GameEntity   entity = null;

            for (; n > 0; --n)
            {
                // visit
                if (entities.Count > 0)
                {
                    hit = IsPointInEntity(entities, x, y, trace, out entity);
                }

                if (!hit && ((trace.Options & TraceLineOptions.IgnoreTiles) == TraceLineOptions.None))
                {
                    hit = IsPointOnSolidTile(x, y, tile, trace, out tile);
                }

                if (hit)
                {
                    break;
                }

                if (error > 0)
                {
                    y     += y_inc;
                    error -= dx;
                }
                else
                {
                    x     += x_inc;
                    error += dy;
                }
            }

            if (_varShowTracelines.Value)
            {
                if (hit)
                {
                    _renderService.DrawLine(new Line(trace.Line.Start.X, trace.Line.Start.Y, x, y), 0);
                    _renderService.DrawLine(new Line(x, y, trace.Line.End.X, trace.Line.End.Y), 0, 0, 255, 0);
                }
                else
                {
                    _renderService.DrawLine(trace.Line, 0);
                }
            }

            entities.Clear();
            _entListPool.PutObject(entities);

            var retval = new TraceResult();

            retval.Hit          = hit;
            retval.ContactPoint = new Point(x, y);
            retval.Entity       = entity;
            retval.Tile         = tile;
            return(retval);
        }