Ez a cikk egy egyszerű memóriafejlesztő játék létrehozásának folyamatát írja le, amelyet nagyon szeretek. Amellett, hogy önmagában jó, egy kicsit többet is megtudhat a Swift osztályokról és protokollokról. De mielőtt elkezdenénk, értsük meg magát a játékot.
Emlékeztetünk:a "Habr" minden olvasója számára - 10 000 rubel kedvezmény, ha a "Habr" promóciós kóddal bármely Skillbox tanfolyamra jelentkezik.
A játék egy sor kártya bemutatásával kezdődik. Arccal lefelé fekszenek (illetve kép lefelé). Ha bármelyikre kattint, a kép néhány másodpercre megnyílik.
A játékos feladata, hogy megtalálja az összes azonos képpel ellátott kártyát. Ha az első kártya kinyitása után megfordítja a másodikat, és a képek megegyeznek, mindkét kártya nyitva marad. Ha nem egyeznek, a kártyákat újra bezárják. A cél az, hogy mindent kinyissanak.
Projekt szerkezete
A játék egyszerű verziójának létrehozásához a következő összetevőkre van szüksége:
Egy vezérlő: GameController.swift.
Egy nézet: CardCell.swift.
Két modell: MemoryGame.swift és Card.swift.
Main.storyboard, hogy biztosítsa, hogy a teljes összetevőkészlet elérhető legyen.
Kezdjük a játék legegyszerűbb összetevőjével, a kártyákkal.
Card.swift
A kártyamodellnek három tulajdonsága lesz: id mindegyik azonosítására, egy logikai változó a kártya állapotának meghatározására (rejtett vagy nyitott), valamint artworkURL a kártyákon lévő képekhez.
class Card {
var id: String
var shown: Bool = false
var artworkURL: UIImage!
}
A következő módszerekre is szüksége lesz a térképekkel való felhasználói interakció szabályozásához:
Kép kártyán való megjelenítésének módja. Itt visszaállítjuk az összes tulajdonságot az alapértelmezettre. Az azonosítóhoz véletlenszerű azonosítót generálunk az NSUUIS().uuidString meghívásával.
Az egyes kártyák másolatának elkészítésének módja - annak érdekében, hogy minél nagyobb számú egyforma legyen. Ez a módszer hasonló értékű kártyát ad vissza.
A második modell a MemoryGame, itt egy 4*4-es rácsot állítunk be. A modellnek olyan tulajdonságai lesznek, mint a kártyák (kártyatömb egy rácson), a cardsShown tömb már megnyitott kártyákkal, és egy logikai változó isPlaying a játék állapotának nyomon követésére.
class MemoryGame {
var cards:[Card] = [Card]()
var cardsShown:[Card] = [Card]()
var isPlaying: Bool = false
}
Módszereket kell kidolgoznunk a felhasználói hálózattal való interakció szabályozására is.
Új játék létrehozásának módja. Itt az első módszert hívjuk meg a kezdeti elrendezés elindításához és az isPlaying változó true értékre való inicializálásához.
Ez a metódus beolvassa a **cardsShown** tömb utolsó elemét, és visszaadja a nem egyező kártyát.
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 és GameController.swift
A Main.storyboard valahogy így néz ki:
Kezdetben az új játékot viewDidLoad néven kell beállítani a vezérlőben, beleértve a rács képeit is. A játékban mindezt a 4*4 collectionView fogja képviselni. Ha még nem ismeri a collectionView-t, itt van megkaphatja a szükséges információkat.
A GameControllert az alkalmazás gyökérvezérlőjeként konfiguráljuk. A GameControllernek lesz egy gyűjteménynézete, amelyre IBOutletként fogunk hivatkozni. Egy másik hivatkozás az IBAction onStartGame() gombra, ez egy UIButton, a PLAY nevű storyboard-ban láthatod.
Egy kicsit a vezérlők megvalósításáról:
Először is inicializálunk két fő objektumot - a rácsot: játék = MemoryGame(), és egy kártyakészletet: cards = [Card]().
A kezdeti változókat viewDidLoad néven állítjuk be, ez az első metódus, amely a játék futása közben meghívódik.
A collectionView rejtettre van állítva, mert minden kártya el van rejtve, amíg a felhasználó meg nem nyomja a PLAY gombot.
Amint megnyomjuk a PLAY gombot, elindul az onStartGame IBAction szekció, és a collectionView isHidden tulajdonságot false értékre állítjuk, hogy a kártyák láthatóvá váljanak.
Minden alkalommal, amikor a felhasználó kiválaszt egy kártyát, a didSelectItemAt metódus kerül meghívásra. A metódusban a didSelectCard-ot hívjuk meg a játék fő logikájának megvalósításához.
Most beszéljünk egy kicsit a fontos protokollokról.
protokollok
A protokollokkal való munka a Swift programozás magja. A protokollok lehetővé teszik egy osztály, struktúra vagy felsorolás szabályainak meghatározását. Ez az elv lehetővé teszi moduláris és bővíthető kód írását. Valójában ez egy olyan minta, amelyet már implementálunk a GameController-ben található collectionView-hoz. Most készítsük el a saját verziónkat. A szintaxis így fog kinézni:
protocol MemoryGameProtocol {
//protocol definition goes here
}
Tudjuk, hogy egy protokoll lehetővé teszi, hogy szabályokat vagy utasításokat határozzunk meg egy osztály megvalósításához, ezért gondoljuk át, mik legyenek azok. Összesen négyre van szüksége.
A játék kezdete: memoryGameDidStart.
A kártyát képpel lefelé kell fordítania: memoryGameShowCards.
A kártyát képpel lefelé kell fordítania: memoryGameHideCards.
A játék vége: memoryGameDidEnd.
Mind a négy metódus megvalósítható a fő osztályhoz, ami a GameController.
memoryGameDidStart
Amikor ez a módszer fut, a játéknak el kell indulnia (a felhasználó megnyomja a PLAY gombot). Itt egyszerűen újratöltjük a tartalmat a collectionView.reloadData() meghívásával, amely megkeveri a kártyákat.
Ezt a metódust a collectionSDViewSelectItemAt gyűjteményből hívjuk. Először a kiválasztott kártyát mutatja. Ezután ellenőrzi, hogy van-e páratlan kártya a cardsShown tömbben (ha a Shown kártyák száma páratlan). Ha van ilyen, a kiválasztott kártya összehasonlításra kerül vele. Ha a képek megegyeznek, mindkét kártya hozzáadódik a Megjelenített kártyákhoz, és képpel felfelé marad. Ha eltér, a kártya a Megjelenített kártyákat hagyja, és mindkettőt képpel lefelé fordítják.
memoryGameHideCards
Ha a kártyák nem egyeznek, akkor ez a metódus meghívásra kerül, és a kártyaképek elrejtésre kerülnek.
mutatott = hamis.
memoryGameDidEnd
Ha ezt a metódust hívjuk, az azt jelenti, hogy az összes kártya már fel van fedve, és benne van a kártyákShown listában: cardsShown.count = kártyák.szám, tehát a játéknak vége. A metódus kifejezetten azután hívódik meg, hogy meghívtuk az endGame()-t, hogy az isPlaying var értéket false értékre állítsuk, ami után megjelenik a játék vége üzenet. Az alertController a vezérlő indikátoraként is szolgál. A viewDidDisappar meghívásra kerül, és a játék alaphelyzetbe áll.
Így néz ki mindez a GameControllerben:
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()
}
}
Valójában ez minden. Ezzel a projekttel létrehozhatod a játék saját verzióját.