Crea un gioco Collect-the-Pieces con Corona

In questo tutorial, ti mostrerò come creare un gioco di raccolta pezzi utilizzando il Corona SDK e il linguaggio di programmazione Lua. Esploreremo come utilizzare i controlli touch e gli eventi, creare forme utilizzando l'API grafica e utilizzeremo anche le collisioni e i timer fisici. Iniziamo.


1. Panoramica dell'applicazione

In questo gioco, il giocatore sarà in grado di controllare un disco sullo schermo per raccogliere altri pezzi con lo stesso colore. Il giocatore ha solo un tempo limitato per raccogliere quanti più pezzi possibile. Se il giocatore tocca un pezzo di un altro colore, il gioco è finito.


Questa applicazione utilizza la libreria Graphics 2.0. Se stai utilizzando una versione precedente di Corona SDK, potresti incontrare dei problemi. Consultare la guida alla migrazione per ulteriori informazioni.

In questo progetto imparerai le seguenti abilità:

  • collisioni fisiche
  • crea campi di testo
  • timer e immagini dell'utente
  • come utilizzare i controlli touch e gli eventi
  • creare forme utilizzando la nuova API grafica

2. Dispositivo di destinazione


La prima cosa che dobbiamo fare è selezionare la piattaforma su cui vogliamo eseguire la nostra applicazione. Questo ci consente di scegliere le dimensioni corrette per il disegno che useremo.

La piattaforma iOS ha i seguenti requisiti:

  • iPad 1/2 / Mini: 1024 x 768 px, 132 PPI
  • Retina iPad: 2048px x 1536px, 264 PPI
  • iPhone / iPod Touch: 320 px x 480 px, 163 PPI
  • Retina per iPhone / iPod: 960px x 640px, 326 PPI
  • iPhone 5 / iPod Touch: 1136 px x 640 px, 326 PPI

Poiché Android è una piattaforma più aperta, ci sono molti dispositivi e risoluzioni possibili. Alcuni dei più comuni sono elencati di seguito:

  • Tablet Asus Nexus 7: 800 px x 1280 px, 216 PPI
  • Motorola Droid X: 854 x 480 px, 228 PPI
  • Samsung Galaxy SIII: 720px x 1280px, 306 PPI

In questo tutorial, ci concentreremo sulla piattaforma iOS e l'iPhone e iPod Touch in particolare. Tuttavia, il codice utilizzato in questo tutorial può essere utilizzato anche per la piattaforma Android.


3. Interfaccia


Utilizzeremo un'interfaccia semplice e intuitiva con più forme, pulsanti, bitmap e altro ancora. La grafica per l'interfaccia può essere trovata nei file sorgente di questo tutorial.


4. Esporta grafica


A seconda del dispositivo selezionato, potrebbe essere necessario convertire la grafica nella risoluzione consigliata (PPI), che è possibile eseguire nell'editor di immagini preferito. Ho usato il Regola dimensioni ... opzione nel Utensili menu del Anteprima applicazione su OS X. Ricordarsi di dare alle immagini un nome descrittivo e salvarle nella cartella del progetto.


5. Configurazione dell'applicazione

Useremo un file di configurazione, config.lua, per fare in modo che l'applicazione vada a schermo intero su tutti i dispositivi. Il file di configurazione mostra la dimensione dello schermo originale e il metodo utilizzato per ridimensionare il contenuto nel caso in cui l'applicazione venga eseguita su una risoluzione diversa.

 application = content = width = 320, height = 480, scale = 'letterbox',

6. main.lua

Scriviamo l'applicazione reale. Apri il tuo editor Lua preferito. Qualsiasi editor di testo normale funzionerà, ma si consiglia di utilizzare un editor di testo con evidenziazione della sintassi. Crea un nuovo file e salvalo come main.lua nella cartella del tuo progetto.


7. Struttura del codice

Struttureremo il nostro codice come se fosse una classe. Se hai familiarità con ActionScript o Java, dovresti trovare familiare la struttura del progetto.

 Classi Necessarie Variabili e costanti Denuncia Funzione Funzioni del costruttore (Funzione principale) metodi (altre funzioni) chiamata Funzione principale

8. Nascondi barra di stato

 display.setStatusBar (display.HiddenStatusBar)

Questo snippet di codice nasconde la barra di stato. La barra di stato è la barra nella parte superiore dello schermo del dispositivo che mostra l'ora, il segnale e altri indicatori.


9. Ancoraggi predefiniti

L'impostazione degli ancoraggi predefiniti del display è utile se stai trasferendo un'applicazione dalla libreria grafica precedente, ovvero i progetti che hai creato con la versione precedente di Corona SDK. Dal rilascio della libreria Graphics 2.0, il punto di riferimento di ogni immagine è cambiato dalla sua posizione in alto a sinistra al centro. Per cambiare questo in ogni immagine che usi nel tuo progetto, possiamo invocare il imposta default metodo e passare un valore da 0.0 a 1.0, con 0.0 essendo la sinistra se cambi il X ancora e la cima se cambi il y ancora.

 display.setDefault ('anchorX', 0) display.setDefault ('anchorY', 0)

10. Importa fisica

Useremo la libreria fisica per gestire le collisioni. Importa e avvia la libreria utilizzando lo snippet di codice mostrato di seguito.

 -- Fisica fisica locale = richiede ('fisica') physics.start ()

11. Contesto


Uno sfondo semplice per l'interfaccia utente dell'applicazione. Il frammento di codice qui sotto disegna lo sfondo sullo schermo.

 -- Grafica - [Background] local gameBg = display.newImage ('gameBg.png')

12. Vista titolo


Questa è la vista del titolo. È la prima schermata interattiva a comparire nel nostro gioco. Queste variabili memorizzano i suoi componenti.

 -- [Titolo vista] titolo locale locale playBtn crediti localiBtn titleView locale

13. Vista dei crediti


La vista dei crediti mostra i crediti e il copyright dell'applicazione. Il creditsView la variabile è usata per memorizzarla.

 -- [CreditsView] creditsView locali

14. Campo del testo del punteggio


Creeremo un campo di testo per mostrare la partitura del giocatore un po 'più avanti in questo tutorial. Memorizziamo un riferimento a questo campo di testo nel scoreTF variabile.

 -- Punteggio TextField local scoreTF

15. Pucks


I dischi del gioco sono creati e distribuiti casualmente sul palco. Il pucks il gruppo verrà utilizzato per raggrupparli in modo da poterli manipolare facilmente.

 -- Pucks pucks locali

16. Avviso


Il alertView variabile mantiene un riferimento alla vista di allerta che viene visualizzata quando un disco del colore sbagliato viene toccato dal giocatore. La vista di avviso mostrerà al giocatore che il gioco è finito.

 -- Avvisa locale alertView

17. Suoni


Useremo effetti sonori per dare al personaggio un carattere extra. I suoni che ho usato in questo progetto sono stati ottenuti da as3sfxr. Puoi trovare la musica di sottofondo su Play On Loop.

 -- Suona local bgMusic = audio.loadStream ('POL-sky-sanctuary-short.mp3') local blip = audio.loadSound ('blip.wav') local wrong = audio.loadSound ('lose.wav')

18. Variabili

Il prossimo snippet di codice elenca le variabili che useremo nel gioco. Il totalPucks variabile memorizza il numero di dischi posizionati sul palco, timerSrc mantiene un riferimento al timer del gioco, e tempo fa riferimento al rettangolo che mostra il tempo rimanente.

 -- Variabili locali totalPucks = 20 locale timerSrc ora locale

19. Dichiarare funzioni

Dichiariamo le funzioni come Locale Proprio all'inizio. In Lua, puoi inoltrare una funzione dichiarando il suo nome prima di implementare il corpo della funzione. Questo rende più facile tenere traccia delle varie funzioni che useremo in questo progetto.

 -- Funzioni locali Main =  local startButtonListeners =  local showCredits =  local hideCredits =  local showGameView =  local gameListeners =  local createPuck =  local movePuck =  local reduceTime =  alert locale =  

20. Costruttore

Iniziamo con la creazione di un'implementazione stub per la funzione che inizializzerà la logica di gioco, il Principale funzione.

 funzione Main () end

21. Aggiungi la vista del titolo

Successivamente, disegniamo la vista titolo sullo schermo e aggiungiamo un ascoltatore tocco ad ogni pulsante. Il nuova immagine il metodo viene utilizzato per caricare le immagini e visualizzarle sullo schermo utilizzando le posizioni passate alla funzione. Creiamo anche un gruppo chiamato titleView che funge da contenitore per gli elementi appena creati.

 function Main () titleBg = display.newImage ('titleBg.png') playBtn = display.newImage ('playBtn.png', 220, 168) creditsBtn = display.newImage ('creditsBtn.png', 204, 230) titleView = display.newGroup (titleBg, playBtn, creditsBtn) startButtonListeners ('add') fine

22. Avvia gli ascoltatori di pulsanti

Nel startButtonListeners, aggiungiamo gli ascoltatori di eventi ai pulsanti della vista del titolo. Toccando il pulsante play, mostriamo e iniziamo il gioco. Toccando il pulsante dei crediti, mostriamo i crediti del gioco.

 function startButtonListeners (action) if (action == 'add') then playBtn: addEventListener ('tap', showGameView) creditsBtn: addEventListener ('tap', showCredits) else playBtn: removeEventListener ('tap', showGameView) creditsBtn: removeEventListener ( 'tocca', mostraCrediti) fine

23. Mostra crediti

Nel showCredits, nascondiamo i pulsanti, visualizziamo i crediti e aggiungiamo un ascoltatore dei tocchi per nascondere i crediti quando il giocatore tocca i crediti.

 function showCredits: tap (e) playBtn.isVisible = false creditsBtn.isVisible = false creditsView = display.newImage ('credits.png', -110, display.contentHeight-80) transition.to (creditsView, time = 300, x = 0, onComplete = function () creditsView: addEventListener ('tap', hideCredits) end) end

24. Nascondi crediti

Quando il giocatore tocca i crediti, la vista viene intercettata dal palco e rimossa.

 function hideCredits: tap (e) playBtn.isVisible = true creditsBtn.isVisible = true transition.to (creditsView, time = 300, y = display.contentHeight + creditsView.height, onComplete = function () creditsView: removeEventListener ('tap' , hideCredits) display.remove (creditsView) creditsView = nil end) end

25. Mostra vista gioco

Quando il giocatore tocca il pulsante di riproduzione per iniziare una nuova partita, la vista del titolo viene intercettata dal palco e nascosta. Questo mostra la vista di gioco. La vista di gioco è il cuore del gioco. Rompiamo il resto del showGameView passo dopo passo.

 function showGameView: tap (e) transition.to (titleView, time = 300, x = -titleView.height, onComplete = function () startButtonListeners ('rmv') display.remove (titleView) titleView = nil end) end

26. Campo del testo del punteggio

Iniziamo creando il campo del testo del punteggio come mostrato di seguito.

 function showGameView: tap (e) transition.to (titleView, time = 300, x = -titleView.height, onComplete = function () startButtonListeners ('rmv') display.remove (titleView) titleView = nil end) - TextFields scoreTF = display.newText ('0', 25, 18, 'Courier', 15) scoreTF: setFillColor (15, 223, 245) fine

Il newText metodo accetta un numero di argomenti.

  • Il testo iniziale del campo di testo.
  • Il campo del testo X coordinata.
  • Il campo del testo y coordinata.
  • Il carattere del testo del testo e la dimensione del carattere.

Su iOS, hai accesso a una vasta gamma di caratteri. Su Android ci sono solo tre tipi di carattere disponibili; Droid Sans, Droid Serif e Droid Sans Mono.


27. Timer

Nel passaggio successivo, creiamo la forma rettangolare del timer utilizzando la libreria grafica vettoriale incorporata di Corona. Il newRect la funzione crea un rettangolo largo 20pt, alto 6pt e posizionato nella parte superiore destra dello stage. Il colore predefinito delle nuove forme è bianco, quindi è necessario cambiare il colore del rettangolo richiamando SetFillColor e passando in un valore RGB. La libreria Graphics 2.0 non utilizza valori che vanno da 0 a 255 per valori RGB. Invece un valore RGB dovrebbe variare da 0.0 a 1.0.

 function showGameView: tap (e) transition.to (titleView, time = 300, x = -titleView.height, onComplete = function () startButtonListeners ('rmv') display.remove (titleView) titleView = nil end) - TextFields scoreTF = display.newText ('0', 25, 18, 'Courier', 15) scoreTF: setFillColor (15, 223, 245) - Timer time = display.newRect (450, 20, 20, 6) tempo: setFillColor (0,05, 0,87, 0,96) fine

Un approccio rapido e semplice per convertire il vecchio valore RGB in nuovi valori è dividendo il vecchio valore di 255. Per esempio, 123 diventa 123/255, che si traduce in 0.48.


28. Pucks

Il pucks gruppo memorizza tutti i dischi in modo che possiamo manipolarli tutti in una volta.

 function showGameView: tap (e) transition.to (titleView, time = 300, x = -titleView.height, onComplete = function () startButtonListeners ('rmv') display.remove (titleView) titleView = nil end) - TextFields scoreTF = display.newText ('0', 25, 18, 'Courier', 15) scoreTF: setFillColor (15, 223, 245) - Timer time = display.newRect (450, 20, 20, 6) tempo: setFillColor (0.05, 0.87, 0.96) - Pucks pucks = display.newGroup () fine

29. Inizia partita

Per finire il showGameViewMethod, installiamo gli ascoltatori di giochi e iniziamo la musica di sottofondo. Impostando il loop parametro a -1, la musica di sottofondo si interrompe finché non gli diciamo di fermarsi.

 function showGameView: tap (e) transition.to (titleView, time = 300, x = -titleView.height, onComplete = function () startButtonListeners ('rmv') display.remove (titleView) titleView = nil end) - TextFields scoreTF = display.newText ('0', 25, 18, 'Courier', 15) scoreTF: setFillColor (15, 223, 245) - Timer time = display.newRect (450, 20, 20, 6) tempo: setFillColor (0.05, 0.87, 0.96) - Pucks pucks = display.newGroup () gameListeners ('add') audio.play (bgMusic, loops = -1, channel = 1) end

30. Ascoltatori di giochi

Nel showGameView, noi chiamiamo il gameListeners funzione in cui vengono creati i dischi invocando il createPucks funzione. Creiamo anche un rettangolo per la visualizzazione del tempo del gioco.

 function gameListeners (action) if (action == 'add') then createPucks () timerSrc = timer.performWithDelay (1000, reduceTime, 20) altro per i = 1, pucks.numChildren do pucks [i]: removeEventListener ('touch' , movePuck) end timer.cancel (timerSrc) timerSrc = nil end end

31. Crea dischi

Nel createPucks, noi usiamo a per loop per istanziare i dischi. Il numero di pucks è memorizzato in totalPucks, che abbiamo impostato 20 un po 'prima in questo tutorial.

Viene calcolata una posizione casuale per ciascun disco utilizzando Math.random. Usiamo anche Math.random per aiutarci a caricare un colore diverso dalle immagini del progetto. Come funziona? Generiamo un intero casuale tra 1 e 4, e aggiungi il risultato al nome dell'immagine che vogliamo caricare. Ad esempio, se il numero casuale è uguale a 3, il gioco carica un'immagine con nome puck3.png.

 function createPucks () per i = 1, totalPucks fa locale p locale rnd = math.floor (math.random () * 4) + 1 p = display.newImage ('puck' ... tostring (rnd) ... '.png', math.floor (math.random () * display.contentWidth), math.floor (math.random () * display.contentHeight)) p.name = 'p' ... tostring (rnd) p: addEventListener ('touch', movePuck) - Physics physics.addBody (p, 'dynamic', raggio = 12) p.isSensor = true pucks: insert (p) end end

32. Sposta funzione

Usiamo gli eventi tattili per consentire al giocatore di spostare i dischi. Quando il giocatore tocca un disco, è allineato con la posizione del tocco, il dito del giocatore, e viene quindi spostato aggiornando la sua posizione. Inoltre aggiungiamo a collisione ascoltatore del disco attivo per rilevare quando il disco si scontra con un altro disco. Questo ascoltatore di eventi viene rimosso quando il giocatore rilascia il disco sollevando il dito dallo schermo.

 function movePuck (e) if (e.phase == 'begin') then - Collision e.target.x = ex - e.target.width / 2 e.target.y = ey - e.target.height / 2 e.target:addEventListener('collision ', onCollision) end if (e.phase ==' moved ') then e.target.x = ex - e.target.width / 2 e.target.y = ey- e. target.height / 2 end if (e.phase == 'ended') then e.target:addEventListener('collision ', onCollision) end end

33. Timer

Il reduceTimer la funzione è responsabile del rettangolo del timer che abbiamo creato in precedenza. Ogni secondo, la larghezza della forma viene ridotta impostando la sua xScale proprietà e viene rimosso dallo stage quando non è più visibile. Una vista di avviso è mostrata al giocatore quando il tempo è scaduto.

 function reduceTime (e) time.xScale = time.xScale - 0.05 time.x = 450 if (time.xScale <= 0.2) then display.remove(time) alert() end end

34. Gestione delle collisioni

Il onCollision la funzione è responsabile della gestione delle collisioni tra i dischi.

 function onCollision (e) if (e.other ~ = nil) then if (e.other.name == e.target.name) then audio.play (blip) - Local Score local score = display.newText ('50 ', e.other.x, e.other.y,' Courier New Bold ', 14) transition.to (punteggio, time = 500, xScale = 1.5, yScale = 1.5, y = score.y - 20, onComplete = function () display.remove (punteggio) score = nil end) - Remove display.remove (e.other) e.other = nil - Total Score scoreTF.text = tostring (tonumber (scoreTF.text) + 50 ) scoreTF.x = 15 else audio.play (errato) alert ('lose') end end end

Questo è ciò che accade quando si verifica una collisione:

  • Per prima cosa controlliamo se i nomi dei puck sono gli stessi per vedere se il loro colore corrisponde.
  • Se hanno lo stesso colore, riproduciamo un effetto sonoro.
  • Il punteggio del giocatore è aumentato di 50 punti e il campo di testo del punteggio viene aggiornato.
  • Se il colore dei dischi non combacia, viene riprodotto un diverso effetto sonoro e viene mostrata al giocatore la vista dell'avversario.

35. Avviso

Il mettere in guardia la funzione è una semplice funzione di supporto per mostrare una vista di avviso e animarla. Interrompiamo l'audio dopo 700 millisecondi per assicurarci di poter riprodurre un effetto sonoro. Gli ascoltatori del gioco vengono rimossi per terminare il gioco e mostriamo un'immagine appropriata al giocatore.

 function alert (action) timer.performWithDelay (700, function () audio.stop (1) audio.dispose (bgMusic) bgMusic = nil end, 1) gameListeners ('rmv') if (action == 'lose') then alertView = display.newImage ('gameOver.png', 155, 125) else alertView = display.newImage ('timeUp.png', 155, 125) score locale = display.newText (scoreTF.text, 225, 160, 'Courier New Grassetto ', 20) punteggio: setFillColor (255, 255, 255) end transition.from (alertView, time = 300, xScale = 0.5, yScale = 0.5) - Attendi 100 ms per interrompere il timer fisico.performWithDelay (10, function () physics.stop () end, 1) end

36. Chiama il principale

Per iniziare il gioco, invochiamo il Principale funzione come mostrato di seguito.

 Principale()

37. Schermata di caricamento


Sulla piattaforma iOS, il file chiamato Default.png viene visualizzato durante l'avvio dell'applicazione. Aggiungi questa immagine alla cartella sorgente del tuo progetto e verrà automaticamente aggiunta dal compilatore Corona.


38. Icona


Usando la grafica creata in precedenza, ora puoi creare una bella icona. Le dimensioni della dimensione dell'icona per un iPhone senza retina sono 57 x x 57 px, mentre la versione di retina deve essere 114 x x 114 px. La grafica per iTunes deve essere 1024 x 1024 px. Suggerisco di creare prima la grafica di iTunes e quindi creare le immagini di dimensioni più ridotte ridimensionando la grafica di iTunes alle dimensioni corrette. Non è necessario rendere l'icona dell'applicazione lucida o aggiungere angoli arrotondati poiché questo è gestito dal sistema operativo.


39. Test nel simulatore


È tempo di testare la nostra applicazione nel simulatore. Apri il simulatore Corona, vai alla cartella del progetto e fai clic Aperto. Se tutto funziona come previsto, sei pronto per il passaggio finale.


40. Build


Nel simulatore Corona, vai a File> Crea e selezionare il dispositivo di destinazione. Compila i campi obbligatori e fai clic Costruire. Attendere alcuni secondi e l'applicazione è pronta per eseguire il test su un dispositivo e / o per essere inviata per la distribuzione.


Conclusione

In questo tutorial abbiamo imparato a conoscere gli spettatori di touch, il rilevamento delle collisioni e la fisica, nonché alcune altre abilità che possono essere utili in un ampio numero di giochi. Sperimenta il risultato finale e prova a modificare il gioco per creare la tua versione. Spero che questo tutorial ti sia piaciuto e l'ho trovato utile. Grazie per aver letto.