Casual-заготовки під Swift

image

Привіт, брати у swift-e. Довелося і мені освоїти цей пташиний мову, і немає кращого способу для навчання, ніж закінчений продукт під потріпаний iPhone. Мене давно кусала зсередини складна математична головоломка, а тут раз! І раптом на свифте. Код місцями виглядає смішно, зате зрозуміло. Сам алгоритм гри я обговорювати не буду, він занадто складний для місцевих модераторів, не вміє подумки розділити 111 на 3. А ось приклади корисних функцій для розробників casual game — будь ласка.

Випадковість

Насамперед у будь-якій грі потрібен власний генератор випадкових послідовностей цілих чисел. Для генерації повторюваних розкладів і для багато чого.
Якщо код функції генератора на Джава, JS і З виглядає однаково (адже Ваша гра на всіх мовах буде написана?), на Swift методом тику довелося сильно переробити код. Замість 2 рядків він став займати 4.

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
}


А ось як виглядав З-ий варіант миксофотовского датчика, видерти мною з MSVC 15 років тому.
- (int)microsoft_rnd {
holdrand = holdrand * 214013 + 2531011;
return ((holdrand >> 16) & 0x7FFF);
}

- (int) microsoft_rand:(int) number{
return [self microsoft_rnd] % number;
}


Як бачимо Swift дуже суворий до переполнениям і додає головні болі розробнику, але, мабуть, знімає стрес з runtime-юзера. При цьому Obj-C чудово працював без всяких стресів і головних болів.

Так ось. Визначаючи змінну holdrand, скажімо holdrand=25, ми свідомо повторимо розклад для умовного рівня 25 у всіх варіантах головоломки — будь вона написана на PHP для гри на сервері, або на Swift для гри на iPhone. Це дає відчуття братерства для гравців — вони як би все оффлайн, але в той же час заочно змагаються на тих же обставин. Схоже на турнір по грі в Бридж. Давно я не грав у бридж, до речі.

Перейдемо до практики. Давайте створимо найпростіший проект на Swift використовуючи Xcode. Натискаємо кнопки 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.
}
} 


Що змінилося з часів Obj-C? По-перше, замість двох файлів став один. Це я схвалюю.
Крім того, в тексті з'явилися дивні символи "?" і "!". Не лякайтеся, це ознаки типу змінної, якщо змінна x:Float! — то точно Float, якщо x:Float? автор не впевнений, що дана змінна завжди буде Float.

Чесно кажучи, Xcode сам підставляє у разі потреби ці знаки, і після 4 годин кодування, Ви почнете розуміти логіку використання ідіотських символів.

Реклама

Отже, що ж необхідно для гри розробнику у другу чергу, але не останню? Звичайно, реклама. Саме в цей class AppDelegate її треба додавати. Викачуємо останню версію GoogleMobileAds зі Свіфтом, додаємо в проект і пишемо пару функцій

import UIKit
import GoogleMobileAds

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var bannerView: GADBannerView!
var iPhone5 = true

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 = yourAdMobID
bannerView.rootViewController = self.window?.rootViewController
let adViewHeight = bannerView.frame.size.height
print("adViewHeight: \(adViewHeight)")
let screenSize: CGRect = UIScreen.mainScreen().bounds
let screenHeight = screenSize.height
bannerView.frame.origin = CGPointMake(0, screenHeight - adViewHeight)
let request = GADRequest()
request.testDevices = [kGADSimulatorID ]
self.window?.rootViewController!.view.addSubview(bannerView)
bannerView.loadRequest(request)
// Заодно і прапор встановимо, щоб 2 рази не ходити
iPhone5 = screenHeight<heightOfScreenOfiPhone5AndMoreInlogicalpixels ? false : true
}

func bringAdsToFront() {
self.window?.rootViewController!.view.bringSubviewToFront(bannerView)
}
} 


У тілі основної функції з'явився виклик startAds().
Функція bringAdsToFront() насправді мені не потрібна, але Вам може стати в нагоді, якщо Ви використовуєте нестандартні ViewControllers, які будуть перекривати рекламне вікно при своїй появі. У цьому випадку банер треба витягувати поверх всіх Views викликом даної процедури.

Змінна iPhone5 жахливо необхідна, як повітря, поки живі два Aspect Ratio в iOS. Нагадую, що 5% відсотків населення все ще користується iPhone 4, пропорції якого відрізняються від сучасних моделей. Крім того, якщо Ваш додаток iPhone only, то при запуску його на iPad Ви отримуєте старий добрий режим 320 на 480 пікселів.

Чому так розміщую банер? Додаток у мене, щоб грати в метро однією рукою на телефоні, тому для нього назавжди визначений робочий режим — Портрет. А рекламу 320х50 я спускаю вниз екрану, що збільшує заробітки вдвічі. На момент публікації статті я вже заробив 40 центів США.

В принципі, тепер Ви навчилися програмувати на Swift.

Звук

Що ще необхідно в грі, навіть самої примітивної? Звуки Му.

Додаємо дві функції і один клас.


import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var soundLib: SoundController?

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
soundLib = SoundController.init()
}

func setVolume(v:Double) {
soundLib?.setVolume(v*v)
}

func playSound(i:Int) {
soundLib?.playSound(i)
}
} 


Крім того, в проект добавлем десяток mp3 і caf файлів, витягнутих з Google, і створюємо клас SoundController в окремому файлі
SoundController.swift
// Created by Vadim Bashurov on 3/19/16.
//

import UIKit
import AVFoundation

class SoundController {
let audioFiles: [String): String] = [
"Ashley_glad_1": "caf",
"star_first": "caf",
"star_third": "caf",
"bouncer":"caf",
"bird shot-a3":"mp3",
"ball_bounce":"mp3",
"bird_a4":"mp3",
"HittingBasketBoard":"mp3",
"piglette_a1":"mp3",
]

var players : [AVAudioPlayer] = []
var volume = 0.0

init () {
for (name, ext) in audioFiles {
нехай a1 = self.setupAudioPlayerWithFile(name, type:ext)
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? {
let path = NSBundle.mainBundle().pathForResource(file as String, ofType: type as String)
let url = NSURL.fileURLWithPath(path!)
var audioPlayer:AVAudioPlayer?
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: url)
audioPlayer!.prepareToPlay()

} catch {
print("Player not available")
}
return audioPlayer
}
}



Зрозуміло, я перебрав всі 4 варіанти відтворення звуку під iOS. Системні звуки не підходять для розробки гри, оскільки програмно не контролюють рівень відтворення. AudioService з OAL бібліотеки на Swift не мною не переписані, не вистачає знань і часу. AudioQuery гальмує. Надалі я кину bridge від своєї Obj-C бібліотеки, оскільки незважаючи на функцію preload, AVAudioPlayer лагает при старті програми.

І на солодке, стрибунці!

Стрибунці



Всі ваші кнопки, написи і малюнки мають з'являтися на екрані, подібно реальним предметам з казкового світу. Або спливати, або прилітати, виходити з тіні і під-дрыгивать. Починаючи з iOS 8 Apple запропонував ліву функцію для bouncing анімації.

Ось приклад
UIView.animateWithDuration(1.2, delay: 0.1, usingSpringWithDamping: 0.3, initialSpringVelocity: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: {

box1.center = CGPointMake(box2.center.x,box2.center.y)

},
completion: {finished in
self.showFingers()
})




В результаті роботи функції ящик 1 впаде на скриньку 2 (це сюжет моєї головоломки) не просто тупо, а з веселими підскоками, після яких мирно спочине.
Фізику підскоку можна варіювати 3 параметрами — часом усього процесу — у мене в тексті це 1.2 секунди, другий параметр — це затримка перед початком падіння (delay: 0.1) на bouncing ніяк не впливає.
А ось 3 і 4 параметри мають значення від 0 до 1 і визначають якість стрибка. Якщо встановити їх в 1, то відскоку не буде. Якщо в нуль, ящик буде скакати як воша на гілці.

Поэкспериментруйте самі, це заняття вкрай веселе.

Тепер Ви готові, щоб написати простеньку игрульку на Swift і заробити пару доларів на пиво.
Прат!

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

0 коментарів

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