Bouw een pokerspel in Corona Game Logic

In het eerste deel van deze tutorial hebben we het project opgezet en de interface van de game gemaakt. We hebben ook een functie gemaakt en geïmplementeerd om een ​​spel kaarten te maken. In deze tweede tutorial zullen we de spellogica maken.


Voorbeeldapplicatie

Als je de voorbeeldapplicatie van deze tutorial wilt gebruiken, zorg er dan voor dat je afbeeldingen voor de auto's toevoegt zoals ik heb uitgelegd in de vorige tutorial. Vergeet niet om de. Op te nemen en bij te werken dataSaver bibliotheek genoemd in deze tutorial.


1. enableDealButton

Update de implementatie van de enableDealButton functie zoals hieronder getoond.

 function enableDealButton () disableDealButton () dealButton: addEventListener ('tap', doDeal) instructionsText.text = "" einde

We bellen eerst disableDealButton, welke eerder toegevoegde luisteraars verwijdert, en voeg een toe tik luisteraar, die aanroept doDeal. De addEventListener methode accepteert een gebeurtenis en een terugroepactie. Er zijn een aantal gebeurtenissen waarnaar u kunt luisteren, afhankelijk van de context waarin u het belt.


2. disableDealButton

Zoals ik in de vorige paragraaf heb vermeld, in disableButton we verwijderen alle eerder toegevoegde luisteraars.

 function disableDealButton () dealButton: removeEventListener ('tap', doDeal) einde

3. enableBetButtons

In enableBetButtons, we voegen toe tik luisteraars betMaxButton en betButton, en geef de speler enkele instructies voor het plaatsen van hun weddenschap.

 function enableBetButtons () betMaxButton: addEventListener ('tap', betMax) betButton: addEventListener ('tap', bet) instructionsText.text = "Plaats uw inzet of bet max ($ 15)" einde

4. disableBetButtons

Als in disableDealButton, we verwijderen eerder toegevoegde luisteraars disableBetButtons.

 function disableBetButtons () betMaxButton: removeEventListener ('tap', betMax) betButton: removeEventListener ('tik', bet) einde

5. enableHoldButtons

In enableHoldButtons, we lopen door de holdButtons tabel en voeg een toe tik luisteraar voor elke knop.

 function enableHoldButtons () voor i = 1, #holdButtons do holdButtons [i]: addEventListener ('tap', holdCard) end end

6. disableHoldButtons

In de disableHoldButtons functie, lopen we ook door de holdButtons tabel, maar we verwijderen eerder toegevoegde luisteraars in plaats van nieuwe luisteraars toe te voegen.

 function disableHoldButtons () voor i = 1, #holdButtons do holdButtons [i]: removeEventListener ('tik op', holdCard) einde

7. generateCard

De implementatie van generateCard vereist een beetje meer uitleg. We genereren eerst een willekeurig nummer van 1 tot de lengte van de dek tafel. We maken vervolgens een tijdelijke kaart met behulp van deck ["randIndex] ..." .png " en bewaar een referentie in tempCard. Wat deck ["randIndex] ..." .png " doet, is een willekeurig element van de pakken dek tafel, wat zoiets zou zijn c1 of h5 en voegt toe .png ernaar toe. Omdat Lua een dynamische taal is, kunnen we nieuwe eigenschappen aan de objecten toevoegen. In dit voorbeeld voegen we een toe houdt vast eigenschap, die ons vertelt of de speler de kaart vasthoudt, kaartnummer eigendom door een substring van de gekozene te krijgen dek element, en we doen hetzelfde voor de cardSuit eigendom. Ten slotte verwijderen we het gekozen element uit de dek tabel en retourneer de array.

 function generateCard () local randIndex = math.random (#deck) local tempCard = display.newImage (deck [randIndex] ... ".png") tempCard.anchorX, tempCard.anchorY = 0,0 tempCard.isHolding = false tempCard.cardNumber = tonumber (string.sub (deck [randIndex], 2,3)) tempCard.cardSuit = string.sub (deck [randIndex], 1,1) table.remove (deck, randIndex); terugkeer tempCard; einde

8. getCard

In getCard, we hebben de cardPosition, welke is de X coördinaat van de eerste kaart in de interface van het spel. We genereren een kaart en voegen deze toe aan de playerHand tafel en geef in a kaart index variabele, die een getal tussen zal zijn 1 en 5, die een van de vijf kaarten vertegenwoordigt. Dit stelt ons in staat om de kaarten in de juiste volgorde in de playerHand tafel. We bepalen de positie van elke kaart met behulp van een offset van (93 * (cardIndex - 1)). Dit betekent dat de kaarten zijn 93 pixels apart van elkaar.

 functie getCard (index) local cardPosition = 199 local tempCard = generateCard () playerHand [cardIndex] = tempCard tempCard.x = cardPosition + (93 * (cardIndex-1)) tempCard.y = 257; einde

9. holdCard

In holdCard, we krijgen eerst een verwijzing naar de knop die werd ingedrukt door de knop ervan te gebruiken buttonNumber eigendom. Dit stelt ons in staat om te controleren of de kaart zich in de playerHand tafel. Als dat zo is, gaan we zitten houdt vast naar false en werk de kaarten bij Y coördineren. Als de kaart zich niet in de playerHand tafel, we zetten houdt vast naar waar en update de kaarten Y coördineren. Als de speler ervoor kiest de kaart te houden, is dat zo Y coördinaat is verlaagd, wat betekent dat de kaart iets omhoog wordt bewogen.

 functie holdCard (gebeurtenis) lokale index = event.target.button Nummer als (playerHand [index] .isHolding == true) then playerHand [index] .isHolding = false playerHand [index] .y = 257 else playerHand [index] .isHolding = true playerHand [index] .y = 200 end end

10. resetCardsYPosition

In resetCardsYPosition, we lopen door de playerHand tafel en kijk of een van de kaarten wordt vastgehouden. Degenen die zijn, worden terug verplaatst naar hun oorspronkelijke positie met behulp van de Overgang bibliotheek. Met de Transitiebibliotheek kunt u objecten heel eenvoudig verplaatsen en tweenen.

 function resetCardsYPosition () voor i = 1, # playerHand do if (playerHand [i] .isHolding) then transition.to (playerHand [i], time = 200, y = 257) end end end

11. Aanhoudende gegevens in alle sessies

We willen dat onze game in staat is om waarden of gegevens gedurende sessies aan te houden. We kunnen zelf een oplossing bouwen met Corio's io-bibliotheek, maar in deze tutorial gaan we een oplossing van derden gebruiken. Arturs Sosins heeft een handige kleine module gemaakt voor het aanhouden van gegevens in gamesessies.

Download de bibliotheek en voeg de twee bestanden die het bevat toe aan uw project. Als u van de bibliotheek gebruik wilt maken, voegt u de volgende regel toe aan de bovenkant van main.lua.

 saver = require ("dataSaver")

Om de bibliotheek in ons project te laten werken, moeten we een paar kleine wijzigingen aanbrengen in dataSaver.lua. Open dit bestand en wijzig het vereisen "json" naar local json = "json" vereisen.

Verandering:

 vereisen "json"

Naar:

 local json = "json" vereisen

De tweede verandering die we moeten aanbrengen, is het veranderen van alle occurrences van system.ResourceDirectory naar system.DocumentsDirectory zoals hieronder getoond.

Verandering:

 system.ResourceDirectory

Naar:

 system.DocumentsDirectory

12. createDataFile

Om een ​​gegevensarchief in te stellen, plaatst u het volgende codefragment onder de setupTextFields functie. Zorg ervoor dat u de functiedefinitie opneemt, omdat we deze functie niet in de vorige zelfstudie hebben gestoken.

 function createDataFile () gameData = saver.loadValue ("gameData") if (gameData == nil) dan gameData =  gameData.numberOfCredits = 100 gameData.numberOfGames = 0 creditText.text = "100" gamesText.text = "0" saver.saveValue ("gameData", gameData) else creditText.text = gameData.numberOfCredits gamesText.text = gameData.numberOfGames end end

In createDataFile, we proberen eerst de spel gegevens sleutel van de spaarder in de spel gegevens variabel. De loadValue methode retourneert nul als de sleutel niet bestaat. Als het niet bestaat, initialiseren we de spel gegevens tafel, toevoegen numberOfCredits en aantal spellen eigenschappen, update de respectieve tekstvelden en sla de spel gegevens tafel door aan te roepen saveValue op spaarder. Als de sleutel bestaat, hebben we dit al gedaan en kunnen we de tekstvelden vullen met de juiste waarden.

In de volgende stap roepen we het createDataFile functie in de opstelling functie zoals hieronder getoond.

 functie setup () math.randomseed (os.time ()) setup Knoppen () setupTextFields () createDataFile () einde

13. betMax

In betMax, we beginnen met het laden van onze gegevens spel gegevens. Als het aantal credits groter of gelijk is aan 15, we gaan door en bellen doDeal. Anders heeft de speler niet genoeg credits om het maximum in te zetten 15 credits en we laten de speler een waarschuwing zien.

 functie betMax () local gameData = saver.loadValue ("gameData") local numberOfCredits = gameData.numberOfCredits if (numberOfCredits> = 15) then enableDealButton () betAmount = 15; betText.text = betAmount instructionsText.text = "" doDeal () else local alert = native.showAlert ("Not Enough Credits", "Je moet 15 of meer credits hebben om Max te Betten", "OK") einde

14. inzet

In de inzet functie, schakelen we de dealknop in en verwijderen we de luisteraar betMaxButton. Omdat de speler regelmatig gokt, kan ze niet tegelijkertijd een maximale inzet spelen. We moeten controleren of het aantal credits groter is dan of gelijk is aan 5 om ervoor te zorgen dat de speler niet probeert meer credits te zetten dan ze nog hebben. Als betAmount is gelijk aan 15, wij bellen doDeal omdat ze het maximale bedrag hebben ingezet.

 functie bet () enableDealButton () betMaxButton: removeEventListener ('tap', betMax) instructionsText.text = "" local numberOfCredits = tonumber (creditText.text - betAmount) if (numberOfCredits> = 5) dan betAmount = betAmount + 5 betText.text = betDraaide anders doDeal () eindigt als (betAmount == 15) then doDeal () end end

15. doDeal

De doDeal functie coördineert de verdeling van de kaarten. Als het een nieuw spel is, delen we de eerste hand. Anders geven we de speler nieuwe kaarten.

 function doDeal () if (isNewGame == true) then isNewGame = false dealInitialHand () else dealNewCards () end end

16. dealInitialHand

We schakelen de inzetknoppen in uit dealInitialHand en schakel de hold-knoppen in. We roepen getCard vijf keer, waarmee de eerste vijf kaarten worden gegenereerd. We laden dan spel gegevens, bijwerken currentCredits, berekenen newCredits, werk het tekstveld voor creditering bij en sla het op spel gegevens.

 function dealInitialHand () disableBetButtons () enableHoldButtons () voor i = 1, 5 do getCard (i) einde lokale gameData = saver.loadValue ("gameData") local currentCredits = gameData.numberOfCredits local newCredits = currentCredits - betAmount creditText.text = newCredits gameData.numberOfCredits = newCredits saver.saveValue ("gameData", gameData) einde

17. dealNewCards

In dealNewCards, we controleren of de speler een kaart vasthoudt. Als dat het geval is, krijgen we een verwijzing naar de huidige kaart, bel removeSelf, zet het op nul, en krijg een nieuwe kaart door aan te roepen getCard (i).

 function dealNewCards () disableDealButton () disableHoldButtons () voor i = 1, 5 do if (playerHand [i] .isHolding == false) en lokale tempCard = playerHand [i] tempCard: removeSelf () tempCard = nihil getCard (i) einde einde resetCardsYPosition () getHand () einde
Wanneer u iets van het scherm verwijdert, moet u dit altijd instellen op nul om ervoor te zorgen dat het goed is ingesteld voor garbage collection.

18. getHand

De getHand functie bepaalt de hand van de speler. Zoals je hieronder kunt zien, is de functie behoorlijk betrokken. Laten we afbreken om te zien wat er aan de hand is. Begin met het implementeren van de getHand functie zoals hieronder getoond.

 function getHand () table.sort (playerHand, functie (a, b) retourneert 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) dan if (numberOfPairs == 1) then winningHand = "1 pair" cashAward = 1 * betAmount else winningHand = "2 pair" cashAward = 2 * betAmount end end if (hasThreeOfAKind) then winningHand = "3 of A Kind" cashAward = 3 * betAmount end if (hasFour) then winningHand = "Four of A Kind" cashAward = 7 * betAmount end if (numberOfPairs == 1 and hasThreeOfAKind) then winningHand = "Full House" cashAward = 6 * betAmount end if (playerHand [ 1] .cardNumber == 1 en playerHand [2] .cardNumber == 10 en playerHand [3] .cardNumber == 11 en playerHand [4] .cardNumber == 12 en playerHand [5] .cardNumber == 13) then isRoyalStraight = true end voor i = 1, 4 do if (playerHand [i] .cardNumber + 1 ~ = playerHand [i + 1] .cardNumber) then isStraight = false break end end voor i = 1, 5 do if (playerHand [i ] .cardSuit ~ = playerHand [1] .cardSuit) then is Flush = false break end end if (isFlush) then winningHand = "Flush" cashAward = 5 * betAmount end if (isStraight) then winningHand = "Straight" cashAward = 4 * betAmount einde als (isRoyalStrai ght) then winningHand = "Straight" cashAward = 4 * betAmount end if (isFlush en isStraight) then winningHand = "Straight Flush" cashAward = 8 * betAmount end if (isFlush and isRoyalStraight) then winningHand = "Royal Flush" cashAward = 9 * betAmount end awardWinnings (winningHand, cashAward) einde

We beginnen met te bellen table.sort op de playerHand tafel. De soort methode doet een in-place sortering, het gebruikt de operator om te bepalen of een element van de tabel vóór of na een ander element moet komen. We kunnen een vergelijkingsfunctie doorgeven als het tweede argument. In ons voorbeeld controleren we of het kaartnummer eigendom is minder dan de vorige. Als dat zo is, wisselt het de twee elementen uit.

We maken vervolgens een frequenties tabel, vul het met dertien nullen (0), loop door de playerHand tabel en verhoog het indexnummer van elke index als het playerHand bevat dat nummer. Als u bijvoorbeeld twee drie en drie vijven had, dan is de frequenties tafel zou zijn 0, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0.

In de volgende stap declareren en stellen we een aantal lokale variabelen in die we in enkele ogenblikken nodig hebben. We lopen dan door de frequenties tabel en controleer de nummers om te zien of de index een bevat 2, wat betekent dat we een paar hebben, a 3, wat betekent dat we three of a kind zijn, of een 4, wat betekent dat we four of a kind zijn. Vervolgens controleren we het aantal paren, three of a kind en four of a kind, en werken het winningHand en cashAward waarden dienovereenkomstig.

Controleren op een Royal Straight, we moeten controleren of de eerste kaart gelijk is aan een aas en de resterende kaarten zijn tien, boer, vrouw en koning. Om te controleren op een reguliere Recht we lopen door de playerHand en controleer of elke volgende kaartnummer is een groter dan de vorige. Controleren op een doorspoelen, we controleren of alle kaarten cardSuit sleutels waren gelijk aan de eerste kaarten cardSuit sleutel.

Aan het einde van getHand, we roepen aan awardWinnings.


19. awardWinnings

In awardWinnings, we laten de speler zien welke hand ze in de hand hebben en werken de spel gegevens instellingen. We besparen spel gegevens en aanroepen nieuw spel met een vertraging van drie seconden.

 function awardWinnings (theHand, theAward) instructionsText.text = "You got" ... theHand winText.text = theAward local 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) einde

20. nieuw spel

In nieuw spel, we gaan door en stellen alle variabelen opnieuw in, maken een nieuw pak kaarten en controleren of gameData.numberOfCredits is gelijk aan nul. Als dat zo is, heeft de speler al zijn credits uitgegeven, dus we geven ze 100 extra credits. Ten slotte werken we de tekstvelden bij.

 function newGame () voor i = 1, # playerHand do playerHand [i]: removeSelf () playerHand [i] = nil end playerHand =  deck =  betAmount = 0 isNewGame = true createDeck () enableBetButtons () instructionsText.text = "Plaats uw inzet of bet max ($ 15)" winText.text = "" betText.text = "" lokale gameData = saver.loadValue ("gameData") if (gameData.numberOfCredits == 0) dan gameData.numberOfCredits = 100 saver.saveValue ("gameData", gameData) end creditText.text = gameData.numberOfCredits gamesText.text = gameData.numberOfGames end

21. Het spel testen

Werk het opstelling functie door het aanroepen van de createDeck functie zoals hieronder getoond en test het eindresultaat.

 functie setup () math.randomseed (os.time ()) createDeck (); setupButtons () setupTextFields () createDataFile () end

Conclusie

In deze tutorial hebben we een leuk en interessant pokerspel gemaakt. We hebben de knop nog niet geïmplementeerd om geld uit te betalen, maar je bent vrij om dit in je game te doen. Ik hoop dat je iets nuttigs hebt geleerd in deze tutorial. Laat uw feedback achter in de opmerkingen hieronder.