Example #1
0
        private bool CollisionUpdate()
        {
            if (currentHull == null)
            {
                Hull collidedHull = Hull.FindHull(position);
                if (collidedHull != null)
                {
                    if (prefab.DeleteOnCollision)
                    {
                        return(false);
                    }
                    OnWallCollisionOutside(collidedHull);
                }
            }
            else
            {
                Rectangle hullRect        = currentHull.WorldRect;
                Vector2   collisionNormal = Vector2.Zero;
                if (velocity.Y < 0.0f && position.Y - prefab.CollisionRadius * size.Y < hullRect.Y - hullRect.Height)
                {
                    if (prefab.DeleteOnCollision)
                    {
                        return(false);
                    }
                    collisionNormal = new Vector2(0.0f, 1.0f);
                }
                else if (velocity.Y > 0.0f && position.Y + prefab.CollisionRadius * size.Y > hullRect.Y)
                {
                    if (prefab.DeleteOnCollision)
                    {
                        return(false);
                    }
                    collisionNormal = new Vector2(0.0f, -1.0f);
                }
                else if (velocity.X < 0.0f && position.X - prefab.CollisionRadius * size.X < hullRect.X)
                {
                    if (prefab.DeleteOnCollision)
                    {
                        return(false);
                    }
                    collisionNormal = new Vector2(1.0f, 0.0f);
                }
                else if (velocity.X > 0.0f && position.X + prefab.CollisionRadius * size.X > hullRect.Right)
                {
                    if (prefab.DeleteOnCollision)
                    {
                        return(false);
                    }
                    collisionNormal = new Vector2(-1.0f, 0.0f);
                }

                if (collisionNormal != Vector2.Zero)
                {
                    bool gapFound = false;
                    foreach (Gap gap in hullGaps)
                    {
                        if (gap.Open <= 0.9f || gap.IsHorizontal != (collisionNormal.X != 0.0f))
                        {
                            continue;
                        }

                        if (gap.IsHorizontal)
                        {
                            if (gap.WorldRect.Y < position.Y || gap.WorldRect.Y - gap.WorldRect.Height > position.Y)
                            {
                                continue;
                            }
                            int gapDir = Math.Sign(gap.WorldRect.Center.X - currentHull.WorldRect.Center.X);
                            if (Math.Sign(velocity.X) != gapDir || Math.Sign(position.X - currentHull.WorldRect.Center.X) != gapDir)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            if (gap.WorldRect.X > position.X || gap.WorldRect.Right < position.X)
                            {
                                continue;
                            }
                            float hullCenterY = currentHull.WorldRect.Y - currentHull.WorldRect.Height / 2;
                            int   gapDir      = Math.Sign(gap.WorldRect.Y - hullCenterY);
                            if (Math.Sign(velocity.Y) != gapDir || Math.Sign(position.Y - hullCenterY) != gapDir)
                            {
                                continue;
                            }
                        }

                        gapFound = true;
                        break;
                    }

                    if (!gapFound)
                    {
                        OnWallCollisionInside(currentHull, collisionNormal);
                    }
                    else
                    {
                        Hull newHull = Hull.FindHull(position, currentHull);
                        if (newHull != currentHull)
                        {
                            currentHull = newHull;
                            hullGaps    = currentHull == null ? new List <Gap>() : currentHull.ConnectedGaps;
                            OnChangeHull?.Invoke(position, currentHull);
                        }
                    }
                }
            }

            return(true);
        }
Example #2
0
        public bool Update(float deltaTime)
        {
            prevPosition = position;
            prevRotation = rotation;

            //over 3 times faster than position += velocity * deltatime
            position.X += velocity.X * deltaTime;
            position.Y += velocity.Y * deltaTime;

            if (prefab.RotateToDirection)
            {
                if (velocityChange != Vector2.Zero || angularVelocity != 0.0f)
                {
                    rotation = MathUtils.VectorToAngle(new Vector2(velocity.X, -velocity.Y));
                }
            }
            else
            {
                rotation += angularVelocity * deltaTime;
            }

            if (prefab.WaterDrag > 0.0f &&
                (currentHull == null || (currentHull.Submarine != null && position.Y - currentHull.Submarine.DrawPosition.Y < currentHull.Surface)))
            {
                ApplyDrag(prefab.WaterDrag, deltaTime);
            }
            else if (prefab.Drag > 0.0f)
            {
                ApplyDrag(prefab.Drag, deltaTime);
            }

            velocity.X += velocityChange.X * deltaTime;
            velocity.Y += velocityChange.Y * deltaTime;

            size.X += sizeChange.X * deltaTime;
            size.Y += sizeChange.Y * deltaTime;

            alpha += prefab.ColorChange.W * deltaTime;

            color = new Color(
                color.R / 255.0f + prefab.ColorChange.X * deltaTime,
                color.G / 255.0f + prefab.ColorChange.Y * deltaTime,
                color.B / 255.0f + prefab.ColorChange.Z * deltaTime);

            if (prefab.Sprites[spriteIndex] is SpriteSheet)
            {
                animState += deltaTime;
                int frameCount = ((SpriteSheet)prefab.Sprites[spriteIndex]).FrameCount;
                animFrame = (int)Math.Min(Math.Floor(animState / prefab.AnimDuration * frameCount), frameCount - 1);
            }

            lifeTime -= deltaTime;
            if (lifeTime <= 0.0f || alpha <= 0.0f || size.X <= 0.0f || size.Y <= 0.0f)
            {
                return(false);
            }

            if (!prefab.DeleteOnCollision && !prefab.CollidesWithWalls)
            {
                return(true);
            }

            if (currentHull == null)
            {
                Hull collidedHull = Hull.FindHull(position);
                if (collidedHull != null)
                {
                    if (prefab.DeleteOnCollision)
                    {
                        return(false);
                    }
                    OnWallCollisionOutside(collidedHull);
                }
            }
            else
            {
                Vector2 collisionNormal = Vector2.Zero;
                if (velocity.Y < 0.0f && position.Y - prefab.CollisionRadius * size.Y < currentHull.WorldRect.Y - currentHull.WorldRect.Height)
                {
                    if (prefab.DeleteOnCollision)
                    {
                        return(false);
                    }
                    collisionNormal = new Vector2(0.0f, 1.0f);
                }
                else if (velocity.Y > 0.0f && position.Y + prefab.CollisionRadius * size.Y > currentHull.WorldRect.Y)
                {
                    if (prefab.DeleteOnCollision)
                    {
                        return(false);
                    }
                    collisionNormal = new Vector2(0.0f, -1.0f);
                }
                else if (velocity.X < 0.0f && position.X - prefab.CollisionRadius * size.X < currentHull.WorldRect.X)
                {
                    if (prefab.DeleteOnCollision)
                    {
                        return(false);
                    }
                    collisionNormal = new Vector2(1.0f, 0.0f);
                }
                else if (velocity.X > 0.0f && position.X + prefab.CollisionRadius * size.X > currentHull.WorldRect.Right)
                {
                    if (prefab.DeleteOnCollision)
                    {
                        return(false);
                    }
                    collisionNormal = new Vector2(-1.0f, 0.0f);
                }

                if (collisionNormal != Vector2.Zero)
                {
                    bool gapFound = false;
                    foreach (Gap gap in hullGaps)
                    {
                        if (gap.IsHorizontal != (collisionNormal.X != 0.0f))
                        {
                            continue;
                        }

                        if (gap.IsHorizontal)
                        {
                            if (gap.WorldRect.Y < position.Y || gap.WorldRect.Y - gap.WorldRect.Height > position.Y)
                            {
                                continue;
                            }
                            int gapDir = Math.Sign(gap.WorldRect.Center.X - currentHull.WorldRect.Center.X);
                            if (Math.Sign(velocity.X) != gapDir || Math.Sign(position.X - currentHull.WorldRect.Center.X) != gapDir)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            if (gap.WorldRect.X > position.X || gap.WorldRect.Right < position.X)
                            {
                                continue;
                            }
                            float hullCenterY = currentHull.WorldRect.Y - currentHull.WorldRect.Height / 2;
                            int   gapDir      = Math.Sign(gap.WorldRect.Y - hullCenterY);
                            if (Math.Sign(velocity.Y) != gapDir || Math.Sign(position.Y - hullCenterY) != gapDir)
                            {
                                continue;
                            }
                        }

                        gapFound = true;
                        break;
                    }

                    if (!gapFound)
                    {
                        OnWallCollisionInside(currentHull, collisionNormal);
                    }
                    else
                    {
                        Hull newHull = Hull.FindHull(position);
                        if (newHull != currentHull)
                        {
                            currentHull = newHull;
                            hullGaps    = currentHull == null ? new List <Gap>() : currentHull.ConnectedGaps;
                            OnChangeHull?.Invoke(position, currentHull);
                        }
                    }
                }
            }

            return(true);
        }