Ovaj članak opisuje proces stvaranja jednostavne igre za vježbanje pamćenja u kojoj stvarno uživam. Osim što je sam po sebi dobar, usput ćete naučiti nešto više o Swift klasama i protokolima. Ali prije nego što počnemo, shvatimo samu igru.
Podsjećamo:za sve čitatelje "Habra" - popust od 10 000 rubalja pri upisu na bilo koji tečaj Skillbox koristeći promotivni kod "Habr".
Igra počinje demonstracijom seta karata. Leže licem prema dolje (odnosno, slikom prema dolje). Kada kliknete na bilo koji, slika se otvara na nekoliko sekundi.
Zadatak igrača je pronaći sve karte s istim slikama. Ako nakon otvaranja prve karte okrenete drugu i slike se poklope, obje kartice ostaju otvorene. Ako se ne podudaraju, karte se ponovno zatvaraju. Cilj je otvoriti sve.
Struktura projekta
Za izradu jednostavne verzije ove igre potrebne su vam sljedeće komponente:
Jedan kontroler: GameController.swift.
Jedan pogled: CardCell.swift.
Dva modela: MemoryGame.swift i Card.swift.
Main.storyboard kako bi se osiguralo da je cijeli skup komponenti dostupan.
Počinjemo s najjednostavnijom komponentom igre, kartama.
Card.swift
Model kartice imat će tri svojstva: ID za identifikaciju svake od njih, Booleovu varijablu prikazanu za određivanje statusa kartice (skrivena ili otvorena) i artworkURL za slike na karticama.
class Card {
var id: String
var shown: Bool = false
var artworkURL: UIImage!
}
Također ćete trebati ove metode za kontrolu interakcije korisnika s kartama:
Metoda prikazivanja slike na kartici. Ovdje vraćamo sva svojstva na zadane. Za id, generiramo nasumični id pozivanjem NSUUIS().uuidString.
Drugi model je MemoryGame, ovdje smo postavili mrežu 4*4. Model će imati svojstva kao što su kartice (niz karata na mreži), polje cardsShown s već otvorenim kartama i booleovu varijablu isPlaying za praćenje statusa igre.
class MemoryGame {
var cards:[Card] = [Card]()
var cardsShown:[Card] = [Card]()
var isPlaying: Bool = false
}
Također moramo razviti metode za kontrolu interakcije korisnika s mrežom.
Ova metoda čita posljednji element u nizu **cardsShown** i vraća karticu koja se ne podudara.
func didSelectCard(_ card: Card?) {
guard let card = card else { return }
if unmatchedCardShown() {
let unmatched = unmatchedCard()!
if card.equals(unmatched) {
cardsShown.append(card)
} else {
let secondCard = cardsShown.removeLast()
}
} else {
cardsShown.append(card)
}
if cardsShown.count == cards.count {
endGame()
}
}
Main.storyboard i GameController.swift
Main.storyboard izgleda otprilike ovako:
U početku morate novu igru postaviti kao viewDidLoad u kontroleru, uključujući slike za rešetku. U igri će sve to predstavljati 4*4 collectionView. Ako još niste upoznati s CollectionViewom, evo ga možete dobiti informacije koje su vam potrebne.
Konfigurirat ćemo GameController kao korijenski kontroler aplikacije. GameController će imati collectionView koji ćemo spominjati kao IBOutlet. Još jedna referenca je gumb IBAction onStartGame(), ovo je UIButton, možete ga vidjeti u ploči scenarija pod nazivom PLAY.
Malo o implementaciji kontrolera:
Prvo inicijaliziramo dva glavna objekta - rešetku: game = MemoryGame() i skup karata: cards = [Card]().
Postavili smo početne varijable kao viewDidLoad, ovo je prva metoda koja se poziva dok igra radi.
collectionView je postavljen na skriven jer su sve kartice skrivene dok korisnik ne pritisne PLAY.
Čim pritisnemo PLAY, pokreće se odjeljak onStartGame IBAction, a svojstvo collectionView isHidden postavljamo na false kako bi kartice postale vidljive.
Svaki put kada korisnik odabere karticu, poziva se metoda didSelectItemAt. U metodi koju pozivamo didSelectCard za implementaciju glavne logike igre.
Rad s protokolima srž je Swift programiranja. Protokoli pružaju mogućnost definiranja pravila za klasu, strukturu ili enumeraciju. Ovaj princip vam omogućuje pisanje modularnog i proširivog koda. Zapravo, ovo je uzorak koji već implementiramo za collectionView u GameControlleru. Sada napravimo vlastitu verziju. Sintaksa će izgledati ovako:
protocol MemoryGameProtocol {
//protocol definition goes here
}
Znamo da nam protokol omogućuje definiranje pravila ili uputa za implementaciju klase, pa razmislimo o tome što bi one trebale biti. Trebate ih ukupno četiri.
Početak igre: memoryGameDidStart.
Morate okrenuti karticu licem prema dolje: memoryGameShowCards.
Morate okrenuti karticu licem prema dolje: memoryGameHideCards.
Kraj igre: memoryGameDidEnd.
Sve četiri metode mogu se implementirati za glavnu klasu, a to je GameController.
memoryGameDidStart
Kada se ova metoda pokrene, igra bi trebala započeti (korisnik pritisne PLAY). Ovdje ćemo jednostavno ponovno učitati sadržaj pozivom collectionView.reloadData(), koji će izmiješati karte.
Ovu metodu pozivamo iz collectionSDViewSelectItemAt. Prvo prikazuje odabranu karticu. Zatim provjerava postoji li neuparena karta u nizu cardsShown (ako je broj cardsShown neparan). Ako postoji, odabrana karta se uspoređuje s njom. Ako su slike iste, obje karte se dodaju na prikazane kartice i ostaju licem prema gore. Ako je drugačija, karta ostavlja prikazane karte i obje su okrenute licem prema dolje.
memoryGameHideCards
Ako se kartice ne podudaraju, poziva se ova metoda i slike kartica se skrivaju.
prikazano = lažno.
memoryGameDidEnd
Kada se ova metoda pozove, to znači da su sve karte već otkrivene i nalaze se na listi cardsShown: cardsShown.count = cards.count, tako da je igra gotova. Metoda se posebno poziva nakon što smo pozvali endGame() da postavimo isPlaying var na false, nakon čega se prikazuje poruka o kraju igre. AlertController se također koristi kao indikator za kontroler. viewDidDisappear se poziva i igra se resetira.
Evo kako to sve izgleda u GameControlleru:
extension GameController: MemoryGameProtocol {
func memoryGameDidStart(_ game: MemoryGame) {
collectionView.reloadData()
}
func memoryGame(_ game: MemoryGame, showCards cards: [Card]) {
for card in cards {
guard let index = game.indexForCard(card)
else { continue
}
let cell = collectionView.cellForItem(
at: IndexPath(item: index, section:0)
) as! CardCell
cell.showCard(true, animted: true)
}
}
func memoryGame(_ game: MemoryGame, hideCards cards: [Card]) {
for card in cards {
guard let index = game.indexForCard(card)
else { continue
}
let cell = collectionView.cellForItem(
at: IndexPath(item: index, section:0)
) as! CardCell
cell.showCard(false, animted: true)
}
}
func memoryGameDidEnd(_ game: MemoryGame) {
let alertController = UIAlertController(
title: defaultAlertTitle,
message: defaultAlertMessage,
preferredStyle: .alert
)
let cancelAction = UIAlertAction(
title: "Nah", style: .cancel) {
[weak self] (action) in
self?.collectionView.isHidden = true
}
let playAgainAction = UIAlertAction(
title: "Dale!", style: .default) {
[weak self] (action) in
self?.collectionView.isHidden = true
self?.resetGame()
}
alertController.addAction(cancelAction)
alertController.addAction(playAgainAction)
self.present(alertController, animated: true) { }
resetGame()
}
}
Zapravo, to je sve. Možete koristiti ovaj projekt za izradu vlastite verzije igre.