初めに
この記事は漫画「NARUTO」に大きく依存していますので「NARUTO」知らない方はごめんなさい。
遡ること二日前、Twitterでニジゲンノモリというところで「NARUTO」のアトラクションがあるということを知りました。
以下ニジゲンノモリURL
http://nijigennomori.com/naruto_shinobizato/
行ってみたいなーと思いましたが、就活とか授業で忙しいし金もないし行けませんでした。
どうしようかなあと思った矢先、ニジゲンノモリのアトラクションの一つでAR使って千鳥とか火遁とかを出してる風な画像が撮れるというものがあることに気づきます。
あ、これ作れば行かなくても実質行ったことになるやん!(謎理論)
そう思い開発が始まりました。
千鳥とは
https://w.atwiki.jp/aniwotawiki/pages/17081.html
妥協点
- 人は殺せない
- 発動しても同じ体勢から動くことができない
- なんか千鳥が平べったい
開発スケジュール
1日目
- Mayaで千鳥っぽい3Dオブジェクトを作る。
- 断念する。
2日目 - 絵を描く。
- コードを書く。
- 術を発動する。
1日目
まずAR上に表示させる千鳥を作り始めました。
3Dモデルを表示させようとMayaで制作しました。
できたもの
僕にはMayaは使いこなせませんでした。
Mayaに詳しい友達に聞いてみたりしましたが作るのが難しいらしく(正しくは面倒くさい)、3Dオブジェクトは断念することにしました。(誰か作って!)
その結果、1日目はほぼコードは書かず3Dオブジェクトも作れず終了。
もっと早く3Dオブジェクト諦めればよかった!!!!!!!
2日目
3Dオブジェクトは断念し画像アニメーションで千鳥することにしました。
この時点でかなりニジゲンノモリのARの劣化になってしまったのですが交通費がないと思えばまあこれでもいいと自分に言い聞かせました。
ということで自分で絵を描いてみました。絵は普段描かないのでクッソ時間かかりました。友達に協力してもらったりしてできた画像が下の4つ
こいつらをアニメーションさせることに決定。
下手ですがまあ初心者なので許してください。
ということで、ここまででだいたい1日半くらい終わってしまってます。
ここまで来てやっとコードを書くことができました。
import UIKit
import SceneKit
import ARKit
class ViewController: UIViewController, ARSCNViewDelegate {
@IBOutlet var sceneView: ARSCNView!
let count = 0
var chidoriNode1: SCNNode!
var chidoriNode2: SCNNode!
var chidoriNode3: SCNNode!
var chidoriNode4: SCNNode!
var rand: Int = 1
override func viewDidLoad() {
super.viewDidLoad()
// Set the view's delegate
sceneView.delegate = self
// Show statistics such as fps and timing information
sceneView.showsStatistics = true
//千鳥をUImageとして取り込みそれぞれノードにして変数に入れる。
chidoriNode1 = (setImageToScene(image: UIImage(named:"Chidori1.png")!))
chidoriNode2 = (setImageToScene(image: UIImage(named:"Chidori2.png")!))
chidoriNode3 = (setImageToScene(image: UIImage(named:"Chidori3.png")!))
chidoriNode4 = (setImageToScene(image: UIImage(named:"Chidori4.png")!))
Timer.scheduledTimer(timeInterval: 0.05, target: self, selector: #selector(activationChidori), userInfo: nil, repeats: true)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Create a session configuration
let configuration = ARWorldTrackingConfiguration()
// Run the view's session
sceneView.session.run(configuration)
}
//画像の大きさとか設定するそしてノードにする
private func createPhotoNode(_ image: UIImage, position: SCNVector3) -> SCNNode {
let node = SCNNode()
let scale: CGFloat = 1.2
let geometry = SCNPlane(width: image.size.width * scale / image.size.height,
height: scale)
geometry.firstMaterial?.diffuse.contents = image
node.geometry = geometry
node.position = position
return node
}
//ノードを返す
private func setImageToScene(image: UIImage) -> SCNNode {
var node: SCNNode!
if let camera = sceneView.pointOfView {
// カメラから見た座標を設定。
let position = SCNVector3(x: 0, y: -0.2, z: -2.0)
let convertedPosition = camera.convertPosition(position, to: nil)
//大きさとか画像を設定してノードにする。
node = createPhotoNode(image, position: convertedPosition)
return node
}
return node
}
//0.05秒ごとに千鳥を発動する
@objc func activationChidori() {
//前回表示された千鳥を消す
sceneView.scene.rootNode.enumerateChildNodes{ (existingNode, _) in
existingNode.removeFromParentNode()
}
var newRand = Int.random(in:1...4)
if(rand == newRand) {
newRand+=1
}
rand = newRand
//ランダムに千鳥を発動する。
switch rand {
case 1:
self.sceneView.scene.rootNode.addChildNode(chidoriNode1)
case 2:
self.sceneView.scene.rootNode.addChildNode(chidoriNode2)
case 3:
self.sceneView.scene.rootNode.addChildNode(chidoriNode3)
case 4:
self.sceneView.scene.rootNode.addChildNode(chidoriNode4)
case 5:
self.sceneView.scene.rootNode.addChildNode(chidoriNode1)
default:
self.sceneView.scene.rootNode.addChildNode(chidoriNode1)
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Pause the view's session
sceneView.session.pause()
}
}
case分や画像読み込みが長ったらしくて、for文とかでまとめれそうですが、for文の中でUIImageを取得しようとするとなぜか取得結果がnilになってしまうのでシャーナシこんな形になってしまいました。
誰か原因分かる人コメントください。
要は0.05秒ごとにさっきの画像4枚をランダムに表示させてアニメーションっぽくしてます。
この方の記事がとても参考になりました。ありがとうございます。
https://qiita.com/k-boy/items/e18e74e8b341f5d5675d
結果
千鳥発動できました。
今日のKIT Developer Advent Calendar 2019では千鳥を体得してみた話を書きました。https://t.co/DEcNsP7TFB#千鳥#NARUTO #AdventCalendar2019 pic.twitter.com/Wo0mGTHzif
— 石田大智 (@Dishida07) December 15, 2019
終わりに
雷のクオリティが低いとかいう人は僕に3Dオブジェクト提供してください。.daeファイルに変換してもらえると助かります。
絵とかMayaとか触ってたらコードを書いていたのは実質2時間くらいでした。もう2度とMayaなんて触りたくないです。
まあ2日で千鳥を習得できたので「NARUTO」の世界では火影くらい余裕で慣れてしまうかもしれませんね。
補足
- 作者は厨二病ではありません。
- 20歳の大学生が一人で家で千鳥をしてても悲しくなんてありません。