/// <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; } } }
public GameplayModel(BunnyGame game) : base(game) { GameOver = false; this.game = game; KillLimit = 1000000; PlayerList = new List <Player>(); BloodParticleList = new List <BloodParticle>(); ProjectileList = new List <Projectile>(); BlackHoleList = new List <BlackHole>(); PlanetList = new List <Planet>(); EntityList = new List <Entity>(); PhysicalObjectList = new List <PhysicalObject>(); GravityPointList = new List <GravityPoint>(); ExplosionList = new List <Explosion>(); collisionEngine = new CollisionEngine(this); updateEngine = new UpdateEngine(this); ScoreBoard = new Dictionary <Player, Scores>(); MaxPlayers = 4; RespawnDelay = 120; }
/// <summary> /// Places an entity in the level so its bounding box is fully inside the level and not colliding with the terrain. /// </summary> /// <param name="e">The entity to be placed.</param> public void PlaceEntity(Entity e) { int timeOutCounter = 100; bool freespaceFound = true; e.Position = new Vector2(rand.Next(Terrain.Width), rand.Next(Terrain.Height)); do { if (CollisionEngine.BoundingBoxTerrainCollision(e.BoundingBox, Terrain) || !Terrain.IsRectangleClear(e.BoundingBox)) { freespaceFound = false; } else { foreach (Entity e2 in EntityList) { if (e.BoundingBox.Intersects(e2.BoundingBox)) { freespaceFound = false; } } } timeOutCounter--; if (timeOutCounter == 0) { DestroyCircle((int)e.Position.X, (int)e.Position.Y, (int)(MathHelper.Max(e.Size.X, e.Size.Y) / 2)); freespaceFound = true; } if (!freespaceFound) { e.Position -= new Vector2(0, e.Size.Y / 2); if (e.Position.Y - e.Origin.Y < 0) { e.Position = new Vector2(rand.Next(Terrain.Width), rand.Next(Terrain.Height)); } } } while (!freespaceFound); }
/// <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; } }