シューティングゲームのように、様々な動きをする敵キャラを制御するプログラムを考える。例えば5種類の動きをする敵キャラを一定時間ごとにランダムに出現させ、最大50匹まで同時に出現するというプログラムを作る場合、敵キャラの情報を格納するキャラクタ構造体と、構造体配列は次のようになる。
#define ENEMY_MAX 50 /* ステータス情報構造体 */ typedef struct _STATUS { int type; // 敵の種類(0〜4の5種類) int x, y; // 表示座標 int mx, my; // 移動量 int life; // ライフ(0なら死亡) RECT rect; // 画像の矩形 RECT hitrect; // 当たり判定用の矩形 int width, height; // キャラクタの幅と高さ } STATUS; /* 敵キャラ制御用変数(配列) */ STATUS ENEMY[ENEMY_MAX];
- 敵の種類(type)によって、表示する画像と、ゲーム中の動きを変える。
このように作成した敵キャラ用構造体配列が、メモリ上でどれだけの容量を使うかを考える。
Windows環境では、各データ型で必要なサイズは次のとおりである。
#include <stdio.h> #include <windows.h> void main(void) { printf("char = %d byte\n", sizeof(char)); printf("int = %d byte\n", sizeof(int)); printf("long = %d byte\n", sizeof(long)); printf("float = %d byte\n", sizeof(float)); printf("double = %d byte\n", sizeof(double)); printf("RECT = %d byte\n", sizeof(RECT)); } char = 1 byteint = 4 bytelong = 4 byte float = 4 byte double = 8 byte RECT = 16 byte※Windowsは32ビットOSなので、int型は2バイトではなく4バイトで扱われる。
ENEMY構造体配列1つの大きさは、int型7つとRECT型2つで、計60バイトであり、50個の配列なので、合計3000バイトのメモリ容量を必要とすることが分かる。
ところがこの配列、よく見ると「無駄」があることに気がつく。それは、
敵の種類が同じなら、画像の矩形情報は同じになるため、キャラクタごとに矩形情報を持つ必要はないということである。
よって、この構造体は次のように分割すると、無駄が省ける。
#define ENEMY_MAX 50 #define ENEMY_TYPE_MAX 5 /* ステータス情報構造体 */ typedef struct _STATUS { int type; // 敵の種類(0〜4の5種類) int x, y; // 表示座標 int mx, my; // 移動量 int life; // ライフ(0なら死亡) } STATUS; /* 矩形情報構造体 */ typedef struct _BLTSTATUS { RECT rect; // 画像の矩形 RECT hitrect; // 当たり判定用の矩形 int width, height; // キャラクタの幅と高さ } BLTSTATUS; /* 敵キャラ制御用変数(配列) */ STATUS ENEMY[ENEMY_MAX]; /* 敵キャラ描画用変数(配列) */ BLTSTATUS ENEMY_BLT[ENEMY_BLT_MAX];このように作成すると、矩形情報が敵キャラの種類の数(5つ)ですむため、メモリ使用量が減ることが分かる。
int型6つ = 24バイト
RECT型2つ + int型2つ = 32 + 8 = 40バイト
24×50 + 40×5 = 1400バイト※構造体1つの場合は3000バイト必要だったので、1600バイト節約できた
※配列の個数が多くなっても、敵の種類が増えなければ24バイトずつしか増えない
敵キャラ情報を2つに分けたため、使い方が若干変わる。どのように使えばいいかを簡単に紹介する。
《初期化》
// 敵キャラ情報初期化 for (i=0 ; i<ENEMY_MAX ; i++) { 敵キャラの数分(50個)、ライフを0クリアする } // 敵キャラ画像情報初期化 for (i=0 ; i<ENEMY_BLT_MAX ; i++) { タイプ別(5個)に矩形、あたり判定用矩形をセットする }《移動処理》
for (i=0 ; i<ENEMY_MAX; i++) { ENEMY[i].x += ENEMY[i].mx; ENEMY[i].y += ENEMY[i].my; }《描画処理》
for (i=0 ; i<ENEMY_MAX ; i++) { hRet = g_pDDSBack->BltFast(ENEMY[i].x, ENEMY[i].y, g_pDDSChara,&ENEMY_BLT[ENEMY[i].type], DDBLTFAST_SRCCOLORKEY); if (hRet != DD_OK) return; }
5−3までに作成したプログラムを改造する。ゴキブリを3匹以上表示し、適当に動き続けるようプログラムを修正しなさい。ただし、ステータス構造体をステータス用と描画用の2つに分割し、ゴキブリステータス用構造体変数は3つ以上の配列、ゴキブリBLT用構造体変数は1つで作成しなさい。
敵キャラとして、ゴキブリ以外のキャラクタをもう1種類追加しなさい。敵キャラ描画用構造体変数は2つの配列となる。