キャラクタ用構造体変数の作り方と使い方

キャラクタ構造体を作成したら、その構造体の型を持つ構造体変数を宣言し、利用する。ここでは、キャラクタ構造体変数の宣言と使用方法を学ぶ。

キャラクタ構造体の宣言

キャラクタ構造体は、様々なソース・ファイルから利用される。よって、共通ヘッダ・ファイル「NKC_Common.h」に宣言するのがベストである。(1)でダウンロードしたプログラムを次のように修正する。

//-----------------------------------------------------------------------------
// 共通ヘッダ・ファイル
//  Copyright NKC Game Staff(←自分の名前) 
//-----------------------------------------------------------------------------
・
・
・

// 構造体宣言
/* 頂点構造体 */
typedef struct tag_dx_TLVERTEX {
    float           x, y, z;                //位置情報
    float           rhw;                    //頂点変換値
    D3DCOLOR        color;                  //頂点カラー
    float           tu, tv;                 //テクスチャ座標
}TLVERTX, *LPTLVERTEX;
/* キャラクタ情報構造体 */
typedef struct _STATUS {
    TLVERTX Vertex[4];                      // 頂点情報配列
    RECT HitRect;                           // 当たり判定矩形情報
    float MoveX, MoveY;                     // 移動量
} STATUS, *LPSTATUS;

《POINT》

キャラクタ構造体の型を持つ構造体変数の宣言

作成したキャラクタ構造体を使って、自キャラのデータを管理してみる。自キャラに必要なデータ(グローバル変数)はすべてキャラクタ構造体に存在するため、次のようになる。

//=============================================================================
//  ゲーム処理関係の自作関数群
//  Copyright NKC Game Staff(←自分の名前) 
//-----------------------------------------------------------------------------
#include "NKC_Common.h"

// グローバル変数
/* 自ソースでのみ利用するもの */
//---- 背景
static TLVERTX BackVertex[4];       // 頂点情報配列
//---- 自機
static STATUS MyChara;              // 自キャラステータス情報
//---- 敵
static TLVERTX EnemyVertex[4];      // 頂点情報配列
static RECT EnemyHitRect;           // 当たり判定矩形
static float EnemyMoveX, EnemyMoveY; // 移動量

《POINT》

キャラクタ構造体を使ったプログラミング

先のように自キャラ情報を構造体変数で管理する場合、プログラムは次のようになる。

自キャラ情報の初期化(GameInit関数)

//-----------------------------------------------------------------------------
// 関数名 : GameInit()
// 機能概要: ゲーム画面初期化処理
//-----------------------------------------------------------------------------
void GameInit(void)
{
    //--------------------------------------------------- 各変数の初期化
    // ゲーム画面で使用するテクスチャの作成
    CreateGameTexture();
    // ポリゴンの初期化
    /* 背景 */
    InitVertex(BackVertex, (float)gl_rcScreen.left, (float)gl_rcScreen.top, (float)gl_rcScreen.right, (float)gl_rcScreen.bottom, 255); // 頂点データ
    /* 自機 */
    InitVertex(MyChara.Vertex, 100.0f, 100.0f, 164.0f, 164.0f, 255); // 頂点データ
    SetRect(&MyChara.HitRect, 10, 15, 10, 15);                       // 当たり判定矩形
    MyChara.MoveX = 2.0f;
    MyChara.MoveY = 2.0f;
    /* 敵 */
    InitVertex(EnemyVertex, 400.0f, 300.0f, 496.0f, 396.0f, 255); // 頂点データ
    SetRect(&EnemyHitRect, 10, 15, 10, 15);                       // 当たり判定矩形
    EnemyMoveX = 0.0f;
    EnemyMoveY = 0.0f;

    //--------------------------------------------------- フレームナンバーセット
    g_FrameNo = GAME_FRAME;

}

自キャラの描画・移動・当たり判定(GameFrame関数)

//-----------------------------------------------------------------------------
// 関数名 : GameFrame()
// 機能概要: ゲーム画面処理
//-----------------------------------------------------------------------------
void GameFrame(void)
{
    float mx, my;  // 移動量

    /* 描画処理 */
    // 背景を描画
    gl_lpD3ddev->SetTexture(0, gl_TXBack);
    gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, BackVertex, sizeof(TLVERTX));
    // 自機を描画
    gl_lpD3ddev->SetTexture(0, gl_TXMyChara);
    gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, MyChara.Vertex, sizeof(TLVERTX));
    // 敵を描画
    gl_lpD3ddev->SetTexture(0, gl_TXEnemy);
    gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, EnemyVertex, sizeof(TLVERTX));

    /* 移動処理 */
    // 自機の移動
    mx = my = 0.0f;
    if ( gl_KeyTbl[VK_LEFT] & 0x80 )  mx = -MyChara.MoveX;
    if ( gl_KeyTbl[VK_UP] & 0x80 )    my = -MyChara.MoveY;
    if ( gl_KeyTbl[VK_RIGHT] & 0x80 ) mx =  MyChara.MoveX;
    if ( gl_KeyTbl[VK_DOWN] & 0x80 )  my =  MyChara.MoveY;
    Move(MyChara.Vertex, mx, my);

    /* 指定範囲を超えないようにする */
    MoveCheck(gl_rcScreen, MyChara.Vertex);

    /* 当たり判定 */
    if ( HitCheck2(MyChara.Vertex, MyChara.HitRect, EnemyVertex, EnemyHitRect) ) {
        ReleaseGameTexture();
        g_FrameNo = START_INIT;
    }

    // F1が押されたら、スタート画面に戻る(デバッグ用)
    if ( gl_KeyTbl[VK_F1] & 0x80 ) {
        ReleaseGameTexture();
        g_FrameNo = START_INIT;
    }

}

※以上の修正を行ったらプログラムをビルド・実行し、正常に動くことを確認しよう。

《POINT》

キャラクタ構造体を使うことにより、プログラムが楽に作成できるようになったことがわかるだろうか?今回のプログラムではキャラクタ情報(メンバ数)が4つしかないため、メリットはあまり感じられないかもしれないが、キャラクタ情報が増えたときのことを考えると、キャラクタ構造体を使ったほうが断然管理しやすくなるはずである。
今のうちからキャラクタ構造体の使い方に慣れておき、実際のゲーム製作に役立てよう。

敵キャラ情報もキャラクタ構造体で管理する

自キャラの情報をキャラクタ構造体で管理できるのであれば、敵キャラ情報もキャラクタ構造体で管理できる。プログラムを修正してみよう。

//=============================================================================
//  ゲーム処理関係の自作関数群
//  Copyright NKC Game Staff(←自分の名前) 
//-----------------------------------------------------------------------------
#include "NKC_Common.h"

// グローバル変数
/* 自ソースでのみ利用するもの */
//---- 背景
static TLVERTX BackVertex[4];       // 頂点情報配列
//---- 自機
static STATUS MyChara;              // 自キャラステータス情報
//---- 敵
static STATUS Enemy;                // 敵キャラステータス情報
・
・
・
ここから先の修正は自分で考えること
・
・
・

BACK(キャラクタ構造体とは) NEXT(敵キャラを簡単に増加させる)