2012年5月5日土曜日

NO・KO・GI Rider(体験版)完成

開発中のSTG「SHOT04 - NO・KO・GI Rider」の体験版がほぼ完成しました。
タイトルは正式に「NO・KO・GI Rider」にしてしまいました。

このタイトルから、「バトライダーのパクリゲーか?」と期待されるマニアな方のために補足すると、バトライダー的な要素は全くありません。ただし、1面のボスが戦車で、バック走行しながら戦い、オプション破壊するとワッショイな辺りは、インスパイアされていると言えなくもないかもしれませんが。(このタイトルの正式な由来は、以前ブログで書いたような気がするので、詳細は過去ログ参照です)

現在、リリースに向けた最終テスト中です。
完了次第、Google Playで配布開始します。
何とか、目標通り、GW中に体験版をリリースできそうです。
GWなど無かった・・・。

一応、タイトルに「SHOT04」と冠を付けておきました。
前作(SHOT03)との関連性は皆無&SHOTxxシリーズの知名度もほぼ無いのですが、念のため。
SHOT02は、VectorでPickupされたり、雑誌に載ったりしたお陰で、若干沢山出回ったので、もしかすると覚えていてくれる人が居ないとも限らないですし。(ちなみに「沢山」といってもVectorでのDL数は精々2,000本程度)

製品版の完成は・・・2012年中が目標です。
とりあえず、今年は夏休みが長い(というより2回ある)ので、夏が勝負。
できれば、夏頃に完成させたいところ。


追記:
いま、アップロードする作業が終わりました。
明日の昼頃には、GooglePlayで「suzukiplan」で検索すれば見つかると思いますので、是非。


なんとかGW中に間に合った・・・と、思ったら明日(時刻的には今日)も休みか。
明日はジックリとiPod touchの怒首領蜂を堪能します。
ちなみに、(Android版は対応していなくて買えなかった)大復活も買ってみました。
大復活が出た当時、ゲーセンに行ってなかった(というより、横浜ではシューティングができるゲーセンが無いに等しい)ので、ほぼ初プレイ。最大往生もその内出るのかな?できればゲーセンでやりたいけど、例の如く、横浜には皆無らしい。





追記2:
今、GooglePlayをチェックしたところ、もうアップされているようでした。
とりあえず、私のスマホにも、GooglePlayからダウンロードして入れてみました。
販売しているアプリの場合、GooglePlayからインストールすることはできない(自分のものを自分で購入することはGoogleCheckoutのポリシー違反なようで、ブロックされる)のですが、無料で配っているアプリの場合、問題無いようです。

2012年5月4日金曜日

VGS version up(1.01)

http://suzukiplan.blogspot.jp/2012/05/blog-post_476.html
上記記事の対策を施したVGSをアップしました。

InvaderBlockは昨日の内に早々とアップできたのですが、VGSの方は1曲追加して出したので、曲を作るのに時間が掛かり、予定(昨日中)よりも0.5日程度遅れましたが、ギリギリセーフか。

これで大往生に専念できる・・・と、思ったら、体験版を作成する作業をやらなければ・・・
しかし、コレ(大往生)が450円というのは、ちょっと微妙な気分。安過ぎる。
大往生なら700円だろうが、3000円だろうが買うつもりだったんですが。

課金アイテムを販売しているのが値段のカラクリ?
本体は激安or無料にして、課金アイテムで利益を得るという手法は、STGでは微妙な気がしますが。
課金でエキストラステージみたいなものが追加されるのなら買うかもしれませんが。

iPod touch購入

iPod touchを購入。

というのも、iPod touchがあれば大往生ができるらしいので・・・で、大往生も購入。
将来的には、開発中のSTGをiPhone/iPod touchに移植するので必要なんですが、当面は大往生用。

とりあえず、Normalでやったら初見で1周できてしまったので、「こんな楽だったか?」と思いましたが、Endingの後、Hardじゃないと2周目にいけないっぽいことを言われたので、通常モード=Hard以降らしい。なるほど。

ちなみに、使用機種はTypeA/レイニャン(レーザー強化)。
無印の怒首領蜂の頃からTypeA・レーザー強化一筋です。
正確には、無印をやり始めの頃はTypeBでしたが、TypeA(ショットが散らばらないで真っ直ぐ飛ぶ)の方がパターンが組み易くて楽です。(レーザー強化にしているのは、ショットが弱いから、コンボを繋ぎ易いため)

iPod版だと、アーケードみたいにショットとレーザーの切り替えが楽ではないのが難点。
ただ、レバーよりも移動に関しては高速にできるので、TypeA+レーザーなら終始レーザーだけで問題無いっぽい。
コンボを繋ぐのにはショットが必要ですが・・・

2012年5月3日木曜日

強制停止になる原因

ようやく、ソースが触れる環境に帰ってきました。
で、早速エラーレポートで報告されている事案の調査をしました。

ちなみに、落ちたクラス(VgeSurfaceView)のソースは↓のような感じ。
/*
*------------------------------------------------------------------------
* メインループ (スレッド)
*------------------------------------------------------------------------
*/
@Override
public void run() {
SurfaceHolder holder=getHolder();
Canvas canvas;
while (isAttached) {
// 仮想VRAMへの描画処理
PSGTEST.setVram(vram);
// 仮想VRAMを実VRAMへ転送
canvas=holder.lockCanvas();
canvas.drawBitmap(vram,vramRect,screenRect,screenPaint);
holder.unlockCanvasAndPost(canvas);
}
}

赤い網掛け部分がNullPointerExceptionが発生した部分。
なので、青い網掛け(lockCanvas)がnullを返したことが原因。

Android SDKのマニュアルを読んでいたら、妙な記述を発見。(以下、抜粋)
If you call this repeatedly when the Surface is not ready (before Callback.surfaceCreated or after Callback.surfaceDestroyed), your calls will be throttled to a slow rate in order to avoid consuming CPU.

上記を逆説すれば、「リトライは必要」ということ。
(ついでに、リトライ時にsleepをしなくてもハングにはならないらしい)

なので、以下のように修正すればOKかな。
Invader BlockとVGE Chiptune Musicの両方に下記の対策を入れて、本日中にリリース予定です。
public void run() {
SurfaceHolder holder=getHolder();
Canvas canvas;
while (isAttached) {
// 仮想VRAMへの描画処理
IBLOCK.setVram(vram);
// 仮想VRAMを実VRAMへ転送
canvas=holder.lockCanvas();
while(null==canvas && isAttached) canvas=holder.lockCanvas();
if(null==canvas) break;
canvas.drawBitmap(vram,vramRect,screenRect,screenPaint);
holder.unlockCanvasAndPost(canvas);
}
}
修正ポイント:
・リトライ要の場合、リトライ(Destroy時は中断して抜ける)
・リトライ中にDestroyになった場合はスレッド停止

久々にAndroidアプリ開発っぽい内容の記事でした。

初エラーレポート

VGS Chiptune musicがいつの間にやら100DL超えてました。
コメントを見る限り、私の音楽自体が好評みたいで、うれしい限りです。
ありがとうございます。

そして、初めてエラーレポートを1件頂きました。
Javaソース部分でSurfaceViewの使い方にマズイところがあるようです。
マズイですね、これは。
たぶん、Invader Blockの方にも同件の問題がありそう。
今日の夜には、調査&対策したいと思います。

本当は、今から即効で対策したいところですが、Javaソースの入った開発環境には夜にならないと触れない・・・お出かけ環境にJavaソースを持ってくるのを失念してました。ソースが無くてもある程度推理できますが。
・SurfaceViewのrunで落ちている(NullPointerException)
・SurfaceViewのrunでやっていること
 (1) VGEのグラフィック更新(JNI)→AndroidBitmap作成
 (2) Canvasをlockし、AndroidBitmapを書き込み、unlock
で、NullPointerExceptionになるということは、(2)に問題がある可能性が高い筈。
SurfaceHolder.getHolderで取得したホルダーのインスタンスを、スレッド生存中に使い回しているのがマズイのかな?(ソースを見ていないから、ハズレの可能性も高いですが)
 
しかし、ソースを難読化しなかったお陰で、Java部分でバグがあればすぐに分かって便利。
Javaソースは全体の1%に満たない(99%はCでできている)から、仮に解読されても問題ありません。

1面完成

1面がとりあえず一通り完成。
現状、ステージ後半とボスが成分未調整で、かなり鬼畜な難易度です。
最高難度はこれぐらいでちょうど良いかも。
1面から飛ばし過ぎじゃないか?と思いましたが、最高難度は全面そんな感じであれば。。

しかし、低難度(Easy/Normal)はもっと調整が必要。
ちなみに、難易度はEasy/Normal/Hardの3種類。
ただ、Easy/Normal/Hardという呼び名が気に入らなかったので、
Beginner = Easy
Soldier = Normal
Ninja = Hard
という感じにしました。

東方の難易度に置き換えると、

Beginner = EasyとNormalの中間
Soldier = NormalとHardの中間
Ninja = HardとLunaticの中間
ぐらいのイメージ。
いわゆる弾幕STGではないから、一概に比べることはできませんが。


あと、細かいバグが未対策だったり、エフェクトを付けてない部分も多々あります。
システムも未だノータッチの部分も多数(スコアとかクリアとかコンティニューとか・・・)。
体験版(1面のみ)の完成はまだ遠い。
GW中に体験版が出せるかどうかは、依然として微妙。

2012年5月2日水曜日

αブレンド

自作ゲームエンジン(VGE)に、αブレンド機能を入れようかどうか、迷い中。
とりあえず、
(1)スプライトを特定の色でマスクする機能
(2)スプライトを1/2に縮小表示する機能
を追加で実装。

これらを準備することで、例えば、敵に弾が当たった時の点滅は(1)、空中の機体の影の表示は(1)+(2)という感じで機械的に作成することができます。(当初、ダメージパターンと影パターンをパーツ別に準備していました...)

影の表示は、2フレームの1回の間隔で影パターンを表示して半透明表示を実現しています。
つまり、錯覚を利用してます。
αブレンド(要するに透過表示機能ですね)を実装すれば、毎フレーム描画が可能。

ただ、毎フレーム描画するメリットといえば、画面のスナップショットを撮るのに失敗するのが無くなる以外にどんなメリットがあるのかと、考えると微妙過ぎて実装する気が起きない・・・という訳です。
決定的なメリットがあれば、頑張って実装すれば良いのですが。

逆に、αブレンドを実装しないメリットとしては、処理性能が良いということ。
αブレンドは色素(RGB)毎に平均値を取得する必要があるので若干重い。
ただし、平均値算出に要する演算処理は、αブレンドの方式にもよりけりですが、最もシンプルな方式であればAND演算、ADD演算、SHIFT演算だけ(=一般的なCPUで処理コストが軽い部類の命令だけ)だし、αブレンド対応に伴う追加の分岐も発生しないから、パイプラインとの相性も良いです。なので、必要最小限に絞って使うようにすれば、性能面でのデメリットはほぼ生じない気もしますが。

使う or 使わないは別にして、とりあえず実装してみるのが吉な気がします。
ただ、Android用のエンジンにも手を入れなければ作れない(Android用のエンジンは16bitカラー、Windows用のエンジンは24bitカラーという違いがある)から、面倒なので、とりあえず後回しで。

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

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