Хрясь і навпіл

image

Привіт, брати. Не приховую, мене часто мучать думки. Що ніякий я не програміст, думаю лінійно, волію легке чтиво підручниками по промисловому виробництву софту. Все нове приводить мене або в жах, або в тугу. Тим не менше, я вирішив змінити професію і батьківщину і отримав по блату посаду 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 launch application.
}
} 


Що змінилося? По-перше, замість двох файлів (в З), став один, як в 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 launch application.

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 players in {
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().представник 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 годин на все! Навіть андроидные хлопці такого не бачили.

Я тут же оголосив її безкоштовною, накатав цей опус, і побажав спокійної ночі братам у свифте.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.