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