/// <summary> /// Used for collision detection. Grid is set up to determine what needs to check for collision. /// </summary> private static ShipDrone CollisionTest(ShipDrone ship) { ShipDrone collidedWith = null; /* * Check ship's collision */ float[] shipCoord = ship.RenderShip(); byte[] colId = AddCollisionBoxes(shipCoord[0], shipCoord[1], (int)shipCoord[3], new byte[] { ship.Id, 0 }); // colId will only be not null if two objects share the same collision box if (colId != null) { // colId[n] = 0 is always a ship. Anything higher would be one of the ship's projectiles. if (colId[1] > 0) { // we will need to determine if a real collision has occurred. We'll need to retrieve the size of the projectile. // get the projectile, since we start projectiles at 1, we need to subtract 1 float[] projectile = ships[colId[0]].GetProjectile(colId[1] - 1); //Console.WriteLine("Possible: Ship hit bullet."); double distance = Math.Sqrt((shipCoord[0] - projectile[0]) * (shipCoord[0] - projectile[0]) + (shipCoord[1] - projectile[1]) * (shipCoord[1] - projectile[1])); if (distance < shipCoord[3] + projectile[3]) { // do not allow ship to collide if still at respawn point if (!(ship.FreezeShipMovement && ship.Id == myShipID)) { //Console.WriteLine("Ship hit bullet."); float[] velShip = ship.GetShipMomentum(); float[] velProjectile = ships[colId[0]].GetProjectileMomentum(colId[1] - 1); float vx = (velShip[0] * (velShip[2] - velProjectile[2]) + 2 * velProjectile[2] * velProjectile[0]) / (velShip[2] + velProjectile[2]); float vy = (velShip[1] * (velShip[2] - velProjectile[2]) + 2 * velProjectile[2] * velProjectile[1]) / (velShip[2] + velProjectile[2]); ship.SetShipVeloctiy(vx, vy); float[] projectileToExplosion = ships[colId[0]].RemoveProjectile(colId[1] - 1); explosions.Add(new Explosion(projectileToExplosion[0], projectileToExplosion[1], projectileToExplosion[2], EXPLOSION_STREAMS, EXPLOSION_SPAN, EXPLOSION_STRENGTH)); // if the main ship has lost all health and should be reset to respawn point if (ship.Id == myShipID) { if (ship.ChangeHealth((-1) * ship.ProjectileDamage)) RespawnShip(); text.RefreshTexture(); text.Update(0, "HEALTH " + (int)((ship.Health * 100) / S_HEALTH) + "%"); text.Update(1, "LIVES " + ship.Lives); } } } } else { //Console.WriteLine("Possible: Ships collided."); float[] otherShipCoord = ships[colId[0]].RenderShip(); double distance = Math.Sqrt((shipCoord[0] - otherShipCoord[0]) * (shipCoord[0] - otherShipCoord[0]) + (shipCoord[1] - otherShipCoord[1]) * (shipCoord[1] - otherShipCoord[1])); if (distance < shipCoord[3] + otherShipCoord[3]) { // do not allow ships to collide if still at respawn point if (!ship.FreezeShipMovement && !ships[colId[0]].FreezeShipMovement) { //Console.WriteLine("Ships collided."); float[] velShip = ship.GetShipMomentum(); float[] velShip2 = ships[colId[0]].GetShipMomentum(); float vx1 = (velShip[0] * (velShip[2] - velShip2[2]) + 2 * velShip2[2] * velShip2[0]) / (velShip[2] + velShip2[2]); float vx2 = (velShip2[0] * (velShip2[2] - velShip[2]) + 2 * velShip[2] * velShip[0]) / (velShip[2] + velShip2[2]); float vy1 = (velShip[1] * (velShip[2] - velShip2[2]) + 2 * velShip2[2] * velShip2[1]) / (velShip[2] + velShip2[2]); float vy2 = (velShip2[1] * (velShip2[2] - velShip[2]) + 2 * velShip[2] * velShip[1]) / (velShip[2] + velShip2[2]); float averageX = (shipCoord[0] + otherShipCoord[0]) / 2; float averageY = (shipCoord[1] + otherShipCoord[1]) / 2; float combinedVel = (float)Math.Sqrt((velShip[0] - velShip2[0]) * (velShip[0] - velShip2[0]) + (velShip[1] - velShip2[1]) * (velShip[1] - velShip2[1])); float angle = (float)(Math.Atan2(shipCoord[0] - otherShipCoord[0], shipCoord[1] - otherShipCoord[1]) * 180 / Math.PI); //Console.WriteLine(combinedVel); Explosion e1 = new Explosion(averageX, averageY, angle + 90, S_EXPLOSION_STREAMS, S_EXPLOSION_SPAN, (combinedVel / 1.4f)); Explosion e2 = new Explosion(averageX, averageY, angle - 90, S_EXPLOSION_STREAMS, S_EXPLOSION_SPAN, (combinedVel / 1.4f)); e1.Color = new byte[] { 255, 220, 150 }; e2.Color = new byte[] { 255, 220, 150 }; explosions.Add(e1); explosions.Add(e2); ship.SetShipVeloctiy(vx1, vy1); ships[colId[0]].SetShipVeloctiy(vx2, vy2); collidedWith = ships[colId[0]]; if (ships[colId[0]].Id == myShipID) { // if the main ship has lost all health and should be reset to respawn point if (ships[colId[0]].ChangeHealth((-1) * combinedVel * MOMENTUM_DAMAGE_RATIO)) RespawnShip(); text.RefreshTexture(); text.Update(0, "HEALTH " + (int)((ships[colId[0]].Health * 100) / S_HEALTH) + "%"); text.Update(1, "LIVES " + ships[colId[0]].Lives); } if (ship.Id == myShipID) { // if the main ship has lost all health and should be reset to respawn point if (ship.ChangeHealth((-1) * combinedVel * MOMENTUM_DAMAGE_RATIO)) RespawnShip(); text.RefreshTexture(); text.Update(0, "HEALTH " + (int)((ship.Health * 100) / S_HEALTH) + "%"); text.Update(1, "LIVES " + ship.Lives); } } } } } /* * Check to make sure ship hasn't collided with edge of screen */ // check width (x) if (shipCoord[0] < 0 || shipCoord[0] > mapWidth) { float[] velShip = ship.GetShipMomentum(); float combinedVel = Math.Abs(velShip[0]); ship.SetShipVeloctiy(-velShip[0], velShip[1]); if (ship.Id == myShipID) { // if the main ship has lost all health and should be reset to respawn point if (ship.ChangeHealth((-1) * combinedVel * MOMENTUM_DAMAGE_RATIO)) RespawnShip(); text.RefreshTexture(); text.Update(0, "HEALTH " + (int)((ship.Health * 100) / S_HEALTH) + "%"); text.Update(1, "LIVES " + ship.Lives); } } // check height (y) if (shipCoord[1] < 0 || shipCoord[1] > mapHeight) { float[] velShip = ship.GetShipMomentum(); float combinedVel = Math.Abs(velShip[1]); ship.SetShipVeloctiy(velShip[0], -velShip[1]); if (ship.Id == myShipID) { // if the main ship has lost all health and should be reset to respawn point if (ship.ChangeHealth((-1) * combinedVel * MOMENTUM_DAMAGE_RATIO)) RespawnShip(); text.RefreshTexture(); text.Update(0, "HEALTH " + (int)((ship.Health * 100) / S_HEALTH) + "%"); text.Update(1, "LIVES " + ship.Lives); } } /* * Test projectile's collision */ List<float[]> projectiles = ship.RenderProjectiles(); for (int i = 0; i < projectiles.Count; i++) { colId = AddCollisionBoxes(projectiles[i][0], projectiles[i][1], (int)projectiles[i][3], new byte[] { ship.Id, (byte)(i + 1) }); if (colId != null) { if (colId[1] > 0) { float[] otherProjectile = ships[colId[0]].GetProjectile(colId[1] - 1); //Console.WriteLine("Possible: Bullets collided."); double distance; if (otherProjectile.Length == 0) distance = 0; else distance = Math.Sqrt((otherProjectile[0] - projectiles[i][0]) * (otherProjectile[0] - projectiles[i][0]) + (otherProjectile[1] - projectiles[i][1]) * (otherProjectile[1] - projectiles[i][1])); if (distance == 0 || distance < otherProjectile[3] + projectiles[i][3]) { ships[colId[0]].RemoveProjectile(colId[1] - 1); float[] projectileToExplosion = ship.RemoveProjectile(i); //Console.WriteLine("Bullets collided."); explosions.Add(new Explosion(projectileToExplosion[0], projectileToExplosion[1], projectileToExplosion[2], P_EXPLOSION_STREAMS, P_EXPLOSION_SPAN, P_EXPLOSION_STRENGTH)); } } else { //Console.WriteLine("Possible: Ship hit with bullet..."); shipCoord = ships[colId[0]].RenderShip(); double distance = Math.Sqrt((shipCoord[0] - projectiles[i][0]) * (shipCoord[0] - projectiles[i][0]) + (shipCoord[1] - projectiles[i][1]) * (shipCoord[1] - projectiles[i][1])); if (distance < shipCoord[3] + projectiles[i][3]) { // do not allow ship to collide if still at respawn point if (!(ships[colId[0]].FreezeShipMovement && ships[colId[0]].Id == myShipID)) { //Console.WriteLine("Ship hit with bullet."); float[] velShip = ships[colId[0]].GetShipMomentum(); float[] velProjectile = ship.GetProjectileMomentum(i); float vx = (velShip[0] * (velShip[2] - velProjectile[2]) + 2 * velProjectile[2] * velProjectile[0]) / (velShip[2] + velProjectile[2]); float vy = (velShip[1] * (velShip[2] - velProjectile[2]) + 2 * velProjectile[2] * velProjectile[1]) / (velShip[2] + velProjectile[2]); ships[colId[0]].SetShipVeloctiy(vx, vy); float[] projectileToExplosion = ship.RemoveProjectile(i); explosions.Add(new Explosion(projectileToExplosion[0], projectileToExplosion[1], projectileToExplosion[2], EXPLOSION_STREAMS, EXPLOSION_SPAN, EXPLOSION_STRENGTH)); if (ships[colId[0]].Id == myShipID) { // if the main ship has lost all health and should be reset to respawn point if (ships[colId[0]].ChangeHealth((-1) * ships[colId[0]].ProjectileDamage)) RespawnShip(); text.RefreshTexture(); text.Update(0, "HEALTH " + (int)((ships[colId[0]].Health * 100) / S_HEALTH) + "%"); text.Update(1, "LIVES " + ships[colId[0]].Lives); } // test health level //if (ships[colId[0]].Id == myShipID) // Console.WriteLine("Health3: " + ships[colId[0]].Health); } } } } } return collidedWith; }
/// <summary> /// Renders a given explosion. The explosion takes on the color given in the parameter. /// </summary> private static void RenderExplosion(byte[] color, Explosion explosion) { List<float[]> streams = explosion.RenderStreams(); foreach (float[] stream in streams) { float fromOrigin = stream[3] / 2; GL.LoadIdentity(); GL.Translate(stream[0], stream[1], 0.0f); GL.Rotate(stream[2], 0.0f, 0.0f, 1.0f); // texture GL.Color3(color); GL.BindTexture(TextureTarget.Texture2D, explosionTex); GL.Begin(PrimitiveType.Quads); GL.TexCoord2(0, 0); GL.Vertex2(-fromOrigin, fromOrigin); GL.TexCoord2(1, 0); GL.Vertex2(fromOrigin, fromOrigin); GL.TexCoord2(1, 1); GL.Vertex2(fromOrigin, -fromOrigin); GL.TexCoord2(0, 1); GL.Vertex2(-fromOrigin, -fromOrigin); GL.End(); GL.BindTexture(TextureTarget.Texture2D, 0); } }