2017年2月11日土曜日

SSSレース(前半戦)

2月のSSSレース(参考)に参戦することにした。
以下、日記形式で色々と書いていきます。
(あまり添削してません)

2月1日(水)

参戦初日。
AM00:00から2時間ほど全力で走りスタートダッシュを決める。
一度で良いからトップ付近に立っておきたかったので。
しかし、「そろそろ良いんじゃね?」と思いランキングを見ると130位ぐらい。
マジかー。
デレステの闇を見た。

2月2日(木)

朝起きてから走りAM11:00ぐらいに500位前後。
プロデューサーさん、平日ですよ?
ちなみに、私の勤め先(自宅から徒歩5分)は、11:00ぐらいに出勤しても「朝、早いですね」と言われたりする職場ですが、一応そこで一旦切り上げ。
当然仕事中にプレイすることはできない。私はプレイする姿を見られたくない(結構恥ずかしい)から、職場では一切プレイしない。(食事休憩時に家に帰り、食事をしながらプレイなら稀によくするが)
仕事から帰ると、ランクが1000位付近まで落ちていたので、夜中まで走って700位ぐらいに戻す。
今のところ1日平均獲得ファン数は50万人ほど。
現時点の1曲あたりの獲得ファン数はだいたい5000〜6000人なので、50万集めるのにはだいたい100曲プレイする必要があって、そんだけやっても700位ぐらいとかね。
トップは既に1千万人に到達していた。
獲得ファン数をブーストできる(※)イベント中というのもあるけど、何時間やったらそんなに獲得できるのか。
エリアの観客動員数が100万人につき獲得ファン数が約10%程度上がるらしい。金に糸目をつけなければ、Exで消費50(勿論、毎回オプション有り)とかを回しまくれば、最終日には凄いブーストが掛かる感じだろうか。1000位以内に入れれば良い程度(ライト層)の私はそこまではやらなかった。そもそも、上位には一定数チーターが居るんじゃないかと思っているので、上位を狙うモチベーションが沸かない。明らかに目立つチーターはBANされているようですが、怪しまれない程度ギリギリのライン辺りを狙うチーターが居たら、運営が対処するのは難しいと思うので、一定数は排除仕切れないだろうという想定。ただし、この「バレない範囲」を狙ったチーターというのは当然スコア効率が落ちるので、運営開始からそこそこ期間が経過した今なら、生身のゴリラの方がチーターよりも強いかもしれない。(もっとも、SSSレースを走るとなると、初期投資だけでも結構な額を課金する必要があるので、そのアカウントをBANされる恐れがあると考えるとリスクが高すぎるから、おとなしく普通にプレイするんじゃないだろうか。だから、誰でも参加できる通常イベントとかと比べれば、チーターが居る可能性が低いかもしれない。)

2月3日(金)

Sweet Witches' Night(イベント曲)のMASTERのフルコン率が9割を超えた。
現在のイベント(ライブパレード)は、SSSレースを走る前は正直微妙だと思っていたが、SSSレースを走っている人にとっては少ないコストでファン数を増加できるチャンスといえる。
通常、1曲プレイするのに必要なスタミナは19だが、ライブパレードならスタミナ10で1曲プレイでき、尚且つエリア動員数が少なくても獲得ファン数は通常と変わらない。つまり、約半分のスタミナ消費でファン数を増やせることになる。
更に、エリア動員数を貯め込めばブーストまでできる。
現時点の観客動員数で、イベント曲のMASTERフルコンでの獲得ファン数は平均6000人前後。MASTER+だと平均5000人前後。(安定してフルコンできないので)
この1000人の差は大きい。
という訳で、スコアランキングは狙わず延々とMASTERでフルコンし続けてランクを上げることにした。

2月4日(土)

昨日同様、MASTERで走り続けるのも手だが、ここで楽曲をSnow Wingsに変更。
Snow Wingsは多分、デレステ全曲の中で1番多くプレイされている曲かもしれない。
というのも、この曲は短い上にノーツの密度が高いので、単位時間当たりの獲得ファン数を引き上げるのに丁度良い。
現在のイベント期間だけ見れば、イベント曲のMASTERをやっていた方が安全に多くのファン数を稼げるが、ここでSnow Wingsのフルコンを安定化できれば後半でブーストが掛けられるという算段。
丸1日プレイしたら500コンボ前後は安定してきたが、中々フルコンできない。ただし、慣れれば安定的にフルコンが出せそうだという感触。

2月5日(日)

ケツが痛い(意味深)
私の脱力は多分完璧なので、何時間でも連続してプレイすることができるが、一番最初にガタが来たのはケツだった...
ちなみに椅子は↓の無段階調整椅子を使用。
https://www.amazon.co.jp/gp/product/B004NIZ3SY
機能面では問題無いが、座面が少々硬いのが良く無い。
1日1〜2時間程度のプレイであれば問題無いけど。
という訳でドクターエルのミニクッション(↓)なるものを、ハンズで購入。
http://www.dr-l.co.jp/item/dr-l-mini/
「ミニ」にしたのは、椅子の座面(割と狭い)にピッタリフィットするため。
正直なところ、こんなんで大丈夫のか?と思えるほどチャチな作りというのが第一印象。
良いかどうかは、数日間使ってみないと判断できないが、数時間利用してみた感じでは、ケツが痛い現象が収束したような気がしないでもない。

ケツの血流が良くなったのか?

2月6日(月)

昨日の足切りライン(1000位)の24時間での上昇値は70万人ほど。
割と異常な上がり方だ。
ライブパレード中だし休日だしまぁ仕方ない。
しかし、今日(平日)の上昇値も70万人とか...
ライブパレード中だけど平日だからそれを加味して50万ぐらいだろうという想定だったのに。
皆、ニートなのか?
なんとか、26時ぐらいまで頑張ってみたけど、順位を850位ほどと割と危険水域に居る。
明日がライブパレード最終日だけど、21時で終わってしまう。
仕事が終わるのが22時ぐらいだからキツいなぁ...

2月7日(火)

帰宅してから平常ライブを叩きまくる。
今月走ることを想定して、先月ジュエル消費を抑えつつ、何曲かCLEARランクSに近づけておいたので、それらをSランクにしつつ走っている(CLEARランクSでジュエル250個手に入る)から、この日はなんとか無課金で走り続けられた。
しかし、24時時点での順位は1021位orz
この日のボーダー上昇が、約+100万人とか狂ってる。(平日なのに)
本日がライブパレードの最終日だから明日は落ち着く筈。
初週は無課金で走り続けたけど、そろそろ実弾の補給が必要か。
ちなみに、軍資金は無制限。

2月8日(水)

とりあえず、幾つかCLEARランクSをとって本日も無課金でしのぐ。
順位は900位台中盤ぐらい。
本日のボーダーは約+20万ほどなので、想定通り収束したが、平日のライブパレードが残した爪痕はあまりにも大きすぎる。軍資金を投入する場合、SSSを取らないという選択肢が無くなるが、このままだと余りにもツライので、今回は見送ろうかと思ったほど。
ライブパーティーが始まれば、ファン数の獲得効率が落ちるので、その間にどれぐらい詰められるかで見極めたい。

2月9日(木)

そろそろ、安定的にスコア(目安: 100万+)が稼げる曲のCLEARランクSが無くなってきた。ファン数獲得効率が落ちることを許容してライブパーティーを走り、無料石やドリンクを稼いでおこうと思う。
ちなみに、ライブパーティーは餌(特技レベルを上げるための生贄となるSR, Rアイドルなど)を稼ぐ上ではかなり効率が良いが、所有しているSSR全ての特技レベルが既にMAXなので、餌は不要。
SSRは特定の条件(オバロ持ちVo特化 & 適当なフェス限Vo特化)のものがあと2枚欲しいので、それらをゲットした時用に確保するのもアリだが、アイドルだと在庫調整が困難なので、それは特訓チケットをリザーブする方向で対応している。
欲しい条件のSSRはどちらも限定モノなので引けるのは月末かフェス限定で、しかも月末orフェスで条件に合致するものがピックアップされるとは限らないから、在庫調整は長期的な視点での管理が必要。

2月10日(金)

本日もクリアランクSの布石潰しを中心に行う。
いままで中々フルコンできなかった Lv26 の難曲の内、Orange Sapphire、Snow Wings、サマカニ でフルコンを叩き出す。
これで、レベル26でフルコンできていない曲は残り、
・パステルピンクの恋
・つぼみ
・あんきら狂想曲
になった。
パスピンとあんきらは属性曲なので、SSSレースの得点源としては弱い。つぼみはノーツ数が少ない&切れやすいので、こちらも(慣れれば少しは伸びるだろうけど)弱い。
Lv27以上は属性曲が中心なので、スコア効率が悪い。
Lv27以上でフルコンできていない全タイプ曲はEVERMOREとM@GICで、それらはまだクリアSも取っていないから、暫くはこれらを中心に回すのが効率が良いと思う。
なお、Live Partyは休憩時にプレイした程度。

2月11日(土)

参加条件が厳しいSSSレースの場合、参加者の絶対数が少ないこともあって、自分のランク付近のPと顔見知りになり易い。顔見知りといってもこっちが一方的に記憶しているだけで、実際に交流がある訳ではないが。
今回のSSSレースを走り始めた当初の頃から、私の順位とほぼ同じ位置に居ることが多いとあるPと(一方的に)顔見知りになったのだが、彼(彼女?)がランクを上げると「やばい、追いつかなければ」と追いかけ、逆に私の順位が上がりすぎると「追いつくまで少し休憩するか」と休憩タイムを入れたりする。
休憩時の Live Party で偶然そのPとマッチングした時は、運命めいたものを感じてテンションが上がった。Live Party で特定の相手とマッチングする確率がどの程度かは不明だが、恐らく相当低い。(ついでに、同名のPかもしれないが、その点については腕前で本人だと判断できた)
なお、そのPとは同僚ですらない。恐らく、SSSレースが終われば、この先交流することも無いだろう(※)。しかし、そんな相手に少年ジャンプ風に表現すれば、好敵手と書いてライバルと読むような感情を抱くのは奇妙な感じである。
※「同僚申請ぐらいすれば良いんじゃないか?」と思うかもしれませんが、私はVoトリコロール編成で、そのPはViトリコロール編成だから、若干合わないんですよね。ポテンシャル20以上解放しているトリコ使いはだいたいガチ勢なので、そこら辺がジャストミートしないと申請しても受諾しない人が大半。私の場合、PaのVoトリコを持っていないこともあって、ガチ勢に申請しても結構な確率で拒否られます)

それはさておき、ついに無料石が尽きたので、実弾(課金石)を補給。
まずは1万・・・とはいっても、恐らく今回のレースでの実弾投入はこれが最初で最後のはず。というより、プレイ時間確保の都合上、8400個も消化仕切れないから、使うのは3000個ぐらいで、余ったら月末限定ガチャを回すか、次月のレースを走る場合のストックになる予定。

私の当初の見立てでは、
・前半:無料石でしのぐ(1週間ほど)
・中盤:課金石をちまちま使って順位維持(2週間ぐらい)
・後半:課金石をもりもり消費してひたすらSnow Wingsをプレイし続ける(最終週)
という感じになるスケジュールだったが、前月に作っておいたクリアランクSの布石のお陰で、課金石投入までの期間が4日ほど後ろにズレる感じになった。実弾投入をした場合、撤退という選択肢が無くなるので、ここからがある意味本番。
前月時点の推定では、ファン獲得数1,000万ほどでボーダーを余裕で超えられるというものだったが、いかんせん月初にライブパレードが配置されていたことで、その見立てが若干怪しくなった感がある。
本日(2/11)22:00ぐらい時点のランキング
(793位...割と危険水域だと思っている)

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デバイスとしてコンテキストが取れれば、そこから入力信号が取れる筈。

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

合理的ではないものを作りたい

ここ最近、実機版の東方VGSの開発が忙しくて、東方VGSの曲追加が滞っています。 東方VGS(実機版)のデザインを作りながら検討中。基本レトロUIベースですがシークバーはモダンに倣おうかな…とか pic.twitter.com/YOYprlDsYD — SUZUKI PLAN (...