CollisionInfo? TestMapStickyCollision(Map map, Rectangle rectangle, TileInfo.SideType direction, BitArray maybeGroundTile) { List<CollisionTile> tiles = map.GetCollidingTiles(rectangle, direction); for (int i = 0; i < tiles.Count; i++) { TileInfo.SideType side = TileInfo.OppositeSide(direction); GameUnit perpendicularPosition; if (TileInfo.Vertical(side)) { perpendicularPosition = rectangle.Center.X; } else { perpendicularPosition = rectangle.Center.Y; } GameUnit leadingPosition = rectangle.Side(direction); bool shouldTestSlopes = TileInfo.Vertical(side); TestCollisionInfo testInfo = tiles[i].TestCollision(side, perpendicularPosition, leadingPosition, shouldTestSlopes); if (testInfo.isColliding) { CollisionInfo info = new CollisionInfo(testInfo.position, tiles[i].Position, tiles[i].TileType); return info; } else if (maybeGroundTile != null && direction == TileInfo.SideType.BottomSide) { BitArray tallSlope = TileInfo.CreateTileType(); tallSlope.Set((int)TileInfo.TileFlag.Slope, true); tallSlope.Set((int)TileInfo.TileFlag.TallSlope, true); if ((maybeGroundTile[(int)TileInfo.TileFlag.Slope] && tiles[i].TileType[(int)TileInfo.TileFlag.Slope]) || (maybeGroundTile[(int)TileInfo.TileFlag.Wall] && (tallSlope.And(tiles[i].TileType).Equals(tallSlope)))) { CollisionInfo info = new CollisionInfo(testInfo.position, tiles[i].Position, tiles[i].TileType); return info; } } } return null; }
CollisionInfo? TestMapBouncingCollision(Map map, Rectangle rectangle, TileInfo.SideType direction, BitArray maybeGroundTile) { List<CollisionTile> tiles = map.GetCollidingTiles(rectangle, direction); CollisionInfo? result = null; for (int i = 0; i < tiles.Count; i++) { TileInfo.SideType side = TileInfo.OppositeSide(direction); GameUnit perpendicularPosition; if (TileInfo.Vertical(side)) { perpendicularPosition = rectangle.Center.X; } else { perpendicularPosition = rectangle.Center.Y; } GameUnit leadingPosition = rectangle.Side(direction); bool shouldTestSlopes = TileInfo.Vertical(side); TestCollisionInfo testInfo = tiles[i].TestCollision(side, perpendicularPosition, leadingPosition, shouldTestSlopes); if (testInfo.isColliding) { bool shouldReplaceResult = true; if (result.HasValue) { shouldReplaceResult = TileInfo.IsMin(side) ? testInfo.position < result.Value.position : testInfo.position > result.Value.position; } if (shouldReplaceResult) { CollisionInfo info = new CollisionInfo(testInfo.position, tiles[i].Position, tiles[i].TileType); result = info; } } } return result; }
public List<CollisionTile> GetCollidingTiles(Rectangle rectangle, TileInfo.SideType direction) { TileUnit firstPrimary = Units.GameToTile(rectangle.Side(TileInfo.OppositeSide(direction))); TileUnit lastPrimary = Units.GameToTile(rectangle.Side(direction)); int primaryIncr = TileInfo.IsMax(direction) ? 1 : -1; bool horizontal = TileInfo.Horizontal(direction); TileUnit sMin = Units.GameToTile(horizontal ? rectangle.Top : rectangle.Left); TileUnit sMid = Units.GameToTile(horizontal ? rectangle.Center.Y : rectangle.Center.X); TileUnit sMax = Units.GameToTile(horizontal ? rectangle.Bottom : rectangle.Right); bool sPositive = sMid - sMin < sMax - sMid; int secondaryIncr = sPositive ? 1 : -1; TileUnit firstSecondary = sPositive ? sMin : sMax; TileUnit lastSecondary = sPositive ? sMin : sMax; List<CollisionTile> collisionTiles = new List<CollisionTile>(); for (TileUnit primary = firstPrimary; primary != lastPrimary + primaryIncr; primary = Convert.ToUInt32(Convert.ToInt32(primary) + primaryIncr)) { for (TileUnit secondary = firstSecondary; secondary != lastSecondary + secondaryIncr; secondary = Convert.ToUInt32(Convert.ToInt32(secondary) + secondaryIncr)) { TileUnit row = !horizontal ? primary : secondary; TileUnit col = horizontal ? primary : secondary; collisionTiles.Add(new CollisionTile(row, col, tiles[Convert.ToInt32(row)][Convert.ToInt32(col)].tileType)); } } return collisionTiles; }