Bygg et pokerspill i Corona Game Logic

I første del av denne opplæringen satte vi opp prosjektet og opprettet spillets grensesnitt. Vi har også opprettet og implementert en funksjon for å lage et kort kort. I denne andre opplæringen vil vi lage spilllogikken.


Eksempel på søknad

Hvis du vil kjøre prøveapplikasjonen for denne opplæringen, må du sørge for å ta med bilder for bilene som jeg forklarte i den forrige opplæringen. Ikke glem å inkludere og oppdatere dataSaver bibliotek nevnt i denne opplæringen.


1. enableDealButton

Oppdater implementeringen av enableDealButton fungere som vist nedenfor.

 funksjon enableDealButton () disableDealButton () dealButton: addEventListener ('trykk', doDeal) instructionsText.text = "" end

Vi ringer først disableDealButton, som fjerner eventuelle tidligere lyttere, og legger til en springen lytter, som påberoper doDeal. De addEventListener Metoden aksepterer en hendelse og en tilbakeringing. Det er en rekke arrangementer du kan lytte etter, avhengig av hvilken kontekst du ringer til.


2. disableDealButton

Som nevnt i forrige avsnitt, i disableButton Vi fjerner eventuelle tidligere lyttere.

 funksjon disableDealButton () dealButton: removeEventListener ('tap', doDeal) ende

3. enableBetButtons

I enableBetButtons, vi legger til springen lytter til betMaxButton og betButton, og gi spilleren noen instruksjoner om hvordan de skal satse.

 funksjon enableBetButtons () betMaxButton: addEventListener ('trykk', betMax) betButton: addEventListener ('tap', innsats) instructionsText.text = "Plasser innsatsen din eller Bet Max ($ 15)" slutten

4. disableBetButtons

Som i disableDealButton, Vi fjerner alle tidligere lyttede brukere i disableBetButtons.

 funksjon deaktivereBetButtons () betMaxButton: removeEventListener ('tap', betMax) betButton: removeEventListener ('tap', innsats) ende

5. enableHoldButtons

I enableHoldButtons, vi løp gjennom holdButtons bord og legg til en springen lytter til hver knapp.

 funksjon enableHoldButtons () for i = 1, #holdButtons hold holdButtons [i]: addEventListener ('tap', holdCard) slutten

6. disableHoldButtons

I disableHoldButtons funksjon, vi sløyfe også gjennom holdButtons bord, men vi fjerner tidligere lagt lyttere i stedet for å legge til nye lyttere.

 funksjon disableHoldButtons () for i = 1, #holdButtons hold holdButtons [i]: removeEventListener ('tap', holdCard) slutten

7. generateCard

Gjennomføringen av generateCard krever litt mer forklaring. Vi genererer først et tilfeldig tall fra 1 til lengden av Dekk bord. Vi lager deretter et midlertidig kort ved hjelp av dekk ["randIndex] ..." .png " og lagre en referanse i tempCard. Hva dekk ["randIndex] ..." .png " gjør, tar et tilfeldig element fra Dekk bord, som ville være noe sånt c1 eller h5 og legger til .png til det. Fordi Lua er et dynamisk språk, kan vi legge til nye egenskaper til objektene. I dette eksemplet legger vi til en isHolding eiendom, som forteller oss om spilleren holder kortet, a kortnummer eiendom ved å få en substring av utvalgt Dekk element, og vi gjør det samme for cardSuit eiendom. Til slutt fjerner vi det valgte elementet fra Dekk bord og returnere arrayet.

 funksjon generateCard () local randIndex = math.random (#deck) lokale tempCard = display.newImage (dekk [randIndex] ... ".png") tempCard.anchorX, tempCard.anchorY = 0,0 tempCard.isHolding = falsk tempCard.cardNumber = tonnummer (streng.sub (dekk [randIndex], 2,3)) tempCard.cardSuit = string.sub (dekk [randIndex], 1,1) table.remove (dekk, randIndex); retur tempCard; slutt

8. getCard

I getCard, vi satte cardPosition, hvilken er den x koordinat av det første kortet i spillets grensesnitt. Vi genererer et kort, legg det til playerHand bord, og passere i en Kortindeks variabel, som vil være et tall mellom 1 og 5, som representerer ett av de fem kortene. Dette gjør at vi kan plassere kortene i riktig rekkefølge i playerHand bord. Vi setter posisjonen til hvert kort ved å bruke en offset på (93 * (cardIndex - 1)). Dette betyr at kortene er 93 piksler bortsett fra hverandre.

 funksjon getCard (indeks) lokal cardPosition = 199 lokal tempCard = generateCard () playerHand [cardIndex] = tempCard tempCard.x = cardPosition + (93 * (cardIndex-1)) tempCard.y = 257; slutt

9. holdCard

I holdCard, Vi får først en henvisning til knappen som ble presset ved å bruke dens buttonNumber eiendom. Dette gjør at vi kan kontrollere om kortet er i playerHand bord. Hvis det er, setter vi isHolding å falle og oppdatere kortets y koordinere. Hvis kortet ikke er i playerHand bord satt vi isHolding å true og oppdatere kortets y koordinere. Hvis spilleren velger å holde kortet, er det det y koordinaten er redusert, noe som betyr at kortet er flyttet litt opp.

 funksjon holdCard (event) local index = event.target.buttonNumber hvis (playerHand [index] .isHolding == true) then playerHand [index] .isHolding = falsk spillerHand [indeks] .y = 257 annet spillerHand [index] .isHolding = sann spillerHand [index] .y = 200 endeend

10. resetCardsYPosition

I resetCardsYPosition, vi løp gjennom playerHand bord og se om noen av kortene holdes. De som er, flyttes tilbake til sin opprinnelige posisjon ved hjelp av Overgang bibliotek. Overgangsbiblioteket gjør det veldig enkelt å flytte objekter rundt og mellom egenskapene sine.

 funksjon resetCardsYPosition () for i = 1, # playerHand gjøre hvis (playerHand [i] .isHolding) deretter transition.to (playerHand [i], time = 200, y = 257) endeendens ende

11. Persistente data over sessioner

Vi vil at spillet vårt skal kunne fortsette å være verdier eller data på tvers av øktene. Vi kan bygge en løsning selv ved hjelp av Coronas io-bibliotek, men i denne opplæringen skal vi bruke en tredjepartsløsning. Arturs Sosins har laget en praktisk liten modul for vedvarende data på tvers av spill sesjoner.

Last ned biblioteket og legg til de to filene det inneholder for prosjektet ditt. For å gjøre bruk av biblioteket, legg til følgende linje øverst på main.lua.

 sparer = krever ("dataSaver")

For å få biblioteket til å fungere i prosjektet, må vi gjøre noen få mindre endringer dataSaver.lua. Åpne denne filen og endre krever "json" til lokal json = krever "json".

Endring:

 krever "json"

Til:

 lokal json = krever "json"

Den andre forandringen vi må gjøre er å endre alle forekomster av system.ResourceDirectory til system.DocumentsDirectory som vist under.

Endring:

 system.ResourceDirectory

Til:

 system.DocumentsDirectory

12. createDataFile

For å sette opp en datalager, sett inn følgende kodestykke under setupTextFields funksjon. Pass på at du inkluderer funksjonsdefinisjonen da vi ikke stubber denne funksjonen i den forrige opplæringen.

 funksjon createDataFile () gameData = saver.loadValue ("gameData") hvis (gameData == nil) da gameData =  gameData.numberOfCredits = 100 gameData.numberOfGames = 0 creditText.text = "100" gamesText.text = "0" saver.saveValue ("gameData", gameData) annet creditText.text = gameData.numberOfCredits gamesText.text = gameData.numberOfGames slutten

I createDataFile, Vi prøver først å laste inn gameData nøkkel fra sparer inn i gameData variabel. De loadValue metode returnerer nil hvis nøkkelen ikke eksisterer. Hvis den ikke eksisterer, initialiserer vi gameData bord, legg til numberOfCredits og numberOfGames egenskaper, oppdater de respektive tekstfeltene og lagre gameData bord ved å påkalle saveValuesaver. Hvis nøkkelen eksisterer, har vi allerede gjort dette, og vi kan fylle ut tekstfeltene med de riktige verdiene.

I det neste trinnet påberoper vi oss createDataFile fungere i oppsett fungere som vist nedenfor.

 funksjon oppsett () math.randomseed (os.time ()) setupButtons () setupTextFields () createDataFile () end

1. 3. betMax

I betMax, Vi begynner med å laste inn dataene våre gameData. Hvis antall studiepoeng er større enn eller lik 15, vi fortsetter å ringe doDeal. Ellers har spilleren ikke nok penger til å satse maksimalt på 15 kreditter og vi viser spilleren et varsel.

 funksjon betMax () lokal gameData = saver.loadValue ("gameData") lokalnummerOfCredits = gameData.numberOfCredits hvis (numberOfCredits> = 15) så enableDealButton () betAmount = 15; betText.text = betAmount instructionsText.text = "" doDeal () annet lokalt varsel = native.showAlert ("Ikke nok kreditt", "Du må ha 15 eller flere kreditter til Bet Max", "OK") slutten

14. vedde

I vedde funksjon, aktiverer vi avtale-knappen og fjerner lytteren fra betMaxButton. Siden spilleren gjør en vanlig innsats, kan hun ikke spille en maksimal innsats samtidig. Vi må sjekke om antall studiepoeng er større enn eller lik 5 for å forsikre deg om at spilleren ikke prøver å satse på flere kreditter enn de har forlatt. Hvis betAmount er lik 15, vi ringer doDeal som de har satset maksimumsbeløpet.

 funksjonen Bet () enableDealButton () betMaxButton: removeEventListener ('tap', betMax) instructionsText.text = "" lokalnummerOfCredits = tonnnummer (creditText.text - betAmount) hvis (numberOfCredits> = 5) så betAmount = betAmount + 5 betText.text = betAmount annet doDeal () ende hvis (betAmount == 15) deretter doDeal () ende ende

15. doDeal

De doDeal Funksjonen koordinerer håndtering av kortene. Hvis det er et nytt spill, håndterer vi den første hånden. Ellers håndterer vi spilleren nye kort.

 funksjon doDeal () hvis (isNewGame == true) then isNewGame = falsk dealInitialHand () annet dealNewCards () slutten

16. dealInitialHand

Vi deaktiverer innsatsknappene i dealInitialHand og aktiver venteknappene. Vi påberoper getCard fem ganger, som genererer de første fem kortene. Vi laster deretter inn gameData, Oppdater currentCredits, regne ut newCredits, oppdater kredittfeltet og lagre gameData.

 funksjonen dealInitialHand () deaktivereBetButtons () enableHoldButtons () for i = 1, 5 do getCard (i) avslutte lokale gameData = saver.loadValue ("gameData") local currentCredits = gameData.numberOfCredits local newCredits = currentCredits - betAmount creditText.text = newCredits gameData.numberOfCredits = newCredits saver.saveValue ("gameData", gameData) slutter

17. dealNewCards

I dealNewCards, Vi kontrollerer om spilleren holder et kort. Hvis de er, får vi en referanse til det nåværende kortet, samtale removeSelf, sett det til nil, og få et nytt kort ved å påkalle getCard (i).

 funksjonsavtaleNewCards () disableDealButton () disableHoldButtons () for i = 1, 5 gjør hvis (playerHand [i] .isHolding == false) deretter lokale tempCard = playerHand [i] tempCard: removeSelf () tempCard = null getCard avslutte resetCardsYPosition () getHand () slutten
Når du fjerner noe fra skjermen, bør du alltid sette den til nil for å sikre at det er oppsett for søppelsamling på riktig måte.

18. getHand

De getHand funksjonen bestemmer spillerens hånd. Som du kan se nedenfor, er funksjonen ganske involvert. La oss bryte ned for å se hva som skjer. Begynn med å implementere getHand fungere som vist nedenfor.

 funksjon getHand () table.sort (playerHand, funksjon (a, b) returner a.cardNumber < b.cardNumber end) local frequencies =  for i=1, 13 do table.insert(frequencies,0) end for i=1,#playerHand do frequencies[playerHand[i].cardNumber] = frequencies[playerHand[i].cardNumber] + 1 end local numberOfPairs = 0 local hasThreeOfAKind = false local hasFourOfAKind = false local winningHand = "Nothing" local cashAward = 0 local isStraight = true local isRoyalStraight = false local isFlush = true for i=0, #frequencies do if (frequencies[i] == 2) then numberOfPairs = numberOfPairs+1 end if (frequencies[i] == 3) then hasThreeOfAKind = true end if (frequencies[i] == 4) then hasFour = true end end if (numberOfPairs > 0) så hvis (numberOfPairs == 1) then winningHand = "1 pair" cashAward = 1 * betAmount else winningHand = "2 par" cashAward = 2 * betAmount ende ende hvis (hasThreeOfAKind) then winningHand = "3 of A Kind" cashAward = 3 * betAmount ende hvis (hasFour) then winningHand = "Four of A Kind" cashAward = 7 * betAmount ende hvis (numberOfPairs == 1 og hasThreeOfAKind) then winningHand = "Full House" cashAward = 6 * betAmount ende hvis (playerHand [ 1] .cardNumber == 1 og playerHand [2] .cardNumber == 10 og playerHand [3] .cardNumber == 11 og playerHand [4] .cardNumber == 12 og playerHand [5] .cardNumber == 13) then isRoyalStraight = true end for i = 1, 4 gjør hvis (playerHand [i] .cardNumber + 1 ~ = playerHand [i + 1] .cardNumber) then isStraight = falsk pause slutten for i = 1, 5 gjør hvis (playerHand [i ] .cardSuit ~ = playerHand [1] .cardSuit) then isFlush = false break ende ende hvis (isFlush) then winningHand = "Flush" cashAward = 5 * betAmount ende hvis (isStraight) then winningHand = "Straight" cashAward = 4 * betAmount slutt hvis (isRoyalStrai ghd) deretter winningHand = "Straight" cashAward = 4 * betAmount ende hvis (isFlush og isStraight) deretter winningHand = "Straight Flush" cashAward = 8 * betAmount ende hvis (isFlush og isRoyalStraight) deretter winningHand = "Royal Flush" cashAward = 9 * betAmount end award award (winningHand, cashAward) slutten

Vi begynner med å ringe table.sortplayerHand bord. De sortere Metoden gjør en in-place sort, den bruker operatør for å avgjøre om et element av bordet skal komme før eller etter et annet element. Vi kan passere en sammenligningsfunksjon som det andre argumentet. I vårt eksempel sjekker vi om kortnummer Eiendommen er mindre enn den forrige. Hvis det er, bytter det de to elementene.

Vi lager deretter en frekvenser bord, fyll det med tretten nuller (0), loop gjennom playerHand tabell, og øk hvert indeksnummer hvis playerHand inneholder dette nummeret. For eksempel, hvis du hadde to tre og tre fives, så frekvenser bordet ville være 0, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0.

I det neste trinnet erklærer vi og angir en rekke lokale variabler som vi trenger om noen få øyeblikk. Vi løp deretter gjennom frekvenser bord og kontroller tallene for å se om indeksen inneholder a 2, som betyr at vi har et par, a 3, som betyr at vi har tre eller en slags 4, som betyr at vi har fire i en slags. Deretter sjekker vi antall par, tre i et slag og fire i et slag, og oppdaterer winningHand og cashAward verdier tilsvarende.

For å sjekke om en Royal Straight, Vi må sjekke om det første kortet er lik et ess, og de resterende kortene vil være ti, Jack, Queen og King. For å sjekke for en vanlig Rett vi løp gjennom playerHand og sjekk om hver påfølgende kortnummer er en større enn den forrige. For å sjekke om en flush, Vi sjekker om alle kortene cardSuit nøklene var lik det første kortets cardSuit nøkkel.

Ved slutten av getHand, vi påberoper awardWinnings.


19. awardWinnings

I awardWinnings, Vi viser spilleren hvilken hånd de har i hånden og oppdaterer gameData innstillinger. Vi lagrer gameData og påkalle newGame med en forsinkelse på tre sekunder.

 funksjonen awardWinnings (theHand, theAward) instructionsText.text = "Du har" ... theHand winText.text = theAward lokale gameData = saver.loadValue ("gameData") local currentCredits = gameData.numberOfCredits local currentGames = gameData.numberOfGames local newCredits = currentCredits + TheAward local newGames = currentGames + 1 gameData.numberOfCredits = newCredits gameData.numberOfGames = newGames saver.saveValue ("gameData", gameData) timer.performWithDelay (3000, newGame, 1) slutten

20. newGame

I newGame, Vi går gjennom og tilbakestiller alle variablene, lager et nytt kortkort, og sjekk om gameData.numberOfCredits er lik null. Hvis det er, har spilleren brukt alle sine kreditter, slik at vi tildeler dem 100 flere studiepoeng. Endelig oppdaterer vi tekstfeltene.

 funksjonen newGame () for i = 1, # playerHand do playerHand [i]: removeSelf () playerHand [i] = null endespillerHand =  deck =  betAmount = 0 isNewGame = true createDeck () enableBetButtons () instructionsText.text = "Sett innsatsen din eller innsats max ($ 15)" winText.text = "" betText.text = "" lokal gameData = saver.loadValue ("gameData") hvis (gameData.numberOfCredits == 0) deretter gameData.numberOfCredits = 100 saver.saveValue ("gameData", gameData) avslutte creditText.text = gameData.numberOfCredits gamesText.text = gameData.numberOfGames end

21. Testing av spillet

Oppdater oppsett funksjon ved å påkalle createDeck Funksjon som vist nedenfor og test sluttresultatet.

 funksjonsoppsett () math.randomseed (os.time ()) createDeck (); setupButtons () setupTextFields () createDataFile () slutten

Konklusjon

I denne opplæringen skapte vi et morsomt og interessant pokerspill. Vi har ikke implementert knappen for å sette ut penger ennå, men du er fri til å gjøre det i spillet ditt. Jeg håper du har lært noe nyttig i denne opplæringen. Legg igjen din tilbakemelding i kommentarene nedenfor.