Привет! В этой главе мы начнем использовать технологию git, поговорим про расширения и сделаем первые шаги по созданию нашего поля боевых действий.
Итак, начнем с git:
Технология нужна для контролирования различных версий проекта. Например, если у вас все работало, а затем вы внесли ошибочное изменение, git позволит откатиться на предыдущие версии проекта. Другой пример использования: вы хотите добавить в команду человека, но вы не хотите интегрировать его работу в проект, пока не убедитесь, что все сделано правильно - тоже пожалуйста, git все это умеет.
Так как все это подключить к нашему проекту?
Для этого открываем Terminal, он находится в Приложениях и переходим в директорию с нашим проектом, в моем случае
cd Desktop/Grasp
Затем нам необходимо инициализировать репозиторий:
git init
Добавляем в него все существующие файлы
git add .
(Точка через пробел, это важно!)
Сохраняем все это с комментарием
git commit -m “Initialization”
Проверьте себя:
Если хотите более подробно узнать про git и ее возможности, прочитайте эту статью: goo.gl/67SgBu
Итак, теперь мы можем управлять проектами прямо из Xcode во вкладке Source Control
Перейдем же к самому проекту. Для начала добавим изменений в наш файл Useful.swift
extension CGF {
static func - (l: CGF, r: Double) -> CGF { return l - CGF(r) }
static func + (l: CGF, r: Double) -> CGF { return l + CGF(r) }
static func * (l: CGF, r: Double) -> CGF { return l * CGF(r) }
static func / (l: CGF, r: Double) -> CGF { return l / CGF(r) }
static func - (l: CGF, r: Int) -> CGF { return l - CGF(r) }
static func + (l: CGF, r: Int) -> CGF { return l + CGF(r) }
static func * (l: CGF, r: Int) -> CGF { return l * CGF(r) }
static func / (l: CGF, r: Int) -> CGF { return l / CGF(r) }
}
extension Int {
static func - (l: Int, r: CGF) -> CGF { return CGF(l) - r }
static func + (l: Int, r: CGF) -> CGF { return CGF(l) + r }
static func * (l: Int, r: CGF) -> CGF { return CGF(l) * r }
static func / (l: Int, r: CGF) -> CGF { return CGF(l) / r }
}
extension Double {
static func - (l: Double, r: CGF) -> CGF { return CGF(l) - r }
static func + (l: Double, r: CGF) -> CGF { return CGF(l) + r }
static func * (l: Double, r: CGF) -> CGF { return CGF(l) * r }
static func / (l: Double, r: CGF) -> CGF { return CGF(l) / r }
}
Эти расширения позволяют сильно уменьшить количество кода, повышая его читабельность, например:
var d : Double = 10.0
var c : CGFloat = 7.0
var i : Int = 11
// Без расширений:
var tmp : CGFloat = (CGF(d) + CGF(i)) * CGF(i) + CGF(d)
// С расширениями:
var tmp: CGFloat = (d + i) * i + d
Как видите, разница существенная.
Теперь добавим файл Constants.swift рядом с файлом Useful.swift, в него мы будем записывать константы в течение всего проекта, на данный момент нам необходимы вот эти:
let MENU_HEIGHT = CGF(70.0)
А также переменная размера экрана, инициализируемая при запуске приложения:
var screen : CGSize = CGSize()
Чтобы она проинициализировалась сразу при запуске, в файле AppDelegate.swift в первой функции необходимо прописать следующу строчку:
screen = UIScreen.main.bounds.size
Итак, наше поле боевых действий состоит из узлов, в которых располагаются города, ресурсы и многое другое, а также соединительных линий между этими узлами, по которым ведется торговля о столицей и передвигаются юниты. Поле в первой версии будет фиксированного размера 5 х 9 узлов, но чтобы поле выглядело одинаково хорошо на всех поддерживаемых устройствах, напишем класс, который будет создавать разметку для нашего поля.
Сейчас немного порядка и иерархии:
В папке Scenes создаем файл FieldScene.swift
На том же уровне, что и папка Design, создаем папку Structure, в ней папку Field, а в ней файл Marking.swift, в котором и создаем класс разметки:
import Foundation
import UIKit
import SpriteKit
// Эти три строчки отныне пишем в каждом .swift файле
class Marking {
var frame: (CGF, CGF) = (0, 0) // left, down
var side: CGF = CGF()
init() {}
init(size: CGSize, ratio: (Int, Int)) {
// предподсчитываем стороны узлов, если бы не было адаптивной разметки
let tmp_x = (size.width - MIN_SPACE * 2) / ratio.0
let tmp_y = (size.height - MIN_SPACE * 2 - MENU_HEIGHT - STATUS_BAR_HEIGHT) / ratio.1
// выбираем меньшую из них, так как стороны узла соотносятся, как 1:1 и они все должны поместиться на экране
self.side = min(tmp_x, tmp_y)
self.frame = (
(size.width - self.side * ratio.0) / 2,
MENU_HEIGHT + ((size.height - STATUS_BAR_HEIGHT - MENU_HEIGHT - self.side * ratio.1) / 2)
)
}
}
Что ж, давайте теперь взглянем на то, что получилось - создадим макет нашего поля:
В файле FieldScene.swift пишем следующее:
class FieldScene: SKScene {
final var ratio : (Int, Int) = (5, 9)
var mark : Marking = Marking()
override init(size: CGSize) {
super.init(size: size)
self.mark = Marking(size: size, ratio: self.ratio)
self.backgroundColor = UIC.white
// макет статус бара
let sb = SKSN(color: UIC.blue, size: CGSize(width: screen.width, height: STATUS_BAR_HEIGHT))
sb.anchorPoint = CGPoint(x: 0, y: 0)
sb.position = CGPoint(x: 0, y: screen.height - STATUS_BAR_HEIGHT)
self.addChild(sb)
// макет самой сетки узлов
for var i in 0..<ratio.1 {
for var j in 0..<ratio.0 {
let sn = SKSN(
color: UIC.red,
size: CGSize(width: self.mark.side - 5, height: self.mark.side - 5))
sn.position.x = mark.frame.0 + j * mark.side + 2.5
sn.position.y = mark.frame.1 + i * mark.side + 2.5
sn.anchorPoint = CGPoint(x: 0, y: 0)
self.addChild(sn)
}
}
// макет меню
let menu = SKSN(color: UIC.darkGray, size: CGSize(width: screen.width, height: MENU_HEIGHT))
menu.position = CGPoint(x: 0, y: 0)
menu.anchorPoint = CGPoint(x: 0, y: 0)
self.addChild(menu)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
А теперь, чтобы посмотреть на результат, нужно запустить эту сцену с помощью ViewController’a, как вы уже догадались открываем файл GameViewController.swift и пишем там вот такое заклинание:
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
let scene = FieldScene(size: UIScreen.main.bounds.size)
view.presentScene(scene)
}
}
}
Нажимаем кнопку запустить и наблюдаем, как правильно все разметилось. Кстати, удобнее всего использовать для тестов в симуляторе компактные модели, например, se/6/6s и другие - они не занимают много места на экране
Теперь сделаем commit, все что для этого нужно -> Source Control -> Commit, пишем комментарий, например, Blog -1, Разметка
Продолжение в следующем посте! Следующая часть
Другие статьи
Цикл статей о первом опыте самостоятельной разработки игры для iOS учеником Московской школы программистов. Начало.
"После множественных попыток и экспериментов я все-таки решил написать свою iOS-игру. В этом блоге будет рассказана поэтапная история ее создания. Скажу сразу, до этого момента я пробовал разные проекты, набивал шишки, но приложения, прошедшего путь от самого начала и до логического завершения, ещё не делал. Так что в последующих постах я расскажу вам именно первый опыт разработки полноценного продукта."
Наш юный падаван придумал, как написать iOS-приложение за 30 минут всего одной строчкой заклинания!
Итак, необходимо выполнить всего четыре простых шага:
1. Скачайте бесплатное приложение Xcode для работы с кодом.
2. Создайте новый проект в Xcode (выбрать «платформа iOS», тип приложения «Single View Application»)...