コード例 #1
0
ファイル: SfmlExt.cs プロジェクト: oldbean/space-station-14
        public static IntRect Round(this FloatRect rect)
        {
            var top    = (int)Math.Round(rect.Top);
            var left   = (int)Math.Round(rect.Left);
            var right  = (int)Math.Round(rect.Right());
            var bottom = (int)Math.Round(rect.Bottom());

            return(new IntRect(left, top, right - left, bottom - top));
        }
コード例 #2
0
        /// <summary>
        /// returns true if collider intersects a collidable under management. Does not trigger Bump.
        /// </summary>
        /// <param name="collider">Rectangle to check for collision</param>
        /// <returns></returns>
        public bool IsColliding(FloatRect collider)
        {
            Vector2f[] points =
            {
                new Vector2f(collider.Left,    collider.Top),
                new Vector2f(collider.Right(), collider.Top),
                new Vector2f(collider.Right(), collider.Bottom()),
                new Vector2f(collider.Left,    collider.Bottom())
            };

            //Get the buckets that correspond to the collider's points.
            List <CollidableBucket> buckets = points.Select(GetBucket).Distinct().ToList();

            //Get all of the points
            var cpoints = new List <CollidablePoint>();

            foreach (CollidableBucket bucket in buckets)
            {
                cpoints.AddRange(bucket.GetPoints());
            }

            //Expand points to distinct AABBs
            List <CollidableAABB> aabBs = (cpoints.Select(cp => cp.ParentAABB)).Distinct().ToList();

            //try all of the AABBs against the target rect.
            bool collided = false;

            foreach (CollidableAABB aabb in aabBs.Where(aabb => aabb.Collidable.AABB.Intersects(collider)))
            {
                if (aabb.IsHardCollider) //If the collider is supposed to prevent movement
                {
                    collided = true;
                }
            }

            return(collided || IoCManager.Resolve <IMapManager>().GetTilesIntersecting(collider, true).Any(t => t.Tile.TileDef.IsCollidable));
        }
コード例 #3
0
ファイル: MapManager.cs プロジェクト: rouge/space-station-14
        // If `ignoreSpace` is false, this will return tiles in chunks that don't even exist.
        // This is to make the tile count predictable.  Is this appropriate behavior?
        public IEnumerable <TileRef> GetTilesIntersecting(FloatRect area, bool ignoreSpace)
        {
            int chunkLeft   = (int)Math.Floor(area.Left / ChunkSize);
            int chunkTop    = (int)Math.Floor(area.Top / ChunkSize);
            int chunkRight  = (int)Math.Floor(area.Right() / ChunkSize);
            int chunkBottom = (int)Math.Floor(area.Bottom() / ChunkSize);

            for (int chunkY = chunkTop; chunkY <= chunkBottom; ++chunkY)
            {
                for (int chunkX = chunkLeft; chunkX <= chunkRight; ++chunkX)
                {
                    int xMin = 0;
                    int yMin = 0;
                    int xMax = 15;
                    int yMax = 15;

                    if (chunkX == chunkLeft)
                    {
                        xMin = Mod(Math.Floor(area.Left), ChunkSize);
                    }
                    if (chunkY == chunkTop)
                    {
                        yMin = Mod(Math.Floor(area.Top), ChunkSize);
                    }

                    if (chunkX == chunkRight)
                    {
                        xMax = Mod(Math.Floor(area.Right()), ChunkSize);
                    }
                    if (chunkY == chunkBottom)
                    {
                        yMax = Mod(Math.Floor(area.Bottom()), ChunkSize);
                    }

                    Chunk chunk;
                    if (!chunks.TryGetValue(new Vector2i(chunkX, chunkY), out chunk))
                    {
                        if (ignoreSpace)
                        {
                            continue;
                        }
                        else
                        {
                            for (int y = yMin; y <= yMax; ++y)
                            {
                                for (int x = xMin; x <= xMax; ++x)
                                {
                                    yield return(new TileRef(this,
                                                             chunkX * ChunkSize + x,
                                                             chunkY * ChunkSize + y));
                                }
                            }
                        }
                    }
                    else
                    {
                        for (int y = yMin; y <= yMax; ++y)
                        {
                            int i = y * ChunkSize + xMin;
                            for (int x = xMin; x <= xMax; ++x, ++i)
                            {
                                if (!ignoreSpace || chunk.Tiles[i].TileId != 0)
                                {
                                    yield return(new TileRef(this,
                                                             chunkX * ChunkSize + x,
                                                             chunkY * ChunkSize + y,
                                                             chunk, i));
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #4
0
ファイル: SfmlExt.cs プロジェクト: oldbean/space-station-14
 public static bool Encloses(this FloatRect outer, FloatRect inner)
 => (outer.Left <= inner.Left) &&
 (inner.Right() <= outer.Right()) &&
 (outer.Top <= inner.Top) &&
 (inner.Bottom() <= outer.Bottom());
コード例 #5
0
        public override bool Update(Vector2i mouseS, IMapManager currentMap)
        {
            if (currentMap == null) return false;

            spriteToDraw = GetDirectionalSprite(pManager.CurrentBaseSpriteKey);
            var spriteBounds = spriteToDraw.GetLocalBounds();

            mouseScreen = mouseS;
            mouseWorld = CluwneLib.ScreenToWorld(mouseScreen);

            var spriteSize = CluwneLib.PixelToTile(new Vector2f(spriteBounds.Width, spriteBounds.Height)); // TODO: Doublecheck this.  Use SizeF?
            var spriteRectWorld = new FloatRect(mouseWorld.X - (spriteSize.X / 2f),
                                                 mouseWorld.Y - (spriteSize.Y / 2f),
                                                 spriteSize.X, spriteSize.Y);

            if (pManager.CurrentPermission.IsTile)
                return false;

            currentTile = currentMap.GetTileRef(mouseWorld);

            //Align to similar if nearby found else free
            if (currentTile.Tile.TileDef.IsWall)
                return false; //HANDLE CURSOR OUTSIDE MAP

            var rangeSquared = pManager.CurrentPermission.Range * pManager.CurrentPermission.Range;
            if (rangeSquared > 0)
                if (
                    (pManager.PlayerManager.ControlledEntity.GetComponent<TransformComponent>(ComponentFamily.Transform)
                         .Position - mouseWorld).LengthSquared() > rangeSquared) return false;

            Entity[] nearbyEntities =
                ((EntityManager) IoCManager.Resolve<IEntityManagerContainer>().EntityManager).GetEntitiesInRange(
                    mouseWorld, snapToRange);

            IOrderedEnumerable<Entity> snapToEntities = from Entity entity in nearbyEntities
                                                        where entity.Template == pManager.CurrentTemplate
                                                        orderby
                                                            (entity.GetComponent<TransformComponent>(
                                                                ComponentFamily.Transform).Position - mouseWorld).LengthSquared()
                                                            ascending
                                                        select entity;

            if (snapToEntities.Any())
            {
                Entity closestEntity = snapToEntities.First();
                ComponentReplyMessage reply = closestEntity.SendMessage(this, ComponentFamily.Renderable,
                                                                        ComponentMessageType.GetSprite);

                //if(replies.Any(x => x.messageType == SS13_Shared.GO.ComponentMessageType.CurrentSprite))
                //{
                //    Sprite closestSprite = (Sprite)replies.Find(x => x.messageType == SS13_Shared.GO.ComponentMessageType.CurrentSprite).paramsList[0]; //This is safer but slower.

                if (reply.MessageType == ComponentMessageType.CurrentSprite)
                {
                    var closestSprite = (Sprite) reply.ParamsList[0]; //This is faster but kinda unsafe.
                    var closestBounds = closestSprite.GetLocalBounds();

                    var closestRect =
                        new FloatRect(
                            closestEntity.GetComponent<TransformComponent>(ComponentFamily.Transform).Position.X - closestBounds.Width / 2f,
                            closestEntity.GetComponent<TransformComponent>(ComponentFamily.Transform).Position.Y - closestBounds.Height / 2f,
                            closestBounds.Width, closestBounds.Height);

                    var sides = new List<Vector2f>
                    {
                        new Vector2f(closestRect.Left + (closestRect.Width / 2f), closestRect.Top - closestBounds.Height / 2f),
                        new Vector2f(closestRect.Left + (closestRect.Width / 2f), closestRect.Bottom() + closestBounds.Height / 2f),
                        new Vector2f(closestRect.Left - closestBounds.Width / 2f, closestRect.Top + (closestRect.Height / 2f)),
                        new Vector2f(closestRect.Right() + closestBounds.Width / 2f, closestRect.Top + (closestRect.Height / 2f))
                    };

                    Vector2f closestSide =
                        (from Vector2f side in sides orderby (side - mouseWorld).LengthSquared() ascending select side).First();

                    mouseWorld = closestSide;
                    mouseScreen = CluwneLib.WorldToScreen(mouseWorld).Round();
                }
            }

            spriteRectWorld = new FloatRect(mouseWorld.X - (spriteBounds.Width/2f), mouseWorld.Y - (spriteBounds.Height/2f),
                                             spriteBounds.Width, spriteBounds.Height);
            if (pManager.CollisionManager.IsColliding(spriteRectWorld)) return false;
            return true;
        }
コード例 #6
0
        public override bool Update(Vector2i mouseS, IMapManager currentMap)
        {
            if (currentMap == null)
            {
                return(false);
            }

            spriteToDraw = GetDirectionalSprite(pManager.CurrentBaseSpriteKey);
            var spriteBounds = spriteToDraw.GetLocalBounds();

            mouseScreen = mouseS;
            mouseWorld  = CluwneLib.ScreenToWorld(mouseScreen);

            if (pManager.CurrentPermission.IsTile)
            {
                return(false);
            }

            currentTile = currentMap.GetTileRef(mouseWorld);

            //Align to similar if nearby found else free
            if (currentTile.Tile.TileDef.IsWall)
            {
                return(false); //HANDLE CURSOR OUTSIDE MAP
            }
            var rangeSquared = pManager.CurrentPermission.Range * pManager.CurrentPermission.Range;

            if (rangeSquared > 0)
            {
                if (
                    (pManager.PlayerManager.ControlledEntity.GetComponent <TransformComponent>(ComponentFamily.Transform)
                     .Position - mouseWorld).LengthSquared() > rangeSquared)
                {
                    return(false);
                }
            }

            var manager = IoCManager.Resolve <IClientEntityManager>();

            IOrderedEnumerable <IEntity> snapToEntities =
                from IEntity entity in manager.GetEntitiesInRange(mouseWorld, snapToRange)
                where entity.Prototype == pManager.CurrentPrototype
                orderby
                    (entity.GetComponent <TransformComponent>(
                        ComponentFamily.Transform).Position - mouseWorld).LengthSquared()
                ascending
                select entity;

            if (snapToEntities.Any())
            {
                IEntity closestEntity       = snapToEntities.First();
                ComponentReplyMessage reply = closestEntity.SendMessage(this, ComponentFamily.Renderable,
                                                                        ComponentMessageType.GetSprite);

                //if(replies.Any(x => x.messageType == SS13_Shared.GO.ComponentMessageType.CurrentSprite))
                //{
                //    Sprite closestSprite = (Sprite)replies.Find(x => x.messageType == SS13_Shared.GO.ComponentMessageType.CurrentSprite).paramsList[0]; //This is safer but slower.

                if (reply.MessageType == ComponentMessageType.CurrentSprite)
                {
                    var closestSprite = (Sprite)reply.ParamsList[0]; //This is faster but kinda unsafe.
                    var closestBounds = closestSprite.GetLocalBounds();

                    var closestRect =
                        new FloatRect(
                            closestEntity.GetComponent <TransformComponent>(ComponentFamily.Transform).Position.X - closestBounds.Width / 2f,
                            closestEntity.GetComponent <TransformComponent>(ComponentFamily.Transform).Position.Y - closestBounds.Height / 2f,
                            closestBounds.Width, closestBounds.Height);

                    var sides = new List <Vector2f>
                    {
                        new Vector2f(closestRect.Left + (closestRect.Width / 2f), closestRect.Top - closestBounds.Height / 2f),
                        new Vector2f(closestRect.Left + (closestRect.Width / 2f), closestRect.Bottom() + closestBounds.Height / 2f),
                        new Vector2f(closestRect.Left - closestBounds.Width / 2f, closestRect.Top + (closestRect.Height / 2f)),
                        new Vector2f(closestRect.Right() + closestBounds.Width / 2f, closestRect.Top + (closestRect.Height / 2f))
                    };

                    Vector2f closestSide =
                        (from Vector2f side in sides orderby(side - mouseWorld).LengthSquared() ascending select side).First();

                    mouseWorld  = closestSide;
                    mouseScreen = CluwneLib.WorldToScreen(mouseWorld).Round();
                }
            }

            FloatRect spriteRectWorld = new FloatRect(mouseWorld.X - (spriteBounds.Width / 2f), mouseWorld.Y - (spriteBounds.Height / 2f),
                                                      spriteBounds.Width, spriteBounds.Height);

            if (pManager.CollisionManager.IsColliding(spriteRectWorld))
            {
                return(false);
            }
            return(true);
        }
コード例 #7
0
 /// <summary>
 /// Converts a SFML FloatRect to a OpenTK Box2.
 /// </summary>
 /// <param name="rect">SFML FloatRect.</param>
 /// <returns>OpenTK Box2.</returns>
 public static Box2 Convert(this FloatRect rect)
 {
     return(new Box2(rect.Left, rect.Top, rect.Right(), rect.Bottom()));
 }
コード例 #8
0
 /// <summary>
 /// Returns the positions of the BottomRight corner of the given FloatRect
 /// </summary>
 public static Vector2f BottomRight(this FloatRect rect)
 {
     return(new Vector2f(rect.Right(), rect.Bottom()));
 }
コード例 #9
0
ファイル: SfmlExt.cs プロジェクト: MSylvia/space-station-14
 public static bool Encloses(this FloatRect outer, FloatRect inner)
     => (outer.Left <= inner.Left)
     && (inner.Right() <= outer.Right())
     && (outer.Top <= inner.Top)
     && (inner.Bottom() <= outer.Bottom());
コード例 #10
0
 /// <summary>
 /// Returns the positions of the BottomLeft corner of the given FloatRect
 /// </summary>
 public static Vector2f BottomLeft(this FloatRect rect)
 {
     return(new Vector2f(rect.Left, rect.Bottom()));
 }
コード例 #11
0
        /// <summary>
        /// Render the renderables
        /// </summary>
        /// <param name="frametime">time since the last frame was rendered.</param>
        private void RenderComponents(float frameTime, FloatRect viewPort)
        {
            IEnumerable<Component> components = _entityManager.ComponentManager.GetComponents(ComponentFamily.Renderable)
                .Union(_entityManager.ComponentManager.GetComponents(ComponentFamily.Particles));

            IEnumerable<IRenderableComponent> floorRenderables = from IRenderableComponent c in components
                                                                 orderby c.Bottom ascending, c.DrawDepth ascending
                                                                 where c.DrawDepth < DrawDepth.MobBase
                                                                 select c;

            RenderList(new Vector2f(viewPort.Left, viewPort.Top), new Vector2f(viewPort.Right(), viewPort.Bottom()),
                       floorRenderables);

            IEnumerable<IRenderableComponent> largeRenderables = from IRenderableComponent c in components
                                                                 orderby c.Bottom ascending
                                                                 where c.DrawDepth >= DrawDepth.MobBase &&
                                                                       c.DrawDepth < DrawDepth.WallTops
                                                                 select c;

            RenderList(new Vector2f(viewPort.Left, viewPort.Top), new Vector2f(viewPort.Right(), viewPort.Bottom()),
                       largeRenderables);

            IEnumerable<IRenderableComponent> ceilingRenderables = from IRenderableComponent c in components
                                                                   orderby c.Bottom ascending, c.DrawDepth ascending
                                                                   where c.DrawDepth >= DrawDepth.WallTops
                                                                   select c;

            RenderList(new Vector2f(viewPort.Left, viewPort.Top), new Vector2f(viewPort.Right(), viewPort.Bottom()),
                       ceilingRenderables);
        }
コード例 #12
0
        // If `ignoreSpace` is false, this will return tiles in chunks that don't even exist.
        // This is to make the tile count predictable.  Is this appropriate behavior?
        public IEnumerable<TileRef> GetTilesIntersecting(FloatRect area, bool ignoreSpace)
        {
            int chunkLeft = (int)Math.Floor(area.Left / ChunkSize);
            int chunkTop = (int)Math.Floor(area.Top / ChunkSize);
            int chunkRight = (int)Math.Floor(area.Right() / ChunkSize);
            int chunkBottom = (int)Math.Floor(area.Bottom() / ChunkSize);
            for (int chunkY = chunkTop; chunkY <= chunkBottom; ++chunkY)
            {
                for (int chunkX = chunkLeft; chunkX <= chunkRight; ++chunkX)
                {
                    int xMin = 0;
                    int yMin = 0;
                    int xMax = 15;
                    int yMax = 15;

                    if (chunkX == chunkLeft)
                        xMin = Mod(Math.Floor(area.Left), ChunkSize);
                    if (chunkY == chunkTop)
                        yMin = Mod(Math.Floor(area.Top), ChunkSize);

                    if (chunkX == chunkRight)
                        xMax = Mod(Math.Floor(area.Right()), ChunkSize);
                    if (chunkY == chunkBottom)
                        yMax = Mod(Math.Floor(area.Bottom()), ChunkSize);

                    Chunk chunk;
                    if (!chunks.TryGetValue(new Vector2i(chunkX, chunkY), out chunk))
                    {
                        if (ignoreSpace)
                            continue;
                        else
                            for (int y = yMin; y <= yMax; ++y)
                                for (int x = xMin; x <= xMax; ++x)
                                    yield return new TileRef(this,
                                        chunkX * ChunkSize + x,
                                        chunkY * ChunkSize + y);
                    }
                    else
                    {
                        for (int y = yMin; y <= yMax; ++y)
                        {
                            int i = y * ChunkSize + xMin;
                            for (int x = xMin; x <= xMax; ++x, ++i)
                            {
                                if (!ignoreSpace || chunk.Tiles[i].TileId != 0)
                                    yield return new TileRef(this,
                                        chunkX * ChunkSize + x,
                                        chunkY * ChunkSize + y,
                                        chunk, i);
                            }
                        }
                    }
                }
            }
        }
コード例 #13
0
        /// <summary>
        /// returns true if collider intersects a collidable under management. Does not trigger Bump.
        /// </summary>
        /// <param name="collider">Rectangle to check for collision</param>
        /// <returns></returns>
        public bool IsColliding(FloatRect collider)
        {
            Vector2f[] points =
                {
                    new Vector2f(collider.Left, collider.Top),
                    new Vector2f(collider.Right(), collider.Top),
                    new Vector2f(collider.Right(), collider.Bottom()),
                    new Vector2f(collider.Left, collider.Bottom())
                };

            //Get the buckets that correspond to the collider's points.
            List<CollidableBucket> buckets = points.Select(GetBucket).Distinct().ToList();

            //Get all of the points
            var cpoints = new List<CollidablePoint>();
            foreach (CollidableBucket bucket in buckets)
            {
                cpoints.AddRange(bucket.GetPoints());
            }

            //Expand points to distinct AABBs
            List<CollidableAABB> aabBs = (cpoints.Select(cp => cp.ParentAABB)).Distinct().ToList();

            //try all of the AABBs against the target rect.
            bool collided = false;
            foreach (CollidableAABB aabb in aabBs.Where(aabb => aabb.Collidable.AABB.Intersects(collider)))
            {
                if (aabb.IsHardCollider) //If the collider is supposed to prevent movement
                {
                    collided = true;
                }
            }

            return collided || IoCManager.Resolve<IMapManager>().GetTilesIntersecting(collider, true).Any(t => t.Tile.TileDef.IsCollidable);
        }
コード例 #14
0
 /// <summary>
 ///     Converts a SFML FloatRect to a SS14 Box2.
 /// </summary>
 public static Shared.Maths.Box2 ToBox(this FloatRect rect)
 {
     return(new Shared.Maths.Box2(rect.Left, rect.Top, rect.Right(), rect.Bottom()));
 }