/// <summary> /// Checks if the player hits the ground or a planet. /// </summary> /// <param name="p">The player.</param> private void CheckAirCollision(Player p) { if (CollidesWithBorders(p)) { PlacePlayerInsideLevel(p); if (PhysicsEngine.CollidesWithBottomBorder(p, model.Terrain)) { p.IsStandingOn = GroundTypes.Ground; } } p.Position += p.TotalVelocity; //Check if next position collides with terrain bool collision = CollisionEngine.IntersectPixels(p.WorldTransform, (int)p.Size.X, (int)p.Size.Y, p.ColorData, model.Terrain); //bool collision = CollisionEngine.BoundingBoxTerrainCollision(p.BoundingBox, model.Terrain); if (collision) //check player vs terrain { Rectangle bottomHalf = PhysicsEngine.GetBottomHalf(p.BoundingBox); if (BunnyGame.DebugMode) { model.View.DrawRectangle(bottomHalf, Color.Green); } bool bottomCollision = CollisionEngine.BoundingBoxTerrainCollision(bottomHalf, model.Terrain); p.Position -= p.TotalVelocity; if (bottomCollision) { //bottom half collides with terrain PlacePlayerOnGround(p); } else { //top half collides with terrain p.SelfVelocity = -p.SelfVelocity; p.Velocity = -p.Velocity; } } else { //Check player vs. planets Planet planet = CollidesWithPlanet(p); if (planet != null) { PlacePlayerOnPlanet(p, planet); collision = true; } if (!collision) { p.Position -= p.TotalVelocity; } } }
/// <summary> /// Checks if projectiles' center point will collide with terrain or players, /// and notifies model if it does. /// </summary> private void CalculateProjectileCollisions() //TODO: Modify method to handle bouncing projectiles, terrain-adding projectiles, etc. { int margin = 200; //Projectile can go this far out of screen before disappearing for (int i = 0; i < model.ProjectileList.Count; i++) { Projectile proj = model.ProjectileList.ElementAt(i); bool collisionFound = false; Vector2 originalPos = proj.Position; Vector2 nextPos = proj.Position + proj.TotalVelocity; Vector2 stepSize = Vector2.Normalize(proj.TotalVelocity); Vector2 collisionPoint; do { //Check projectile vs. terrain, if entity limit is reached use cheaper collision detection bool collision = model.IsEntityLimitReached ? !model.Terrain.IsRectangleClear(proj.BoundingBox) : CollisionEngine.IntersectPixels(proj.WorldTransform, (int)proj.SourceRect.Width, (int)proj.SourceRect.Height, proj.ColorData, Matrix.Identity, model.Terrain.Width, model.Terrain.Height, model.Terrain.GetTextureColor(), out collisionPoint); //if(!model.Terrain.IsPositionClear(nextStep)) if (collision) { model.TerrainHit(proj, proj.Position); collisionFound = true; }// Check projectile vs. black hole else if (CollidesWithBlackHole(proj)) { model.BlackHoleHit(proj); collisionFound = true; } else if (CollidesWithPlanet(proj) != null) { model.PlanetHit(proj); collisionFound = true; } else {//Check projectile vs. player foreach (Player p in model.PlayerList) { if (p.Enabled) { //collision = model.IsEntityLimitReached ? p.BoundingBox.Contains((int)proj.Position.X, (int)proj.Position.Y) : CollisionEngine.IntersectPixels(proj.WorldTransform, (int)proj.Size.X, (int)proj.Size.Y, proj.ColorData, p.WorldTransform, (int)p.Size.X, (int)p.Size.Y, p.ColorData); collision = p.BoundingBox.Contains(proj.BoundingBox); if (collision) { model.PlayerHit(proj, p, proj.Position); collisionFound = true; } } } if (!collisionFound) { proj.Position += stepSize; } } } while (!collisionFound && Vector2.Distance(proj.Position, nextPos) < 1); /* Explode projectile if it hits bottom */ if (!collisionFound && proj.Ammunition.IsExplosive && PhysicsEngine.CollidesWithBottomBorder(proj, model.Terrain)) { model.TerrainHit(proj, proj.Position); } Rectangle extendedBoundingBox = new Rectangle(0, 0, model.Terrain.Width, model.Terrain.Height); extendedBoundingBox.Inflate(margin, margin); if (!collisionFound && !extendedBoundingBox.Contains(Utility.ToPoint(proj.Position))) { //Projectile outside level bounds model.ProjectileOutsideLevelBounds(proj); collisionFound = true; } proj.Position = originalPos; } }