introduction of swift from game development
TRANSCRIPT
ゲーム開発で学ぶSwift入門
株式会社BizReach プロダクトマーケティング本部 山下大輔
自己紹介・山下大輔(やました だいすけ) ・2015年1月よりビズリーチのiOSエンジニア ・@daisuke0131 ・http://www.facebook.com/daisuke0131 ・https://github.com/daisuke0131
https://itunes.apple.com/jp/app/haikurasu-ren-cainokyaria/id972002786?mt=8
おしながき
・SpriteKitについて・・・30min ・ハンズオン・・・60min
SpriteKit
・iOS7からサポートされた2Dゲーム用標準framework ->外部のライブラリを入れる必要がない、すぐに使える。
・普通のview(UIView)と組み合わせて使える ->普通のアプリを作っている時にも、目を引くエフェクトなどのちょっとしたところに も使えるかも
SpriteKit・以下の4つの構成要素からなるノード(SKNode)・・・表示される個々のパーツ アクション(SKAction)・・動きを表すもの シーン(SKScene)・・・ゲームの画面(ノードのサブクラス) ビュー(SKView)・・・アプリ上でSpriteKitを表示するView(UIViewのサブクラス)
シーン
ノード
ノードA
ノードB
ノードの階層関係
シーンをビューに 紐付けることで描画
SpriteKit
・座標系
x
y x
y
(x,y)
(x,y)
SpriteKit 普通のアプリ(UIKit)
・位置の指定方法
(0,0)
(0,0)
SKNode
・ゲーム要素を作るSKNodeのサブクラス ->何かしらを表示する時に元の素材毎に使うクラスを選ぶイメージ。
SKSpriteNode・・・画像を描画。一番便利なやつ SKEmitterNode・・・パーティクルを表示。面白いやつ。 SKShapeNode・・・図形を描画。
SKVideoNode・・・動画を描画 SKLabelNode・・・文字を描画 SKCropNode・・・子ノードにマスクを適用して切り出す SKEffectNode・・・子ノードにCore Imageフィルタを適用
SKAction
・SKNodeの動きを作るやつ ->ノードの移動、回転、拡大縮小などの変化を作ることができる
・使い方は、作ったActionをnodeの持つrunAction メソッドに渡すだけ
・連続的なActionも渡せるよ!
let action = SKAction.moveByX(…) node.runAction(action)
let action1 = SKAction.moveByX(…) let action2 = SKAction.moveByX(…) let sequenceAction = SKAction.sequence([action1,action2]) node.runAction(sequenceAction)
SKScene
・ゲーム画面。 ->スタート画面、ゲーム画面、終了画面の単位でSKSceneを作るイメージ
SKView
・SpriteKitを表示するView。 ->UIViewのサブクラスであることがポイント。普通のアプリの中で普通にView として扱える。
ハンズオン
クソゲーハンズオン
ぶどう汁ブシャーッ
要件・ボール、バー、グレープの要素からなる ・グレープは5回ぶつかると「ブシャーッ」 ・グレープ全部「ブシャーッ」するとクリア ・ボールが下に落ちちゃうとゲームオーバー ・ボールは等速運動をする ・ボールはバー、グレープ、画面の端とは完全弾性衝突
物理エンジンの使い方
・SKNodeに定義されているphysicsBodyを設定する ->衝突、重力加速度などの物理効果が有効化
衝突の検出
・検出したいノード同士のphysicsBodyの contactTestBitMaskに0以外の値をセットする。 ->didBeginContactが呼ばれるようになる
※contactTestBitMaskとcategoryBitMaskの論理積が0以外の 値になると衝突判定
完全弾性衝突ってなんぞや??
・運動エネルギーが保存される衝突
v
v
衝突前 衝突後
・physicsBodyのrestitutionに1.0を設定すればいいnode.physicsBody?.restitution = 1.0
例えば
Step1 プロジェクトの作り方
https://github.com/daisuke0131/GrapePinBall/blob/master/resources/resources.zip?raw=true
Step2 リソースの登録
https://github.com/daisuke0131/GrapePinBall/blob/master/resources/resources.zip?raw=true
drag&drop
Step2 リソースの登録
https://github.com/daisuke0131/GrapePinBall/blob/master/resources/resources.zip?raw=true
Step3 GemaSceneの登録
let scene = GameScene() let view = self.view as! SKView view.showsFPS = true view.showsNodeCount = true scene.size = view.frame.size view.presentScene(scene)
・GameViewControllerのviewDidLoadに
Step4 ノードの表示と物理効果
let ball = SKSpriteNode(imageNamed: “ball”)
ball.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed:"ball"), size: ball.size)
ball.position = CGPoint(x:100 ,y:100)
self.addChild(ball)
・GameSceneのdidMoveToViewに
ボール、バー、ボードを表示するように設定していきます。
Step5 Swiftのちょっとした文法
class Grape:SKSpriteNode { var hitCount:Int = 0 }
・クラスの継承
・データ構造
let grapesPosition:[(x:CGFloat,y:CGFloat)] = [(60.0,500.0),(160.0,500.0),(260.0,500.0),(110.0,400.0),(220.0,400.0)]
配列、タプル
・繰り返し //グレープの配置 for pos in grapesPosition{ makeGrape(pos) }
Step6 physicsBodyのプロパティ設定
restitution・・・反発係数(ぶつかった時の跳ね返り率) linearDamping・・・移動時の減衰率(空気抵抗的なやつ) friction・・・摩擦係数
affectedByGravity・・・重力の影響を受けるかどうか dynamic・・・動くようにするかどうか。(falseだと衝突も無視)
applyImpulse()・・・衝撃を与えることができる。
Step7 タッチ系イベントハンドリング
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) { if let touch: AnyObject = touches.first { let location = touch.locationInNode(self) let action = SKAction.moveTo(CGPoint(x: location.x, y: 100), duration: 0.2) self.board.runAction(action) } } override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) { if let touch: AnyObject = touches.first { if !isStarted{ startBall() isStarted = true } } }
Step8 衝突判定
self.physicsWorld.contactDelegate = self
extension GameScene:SKPhysicsContactDelegate{ func didBeginContact(contact: SKPhysicsContact) { } }
delegateの設定
以下のメソッドを追加することで衝突時に呼ばれる
※contactTestBitMaskとcategoryBitMaskの論理積が0以外の 値になると衝突判定
Step9 パーティクル
Step9 パーティクル
let particle = SKEmitterNode(fileNamed: "MyParticle.sks") self.addChild(particle) let removeAction = SKAction.removeFromParent() let durationAction = SKAction.waitForDuration(1) let sequenceAction = SKAction.sequence([durationAction,removeAction]) particle.runAction(sequenceAction) particle.position = CGPoint(x: g.position.x, y: g.position.y) particle.alpha = 1
おしまい