/// <summary> /// See return value. Fills hitBlockEntities with all/solid (see param solidOnly) entities hit /// </summary> /// <param name="box">Box for which to check collisions</param> /// <param name="property">Property to check for</param> /// <param name="solidOnly">Only checks for solid entities</param> /// <param name="pushAway">Solve collisions</param> /// <returns>True if an entity solid/not (see param solidOnly) is hit</returns> private bool CollisionWithAllEntities_RealTime(CollisionBox box, string property, bool solidOnly = true, bool pushAway = false) { box.SetParent(this); Rectangle boundbox = box.BoxAt(PositionSrc.Position); //calculate boundbox absolute coordinate hitBlockEntities_RealTime = new List <Collision>(); boundbox = CheckEntityCollisions(hitBlockEntities_RealTime, box, boundbox, pushAway, solidOnly); return(CheckIfOneEntityHitContainProperty_RealTime(property)); }
private Rectangle CheckTargetBox(CollisionBox hitbox, Rectangle boundBox, IEntity entity, CollisionComponent coll, CollisionBox targetBox) { var 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 CheckEnvironment(List <MapSquare> hitSquares, CollisionBox hitbox, bool pushAway = true) { Point offset = new Point(0, 0); Rectangle hitRect = hitbox.BoxAt(PositionSrc.Position); // Absolute positions of collision box // this bounds checking prevents needlessly checking collisions way too far away // it's a very effective optimization (brings busy time from ~60% down to 45%!) int size = Parent.Screen.TileSize; for (int y = hitRect.Top - size; y < hitRect.Bottom; y += size) { for (int x = hitRect.Left - size; x < hitRect.Right; x += size) { var tile = Parent.Screen.SquareAt(x, y); if (tile == null) { continue; } CheckEnvironmentTile(hitSquares, hitbox, hitRect, tile, ref offset, pushAway); } var rightEdge = Parent.Screen.SquareAt(hitRect.Right, y); if (rightEdge != null) { CheckEnvironmentTile(hitSquares, hitbox, hitRect, rightEdge, ref offset, pushAway); } } for (int x = hitRect.Left - size; x < hitRect.Right; x += size) { var tile = Parent.Screen.SquareAt(x, hitRect.Bottom); if (tile == null) { continue; } CheckEnvironmentTile(hitSquares, hitbox, hitRect, tile, ref offset, pushAway); } var lastCorner = Parent.Screen.SquareAt(hitRect.Right, hitRect.Bottom); if (lastCorner != null) { CheckEnvironmentTile(hitSquares, hitbox, hitRect, lastCorner, ref offset, pushAway); } }
private void ReactForHitbox(List <MapSquare> hitSquares, HashSet <TileProperties> hitTypes, CollisionBox hitbox) { hitbox.SetParent(this); var boundBox = hitbox.BoxAt(PositionSrc.Position); if (hitbox.Environment) { foreach (MapSquare tile in hitSquares) { var tileBox = tile.BlockBox; bool downonly = (!Parent.Container.IsGravityFlipped && tile.Tile.Properties.Climbable); bool uponly = (Parent.Container.IsGravityFlipped && tile.Tile.Properties.Climbable); bool hit = (tile.BlockBox != Rectangle.Empty) ? BlockByIntersection(boundBox, tileBox, uponly, downonly) : boundBox.IntersectsWith(tile.BoundBox); if (hitbox.PushAway && (hit || boundBox.IntersectsWith(tile.BoundBox))) // the environment touched me! { hitTypes.Add(tile.Tile.Properties); } } } // but for entities, we can go ahead and be active aggressors - // inflict our effects on the target entity, not the other way around 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.TargetBoxes(hitbox)) { boundBox = CheckTargetBox(hitbox, boundBox, entity, coll, targetBox); } } }
private void ReactForHitbox(List<MapSquare> hitSquares, HashSet<TileProperties> hitTypes, CollisionBox hitbox) { hitbox.SetParent(this); RectangleF boundBox = hitbox.BoxAt(PositionSrc.Position); if (hitbox.Environment) { foreach (MapSquare tile in hitSquares) { RectangleF tileBox = tile.BlockBox; bool downonly = (!Parent.Container.IsGravityFlipped && tile.Tile.Properties.Climbable); bool uponly = (Parent.Container.IsGravityFlipped && tile.Tile.Properties.Climbable); bool hit = (tile.BlockBox != RectangleF.Empty) ? BlockByIntersection(boundBox, tileBox, uponly, downonly) : boundBox.IntersectsWith(tile.BoundBox); if (hitbox.PushAway && (hit || boundBox.IntersectsWith(tile.BoundBox))) // the environment touched me! { hitTypes.Add(tile.Tile.Properties); } } } // but for entities, we can go ahead and be active aggressors - // inflict our effects on the target entity, not the other way around 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.TargetBoxes(hitbox)) { boundBox = CheckTargetBox(hitbox, boundBox, entity, coll, targetBox); } } }
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 CheckEnvironment(List<MapSquare> hitSquares, CollisionBox hitbox) { PointF offset = new PointF(0, 0); RectangleF hitRect = hitbox.BoxAt(PositionSrc.Position); // this bounds checking prevents needlessly checking collisions way too far away // it's a very effective optimization (brings busy time from ~60% down to 45%!) int size = Parent.Screen.TileSize; for (float y = hitRect.Top - size; y < hitRect.Bottom; y += size) { for (float x = hitRect.Left - size; x < hitRect.Right; x += size) { var tile = Parent.Screen.SquareAt(x, y); if (tile == null) continue; CheckEnvironmentTile(hitSquares, hitbox, hitRect, tile, ref offset); } var rightEdge = Parent.Screen.SquareAt(hitRect.Right, y); if (rightEdge != null) { CheckEnvironmentTile(hitSquares, hitbox, hitRect, rightEdge, ref offset); } } for (float x = hitRect.Left - size; x < hitRect.Right; x += size) { var tile = Parent.Screen.SquareAt(x, hitRect.Bottom); if (tile == null) continue; CheckEnvironmentTile(hitSquares, hitbox, hitRect, tile, ref offset); } var lastCorner = Parent.Screen.SquareAt(hitRect.Right, hitRect.Bottom); if (lastCorner != null) { CheckEnvironmentTile(hitSquares, hitbox, hitRect, lastCorner, ref offset); } }
/// <summary> /// See return value. Fills hitBlockEntities with all/solid (see param solidOnly) entities hit /// </summary> /// <param name="box">Box for which to check collisions</param> /// <param name="property">Property to check for</param> /// <param name="solidOnly">Only checks for solid entities</param> /// <param name="pushAway">Solve collisions</param> /// <returns>True if an entity solid/not (see param solidOnly) is hit</returns> private bool CollisionWithAllEntities_RealTime(CollisionBox box, string property, bool solidOnly = true, bool pushAway = false) { box.SetParent(this); RectangleF boundbox = box.BoxAt(PositionSrc.Position); //calculate boundbox absolute coordinate hitBlockEntities_RealTime = new List<Collision>(); boundbox = CheckEntityCollisions(hitBlockEntities_RealTime, box, boundbox, pushAway, solidOnly); return CheckIfOneEntityHitContainProperty_RealTime(property); }