In het eerste bericht van deze serie hebben we besproken waarom objectgericht programmeren (OOP) nuttig was voor de ontwikkeling van spellen en hoe we voorwerpen, hun toestanden en hun gedrag konden identificeren. In dit artikel zullen we kijken naar het specifieke OOP-principe van samenhang en hoe dit van toepassing is op games.
Notitie: Hoewel deze tutorial geschreven is met behulp van Java, zou je in bijna elke game-ontwikkelomgeving dezelfde technieken en concepten moeten kunnen gebruiken.
Cohesie is het principe één ding goed te zijn of te doen. Met andere woorden, cohesie betekent het groeperen van code die bijdraagt aan een enkele taak.
Een geweldig niet-programmeervoorbeeld van dit principe werd behandeld in een van de eerste Gamedevtuts + -artikelen die het hadden over de geheime actieregel:
Probeer niet te veel games in één pakket te doen ... Individueel waren het allemaal goede games. Samen vochten ze met elkaar.
Dezelfde regel is van toepassing op objectgeoriënteerd programmeren. Elk object zou maar één verantwoordelijkheid moeten hebben. Elk gedrag van dat object zou maar één taak moeten doen. Meer dan dat en je zult het veel moeilijker hebben om de code aan te passen.
Code die is georganiseerd op basis van functionaliteit en waarvan wordt gezegd dat hij maar één taak heeft hoge cohesie. Zeer samenhangende code is herbruikbaar, eenvoudig en gemakkelijk te begrijpen. Het creëert ook objecten die klein en gericht zijn.
Code die willekeurig is georganiseerd en meerdere taken heeft, zou dat wel zijn lage cohesie. Dergelijke code is moeilijk te begrijpen, te onderhouden en opnieuw te gebruiken en is vaak complex. Het maakt ook objecten die groot en ongericht zijn.
Een hoge cohesie is over het algemeen goed, terwijl een lage cohesie over het algemeen slecht is. Denk bij het schrijven van code altijd aan het schrijven van zeer samenhangende code.
Dus hoe passen we dit toe op objectgeoriënteerd programmeren? Goed om te beginnen, het organiseren van code in objecten helpt de samenhang van het spel in het algemeen te vergroten. Elk individueel object moet echter ook een hoge cohesie hebben. Laten we teruggaan naar onze drie voorbeelden om te zien hoe dit werkt.
Bedenk uit het laatste artikel dat we het scheepsobject gedefinieerd hebben als gedragingen van draaien, bewegen en schieten.
Als we een enkel stuk code zouden schrijven dat alle drie de gedragingen tegelijk deed, zou het behoorlijk rommelig worden. In plaats daarvan moeten we elk gedrag scheiden in zogenaamde functies. Functies stellen ons in staat om functionaliteit te scheiden en dezelfde code samen te groeperen, waardoor we helpen om sterk samenhangende code te creëren.
Tijdens het programmeren wordt een object gedefinieerd door een klasse te maken. In Java is een klasse als volgt gecodeerd:
/ ** * De klasse Ship * / public class Ship / ** * Function - voert het gedrag (de taak) uit van het draaien van het schip * / public void rotate () // Code dat het schip verandert / ** * Functie - voert het gedrag (de taak) uit van het verplaatsen van de beweging Ship * / public void () // Code die het schip verplaatst / ** * Functie - voert het gedrag uit (taak) van het afvuren van het scheepsgeweer * / openbare leegte ( ) // Code waarmee het schip een kogel afvuurt
Zoals je ziet, krijgt elk gedrag zijn eigen functie en de code is vrij goed georganiseerd, alleen in deze skeletstructuur.
Maak je nog geen zorgen om de exacte syntaxis; we zullen het in meer detail bespreken als we verder komen in de serie.Denk er bij Tetris aan dat het gedrag van een tetromino daalde, verschoof (zijwaarts) en roterend. De basisklasse structuur is als volgt:
/ ** * De Tetromino-klasse * / openbare klasse Tetromino / ** * Functie - update de positie van een Tetromino * / openbare ongeldige val () // Code die de positie van Tetromino bijwerkt / ** * Functie - verplaats een Tetromino * / public void move () // Code die de Tetromino zijwaarts verplaatst / ** * Functie - roteer een Tetromino * / public void rotate () // Code die de Tetromino 90 graden roteert
Nogmaals, het gedrag is gescheiden in hun eigen functies. Voor de vallen
methode, merk op dat het de taak is om de positie van de tetromino bij te werken. Dit komt omdat de tetromino altijd valt, dus we kunnen niet alleen de taak maken "omdat de tetromino valt".
In plaats daarvan beweegt een dalende tetromino gewoon een bepaald aantal rijen tegelijk naar beneden - dus we moeten de positie van de tetromino bijwerken om deze dalende snelheid weer te geven.
Voor het spookobject met gedragingen van bewegende en veranderende toestand, moeten we wat meer werk doen om het zeer samenhangend te maken.
/ ** * De Ghost Class * / public class Ghost / ** * Function - verplaatst de Ghost * / openbare beweging () // Code die de geest in de huidige richting verplaatst / ** * Functie - verander Ghost richting * / public void changeDirection () // Code die de richting van de Geest verandert / ** * Functie - verander Ghost-snelheid * / public void changeSpeed () // Code die de snelheid van de Geest verandert / ** * Functie - verander Spookkleur * / public void changeColor () // Code die de kleur van de Geest verandert / ** * Functie - verander Ghost state * / public void changeState () // Code die de status van de Geest verandert // Deze functie ook roept de drie functies van changeDirection, changeSpeed en changeColor aan
De Ghost-staat heeft er drie extra functies aan toegevoegd: verander richting
, verander kleur
, en changeSpeed
. Deze stonden niet in onze oorspronkelijke gedragslijst omdat ze geen gedrag zijn. In plaats daarvan zijn deze functies die bekend staan als helperfuncties en zijn er om ons te helpen een hoge cohesie te behouden.
Het gedrag van de veranderende toestand (wat gebeurt er wanneer Pac-Man een krachtpellet eet) vereist drie verschillende taken die moeten worden uitgevoerd: diepblauw draaien, achteruit draaien en langzamer bewegen. Om de cohesie te behouden, willen we niet dat één functie alle drie deze taken uitvoert, dus verdelen we ze in drie subtaken die de functie zal gebruiken om zijn enige hoofdtaak te voltooien.
Het gebruik van het woord en bij het beschrijven wat een gedrag / functie gewoonlijk betekent, moeten we meer dan één functie creëren.
Cohesie is het principe van het samen groeperen van code en ervoor zorgen dat elke functie slechts één taak vervult. Cohesie helpt bij het maken van code die onderhoudbaar en herbruikbaar is.
In de volgende Quick Tip bespreken we het principe van koppeling en hoe het zich verhoudt tot cohesie. Volg ons op Twitter, Facebook of Google+ om op de hoogte te blijven van de laatste berichten.