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); }
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); }
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; }
public HitBox(float x, float y, float width, float height) { box = new RectangleF(x, y, width, height); }
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; }
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); }
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; }
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; }
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; }
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; } } } } }
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; }
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); } }
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; }
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; }
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); }
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); }
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; }
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; }
// 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; }
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))); } } } }
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); }