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.
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.
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.
disableDealButton
Som nevnt i forrige avsnitt, i disableButton
Vi fjerner eventuelle tidligere lyttere.
funksjon disableDealButton () dealButton: removeEventListener ('tap', doDeal) ende
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
disableBetButtons
Som i disableDealButton
, Vi fjerner alle tidligere lyttede brukere i disableBetButtons
.
funksjon deaktivereBetButtons () betMaxButton: removeEventListener ('tap', betMax) betButton: removeEventListener ('tap', innsats) ende
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
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
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
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
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
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
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
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 saveValue
på saver
. 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
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
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
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
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
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 () sluttenNå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. 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.sort
på playerHand
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
.
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
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
Oppdater oppsett
funksjon ved å påkalle createDeck
Funksjon som vist nedenfor og test sluttresultatet.
funksjonsoppsett () math.randomseed (os.time ()) createDeck (); setupButtons () setupTextFields () createDataFile () slutten
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.