Пример #1
0
        private RectangleF CheckEntityCollisions(List <Collision> blockEntities, CollisionBox hitbox, RectangleF boundbox, bool pushAway = true, bool solidOnly = true)
        {
            foreach (var entity in Parent.Entities.GetAll())
            {
                if (entity == Parent)
                {
                    continue;
                }
                CollisionComponent coll = entity.GetComponent <CollisionComponent>();
                if (coll == null)
                {
                    continue;
                }

                IEnumerable <CollisionBox> collToCheck = (solidOnly) ? coll.HitByBoxes(hitbox).Where(box => box.Properties.Blocking) : coll.HitByBoxes(hitbox);

                foreach (CollisionBox targetBox in collToCheck)
                {
                    // 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 && 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);
        }
Пример #2
0
 private void CheckEnvironmentTile(List <MapSquare> hitSquares, CollisionBox hitbox, Rectangle hitRect, MapSquare tile, ref Point offset, bool pushAway)
 {
     if (hitbox.EnvironmentCollisions(PositionSrc.Position, tile, ref offset))
     {
         hitSquares.Add(tile);
         if (hitbox.PushAway && pushAway)
         {
             PositionSrc.Offset(offset.X, offset.Y);
         }
     }
     else if (hitRect.IntersectsWith(tile.BoundBox))
     {
         hitSquares.Add(tile);
     }
 }
Пример #3
0
        private void ReactToTileEffect(TileProperties properties)
        {
            if (MovementSrc != null)
            {
                MovementSrc.PushX(properties.PushX);
                MovementSrc.PushY(properties.PushY);
                MovementSrc.ResistX(properties.ResistX);
                MovementSrc.ResistY(properties.ResistY);
                MovementSrc.DragX(properties.DragX);
                MovementSrc.DragY(properties.DragY);

                if (properties.Sinking > 0)
                {
                    if (Parent.Container.IsGravityFlipped)
                    {
                        if (MovementSrc.VelocityY <= 0)
                        {
                            BlockTop = true;
                            PositionSrc.Offset(0, -1 * properties.Sinking);
                            // don't let gravity accumulate like in MM1
                            MovementSrc.VelocityY = 0;
                        }
                    }
                    else
                    {
                        if (MovementSrc.VelocityY >= 0)
                        {
                            BlockBottom = true;
                            PositionSrc.Offset(0, properties.Sinking);
                            MovementSrc.VelocityY = 0;
                        }
                    }
                }
            }
            // don't just kill, it needs to be conditional on invincibility
            if (properties.Lethal && Parent.Name == "Player")
            {
                Parent.SendMessage(new DamageMessage(null, float.PositiveInfinity));
            }
        }
Пример #4
0
        protected override void Update()
        {
            hitSquares = hitSquares_RealTime = null;

            DamageDealt    = 0;
            BlockTop       = BlockRight = BlockLeft = BlockBottom = false;
            blockBottomMin = blockLeftMin = blockRightMin = blockTopMin = float.PositiveInfinity;
            blockBottomMax = blockTopMax = blockLeftMax = blockRightMax = float.NegativeInfinity;
            if (PositionSrc == null)
            {
                return;
            }
            if (!Enabled)
            {
                return;
            }

            // first run through, resolve intersections only
            hitSquares = new List <MapSquare>();

            foreach (CollisionBox hitbox in hitboxes)
            {
                if (!enabledBoxes.Contains(hitbox.ID))
                {
                    continue;
                }

                hitbox.SetParent(this);
                if (hitbox.Environment) // check collision with environment
                {
                    CheckEnvironment(hitSquares, hitbox);
                }

                Rectangle boundbox = hitbox.BoxAt(PositionSrc.Position);
                hitBlockEntities = new List <Collision>();

                // now check with entity blocks
                if (MovementSrc != null)
                {
                    boundbox = CheckEntityCollisions(hitBlockEntities, hitbox, boundbox);
                }
            }

            // this stores the types of tile we're touching
            HashSet <TileProperties> hitTypes = new HashSet <TileProperties>();

            // first, as an aside, if i'm still touching a blocking entity, i need to react to that
            foreach (Collision collision in hitBlockEntities)
            {
                Rectangle boundBox = collision.myBox.BoxAt(PositionSrc.Position);
                Rectangle rect     = collision.targetBox.BoxAt(collision.targetColl.PositionSrc.Position);
                if (BlockByIntersection(boundBox, rect, false, false))
                {
                    collision.targetColl.Touch(collision.myBox, collision.targetBox);
                    Touch(collision.targetBox, collision.myBox);
                    // for now, entities can only be normal type
                    hitTypes.Add(collision.targetBox.Properties);
                    // now cause friction on the x, a la moving platforms
                    if (collision.targetColl.MovementSrc != null && collision.myBox.PushAway)
                    {
                        PositionSrc.Offset(collision.targetColl.MovementSrc.VelocityX, 0);
                    }
                }
            }

            // now determine who i'm still touching, the resulting effects
            // notice - there's really no one to speak on behalf of the environment,
            // so we need to inflict the effects upon ourself
            foreach (CollisionBox hitbox in hitboxes)
            {
                if (!enabledBoxes.Contains(hitbox.ID))
                {
                    continue;
                }
                ReactForHitbox(hitSquares, hitTypes, hitbox);
            }

            if (MovementSrc != null)
            {
                if (BlockTop && MovementSrc.VelocityY < 0)
                {
                    MovementSrc.VelocityY = 0;
                }
                if (BlockBottom && MovementSrc.VelocityY > 0)
                {
                    MovementSrc.VelocityY = 0;
                }
            }

            // react to tile effects
            foreach (TileProperties tileprops in hitTypes)
            {
                ReactToTileEffect(tileprops);
            }
        }