2016年12月29日木曜日

いけそう

デレステでPRP1,000獲得の為、昨日フェスでガチャを100連ほど回し、無事フェス限定SSRを3枚ほどゲットした(参照)ので、これで1,000に届く確認するため、試しに流れ星キセキ(Lv26)でフルコンしてみたのですが、
強い。
※Greatが多いのは気合の問題です

従来編成では全てを完全にALL OUTし尽くして94万でしたが、まだ全然(特技Lvが)育っていない状態 & Great多めのやる気が無いプレイで、アッサリと+4万点も超えてしまった。

こ れ が 金 の 力 か !

これなら、PRP1,000狙いは特技Lvを育て切れば余裕だろうと思います。

なお、この時の編成は、
①渋谷/オーバー・マイセルフ(Co/Vo), 特技Lv6, ポテ解放=16
②ウサミン・ザ・シークレット(Cu/Vo), 特技Lv5, ポテ解放=3
③杏/ぐうたら王国(Cu/Vi)特技Lv10, ポテ解放=20
④みく/キャットパーティー(Cu/Da),特技Lv9, ポテ解放=9
⑤なつきち/Jet to the Future(Pa/Da), 特技Lv10, ポテ解放=11

というアピール値的にはかなり微妙なもの。
ゲストにトリコロールボイスを持ってきてギリギリ30万点に届かないぐらい。

編成を特技で並べてみると、
①コンボボーナス / 18%up / 7秒ごと / 高確率 / わずかな間
②コンボボーナス / 18%up / 6秒ごと / 中確率 / わずかな間
③スコアアップ / 17%up / 13秒ごと / 高確率 / かなりの間
④スコアアップ / 17%up / 9秒ごと / 高確率 / 少しの間
⑤オーバーロード / 16%up / 9秒ごと / 中確率 / しばらくの間

⑤(オバロ)はテストランのつもりだったからチキン配置です。
Lv10のコンボボーナス持ちのSR/Pa(何体か持っている)を突っ込んでいれば、現時点の編成で100万点に届いたかも。

それでも、SSSを狙って走る時の時短のために、SSRの特技Lv10化はしますが。
ただし、餌が無いのでキャラバンやライブパーティー待ちです。
それまでの間にPaの枠を何とかしておきたい。

Voが強いPaで、尚且つコンボボーナス持ちであれば最強ですが、そうなると月末復活かフェス限定狙い(よく調べてませんが、多分グロリアス★グロウ1点狙いかな?死ねる)で期待値が薄いので、そこは妥協してスコアアップでも良いかなと。(オバロでも100万に乗りそうだったので無理する必要もない)

そうなると候補は、
・仁奈(ともだちたくさん)
・高森(てづくりのしあわせ)
・及川(はつらつハーヴェスト)
・相葉(束ねた気持ち)
辺りになりますが、これらをタイプセレクトで狙うにしても確率的にキツイのでスカチケを待つのが賢明かな。(ただし、年明けの宝くじは期待値ほぼ0だと思っている)

パッションが足りない

夏頃プレイを始めたデレステですが、昨日SSランクに昇格。
ここまで来たらSSSランクを1回は取っておきたいところですが、今の手札(恒常SSRの杏、みく、渋凛)では参加条件のPRP1,000を満たすのが難しい。

このSSRだと、全タイプのLv27〜28をフルコンして運が良ければ100万点に届くので、それをx10曲やれば届きそうですが、条件に合う曲が3曲(m@gic, evermore, goin'!!!)しか無いので、難しいというか無理ですね。

そんなタイミングで、狙いすましたかのようにシンデレラフェスが始まる。
フェス限定を1体でも入れれば、多分Lv26でも届きそうなので、課金して石を仕入れてガチャを回すことにした。

まず、20連でウサミンを引く。

えぇ...

いや、ウサミンは悪くないです。
問題はステータス(Vo)。
手持ちのCu系SSRは、杏(Vi)、みく(Da)で見事に割れてしまっている...
Viだったら、その時点で辞めれたのに。

という訳で、更に回してみたところ、60連目で周子を引く。

えぇ...

いや、周子は悪くないです。
問題はステータス(Da)。
手持ちは全般的にDa系の強いアイドルが居ないので、ステータス強化目的という意味ではハズレです。(強いアイドルとは...)

恐らく、もう1枚(Pa)が壁かー、などと考えつつ、更に回してみたところ70連目で初のSSR確定封筒が出る。
「100連未満で今回追加のフェス限定アイドルが全部出てくれれば悪くはない」
などと考えていたのですが、出たのは渋凛でした。(興奮してスクショは撮り忘れた)

これは大当たりです。
今回引いたウサミンと組ませて、特技LvをMaxまで育てれば、Lv26のフルコンとかで簡単に(100万点に)届きそう。

あとは、PaのSSRが1枚引ければ最強ではないかね?という悪魔の囁きに耳を貸し、トータル110連(約3万円)回しましたが、結局出ませんでした。
最初っから100連回すつもりで石を購入済みだったので問題ありません。
(10連余分に回しているのは無料石を使ったのでノーカン)

確率的にはキレイにだいたい3%。
提供割合の表示通りですね。
実際のところ100連回して3枚引けるのは60%ぐらいとかなので、まぁ良い方ではないでしょうか。

今回のガチャでSSRがトータル6枚になりましたが、CuとCoしか居ない偏った状態です。これって案外こういう風になるようにコントロールされているのではないかと勘ぐってしまう。(キレイにバラけるよりも、ある程度偏らせた方が運営サイドの収益性が良くなる筈なので)
※鍵を付けているのがSSR
そして、謎の渋谷率。
仕方がないので渋谷担当を名乗っておくことにしました。
なので、Trancing Pulseはフルコンしておこう(もうちょっとで出来そう)

ちなみに、累計の課金額は6万円ほど。
旧来のコンシューマゲームだと1本のゲームに6万とかあり得ないですが、デレステをプレイし始めてだいたい100日ちょっとで、コンシューマゲームだと1本のゲームで100日以上遊べるものはそうそう無いから、妥当な額かなと。

2016年12月18日日曜日

ゲーム機エミュレータの技術的な話

割と古めのエミュレータのソースコードを眺めてみて、プラットフォーム依存(主にWindows依存)の実装がモリモリと入っているものが多いなと。

エミュレータのコア部分は、必ずしもプラットフォームに依存する必要はなくて、Cの標準ライブラリやC++のSTLだけで実装できるものです。

何処までがプラットフォーム非依存(PIL)で、何処からがプラットフォーム依存(PDL)か。
その線引は、以下のようになります。

【プラットフォーム非依存】(PIL)
・CPUなどのエミュレーション全般
・プラットフォーム依存(PDL)間のブリッジ

【プラットフォーム依存】(PDL)
・映像出力
・音声出力
・入力機器からの入力

コードで書いた方が分かり易いので、LaiNESというファミコンエミュレータの実装をベースに見てみると分かり易いです。

オリジナルのLaiNESは、PIL と PDL が若干入り乱れているので、純粋な PIL だけを切り離した LaiNES を私の方で作ってみました。
https://github.com/suzukiplan/LaiNES

上記のSUZUKI PLANカスタム版LaiNESは純粋なPILのみ実装している キレイなエミュレータ なので、ターミナル上でファミコンを動かすこともできてしまいます。上記リポジトリのtest.cppが実際にターミナル上でファミコンを動かすプログラムの例です。

ファミコンを動かすといっても、ターミナル上でPDL(の全て)を再現するのは厳しいので、PDL部分(namespace HALの部分の実装)はダミーですが。

それだとあんまりなので、このSUZUKI PLANカスタム版LaiNESを用いてAndroidでPDLを実装してみた例も作ってみました。
https://github.com/suzukiplan/nes-view-android

なお、動作についてはPublic DomainのROMで確認してます。

2016年12月11日日曜日

iPad pro + Smart keyboard + Apple pencil を買ってみた

元々漫画(ニコ書)専用で iPad mini 2 (retina) を使っていたのですが、デレステをプレイするようになってから、容量(16GB)的にキツキツで、仕方なくニコ書を消してデレステ専用機としてiPadを使っていました。

しかし、そのiPadだとデレステの要求スペック的にキツく、結構高頻度でアプリが落ちるんですよね。

iPhone SEだと落ちないので、多分、メモリ不足によるものだと思います。
Unityだから仕方ないね。
当然、2D軽量でしかプレイしていないのですが、それでもよく落ちる。
主にルームへ行くと落ちやすくなる。多分、3Dでプレイしても落ちやすくなるかもしれませんが、3Dは、プレイし始めの1〜2週間ぐらいで一切見なくなったので未確認。
という訳で、新しいiPadを買ってきました。
購入したのは iPad pro 9.7 inch (WiFi) です。
容量は128GB。
これで、デレステと漫画だけでなくiTunesのアルバムも全てiPadに入れられるようになりました。

ついでに、Smart keyboard と Apple pencil も購入。

Smart keyboardはProが出た当初から割と気になっていました。
以前、スマホやタブレットで使える外部キーボードを使ってみて、かなりストレスフルで使い物にならなかったのですが、Smart keyboardならApple純正だから大丈夫だろうと。

実際に使ってみて、Smart keyboardは結構満足度が高いものでした。
これなら、出先でもiPadだけ持っていけば文書を書くのには困らない。
プログラミング用途としては、JavaScript any whereとかで簡単なJavaScriptを書く程度なら問題無さそうです。(JavaScript以外はApp Storeの規約の壁の影響でアレですが...)
せめてiPadでもmacOSと同等のbashが使えれば最強なのになぁ...

Apple pencilの方は、特に理由も無く購入しました。

私は絵は(ドット絵しか)描きませんが、昔Windowsを使っていた頃、ワコムの安いペンタブとSaiというアプリで落書きをするのが結構楽しかった(値段分遊べたと思う)ので、Apple pencilもその程度の楽しさが味わえれば値段的にもまぁ買いかなと。(参考: ワコムのペンタブ+Sai = 1万円ぐらい, Apple pencil = 同じく1万円ぐらい)
お絵かきツールは、procreateというアプリを購入。

使ってみてまず思ったのは「若干、遅延があるな」という事。
だいたい、100msぐらいでしょうか。
この点については、書く所と結果(ディスプレイ)が離れているペンタブよりはマシではありますが、もっと何とかならなかったんだろうか...(Apple pencilはiPad pro専用機器なので、技術的には何とでもなりそうな気がするので、つまり、この辺は開発コスト的な事情かな)

また、鉛筆ツールの書き味は、ワコムの安物のペンタブの方がしっかりしていた感。
ついでに、筆圧の感度も、ワコムの安物のペンタブの方が体感的に細かった印象。
書き味や筆圧についての印象は、そもそも、Apple pencilはペンタブではなく、どちらかといえば液タブだと思うので、ペンタブと比較するのが間違っているかもしれません。液タブの書き味は触った事がないので分かりません。

ちょっとしたメモを取るには良い感じかもしれませんが、使い続けるだろうかと問われるとちょっと微妙です。
Smart keyboardにApple pencilを格納する場所が付いていない点が最大のネックです。恐らく、それがネックで持ち出す機会が少なくなる→使わなくなるというパターンになりそうな気がします。(Smart keyboardではなくサードパーティー製のカバーであれば、ペンを仕舞えるものもあるので良いのですが)

2016年10月23日日曜日

switch

Nintendo Switchが発表されましたが、投資家の反応はイマイチみたいですね。
「発表するぞ」で若干上がって、発表されたらガクン。登場前の話題性という意味で、VRほどのインパクトが無い普通のゲーム機なので、まぁ、当然そうなりますよね。

私の期待値はそのまま保留。
むしろ、今のところは好感触です。
私の興味は、ハードそのものの革新性ではなく、ゲームプラットフォームとしてNintendo Switchがどういう形になるかという点で、Developer PortalにはまだNintendo Switch関連の情報が一切出ていないので、判断できません。(一番知りたいのは、開発に必要な機材とか参入ライセンスがどんな感じかということですが、それらはまだ分からない)

むしろ興味深かったのはパートナー企業の一覧(一部)。
上5段はコンテンツ制作企業で、昔からコンシューマ中心で作っている企業が中心。
「スマホ系だけ」という企業(CA系列とかコロプラとか)は載ってないっぽい。

下2段は、Unity、EPIC(Unreal Engine)、Web Technology(Sprite Studio)など、ツールやミドルウェアの制作企業のようです。

興味深いのはDeNA。
スマホゲーを一緒に作っているのは知っていますが、DeNAがコンシューマというのは違和感がある。少なくとも、コンテンツ制作での参加ではないはず。(並び順からしてもツールやミドルウェアのグループ内ですし)

あと分からないのはレコチョク。
これは、何故入っているのか全く分からない。
音楽ストリーミングでもやるつもりなのだろうか?




2016年10月17日月曜日

【疑問】何故VRを最初から家庭用で出したのか

PSVRが販売されて、色々な情報がチラホラでてきました。

ちなみに、今「PSVR」ググって出てきた記事は...

「PSVRじゃない」 父親殴った息子を逮捕 

http://kyoko-np.net/2016101401.html

虚構新聞ですね。

ちなみに私はイベントでオキュラスの試作品を少し触らせて貰った程度で、PSVR実機は触っていないので何とも言えません。オキュラスの試作を触った感想としては、「凄いとは思ったけど面白いゲームが作れるのか?」というもの。実際に出ているタイトルもサマーレッスン、アイマス、初音ミクなど、イマイチ触手が動かないモノ(※正確にいえば、それらが嫌いな訳ではないが、わざわざVRじゃなくて良いじゃないというモノ)しかない。

参考: PSVR 専用/対応予定ソフト一覧
http://gamefavo.com/db/psvr/soft-list/

仮に面白いゲームが世に出てきたとして、スマホゲームをポチポチやって満足している層にどうやって面白さを伝えるのだろうか。本体価格がPS4とセットで10万を超えるようなものを買わせるには、かなり大きな動機を与えなければいけないはず。

エロは甘えですが、それをアリにしても、ネタとしては良いけど欲しいとまでは思えない。これなら企画モノのDVDをツタヤで借りてくれば良いのでは?と思ってしまう。自分本位で操作できる点は新しいけど、それにしてもエロゲーで良いのではないだろうか(エロゲーは全くプレイしないので適当なことを言っているが)。

参考: PSVR ひかりちゃんのパンツを全力で見ようとした
http://www.nicovideo.jp/watch/sm29842806

虚構新聞でネタにされているバーチャルボーイも、ソコ(プロモーションの難しさ)がネックで売れなかったとか。でも、私はそれが原因でバーチャルボーイが売れなかった訳ではなく、単純にVRを活かした面白いゲームが作れなかったからバーチャルボーイは売れなかったのだと思っています。

PSVRは、バーチャルボーイと比べれば天と地ほどにハード性能が違います。単純なグラフィックや演算性能だけでなく、当時では無理だったインターネットを組み合わせた技術も使えます。PSVRでは、それらを活かした面白いゲームが作れる可能性があることは否定しません。

が、根本的な遊びの面白さみたいなものであれば、バーチャルボーイで実現できた筈で、単に性能が良くなっただけのPSVRでソレが解決できるのかは疑問。バーチャルボーイは生存期間が短かったから、それを探る試行期間が不足していたのかもしれません。

ゲームとしてはつまらなくても、美しいグラフィックを活かした別のエンターテイメント機器としての価値創出なら出来るかもしれませんが、そのグラフィックに関しては、まとめサイトを見ると「荒い」という意見が多い。まぁ、フレームレートを上げてる関係で、現状30〜60fps前後で見慣れているものと比較すればそうなるのも致し方ないと思いますが。

参考: PSVR】画質、解像度の評価、買う価値はあるのか
http://uver2468.hatenablog.com/entry/2016/10/16/014147

新しいものを作る上での試行錯誤というのは不可避です。ただ、それ(試行錯誤期間)を最初から家庭用でやるのは如何なものかと思っています。ビデオゲームが世に出てきた時と同様、最初はアーケード(機器をシェアしてプレイすることで消費者当たりの支出を下げる)、芽が出てきてから家庭用(機器を消費者毎に専有)という流れの方が成功率が高いのではないだろうかと思っています。要するに、市場形成ができていない状態でいきなりモノが売れる筈が無いのに、何故その方向で舵を切ったのかが疑問です。今のままでは、単なるガジェッター専用の玩具で終わってしまうのではないだろうか。

2016年10月15日土曜日

IBv6開発状況

ずっとデレステばかりやっていると疑われるとアレなので、最新の開発状況でも書いておきます。

Invader Block variatio 6 は
・Invader Blockステージ
・Battle Marineステージ
・連魂ステージ
という3種類のルールが異なるステージから構成されるゲームで、現在は連魂ステージを開発中という状態。

初代連魂はモノクロでしたが、今回はちゃんとカラーです。
グラフィックが進化し続けている今日日、「カラーですよ」とドヤ顔されてもアレでしょうけど。

かなり激しいです。
静止画だと上手く魅力が伝わりませんが。

敵のバリエーションがかなり豊富なロングステージ構成となっています。
例えば、上図の青い弾を出してきているヤツは、プレイヤーが近づくまで海の中に潜っていて、近づいたらザパーンと出てきて自機狙いベースの乱射をしてきたりとか。

現在は中ボスを作成中。
中ボスはNOKOGI Riderから友情出演(という名の作画手抜き)

これまでSUZUKI PLANが作ってきたゲームの集大成という感じの仕上がりにしたいので、思いついたことは全てぶっ込むようにしています。ただし、「その場の思いつき」みたいなアイディアは多分ひとつも無く、実際に作ってきてリリースしてきたからこそ分かる「こうすれば面白くなる」みたいな道筋が朧げに見えているので、だからこそ、思いついたことを黙殺できません。

私はNOKOGI Rider以降、その正統後継的な規模感のゲームは作らず、Battle Marineや連魂などの小粒なゲームを沢山作ってきましたが、これらはその「朧げな道筋」を見極める為に必要なプロセスだと考えています。面白いか面白くないかは、実際に作って遊んでみないと分からないので。

正統後継的な規模感のゲームを繰り返し作り続けるというアプローチ(東方Projectとかが多分そういうアプローチ)も当然アリだと思いますが、小粒なモノで色々と試していった方が、私が作りたいモノの方向性がよりクリアに見えてくるのではないだろうかと思います。

「弾幕STGを作りたい」など、方向性がキッチリ決まっていれば、正統後継的な規模感のゲームを繰り返し作り続けるアプローチの方が多分良いです。しかし、私の場合、それほど弾幕STGを作りたい訳でもなく、だからといってどういうゲームを作りたいのかもハッキリ見えていなかったので、小粒なモノで色々と試していくアプローチの方が肌に合っているんじゃないかなと。

まぁ、そんな感じですので、恐らく完成までにはまだ時間が掛かりそうです。
それでも今年中には出したいところですが。

2016年10月2日日曜日

ようやく PRO をフルコン

今年は8月末〜9月初旬が夏休みでした。
この時期に休めば、誰とも都合が合わないので、集中してゲーム開発ができる訳です。

そして、前の記事で書いたようにモリモリ開発を進めていたのですが、今日ついに、その時に息抜きで始めたデレステで PRO の全楽曲(※現時点)のフルコンクリアを達成。
いやー、大変でした♨

音ゲーは苦手なんですよね。

ちなみに、上図の杏(SSR)はスカチケでゲットしたもので、リセマラはやっていない(その分の石は全部スタミナ回復に費やした)ので、SSRはその1枚のみというほぼ無課金プレイです。(※スカチケ=3000円)
niceやbadでもコンボが繋がるアイドルが居ればもっと楽にできたかも。

MASTERは一通りクリアしてみた限りの感触では、フルコンできるのはLv26までぐらいが限界点かな。
MASTER+のフルコンは多分無理。
iPhone SEで親指縛りだと。

一応、iPad(mini 2 retina)も持っているので、そっちでやればMASTERまでの全曲フルコンもできそうな気がしています。ただし、iPadの方は主に片手縛りで遊ぶ用に別アカウントで使用中。そろそろ今iPhoneで使っているメインアカウントに統合して、iPadで縛り無しのガチプレイをすべきかもしれない。


・・・息抜きとは・・・


とりあえず、無料石が多すぎて、ガチャを引かなければ延々と遊べてしまうのがマズイ。
という訳で、適当にガチャを引いて有り余っている石を潰し、スタミナが無くなったら(課金しなければ)プレイできないようにしようかと考え中。

2016年9月25日日曜日

xcode 8.0 で clang-format を使えるようにする方法

xcode 8.0 でプラグイン周りの仕様がだいぶ変わってしまったようで、今まで外部プラグイン(Alcatraz)で入れていたclang-formatが使えなくなった(参考)らしい。という訳で、Alcatrazを使わずにxcode 8.0に新しいプラグイン方式に対応したclang-formatを探してみて、幾らか方法が見つかったのですが、どれも面倒くさそう...

まぁ、Alcatraz自体、元から面倒くさかったんですよね。

xcodeをアップデートする都度、一時的に使えなくなったりするので。

という訳で、
・xcodeのアップデートに動じず
・commit時に漏れなく簡単に全ソースにclang-formatを実行でき
・楽であること
という全ての条件を満たす方式を考えることにしました。

その結果、
「普通にmakefileで書くのが一番楽では?」
という結論に至る。

という訳で、私のxcode projectでmakefileを使ってclang-formatの実行を自動化したやり方を書いておきます。

まず、xcode projectのディレクトリ直下に以下のようなシェルを作成

■format.sh
#!/bin/sh
echo formatting: $1
clang-format -assume-filename=.clang-format <$1 >.work
diff .work $1 >/dev/null
if [ $? -eq 1 ]
then
cat .work > $1
fi

\rm -f .work


このシェルがやっていることは、
1. 引数に指定されたソース に clang-format を掛けたソース(.work)を作成
2. 元ソース と .work を比較
3. 差分があれば元ソースの内容を .work の内容に書き換える
ということ。
毎回無条件でclang-formatを掛けてしまうと、差分ビルドに時間が掛かってしまうので、clang-formatの結果変化があるソースのみを書き換える感じです。

そして、同ディレクトリに以下のような makefile を作成

■makefile
HEADER = $(shell for file in `find . -name *.h`;do echo $$file; done)
C_SOURCE = $(shell for file in `find . -name *.c`;do echo $$file; done)
CPP_SOURCE = $(shell for file in `find . -name *.cpp`;do echo $$file; done)
OBJC_SOURCE = $(shell for file in `find . -name *.m`;do echo $$file; done)
SOURCES = $(HEADER) $(C_SOURCE) $(CPP_SOURCE) $(OBJC_SOURCE)

all:
    for SOURCE in $(SOURCES); do make format SRC=$$SOURCE; done

format:
    @sh format.sh $(SRC)


上記のmakefileでは現在のカレントディレクトリ(find .)から拡張子 .h .c .m のファイルを検索して見つけたリスト(SOURCES)を作り、そのリスト内のファイルをひとつづつ先程のシェル(format.sh)に指定して実行するという感じのものです。

あとは、git commit をする前に一発makeを叩けば、全ソースのコードフォーマットが掛けられるという感じになります。(findの所はプロジェクトによっては若干書き換えが必要になることがあるかもしれませんが)

今開発中の Invader Block 6 のプロジェクトでこの makefile を叩いてみた結果は以下のような感じです。
$ make
for SOURCE in IBLOCK6/AppDelegate.h IBLOCK6/ball.h IBLOCK6/bird.h IBLOCK6/bomb.h IBLOCK6/bonus.h IBLOCK6/check.h IBLOCK6/dot.h IBLOCK6/draw.h IBLOCK6/enemy.h IBLOCK6/ft.h IBLOCK6/game.h IBLOCK6/hanabi.h IBLOCK6/hit.h IBLOCK6/laser.h IBLOCK6/player.h IBLOCK6/replay.h IBLOCK6/stage.h IBLOCK6/teki.h IBLOCK6/utility.h IBLOCK6/vgs2.h IBLOCK6/VGSLayer.h IBLOCK6/VGSView.h IBLOCK6/ViewController.h IBLOCK6/wall.h IBLOCK6/ball.c IBLOCK6/bird.c IBLOCK6/bomb.c IBLOCK6/bonus.c IBLOCK6/check.c IBLOCK6/dot.c IBLOCK6/draw.c IBLOCK6/enemy.c IBLOCK6/game.c IBLOCK6/game_lv1.c IBLOCK6/game_lv2.c IBLOCK6/game_lv3.c IBLOCK6/game_opening.c IBLOCK6/game_ranking.c IBLOCK6/game_result.c IBLOCK6/game_title.c IBLOCK6/hanabi.c IBLOCK6/hit.c IBLOCK6/laser.c IBLOCK6/player.c IBLOCK6/replay.c IBLOCK6/stage.c IBLOCK6/teki.c IBLOCK6/utility.c IBLOCK6/vgs2api.c IBLOCK6/vgs2i.c IBLOCK6/wall.c IBLOCK6/AppDelegate.m IBLOCK6/main.m IBLOCK6/VGSLayer.m IBLOCK6/VGSView.m IBLOCK6/ViewController.m; do make format SRC=$SOURCE; done
formatting: IBLOCK6/AppDelegate.h
formatting: IBLOCK6/ball.h
formatting: IBLOCK6/bird.h
formatting: IBLOCK6/bomb.h
formatting: IBLOCK6/bonus.h
formatting: IBLOCK6/check.h
formatting: IBLOCK6/dot.h
formatting: IBLOCK6/draw.h
formatting: IBLOCK6/enemy.h
formatting: IBLOCK6/ft.h
formatting: IBLOCK6/game.h
formatting: IBLOCK6/hanabi.h
formatting: IBLOCK6/hit.h
formatting: IBLOCK6/laser.h
formatting: IBLOCK6/player.h
formatting: IBLOCK6/replay.h
formatting: IBLOCK6/stage.h
formatting: IBLOCK6/teki.h
formatting: IBLOCK6/utility.h
formatting: IBLOCK6/vgs2.h
formatting: IBLOCK6/VGSLayer.h
formatting: IBLOCK6/VGSView.h
formatting: IBLOCK6/ViewController.h
formatting: IBLOCK6/wall.h
formatting: IBLOCK6/ball.c
formatting: IBLOCK6/bird.c
formatting: IBLOCK6/bomb.c
formatting: IBLOCK6/bonus.c
formatting: IBLOCK6/check.c
formatting: IBLOCK6/dot.c
formatting: IBLOCK6/draw.c
formatting: IBLOCK6/enemy.c
formatting: IBLOCK6/game.c
formatting: IBLOCK6/game_lv1.c
formatting: IBLOCK6/game_lv2.c
formatting: IBLOCK6/game_lv3.c
formatting: IBLOCK6/game_opening.c
formatting: IBLOCK6/game_ranking.c
formatting: IBLOCK6/game_result.c
formatting: IBLOCK6/game_title.c
formatting: IBLOCK6/hanabi.c
formatting: IBLOCK6/hit.c
formatting: IBLOCK6/laser.c
formatting: IBLOCK6/player.c
formatting: IBLOCK6/replay.c
formatting: IBLOCK6/stage.c
formatting: IBLOCK6/teki.c
formatting: IBLOCK6/utility.c
formatting: IBLOCK6/vgs2api.c
formatting: IBLOCK6/vgs2i.c
formatting: IBLOCK6/wall.c
formatting: IBLOCK6/AppDelegate.m
formatting: IBLOCK6/main.m
formatting: IBLOCK6/VGSLayer.m
formatting: IBLOCK6/VGSView.m
formatting: IBLOCK6/ViewController.m

2016年9月1日木曜日

開発状況2(IB6)

ステージ2をもりもり作成中。
Invader Block variatio 6 のステージ2は Battle Marine 仕様です。
ゲーム内容については、だいたい旧Battle Marineを去就した形になっています。敵の種類やグラフィックは流用。
プログラム的な部分は完全にゼロから作り直していて、コンボの爽快さなどを追求。

今週夏休みなので今日中ぐらいにステージ2を完成させるつもりですが、やや遅れ気味。

ステージ1(Invader Block仕様)からステージ2に進むまでの演出を凝らせていたら、作り始めるまでに結構時間が掛かってしまいました。

それ以上に、このタイミングでデレステを始めてしまい、それに時間が取られた感が否めない。
本当はコーヒーブレイク用に始めたのですがね。
ソシャゲって体力回復待ちがあるから、体力が尽きるまでプレイして、回復するまでの間に開発。そして、回復したらまたプレイみたいな風にすれば割と良い感じなんじゃないかと。
しかし、実際には無料石を回収し、石を使って(ガチャには回さず)体力回復してプレイを延々と繰り返し、そのコーヒーブレイクにIB6の開発を進めていた感が否めない。
夏休みはあと4日(木、金、土、日)で、土曜は予定があるから、流石に木、金は石を使った回復は自重するなどの縛りを入れねば。

2016年8月24日水曜日

開発状況(IBV6)

タイトル画面やらチュートリアルをザックリ作成。
システム的には NSWindow でのフルスクリーンモード(安定している方)にしておきました。
ウィンドウモードはナシです。

チュートリアル(というかHOW TO PLAY)は、昨今のチュートリアルと違ってかなりアッサリしたもの。アーケードゲームのインストに書いてある相当の情報量以上は入れないつもり。

ゲーム本編としては、ステージ1がだいたい完成したというところ。

Invader Block 5からの要素的な意味での変更点は、
・画面上部に吹き抜け(左右ループ)を入れてみた
・画面下にブロックを配置
・(メダルを消費して)ショットを撃てる
・(Battle Marineの)鳥が登場する
といったあたり。

かなりカオスな感じです。
難易度的なところはより一般向けに低くしています。
インベーダーを数グループ撃破するとステージクリアになって、Battle Marineシステムのステージ2に進む予定。

ステージは、
・Invader Block
・Battle Marine
・RENCON
・Invader Block(裏)
・Battle Marine(裏)
・RENCON(裏)
の全6面にするつもりで、特定条件を満たせば周回ループ(最大2周)できるようにしようかなと思っています。まだステージ1までしか作っていなくて、そこで色々と鬼調整をしているところなので、ステージ2以降は完全に未定。

ちなみに、今のところMac版しか作っていないですが、Windowsへの移植もすぐにできます(ゲーム本体はVGSで書いているので技術的には移植は一瞬でできる)。今秋ぐらいまでにMac AppStoreでの販売開始が目標で、その後Greenlightに出して成功すればSteam版(Steamのスコアボードやアチーブメントに対応したもの)を作ろうと思っています。(要するにGreenlightを通らない限りWindows版は世に出さないつもり)

課金要素としては有料販売のみで追加課金ナシ。
Mac AppStore版は1usd、Steam版は5〜10usdの間ぐらいにする予定。

2016年8月23日火曜日

Nintendo Developer Portalに登録した

任天堂から、Nintendo Developer Portal なるものが個人向けにも解放されたので、個人名義で登録しておきました。(ビジネス名はSUZUKI PLANにしておきましたが)
https://developer.nintendo.com/
NTSCみたいなものだろうか?(実務での任天堂ハードでの開発経験はゼロなので、その辺の詳しいことはよく分からない)
登録自体は無料でできるので、個人/同人のゲームデベロッパはとりあえず登録しておけば色々と見えてきて面白いかと思います。
とりあえず、3DS or WiiU向けの開発ならできそうです。
実際に開発を始めようとすると、開発機材の初期費用がそこそこ掛かるので、中々敷居が高いですが。

私自身も、実際に3DS向けゲームの開発に乗り出そうとして登録した訳ではなく、どういうSDKがあってだいたいどんな感じの仕様かを把握しておく為に登録しました。恐らく、今回のNDP解放は次(NX)に本格的にインディー開発者を取り込む流れにするための布石ではないかと思ったので。(5年前ならともかく、今から3DSだとミニマムの開発費用20万円をペイすることすら個人だと難しいんじゃなかろうかと)

3DSのSDK(nativeの方)の仕様書をまだ読み途中で、SDKがC++だったのは予想通りですが、Unitiyなんてものもあるんですね。
使いませんが。
Unityをディスっている訳ではなく、私の場合、ネイティブで動くVGSエミュレータを先に作り、その後ゲームを開発するというスタイルで、それはプラットフォームがどのように変化しようとも変わらないことなので、そうなるとUnityという選択肢は無意味だということ。
しかし、結構最近のコンソール開発環境って色々充実している感じなんですね。
無駄に充実しているというか。
Visual Studio統合って何なんですか(要らない)。

NXでは、CTR_SDK(CLI)のLinux版やMac版が欲しいところです。
あと、ハードは実機+USBケーブル+PCだけで開発できるようになっているといいなぁ。

2016年8月16日火曜日

Macでフルスクリーンゲーム開発のつらみ

macOS用のゲーム開発ですが、NSViewのフルスクリーンで開発すると中々つらい。というのも、落ちる系のバグが残っていると、電源OFFして止めるしか無い状況に陥る。そして、電源OFFにすると落ちる系のバグを特定できる情報が飛んでしまうとか。

という訳で開発中はウィンドウモードで作っておくことにしました。

ウィンドウの大きさに応じてアスペクト比を保った状態でゲーム画面を拡大。
そして、余白は(とりあえず)黒塗り。

余白がある場合は下図のような形になります。
上図は試験的にインタレース描画にしているので、若干画面が暗いな。

緑ボタン(or NSWindow の toggleFullScreen)でフルスクリーンにしてやれば、結果的にはNSViewをフルスクリーンにした場合と見た目は同じになります。なので、こっちの方法でフルスクリーン対応しておくべきかも。

macOSでフルスクリーンのアプリ(主にゲーム)を作る方法としては、

・NSViewをフルスクリーンにする方法(OSX 10.5以降)
[self.view.window.contentView enterFullScreenMode:self.view.window.screen withOptions:nil];
・NSWindowをフルスクリーンにする方法(OSX 10.7以降)
[self.view.window toggleFullScreen:nil];

の2種類があるのですが、どちらかといえば後者で対応した方が良いのだろうか... 前者の方が色々と考える事が少なくて実装が楽になるのですが。

前者にも色々とトラップ(※)がありますが。
※ドキュメントから抜粋: On OS X v 10.5, invoking this method when the view was not in a window would cause an exception. On OS X v 10.6 and later, you can now send this message to a view not in a window. For applications that must also run on OS X v 10.5, a simple workaround is to place the view in an offscreen dummy window.
まぁ、古いOS(10.6以下)を救うメリットはWindowsと違ってほぼ無いので、素直に新しい方(後者)で対応しておいた方が良いのではないかと思います。

後者での対応は色々と面倒臭いのですが。
最小化を考慮した対応、Windowサイズの制御、Storyboardをいじってメニューをちゃんと作らないとMac AppStoreへ出す時の審査でよくリジェクトされたりなど。

2016年8月14日日曜日

INVADER BLOCK variatio Ⅵ

SUZUKI PLAN というサークル名で活動を初めてからそろそろ丸8年経とうとしています。

8年やって当たったモノといえば 東方BGM on VGS ぐらいですが、これはノーカウントで。(純粋にオリジナルのものではないので)

特に生活が掛かっている訳でもないので、好きなゲームを好きなように作っていけば良いのではないかと思っています。

私が好きなゲームというと、例えばドンキーコング、アルカノイド、スペースインベーダーなどのような固定画面アクションゲームで、だから SUZUKI PLAN が最初に作ったゲームはINVADER BLOCKだったし、その後もBATTLE MARINE、CANON SNIPER、LUNATIC CRAYといった固定画面アクションゲームの比率が高い感じになっています。

中でも INVADER BLOCK は、最初に作ったためか特に思い入れが強く、私が新しい開発環境でゲームを作る時、必ず最初に作るのは INVADER BLOCK のリメイクという形になっています。

・ファミコン版: INVADER BLOCK FC(※未発表)
・スマートフォン(iOS, Android)版: INVADER BLOCK 2
・VGS mk-II版: INVADER BLOCK 3
・HTML5版: INVADER BLOCK 5
という具合。

あぁ、INVADER BLOCK 4が無いですね。まぁ、2と3は未発表のファミコン版を飛ばして採番しているので、INVADER BLOCKシリーズは実質5作品あることになります。
実のところHTML5版は公開しているもの(enchant.jsを使用)とは別のゲームエンジンを使ったバージョンもあったりしますが。

どれもそんなに大ヒットはしてません。
どちらかといえば試作的に作ったものなので当然ですが。
しかし、SUZUKI PLAN は今まで結構な数のゲームを作ってきましたが、その中で大ヒットの芽があるであろう作品は INVADER BLOCK だろうと思っています。

そこで、今の私ができ得る最大限のクオリティのINVADER BLOCKを作ろうと思いたち、現在開発中です。
タイトルは INVADER BLOCK variatio Ⅵ(仮)

対応プラットフォームはMacとWindowsで、最初にMac版だけAppStoreで出し、反応が良ければSteamでWindows+Mac版(AppStore版とは別でSteam関連のアチーブメントやリーダーボード等を実装する予定)を出そうかなと計画してます。

Steamで出すにはグリーンライトを通過する必要があるので、出ない可能性もありますが、AppStore版については今秋ぐらいまでには販売開始しようと思っています。

なお、スマホ版は今のところ予定していません。
VGSで開発しているので、スマホにはほぼノーコストで対応可能ですが、今回はタッチパネルではなくゲームパッドやジョイスティックを前提としたゲームプレイにしたいので、タッチパネル操作という足かせを付けながらのゲームデザインは避けようと思っています。
完成後であれば、スマホ移植する可能性が無い訳ではないです。
(要するにスマホファーストではないというだけのこと)

2016年8月10日水曜日

gamepad-osxの実装詳解

前回記事で書いた gamepad-osx の実装内容を軽く解説。

まず、mac OS (OSX) や iOS で HID(Human Interface Device; キーボード、マウス、ゲームパッドといった入力デバイス)へのアクセスは HID Manager 経由で行うので生成。

IOHIDManagerRef hid_manager = IOHIDManagerCreate(kCFAllocatorDefaultkIOHIDOptionsTypeNone);

次に、取得対象のデバイス情報を指定した CFMutableArray を作成する。
Objective-cなら割と簡単にできるが、Core Foundation を用いる必要があるので物凄く面倒くさい。

static void append_matching_dictionary(CFMutableArrayRef matcher, uint32_t page, uint32_t use)
{
    CFMutableDictionaryRef result = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    if (!result) return;
    CFNumberRef pageNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &page);
    CFDictionarySetValue(result, CFSTR(kIOHIDDeviceUsagePageKey), pageNumber);
    CFRelease(pageNumber);
    CFNumberRef useNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &use);
    CFDictionarySetValue(result, CFSTR(kIOHIDDeviceUsageKey), useNumber);
    CFRelease(useNumber);
    CFArrayAppendValue(matcher, result);
    CFRelease(result);
}
余談ですが、Core Foundation を C/C++ で書いたコードを見ていつも思うのが「無駄なオーバーヘッド要因が異様に多い」ってことですね。その代わり拡張性は高い。これが所謂 Mach の設計思想から引き継がれたオドロオドロしい部分なんだろうと思います。要するに効率性ではなく柔軟性・拡張性みたいなところに特化した仕組みで、だからNeXTSTEPは実用に耐えられなかったのだろうと。iOS世代もそのCFを内部で引きずり続けているから、結局のところ処理効率はそんなに良くない。何故スマホ初期の頃にピュアなLinux Phoneが出なかったのかと今でも思っています(今となっては商業的な意味で手遅れですが)。

上記関数の page は kHIDPage_GenericDesktop で use は以下のような値を指定する。
なお、ジョイスティックとゲームパッドは別useになっているので注意。私の手持ちのゲームパッドの場合, kHIDUsage_GD_GamePad を指定しないと認識しませんでした。
・kHIDUsage_GD_Joystick : ジョイスティック
・kHIDUsage_GD_GamePad : ゲームパッド
・kHIDUsage_GD_Keyboard : キーボード
・kHIDUsage_GD_Mouse : マウス(トラックパッド)

そして、作成したCFMutableArrayで指定したものが取得したいデバイスだということを HID Manager へ通知して、そのデバイスが接続されたことと切断したことを検出するコールバックを登録。


IOHIDManagerSetDeviceMatchingMultiple(hid_manager, matcher);
IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, device_attached, c);
IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, device_detached, c);

なお、接続(切断)のコールバックの形式は以下のような感じ。(detachedも同じ)

void device_attached(void* ctx, IOReturn result, void* sender, IOHIDDeviceRef device);

このコールバックでは、接続(切断)されたデHIDの情報を教えてくれるだけなので、そのHIDからの入力を検出したり解除するには、更に別のコールバックを設定する必要があります。(詳細は後述)

あとは、HID Managerを動かすrun-loopをスケジュールしてOpenすれば、デバイスの接続と切断が検知できるようになります。

IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetMain(), kCFRunLoopCommonModes);
IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone);

ここまでが、HIDの接続・切断を検出するまでの手続きです。
あとは、接続を検出したHIDに対して入力を受け付けるコールバックを設定してあげれば、入力された内容を検出することが可能になります。
これは接続時のコールバックで次のように実行すればOK。

IOHIDDeviceOpen(device, kIOHIDOptionsTypeNone);
IOHIDDeviceScheduleWithRunLoop(device, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
IOHIDDeviceRegisterInputValueCallback(device, device_input, c);

デバイス入力コールバックの形式は以下のような感じです。

void device_input(void* ctx, IOReturn result, void* sender, IOHIDValueRef value);

最後に、この入力コールバックで以下を発行すれば入力された情報が検出できることになります。

IOHIDElementRef element = IOHIDValueGetElement(value);
type = IOHIDElementGetType(element);
page = IOHIDElementGetUsagePage(element);
usage = IOHIDElementGetUsage(element);
val = IOHIDValueGetIntegerValue(value));

ね、簡単でしょ?

Steamで購入したとある日本製のゲームが、ゲームパッドに対応できていない(海外製のゲームはだいたい対応できている)ので、そのサポートに対して「簡単だからゲームパッドの入力に対応してくれ」とお願いしてみたのですが、日本語でIOKitの仕様を正しく解説できているサイトがほぼ皆無だったんですよね...

そういう事情もあって、もしかすると多少ニーズがあるかもしれないと思い、かなり簡単な手続きでmac OSのアプリでゲームパッド入力に対応できるライブラリ(gamepad-osx)を作ってみた感じです。

まともな資料は英語しか無かったけど、冷静に読めば結構簡単なことしか書いていないので、特に困る人が居ない→だから日本語資料が無いのかもしれませんが。

ちなみにこのIOKitというフレームワークですが、mac OS(OSX)の中ではかなりベーシックなもので、Wikipediaなんかを見ても(かなりあっさりとだが)MachやBSDと同列に解説されています。要するに、mac OS(OSX)の仕組みを理解する上でかなり重要な部分なので、技術書ぐらい幾つかあるんじゃないかなと思ってAmazonで検索してみたのですが、見事に皆無。
https://www.amazon.co.jp/s/ref=nb_sb_noss?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&url=search-alias%3Daps&field-keywords=IOKit&rh=i%3Aaps%2Ck%3AIOKit
Appleによる情報統制でも掛かっているのかな?
まぁ、このブログは妄言ということで許される(のだろうか^^;)

2016年8月7日日曜日

mac OS (OSX) のアプリでゲームパッドを使う方法

Windowsだとゲームパッドへの対応は簡単(DirectInputで可能)ですが、mac OS(OSX)だとかなり躓きどころが多い。

まず、GameControllerを検出する標準フレームワークがありますが、これが全く使い物にならない
対応機種が限られてしまうので。
AppleがMagic Gamepadみたいなものを出していればまだ良いのですが。

という訳で、mac OS(OSX) でゲームパッドの入力に対応する場合、HID Device Interfaceを使う方法が一般的です。

ただし、GameControllerと違って日本語の資料も無いし、ぐぐっても情報が全く出てこない。(ゼロという訳ではないですが)

という訳で、割と簡単に使える mac OS (OSX)用 のゲームパッド・ライブラリを作ってみました。
https://github.com/suzukiplan/gamepad-osx

呼び出しはC規約なのが若干面倒かもしれませんが、Objective-cのXcodeプロジェクトであれば問題無く利用できます。(開発中のOSX用STGに組み込んでみたのですが、問題なく動きました)

swiftのXcodeプロジェクトで使えるかは未確認ですが、int型とvoid*型しかインタフェースに使っていないので、まず問題ないでしょう。

[追記]
どうせなら、入力系統は全て gamepad で処理した方が良いということで、キーボードとマウスの入力も受け付けられるようにしました。
ただし、キーボードに関しては実装する NSView のサブクラスをファーストレスポンダに設定しておく必要があります(そうしないとキー入力時に警告音が出てしまうので)。
また、これはかなりベーシックなレイヤーで入力を受け取っている関係で、NSWindowなどの状態が非フォーカスでも入力が受け付けられる筈です。また、マウス座標も全体座標の筈。(要するにキーボードとマウスはどちらかといえばフルスクリーンで動作するゲームを想定したものです)

レベル3の壁超えについて

さて、あなたは以下の幾つが YES だろうか。

Level 1. ゲームを作りたいと思ったことがある
Level 2. ゲームを作ろうとしたことがある
Level 3. ゲームを完成させたことがある
Level 4. 完成したゲームを不特定多数の人に向けて公開したことがある
Level 5-1. 公開したゲームが法人から評価されたことがある
 ・例1: 雑誌に取り上げられた(掲載された)
 ・例2: コンテストで入賞した
Level 5-2. 公開したゲームで収益を得たことがある
 ・例1: 入賞賞金をゲットした
 ・例2: 原稿料をもらった
 ・例3: 有料販売して売れた
 ・例4: 広告収益を得られた
Level 6. 公開したゲームの収益が1年あたり20万円以上(確定申告が必要)になったことがある
Level 7. 公開したゲームで得られた収益を青色申告している
Level 8. 公開したゲームで得られた収益を白色申告している

細かいルールですが、レベル5とレベル6の判定ルールは以下のような感じです。
・5-1 or 5-2 何れか一方をクリア = レベル4.5
・5-1 and 5-2 両方をクリア = レベル5
・5-1 or 5-2 何れか一方をクリアしていなくても、レベル6をクリア = レベル6
要するにレベル4.5からレベル6への飛び級があり得るということ。
まぁ、どうでも良いことなのですが。

上記の「ゲーム」を「サービス」に置き換えても良いかも。
私は 1〜4 と 5.1&5.2 が YES で 6〜8 が NO。
つまり、レベル5 です。

私は2008年にゲーム作りを再開した当初から、このレベル設定を考え、最終的にレベル8を目指すという超絶難易度のクソゲーを遊んでいる訳です。

私がSUZUKI PLANを名乗るようになってからの遍歴を晒すと、2008年にSHOT01を完成させ(レベル3)、公開して(レベル4)、2009年にSHOT02で何冊か雑誌に載ったりして(レベル4.5)、2012年にSHOT04でようやく売れるようになってきた(レベル5)という感じです。

レベル4.5からレベル5への壁は、スマホ普及以前と比べれば大分低くなってきたものの、まだまだ依然として大きい。AdMobとか入れれば少しぐらいの収益ならゲットできるだろ?と思われる方も居るかもしれませんが、一定額(確か100$ぐらいだったかな?)以上ならないと振り込みはされないので、結構大変なことだと思います。

それでも、手段が皆無に等しかった昔と比べれば、レベル3の壁さえ超えればワンチャンあると言っても過言ではないでしょう。

しかし、レベル3の壁を超えられないという人は意外と多い。
恐らく、最初っからハイレベルなものを狙い過ぎているんじゃないですかね。
レベル3に達せない人は、まずレベル3を超えるだけのことを考えれば良いと思います。
例えば、ドラクエ3みたいなゲームを作りたいけど、プログラムは書けるが絵や音楽は無理なら、絵や音楽はキャプチャするなりROMから抜くなり(^^;)してでも作れば良いのではないかなと。
もちろん、キャプったり抜いて作った場合は公開してはいけませんが、まずはレベル3をクリアすることだけ専念すれば良くて、どうしても公開したければ、完成後に権利上問題ない素材を作るなりフリー素材から集めるなりして差し替えれば良いでしょう。
動くものがあれば、「じゃぁ、素材は俺が作ってやんよ」みたいな友達が見つかり易いかもしれません。

2016年7月29日金曜日

ポケモンgoの各国評価を見たら割と面白かった

ポケモンgoの人気凄いですね。
私もやっていますが、あまりやり込んではいなくてLv18, 集めたモンスターは43種ほど。

スマホゲームは、パズドラ、モンストが長年AppStore, GooglePlayの売上1位を独占し続けていた事からも分かるように、一発当てれば息が長い。果たしてポケモンgoはどうなるのか。

各国の売上ランクはAppAnnieで確認した限り1位キープという状態。パズドラやモンストが1位キープを続けたのは日本限定ですが、ポケモンgoの場合全世界(※一部地域を除く)で1位キープを(今のところ)続けているという違いがあります。

それはさておき、各国の評価を見てみると結構面白いことになっていました。

※図面+データはAppAnnie(https://www.appannie.com)から引用してます

まずは、日・米・英

だいたい同じような形です。
米英は 5 > 1 > 4 > 3 > 2 という並びに対して
日本は 5 > 1 > 3 > 4 > 2 という並び(3と4が逆)だったりと、
細かい違いはありますが。

余談ですが、これは私のアプリの評価を見ていても同じ傾向がある(日本人は3を付ける確率が他国と比べて若干多い)ような気がするので、これは国民性かな?「良い」「普通」「悪い」の選択肢で迷ったらとりあえず「普通」を選べ的な感じのアレです。

日本の評価1の指摘内容を見てみると、地域格差を指摘する声が多いので、各国だいたい同じような状況で評価1が集まっているのではないかと思います。(Ingressのポータルの情報がポケストップになっているので、Ingressが流行していた地域なら田舎でもそれなりに充実しているかもしれませんが)

ドイツ、オーストラリア、カナダ、オランダ、スウェーデン、スイスでもだいたい同じ評価分布になっています。世界各国だいたい同じような都市構造になっているんでしょうね。

しかし、イタリアは大分違う形をしている。
★1が圧倒的に多い。
これは一体・・・
Ingressポータルが全般的に少なかったとか?

逆にフランスは★1が圧倒的に少ない。
なお、フランスの評価件数が少ないのは、日本と同じく配信開始が遅かったためのようです。

世界各国で同じようにヒットしているので、評価分布は世界各国でだいたい同じ形(逆コの字型)になると推測していましたが、何故こんな差が出たのかな?色々と想像が湧いてきて面白いのですが、如何せん私はイタリアとフランスには実際に行ったことが無い(陽気なイタリア人と適当なフランス人といった漠然としたイメージぐらいしかない)ので、空想の域を出ません。

2016年7月26日火曜日

vgsdrun で ステップ実行

vgsdrun(vgs-cpu付属のデバッグ実行コマンド)にステップ実行機能を追加してみました。
これは実際に動かしてみると楽しい。
楽しい?
...いや、私だけかもしれません。
ポケモンgoの方が楽しいですね。

インストールから動かすまでの手順は下記の通り。

$ git clone https://github.com/suzukiplan/vgs-cpu.git
$ cd vgs-cpu
$ make build
$ ./vgsdrun src/test/asm_mul.asm  -s
assembling: src/test/asm_mul.asm on memory
starting debug run.
00000000: ----- start-a -----
00000000: 08 E8 03               : line#00006 > LD   A, 1000
00000003: 6F 64                  : line#00007 > MUL  A, 100
00000005: A7 A0 86 01 00         : line#00008 > CMP  A, 100000
0000000a: F8 08 03 00 00         : line#00009 > JNE  $308 (test-failed)
> h
command usage:
- h     ... help
- r     ... show registers
- q     ... quit
- other ... execute next line
> r
registers:
c->r.a = 000186A0, c->r.b = 00000000, c->r.c = 00000000, c->r.d = 00000000
c->r.p = 0000000A, c->r.s = 00000000, c->f.z = 00000000, c->f.q = 00000000
> q
$

vgsdrunを実行すると以下のようにコマンド入力待ちになります。

00000000: ----- start-a -----
00000000: 08 E8 03               : line#00006 > LD   A, 1000

上記は1行上の命令(08 E8 03)をこれから実行するという意味です。
enter キーを押せば実行して以下のように表示されます。

00000000: ----- start-a -----
00000000: 08 E8 03               : line#00006 > LD   A, 1000
00000003: 6F 64                  : line#00007 > MUL  A, 100

ちゃんとエスケープで綺麗に表示してます。
復帰(\r)や改行(\n)とかは割とよく使うかもしれませんが、1行上に戻るという中々普通に生活(プログラミング)していると使わないエスケープを使っています。
printfで書くと以下のような感じ。

printf("\033[1A");

ぐぐっても1発では出てこかなかったけど、C/C++言語で作るコマンドインタフェース(CLI)のプログラムで「1行上の行に戻りたい」みたいなニーズは少ないのだろうか。
なお、WindowsのMS-DOSプロンプトでちゃんと動くかは未確認です。

2016年7月24日日曜日

vgsdrun (デバッグ実行コマンド)

vgsasmのテスト(アセンブル+実行テスト)をもりもり実施中なのですが、アセンブリ言語自体のコーディングミスでテストがコケるというケース(=テストケースの間違い)が割と多い。

まぁ、それ自体は仕方のないことですが、どういう経路を辿ってエラーになったのかを特定するのが割とツライ。

という訳で、vgsdrun というデバッグ用コマンドを作ってみました。
https://github.com/suzukiplan/vgs-cpu/pull/10

これでアセンブリ言語のソースを実行すると、以下のように実行経過の情報をズラズラと出力していきます。

$ ./vgsdrun src/test/asm_add_a.asm 
assembling: src/test/asm_add_a.asm on memory
starting debug run.
00000000: 08 E8 03               : line#00006 > LD   A, 1000
00000003: 5D 00                  : line#00007 > ADD  A, 0
00000005: A6 E8 03               : line#00008 > CMP  A, 1000
00000008: F8 02 01 00 00         : line#00009 > JNE  $102
0000000d: F5 02 01 00 00         : line#00010 > JZ   $102
00000012: 5D FF                  : line#00011 > ADD  A, 255
00000014: A6 E7 04               : line#00012 > CMP  A, 1255
00000017: F8 02 01 00 00         : line#00013 > JNE  $102
0000001c: F5 02 01 00 00         : line#00014 > JZ   $102
00000021: 5E 00 01               : line#00015 > ADD  A, 256
00000024: A6 E7 05               : line#00016 > CMP  A, 1511
00000027: F8 02 01 00 00         : line#00017 > JNE  $102
0000002c: F5 02 01 00 00         : line#00018 > JZ   $102
00000031: 5E FF FF               : line#00019 > ADD  A, 65535
00000034: A7 E6 05 01 00         : line#00020 > CMP  A, 67046
00000039: F8 02 01 00 00         : line#00021 > JNE  $102
0000003e: F5 02 01 00 00         : line#00022 > JZ   $102
00000043: 5F 00 00 01 00         : line#00023 > ADD  A, 65536
00000048: A7 E6 05 02 00         : line#00024 > CMP  A, 132582
0000004d: F8 02 01 00 00         : line#00025 > JNE  $102
00000052: F5 02 01 00 00         : line#00026 > JZ   $102
00000057: 5F 1A FA FD FF         : line#00027 > ADD  A, -132582
0000005c: F6 02 01 00 00         : line#00028 > JNZ  $102
00000061: 09 78 56 34 12         : line#00031 > LD   A, $12345678
00000066: 12 00 00 00 00         : line#00032 > ST   A, [0]
0000006b: 07 00                  : line#00033 > LD   A, 0
0000006d: 63 00 00 00 00         : line#00034 > ADD  A, [0]O
00000072: A5 78                  : line#00035 > CMP  A, $78
00000074: F8 02 01 00 00         : line#00036 > JNE  $102
00000079: F5 02 01 00 00         : line#00037 > JZ   $102
0000007e: 5F 88 FF FF FF         : line#00038 > ADD  A, -120
00000083: F6 02 01 00 00         : line#00039 > JNZ  $102
00000088: 64 00 00 00 00         : line#00040 > ADD  A, [0]H
0000008d: A6 78 56               : line#00041 > CMP  A, $5678
00000090: F8 02 01 00 00         : line#00042 > JNE  $102
00000095: F5 02 01 00 00         : line#00043 > JZ   $102
0000009a: 5F 88 A9 FF FF         : line#00044 > ADD  A, -22136
0000009f: F6 02 01 00 00         : line#00045 > JNZ  $102
000000a4: 65 00 00 00 00         : line#00046 > ADD  A, [0]
000000a9: A7 78 56 34 12         : line#00047 > CMP  A, $12345678
000000ae: F8 02 01 00 00         : line#00048 > JNE  $102
000000b3: F5 02 01 00 00         : line#00049 > JZ   $102
000000b8: 5F 88 A9 CB ED         : line#00050 > ADD  A, -305419896
000000bd: F6 02 01 00 00         : line#00051 > JNZ  $102
000000c2: 1E 00 00 11 11         : line#00054 > LD   B, $11110000
000000c7: 32 11 11               : line#00055 > LD   C, $00001111
000000ca: 48 11 11 11 11         : line#00056 > LD   D, $11111111
000000cf: 60                     : line#00057 > ADD  A, B
000000d0: A7 00 00 11 11         : line#00058 > CMP  A, $11110000
000000d5: F8 02 01 00 00         : line#00059 > JNE  $102
000000da: F5 02 01 00 00         : line#00060 > JZ   $102
000000df: 61                     : line#00061 > ADD  A, C
000000e0: A7 11 11 11 11         : line#00062 > CMP  A, $11111111
000000e5: F8 02 01 00 00         : line#00063 > JNE  $102
000000ea: F5 02 01 00 00         : line#00064 > JZ   $102
000000ef: 62                     : line#00065 > ADD  A, D
000000f0: A7 22 22 22 22         : line#00066 > CMP  A, $22222222
000000f5: F8 02 01 00 00         : line#00067 > JNE  $102
000000fa: F5 02 01 00 00         : line#00068 > JZ   $102
000000ff: 46 01                  : line#00070 > LD   D, 1
00000101: 00                     : line#00071 > BRK 

[registers]
c->r.a = 22222222, c->r.b = 11110000, c->r.c = 00001111, c->r.d = 00000001
c->r.p = 00000101, c->r.s = 00000000, c->f.z = 00000000, c->f.q = 00000000
$

最初は、普通のgdbやxdbなどと同じようなステップ実行コマンドを用意しようと思ったのですが、それを作ろうとするとディスアセンブラを作らなければならず、ディスアセンブラ自体、後々必要になるかもしれませんが、今のところ必要になりそうな気配が無い。

という訳で、vgs-asm と vgs-cpu のコードをベースにして簡単に作ってみたのが、このvgsdrun コマンドです。

仕組みは物凄く単純で、vgs-asmは行バッファという領域にオペコードに変換したデータを持っているので、その情報をvgs-cpuの命令実行サイクル時にコールバックしてプログラムレジスタから該当する行バッファの内容を表示してあげるというもの。

ディスアセンブラをガチで作ると多分2000行の開発コストが掛かりますが、この方式ならだいたい200行ぐらいの改造(要するに労力的には1/10の作業量)で作れました。

まぁ、こういう所で削っていかないと、いつまで経ってもモノが完成しないので。

今回のCPU開発(というかVGS mk-III開発)のゴールは、
1. CPU(vgs-cpu)を自作する
2. アセンブラ(vgs-asm)を自作する
3. VGS mk-III の SDK をWindows + Mac + Linuxでザックリ使えるレベルで仕上げる
4. Invader Block を VGS mk-III で作って何処かにリリース
という風に想定していて、現在はとりあえず1と2が一区切りついた段階です。
前記事で完成したと言いましたが、アレは初期目標段階に達した(マイルストーンをクリアした)という意味で、まだまだ実際にゲームを作るのには不足した機能が割とあります。

あまり最初から完璧なモノを仕上げるより、とりあえず次フェーズに進めそうな形にしておき、次フェーズを進めながら随時細かいエンハンスを繰り返していくという開発モデル(だいたいアジャイル)です。

2016年7月18日月曜日

vgs-cpuを完成させる

昨日書いた VGS-CPU + アセンブラ (VGS-ASM) を(とりあえず)完成させた。ただし、アセンブラの方は、まだ十分にテストしていないのでまだバグがあるかもしれません。(CPUの方にはバグはありません)
https://github.com/suzukiplan/vgs-cpu

命令セットの仕様的には、8086 と 6502 がごっちゃになった感じで、尚且つ32bit CPU という、一見するとカオスな感じでありながら、実際のところかなりアセンブリ言語でのコーディングがし易い形になっているのではないかと思います。

当初VGSオペランドという特殊命令を実装するつもりでしたが、それだと VGS-CPU の用途が狭まってしまう。元々、VGS用ゲーム開発専用のCPUを開発するつもりで作っていたので、それでも目的は外れていないのですが、VGS-CPUをベースにした亜種CPUを開発し易いようにするため、8086のINT命令相当のものを実装することにしました。

INT命令といえば、MS-DOSのサービスコール INT 21h とかよく使いましたね。

INT命令で実行される命令は、以下のように簡単に(最大256個)登録できます。

int hello_world(struct vgscpu_context *c)
{
    printf("HELLO, VGS-CPU");
    return 0;
}

int main()
{
    struct vgscpu_context *c = (struct vgscpu_context *)vgscpu_create_context();
    vgscpu_regist_interrupt(c, 0, hello_world);

VGS mark-III では、この割り込みの大半が VGS-API に割り当てる形になります。
INT命令を実装したことで、VGS-CPU と VGS-ASM の責務範囲は一通り実装できたことになるので、「だいたい完成した」といって良い状態ではないかと思います。

VGS-ASMの方は、まだまだ実装したい項目が盛り沢山ですが。
とりあえず、VGS-CPUの全ての命令セットを使用したコーディングができるという状態。

テストが通っているアセンブリ言語のサンプルソース:

/*
    PUSH/POP A の テストプログラム
 */
start:
    LD      A, $deadbeef
    PUSH    A
    PUSH    AH
    PUSH    AO

    POP     AO
    CMP     A, $ef
    JNE     test-failed

    POP     AH
    CMP     A, $beef
    JNE     test-failed

    POP     A
    CMP     A, $deadbeef
    JNE     test-failed

    LD      D, 1
    BRK

test-failed:
    LD      D, -1
    BRK

中々良い感じではないでしょうか。

今は MMM; main memory mapper という、フルアセでコーディングする上で一番厄介になる主記憶のメモリマッピングをアセンブリ言語で簡潔に表現できる仕組みを脳内で設計中。(あとはテストも書かないと)

2016年7月17日日曜日

vgs-cpuがひとまず完成(cpuは...)

5月からシコシコと作り続けていた vgs-cpu がついに完成。
https://github.com/suzukiplan/vgs-cpu
まだ、VGSオペランドで実行する命令は未着状態ですが

従来のVGS(mk-II SR)では、プログラムはC/C++のネイティブコードで記述していましたが、新しいVGSでは独自の仮想CPU用のネイティブコードでプログラムを記述していくスタイルにするつもりです。

そして、無事CPUエミュレータが(ほぼ)完成した訳ですが、現状では一応プログラムを書くことはできるものの、全てハンドアセンブルしなければならない状態なので、この状態でプログラミングするのは中々キツイ(できない訳ではないけど)。

誰でもゲームを作れるようにするにはアセンブラぐらいは必要だろうということで、今度はアセンブラをシコシコ作成中。
https://github.com/suzukiplan/vgs-cpu/pull/1

コンパイラ?

コンパイラは甘え

2016年7月12日火曜日

Travis CIでC言語プロジェクトの自動ビルド+テスト

vgs-cpuのLinuxでの自動ビルド+テストにTravis CIを導入してみました。
オープンソースなのでタダ乗りです。

README.md でよく見られる下図の「build passing」というバッジをクリックすれば、vgs-cpuをTravis CIでビルドしたログとかが見れたりします。
バッジ(build: passing)
ビルド+テストログが誰でも見れる
Web版のTravis CIで、C++やclangを利用したプロジェクトの場合、コンパイラのバージョン依存が結構あると思いますが、vgs-cpuならGCCバージョン2.96という枯れ切った規格に準拠した記述をしているので全く問題ありません。

(対応するためにやったこと)
・全てのビルドとテストの手順をmakeで書く(最初からそう書いている)
・GitHub上のアカウントの設定でTravis CIのWeb hookを許可
・Travis CIでアカウント連携
・対象プロジェクト(vgs-cpu)のトグルをON
・対象プロジェクト(vgs-cpu)に .travis.yml(内容は下記) を追加

script: 
  - make --no-print-directory test

・README.mdにバッジを表示する情報を追記

# [WIP] VGS CPU [![Build Status](https://travis-ci.org/suzukiplan/vgs-cpu.svg?branch=master)](https://travis-ci.org/suzukiplan/vgs-cpu)

これだけで、あとは master へ push なり Pull Request を merge するなりすれば、Travis CIがLinux(Ubuntu)でvgs-cpuのビルド&テスト(make test)を実行してくれます。

基本的に普段はMacでビルド+テストしているので、Linuxでのビルド&テストも放っておけば(というかpushすれば)勝手にやってくれるのは中々便利。

そうそう環境依存のバグを作り込むことは無いですが、一発仕掛ければ後は勝手にやってくれるのが良いですね。どちらかといえば、環境依存バグはWindowsで作り込み易いので、Windowsの似たようなCI(Platform SDKが使える)があれば尚良いのですが...

2016年7月3日日曜日

ランダム要素+ランキングシステムが秀逸なゲーム

私が最近はまっている Nuclear Throne というゲームを紹介します。(Nuclear Throneは日本語に直訳すれば、核の玉座という感じでしょうか)

Steamで売られていて、Windows, Mac, Linux に対応してます。
http://store.steampowered.com/app/242680/
あと日本で買えるかは分かりませんが、PS4とかでも売られているらしいです。

どのぐらい面白いのかというと、ソーシャル要素の無いオフラインゲームなのに、プレイ時間が100時間を超えてもなお飽きないぐらい面白いです。

Steamだとプレイ時間が測れるから良いですね。

ゲームの内容は、ライフ制の全方向スクロール・シューティングです。
シューティングとはいっても、ゼルダの伝説みたいな感じですが。
2つの武器を持つことができるので、それらを使い分けて敵を倒していきます。

ステージ構成は、全7ステージ(15エリア)で周回ループ有りです。
奇数ステージは通常3エリア。
偶数ステージは通常1エリアのみのショートステージ(ボス無し)。
奇数ステージのエリア3にはボスがいますが、1面はエリア1でボスが出てくることが稀にあります(倒せばそのままステージ2へ)。
7-3をクリアして一定条件を満たせば2週目(ステージ0)に入ります。

全ステージクリア(1周)に掛かる時間は15〜20分ぐらいです。
1周オールに掛かる時間の例(17分24秒)
上図の場合、隠しステージに一切寄らずにストレートに15エリアクリアしていますが、隠しステージがかなり豊富にあったりします。

例えば、3-1に1つだけある金縁の車をスクリュードライバーで叩くと、ゴールデン装備が手に入る隠しステージに行けたりとか。

ゴールデン装備とは、通常ゲームスタート時はピストルを持って開始しますが、ゴールデン装備を手に入れて有効な状態にすることができれば、それを初期装備とすることができます(ただし、dailyチャレンジの場合は使用不可)。

私は近接武器(レンチ、シャベル、ハンマーあたり)をメインに使っているので、ゴールデン・レンチが取れるまで結構粘りました。
ちなみに、このゲームで近接武器をメインで使う人は少数派かもしれません。マウス+キーボードでプレイする場合は飛び道具メインでプレイした方が面白いので。ただ、ゲームパッドでプレイする場合、飛び道具が使い難いので近接メインでプレイせざるを得ないかも。(攻撃をする時の入力が進行方向と逆に入れる必要があるというかなりクセのあるものなので)
このゲームの最大の特徴は、とにかくランダム要素が多いことです。

ステージの形状や敵の配置がランダム
どういう武器が拾えるかもランダム
回復アイテムが拾えるかどうかもランダム

近接武器をメインに使う私の場合、ステージ4に入るまで(3-3まで)にシャベルが拾えるか拾えないかで、難易度がかなり揺れます。
もっとも、私が初めて1周オールした時は、ハンマーもシャベルも拾えず、ゴールデン・レンチで Nuclear Throne を殴り壊しましたが。
初回クリア時のスクショ
ゴールデンレンチで殴り壊しました
1周目なら、装備よりもどちらかというと進化の方が重要かも。

一定量の緑のアイテムを集めてレベルが上がると特殊能力を追加できるのですが、これもどれが来るかはランダムです。
近接メインで攻める場合の最重要進化は、LONG ARMS(射程が伸びる)とGAMMA GUTS(体当たりでダメージを与える)で、ステージ4までにこれらの進化が出来たか出来なかったかで難易度がかなり変わってきます。
LONG ARMS
(最重要進化)
GAMMA GUTS
(下手な内は)結構重要な進化
更に、デスエンカみたいな敵も稀に出ます。
1面の黄色いサソリとか5面の黄色いロボとか。
黄色いサソリは良いですが、黄色いロボはヤバイ。
黄色いロボ
(恐らく1周目最恐のデスエンカ)
上図のように壁に隠れながら、EYESの敵を引き付ける特殊能力で誘導しつつ、近接武器(※近接武器の場合、壁を貫通して敵を攻撃できる)で殴り壊せば怖くないですが、そういう風にできるかどうかも運ですね。
やや広い地形に3体黄色いロボが居て、ハンマーヘッド(壁を壊せるようになる進化)も無かった時は、「あ、死んだな」って感じになります。

このゲームのランダム要素以外の特徴としては、日々クリアされるデイリーランキングでしょうか。

iOSとかのゲームセンターを使った事がある人なら分かると思いますが、有名どころのゲームのランキングというのは、一部の馬鹿な人がクラッキングして出した不正なスコアで上位ランキングが埋め尽くされているので、何も面白くありません。そんなクソランキングは、むしろ無い方が良いというのが、真にゲームを楽しみたい人にとっての共通認識ではないかと思います。

このNuclear Throneのランキングですが、1日1回しか挑戦できず、しかも毎日クリアされます。
在りし日のデイリーランキング(Global)
1日1回しか挑戦できないという成約は上手いですね。
継続プレイ率をかなり上げることが出来るのではないかと思います。
実際、毎日数千人のプレイヤーが競いあっています。
更に、デイリーでクリアされることから、チートでランキングを荒らす馬鹿も湧きにくいし、仮に湧いてもすぐにクリアされます。(まぁ、ボットで毎日送り続けるようにする阿呆も湧いてくるかもしれませんが、ゲームセンターと違って毎日送り続ける必要があるから、それは相当リスキーでしょう)

総括すると、Nuclear Throneは、
・適度なランダム要素で得られる新鮮なゲームプレイ
・チート対策で純粋にゲームで競いたい人にとって嬉しいランキングシステム
あたりが秀逸なゲームという感じでしょうか。

ちなみに、難易度は結構高めです。
近接メインでクリアするのは中級者向けで、あまりゲームが上手くない人は飛び道具メイン(キーボード+マウス)でプレイした方が無難です。飛び道具メインでプレイする人向けに参考になりそうな実況動画がニコニコ動画に上がってました。
http://www.nicovideo.jp/watch/sm27848106