Ta članek opisuje postopek ustvarjanja preproste igre za urjenje spomina, v kateri resnično uživam. Poleg tega, da je sam po sebi dober, se boste sproti naučili nekaj več o razredih in protokolih Swift. Toda preden začnemo, razumejmo samo igro.
Spomnimo:za vse bralce "Habr" - popust v višini 10 rubljev ob vpisu v kateri koli tečaj Skillbox s promocijsko kodo "Habr".
Igra se začne s predstavitvijo kompleta kart. Ležijo z obrazom navzdol (oziroma s sliko navzdol). Ko kliknete katero koli, se slika odpre za nekaj sekund.
Igralčeva naloga je najti vse karte z enakimi slikami. Če po odprtju prve karte obrnete drugo in se sliki ujemata, ostaneta obe karti odprti. Če se ne ujemajo, se karte ponovno zaprejo. Cilj je odpreti vse.
Struktura projekta
Za ustvarjanje preproste različice te igre potrebujete naslednje komponente:
En krmilnik: GameController.swift.
En pogled: CardCell.swift.
Dva modela: MemoryGame.swift in Card.swift.
Main.storyboard, da zagotovite, da je na voljo celoten nabor komponent.
Začnemo z najpreprostejšim delom igre, kartami.
Card.swift
Model kartice bo imel tri lastnosti: ID za identifikacijo vsake, logično spremenljivko, prikazano za določitev statusa kartice (skrita ali odprta), in artworkURL za slike na karticah.
class Card {
var id: String
var shown: Bool = false
var artworkURL: UIImage!
}
Te metode boste potrebovali tudi za nadzor interakcije uporabnika z zemljevidi:
Metoda za prikaz slike na kartici. Tukaj ponastavimo vse lastnosti na privzete. Za id ustvarimo naključni id s klicem NSUUIS().uuidString.
Drugi model je MemoryGame, tukaj smo postavili mrežo 4*4. Model bo imel lastnosti, kot so kartice (matrika kart na mreži), matrika cardsShown z že odprtimi kartami in logična spremenljivka isPlaying za sledenje statusu igre.
class MemoryGame {
var cards:[Card] = [Card]()
var cardsShown:[Card] = [Card]()
var isPlaying: Bool = false
}
Prav tako moramo razviti metode za nadzor interakcije uporabnikov z omrežjem.
Ta metoda prebere zadnji element v matriki **cardsShown** in vrne neujemajočo se kartico.
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 in GameController.swift
Main.storyboard izgleda nekako takole:
Na začetku morate novo igro nastaviti kot viewDidLoad v krmilniku, vključno s slikami za mrežo. V igri bo vse to predstavljal 4*4 collectionView. Če še niste seznanjeni s CollectionView, je tukaj lahko dobite informacije, ki jih potrebujete.
GameController bomo konfigurirali kot korenski krmilnik aplikacije. GameController bo imel collectionView, ki ga bomo sklicevali kot IBOutlet. Druga referenca je gumb IBAction onStartGame(), to je UIButton, lahko ga vidite v snemalni knjigi z imenom PLAY.
Nekaj o izvedbi krmilnikov:
Najprej inicializiramo dva glavna objekta - mrežo: game = MemoryGame() in niz kart: cards = [Card]().
Začetne spremenljivke smo nastavili kot viewDidLoad, to je prva metoda, ki se kliče, ko se igra izvaja.
collectionView je nastavljen na skrito, ker so vse kartice skrite, dokler uporabnik ne pritisne PLAY.
Takoj ko pritisnemo PLAY, se zažene razdelek onStartGame IBAction, lastnost collectionView isHidden pa nastavimo na false, tako da lahko kartice postanejo vidne.
Vsakič, ko uporabnik izbere kartico, se pokliče metoda didSelectItemAt. V metodi, ki jo pokličemo didSelectCard za implementacijo glavne logike igre.
Zdaj pa se pogovorimo malo o pomembnih protokolih.
Protokoli
Delo s protokoli je jedro programiranja Swift. Protokoli nudijo možnost definiranja pravil za razred, strukturo ali oštevilčenje. To načelo vam omogoča pisanje modularne in razširljive kode. Pravzaprav je to vzorec, ki ga že izvajamo za collectionView v GameControllerju. Zdaj pa naredimo svojo različico. Sintaksa bo videti takole:
protocol MemoryGameProtocol {
//protocol definition goes here
}
Vemo, da nam protokol omogoča definiranje pravil ali navodil za implementacijo razreda, zato pomislimo, kakšna bi morala biti. Skupaj potrebujete štiri.
Začetek igre: memoryGameDidStart.
Kartico morate obrniti z licem navzdol: memoryGameShowCards.
Kartico morate obrniti z licem navzdol: memoryGameHideCards.
Konec igre: memoryGameDidEnd.
Vse štiri metode je mogoče implementirati za glavni razred, ki je GameController.
memoryGameDidStart
Ko je ta metoda zagnana, se mora začeti igra (uporabnik pritisne PLAY). Tukaj bomo preprosto znova naložili vsebino s klicem collectionView.reloadData(), ki bo premešal karte.
To metodo kličemo iz zbirkeSDViewSelectItemAt. Najprej prikaže izbrano kartico. Nato preveri, ali je v matriki cardsShown karta, ki se ne ujema (če je število cardsShown liho). Če obstaja, se izbrana karta primerja z njo. Če sta sliki enaki, sta obe kartici dodani na cardsShown in ostaneta obrnjeni navzgor. Če je drugačna, karta ostane prikazana in obe sta obrnjeni z licem navzdol.
memoryGameHideCards
Če se karti ne ujemata, se ta metoda pokliče in slike kartic se skrijejo.
prikazano = napačno.
memoryGameDidEnd
Ko je ta metoda poklicana, to pomeni, da so vse karte že razkrite in so na seznamu cardsShown: cardsShown.count = cards.count, torej je igre konec. Metoda je poklicana posebej potem, ko smo poklicali endGame(), da nastavimo isPlaying var na false, po tem pa se prikaže sporočilo o koncu igre. AlertController se uporablja tudi kot indikator za krmilnik. viewDidDisappear se pokliče in igra se ponastavi.
Tako je videti vse skupaj v GameControllerju:
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()
}
}
Pravzaprav je to vse. Ta projekt lahko uporabite za ustvarjanje lastne različice igre.