Cele lekcji
Po zakończeniu tej lekcji…
- Nie nauczysz się niczego nowego. Dokończysz program, korzystając z wiedzy, którą już dysponujesz.
Stworzymy teraz funkcje, z których gracz będzie korzystał podczas walki z potworami.
Postać może wykonać dwie akcje (poza ucieczką z walki): użyć broni na potworze lub użyć mikstury leczniczej na sobie – jeśli ma ją w ekwipunku.
Poniżej znajduje się pseudokod obu funkcji:
Użycie funkcji broni
- Pobierz aktualnie wybraną broń z formantu ComboBox cboWeapons
- Określ obrażenia zadane potworowi przez gracza
- Pomniejsz punkty CurrentHitPoints zgodnie z obrażeniami
- Wyświetl komunikat
- Jeśli potwór jest martwy (ma zero punktów wytrzymałości)
- Wyświetl komunikat o zwycięstwie
- Przydziel graczowi punkty doświadczenia za zabicie potwora
- Wyświetl komunikat
- Przydziel graczowi złoto za zabicie potwora
- Wyświetl komunikat
- Przydziel łupy za potwora
- Wyświetl komunikat dla każdego łupu
- Dodaj odpowiednie przedmioty do ekwipunku gracza
- Odśwież dane gracza w interfejsie użytkownika
- Złoto i punkty doświadczenia ExperiencePoints
- Ekwipunek i formanty ComboBox
- „Przenieś” gracza do bieżącej lokacji
- Spowoduje to uzdrowienie gracza i stworzenie nowego potwora
- Jeśli potwór nadal żyje
- Określ obrażenia zadane potworowi
- Wyświetl komunikat
- Odejmij punkty obrażeń od aktualnych punktów obrażeń CurrentHitPoints
- Odśwież dane gracza w interfejsie użytkownika
- Jeśli gracz jest martwy (ma zero punktów wytrzymałości)
- Wyświetl komunikat
- „Przenieś” gracza do lokacji początkowej
Używanie funkcji eliksiru
- Uzyskaj aktualnie wybrany eliksir z formantu cboPotions ComboBox
- Zwiększ liczbę punktów wytrzymałości CurrentHitPoints gracza
- Liczba punktów CurrentHitPoints nie może być większa od maksymalnej liczby punktów wytrzymałości MaximumHitPoints
- Usuń miksturę z ekwipunku gracza
- Wyświetl komunikat
- Tura ataku potwora
- Określ obrażenia zadane potworowi
- Wyświetl komunikat
- Odejmij punkty obrażeń od aktualnych punktów obrażeń CurrentHitPoints
- Odśwież dane gracza w interfejsie użytkownika
- Jeśli gracz jest martwy (ma zero punktów wytrzymałości)
- Wyświetl komunikat
- „Przenieś” gracza do lokacji początkowej
- Odśwież dane gracza w interfejsie użytkownika
Są to znacznie prostsze funkcje niż funkcja MoveTo().
Będziemy mogli korzystać z niektórych mniejszych funkcji, które stworzyliśmy podczas refaktoryzacji, na przykład z funkcji AddItemToInventory() w klasie Player, jeśli gracz pokona potwora i otrzyma łupy.
Dodanie funkcji walk z potworami
Etap 1: Uruchom aplikację Visual Studio i otwórz swoje rozwiązanie.
Etap 2: Aby rozpocząć pracę z kodem interfejsu użytkownika, prawym przyciskiem myszy kliknij formularz SuperAdventure.cs w projekcie SuperAdventure.
Aby dodać możliwość używania broni i mikstur podczas walk, można dodać poniższy kod lub zastąpić kod SuperAdventure.cs, używając poniższego kodu: https://gist.github.com/ScottLilly/b20787650f2ab2a78362
Do funkcji btnUseWeapon_Click dodaj:
private void btnUseWeapon_Click(object sender, EventArgs e) { // Get the currently selected weapon from the cboWeapons ComboBox Weapon currentWeapon = (Weapon)cboWeapons.SelectedItem; // Determine the amount of damage to do to the monster int damageToMonster = RandomNumberGenerator.NumberBetween(currentWeapon.MinimumDamage, currentWeapon.MaximumDamage); // Apply the damage to the monster's CurrentHitPoints _currentMonster.CurrentHitPoints -= damageToMonster; // Display message rtbMessages.Text += "You hit the " + _currentMonster.Name + " for " + damageToMonster.ToString() + " points." + Environment.NewLine; // Check if the monster is dead if(_currentMonster.CurrentHitPoints <= 0) { // Monster is dead rtbMessages.Text += Environment.NewLine; rtbMessages.Text += "You defeated the " + _currentMonster.Name + Environment.NewLine; // Give player experience points for killing the monster _player.ExperiencePoints += _currentMonster.RewardExperiencePoints; rtbMessages.Text += "You receive " + _currentMonster.RewardExperiencePoints.ToString() + " experience points" + Environment.NewLine; // Give player gold for killing the monster _player.Gold += _currentMonster.RewardGold; rtbMessages.Text += "You receive " + _currentMonster.RewardGold.ToString() + " gold" + Environment.NewLine; // Get random loot items from the monster List<InventoryItem> lootedItems = new List<InventoryItem>(); // Add items to the lootedItems list, comparing a random number to the drop percentage foreach(LootItem lootItem in _currentMonster.LootTable) { if(RandomNumberGenerator.NumberBetween(1, 100) <= lootItem.DropPercentage) { lootedItems.Add(new InventoryItem(lootItem.Details, 1)); } } // If no items were randomly selected, then add the default loot item(s). if(lootedItems.Count == 0) { foreach(LootItem lootItem in _currentMonster.LootTable) { if(lootItem.IsDefaultItem) { lootedItems.Add(new InventoryItem(lootItem.Details, 1)); } } } // Add the looted items to the player's inventory foreach(InventoryItem inventoryItem in lootedItems) { _player.AddItemToInventory(inventoryItem.Details); if(inventoryItem.Quantity == 1) { rtbMessages.Text += "You loot " + inventoryItem.Quantity.ToString() + " " + inventoryItem.Details.Name +Environment.NewLine; } else { rtbMessages.Text += "You loot " + inventoryItem.Quantity.ToString() + " " + inventoryItem.Details.NamePlural + Environment.NewLine; } } // Refresh player information and inventory controls lblHitPoints.Text = _player.CurrentHitPoints.ToString(); lblGold.Text = _player.Gold.ToString(); lblExperience.Text = _player.ExperiencePoints.ToString(); lblLevel.Text = _player.Level.ToString(); UpdateInventoryListInUI(); UpdateWeaponListInUI(); UpdatePotionListInUI(); // Add a blank line to the messages box, just for appearance. rtbMessages.Text += Environment.NewLine; // Move player to current location (to heal player and create a new monster to fight) MoveTo(_player.CurrentLocation); } else { // Monster is still alive // Determine the amount of damage the monster does to the player int damageToPlayer = RandomNumberGenerator.NumberBetween(0, _currentMonster.MaximumDamage); // Display message rtbMessages.Text += "The " + _currentMonster.Name + " did " + damageToPlayer.ToString() + " points of damage." + Environment.NewLine; // Subtract damage from player _player.CurrentHitPoints -= damageToPlayer; // Refresh player data in UI lblHitPoints.Text = _player.CurrentHitPoints.ToString(); if(_player.CurrentHitPoints <= 0) { // Display message rtbMessages.Text += "The " + _currentMonster.Name + " killed you." + Environment.NewLine; // Move player to "Home" MoveTo(World.LocationByID(World.LOCATION_ID_HOME)); } } }
Następnie do funkcji btnUsePotion_Click dodaj:
private void btnUsePotion_Click(object sender, EventArgs e) { // Get the currently selected potion from the combobox HealingPotion potion = (HealingPotion)cboPotions.SelectedItem; // Add healing amount to the player's current hit points _player.CurrentHitPoints = (_player.CurrentHitPoints + potion.AmountToHeal); // CurrentHitPoints cannot exceed player's MaximumHitPoints if(_player.CurrentHitPoints > _player.MaximumHitPoints) { _player.CurrentHitPoints = _player.MaximumHitPoints; } // Remove the potion from the player's inventory foreach(InventoryItem ii in _player.Inventory) { if(ii.Details.ID == potion.ID) { ii.Quantity--; break; } } // Display message rtbMessages.Text += "You drink a " + potion.Name + Environment.NewLine; // Monster gets their turn to attack // Determine the amount of damage the monster does to the player int damageToPlayer = RandomNumberGenerator.NumberBetween(0, _currentMonster.MaximumDamage); // Display message rtbMessages.Text += "The " + _currentMonster.Name + " did " + damageToPlayer.ToString() + " points of damage." + Environment.NewLine; // Subtract damage from player _player.CurrentHitPoints -= damageToPlayer; if(_player.CurrentHitPoints <= 0) { // Display message rtbMessages.Text += "The " + _currentMonster.Name + " killed you." + Environment.NewLine; // Move player to "Home" MoveTo(World.LocationByID(World.LOCATION_ID_HOME)); } // Refresh player data in UI lblHitPoints.Text = _player.CurrentHitPoints.ToString(); UpdateInventoryListInUI(); UpdatePotionListInUI(); }
W tych dwóch funkcjach nie pojawia się nic nowego. Dodawane są po prostu kolejne pętle if i foreach do obsługi działań gracza podczas walki.
Podsumowanie
Teraz gra już działa, a gracz może poruszać się po świecie, wykonywać zadania, walczyć z potworami, otrzymywać łupy i wykonywać zadania.
Te nowe funkcje można jeszcze refaktoryzować, ponieważ są długie i wykonują kilka czynności, ale to już zadanie dla Ciebie.
Łącza do tej lekcji