Voorkennis
- programmeer-basics
- programmeertaal: C#
Doel
- leren en toepassen van drie van de vier pilaren van Object Oriented Programming in de C# taal:
- Encapsulation
- Inheritance
- Polymorphism
Als je meer met ASP.net wilt gaan doen is het noodzakelijk dat je meer kennis opdoet van OOP (Object Oriented Programming) met C#; want alles draait op OOP principes als je met ASP.net gaat werken!
Omdat deze principes abstract in nature zijn en snel te veel kunnen worden, worden deze concepten geintroduceerd in opgedeelde uitleg filmpjes en maak je een Textbased Adventure Game via een commandline applicatie! Waarom specifiek een game? De mechanieken van een game lenen zich heel goed uit voor de verschillende onderdelen van OOP.
Opdrachten
Vantevoren
Voordat je begint met de eerste opdracht:
Volg de instructie video om een start te maken met de textbased adventure game. Alle opvolgende opdrachten breiden deze start uit met nieuwe mechanieken en leer je verschillende principes van OOP programmeren. Eind resultaat is dus 1 werkende text based adventure game!
Uiteindelijk ben je vrij om opdrachten uit te breiden of eigen mechanics toe te voegen. Hoe uitgebreider jij het maakt hoe beter het een centerpiece kan zijn in jouwn portfolio!
Opdracht 1 - Humble Beginnings
Voordat je verder gaat moet je het volgende hebben gedaan: het instantiëren van een enemy object en deze kunnen we beschadigen door een commando uit te typen. Heb je dat nog niet, volg dan de video in het Vantevoren blok hierboven.
Heb je deze onderdelen al wel klaar dan heb je al een kleine start gemaakt met een text based adventure game! Maar we kunnen het nog zeker geen 'echte' game noemen. Wat je nu hebt gemaakt ga je uitbreiden tot een werkende game door de vijf opdrachten uit te voeren; en ondertussen leer je ook nog eens OOP programmeren in C#!
Breid wat je tot nu toe hebt met het volgende uit:
Extra
Experimenteer metRandom() om een variatie inhealth endamage te implementeren.
Een keer aanvallen en aangevallen worden is niet heel spectaculair. Stop daarom het geven en krijgen van schade in een loop zodat beide de speler en vijand kunnen blijven vechten tot een van de twee dood is. Dit betekend dus dat je meerdere keren commando's kan invoeren. Voeg een nieuwe
Het herhalen van acties en mechanics om tot een bepaalt doel te komen noemen we ook wel een gameloop.
Als de vijand is verslagen stopt de gameloop met een WriteLine
(omschrijf wat de speler/vijand doet en wat het gevolg is. Bijv:
Console.BackgroundColor = ConsoleColor.Blue;
Console.ForegroundColor = ConsoleColor.White;
Maak er wat moois van!
Extra
Probeer alvast deplayerInput
in een switch case te stoppen, met ‘Attack’ en ‘Use item’ als cases. Voor nu kan je bij ‘Use item’ de speler een waarde laten ‘healen’ (health weer terug krijgen. Dit mag met een vaste waarde maar ook metRandom() ).
Opdracht 2 - And they won't stop coming!
Bekijk de videos van Inheritance, Constructors en Getters&Setters.
Maak eerst een superklasse
Zet de variabelen van
Zorg ervoor dat alle gedeelde variabelen tussen
Met het verplaatsen van het aanmaken van de enemy naar bovenin de gameloop kan je er voor zorgen dat bij elke loop er een nieuwe
TIP: de Enemy variabele moet NIET in de loop, het initialiseren ervan wel!.
De loop stopt nu dus alleen wanneer de speler dood gaat.
Extra
Geef nieuweEnemies een randomhealth endamage waarde (wees gebalanceerd!)bonus: geef nieuwe
Enemies een random naam uit een naam verzameling (randomize de index)
Je kan nu eindeloos vechten tegen enemies tot jij, de speler, dood gaat.
Voeg nu de volgende functionaliteit toe (je zou nu de kennis moeten hebben om dit zelf te implementeren. X en Y zijn waardes die je zelf 'gebalanceerd' bepaalt):
Geef de speler een
level en eenexperience variabele; geef alleen level de waarde 1. Bij elke verslagen vijand krijgt de speler een X aantal exp erbij (via eensetter ). Wanneer deexperience hoger is dan Y gaat de speler LEVELUP (via eensetter ). Bij elke LEVELUP worden de volgende variabelen gewijzigd:
- level van de speler +1
- maxHealth van de speler + Random tussen 5 en 10
- health krijgt de waarde van maxHealth
- damage van de speler + Random tussen 1 en 3
- De Y grens voor een levelup * 1.2
- exp gaat weer terug naar 0
Resultaat
Je kan nu eindeloos vechten tegen vijanden en ga je een level omhoog gaan wanneer X aantal vijanden zijn verslagen (en je zo steeds sterker wordt).
Let op!: zorg dat het uitlezen en wijzigen van variabelen altijd viagetters ensetters gaat.
Opdracht 3 - I command you to...
Voor deze opdracht ga je de mechanics die je op dit moment hebt gemaakt, opschonen en wat uitbreiden. Kijk eerst de video Enums. Na de videos weet je hoe je enums kan aanmaken en gebruiken in combinatie met een switchcase. Voeg een enum toe voor de volgende gamestates:
COMBAT
STORY
GAMEOVER
Voeg een variabele voor de
STORY - comment een todo voor story segmenten (je hoeft hier dus nog geen logica voor te schrijven)
GAMEOVER - wanneer de speler zijn health op 0 of lager komt wordt de gamestate omgezet naar GAMEOVER.
Voeg in de
als de gamestate op COMBAT staat wordt de combat uitgevoerd zoals voorheen en kan de speler commando's geven om aan te vallen en/of items gebruiken (als je dat hebt geprogrammeerd), waarna de vijand de speler aanvalt. Er moet een functie zijn voor het wijzigen van de gamestate wanneer dat evt. nodig is. Dit moet altijd aan het einde van de gameloop gebeuren zodat de volgende loop methodes wordt bepaalt. Als de speler dood is word de gamestate omgezet naar GAMEOVER en word de gameover logica uitgevoerd.
Wijzig de enemy naar een
Resultaat
Er kunnen meerdere vijanden tegelijk verschijnen en worden samengevoegd in de intro (bijv.: A wild Goblin and Giant Rat appeared!). De speler kan in zijn aanval commando een naam meegeven voor welke vijand hij/zij wilt aanvallen. Daarna krijgt elke vijand een beurt om de speler aan te vallen. Dit blijft herhalen tot de speler dood is of alle vijanden zijn verslagen; in dit geval worden er weer nieuwe vijanden aangemaakt en begint het gevecht opnieuw!).
Opdracht 4 - Are they getting stronger?
Kijk de video over Polymorfisme. We gaan variatie in de vijanden brengen doormiddel van polymorfisme.
Creëer twee nieuwe klassen
De
TankEnemy heeft een extravariabele armorValue . Elke keer als deze vijand schade krijgt, gaat het eerst van dearmorValue af, voordat het van zijnhealth af gaat.De
BlitzEnemy heeft elke keer als het aanvalt een kans om nog een keer aan te vallen. Deze kans begint hoog, maar wordt bij elke aanval kleiner.Polymorph beide damage en aanval methodes zodat ze wel dezelfde methode naam en argumenten houden maar dat het de bovengenoemde functionaliteiten implementeert.
Laat deze nieuwe vijanden, samen met de originele, ook verschijnen in de gameloop bij gevechten doormiddel van kans.
Opdracht 5 - In a single file line, please!
Kijk eerst het filmpje QueuesandStacks; je weet dan wat
Voor deze opdracht gaan je wat meer order creëren in de combat, met name de volgorde van wie als eerste acties mag uitvoeren!
Voeg aan
Voeg aan
Je kan zelf bepalen wat voor sortering gebruikt gaat worden, maar een mooie start in deze wereld is de BubbelSort.
Eindresultaat
Voordat combat begint worden alle entiteiten in het gevecht gesorteerd op hun snelheid. Deze volgorde wordt overgenomen in de combat queue, waardoor er een variërende volgorde in beurten ontstaat: snellere entiteiten zijn als eerste aan de beurt!Bonus
Voeg een mechanic toe dat de speed variabele van de entiteiten versneld/vertraagd kunnen worden tijdens combat. Bijvoorbeeld: wanneer een entiteit geraakt wordt met ice magic dan wordt zijn speed gehalveerd (waardoor hij dus later aan de beurt is). Hiervoor moet je dus alle entiteiten opnieuw sorteren nadat iedereen aan de beurt is geweest. Als je hier een dynamischere manier voor kan bedenken dan is dat bonus punten!
Opdracht 6 - What happens next?
Maak eerst een backup van jouw huidige project; deze opdracht is namelijk een flinke ingreep! Deze opdracht vraagt ook inzicht in code architectuur en volgorde!
Kijk de video over Linkedlists; je hebt dan de kennis om je eigen verzameling te schrijven volgens het linkedlist principe.
Maak een nieuwe folder "Datastructures" aan. Maak binnen deze folder de benodigde klassen voor een linkedlist (zoals in de video). Via een aparte klasse
De
Als voorbeeld
De GameManager kijkt naar de huidige gamestate: deze staat op STORY en kijkt naar de huidige linkedlist node. De isCombat boolean staat op false en de print methode van de huidige linkedlist node wordt uitgevoerd. De node data wordt via een Console.WriteLine uitgeschreven naar de console en de opvolgende node word nu de huidige node.
De GameManager kijkt opnieuw naar de huidige gamestate: deze staat nog steeds op STORY en word er weer eerst gekeken naar de huidige linkedlist node. Hier is de isCombat boolean wel waar; de gamestate wordt gewijzigd naar COMBAT en de huidige node word alvast vervangen met de volgende node (deze node wordt nog niet gebruikt totdat combat voorbij is!).
De GameManager kijkt opnieuw naar de huidige gamestate: deze staat op COMBAT en word vervolgens de combat code uitgevoerd tot dat alle vijanden verslagen zijn. Bij het verslaan van alle vijanden word de gamestate weer gewijzigd naar STORY en gaat het weer verder zoals gewoon.
Voeg een aantal nodes toe om een basic verhaal te vertellen met halverwege wat combat (minimaal drie nodes voor introductie, combat, afsluiting).
Bonus: voeg een keuze toe aan nodes. Geef de speler de opdracht om een keuze te maken na een kort verhaal. Houd het op twee keuzes die elk wijzen naar twee verschillende next nodes. Of deze nodes combat of story zijn mag je zelf bepalen. Beide routes wijzen naar dezelfde next node om de splitting weer samen te voegen.