ランダム関数†
本格的なゲームを作るにはランダム関数(乱数)が必要不可欠です。乱数といっても大まかに3種類に分類されていると思って構わないと思います。使い分けをすることによってゲーム全体の裏ハッタリ度がアップすることを願っています。
1.完全な乱数†
- 使用目的
言わずもがな、全く予測不能、乱数らしい乱数です。あらゆるギャンブル、あらゆる確率など。gccに使われるrand関数は精度がよくなく、インターネットで調べてみるとMT法が良いとされています。
- 生成方法
- 内蔵時計や(キー入力等でずらした)タイマーカウンタを見て、それを初期値とする。
- あとはキー入力待ちなどのループが起こるたびに、一定の計算法で乱数を生成。
2.完全パターンの擬似乱数†
- 使用目的
厳密に言うと乱数ではありませんが、同じアルゴリズムで生成されたものです。ザコを無造作に出したい。でも毎回パターンが違うと困る、というときに重宝します。ザコ敵の出現位置パターンなど。
- 生成方法
- 初期値は完全に固定とする。
- あとは乱数を必要とするたびに一定の計算法で乱数を生成。
3.初期設定のみ乱数で、あとは擬似乱数(一定パターン乱数)†
- 使用目的
一番分かりにくいのがこれです。しかし重要度は一番だと思います。1と2の複合型です。ある程度運の要素が絡むゲームにおけるリプレイ機能の再現、パスワードの生成・解読。
- 生成方法
- 内蔵時計やタイマーカウンタを見て、それを初期値とする。ただしこの値はどこかに保存しておく。
- あとは乱数を必要とするたびに一定の計算法で乱数を生成。
- リプレイ時に、保存していた値を初期値として再設定する。
MT法†
メルセンヌ・ツイスタ法の使用方法を以下に表します。基本的に中身には一切ふれず、関数の呼び出し名、引数の変更をしました。使用するときはライセンスの確認を怠らないでください。シード値はデフォルトで使用されている5489UL、テストの内容は0x0~0xfまでの値をひたすら生成してカウントアップさせています。
int main(void)
{
REG_WSCNT = 0x4317;
BgInit();
IrqInit();
RndInit(5489UL);
KeyInit();
char str[32];
u32 num[0x10];
_Memset(&num, 0x00, sizeof(num));
for(;;)
{
// VBlankIntrWait();
KeyExec();
// Stop
if(KeyGetCnt() & KEY_A)
{
continue;
}
num[RndU32() & 0xf]++;
for(s32 i=0; i<0x10; i++)
{
_Sprintf(str, "0x%x:%d", i, num[i]);
BgAsciiDrawStr(0, i, str);
}
}
}
動作画面†
参考リンク†
出典元†
- M-KAIさんの「Witchシューティングゲーム制作記帳」