2017年1月29日日曜日

なんとなく音ゲーの形をしてきた

開発中のVGS Keyboardに単発ノートを実装してみたところ、何となく音ゲーの形になってきました。
とはいえ、まだ遊べるのは カエルの歌 限定ですが。
そういえば、VGSの波形メモリ音源を最初にテストした時の楽曲もカエルの歌でした。
この記事を書いていて気づいたのですが、カエルの歌よりもきらきら星の方が良かったかも。(移調はできないけどマルチノートの検証ができるので)
このカエルの歌ですが、ハ長調、ロ長調、変ロ長調、イ長調、変イ長調、ト長調、嬰ヘ長調、ヘ長調、ホ長調、変ホ長調、ニ長調、嬰ハ長調の12スケールで演奏できたりします。(なるべく全ての鍵盤を叩けるテストがしたかったので)

ノーツの判定も一応実装しています。
デレステと同じく、Perfect, Great, Good, Bad, Missの5段階判定を一応しているのですが、結果表示されるのはxcode console上のみという、ベータ臭がプンプン漂う状態です。(まぁ、今日開発開始初日だから仕方ないね)
私レベルでも、12音階全てでAP(All Perfect)できる激甘判定となっています。
というより、判定間隔が60fpsだから、ある程度甘くせざるを得ないんですよね...

あとは、ロングノーツを実装すれば基本的な入力システムはできあがります。

ロングノーツの実装は特に問題ないのですが、問題はその後に控えているVGSの楽譜データとノーツとの連携をどうするかという点。

とりあえず東方VGSで音ゲーを作ることにする

前の記事で書いたVGS-Keyboardで、とりあえず音を鳴らす仕組みを実装。
これで、単純なMIDIキーボード対応のVGSシンセサイザーみたいな感じになりました。

この音を鳴らす仕組みですが、1鍵1voiceという面白い仕様にしました。
通常のVGS音源(6voices)とは別音源としてVGSキーボード音源という24voices(!?)の新たな音源システムを定義する形で実現。(このキーボード音源の各voiceの実体はこの辺りで実装している構造体要素ですね)

これは、本物のチップチューン音源だったら割と実現が難しいです。
ピアノ等のリアル楽器は1鍵1voice方式だから、よりリアル楽器に近い自然な実装といえますが、それだとコストが掛かり過ぎるので。

しかし、こうした方が音ゲーとして扱い易そうかなと。

今考えてる音ゲーの大枠での仕組みは、VGSのNOTEオペレーションに通常の譜面データと同じ形でノーツ発生命令みたいなものを作りそれに従って操作していく感じのもので、このノーツに合わせて鍵盤を叩くことがゲームの操作としてそれとは別のスキームで発音ロジックを実装していくというものです。つまり、それなら音源システムはオリジナルVGS音源とは別枠にしておいた方が何かと都合が良いということになります...多分(この辺はカンだけを頼りに作っているので必ずしも正解ではないかもしれません)。

まずは、東方VGSの曲データをベースにして、とりあえず1曲遊べる状態のものを作ってみないと分からないですね。(理屈を捏ねる時間があったらコードを書けと)

音ゲーをオープンソースで作っていこうと思っています

既に作り始めてます。
https://github.com/suzukiplan/vgs-keyboard

もっとも、この記事を書いている時点ではMIDIキーボードの入力に合わせて鍵盤を描画するだけみたいな感じですが。
音ゲーというのは、比較的歴史が浅いこともあって、特許回避などが非常に面倒くさいジャンルとして知られています。歴史が浅いといっても、代表的な特許が出願からそろそろ20年経過して効力が切れようとしている頃合いなので、来年あたりから自由度が増してくるかもしれませんが。

ちなみに、README.mdの方で書いていますが、ゲーム本体はオープンソース&完全無料です。ついでに、コンテンツのデータ・フォーマットについてもデコーダ部分はオープンという、ほぼおっ広げ状態で開発していこうと思っています。
ゆくゆくは、楽曲データを同人ショップで売るなどしてマネタイズしようという作戦ですが、当面は(これがゲームとして面白いと確信できるまでは)無料で出すつもりです。

2017年1月28日土曜日

OSXでMIDIキーボードの入力信号を取得する方法(完結編)

前回と前々回の記事の続きです。

簡単におさらいしておくと、
・前々回:MIKMIDIを使えば実現できそうだと理解。
・前回:MIKMIDIを使ってnanoKEY2のデバイス情報が取れることを確認。
という感じで、今回はMIKMIDIを使って、nanoKEY2の入力信号をハンドリングする方法の解説です。

先に回答を書くと、以下のような感じで実装すれば、「★ココで捕捉」の箇所で入力信号を捕捉できます。

    MIKMIDIDeviceManager* dm = [MIKMIDIDeviceManager sharedDeviceManager];
    NSArray<MIKMIDIDevice*>* devices = [dm availableDevices];
    for (MIKMIDIDevice* device in devices) {
        NSArray<MIKMIDIEntity*>* entities = device.entities;
        for (MIKMIDIEntity* entity in entities) {
            NSArray<MIKMIDISourceEndpoint*>* sources = entity.sources;
            for (MIKMIDISourceEndpoint* source in sources) {
                NSLog(@"source: %@", source);
                [dm connectInput:source error:nil eventHandler:^(MIKMIDISourceEndpoint * _Nonnull source, NSArray<MIKMIDICommand *> * _Nonnull commands) {
                    // ★ココで捕捉
                    NSLog(@"detected commands: %@", commands);
                }];
            }
        }
    }

以降は、上記の実装をザックリと解説するだけなので、コードだけ見れば分かる人は読まなくても、もう自分のプログラムでMIDIキーボードを入力機器として使うことができますね。

まず、MIKMIDIDeviceManageravailableDevicesで接続されているデバイスの一覧を取得します。
デバイスの実体(MIKMIDIDeviceMIKMIDIEntity)には、
・source endpoint
・destination endpoint
という2種類の情報があり、入力信号を捕捉するにはsource endpointの方を使います。

入力信号の捕捉は、MIKMIDIDeviceManagerconnectInputで対象のsource endpointを指定してあげれば、入力信号が発生した時にeventHandlerがコールバックされるという感じです。

簡単ですね。

で、このプログラムを動作させた状態で、nanoKEY2の「ド」のキーを押してみると、押したタイミングで、XCodeのconsoleに

2017-01-28 18:41:57.014351 VGSKeyboard[36587:9378038] detected commands: (
    "<MIKMIDINoteOnCommand: 0x600000024aa0> time: 18:41:57.013 command: 159 channel 0 note: 48 velocity: 118 \n\tdata: <903076>")

という感じのMIDIイベント(MIKMIDICommand)が発生します。
そして、キーを離してみると、

VGSKeyboard[36587:9378038] detected commands: (
    "<MIKMIDINoteOffCommand: 0x608000029860> time: 18:41:57.549 command: 143 channel 0 note: 48 velocity: 64 \n\tdata: <803040>")

というMIKMIDICommandが発生しました。

つまり、キーボードのキーを押すとcommand 159が発生して、離すとcommand 143が発生するという感じでしょうか。そして、noteで対象の音階が分かるという感じです。

いやー、簡単ですね。このMIKMIDIというライブラリはCore MIDIというframeworkを使っているのですが、直にCore MIDIを叩くよりは大分楽な感じではないでしょうか。

しかも、OSXだけでなくiOSにも対応しているので、入力機器としてブルートゥースMIDIキーボードを使うiPhoneアプリなんかも作れてしまうのではないでしょうか。(今回はスマホ関連のことは未調査ですが)

OSXでMIDIキーボードからの入力信号を取得する(導入編)

前の記事で書いた MIKMIDI を使ってみる件の導入編です。
まず、XCodeで適当なプロジェクト(VGSKeyboard)を作り、CocoaPodsでMIKMIDIを取り込みます。

Podfileを以下のように作成して、

source 'https://github.com/mixedinkey-opensource/MIKMIDI.git'

target 'VGSKeyboard' do
  pod 'MIKMIDI', :git => 'https://github.com/mixedinkey-opensource/MIKMIDI.git'

end

pod update と pod install を実行すれば取り込めます。
そして、podにより生成されたワークスペース(VGSKeyboard.xcworkspace)を開き、ViewController.mでとりあえず、デバイス一覧を拾ってログに出すコードを書いてみました。

$ git diff VGSKeyboard/ViewController.m
diff --git a/VGSKeyboard/ViewController.m b/VGSKeyboard/ViewController.m
index 6ba3050..e9a5aea 100644
--- a/VGSKeyboard/ViewController.m
+++ b/VGSKeyboard/ViewController.m
@@ -7,13 +7,15 @@
 //

 #import "ViewController.h"
+#import "MIKMIDI.h"

 @implementation ViewController

 - (void)viewDidLoad {
     [super viewDidLoad];

-    // Do any additional setup after loading the view.
+    NSArray* availableMIDIDevices = [[MIKMIDIDeviceManager sharedDeviceManager] availableDevices];
+    NSLog(@"availableMIDIDevices: %@", availableMIDIDevices);

 }

そして、実行してXCodeのログを確認してみたところ、

2017-01-28 15:54:45.962064 VGSKeyboard[34236:9311302] availableMIDIDevices: (
    "<MIKMIDIDevice: 0x608000262100> Bluetooth:
        Entities: {
        }",
    "<MIKMIDIDevice: 0x600000075a40> \U30cd\U30c3\U30c8\U30ef\U30fc\U30af:
        Entities: {
        }",
    "<MIKMIDIDevice: 0x6080002628c0> nanoKEY2:
        Entities: {
            <MIKMIDIEntity: 0x600000075a80> nanoKEY2:
        Sources: {
            <MIKMIDISourceEndpoint: 0x600000051a60> nanoKEY2 KEYBOARD,
        }
        Destinations: {
            <MIKMIDIDestinationEndpoint: 0x608000047890> nanoKEY2 CTRL,
        },
        }"

)

おぉ、ちゃんとnanoKEY2のデバイス情報が取れている。

OSXでMIDIキーボードからの入力信号を取得する方法(模索中)

VGSの技術を応用した音ゲーとか作ったら面白いかもしれない。

という訳で、MacにMIDIキーボードを繋いで、そこから入力信号を拾うにはどうしたものか。

以前、ゲームパッドの入力信号を拾うため、色々と調べてみた結果、IOKitを使えば良いということが分かり、gamepad-osxというライブラリを作りました。
これは、IOKitのHID(Human Interface Device)の接続・切断・入力信号を拾う機能を使って実現しています。

MIDIキーボードも、HIDの一種と言えるので、同じ方式でいけるのでは?

と、思って色々と試してみたのですが、どうもMIDIキーボードはHIDとして認識されないらしい。ちなみに、使っているMIDIキーボードはKORGのnanoKEY2です。このMIDIキーボードは、Logicでは普通に使えているので、OSとしては認識できているようです。

MIDIキーボードはHIDとは別の手段で入力を検出するのかな?

そう思ってGitHubで何か良いものは無いものかと探してみたところ、良さそうなヤツがありました。
https://github.com/mixedinkey-opensource/MIKMIDI

上記を使えば、MIDIキーボードに限らず、MIDIデバイス全般を操作(MIDI信号の送受信)ができるらしいです。コレを使って、MIDIキーボードをMIDIデバイスとしてコンテキストが取れれば、そこから入力信号が取れる筈。

とりあえず、今回は足回りはコレで何とかなりそうだということで、試しに使ってみよう。
使ってみた結果の記事は別途書くつもりです。

Apple開発者アカウントをどうするか

Apple開発者アカウントの更新時期がそろそろ迫ってきました。
が、今回は更新しようか若干悩ましい。
今のところ、更新しない方向で考えています。

最低限、更新できる程度の売上がAppStoreから出ていれば良いのですが、ここ1年間、新作を出していないこともあって、更新費用(12000円)すら稼げていない感じです。ちなみに、過去365日での売上は37ドルと67セントで、収益は26ドルと9セント)

新作を作ろうとする意欲はまだ有るのですが、今作っているものはPC(Windows+Mac)向けで、MacであればAppStoreよりはWindowsとセットで出せるSteamとかの方が良いと思っていて、それならApple開発者アカウント(正確にはAppStoreでの配信権)を維持する必要がありません。

仮に更新しなかった場合、SUZUKI PLAN製のアプリをAppStoreから新たにインストールすることができなくなります。念のため、最近のダウンロード数をかなり久々にチェックしてみましたが、東方VGSとかはまだ1日平均100ダウンロードぐらいされているらしい。東方強い。