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.
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.
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.
disableDealButton
Zoals ik in de vorige paragraaf heb vermeld, in disableButton
we verwijderen alle eerder toegevoegde luisteraars.
function disableDealButton () dealButton: removeEventListener ('tap', doDeal) einde
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
disableBetButtons
Als in disableDealButton
, we verwijderen eerder toegevoegde luisteraars disableBetButtons
.
function disableBetButtons () betMaxButton: removeEventListener ('tap', betMax) betButton: removeEventListener ('tik', bet) einde
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
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
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
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
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
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
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
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
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
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
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
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
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 () eindeWanneer 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. 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
.
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
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
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
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.