13
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

KIT DeveloperAdvent Calendar 2019

Day 15

うちはサスケが習得するのに1ヶ月かかった千鳥を2日で習得してみた。

Last updated at Posted at 2019-12-15

初めに

この記事は漫画「NARUTO」に大きく依存していますので「NARUTO」知らない方はごめんなさい。
遡ること二日前、Twitterでニジゲンノモリというところで「NARUTO」のアトラクションがあるということを知りました。
以下ニジゲンノモリURL
http://nijigennomori.com/naruto_shinobizato/
行ってみたいなーと思いましたが、就活とか授業で忙しいし金もないし行けませんでした。
どうしようかなあと思った矢先、ニジゲンノモリのアトラクションの一つでAR使って千鳥とか火遁とかを出してる風な画像が撮れるというものがあることに気づきます。
あ、これ作れば行かなくても実質行ったことになるやん!(謎理論)
そう思い開発が始まりました。
千鳥とは
https://w.atwiki.jp/aniwotawiki/pages/17081.html

妥協点

  • 人は殺せない
  • 発動しても同じ体勢から動くことができない
  • なんか千鳥が平べったい

開発スケジュール

1日目

  1. Mayaで千鳥っぽい3Dオブジェクトを作る。
  2. 断念する。
    2日目
  3. 絵を描く。
  4. コードを書く。
  5. 術を発動する。

1日目

まずAR上に表示させる千鳥を作り始めました。
3Dモデルを表示させようとMayaで制作しました。
できたもの
IMG_5913.JPG
僕にはMayaは使いこなせませんでした。
Mayaに詳しい友達に聞いてみたりしましたが作るのが難しいらしく(正しくは面倒くさい)、3Dオブジェクトは断念することにしました。(誰か作って!)
その結果、1日目はほぼコードは書かず3Dオブジェクトも作れず終了。
もっと早く3Dオブジェクト諦めればよかった!!!!!!!

2日目

3Dオブジェクトは断念し画像アニメーションで千鳥することにしました。
この時点でかなりニジゲンノモリのARの劣化になってしまったのですが交通費がないと思えばまあこれでもいいと自分に言い聞かせました。
ということで自分で絵を描いてみました。絵は普段描かないのでクッソ時間かかりました。友達に協力してもらったりしてできた画像が下の4つ
Chidori2.png
Chidori1.png
Chidori3.png
Chidori4.png
こいつらをアニメーションさせることに決定。
下手ですがまあ初心者なので許してください。
ということで、ここまででだいたい1日半くらい終わってしまってます。
ここまで来てやっとコードを書くことができました。

viewController.swift
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

結果

千鳥発動できました。

終わりに

雷のクオリティが低いとかいう人は僕に3Dオブジェクト提供してください。.daeファイルに変換してもらえると助かります。
絵とかMayaとか触ってたらコードを書いていたのは実質2時間くらいでした。もう2度とMayaなんて触りたくないです。
まあ2日で千鳥を習得できたので「NARUTO」の世界では火影くらい余裕で慣れてしまうかもしれませんね。

補足

  • 作者は厨二病ではありません。
  • 20歳の大学生が一人で家で千鳥をしてても悲しくなんてありません。
13
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?