Общий аккаунт ( обновлен 24 мая )   Форум
марта 23, 2015 iphone-gps.ru 2015-03-23

Делаем игру для iPhone в стиле Mega Jump – Часть 4 (последняя)

Делаем игру для iPhone в стиле Mega Jump – Часть 4 (последняя)

Ну вот мы и подошли к последней, заключительной части нашего урока. В предыдущих частях: части 1, части 2, части 3, мы создали физику игры, подключили графическую оболочку и научили нашего героя реагировать на наклон устройства. Осталось совсем немного – сделать подсчет очков и дописать кое-какие мелочи по коду. В результате у нас получится настоящая игра, готовая для размещения в App Store…

Создание HUD

Перед тем как начать считать очки, мы должны обеспечить их отображение на экране HUD, чтобы игрок мог видеть набранные баллы и количество звезд.
В левом верхнем углу сцены на нашем HUD будет отображаться общее число собранных звезд, а текущий счет – в правом верхнем углу. Для этого нам нужно создать два лейбла класса SKLabelNodes.

Создайте следующие свойства в файле GameScene.swift:

// Labels for score and stars
var lblScore: SKLabelNode!
var lblStars: SKLabelNode!

Чтобы скомпоновать HUD, добавьте следующий код в метод init(size:) класса GameScene.swift сразу перед строкой, которая инициализирует MotionManager:

// Build the HUD
 
// Stars
// 1
let star = SKSpriteNode(imageNamed: "Star")
star.position = CGPoint(x: 25, y: self.size.height-30)
hudNode.addChild(star)
 
// 2
lblStars = SKLabelNode(fontNamed: "ChalkboardSE-Bold")
lblStars.fontSize = 30
lblStars.fontColor = SKColor.whiteColor()
lblStars.position = CGPoint(x: 50, y: self.size.height-40)
lblStars.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Left
 
// 3
lblStars.text = String(format: "X %d", GameState.sharedInstance.stars)
hudNode.addChild(lblStars)
 
// Score
// 4
lblScore = SKLabelNode(fontNamed: "ChalkboardSE-Bold")
lblScore.fontSize = 30
lblScore.fontColor = SKColor.whiteColor()
lblScore.position = CGPoint(x: self.size.width-20, y: self.size.height-40)
lblScore.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Right
 
// 5
lblScore.text = "0"
hudNode.addChild(lblScore)

Рассмотрим детально этот блок кода:

1. Сначала мы добавили графику для звезды в левом верхнем углу сцены, чтобы показать игроку, что стоящее рядом с ней число — это количество собранных звезд.

2. Рядом со звездой, мы размещаем SKLabelNode, в котором текст выровнен по левому краю.

3. Мы отобразили на лейбле количество звезд, взятого из класса GameState.

4. Мы добавили в правый верхний угол сцены лейбл SKLabelNode с текстом, выровненным по правому краю.

5. Мы отобразили на этом лейбле ноль, так как в настоящее время никакого счета ещё нет.

Постройте и запустите. Вы увидите два лейбла в верхней части экрана.

Делаем игру для iPhone в стиле Mega Jump – Часть 4 (последняя)

Начисление очков

Наконец пришло время, чтобы начать начислять игроку очки за его тяжкий труд. В Uber Jump набрать очки можно двумя способами: подниматься вверх по сцене и собирать звезды.

Для того, чтобы настроить получение очков за звезды, откройте GameObjectNode.swift и просто добавьте следующий код в нижнюю часть метода collisionWithPlayer класса StarNode сразу перед оператором return:

// Award score
GameState.sharedInstance.score! += (starType == .Normal ? 20 : 100)

И это всё! Мы добавляем 20 очков к счету за обычную звезду и 100 очков за звезду специального типа.

Чтобы отобразить обновленный счет, давайте вернёмся к методу didBeginContact в GameScene.swift. Напомним, что в первой части этого урока в этом методе мы устанавливали значение true для флага с именем updateHUD в случае необходимости изменять отображаемые в HUD значения.

Заключите следующие две строчки кода между фигурных скобок условия if updateHUD {…} внутри этого метода (сейчас там должен быть комментарий с текстом «TODO: Update HUD in Part 2»):

lblStars.text = String(format: "X %d", GameState.sharedInstance.stars)
lblScore.text = String(format: "%d", GameState.sharedInstance.score)

Постройте и запустите. Нажмите, чтобы начать игру. По мере того как вы будете собирать звезды, ваш счет станет увеличиваться.

Делаем игру для iPhone в стиле Mega Jump – Часть 4 (последняя)

Чтобы понимать, когда именно нужно начислять очки за путешествие вверх по экрану, вы должны хранить самую высокую точку по оси Y, которой достиг герой в течение текущей игры. Мы будем использовать эти данные, чтобы увеличивать счет только тогда, когда герой добирается до новой наивысшей точки, а не присуждать очки постоянно, пока игрок прыгает вверх и вниз по экрану.

Добавьте следующее свойство класса в файл GameScene.swift:

// Max y reached by player
var maxPlayerY: Int

Узел героя начинает движение, когда его координата по оси Y равна 80, поэтому вы должны присвоить свойству maxPlayerY значение 80, если ,конечно, не хотите дать игроку 80 очков только за то, что начал игру. ;]

Добавьте следующую строчку в метод init(size:) класса GameScene.swift сразу после строки, которая устанавливает цвет фона:

// Reset
maxPlayerY = 80

Чтобы начислять игроку очки за перемещение вверх экрана, откройте начало метода update: и добавьте следующие строки:

// New max height ?
// 1
if Int(player.position.y) > maxPlayerY! {
  // 2
  GameState.sharedInstance.score! += Int(player.position.y) - maxPlayerY!
  // 3
  maxPlayerY = Int(player.position.y)
  // 4
  lblScore.text = String(format: "%d", GameState.sharedInstance.score)
}

Этот код лучше рассмотреть детально:

1. Во-первых, нужно проверить, поднялся ли узел героя выше максимальной отметки, которой достигал в пределах данного цикла игры.

2. Если да, то мы добавляем к счету разницу между текущей высотой и максимальной.

3. Теперь мы устанавливаем новое максимальное значение y.

4. Наконец, мы обновляем лейбл, отображающий счет, в соответствии с новым значением.

Постройте и запустите. Нажмите, чтобы начать. Начните играть и вы увидите, как ваш счет будет увеличиваться по мере продвижения вверх.

Делаем игру для iPhone в стиле Mega Jump – Часть 4 (последняя)

Теперь обратим внимание на подсчет звезд. Мы должны увеличивать его каждый раз, когда узел игрока пересекается со звездой, поэтому откройте GameObjectNode.swift и добавьте следующий код в метод collisionWithPlayer класса StarNode сразу после строки, которая начисляет очки:

// Award stars
GameState.sharedInstance.stars! += (starType == .Normal ? 1 : 5)

Это все, что нужно было сделать! Постройте и запустите. Нажмите, чтобы начать. Следите за увеличением количества звезд по мере того, как будете собирать их.

Делаем игру для iPhone в стиле Mega Jump – Часть 4 (последняя)

Во время вашей игры вы могли заметить, что когда вы падаете, все пересекаемые героем игровые объекты всё ещё остаются в игре. “Эй!” Вы наверняка думаете: “Я достаточное много играл в Mega Jump, чтобы с уверенностью утверждать, что там такого не было!” Да верно, но это легко исправить.

Напомним, что мы добавляли метод под названием checkNodeRemoval в класс GameObjectNode, который проверяет, нужно ли удалять узел. Пришло время, чтобы вызвать этот метод в каждом кадре.

Добавьте следующий код в метод update класса GameScene.swift, сразу перед строкой, которая проверяет, превышает ли ордината позиции узла героя значение 200:

// Remove game objects that have passed by
foregroundNode.enumerateChildNodesWithName("NODE_PLATFORM", usingBlock: {
  (node, stop) in
  let platform = node as PlatformNode
  platform.checkNodeRemoval(self.player.position.y)
})
 
foregroundNode.enumerateChildNodesWithName("NODE_STAR", usingBlock: {
  (node, stop) in
  let star = node as StarNode
  star.checkNodeRemoval(self.player.position.y)
})

Здесь мы перечисляем все платформы в узле переднего плана и вызываем метод checkNodeRemoval для каждой из них. Потом тоже самое делаем для звёзд.

Постройте и запустите. Нажмите, чтобы начать. Теперь, когда вы будете падать, то не почувствуете под ногами ничего, кроме чистого неба.

Делаем игру для iPhone в стиле Mega Jump – Часть 4 (последняя)

Game Over!

Игра заканчивается тогда, когда герой падает в нижнюю часть сцены или поднимается на вершину уровня. В этот момент нам нужно отобразить финальный счет и наивысший балл. Мы осуществим это посредством перехода к сцене конца игры.

Создайте новый Cocoa Touch Class с именем EndGameScene и сделайте его подклассом SKScene.

Делаем игру для iPhone в стиле Mega Jump – Часть 4 (последняя)

EndGameScene будет представлять из себя обычный экран, отображающий счет игрока, количество собранных звезд и наивысший балл. Мы добавим все узлы в метод init(size:):, поэтому откройте EndGameScene.swift и замените всё содержимое файла на следующее:

import SpriteKit
 
class EndGameScene: SKScene {
 
  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
  }
 
  override init(size: CGSize) {
    super.init(size: size)
 
    // Stars
    let star = SKSpriteNode(imageNamed: "Star")
    star.position = CGPoint(x: 25, y: self.size.height-30)
    addChild(star)
 
    let lblStars = SKLabelNode(fontNamed: "ChalkboardSE-Bold")
    lblStars.fontSize = 30
    lblStars.fontColor = SKColor.whiteColor()
    lblStars.position = CGPoint(x: 50, y: self.size.height-40)
    lblStars.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Left
    lblStars.text = String(format: "X %d", GameState.sharedInstance.stars)
    addChild(lblStars)
 
    // Score
    let lblScore = SKLabelNode(fontNamed: "ChalkboardSE-Bold")
    lblScore.fontSize = 60
    lblScore.fontColor = SKColor.whiteColor()
    lblScore.position = CGPoint(x: self.size.width / 2, y: 300)
    lblScore.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Center
    lblScore.text = String(format: "%d", GameState.sharedInstance.score)
    addChild(lblScore)
 
    // High Score
    let lblHighScore = SKLabelNode(fontNamed: "ChalkboardSE-Bold")
    lblHighScore.fontSize = 30
    lblHighScore.fontColor = SKColor.cyanColor()
    lblHighScore.position = CGPoint(x: self.size.width / 2, y: 150)
    lblHighScore.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Center
    lblHighScore.text = String(format: "High Score: %d", GameState.sharedInstance.highScore)
    addChild(lblHighScore)
 
    // Try again
    let lblTryAgain = SKLabelNode(fontNamed: "ChalkboardSE-Bold")
    lblTryAgain.fontSize = 30
    lblTryAgain.fontColor = SKColor.whiteColor()
    lblTryAgain.position = CGPoint(x: self.size.width / 2, y: 50)
    lblTryAgain.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Center
    lblTryAgain.text = "Tap To Try Again"
    addChild(lblTryAgain)
  }
}

Здесь много кода, но после всего того, что вы сделали в этом уроке, вас уже ничего не должно пугать.

По сути мы создаем три лейбла, которые будут служить для отображения количества собранных звезд, финального счета и наивысшего балла. Мы присваиваем им значения, взятые из синглтона GameState. Мы также добавляем лейбл, который подсказывает пользователю, что ему нужно коснуться экрана для начала новой игры.

Чтобы отслеживать, закончилась игра или нет, добавьте следующую булевую переменную в свойства класса GameScene.swift:

// Game over dude!
var gameOver = false

В конце игры нужно сохранить текущее состояние в синглтон GameState и осуществить переход к новой сцене. Добавьте следующий метод в GameScene.swift:

func endGame() {
  // 1
  gameOver = true
 
  // 2
  // Save stars and high score
  GameState.sharedInstance.saveState()
 
  // 3
  let reveal = SKTransition.fadeWithDuration(0.5)
  let endGameScene = EndGameScene(size: self.size)
  self.view!.presentScene(endGameScene, transition: reveal)
}

Давайте рассмотрим его детально:

1. Сначала мы устанавливаем переменной gameOver значение true.

2. Затем сообщаем синглтону GameState, чтоб он записал состояние игры в файл пользовательских настроек.

3. И, наконец, мы создаём экземпляр класса EndGameScene и делаем переход к нему путём затухания экрана в течение 0,5 секунд.

Метод endGame нужно вызывать, когда узел героя либо падает на дно экрана, либо достигает максимальной высоты уровня. Мы проверяем оба эти случая в методе update главной сцены.

Добавьте следующий код в тот же класс GameScene.swift, в конец метода update:

// 1
// Check if we've finished the level
if Int(player.position.y) > endLevelY {
  endGame()
}
 
// 2
// Check if we've fallen too far
if Int(player.position.y) < maxPlayerY - 800 {
  endGame()
}

Взгляните на эти проверки:

Помните, мы загружали endLevelY из листа свойств? Это то значение координаты Y, при которой игрок должен заканчивать уровень.

Если узел героя падает более чем на 800 ниже максимальной отметки, которой он достиг, то игра заканчивается.

Прежде чем запустить игру для того, чтобы увидеть сцену конца игры, мы должны убедиться, что метод endGame не вызывается более одного раза. А это произойдёт, как только метод update() сработает в следующем кадре.

Добавьте следующую строку в начало метода Update () в GameScene.swift:

if gameOver {
  return
}

Теперь при вызове метода update(), прежде чем сделать переход, он проверяет, закончилась ли игра.

Постройте и запустите. Нажмите, чтобы начать, поиграйте немного, а затем дайте «ультра прыгуну» упасть. Произойдёт переход на сцену конца игры.

Делаем игру для iPhone в стиле Mega Jump – Часть 4 (последняя)

Перезапуск

Чтобы иметь возможность перезапустить игру, находясь на конечной сцене, мы должны модифицировать класс EndGameScene так, чтобы он по событию касания осуществлял переход обратно на основную сцену.

Откройте EndGameScene.swift и добавьте следующий метод в этот класс для обработки касаний:

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
  // Transition back to the Game
  let reveal = SKTransition.fadeWithDuration(0.5)
  let gameScene = GameScene(size: self.size)
  self.view!.presentScene(gameScene, transition: reveal)
}

Этот код просто создаёт переход на новую сцену GameScene подобно тому, как он осуществлялся при первом запуске приложения.

Остался последний штрих и всё будет готово! Откройте GameScene.swift. В методе init(size:), там где мы сбрасывали значение maxPlayerY, добавьте следующий код:

GameState.sharedInstance.score = 0
gameOver = false

Мы обнуляем счёт в синглетоне GameState, а также сбрасываем флаг GameOver, чтобы игра могла начаться заново.

Постройте и запустите. Нажмите, чтобы начать и играйте. А теперь постарайтесь побить самый высокий балл! ;]

Что можно сделать еще?

Поздравляю, вы создали игру в стиле Mega Jump!

Под статьей вы найдете ссылку на готовый проект с полным кодом уроков.

В четырех частях мы охватили весь процесс создания игры на физическом движке. Вы многое узнали о том, как настроить обнаружения столкновений и как построить свою игровую логику для обработки столкновений.

Но вы можете сделать гораздо больше! Откройте файл конфигурации plist и подумайте о новых уровнях и возможностях, которые сможете реализовать. Просто скопируйте исходный plist и создавайте любое количество уровней, меняя конфигурацию внутри файла.

Сыграйте в Mega Jump и вдохновитесь! Сможете ли вы воплотить идеи, которые будут лучше, чем в оригинальной игре?

И последнее, но не менее важное: если вы хотите узнать больше о Sprite Kit, прочитайте книгу iOS Games by Tutorials, в которой вы узнаете, как сделать пять полных игр: от «зомби экшинов» до автомобильных гонок и перестрелок в космосе!

И, конечно, если у вас есть какие-либо вопросы или комментарии, то пожалуйста, присоединяйтесь к обсуждению.

Скачать готовый проект и код игры.

  1. 5
  2. 4
  3. 3
  4. 2
  5. 1
(1 голос, в среднем: 5)


Подписка на рассылку "Временно бесплатные в App Store"
vk.com/freeappsnow

Рассылка выходит раз в сутки и содержит список программ из App Store для iPhone перешедших в категорию бесплатные за последние 24 часа.

группа ВКонтакте

Написать комментарий.

Чтобы оставить комментарий Вы должны быть зарегистрированны на сайте.

Или Вы можете войти через: