今からコミケ合わせでGBAゲームを作ってみる(5)
タイトル→ゲームプレイ→ゲームオーバーという基本的なシーン遷移と、
ゲームルーチンの実装まで完了。
テキストベースだが一応遊べるように成った。
HSP と GameMarker:Studio というベースはあったけど、
じっくりと考察せず急ぎ実装してったもんだから、
良いトコ取りというより、例えるなら「キメラ」と言えばしっくり来るような、
そんな様相に仕上がってしまって辛い。
既に一刻も早くリファクタリングしたい衝動に駆られているが、
コミケまでもう2週間しか無いので後回し。
何とか絵と音まで乗っけて持って行きたいのう…。
(printf 画面だけじゃ何しているか分からないという反応を頂いたので。)
最近垂れ流している作業用BGM
The End of Evangelion - Sohryu Asuka Langley vs Eva Series 60fps FI - sub ESP ENG
www.youtube.com
初見の動画とか見入っちゃうんで適当に知っているのをチョイス。
devkitPro の libgba キー入力ライブラリの備忘とか
libgba のキー入力ライブラリは scanKeys 関数でキーデータ更新後、
keysUp、keysDown、keysDownRepeat 関数で入力情報を 1 度取得すると、
2 回目以降値を返してくれなくなる。
libnds 使って DS 開発してた頃も確かそういう動きだったなーと思い
ソースコード見てみたら案の定だった。
関数内で値を返しつつ 0 でクリアしていやがる。
但し、keysHeld だけは何故か値クリアされていない。
for (;;) { VBlankIntrWait(); scanKeys(); if (keysDown() & KEY_A) { iprintf("INPUT A"); } if (keysDown() & KEY_B) { iprintf("INPUT B"); } }
この場合 A ボタンの入力には反応するが
B ボタンの入力には反応しない。
なので、押したときや離したときを複数回評価したいなら
一度変数に入れてから作業することになる。
for (;;) { VBlankIntrWait(); scanKeys(); off = keysUp(); trg = keysDown(); rep = keysDownRepeat(); if (trg & KEY_A) { iprintf("INPUT A"); } if (trg & KEY_B) { iprintf("INPUT B"); } }
なお、keysUp、keysDown、keysDownRepeat の戻り値はそれぞれ別なので、
3 つの変数を用意して scanKeys で更新の度に取得しておくと
必要なとき最新のデータが手に入って何かと便利。
という事で、とりあえずライブラリ化してみたものが以下。
id:akkera102さんの key.h, key.c をリスペクト(汗)。
中身は libgba と C 標準ライブラリで実装。
…実を言うとakkeraさんのサンプルプログラムから
こそーり借用しようかと思ったけど
如何せん key.h, key.c 以外のインクルードは増やしたくなかったので
結局お借りしないでポーティングという手段を取った。
key.h
#ifndef KEY_H #define KEY_H #ifdef __cplusplus extern "C" { #endif //共通ヘッダを記述 #include <gba_types.h> #include <gba_input.h> //--------------------------------------------------------------------------- //定数を記述 #define KEY_REPEAT_CNT 30 #define KEY_REPEAT_DLY 60 //--------------------------------------------------------------------------- //構造体を記述 typedef struct { u32 cnt; // 現在のキー u32 trg; // 押されたキー u32 off; // 離されたキー u32 rep; // リピートキー } ST_KEY; //--------------------------------------------------------------------------- //プロトタイプ宣言を記述 void KeyInit(void); void KeyExec(void); u32 KeyGetCnt(void); u32 KeyGetTrg(void); u32 KeyGetOff(void); u32 KeyGetRep(void); #ifdef __cplusplus } #endif #endif
key.c
//ヘッダを記述 #include "key.h" #include <string.h> //--------------------------------------------------------------------------- //構造体変数宣言を記述 ST_KEY Key; //--------------------------------------------------------------------------- void KeyInit(void) { //初期化処理を記述 memset(&Key, 0x00, sizeof(ST_KEY)); setRepeat(KEY_REPEAT_DLY, KEY_REPEAT_CNT); } //--------------------------------------------------------------------------- // vblank中に1回だけ呼び出します(チャタリング防止) void KeyExec(void) { //主処理を記述 scanKeys(); Key.cnt = keysHeld(); Key.trg = keysDown(); Key.off = keysUp(); Key.rep = keysDownRepeat(); } //--------------------------------------------------------------------------- // 現在押されているボタン u32 KeyGetCnt(void) { return Key.cnt; } //--------------------------------------------------------------------------- // 押された時のボタン u32 KeyGetTrg(void) { return Key.trg; } //--------------------------------------------------------------------------- // 離された時のボタン u32 KeyGetOff(void) { return Key.off; } //--------------------------------------------------------------------------- // キーリピートのボタン u32 KeyGetRep(void) { return Key.rep; }
今からコミケ合わせでGBAゲームを作ってみる(3)
画面デザインとリソース準備を主に。
久しぶりにペイントソフトを触った気がする。
作業内容。
・8x8フォントの作成(目コピー) ・背景リソースの減色とリサイズ、リサンプル ・GBA解像度に合わせて画面デザイン・配置など再考
また、GBAで実現するに辺り仕様を以下のように仮決め。
・画面描画はMODE 0を使用 ・背景(タイトル、ゲーム中、フォント)は256色1パレットとしBG2枚構成とする (ビットマップモードは描画ライブラリでも用意しない限り不便なので) ・スプライトは16色1パレットの64x32サイズで1オブジェクトとして複数表示する
スプライトの管理方法については積み残し。
複雑な事を求めている訳じゃないので多分難航しないとは思うけど。
今からコミケ合わせでGBAゲームを作ってみる(2)
GBA開発の現状についてざっくり調べてみた。
以下は、過去にlibndsを用いてDS Homebrewを少しだけ齧った人間の感想。
・libgbaはlibndsほど整備がされないまま更新が止まっている ・有用なexampleが殆ど無いのと、そもそも提供されているexample自体が少ない ・基本処理に至っては開発者が各々GBA仕様を元にスクラッチ開発している ・よって定番機能が統一化されていない (スプライト・BG表示、サウンド再生など) ・C標準ライブラリの対応状況は不明。というか未見 (今回開発するタイトルに関しては余り重要じゃない。 気にするのはメモリ周りくらい?)
今から約1か月で完成させる想定だと、
先人同様ライブラリ整備から始めていたのでは間に合わないので、
基本処理はネットの解説サンプルを参考に構築していって、
深い理解は後に回す、という方針が現実的な落としどころか。
今からコミケ合わせでGBAゲームを作ってみる(1)
今年は国内Homebrew界隈でGB/GBA開発がお盛んな様子で。
年始は自分もコンシューマ機向けに
一丁作ったろうかって息巻いていたが、
色々やりたい事とか目移りしてるうちに
気付けば成果も無いまま11月もあと僅かとなっていて。
過ぎた日は取り戻せないけど、
せめて1本何か作って、活動実績を残しておきたいと思う。
今更、今からGBAと言われそうだが気にせず頑張る。
で、この開発における個人的な目的や狙いはこんな感じ。
(動機付けとも言う。)
・GBAで何か作る ・一部でカルトな人気を誇る(?)某ゲームの移植(To Heartではない) ・コミケにakkera102さんが来るらしいので
言うのは容易いがちゃんと完成に至れるのか正直未知数ってなくらい
モチベーションの持続が下手糞になってる自分に失望を覚えつつ、
取り合えず開発環境を構築する所から始めてみたい。
・インストールしたもの
・開発環境 ・devkitPro ・エミュレータ ・VisualBoyAdvance ・グラフィック ・EDGE ・mspaint(WindowsXP 32bit版) ・IrFanView32 ・PhotoShop CS2 ・YY-CHR ・grit (bmp/png画像コンバート、devkitProに含まれている) ・サウンド ・SOX (WAV→RAW変換)
バージョン管理を始めてみる。
主に仕事プログラム(エクセルマクロ)での、
保守とかバージョンアップとか、
移動中スマホのDropboxからソースが見れないとか諸々あって、
ついでに言うとフォルダバージョン管理に嫌気が差して来たので、
Git と SourceTree を導入。
わかばちゃんと学ぶGit使い方入門って本読んで、
やっと有用性を知れたところ。
食わず嫌いも大概にせえよと。
robocopy コマンドで簡易バックアップの仕組みを用意する
先週末にメインで使っていたPCが大破。
微妙なマシンは幾らか有していた為、
そのうちのスティックPCで暫しの間過ごす事に。
データ関連は外付け USB HDD への保存を基本としていたので
移行作業自体は接続の変更だけで終了したのだが、
タスク登録していたバックアップバッチはシステムドライブ上に在り
直ぐ取り出す事も侭ならず、仕方ないので書き直すことにした。
書き直すとは言っても、実際のところ今までのバッチが
融通聞かない代物だったので、リファインの切っ掛けとしては
丁度良かった気もする。
想定する利用シーンに基づき、2 つの実行ウィザードと
1 つの実行バッチを追加。
前に書いたものよりかは大分マシなものになったと思う。
実際のスクリプトは以下。
俺俺感ぱないけど、何かの参考になれば幸いである。
(1)バッチ HDD バックアップ
設定ファイルに記述されたドライブに対してバックアップ処理を実行。
BatchHDDBackup.bat
@echo off set cfg_name=%~n0 set cfg_ext=.ini set cfg_file=%cfg_name%%cfg_ext% if not exist "%cfg_file%" ( echo コンフィグファイル %cfg_file% が見つかりません。 echo ; %cfg_name% configuration>%cfg_file% echo [directory]>>%cfg_file% echo src=>>%cfg_file% echo dst=>>%cfg_file% echo コンフィグファイル %cfg_file% を作成しました。 echo; echo 'src=' 以降にバックアップ元ドライブまたはフォルダを、 echo 'dst=' 以降にバックアップ先ドライブまたはフォルダを、 echo フルパスで指定してください。 echo; echo なお、パスの指定に前後「"」または末尾「\」を含めないでください。 echo 上記記号が混入してると正しく動作しません。 echo; echo 例:) echo src=Z: echo dst=Y: echo; exit /b ) rem コンフィグファイル %cfg_file% は既に存在します。 rem バックアップ元ドライブ for /f "eol=; tokens=1* delims==" %%a in ('find "src" %cfg_file%') do (set src=%%b) rem バックアップ先ドライブ for /f "eol=; tokens=1* delims==" %%a in ('find "dst" %cfg_file%') do (set dst=%%b) call HDDBackup.bat "%src%" "%dst%" exit /b
BatchHDDBackup.ini
; BatchHDDBackup configuration [directory] src=Z: dst=Y:
タスクスケジューラに登録して定期実行することを想定。
壊れた PC で主に利用していた動作。
(2)カレント HDD バックアップ
カレントドライブを元、選択したドライブを先としてバックアップ処理を実行。
CurrentHDDBackup.bat
@echo off set src=%~d0 echo カレントドライブ %src% をバックアップします。 vol %src% echo; set dst=0 set /p dst="バックアップ先ドライブを入力してください . . . " rem 指定されたドライブが見つかりません。 set is_exist=0 for /f "usebackq tokens=*" %%i in (`vol %dst% ^| find "ラベル" /C`) do (set is_exist=%%i) if %is_exist%==0 goto END vol %dst% echo; set yesno=n set /p yesno="バックアップを開始しますか?(y/n) . . . " if not "%yesno:y=y%"=="y" goto END call HDDBackup.bat "%src%" "%dst%" echo; echo バックアップが終了しました。 pause exit /b :END echo; echo バックアップを中止しました。 pause exit /b
今回一番欲しかったもの。別 PC にドライブを移した際、
即時使えるものを求めていた。
こいつがメイン、バックアップの両方に入っていれば
仮に一方が壊れた場合でも、新調したドライブへのリストアが容易に行えるって寸法。
(3)セレクト HDD バックアップ
始めに選択したドライブを元、後に選択したドライブを先としてバックアップ処理を実行。
SelectHDDBackup.bat
@echo off echo 選択したドライブをバックアップします。 echo; set src=0 set /p src="バックアップ元ドライブを入力してください . . . " rem 指定されたドライブが見つかりません。 set is_exist=0 for /f "usebackq tokens=*" %%i in (`vol %src% ^| find "ラベル" /C`) do (set is_exist=%%i) if %is_exist%==0 goto END vol %src% echo; set dst=0 set /p dst="バックアップ先ドライブを入力してください . . . " rem 指定されたドライブが見つかりません。 set is_exist=0 for /f "usebackq tokens=*" %%i in (`vol %dst% ^| find "ラベル" /C`) do (set is_exist=%%i) if %is_exist%==0 goto END vol %dst% echo; set yesno=n set /p yesno="バックアップを開始しますか?(y/n) . . . " if not "%yesno:y=y%"=="y" goto END call HDDBackup.bat "%src%" "%dst%" echo; echo バックアップが終了しました。 pause exit /b :END echo; echo バックアップを中止しました。 pause exit /b
カレントバックアップのついでに書いたもの。
過去何回かメインデータの方を誤って削除して、
その度にリストアで不便を伴っていたのも事実なので、
有るに越したことはないと思う。
(4)HDD バックアップ
処理本体。robocopy コマンドでバックアップ処理を実行。
HDDBackup.bat
@echo off rem バックアップ元ドライブ if "%~1"=="" goto END set src=%~1 rem バックアップ先ドライブ if "%~2"=="" goto END set dst=%~2 set root_dir=Regekatsu set sub_dir=Backup set log_dir=log set save_dir=%SystemDrive%\%root_dir%\%sub_dir%\%log_dir% md "%save_dir%" set dt=%date% set tm=%time% set dt=%dt:~0,4%-%dt:~5,2%-%dt:~8,2% set tm=%tm:~0,2%-%tm:~3,2%-%tm:~6,2% set tm=%tm: =0% set log_dttm=%dt%_%tm% set log_prefix=Backup_ set log_ext=.log set log_file="%save_dir%\%log_prefix%%log_dttm%%log_ext%" setlocal cd \ robocopy "%src%" "%dst%" /MIR /R:0 /W:0 /LOG:"%log_file%" /NP /NDL /TEE endlocal exit /b :END echo usage: %~nx0% バックアップ元ドライブ バックアップ先ドライブ exit /b
実行ログの保存先。これは決め打ち。
%SystemDrive%\Regekatsu\Backup\log