I det første innlegget i denne serien diskuterte vi hvorfor objektorientert programmering (OOP) var nyttig for spillutvikling, og lærte å identifisere objekter, deres stater og deres oppførsel. I denne artikkelen ser vi på det spesifikke OOP-prinsippet for samhold og hvordan det gjelder spill.
Merk: Selv om denne opplæringen er skrevet ved hjelp av Java, bør du kunne bruke de samme teknikkene og konseptene i nesten hvilket som helst spillutviklingsmiljø.
Samhold er prinsippet om å være eller gjøre en ting bra. Med andre ord betyr kohesjon gruppering av kode som bidrar til en enkelt oppgave.
Et stort ikke-programmeringseksempel på dette prinsippet ble dekket i en av de første Gamedevtuts + artiklene som snakket om den Covert Action Rule:
Ikke prøv å gjøre for mange spill i en pakke ... Individuelt kunne de begge vært gode spill. Sammen kjempet de med hverandre.
Samme regel gjelder for objektorientert programmering. Hvert objekt burde bare ha ett ansvar. Hver oppførsel av objektet skal bare gjøre en oppgave. Mer enn det, og du vil ha en mye vanskeligere tid å gjøre endringer i koden.
Kode som er organisert av funksjonalitet og det er bare en oppgave å ha høy kohesjon. Meget kohesiv kode er gjenbrukbar, enkel og lett å forstå. Det skaper også objekter som er små og fokuserte.
Kode som er organisert vilkårlig og har flere oppgaver, sies å ha lav sammenheng. Slik kode er vanskelig å forstå, vedlikeholde og gjenbruke, og er ofte kompleks. Det skaper også objekter som er store og ufokuserte.
Å ha høy kohesjon er generelt god, mens det er generelt dårlig å ha lav sammenheng. Når du skriver kode, forsøker du alltid å skrive svært sammenhengende kode.
Så hvordan bruker vi dette til objektorientert programmering? Vel for det første bidrar organisering av kode til objekter til å øke samholdet i spillet generelt. Men hvert enkelt objekt bør også ha høy kohesjon. La oss se tilbake til våre tre eksempler for å se hvordan dette fungerer.
Husk fra den siste artikkelen at vi definerte skipobjektet som å ha atferd for å snu, flytte og skyte.
Hvis vi skulle skrive et enkelt stykke kode som gjorde alle tre oppføringene samtidig, ville det bli ganske rotete. I stedet bør vi skille hver oppførsel til det som er kjent som funksjoner. Funksjoner tillater oss å skille funksjonalitet og gruppere lignende kode sammen, og dermed bidra til å skape høy kohesiv kode.
Ved programmering defineres en objekt ved å opprette en klasse. I Java er en klasse kodet som følger:
/ ** * Skipsklassen * / offentlig klasse Skip / ** * Funksjon - utfører oppførselen (oppgave) for å snu skipet * / offentlig tomgang rotere () // Kode som gjør skipet / ** * Funksjon - utfører oppførselen (oppgave) for å flytte skipet * / offentlig tomgangshastighet () // kode som beveger skipet / ** * funksjon - utfører oppførselen (oppgave) for å skyte skipets pistol * / offentlig tomrom ) // Kode som gjør skipet brann en kule
Som du kan se, får hver oppførsel sin egen funksjon, og koden er ganske godt organisert bare i denne skjelettstrukturen.
Ikke bekymre deg for mye om den nøyaktige syntaksen ennå; Vi vil diskutere det mer detaljert ettersom vi går videre i serien.For Tetris, husk at atferd av en tetromino faller, beveger seg (sidelengs) og roterer. Grunnklassestrukturen er som følger:
/ ** * Tetromino-klassen * / offentlig klasse Tetromino / ** * Funksjon - oppdatere en Tetromino posisjon * / offentlig tomgang () // Kode som oppdaterer Tetromino posisjonen / ** * Funksjon - flytt en Tetromino * / public void move () // Kode som beveger Tetromino sideveis / ** * Funksjon - roter en Tetromino * / public void rotate () // Kode som roterer Tetromino med 90 grader
Igjen er atferdene skilt i sine egne funksjoner. For falle
metode, men legg merke til at oppgaven er å oppdatere tetromino posisjon. Dette skyldes at tetromino alltid faller, så vi kan ikke bare gjøre oppgaven "fordi tetromino faller".
I stedet beveger en fallende tetromino bare et visst antall rader om skjermen nedover skjermen - så vi må oppdatere posisjonen til tetromino for å reflektere denne fallende hastigheten.
For spøkelsesobjektet med atferd av bevegelse og endring av tilstand, må vi gjøre litt mer arbeid for å få det til å være svært sammenhengende.
/ ** * Spøkelsesklassen * / offentlig klasse Ghost / ** * Funksjon - flytter Ghost * / public void move () // Kode som beveger spøkelset i den nåværende retningen / ** * Funksjon - skift Ghost retning * / public void changeDirection () // Kode som endrer Ghosts retning / ** * Funksjon - endre Ghost speed * / public void changeSpeed () // Kode som endrer Ghosts hastighet / ** * Funksjon - endre Ghost farge * / offentlig ugyldig endringColor () // Kode som endrer Ghosts farge / ** * Funksjon - endre Ghost state * / public void changeState () // Kode som endrer Ghosts tilstand // Denne funksjonen også vil ringe de tre funksjonene til changeDirection, changeSpeed og changeColor
Ghost-staten har tre ekstra funksjoner lagt til: endre retning
, changeColor
, og changeSpeed
. Disse var ikke i vår opprinnelige oppføringsliste fordi de ikke er atferd. I stedet er disse funksjonene det som er kjent som hjelperfunksjoner, og er der for å hjelpe oss med å opprettholde høy kohesjon.
Oppførselen til endring av tilstanden (hva skjer når Pac-Man spiser en pellets) krever tre forskjellige oppgaver som skal utføres: skru dyp blå, bakover og beveger seg sakte. For å opprettholde sammenhold, vil vi ikke ha en funksjon til å gjøre alle tre oppgavene, så vi deler dem opp i tre deltakere som funksjonen vil påkalle for å fullføre den ene hovedoppgaven.
Bruk av ordet og Når vi beskriver hva en oppførsel / funksjon betyr, betyr det vanligvis at vi skal skape mer enn en funksjon.
Samhold er prinsippet om å gruppere som kode sammen og sikre at hver funksjon utfører bare en enkelt oppgave. Samholdskraft bidrar til å skape kode som kan vedlikeholdes og gjenbrukes.
I neste Quick Tip, diskuterer vi koblingsprinsippet og hvordan det er knyttet til sammenhold. Følg oss på Twitter, Facebook eller Google+ for å holde deg oppdatert med de siste innleggene.