Nesten hvert spill kan tenkes å ha en hovedfunksjon som inneholder all spilllogikken, og som kjøres enten når brukeren gjør noe eller etter en viss tid. Denne syklusen med å kjøre den samme kjernefunksjonen igjen og igjen kalles spillsløyfe, og er avgjørende for å forstå for noen form for spillutvikling.
Du har sikkert spilt brettspillet Chutes og Ladders (eller Snakes and Ladders som vi kaller det i Storbritannia).
(Foto kreditt incurable_hippie på Flickr)
Hver spiller ruller dysen (eller spinner spinneren) og beveger frem antall kvadratene som er angitt. Torget de lander på, kan lede dem til å skyve bakover eller klatre fremover flere mellomrom. Spilleren vinner spillet når de kommer til det endelige torget.
Så, i bildet over, gjør landing på Square 6 deg klatre fire firkanter til Square 10; landing på Square 19 gjør at du glir tilbake 15 rutene til Square 4; og landing på Square 64 betyr at du vinner spillet.
Anta nå at du spiller singleplayer, for å øve. Du gjør det samme som ovenfor, igjen og igjen, til du når Square 64. Hvordan ville du representere dette i kode?
Du vil sannsynligvis begynne med å lage en matrise for å lagre verdiene til rutene. De fleste elementene vil inneholde null, men noen vil inneholde enten et positivt tall (indikerer en stige) eller et negativt tall:
Merk: Dette er pseudokode, ikke AS3
var specialSquares: Array = []; specialSquares [0] = 0; // kvadratet spillerne starter på, før 1 specialSquares [1] = 0 ;? specialSquares [6] = +4 ;? specialSquares [19] = -15;
? og så videre. Deretter vil du ha en funksjon for å flytte spilleren basert på nummeret på døren:
funksjon movePlayer (kvadrater: Nummer) newSquare = currentSquare + kvadrater; newSquare + = specialSquares [newSquare]; currentSquare = newSquare;
Du kan da sette dette inn i en større funksjon som representerer en hel tur:
funksjon takeATurn () diceNumber = random (1, 6); // tilfeldig tall mellom 1 og 6 movePlayer (diceNumber); hvis (currentSquare == 64) // spiller har vunnet! spillet er slutt
Denne funksjonen, takeATurn ()
, encapsulates kjernen spill logikken for single-player Chutes og Stiger. Men hvordan får vi faktisk denne funksjonen til å løpe? Det er flere alternativer:
Vi kunne plassere en knapp på skjermen, og få den til å ringe takeATurn ()
hver gang den klikkes. Hvis du noen gang har spilt Facebook Scrabble eller Words With Friends, har du sett dette alternativet i handling.
Vi kunne gjøre takeATurn ()
Kjør hvert seksti sekunder.
Faktisk er dette alternativet litt mer komplisert enn det kan virke. I praksis ser vi aldri noen spill uten noen spillerinngang; uten interaksjon, kan det egentlig ikke betraktes som et spill. Men likevel, noen spill har et element av "kalendertid" involvert. Vurder Farmville: du, spilleren, plant avlinger, og deretter hvert par minutter (eller timer) utvikler de seg litt lenger, fra frø til skudd til frukt. Og i noen sivilisasjonsformer får du en viss tid (si fem minutter) for å gjøre alle dine trekk for en "sving"; Når de fem minuttene er opp, utløses kjernespilllogikkfunksjonen.
Noen spill bruker en blanding av disse to alternativene: for eksempel har Mafia Wars en ressurs kalt "energi" som fyller på en enhet hvert femte minutt; du tar handlinger i spillet ved hjelp av denne ressursen, slik at kjernevilje logikkfunksjonen fortsatt utløses av en brukerhandling, den er bare begrenset av tiden.
Dette er et mønster som er vanlig for de fleste spill: Ett stykke kode som inneholder kjernespilllogikken, utløses gjentatte ganger. Vi kaller dette på spillsløyfe.
Det er et begrep for handlingen eller tidsperioden som utløser kjernespilllogikkkoden også: a sett kryss (som lyden en klokke gjør).
Så i sivilisasjonen er krysset hvert femte minutt. I ord med venner spiller du på tur fører til en flått. Med andre ord går spillsløyfen en gang per kryss.
Super Mario Bros ser ikke ut til å passe inn i noen av disse kategoriene. Mario svarer på spillerens innspill? og likevel skjer alt slags ting uten at du trenger å gjøre noe (Goombas går rundt, timeren teller ned, objekter faller). Er det to spillsløyfer?
Nei. Det er bare en, og det utløses utelukkende etter tid - men med et kryss av bare en brøkdel av et sekund.
I sivilisasjonen har du en periode på fem minutter til å legge inn alt du vil gjøre i dagens tur, før spillet "ticks" og kjører spillsløyfen igjen basert på alle dine innspill. Så hvis du sier, i Turn 23, at du vil at dine krigere skal angripe en hjort, så i Turn 24 får alle vilt til middag.
Det er det samme med Mario. Hvis du trykker på Jump-knappen under ett kryss, så vil Mario hoppe i neste iterasjon av spillsløyfen.
Legg merke til at du ikke må du trykke på Jump-knappen for å skje akkurat som kjernespilllogikkfunksjonen utløses - alle dine handlinger i en kryssperiode registreres og brukes under neste iterasjon av spillsløyfen.
Alt spilllogikken håndteres i spillsløyfen. Men det er mer til et spill enn sin logikk, grafikk er det store eksemplet.
Tegne grafikk til skjermen er hardt arbeid for datamaskinen. La oss anta at du har et actionspill med et kryss på 1 / 60th av et sekund; som burde få spillet til å føle at det reagerer fluidly til spillerens kontroller. Men hva skjer hvis spillerens datamaskin er for sakte til å kjøre all kode for spilllogikken (svare på inngang, simulere tyngdekraft, kjører AI rutiner) og Tegn alt på skjermen innen 1 / 60th av et sekund?
I dette scenariet kan vi bruke to separate løkker: en spillsløyfe og a tegne sløyfe. Vi kunne deretter kjøre tegnebøylen med en mye lavere frekvens enn spillsløyfen; la oss si at vi oppdaterer skjermen halv så ofte, dvs. hver 1 / 30th av et sekund.
Mengden prosessorkraft som kreves av spillet kan variere fra nivå til nivå. Tenk på et skytespill: De første nivåene vil ha svært få skip på skjermen, for å lette spilleren forsiktig, mens de siste nivåene kan ha dusinvis av fiendtlige skip og hundrevis av kuler som alle flyr rundt samme scene på en gang. Spillsløyfen må finne ut hvordan alle disse objektene skal bevege seg, og tegnesløyfen må gjengi hver enkelt, så mens det kan ha vært mulig å kjøre både spillsløyfen og tegningssløyfen hver 1 / 60th av et sekund på Start av spillet, til slutt har noe å gi.
Det er generelt enklere å redusere draw-sløyfen enn spillsløyfen, hvis du må velge. Justering av spillløkkens tikkelengde betyr å justere alt i spillet ditt som er basert på tid; Hvis Mario kjører med en hastighet på 20 piksler / sekund, og du designer spillet med en tikkelengde på 1 / 60th av et sekund, må du flytte ham 1/3 av en piksel per kryss. Hvis du justerer spillsløyfen for å ha en krysslengde på 1 / 30th av et sekund, må du justere dette til 2 / 3rds av en piksel per kryss - og selv det er en enkel forandring i forhold til å holde fysikkberegninger og AI-rutiner konsistent.
Av denne grunn tar spillene ofte sikte på å holde spillsløysens tippe konsistent, og redusere tegningsløyfen hvis det er mer strøm nødvendig. Hvis du noen gang har slått på FPS-telleren (kort for rammer per sekund, antall ganger tegnesløyfen kjører per sekund) i en første personskytter, har du sett den endres avhengig av hvor mye som er på skjermen ; Uttrekkingsløpens oppdateringshastighet blir automatisk justert. Spillet kan se på dømmekraft - som en live streaming video på en langsom internettforbindelse - men med mindre det kjøres på en datamaskin med mye mindre strøm enn spillutviklerne hadde i tankene, vil alle gjenstandene i spillverdenen fortsette å flytte og samhandle med de riktige hastighetene.
For en flott artikkel som forklarer hvordan Flash håndterer dette, sjekk ut Sean Christmanns innlegg på 'Elastic Racetrack'.