Привет, братья. Не скрою, меня часто терзают мысли. Что никакой я не программист, думаю линейно, предпочитаю легкое чтиво учебникам по промышленному производству софта. Все новое приводит меня либо в ужас, либо в тоску. Тем не менее, я решил поменять профессию и родину и получил по блату должность iOS-евангелист (это официально, я не шучу). Пришлось лечь под репозитории, юнит-тесты, и освоить язык Swift. Нет лучшего способа выучить новый язык, чем завести девчонку-носительницу этого языка. А где такую взять? Нет их, а если есть, то заняты молодыми и красивыми программистами, не мне чета. Другой способ обучения — написать что-то на новом языке, тем более, что идея для приложения у меня есть. Да конечно это игра, — простая, как Архимед в ванной.
В процессе творчества возникло несколько вопросов, которые нигде не засвечены, а думаю, хабрахабрахаб самое место для ответов на них.
И да, тот кто сказал, что программировать на Swift проще, чем на Objective-C, тот собака позорная.
Итак, нажимая кнопку File->New->Project…->Single View Application Вы получаете готовый проект-заготовку, главный класс приложения AppDelegate.swift выглядит пугающе просто
import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Override point for customization after application launch. } }
Что изменилось? Во-первых, вместо двух файлов (как в С), стал один, как в Pascal. Это я одобряю.
Кроме того, в тексте появились странные символы? и!.. Не пугайтесь, это признаки типа переменной, если переменная x:Float! — то точно Float, если x:Float? — то автор не уверен, что данная переменная всегда будет Float.
Честно говоря, Xcode сам подставляет в случае нужды эти знаки, и после дня потного кодирования, Вы начнете понимать логику использования идиотских символов.
Реклама
Итак, что же необходимо для игры? Конечно, реклама. Именно в этот class AppDelegate ее надо добавлять. Скачиваем последнюю версию GoogleMobileAds со Свифтом, добавляем в проект и пишем пару функций
import UIKit import GoogleMobileAds @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? var bannerView: GADBannerView! var iPhone5 = 1 func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { startAds() return true } func startAds() { bannerView = GADBannerView(adSize: kGADAdSizeBanner) print("Google Mobile Ads SDK version: " + GADRequest.sdkVersion()) bannerView.adUnitID = "ca-app-pub-here your ID-/8937549167" bannerView.rootViewController = self.window?.rootViewController let adViewHeight = bannerView.frame.size.height print("adViewHeight: \(adViewHeight)") let screenSize: CGRect = UIScreen.mainScreen().bounds let screenHeight = screenSize.height iPhone5 = screenHeight<500 ? 0 : 1 bannerView.frame.origin = CGPointMake(0, screenHeight - adViewHeight) let request = GADRequest() request.testDevices = [kGADSimulatorID ] self.window?.rootViewController!.view.addSubview(bannerView) bannerView.loadRequest(request) } func bringAdsToFront() { self.window?.rootViewController!.view.bringSubviewToFront(bannerView) } }
В теле основной функции появился вызов startAds().
В принципе, Вы научились программировать на Swift.
Функция bringAdsToFront() на самом деле мне не нужна, но Вам может пригодиться.
Переменная iPhone5 всегда необходима, как воздух, пока живы два Aspect Ratio в iOS.
Почему так? Приложение у меня, чтобы играть в метро одной рукой на телефоне, поэтому всегда рабочий режим — Портрет. Рекламу 320х50 я спускаю вниз экрана, это увеличивает заработки вдвое.
Звук
Что еще необходимо в игре, даже самой примитивной? Звуки Му.
Добавляем.
import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? var soundLib: SoundController? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Override point for customization after application launch. soundLib = SoundController.init() } func setVolume(v:Double) { soundLib?.setVolume(v*v) } func playSound(i:Int) { soundLib?.playSound(i) } }
В проект добавлем десяток mp3 файлов, вытащенных из Google, и создаем класс SoundController в отдельном файле SoundController.swift
// // здесь ссылка на приложение в аппстор, качайте не пожалеете // // https://itunes.apple.com/us/app/pow-2/id1093873891?ls=1&mt=8 // import UIKit import AVFoundation class SoundController { var players : [AVAudioPlayer] = [] var volume = 0.0 init () { var a1 = self.setupAudioPlayerWithFile("Ashley_glad_1", type:"caf") // 0 players.append(a1!) a1 = self.setupAudioPlayerWithFile("star_first", type:"caf") // 1 players.append(a1!) a1 = self.setupAudioPlayerWithFile("star_third", type:"caf") // 2 players.append(a1!) a1 = self.setupAudioPlayerWithFile("bouncer", type:"caf") // 3 players.append(a1!) a1 = self.setupAudioPlayerWithFile("bird shot-a3", type:"mp3") // 4 players.append(a1!) a1 = self.setupAudioPlayerWithFile("ball_bounce", type:"mp3") // 5 players.append(a1!) a1 = self.setupAudioPlayerWithFile("bird_a4", type:"mp3") // 6 players.append(a1!) a1 = self.setupAudioPlayerWithFile("HittingBasketBoard", type:"mp3") // 7 players.append(a1!) a1 = self.setupAudioPlayerWithFile("piglette_a1", type:"mp3") // 8 players.append(a1!) } func setVolume(v:Double) { volume = v for audioPlayer in players { audioPlayer.volume = Float(volume) } } func playSound(i:Int) { let audioPlayer = players[i] audioPlayer.play() } func setupAudioPlayerWithFile(file:NSString, type:NSString) -> AVAudioPlayer? { //1 let path = NSBundle.mainBundle().pathForResource(file as String, ofType: type as String) let url = NSURL.fileURLWithPath(path!) //2 var audioPlayer:AVAudioPlayer? // 3 do { try audioPlayer = AVAudioPlayer(contentsOfURL: url) audioPlayer!.prepareToPlay() } catch { print("Player not available") } return audioPlayer } }
Можно все сделать изящней, но на первый раз пусть будет надежно и тупо.
Теперь для проигрыша любого из десяти файлов в любом месте Вашей программы надо выполнить вызов.
let app = UIApplication.sharedApplication().delegate as! AppDelegate app.playSound(0)
Настройки
В любой игре надо сохранять настройки и текущее состояние игры. Мало ли что, телефон разрядится, и клиент не должен потерять блестяще найденное решение при решении очередной головоломки.
Для этого в том же классе AppDelegate добавляем две функции
func loadPrefs() { let pre = NSLocale.preferredLanguages()[0] if pre == "ru" { flag = 7 } print("language = \(pre) flag=\(flag)") let defaults = NSUserDefaults.standardUserDefaults() for i in 0...20 { let s = defaults.integerForKey("s_\(i)") status[i] = s%500 a_best[i] = s/500 } } func savePrefs() { let defaults = NSUserDefaults.standardUserDefaults() for i in 0...20 { let s = status[i] + 500 * a_best[i] defaults.setInteger(s, forKey: "s_\(i)") } defaults.synchronize() }
Нетрудно заметить, что поскольку я парень советский, то единственная локализация, которую я признаю и умею делать — русская. В теле функции loadPrefs() я определяю отечественный ли iPhone у уважаемого игрока, если да, то пишу ему гнусные шутки внутри приложения на нашем родном языке.
Так игра называется Pow 2, а в родном варианте почему-то Хрясь
Управляемый Счетчик Случайных Чисел
Нужен почти всегда. Причем я использую выдранный из MSVC 20 лет назад С-шный код, который адаптировал на все языки от JS до PHP, и он выдает одинаковые последовательности случайных чисел начиная с любого holdrand от 0 до конечности Int32
var holdrand = 0 func microsoft_rnd()->Int { var k = Int.multiplyWithOverflow(holdrand, 214013) k = Int.addWithOverflow(k.0, 2531011) holdrand = k.0 return Int((holdrand >> 16) & 0x7FFF) } func microsoft_rand(number:Int)->Int { return microsoft_rnd() % number }
Как видно, по сравнению с Obj-C пришлось изрядно повозиться — Swift не любит переполнения и строго за них наказывает.
Вызов функции в коде выглядит примерно так
for _ in 0..<2016 { let k = microsoft_rand(25) // Int(arc4random()%25) let j = microsoft_rand(25) //Int(arc4random()%25) if dots[k] > 0 && dots[j] > 0 { let d = dots[k] dots[k] = dots[j] dots[j] = d } }
Все остальное
Все остальное в моей игре стандартно и взято из документации по Swift.
Саму идею приложения и как она родилась расписывать не стану, модераторы меня беспощадно посылают в черновик.
Так что играйте, если нужна ссылка, в комментариях отвечу.
Самое удивительное, что статью я и не собирался публиковать. Просто сегодня произошло чудо. Я выложил игру после обеда в магазин на проверку и приготовился к долгому двухнедельному ожиданию. И вдруг, хлоп, вечером уже она одобрена. 6 часов на все! Даже андроидные ребята такого не видали.
Я тут же объявил ее бесплатной, накатал сей опус, и пожелал спокойной ночи братьям во свифте.
ссылка на оригинал статьи https://habrahabr.ru/post/280184/
Добавить комментарий