Costruisci un gioco di poker su Corona Game Logic

Nella prima parte di questo tutorial, abbiamo impostato il progetto e creato l'interfaccia del gioco. Abbiamo anche creato e implementato una funzione per creare un mazzo di carte. In questo secondo tutorial, creeremo la logica del gioco.


Applicazione di esempio

Se vuoi eseguire l'applicazione di esempio di questo tutorial, assicurati di includere immagini per le auto come ho spiegato nel tutorial precedente. Non dimenticare di includere e aggiornare il dataSaver libreria menzionata in questo tutorial.


1. enableDealButton

Aggiorna l'implementazione di enableDealButton funzione come mostrato di seguito.

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

Per prima cosa chiamiamo disableDealButton, che rimuove eventuali ascoltatori aggiunti in precedenza e aggiunge un rubinetto ascoltatore, che invoca doDeal. Il addEventListener metodo accetta un evento e un callback. Esistono numerosi eventi che puoi ascoltare, a seconda del contesto in cui lo stai chiamando.


2. disableDealButton

Come ho detto nella sezione precedente, in disableButton rimuoviamo tutti gli ascoltatori aggiunti in precedenza.

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

3. enableBetButtons

Nel enableBetButtons, noi aggiungiamo rubinetto ascoltatori betMaxButton e betButton, e dare al giocatore alcune istruzioni su come piazzare la propria scommessa.

 function enableBetButtons () betMaxButton: addEventListener ('tap', betMax) betButton: addEventListener ('tap', bet) instructionText.text = "Inserisci la tua puntata o puntata massima ($ 15)" fine

4. disableBetButtons

Come in disableDealButton, rimuoviamo tutti gli ascoltatori aggiunti in precedenza disableBetButtons.

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

5. enableHoldButtons

Nel enableHoldButtons, passiamo attraverso il holdButtons tabella e aggiungi a rubinetto ascoltatore per ogni pulsante.

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

6. disableHoldButtons

Nel disableHoldButtons funzione, anche ciclicamente holdButtons tabella, ma rimuoviamo gli ascoltatori aggiunti in precedenza invece di aggiungere nuovi listener.

 function disableHoldButtons () per i = 1, #holdButtons do holdButtons [i]: removeEventListener ('tap', holdCard) end end

7. generateCard

L'implementazione di generateCard richiede un po 'più di spiegazione. Per prima cosa generiamo un numero casuale da 1 alla lunghezza del ponte tavolo. Creiamo quindi una carta temporanea usando deck ["randIndex] ..." .png " e memorizzare un riferimento in tempCard. Che cosa deck ["randIndex] ..." .png " fa, è prendere un elemento casuale dal ponte tavolo, che sarebbe qualcosa di simile c1 o h5 e aggiunge .png ad esso. Poiché Lua è un linguaggio dinamico, possiamo aggiungere nuove proprietà agli oggetti. In questo esempio, aggiungiamo a sta tenendo proprietà, che ci dice se il giocatore è in possesso della carta, a numero di carta proprietà ottenendo una sottostringa del prescelto ponte elemento, e facciamo lo stesso per il cardSuit proprietà. Infine, rimuoviamo l'elemento scelto dal ponte tabella e restituire l'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); restituire tempCard; fine

8. getCard

Nel getCard, abbiamo impostato il cardPosition, qual è X coordinata della prima carta nell'interfaccia del gioco. Generiamo una carta, aggiungiamola al playerHand tabella e passare in a cardIndex variabile, che sarà un numero tra 1 e 5, rappresenta una delle cinque carte. Questo ci consente di posizionare le carte nell'ordine corretto in playerHand tavolo. Impostiamo la posizione di ogni carta usando un offset di (93 * (cardIndex - 1)). Questo significa che le carte sono 93 pixel l'uno dall'altro.

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

9. holdCard

Nel holdCard, per prima cosa otteniamo un riferimento al pulsante che è stato premuto usando il suo buttonNumber proprietà. Questo ci permette di verificare se la carta è nel playerHand tavolo. Se lo è, abbiamo impostato sta tenendo per falso e aggiornare la carta y coordinata. Se la carta non è nel playerHand tavolo, abbiamo impostato sta tenendo per true e aggiornare la carta y coordinata. Se il giocatore sceglie di tenere la carta, lo è y la coordinata è diminuita, il che significa che la carta viene spostata leggermente.

 function holdCard (event) local index = event.target.buttonNumber if (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

Nel resetCardsYPosition, passiamo attraverso il playerHand tabella e vedere se una qualsiasi delle carte è in attesa. Quelli che sono, vengono spostati nella loro posizione originale usando il Transizione biblioteca. La libreria Transition rende molto facile spostare gli oggetti e interpolarne le proprietà.

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

11. Dati persistenti su sessioni

Vogliamo che il nostro gioco sia in grado di mantenere valori o dati attraverso le sessioni. Possiamo costruire noi stessi una soluzione usando la libreria io di Corona, ma in questo tutorial useremo una soluzione di terze parti. Arturs Sosins ha creato un piccolo e pratico modulo per la persistenza dei dati nelle sessioni di gioco.

Scarica la libreria e aggiungi i due file che contiene al tuo progetto. Per utilizzare la libreria, aggiungere la seguente riga nella parte superiore di main.lua.

 saver = require ("dataSaver")

Per far funzionare la biblioteca nel nostro progetto, dobbiamo apportare alcune modifiche minori a dataSaver.lua. Apri questo file e cambia richiedere "json" a json locale = richiede "json".

Modificare:

 richiedere "json"

A:

 json locale = richiede "json"

Il secondo cambiamento che dobbiamo fare è cambiare tutte le occorrenze di system.ResourceDirectory a system.DocumentsDirectory come mostrato di seguito.

Modificare:

 system.ResourceDirectory

A:

 system.DocumentsDirectory

12. createDataFile

Per impostare un archivio dati, inserisci il seguente frammento di codice sotto il setupTextFields funzione. Assicurati di includere la definizione della funzione poiché non abbiamo arrestato questa funzione nel tutorial precedente.

 function createDataFile () gameData = saver.loadValue ("gameData") if (gameData == nil) then 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

Nel createDataFile, per prima cosa tentiamo di caricare il file gamedata chiave dal risparmiatore in gamedata variabile. Il loadValue metodo restituisce zero se la chiave non esiste. Se non esiste, inizializziamo il gamedata tabella, aggiungere numberOfCredits e numberOfGames proprietà, aggiornare i rispettivi campi di testo e salvare il gamedata tabella invocando saveValue sopra risparmiatore. Se la chiave esiste, l'abbiamo già fatto e possiamo popolare i campi di testo con i valori corretti.

Nel prossimo passaggio, invochiamo il createDataFile funzione nel impostare funzione come mostrato di seguito.

 function setup () math.randomseed (os.time ()) setupButtons () setupTextFields () createDataFile () end

13. betMax

Nel betMax, iniziamo caricando i nostri dati in gamedata. Se il numero di crediti è maggiore o uguale a 15, andiamo avanti e chiamiamo doDeal. Altrimenti, il giocatore non ha abbastanza crediti per scommettere il massimo 15 crediti e mostriamo al giocatore un avviso.

 function betMax () local gameData = saver.loadValue ("gameData") local numberOfCredits = gameData.numberOfCredits if (numberOfCredits> = 15) then enableDealButton () betAmount = 15; betText.text = betAmount instructionsText.text = "" doDeal () else alert locale = native.showAlert ("Not enoughno Credits", "Devi avere almeno 15 crediti per puntare il massimo", "OK") end end

14. scommessa

Nel scommessa funzione, abilitiamo il pulsante deal e rimuoviamo l'ascoltatore da betMaxButton. Poiché il giocatore sta puntando regolarmente, non può giocare una puntata massima allo stesso tempo. Dobbiamo verificare se il numero di crediti è maggiore o uguale a 5 per assicurarsi che il giocatore non stia cercando di scommettere più crediti di quanti ne siano rimasti. Se betAmount è uguale a 15, Noi chiamiamo doDeal come hanno scommesso l'importo massimo.

 function bet () enableDealButton () betMaxButton: removeEventListener ('tap', betMax) instructionsText.text = "" local numberOfCredits = tonumber (creditText.text - betAmount) if (numberOfCredits> = 5) then betAmount = betAmount + 5 betText.text = betAmount else doDeal () end if (betAmount == 15) then doDeal () end end

15. doDeal

Il doDeal la funzione coordina lo scambio delle carte. Se è un nuovo gioco, ci occupiamo della mano iniziale. Altrimenti, distribuiamo le nuove carte al giocatore.

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

16. dealInitialHand

Disabilitiamo i pulsanti di scommessa in dealInitialHand e abilitare i pulsanti di attesa. Invochiamo getCard cinque volte, che genera le cinque carte iniziali. Quindi carichiamo gamedata, aggiornare currentCredits, calcolare newCredits, aggiorna il campo del testo del credito e salva gamedata.

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

17. dealNewCards

Nel dealNewCards, controlliamo se il giocatore è in possesso di una carta. Se lo sono, allora otteniamo un riferimento alla carta attuale, chiama removeSelf, impostalo su zero, e ottieni una nuova carta invocando getCard (i).

 function dealNewCards () disableDealButton () disableHoldButtons () per i = 1, 5 do if (playerHand [i] .isHolding == false) then tempCard locale = playerHand [i] tempCard: removeSelf () tempCard = nil getCard (i) end end resetCardsYPosition () getHand () end
Ogni volta che rimuovi qualcosa dallo schermo, dovresti sempre impostarlo zero per assicurarsi che sia impostato correttamente per la garbage collection.

18. getHand

Il getHand la funzione determina la mano del giocatore. Come puoi vedere qui sotto, la funzione è piuttosto coinvolgente. Rompiamo se giù per vedere cosa sta succedendo. Inizia implementando il getHand funzione come mostrato di seguito.

 function getHand () table.sort (playerHand, function (a, b) restituisce 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) quindi if (numberOfPairs == 1) then winningHand = "1 coppia" 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 e hasThreeOfAKind) then winningHand = "Full House" cashAward = 6 * betAmount end if (playerHand [ 1] .cardNumber == 1 e playerHand [2] .cardNumber == 10 e playerHand [3] .cardNumber == 11 e playerHand [4] .cardNumber == 12 e playerHand [5] .cardNumber == 13) then isRoyalStraight = true end per i = 1, 4 do if (playerHand [i] .cardNumber + 1 ~ = playerHand [i + 1] .cardNumber) then isStraight = false break end end per i = 1, 5 do if (playerHand [i ] .cardSuit ~ = playerHand [1] .cardSuit) then isFlush = false break end end if (isFlush) then winningHand = "Flush" cashAward = 5 * betAmount end if (isStraight) then winningHand = "Straight" cashAward = 4 * betAmount fine se (isRoyalStrai ght) then winningHand = "Straight" cashAward = 4 * betAmount end if (isFlush e isStraight) then winningHand = "Straight Flush" cashAward = 8 * betAmount end if (isFlush e isRoyalStraight) then winningHand = "Royal Flush" cashAward = 9 * betAmount end awardWinnings (winningHand, cashAward) end

Iniziamo chiamando table.sort sul playerHand tavolo. Il ordinare metodo fa un ordinamento sul posto, usa il operatore per determinare se un elemento della tabella deve venire prima o dopo un altro elemento. Possiamo passare una funzione di confronto come secondo argomento. Nel nostro esempio, controlliamo se il numero di carta la proprietà è inferiore alla precedente Se lo è, allora scambia i due elementi.

Quindi creiamo a frequenze tabella, popolarlo con tredici zeri (0), loop attraverso il playerHand tabella, e incrementare il numero di ogni indice se il playerHand contiene quel numero Per esempio, se tu avessi due tre e tre cinque, allora il frequenze tavolo sarebbe 0, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0.

Nel passaggio successivo dichiariamo e impostiamo un numero di variabili locali di cui abbiamo bisogno in pochi istanti. Quindi passiamo attraverso il frequenze tabella e controllare i numeri per vedere se l'indice contiene a 2, il che significa che abbiamo una coppia, a 3, il che significa che abbiamo un tris o a 4, il che significa che abbiamo quattro di un tipo. Successivamente, controlliamo il numero di coppie, il tris e il tris e aggiorniamo il winningHand e cashAward valuta di conseguenza.

Per verificare la presenza di a Royal Straight, dobbiamo controllare se la prima carta è uguale a un asso e le carte rimanenti saranno dieci, Jack, Queen e King. Per controllare un regolare Dritto passiamo attraverso il playerHand e controllare se ogni successivo numero di carta è uno più grande del precedente. Per verificare la presenza di a rossore, controlliamo se tutte le carte cardSuit le chiavi erano uguali alla prima cardSuit chiave.

Alla fine di getHand, noi invochiamo awardWinnings.


19. awardWinnings

Nel awardWinnings, mostriamo al giocatore la mano che hanno in mano e aggiorniamo il gamedata impostazioni. Noi salviamo gamedata e invocare nuovo gioco con un ritardo di tre secondi.

 function awardWinnings (theHand, theAward) instructionsText.text = "Hai ottenuto" ... 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) end

20. nuovo gioco

Nel nuovo gioco, passiamo attraverso e ripristiniamo tutte le variabili, creiamo un nuovo mazzo di carte e controlliamo se gameData.numberOfCredits è uguale a zero. Se lo è, allora il giocatore ha speso tutti i suoi crediti quindi li assegniamo altri 100 crediti. Infine, aggiorniamo i campi di testo.

 function newGame () per i = 1, # playerHand do playerHand [i]: removeSelf () playerHand [i] = nil end playerHand =  deck =  betAmount = 0 isNewGame = true createDeck () enableBetButtons () instructionText.text = "Piazza la tua scommessa o puntata massima ($ 15)" winText.text = "" betText.text = "" local gameData = saver.loadValue ("gameData") if (gameData.numberOfCredits == 0) then gameData.numberOfCredits = 100 saver.saveValue ("gameData", gameData) end creditText.text = gameData.numberOfCredits gamesText.text = gameData.numberOfGames end

21. Test del gioco

Aggiorna il impostare funzione invocando il createDeck funziona come mostrato sotto e testare il risultato finale.

 function setup () math.randomseed (os.time ()) createDeck (); setupButtons () setupTextFields () createDataFile () fine

Conclusione

In questo tutorial, abbiamo creato un gioco di poker divertente e interessante. Non abbiamo implementato il pulsante per incassare ancora, ma sei libero di farlo nel tuo gioco. Spero che tu abbia imparato qualcosa di utile in questo tutorial. Lascia il tuo feedback nei commenti qui sotto.