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.
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.
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.
disableDealButton
Come ho detto nella sezione precedente, in disableButton
rimuoviamo tutti gli ascoltatori aggiunti in precedenza.
function disableDealButton () dealButton: removeEventListener ('tap', doDeal) fine
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
disableBetButtons
Come in disableDealButton
, rimuoviamo tutti gli ascoltatori aggiunti in precedenza disableBetButtons
.
function disableBetButtons () betMaxButton: removeEventListener ('tap', betMax) betButton: removeEventListener ('tap', bet) end
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
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
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
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
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
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
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
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
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
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
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
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
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 () endOgni volta che rimuovi qualcosa dallo schermo, dovresti sempre impostarlo
zero
per assicurarsi che sia impostato correttamente per la garbage collection. 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
.
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
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
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
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.