Denne artikel beskriver processen med at skabe et simpelt hukommelsestræningsspil, som jeg virkelig nyder. Udover at være god i sig selv, lærer du lidt mere om Swift-klasser og -protokoller, mens du går. Men før vi starter, lad os forstå selve spillet.
Påmindelse:for alle læsere af "Habr" - en rabat på 10 rubler ved tilmelding til ethvert Skillbox-kursus ved hjælp af "Habr"-kampagnekoden.
Spillet begynder med en demonstration af et sæt kort. De ligger med forsiden nedad (henholdsvis billedet nedad). Når du klikker på en, åbnes billedet i et par sekunder.
Spillerens opgave er at finde alle kort med de samme billeder. Hvis du efter at have åbnet det første kort vender det andet og billederne matcher, forbliver begge kort åbne. Hvis de ikke matcher, lukkes kortene igen. Målet er at åbne alt.
Projektets struktur
For at lave en simpel version af dette spil skal du bruge følgende komponenter:
Én controller: GameController.swift.
One View: CardCell.swift.
To modeller: MemoryGame.swift og Card.swift.
Main.storyboard for at sikre, at hele sættet af komponenter er tilgængeligt.
Vi starter med den enkleste komponent i spillet, kortene.
Card.swift
Kortmodellen vil have tre egenskaber: id til at identificere hver enkelt, en boolesk variabel vist for at angive kortets status (skjult eller åben) og artworkURL for billederne på kortene.
class Card {
var id: String
var shown: Bool = false
var artworkURL: UIImage!
}
Du skal også bruge disse metoder til at kontrollere brugerinteraktion med kort:
Metode til at vise et billede på et kort. Her nulstiller vi alle egenskaber til standard. For id genererer vi et tilfældigt id ved at kalde NSUUIS().uuidString.
Den anden model er MemoryGame, her sætter vi et 4*4 gitter. Modellen vil have egenskaber såsom kort (en række kort på et gitter), et kort vist array med kort, der allerede er åbne, og en boolsk variabel isPlaying for at spore spillets status.
class MemoryGame {
var cards:[Card] = [Card]()
var cardsShown:[Card] = [Card]()
var isPlaying: Bool = false
}
Vi skal også udvikle metoder til at kontrollere brugerinteraktion med nettet.
Denne metode læser det sidste element i **cardsShown**-arrayet og returnerer det ikke-matchende kort.
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 og GameController.swift
Main.storyboard ser sådan ud:
I første omgang skal du indstille det nye spil som viewDidLoad i controlleren, inklusive billederne til gitteret. I spillet vil alt dette blive repræsenteret af 4*4 collectionView. Hvis du endnu ikke er bekendt med collectionView, så er den her du kan få de oplysninger, du har brug for.
Vi vil konfigurere GameController som applikationens root-controller. GameControlleren vil have en samlingsvisning, som vi vil referere til som en IBoutlet. En anden reference er IBAction onStartGame() knappen, dette er en UIButton, du kan se den i storyboardet kaldet PLAY.
Lidt om implementeringen af controllere:
Først initialiserer vi to hovedobjekter - gitteret: spil = MemoryGame(), og et sæt kort: kort = [Card]().
Vi indstiller de indledende variabler som viewDidLoad, dette er den første metode, der kaldes, mens spillet kører.
collectionView er sat til skjult, fordi alle kort er skjult, indtil brugeren trykker på PLAY.
Så snart vi trykker på PLAY, starter onStartGame IBAction-sektionen, og vi sætter egenskaben collectionView isHidden til false, så kortene kan blive synlige.
Hver gang brugeren vælger et kort, kaldes didSelectItemAt-metoden. I metoden kalder vi didSelectCard for at implementere hovedspillets logik.
Her er den endelige GameController-implementering:
At arbejde med protokoller er kernen i Swift-programmering. Protokoller giver mulighed for at definere regler for en klasse, struktur eller opregning. Dette princip giver dig mulighed for at skrive modulær og udvidelig kode. Faktisk er dette et mønster, som vi allerede implementerer for collectionView i GameController. Lad os nu lave vores egen version. Syntaksen vil se således ud:
protocol MemoryGameProtocol {
//protocol definition goes here
}
Vi ved, at en protokol giver os mulighed for at definere regler eller instruktioner til implementering af en klasse, så lad os tænke over, hvad de skal være. Du skal bruge fire i alt.
Spilstart: memoryGameDidStart.
Du skal vende kortet med forsiden nedad: memoryGameShowCards.
Du skal vende kortet med forsiden nedad: memoryGameHideCards.
Spilslut: memoryGameDidEnd.
Alle fire metoder kan implementeres for hovedklassen, som er GameController.
memoryGameDidStart
Når denne metode køres, bør spillet starte (brugeren trykker på PLAY). Her genindlæser vi simpelthen indholdet ved at kalde collectionView.reloadData(), som vil blande kortene.
Vi kalder denne metode fra collectionSDViewSelectItemAt. Først viser det det valgte kort. Kontrollerer derefter, om der er et umatchet kort i arrayet med de viste kort (hvis antallet af de viste kort er ulige). Hvis der er et, sammenlignes det valgte kort med det. Hvis billederne er ens, føjes begge kort til de viste kort og forbliver med billedsiden opad. Hvis det er forskelligt, efterlader kortet de viste kort, og begge vendes med forsiden nedad.
memoryGameHideCards
Hvis kortene ikke stemmer overens, kaldes denne metode, og kortbillederne er skjult.
vist = falsk.
memoryGameDidEnd
Når denne metode kaldes, betyder det, at alle kort allerede er afsløret og er på listen over de viste kort: cardsShown.count = cards.count, så spillet er slut. Metoden kaldes specifikt efter at vi har kaldt endGame() for at sætte isPlaying var til false, hvorefter meddelelsen om spilslut vises. Også alertController bruges som indikator for controlleren. viewDidDisappear kaldes, og spillet nulstilles.
Sådan ser det hele ud i GameController:
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()
}
}
Faktisk er det alt. Du kan bruge dette projekt til at skabe din egen version af spillet.