#Swift
#C4

C4でパリピな感じのiPhoneアプリを作ろう

はじめに

ご挨拶

こんちは!
iPhoneアプリのプログラミングやってます、いのっちです!
日々プログラミングで生活を楽しくすることだけを考えています。
そして今日もまた楽しいアプリを作ろうと思います。

概要

今日はC4という、swiftでクリエイティブコーディングできるフレームワークを使ってアプリを作っていきたいと思います。

作るもの

そもそもパリピな感じなアプリとは

定義を決めましょう。僕はパリピなアプリを、

  • カラフル
  • 騒がしい

という2点で定義しました。ここに関しては異論は認めません。
では早速作っていきましょう。

環境構築

まずは環境を作りましょう。

XcodeにC4を追加します。
XcodeはmacのApp Storeで無料でダウンロードできます。
Xcodeのダウンロードに関する説明はここでは割愛させていただきます。

C4のダウンロード

こちらからC4をインストールしましょう

image.png

ダウンロードの方法はいくつかあるようですが、一番難易度の低いジャッキーチェーンのやり方をオススメします。
なぜC4のダウンロードでこの難易度の表現をしたのかは全くもってわかりません。
C4のインストーラがダウンロードできたら .pkg を展開して案内に従ってインストールします。

C4の新規プロジェクトを作成

インストールが正常に完了したらXcodeを開きましょう。
新規プロジェクトを作成すると、こうなっているはずです。
image.png
今回は C4 Single View Application を選びます。

image.png

プロジェクト名は好きにつけてほしいんですが、"C4"というプロジェクト名はやめてください。本物のC4と名前が衝突します。
僕は"PartyC4"という名前にしました。

開発環境構築

さて、早速コードを書きたいんですが、いくつか問題があります。

  • C4はswift4に対応していない
  • Main.storyboard使わないから消したい

この2点を解決したいと思います。

ビルドするswiftのバージョンを変更する

C4という名前のわりにswift4に対応していないのは残念です。
プロジェクトの Build SettingSwift Language Version からswiftのバーションを変更します。
image.png
ありました。この Swift 4.0Swift 3.2 に変更しましょう。

Main.storyboardを消す

クリエイティブコーディングするのにMain.storyboardは不要です。
実行したいファイルを切り替えるのが大変になるだけなので、今回はMain.storyboardを消します。
image.png

Main.storyboardをDeleteします。Move to Trash して完全に葬ってくださいね。

ただ消しただけだと、実行した時にプロジェクトはMain.storyboardを探して動くのがデフォルトの設定なので、この設定を変える必要があります。

またプロジェクトの設定にいきます。
GeneralDeployment InfoMain Interface を消して空欄にしましょう。
image.png

そして AppDelegate.swift を編集します。

AppDelegate.swift
// 前略
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        /* ここから追記 */
        // MARK : 最初に表示するVCを定義
        let initialViewController = WorkSpace()

        self.window = UIWindow(frame: UIScreen.main.bounds)
        self.window?.rootViewController = initialViewController
        self.window?.makeKeyAndVisible()
        /* ここまで追記 */

        return true
    }
// 後略

これで完了です。
initialViewController に実行したいクラスを入れて実行します。

たとえば、MyCanvusController クラスにコードを書いて実行したいときは、initialViewController に入れるクラスを WorkSpaceから MyCanvusController に書き換えてあげます。簡単ですね。

なぜ上記のコードでWorkSpace()と書いたのかというと、C4のプロジェクトを作るとこのWorkSpaceというクラスでCanvusControllerが勝手に作られるからです。

ここで試しに実行(Run)してみましょう。
白い画面が表示されたら成功です!

コーディング

やっとコードが書けます。幸せです。
これから書くコードは僕が作りたかったパリピアプリのために必要なコードを、細分化して紹介しています。
C4の他のコードを学びたいからはC4のリファレンスを置いておくので、必要でしたら参照してください。

円を表示しよう

ひとまず円を表示しよう

新しいファイル、クラスを作りましょう。
New File から iOS -> Source -> Swift File を選択します。
この先で作るファイルも全てこの選択をします。
ファイル名は CircleCanvusController.swift としました。

さて、このファイルに円を表示するコードを書いていきます。

CircleCanvusController.swift
class CircleCanvusController: CanvasController {

    // 表示する円
    var circle: Circle!

    // 実行して最初に呼ばれるメソッド
    override func setup() {

        // 円の中心と半径を指定する
        circle = Circle(center: canvas.center, radius: 100)

        // canvasに追加する
        canvas.add(circle)
    }
}

そして AppDelegate.swiftinitialViewController に入れるクラスを WorkSpaceから CircleCanvusController に書き換えて、実行してみましょう。

IMG_1994.PNG

こうなれば成功です! おめでとうございます。
でも少し味気ないですねこの円。装飾しましょう。

円を装飾しよう

背景を黒くして、円の色を変更しましょう。
さきほどのファイルに書き足していきます。

CircleCanvusController.swift
    // 実行して最初に呼ばれるメソッド
    override func setup() {

        // canvasの背景色を黒に変更(RGBA)
        canvas.backgroundColor = Color(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)

        // 円の中心と半径を指定する
        circle = Circle(center: canvas.center, radius: 100)

        // 円の色を変更(HSBA)
        circle.fillColor = Color(hue: 0.33, saturation: 1.0, brightness: 1.0, alpha: 0.7)

        // 円の枠線を消す(枠線の太さを0にする)
        circle.lineWidth = 0.0

        // canvasに追加する
        canvas.add(circle)
    }

実行してみましょう!

IMG_1995.PNG

こうなれば成功です!
だんだんパリピっぽくなって、、きていません?

写真を表示しよう

ひとまず写真を表示しよう

楽しげな写真を探しましょう。
僕はこちらを採用しました。
party.jpg

僕はこの写真を party.jpg と命名してプロジェクトに追加しています。

新しく写真を表示するためのファイル、クラスを作成します。
ファイル名は ImageCanvusController.swift、クラス名は ImageCanvusControllerとしてこのクラスにコードを書いていきます。

ImageCanvusController.swift
class ImageCanvusController: CanvasController {

    // 実行して最初に呼ばれるメソッド
    override func setup() {

        // 画像を表示
        let partyImage = Image("party.jpg")!

        // 写真のheightを画面の高さにする
        partyImage.height = canvas.height

        // 写真の中央位置を画面の中央にする
        partyImage.center = canvas.center

        // canvasに写真を追加
        canvas.add(partyImage)
    }
}

書けたら実行してみましょう。
AppDelegateの書き換えも忘れずにやりましょう。

image.png

最近このエラーよく出ます。
原因は2つ考えられます。

  • 写真の名前とコードで指定している名前が違う
  • 写真のTarget Membershipのチェックが外れている

前者はよく確認してくだいさい。後者はこう直します。

party_jpg_と_「C4でパリピな感じのiPhoneアプリを作ろう」を編集_-_Qiita_と_ImageCanvasController_swift.png

ここにチェックを入れて再度Runしてみてください。

IMG_1996.PNG

出ました!
でもちょっと主張が激しいですね。調整してあげましょう。

写真を加工しよう

さきほどのクラスに追記します。

ImageCanvusController.swift
    // 実行して最初に呼ばれるメソッド
    override func setup() {

        // canvasの背景色を黒に変更(RGBA)
        canvas.backgroundColor = Color(red: 0, green: 0, blue: 0, alpha: 1)

        // 画像を表示
        let partyImage = Image("party.jpg")!

        // 写真のheightを画面の高さにする
        partyImage.height = canvas.height

        // 写真の中央位置を画面の中央にする
        partyImage.center = canvas.center

        // 写真の透明度をあげる
        partyImage.opacity = 0.7

        // canvasに写真を追加
        canvas.add(partyImage)
    }

実行してみましょう
写真がさっきより黒っぽくなっていれば成功です!

オーディオを再生しよう

さて、賑やか要素として音を追加します。

ひとまずオーディオを再生しよう

新しくオーディオを再生するファイル、クラスをAudioCanvasControllerという名前で作成します。
オーディオは好きな楽曲をプロジェクトにインポートしてください。
僕は最近エド・シーランが好きなので、Galway Girl.mp3 をインポートしました。

コードを書きます。

AudioCanvasController.swift
class AudioCanvasController: CanvasController {

    // 再生するオーディオを指定
    let audioPlayer = AudioPlayer("Galway Girl.mp3")!

    // 実行して最初に呼ばれるメソッド
    override func setup() {

        // オーディオの再生オプションの設定
        audioPlayer.loops = true

        // 再生
        audioPlayer.play()

    }
}

実行してみましょう。流れましたでしょうか!

オーディオの波形からレベルを取得しよう

曲の抑揚を数値で取得したいと思います。先程のファイルに追記します。

AudioCanvasController.swift
class AudioCanvasController: CanvasController {

    // 再生するオーディオを指定
    let audioPlayer = AudioPlayer("Galway Girl.mp3")!

    // 実行して最初に呼ばれるメソッド
    override func setup() {

        // オーディオの再生オプションの設定
        audioPlayer.loops = true

        // レベルを取得する許可
        audioPlayer.meteringEnabled = true

        // 再生
        audioPlayer.play()

        // 更新頻度の定義
        let timer = Timer(interval: 1.0 / 30.0) {
            self.update()
        }
        timer.start()
    }

    func update() {
        audioPlayer.updateMeters()

        // 左と右のオーディオレベルを取得
        let powerAverageLeft = pow(10, 0.05 * audioPlayer.averagePower(0))
        let powerAverageRight = pow(10, 0.05 * audioPlayer.averagePower(1))

        // 平均値
        let average = (powerAverageLeft + powerAverageRight) / 2

        // コンソールに出力
        print(average)
    }
}

これでコンソールに楽曲の音源のレベルが出力されるようになりました。

いままでのコードをまとめよう

さて、これまでやってきたことを全てまとめます。

新しく TotalCanvasController というファイル、クラスを作成します。

書きます。

TotalCanvasController.swift
class TotalCanvusController: CanvasController {

    // 表示する円
    var circle: Circle!

    // 再生するオーディオを指定
    let audioPlayer = AudioPlayer("Galway Girl.mp3")!

    // 円の背景色のHSBのHueの値
    var circleColorHue = 0.0

    // 実行して最初に呼ばれるメソッド
    override func setup() {
        // canvasの背景色を黒に変更(RGBA)
        canvas.backgroundColor = Color(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)

        // 画像を表示
        let partyImage = Image("party.jpg")!

        // 写真のheightを画面の高さにする
        partyImage.height = canvas.height

        // 写真の中央位置を画面の中央にする
        partyImage.center = canvas.center

        // 写真の透明度をあげる
        partyImage.opacity = 0.7

        // canvasに写真を追加
        canvas.add(partyImage)

        // 円の中心と半径を指定する
        circle = Circle(center: canvas.center, radius: 100)

        // 円の色を変更(HSBA)
        circle.fillColor = Color(hue: circleColorHue, saturation: 1.0, brightness: 1.0, alpha: 0.7)

        // 円の枠線を消す(枠線の太さを0にする)
        circle.lineWidth = 0.0

        // canvasに追加する
        canvas.add(circle)

        // オーディオの再生オプションの設定
        audioPlayer.loops = true

        // レベルを取得する許可
        audioPlayer.meteringEnabled = true

        // 再生
        audioPlayer.play()

        // 更新頻度の定義
        let timer = Timer(interval: 1.0 / 30.0) {
            self.update()
        }
        timer.start()
    }

    func update() {

        // 円の背景色のHSBのHueの値を更新
        circleColorHue += 0.01
        if circleColorHue > 1.0 {
            circleColorHue = 0.0
        }
        circle.fillColor = Color(hue: circleColorHue, saturation: 1.0, brightness: 1.0, alpha: 1.0)

        ShapeLayer.disableActions = true
        audioPlayer.updateMeters()

        // 左と右のオーディオレベルを取得
        let powerAverageLeft = pow(10, 0.05 * audioPlayer.averagePower(0))
        let powerAverageRight = pow(10, 0.05 * audioPlayer.averagePower(1))

        // 表示する円の半径 = (その平均値) * (画面の幅 / 2)
        let radius = (powerAverageLeft + powerAverageRight) / 2 * canvas.frame.width * 1/2

        // サイズを変更
        circle.frame.size = Size(radius, radius)

        // 中央位置を設定
        circle.center = canvas.center
        ShapeLayer.disableActions = false
    }
}

実行します。完成です!
アプリは音と一緒に動くため、完成アプリのキャプチャは載せないでおきます。

今回はC4というフレームワークを使って、アプリを作ってみました。
普段書いているswiftとは少しコードの書き方が違うが故、よりswiftを客観的にみることができた気がします。
ここから学ぶことは普段と少し違うことをやってみると普段のことをより知ることができるかもってことなのかもしれません。
いい収穫を得ました。

今回作ったアプリは解説が多い分シンプルになってしまいましたが、計算式をいじったりするだけでもっとアクティブになります。他にもマイクで外部の音声の波形から円のサイズを変化させたりする試作品も作ったりしたんですが、記事のボリューム的に別の記事で紹介させていただけたらと思います。

ここまで読んでくださってありがとうございます。
フィードバックいただけたらもっと嬉しい次第です。よろしくお願いします。どろん。