예제 #1
0
파일: HitBox.cs 프로젝트: laazer/cs_megaman
        public HitBox(XElement xmlNode)
        {
            float width = xmlNode.GetAttribute<float>("width");

            float height = xmlNode.GetAttribute<float>("height");

            float x = xmlNode.GetAttribute<float>("x");

            float y = xmlNode.GetAttribute<float>("y");

            box = new RectangleF(x, y, width, height);
        }
예제 #2
0
        public MapSquare(IScreenLayer layer, Tile tile, int x, int y, int tilesize)
        {
            this.layer = layer;
            Tile = tile;
            X = x;
            Y = y;
            screenX = x * tilesize;
            screenY = y * tilesize;

            var commonBox = Tile.Sprite.BoundBox;

            blockBox = new RectangleF(commonBox.X, commonBox.Y, commonBox.Width, commonBox.Height);
            blockBox.Offset(-Tile.Sprite.HotSpot.X, -Tile.Sprite.HotSpot.Y);
        }
예제 #3
0
        private void LoadLadderBoxes()
        {
            var tilesize = Tile.Width;

            MapSquare below = layer.SquareAt(ScreenX, ScreenY + tilesize);
            if (below != null && !below.Tile.Properties.Climbable)
            {
                flipLadderBox = blockBox;
                flipLadderBox.Offset(0, flipLadderBox.Height - 4);
                flipLadderBox.Height = 4;
            }
            else flipLadderBox = RectangleF.Empty;

            MapSquare above = layer.SquareAt(ScreenX, ScreenY - tilesize);
            if (above != null && !above.Tile.Properties.Climbable)
            {
                ladderBox = blockBox;
                ladderBox.Height = 4;
            }
            else ladderBox = RectangleF.Empty;

            ladderBoxesLoaded = true;
        }
예제 #4
0
 public HitBox(float x, float y, float width, float height)
 {
     box = new RectangleF(x, y, width, height);
 }
예제 #5
0
        private bool EnvironmentContact(IMapSquare square, RectangleF tileBox, RectangleF boundBox, out PointF offset)
        {
            // can't use intersection, use epsilon
            offset = PointF.Empty;
            if (tileBox.Top < boundBox.Top)
            {
                if (tileBox.Bottom - boundBox.Top + Const.PixelEpsilon <= 0) return false;
            }
            else
            {
                if (boundBox.Bottom - tileBox.Top + Const.PixelEpsilon <= 0) return false;
            }
            if (tileBox.Left < boundBox.Left)
            {
                if (tileBox.Right - boundBox.Left + Const.PixelEpsilon <= 0) return false;
            }
            else
            {
                if (boundBox.Right - tileBox.Left + Const.PixelEpsilon <= 0) return false;
            }

            bool down = (!parentComponent.Parent.Container.IsGravityFlipped && square.Properties.Climbable);
            bool up = (parentComponent.Parent.Container.IsGravityFlipped && square.Properties.Climbable);

            if (parentComponent.MovementSrc != null) offset = GetIntersectionOffset(tileBox, boundBox, parentComponent.MovementSrc.VelocityX, parentComponent.MovementSrc.VelocityY, up, down);
            else offset = GetIntersectionOffset(tileBox, boundBox, 0, 0, up, down);

            // Quicksand sinking property tells us not to push the hitbox outward
            if (square.Properties.Sinking > 0)
            {
                // don't clip left or right at all
                offset.X = 0;

                if (parentComponent.Parent.Container.IsGravityFlipped)
                {
                    // don't clip them downward out of the collision
                    if (offset.Y > 0)
                    {
                        offset.Y = 0;
                    }
                }
                else
                {
                    // don't clip them upward out of the collision
                    if (offset.Y < 0)
                    {
                        offset.Y = 0;
                    }
                }
            }

            return true;
        }
예제 #6
0
        public static bool VerticalApproach(RectangleF intersection, RectangleF boundBox, float vx, float vy)
        {
            if ((vx == 0 && intersection.Width > 0) || intersection.Height == 0) return true;
            if ((vy == 0 && intersection.Height > 0) || intersection.Width == 0) return false;
            if ((intersection.Bottom == boundBox.Bottom && vy < 0) ||
                (intersection.Top == boundBox.Top && vy > 0))
                return false;
            if ((intersection.Left == boundBox.Left && vx > 0) ||
                (intersection.Right == boundBox.Right && vx < 0))
                return true;

            float velocitySlope = Math.Abs(vy) / Math.Abs(vx);
            float collisionSlope = intersection.Height / intersection.Width;
            return (velocitySlope >= collisionSlope);
        }
예제 #7
0
파일: Math.cs 프로젝트: laazer/cs_megaman
 public bool IntersectsWith(RectangleF rect)
 {
     return rect.X < this.X + this.Width && this.X < rect.X + rect.Width && rect.Y < this.Y + this.Height && this.Y < rect.Y + rect.Height;
 }
예제 #8
0
파일: Math.cs 프로젝트: laazer/cs_megaman
 public bool Contains(RectangleF rect)
 {
     return this.X <= rect.X && rect.X + rect.Width <= this.X + this.Width && this.Y <= rect.Y && rect.Y + rect.Height <= this.Y + this.Height;
 }
예제 #9
0
파일: Math.cs 프로젝트: laazer/cs_megaman
 public static RectangleF Intersect(RectangleF a, RectangleF b)
 {
     float num = Math.Max(a.X, b.X);
     float num2 = Math.Min(a.X + a.Width, b.X + b.Width);
     float num3 = Math.Max(a.Y, b.Y);
     float num4 = Math.Min(a.Y + a.Height, b.Y + b.Height);
     if (num2 >= num && num4 >= num3)
     {
         return new RectangleF(num, num3, num2 - num, num4 - num3);
     }
     return RectangleF.Empty;
 }
예제 #10
0
        private void CheckInReach()
        {
            inReach = false;
            if (position == null) return;

            foreach (HitBox hitbox in hitboxes)
            {
                foreach (MapSquare tile in Parent.Screen.Tiles)
                {
                    if (tile.Tile.Properties.Climbable)
                    {
                        RectangleF myBox = hitbox.BoxAt(position.Position, Parent.IsGravitySensitive ? Parent.Container.IsGravityFlipped : false);
                        RectangleF intersection = RectangleF.Intersect(tile.BoundBox, myBox);
                        if (!intersection.IsEmpty)
                        {
                            inReach = true;
                            inReachTile = tile;
                            inReachCached = true;
                            reachRect = intersection;
                            return;
                        }
                    }
                }
            }
        }
예제 #11
0
 private RectangleF CheckTargetBox(CollisionBox hitbox, RectangleF boundBox, IEntity entity, CollisionComponent coll, CollisionBox targetBox)
 {
     RectangleF rect = targetBox.BoxAt(coll.PositionSrc.Position);
     if (boundBox.IntersectsWith(rect))
     {
         coll.Touch(hitbox, targetBox);
         Touch(targetBox, hitbox);
         CollideWith(entity, hitbox, targetBox);
     }
     return boundBox;
 }
예제 #12
0
 private void CheckEnvironmentTile(List<MapSquare> hitSquares, CollisionBox hitbox, RectangleF hitRect, MapSquare tile, ref PointF offset)
 {
     if (hitbox.EnvironmentCollisions(PositionSrc.Position, tile, ref offset))
     {
         hitSquares.Add(tile);
         if (hitbox.PushAway) PositionSrc.Offset(offset.X, offset.Y);
     }
     else if (hitRect.IntersectsWith(tile.BoundBox))
     {
         hitSquares.Add(tile);
     }
 }
예제 #13
0
        private RectangleF CheckEntityCollisions(List<Collision> blockEntities, CollisionBox hitbox, RectangleF boundbox)
        {
            foreach (var entity in Parent.Entities.GetAll())
            {
                if (entity == Parent) continue;
                CollisionComponent coll = entity.GetComponent<CollisionComponent>();
                if (coll == null) continue;

                foreach (CollisionBox targetBox in coll.HitByBoxes(hitbox).Where(box => box.Properties.Blocking))
                {
                    // if he's blocking, check for collision and maybe push me away

                    RectangleF rect = targetBox.BoxAt(coll.PositionSrc.Position);
                    RectangleF adjustrect = rect;
                    adjustrect.X -= Const.PixelEpsilon;
                    adjustrect.Y -= Const.PixelEpsilon;
                    adjustrect.Width += 2 * Const.PixelEpsilon;
                    adjustrect.Height += 2 - Const.PixelEpsilon;
                    RectangleF intersection = RectangleF.Intersect(boundbox, adjustrect);
                    if (intersection.Width != 0 || intersection.Height != 0)
                    {
                        blockEntities.Add(new Collision(hitbox, targetBox, coll));

                        if (hitbox.PushAway)
                        {
                            float vx, vy;
                            MovementComponent mov = entity.GetComponent<MovementComponent>();
                            vx = MovementSrc.VelocityX;
                            vy = MovementSrc.VelocityY;
                            if (mov != null)
                            {
                                vx -= mov.VelocityX;
                                vy -= mov.VelocityY;
                            }

                            PointF offset = hitbox.GetIntersectionOffset(rect, boundbox, vx, vy, false, false);
                            if (offset.X != 0 || offset.Y != 0)
                            {
                                PositionSrc.Offset(offset.X, offset.Y);
                                boundbox.Offset(offset.X, offset.Y);
                            }
                        }
                    }
                }
            }
            return boundbox;
        }
예제 #14
0
        private bool BlockByIntersection(RectangleF myBox, RectangleF targetBox, bool uponly, bool downonly)
        {
            // correct floating point errors
            myBox = FloatCorrect(myBox);
            targetBox = FloatCorrect(targetBox);

            RectangleF intersection = RectangleF.Intersect(myBox, targetBox);
            bool ret = false;

            if (intersection.Height > Const.PixelEpsilon)
            {
                if (intersection.Left == myBox.Left && !downonly && !uponly) BlockLeft = true;
                if (intersection.Right == myBox.Right && !downonly && !uponly) BlockRight = true;
                if (BlockRight)
                {
                    blockRightMin = Math.Min(blockRightMin, intersection.Top);
                    blockRightMax = Math.Max(blockRightMax, intersection.Bottom);
                }
                if (BlockLeft)
                {
                    blockLeftMin = Math.Min(blockLeftMin, intersection.Top);
                    blockLeftMax = Math.Max(blockLeftMax, intersection.Bottom);
                }
                ret = true;
            }
            if (intersection.Width > Const.PixelEpsilon)
            {
                if (intersection.Top == myBox.Top && !downonly) BlockTop = (uponly && MovementSrc != null) ? (MovementSrc.VelocityY * -1 > intersection.Height) : true;
                if (intersection.Bottom == myBox.Bottom && !uponly) BlockBottom = (downonly && MovementSrc != null) ? (MovementSrc.VelocityY > intersection.Height) : true;
                if (BlockBottom)
                {
                    blockBottomMin = Math.Min(blockBottomMin, intersection.Left);
                    blockBottomMax = Math.Max(blockBottomMax, intersection.Right);
                }
                if (BlockTop)
                {
                    blockTopMin = Math.Min(blockTopMin, intersection.Left);
                    blockTopMax = Math.Max(blockTopMax, intersection.Right);
                }
                ret = true;
            }
            return ret;
        }
예제 #15
0
        private static RectangleF FloatCorrect(RectangleF rect)
        {
            int rleft = (int)Math.Round(rect.Left);
            int rtop = (int)Math.Round(rect.Top);

            if (Math.Abs(rleft - rect.Left) < Const.PixelEpsilon) rect.X = rleft;
            if (Math.Abs(rtop - rect.Top) < Const.PixelEpsilon) rect.Y = rtop;

            int rright = (int)Math.Round(rect.Right);
            int rbottom = (int)Math.Round(rect.Bottom);

            if (Math.Abs(rright - rect.Right) < Const.PixelEpsilon) rect.Width = rright - rleft;
            if (Math.Abs(rbottom - rect.Bottom) < Const.PixelEpsilon) rect.Height = rbottom - rtop;

            return rect;
        }
        public void IntersectionOffset_HorizontalApproach_PushOutHorizontally()
        {
            var box = new CollisionBox(0, 0, 10, 10);
            box.SetParent(_collision);

            var tileBox = new RectangleF(8.6f, 4.1f, 10, 10);

            var collisionPoint = box.GetIntersectionOffset(tileBox, box.BoxAt(PointF.Empty), 1.0f, 0, false, false);

            // pushes the block out horizontally
            Assert.AreEqual(-1.4f, collisionPoint.X, Const.PixelEpsilon);
            Assert.AreEqual(0, collisionPoint.Y);
        }
예제 #17
0
파일: Math.cs 프로젝트: laazer/cs_megaman
 public static RectangleF Inflate(RectangleF rect, float x, float y)
 {
     RectangleF result = rect;
     result.Inflate(x, y);
     return result;
 }
        public void IntersectionOffset_UpOnly_GoingDown_NoPushOut()
        {
            var box = new CollisionBox(0, 0, 10, 10);
            box.SetParent(_collision);

            var tileBox = new RectangleF(8.6f, -4.1f, 10, 10);

            var collisionPoint = box.GetIntersectionOffset(tileBox, box.BoxAt(PointF.Empty), 0, 1.0f, true, false);

            Assert.AreEqual(Point.Empty, collisionPoint);
        }
예제 #19
0
파일: Math.cs 프로젝트: laazer/cs_megaman
 public static RectangleF Union(RectangleF a, RectangleF b)
 {
     float num = Math.Min(a.X, b.X);
     float num2 = Math.Max(a.X + a.Width, b.X + b.Width);
     float num3 = Math.Min(a.Y, b.Y);
     float num4 = Math.Max(a.Y + a.Height, b.Y + b.Height);
     return new RectangleF(num, num3, num2 - num, num4 - num3);
 }
        private IMapSquare GetMapSquare(RectangleF rectangle)
        {
            var square = new Mock<IMapSquare>();
            square.SetupGet(s => s.BlockBox).Returns(rectangle);
            square.SetupGet(s => s.Properties).Returns(Common.TileProperties.Default);

            return square.Object;
        }
예제 #21
0
파일: Math.cs 프로젝트: laazer/cs_megaman
 public void Intersect(RectangleF rect)
 {
     RectangleF rectangleF = RectangleF.Intersect(rect, this);
     this.X = rectangleF.X;
     this.Y = rectangleF.Y;
     this.Width = rectangleF.Width;
     this.Height = rectangleF.Height;
 }
예제 #22
0
        // change those last bools into an enum or something else!
        public PointF GetIntersectionOffset(RectangleF tileBox, RectangleF boundBox, float approach_vx, float approach_vy, bool uponly, bool downonly)
        {
            float top = -1, bottom = -1, left = -1, right = -1;
            RectangleF intersection = RectangleF.Intersect(boundBox, tileBox);

            PointF offset = new PointF(0, 0);
            if (intersection.Width == 0 && intersection.Height == 0) return offset;

            if (Math.Abs(intersection.Bottom - boundBox.Bottom) < Const.PixelEpsilon) bottom = intersection.Height;
            if (Math.Abs(intersection.Top - boundBox.Top) < Const.PixelEpsilon) top = intersection.Height;

            if (Math.Abs(intersection.Right - boundBox.Right) < Const.PixelEpsilon) right = intersection.Width;
            if (Math.Abs(intersection.Left - boundBox.Left) < Const.PixelEpsilon) left = intersection.Width;

            if (top > 0 || bottom > 0 || left > 0 || right > 0)
            {
                bool vert = CollisionComponent.VerticalApproach(intersection, boundBox, approach_vx, approach_vy);

                if (vert)
                {
                    if (downonly)
                    {
                        if (approach_vy > 0 && boundBox.Bottom <= tileBox.Bottom)
                        {
                            offset.Y = -bottom;
                            return offset;
                        }
                        else return new PointF(0, 0);
                    }
                    else if (uponly)
                    {
                        if (approach_vy < 0 && boundBox.Top >= tileBox.Top)
                        {
                            offset.Y = top;
                            return offset;
                        }
                        else return new PointF(0, 0);
                    }

                    if (top >= 0) offset.Y = top;
                    if (bottom >= 0) offset.Y = -bottom;
                }
                else
                {
                    if (uponly || downonly) return new PointF(0, 0);
                    if (left >= 0)
                    {
                        if (approach_vx < 0) offset.X = left;
                    }
                    if (right >= 0)
                    {
                        if (approach_vx > 0) offset.X = -right;
                    }
                }
            }

            return offset;
        }
예제 #23
0
        private void Draw(IRenderingContext context, float positionX, float positionY)
        {
            if (meterTexture == null)
            {
                meterTexture = context.LoadResource(this.info.Background);
                bounds = new RectangleF(positionX, positionY, meterTexture.Width, meterTexture.Height);
            }

            if (tickTexture == null)
                tickTexture = context.LoadResource(this.info.TickImage);

            if (tickTexture != null)
            {
                int i = 0;
                int ticks = (int)Math.Ceiling(value / tickSize);
                // prevent float errors
                if (ticks > 28) ticks = 28;

                if (meterTexture != null)
                    context.Draw(meterTexture, 4, new Common.Geometry.Point((int)positionX, (int)positionY));

                if (horizontal)
                {
                    for (int y = (int)positionX; i < ticks; i++, y += tickTexture.Width)
                    {
                        context.Draw(tickTexture, 4, new Common.Geometry.Point(y, (int)positionY));
                    }
                }
                else
                {
                    for (int y = 54 + (int)positionY; i < ticks; i++, y -= tickTexture.Height)
                    {
                        context.Draw(tickTexture, 4, new Common.Geometry.Point((int)(positionX + tickOffset.X), (int)(y + tickOffset.Y)));
                    }
                }
            }
        }
예제 #24
0
        private bool EntityBounded(EntityPlacement entityInfo, Point location)
        {
            var entity = Stage.Project.EntityByName(entityInfo.entity);
            RectangleF bounds;

            if (entity.DefaultSprite == null)
            {
                bounds = new RectangleF(-8, -8, 16, 16);
            }
            else
            {
                var sprite = entity.DefaultSprite;
                bounds = sprite.BoundBox;
                bounds.Offset(-sprite.HotSpot.X, -sprite.HotSpot.Y);
            }

            bounds.Offset(entityInfo.screenX, entityInfo.screenY);
            return bounds.Contains(location);
        }