メモ > 技術 > IDE: Xcode > UIKit+Game
UIKit+Game
■デフォルトのプロジェクト
「Game」で以下の設定で新規作成する
Product Name: game2d
Language: Swift
Game Technology: SpritKit
実行すると画面に「Hello, World!」と表示され、
画面をタップすると画面に反応がある
以下を参考に、引き続き調整していく
iOS GameplayKitの「Agents, Goals, and Behaviors」で作る、鬼ごっごの鬼AI
https://atmarkit.itmedia.co.jp/ait/articles/1701/30/news021.html
■不要な処理を削除してプレイヤーを表示
GameScene.sks を開き、Sceneの下にある helloLabel を削除する
GameScene.swift のコードを、以下のように最低限のものに変更する
GameScene.swift
import SpriteKit
import GameplayKit
class GameScene: SKScene {
// プレイヤー
let player = SKShapeNode(circleOfRadius: 10)
// GameSceneがviewに設置されたとき(画面が表示されたとき)に呼ばれる
override func didMove(to view: SKView) {
// プレイヤー(黄色い丸)を画面に表示
player.fillColor = UIColor(red: 0.90, green: 0.90, blue: 0.10, alpha: 1.0)
addChild(player)
}
}
■プレイヤーを動かす処理を追加
GameSceneクラスに以下のメソッドを追加する
GameScene.swift
// タッチされた位置に向かってプレイヤーを移動
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
// すべてのタッチ位置を処理
touches.forEach {
// タッチされた位置を取得
let point = $0.location(in: self)
// 移動方向を決定
let path = CGMutablePath()
path.move(to: CGPoint())
path.addLine(to: CGPoint(x: point.x - player.position.x, y: point.y - player.position.y))
// 設定済みのアニメーションを削除
player.removeAllActions()
// SKActionでSKNodeをアニメーション(移動)
player.run(SKAction.follow(path, speed: 50.0))
}
}
■敵を追加
GameScene.swift
// 敵
var enemies = [SKShapeNode]()
var timer: Timer?
var prevTime: TimeInterval = 0
// GameSceneがviewに設置されたとき(画面が表示されたとき)に呼ばれる
override func didMove(to view: SKView) {
〜略〜
// 敵を作成し続ける
setCreateEnemyTimer()
// 敵が落下しないようにする
physicsWorld.gravity = CGVector()
}
〜略〜
// 1フレームごとに呼ばれる
override func update(_ currentTime: TimeInterval) {
if prevTime == 0 {
prevTime = currentTime
}
// プレイヤーの位置が変わるので、1秒ごとに移動方向を調整
if Int(currentTime) != Int(prevTime) {
// すべての敵を処理
enemies.forEach {
// 移動方向を決定
let path = CGMutablePath()
path.move(to: CGPoint())
path.addLine(to: CGPoint(x: player.position.x - $0.position.x, y: player.position.y - $0.position.y))
// 設定済みのアニメーションを削除
$0.removeAllActions()
// SKActionでSKNodeをアニメーション(移動)
$0.run(SKAction.follow(path, speed: 50.0))
}
}
prevTime = currentTime
}
// 敵を作成し続ける
func setCreateEnemyTimer() {
timer?.invalidate()
// 5秒ごとにcreateEnemyを呼び出す
timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(GameScene.createEnemy), userInfo: nil, repeats: true)
timer?.fire()
}
// 敵を作成する
@objc func createEnemy() {
// 敵(赤い丸)を画面に表示する
let enemy = SKShapeNode(circleOfRadius: 10)
enemy.position.x = size.width / 2
enemy.fillColor = UIColor(red: 0.90, green: 0.10, blue: 0.10, alpha: 1.0)
enemy.physicsBody = SKPhysicsBody(circleOfRadius: enemy.frame.width / 2)
addChild(enemy)
// 敵を配列で管理する
enemies.append(enemy)
}
■ゲームオーバーを追加
GameScene.swift
// 終了判定
var startTime: TimeInterval = 0
var isGameFinished = false
〜略〜
// 1フレームごとに呼ばれる
override func update(_ currentTime: TimeInterval) {
if prevTime == 0 {
prevTime = currentTime
startTime = currentTime
}
〜略〜
// ゲームオーバーを判定
if !isGameFinished {
// すべての敵を処理
for enemy in enemies {
// 敵の位置を取得
let dx = enemy.position.x - player.position.x
let dy = enemy.position.y - player.position.y
// プレイヤーと敵の接触を確認
if sqrt(dx*dx + dy*dy) < player.frame.width / 2 + enemy.frame.width / 2 {
// ゲームを終了
isGameFinished = true
timer?.invalidate()
// 結果を表示
let label = SKLabelNode(text: "記録:\(Int(currentTime - startTime))秒")
label.fontSize = 80
label.position = CGPoint(x: 0, y: -100)
addChild(label)
break
}
}
}
prevTime = currentTime
}