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); }
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); }