public void AddAsteroid(Asteroid asteroid, int levelWidth, int levelHeight, Random r, float frameDeltaTime) { foreach (var ast in _asteroidsInCell) { HandleCollision(ast, asteroid, levelWidth, levelHeight, r, frameDeltaTime); } _asteroidsInCell.Add(asteroid); }
public void SetUpLevel(AsteroidType[] types, int asteroidPoints, Random r) { Asteroids.Clear(); //Just to make sure it's really empty int width = _gameMain.LevelSize.X; int height = _gameMain.LevelSize.Y; _astCells = new AstCell[width / GameMain.CELL_SIZE][]; for (int i = 0; i < _astCells.Length; i++) { _astCells[i] = new AstCell[height / GameMain.CELL_SIZE]; for (int j = 0; j < _astCells[i].Length; j++) { _astCells[i][j] = new AstCell(); _astCells[i][j].PlayerIsOwedMoney += _gameMain.PayPlayer; } } while (asteroidPoints > 0) { var type = types[r.Next(types.Length)]; Asteroid newAst = new Asteroid(type, width, height, r); Asteroids.Add(newAst); asteroidPoints -= newAst.Point; } }
private List<Asteroid> SpawnAsteroids(Asteroid whichAsteroid) { var newAsteroids = new List<Asteroid>(); if (whichAsteroid.Size == 1) { //Smallest asteroid, do nothing unless it's explosive, in which case, spawn an explosion //TODO: Add explosion code return newAsteroids; } int point = whichAsteroid.Size; while (point > 0) { //Continue spawning until points run out float addVel = 0; //for yellow asteroids, they explode fragments FAST int newSize = _gameMain.Random.Next(whichAsteroid.Size - 1) + 1; Asteroid newAsteroid = new Asteroid(whichAsteroid.AsteroidType, _gameMain.LevelSize.X, _gameMain.LevelSize.Y, _gameMain.Random); switch (whichAsteroid.AsteroidType) { case AsteroidType.GENERIC: newAsteroid.HP = 5 * newSize; break; case AsteroidType.CLUMPY: newAsteroid.HP = 10 * newSize; break; case AsteroidType.GRAVITIC: newAsteroid.HP = 10 * newSize; break; case AsteroidType.REPULSER: newAsteroid.HP = 10 * newSize; break; case AsteroidType.GOLD: newAsteroid.HP = 40 * newSize; break; case AsteroidType.MAGNETIC: newAsteroid.HP = 10 * newSize; break; case AsteroidType.BLACK: newAsteroid.HP = 5 * newSize; break; case AsteroidType.ZIPPY: addVel = 200; newAsteroid.HP = 5 * newSize; break; case AsteroidType.DENSE: newAsteroid.HP = 50 * newSize; break; default: newAsteroid.HP = 20 * newSize; break; } newAsteroid.Size = newSize; newAsteroid.Radius = newAsteroid.Size * 16; newAsteroid.AsteroidSprite = SpriteManager.GetAsteroidSprite(newAsteroid.Size, newAsteroid.Style, _gameMain.Random); var randomAngle = (_gameMain.Random.Next(360) / 180.0) * Math.PI; float tempXVel = (float)Math.Cos(randomAngle) * (75.0f + addVel); float tempYVel = (float)Math.Sin(randomAngle) * (75.0f + addVel); newAsteroid.PositionX = whichAsteroid.PositionX; newAsteroid.PositionY = whichAsteroid.PositionY; newAsteroid.VelocityX = whichAsteroid.VelocityX + tempXVel; newAsteroid.VelocityY = whichAsteroid.VelocityY + tempYVel; point -= newAsteroid.Size; newAsteroids.Add(newAsteroid); } return newAsteroids; }
private static void HandleCollision(Asteroid ast1, Asteroid ast2, int levelWidth, int levelHeight, Random r, float frameDeltaTime) { if (ast1.ToBeRemoved || ast2.ToBeRemoved) { //Some asteroids have clumped together, don't calculate between any asteroids with the asteroid to be removed; return; } if ((ast1.Phase < 100 && ast2.Phase >= 100) || (ast1.Phase >= 100 && ast2.Phase < 100)) { //Out of phase asteroids won't collide with each other. Phased asteroids will collide, as non-phased asteroids will. return; } //create variables that'd be easier to read than function calls float x1 = ast1.PositionX; float y1 = ast1.PositionY; float x2 = ast2.PositionX; float y2 = ast2.PositionY; Utility.GetClosestDistance(x1, y1, x2, y2, levelWidth, levelHeight, out x2, out y2); float v1x = ast1.VelocityX; //e.FrameDeltaTime is the time between frames, less than 1 float v1y = ast1.VelocityY; float v2x = ast2.VelocityX; float v2y = ast2.VelocityY; //get the position plus velocity float tx1 = x1 + v1x * frameDeltaTime; float ty1 = y1 + v1y * frameDeltaTime; float tx2 = x2 + v2x * frameDeltaTime; float ty2 = y2 + v2y * frameDeltaTime; float dx = tx2 - tx1; float dy = ty2 - ty1; float dx2 = x2 - x1; float dy2 = y2 - y1; float r1 = (float)Math.Sqrt(dx * dx + dy * dy); //Get the distance between centers of asteroids float r2 = (float)Math.Sqrt(dx2 * dx2 + dy2 * dy2); if (r1 < ast1.Radius + ast2.Radius && r1 < r2) //Collision! { if (!((ast1.AsteroidType == AsteroidType.CLUMPY && ast2.AsteroidType == AsteroidType.CLUMPY) && ast1.Size + ast2.Size <= 5)) //Make sure it's not clumpy asteroids that can clump together { //Calculate the impulse or change of momentum, or whatever people call it float rx = dx / r1; float ry = dy / r1; float k1 = 2 * ast2.Mass * (rx * (v2x - v1x) + ry * (v2y - v1y)) / (ast1.Mass + ast2.Mass); float k2 = 2 * ast1.Mass * (rx * (v1x - v2x) + ry * (v1y - v2y)) / (ast1.Mass + ast2.Mass); //Adjust the velocities v1x += k1 * rx; v1y += k1 * ry; v2x += k2 * rx; v2y += k2 * ry; //Assign the final value to asteroids ast1.VelocityX = v1x; ast1.VelocityY = v1y; ast2.VelocityX = v2x; ast2.VelocityY = v2y; } else //it's clumpy, clump them together { float firstAsteroidFactor = (ast1.Size * 1.0f) / (ast1.Size + ast2.Size); float secondAsteroidFactor = 1.0f - firstAsteroidFactor; ast1.Size += ast2.Size; ast1.Radius = ast1.Size * 16; ast1.Mass = ast1.Size * 300; ast1.PositionX = (ast1.PositionX + ast2.PositionX) / 2; ast1.PositionY = (ast1.PositionY + ast2.PositionY) / 2; //Combine position and velocity: ast1.VelocityX = (ast1.VelocityX * firstAsteroidFactor) + (ast2.VelocityX * secondAsteroidFactor); ast1.VelocityY = (ast1.VelocityY * firstAsteroidFactor) + (ast2.VelocityY * secondAsteroidFactor); ast1.AsteroidSprite = SpriteManager.GetAsteroidSprite(ast1.Size, ast1.Style, r); //TODO: Combine the remaining HP ast2.ToBeRemoved = true; } } if ((ast1.AsteroidType == AsteroidType.REPULSER || ast2.AsteroidType == AsteroidType.REPULSER) && (r1 < ast1.Size * 64 || r1 < ast2.Size * 64)) { var degree = Math.Atan2(ty2 - ty1, tx2 - tx1); float repulsingForce; if (ast1.AsteroidType == AsteroidType.REPULSER && ast2.AsteroidType == AsteroidType.REPULSER) { if (r1 < ast1.Size * 64 && r1 < ast2.Size * 64) { //Double the power repulsingForce = ((ast1.Size * 96) - r1) + ((ast2.Size * 96) - r1); } else if (r1 < ast1.Size * 64) { repulsingForce = ((ast1.Size * 96) - r1); } else { repulsingForce = ((ast2.Size * 96) - r1); } } else { if (ast1.AsteroidType == AsteroidType.REPULSER) { repulsingForce = ((ast1.Size * 96) - r1); } else { repulsingForce = ((ast2.Size * 96) - r1); } } ast2.VelocityX += (float)(repulsingForce * Math.Cos(degree) * frameDeltaTime * (ast1.Mass / (float)(ast1.Mass + ast2.Mass))); ast2.VelocityY += (float)(repulsingForce * Math.Sin(degree) * frameDeltaTime * (ast1.Mass / (float)(ast1.Mass + ast2.Mass))); ast1.VelocityX -= (float)(repulsingForce * Math.Cos(degree) * frameDeltaTime * (ast2.Mass / (float)(ast1.Mass + ast2.Mass))); ast1.VelocityY -= (float)(repulsingForce * Math.Sin(degree) * frameDeltaTime * (ast2.Mass / (float)(ast1.Mass + ast2.Mass))); } if ((ast1.AsteroidType == AsteroidType.GRAVITIC || ast2.AsteroidType == AsteroidType.GRAVITIC) && (r1 < ast1.Size * 64 || r1 < ast2.Size * 64)) { var degree = Math.Atan2(ty2 - ty1, tx2 - tx1); float graviticForce; if (ast1.AsteroidType == AsteroidType.GRAVITIC && ast2.AsteroidType == AsteroidType.GRAVITIC) { if (r1 < ast1.Size * 64 && r1 < ast2.Size * 64) { //Double the power graviticForce = ((ast1.Size * 96) - r1) + ((ast2.Size * 96) - r1); } else if (r1 < ast1.Size * 64) { graviticForce = ((ast1.Size * 96) - r1); } else { graviticForce = ((ast2.Size * 96) - r1); } } else { if (ast1.AsteroidType == AsteroidType.REPULSER) { graviticForce = ((ast1.Size * 96) - r1); } else { graviticForce = ((ast2.Size * 96) - r1); } } ast2.VelocityX -= (float)(graviticForce * Math.Cos(degree) * frameDeltaTime * (ast1.Mass / (float)(ast1.Mass + ast2.Mass))); ast2.VelocityY -= (float)(graviticForce * Math.Sin(degree) * frameDeltaTime * (ast1.Mass / (float)(ast1.Mass + ast2.Mass))); ast1.VelocityX += (float)(graviticForce * Math.Cos(degree) * frameDeltaTime * (ast2.Mass / (float)(ast1.Mass + ast2.Mass))); ast1.VelocityY += (float)(graviticForce * Math.Sin(degree) * frameDeltaTime * (ast2.Mass / (float)(ast1.Mass + ast2.Mass))); } }