今からコミケ合わせでGBAゲームを作ってみる(5)

タイトル→ゲームプレイ→ゲームオーバーという基本的なシーン遷移と、
ゲームルーチンの実装まで完了。
テキストベースだが一応遊べるように成った。

HSP と GameMarker:Studio というベースはあったけど、
じっくりと考察せず急ぎ実装してったもんだから、
良いトコ取りというより、例えるなら「キメラ」と言えばしっくり来るような、
そんな様相に仕上がってしまって辛い。

既に一刻も早くリファクタリングしたい衝動に駆られているが、
コミケまでもう2週間しか無いので後回し。

何とか絵と音まで乗っけて持って行きたいのう…。
(printf 画面だけじゃ何しているか分からないという反応を頂いたので。)

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ゲームを作ってみる(4)

まさかの風邪でノックダウン。
一日半ほど食っちゃ寝したら大分良くなったので製造フェーズへ移行。

元ネタのHSPソースとGameMarker:Studioプロジェクトを見つけたので、
チマチマC言語に翻訳している最中。

幸いにしてC標準ライブラリも多少は機能するようなので、
先にコンソールベースで動く所まで作ってしまいたいと思う。

別に間に合わなかった時の言い訳に使うつもりは無いけど、
…そうならないよう注意はしたい。

今からコミケ合わせで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

デスクトップPCが壊れたり。

しぶとく使っていたASUSマザーの自作PC
先月末でお亡くなりになった。

A8N-VM CSMなんて12年前の製品を
随分長いこと使っていたものだと我ながら感心する。

愛着とかそういうのでは無く、
安い買い物じゃないという辺りが継続利用の根本であり、
壊れるまで使い倒した原因とも言える。

そして目下の問題は、先々を考えなかった故の、
新しいマシンを手配するマネーが無いという現状だ。

スティックPCとかWinタブとか、
メイン機として微妙なラインナップはそこそこ有るので、
当面の急場は凌げそうだけども。

作業効率とかは著しく低下しそうだ。