// Startet das erste bzw. nächste Level. Erzeugt dazu neue Reihen von Gegnern, die mit jedem Level stärker werden private void InitLevel(int level) { saveGameToDisk(SaveType.JSON); if (level % 5 == 0) { bossEnemy = new cBoss() { DropItem = dropItem, FireMissile = invMissile, Health = 1000 + level * 5000, HealthMax = 1000 + level * 5000, DamageOnContact = 1000000000, Level = level, Location = new Point((this.ClientSize.Width - bossSize.Width) / 2, 50), Size = bossSize, MoveType = MovementType.Suicide, Speed = r.Next(200, 250), Random = r } } ; else { for (int i = 1; i <= 4; i++) { invaderRows.Add(new cInvaderRow(10, 300 + level * 300, this.Width, i, invaderSize, invMissile, dropItem, r, level)); } rowsMovedDownCount = 0; MoveRowDownTimer.Start(); } }
// Löst alle 5 Millisekunden aus und sorgt für die Berechnung aller aktuellen Positionen/Kollisionen // Bewirkt das Neuzeichnen private void GameTimer_Tick(object sender, EventArgs e) { frameLast = frameNow; frameNow = DateTime.Now; TimeSpan deltaTime = new TimeSpan((frameNow - frameLast).Ticks); if (removeCounter % 10 == 0) { // Lösche die Raketen, die nicht mehr im sichtbaren Bereich sind missiles.RemoveAll(x => x.Location.Y < -x.Size.Height); // Lösche die gegnerischen Reihen, in denen kein Gegner mehr übrig ist. invaderRows.RemoveAll(x => x.Invaders.Count == 0); } // Wenn es keine Reihen mehr gibt, ist das Level geschafft, dann nächstes Level initialisieren if (invaderRows.Count == 0 && bossEnemy == null) { InitLevel(level++); } // Treffer berechnen zwischen den A B B Buchstaben und den Gegnern foreach (cMissile m in missiles) { if (m.Collision) { continue; } // Die ABB Rakete nach oben bewegen //m.Location = new Point(m.Location.X, m.Location.Y - m.Speed); m.Move(deltaTime.TotalSeconds); // Prüfen ob die Rakete einen der Gegner getroffen hat // Dazu durch alle Reihen und alle darin enthaltenen Invader schleifen und auf Kollision prüfen if (bossEnemy == null) { foreach (cInvaderRow row in invaderRows) { bool missileDestroyed = false; foreach (cInvader inv in row.Invaders) { if (inv.Health <= 0) { continue; } bool collisionResult = m.CalculateCollision(inv.CollisionArea); if (collisionResult) { inv.Health -= m.Damage; missileDestroyed = true; break; } } if (missileDestroyed) { break; } } } else { bool collisionResult = m.CalculateCollision(bossEnemy.CollisionArea); if (collisionResult) { bossEnemy.Health -= m.Damage; if (bossEnemy.Health <= 0) { bossEnemy = null; } m.Collision = true; } } } // Kollision mit eigenem Raumschiff berechnen. Dazu alle gegnerischen Raketen prüfen, ob sie // das Raumschiff getroffen haben foreach (cMissile m in invMissiles) { if (m is cTargetMissile) { } else { } if (m.Collision) { continue; } //m.Location = new Point(m.Location.X, m.Location.Y + m.Speed); m.Move(spaceShip.Location, deltaTime.TotalSeconds); bool collisionResult = m.CalculateCollision(new Rectangle(spaceShip.Location, spaceShip.Size)); if (collisionResult) { m.Collision = true; spaceShip.DoDamage(m.Damage); } } foreach (cDropItem d in dropItems) { d.Location = new Point(d.Location.X, d.Location.Y + d.Speed); if (d.Collision) { continue; } bool collisionResult = d.CalculateCollision(new Rectangle(spaceShip.Location, spaceShip.Size)); if (collisionResult) { d.Collision = true; if (d.ItemType == DropItemType.Radio) { fireInsaneAmountOfMissiles(); } else if (d.ItemType == DropItemType.Weapon && FireTimer.Interval > 50) { FireTimer.Interval = 500 - spaceShip.WeaponFrequency++ *27; } else { spaceShip.TakeItem(d.ItemType); } } } // Kollisionen zwischen dem Raumschiff und den Gegnern berechnen if (bossEnemy == null) { foreach (cInvaderRow row in invaderRows) { foreach (cInvader inv in row.Invaders) { spaceShip.CalculateCollision(inv); } } } else { spaceShip.CalculateCollision(bossEnemy); } if (removeCounter++ % 5 == 0) { foreach (cInvaderRow row in invaderRows) { score += row.Invaders.Count(x => x.Health <= 0); // Alle Invader aus der Reihe löschen, die kein Leben mehr haben foreach (cInvader inv in row.Invaders) { if (inv.Health <= 0 && r.Next(0, 100) < 50) { InvaderMissileHandler(inv.CenterDropLocation, r.Next(150, 300), true); } } row.Invaders.RemoveAll(x => x.Health <= 0); } missiles.RemoveAll(x => x.Location.Y < 0 || x.Location.X <0 || x.Location.X> this.ClientRectangle.Width); missiles.RemoveAll(x => x.Collision); invMissiles.RemoveAll(x => x.Collision); invMissiles.RemoveAll(x => x.Location.Y > this.ClientRectangle.Height); dropItems.RemoveAll(x => x.Collision); dropItems.RemoveAll(x => x.Location.Y > this.Height); } if (bossEnemy != null) { bossEnemy.Move(spaceShip.Location, deltaTime.TotalSeconds); } // 5% aller Invader sollen stets zum SuicideInvader werden List <cInvader> allInvaders = new List <cInvader>(); foreach (cInvaderRow row in invaderRows) { foreach (cInvader inv in row.Invaders) { allInvaders.Add(inv); inv.Move(spaceShip.Location, deltaTime.TotalSeconds); } } int alreadySuicide = allInvaders.Count(x => x.MoveType == MovementType.Suicide); for (int i = 0; i < (allInvaders.Count * 0.04) - alreadySuicide; i++) { int num = r.Next(0, allInvaders.Count); allInvaders[num].MoveType = MovementType.Suicide; allInvaders[num].Speed = r.Next(200, 300); } if (spaceShip.Health <= 0) { StopGame(); if (MessageBox.Show("Wiederbeleben?", "Game Over", MessageBoxButtons.YesNo) == DialogResult.Yes) { invMissiles.Clear(); missiles.Clear(); dropItems.Clear(); invaderRows.Clear(); spaceShip.Health = spaceShip.HealthMax; spaceShip.Location = new Point((this.Width - spaceShip.Size.Width) / 2, (this.Height - 150)); StartGame(getGameStatus()); } else { if (viewChanger != null) { viewChanger(ViewToSelect.Main, getGameStatus()); } } } Draw(); }