マップチップを背景にしてスクロール

一枚絵の背景ではなく、マップチップと呼ばれる正方形の小さな画像をタイル上に敷き詰めて、背景として使用するプログラムを紹介する。

NKC_BackMapchip.cppの組み込み

マップチップを敷き詰めて表示するだけでなく、スクロールも行えるプログラムをソースファイルで用意したので、それを組み込んで利用する方法を紹介する。

1.ソースファイルの準備

NKC_BackMapchip.lzhをダウンロードして解凍すると「NKC_BackMapchip.cpp」「NKC_BackMapchip.h」が現れる。それをプロジェクトのフォルダに配置し、VCを開いて、プロジェクトに追加する作業を行う。

2.背景画像ファイル、マップデータファイルの準備

マップの元となる画像ファイルを用意する。NKC_BackMapchip.cppは、マップチップが並べられている1枚の画像ファイルと使うようプログラムされているので、そのような画像ファイルを用意する。
今回は、次のような画像ファイル(フリー素材)を使用する。

これは、32×32ピクセルで作成したマップチップをタイル上に並べたものである。これを好きなように並べ替えて背景として描画させるのである。これ(mapchip.bmp)をダウンロードして、プロジェクトのフォルダに配置する。

また、マップチップをどのように背景として配置するかといったデータをファイルで用意する。データファイルの作り方は後で解説するが、とりあえずこれ(mapdata.dat)をダウンロードして、プロジェクトのフォルダに配置する。

3.NKC_Common.hの修正

NKC_BackMapchip.cppを利用できるよう、NKC_Common.hからNKC_BackMapchip.hをインクルードする。

//-----------------------------------------------------------------------------
// 共通ヘッダ・ファイル
//  Copyright NKC Game Staff(←自分の名前) 
//-----------------------------------------------------------------------------
・
・
・
// 自作ソース・ファイルの組み込み
#include "NKC_DGraphics.h"
#include "NKC_Public.h"
#include "NKC_BackMapchip.h"
#include "Start.h"
#include "Game.h"
#include "Enemy.h"

4.NKC_BackMapchip.cppの修正

マップチップの大きさや配置した数、画像ファイル名など、用意したデータによって初期設定が変わるため、NKC_BackMapchip.cppを修正する。修正する場所は次のとおり。

//=============================================================================
//  背景にマップチップを利用するスクリプト
//  Copyright NKC Game Staff(←自分の名前) 
//-----------------------------------------------------------------------------
#include "NKC_Common.h"

// マクロ
/* マップチップ */
#define MAPCHIP_HEIGHT          32	// マップチップの高さ(ピクセル)
#define MAPCHIP_WIDTH           32	// マップチップの幅(ピクセル)
#define MAPCHIP_HEIGHT_COUNT    15	// マップチップの縦の数
#define MAPCHIP_WIDTH_COUNT     20	// マップチップの横の数
/* マップデータ */
#define MAPDATA_HEIGHT_COUNT    15	// 縦に並べる数
#define MAPDATA_WIDTH_COUNT     20	// 横に並べる数

// 構造体
typedef struct _MAPDATA {
	TLVERTX Vertex[4];  // ポリゴン
	int MapNumber;		// マップチップ番号
} MAPDATA, *LPMAPDATA;

// グローバル変数
static LPDIRECT3DTEXTURE8 gl_TXMapchip1 = NULL; // マップチップ用テクスチャ1
static MAPDATA MapData1[MAPDATA_HEIGHT_COUNT][MAPDATA_WIDTH_COUNT]; // マップデータ1
static char* MapchipFileName1 = "mapchip.bmp";	// マップチップ画像ファイル名1
static char* MapdataFileName1 = "mapdata.dat";	// マップデータファイル名1

// プロトタイプ宣言
static void CreateMapData(char*, LPMAPDATA, int, int, int, int, int, int);
static void InitMapData(LPMAPDATA, int, int, int, int, int, int, int);

//-----------------------------------------------------------------------------
// 関数名 : InitBackMapchip()
// 機能概要: 初期化処理
//-----------------------------------------------------------------------------
void InitBackMapchip(void)
{
    HRESULT hr;
    char buff[80];

    // マップチップ用テクスチャの生成
    hr = D3DXCreateTextureFromFileEx(
        gl_lpD3ddev,
        MapchipFileName1,               // ファイル名
        0,
        0,
        0,
        0,
        D3DFMT_A1R5G5B5,                // 色抜きを可能に
        D3DPOOL_MANAGED,
        D3DX_FILTER_LINEAR,
        D3DX_FILTER_LINEAR,
        D3DCOLOR_ARGB(255, 0, 0, 0),    // 透過色の指定()
        NULL,
        NULL,
        &gl_TXMapchip1                  // テクスチャ名
    );
    if ( FAILED(hr) ) {
        wsprintf(buff, "%s をテクスチャとして読み込めませんでした", MapchipFileName1);
        MessageBox(hWnd, buff, "ERROR", MB_OK);
        return;
    }

    // マップデータ作成
    CreateMapData(
        MapdataFileName1,
        *MapData1,
        MAPCHIP_HEIGHT, MAPCHIP_WIDTH,
        MAPCHIP_HEIGHT_COUNT, MAPCHIP_WIDTH_COUNT,
        MAPDATA_HEIGHT_COUNT, MAPDATA_WIDTH_COUNT
        );

}
・
・
・

《解説》

マップチップの高さ/幅(MAPCHIP_HEIGHT / MAPCHIP_WIDTH)
マップチップ1つ分の高さ/幅をピクセル単位で指定
マップチップの縦/横の数(MAPCHIP_HEIGHT_COUNT / MAPCHIP_WIDTH_COUNT)
マップチップ画像ファイルに配置したマップチップの数(縦/横)を指定
縦/横に並べる数(MAPDATA_HEIGHT_COUNT / MAPDATA_HEIGHT_COUNT)
画面に並べるマップチップの数(縦/横)を指定
マップチップ画像ファイル名
マップチップ画像用テクスチャ作成時に読み込むファイル名を指定
マップデータファイル名
マップチップをどのように並べるかといったデータを格納したファイル名を指定
透明色
マップチップ画像の透明色を指定

5.確認

ここまでの修正を行ったら一度ビルドして、エラーが出ないことを確認する。

マップチップで形成された背景を描画する(スクロール無し)

NKC_BackMapchip.cppの組み込みが終われば、マップチップで形成された背景を表示し、自由にスクロールさせることができるようになる。スクロール処理を追加する前に、まず、スクロールしないマップチップの背景が描画されるようにプログラムする。その後、様々なスクロール処理を考える。

NKC_BackMapchip.cppの組み込み時、テクスチャ画像ファイルの他に、マップデータファイル(mapdata.dat)を用意した。このファイルには、マップチップをどのように並べるかというデータが格納されており、このデータファイルを修正すれば、プログラムを修正しなくても背景を変更できる。
マップデータの作り方は後で解説するが、ここでは作成済みのマップデータファイル(mapdata.dat)を使って、スクロールしない背景を描画する方法を紹介する。

Game.cppを開き、次のように修正する。

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

// マクロの定義

// グローバル変数
/* 自ソースでのみ利用するもの */
//---- 背景
static float BackMoveX, BackMoveY;  // 背景移動量
//---- 自機
static STATUS MyChara;              // 自キャラステータス情報

// プロトタイプ宣言
/* 自ソース(Game.cpp)内でのみ利用するもの */
static void BackDraw(void);         // 背景描画
static void MyCharaDraw(void);      // 自機描画
static void MyCharaMove(void);      // 自機移動

//-----------------------------------------------------------------------------
// 関数名 : GameInit()
// 機能概要: ゲーム画面初期化処理
//-----------------------------------------------------------------------------
void GameInit(void)
{

    //--------------------------------------------------- 各変数の初期化
    // ゲーム画面で共通して使用するテクスチャの作成
    CreateGameTexture();
    // ポリゴンの初期化
    /* 背景 */
    InitBackMapchip();
    BackMoveX = 0.0f;
    BackMoveY = 0.0f;
    /* 自キャラ */
    InitVertex(MyChara.Vertex, 273.0f, 193.0f, 367.0f, 287.0f, 255);// 表示位置
    SetRect(&MyChara.HitRect, 10, 10, 10, 10);                   // 当たり判定矩形
    MyChara.MoveX = 2.0f;                                        // 移動量(X方向)
    MyChara.MoveY = 2.0f;                                        // 移動量(Y方向)

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

}

//-----------------------------------------------------------------------------
// 関数名 : GameFrame()
// 機能概要: ゲーム画面処理
//-----------------------------------------------------------------------------
void GameFrame(void)
{
    //--------------------------------------------------- 前処理

    //--------------------------------------------------- 描画
    DrawBackMapchip(BackMoveX, BackMoveY); // 背景
    MyCharaDraw(); // 自機

    //--------------------------------------------------- 移動処理
    MyCharaMove(); // 自機

	//--------------------------------------------------- 当たり判定


#ifdef DEBUG
    //--------------------------------------------------- デバッグ用
    // F10を押したらスタート画面に戻る
    if ( gl_KeyTbl[VK_F10] & 0x80 ) {
        ReleaseBackImage();
        ReleaseGameTexture();
        g_FrameNo = START_INIT;
    }
#endif

}
・
・
・

確認

上記修正を行ってビルドを行い、エラーが出ないことを確認する。また、プログラムを実行し、背景がマップチップで構成されていることを確認する。

マップチップ画像データについて

実行結果を確認して分かるとおり、マップチップ画像データには枠線が存在しないのに、実行結果では枠線が表示されてしまっている。これは、画像ファイルのサイズに問題があるからである。

実は、DirectXにおいて、テクスチャのサイズ(縦/横のピクセル数)は2の累乗(2,4,8,16,32,64,128,256,512,1024,2048,・・・)でなければならず、それ以外のサイズで作成されたビットマップファイルを読み込んでテクスチャを作成した場合、サイズが2の累乗になるように引き伸ばされる

よって、今回のサンプルのように640×480ピクセルのビットマップファイルを使ってテクスチャを作成した場合、テクスチャのサイズは2の累乗になるよう拡大され、その拡大されたテクスチャからtu、tvの値を使って画像を切り取るため、誤差が出てしまう
一枚絵の背景画像の場合は、多少の拡大・縮小があっても見た目に影響はほとんどがないが、マップチップのように、テクスチャ全体のうち、ほんの一部分を使うような場合は、実行結果のように影響が出てしまう。

マップチップ用の画像ファイルを作成する場合、画像サイズが2の累乗になるように作ろう。

マップデータの作り方

マップデータとは、マップチップ1つ1つに番号をつけ、どこにどのマップチップを表示するかという情報を格納したものである。

※実際は0からはじめることが多い

このように番号を付けたマップチップを、画面の左上から順番にならべていけば、一枚の背景画像ができあがる。マップチップ1つの大きさが32×32の場合、画面全体(640×480)に背景を表示するには横に20個(640÷32)、縦に15個(480÷32)並べればよいことが分かる。
後は、背景にどのマップチップを使うかといったデータを用意すればいいが、自分でデータを作るのは面倒である。そこで、通常はマップ・エディタというソフトを使う(または自分で作って使用する)ことが多い。マップ・エディタにはフリーウェア、シェアウェアでそれぞれいろんな種類があるが、NKC_BackMapchip.cppでは簡易汎用マップエディターMap Eddyという2つのフリーウェアで作成したデータを使えるようにプログラミングしてある。

簡易汎用マップエディターはその名のとおり、非常に扱いがシンプルで、作成されるデータファイルも、サイズが小さい。ただし、画面を越えるマップデータを作成する際、編集画面のスクロールが何故かうまくいかない(私のPCだけかもしれないが・・・)。
NKC_BackMapchip.cppではデフォルトで、簡易汎用マップエディターで作成したデータファイルを使うように設定されている

Map Eddyは簡易汎用マップエディターと比べ、機能が豊富である。画面を越えるマップデータの作成もスムーズに行うことができる。ただし、作成されるマップデータは前者と比べ、サイズが4倍ほどになる。とはいえ、所詮テキストデータであり、データ読み込み後に加工するため、気にする必要はないと思われる。
こちらで作成したデータを使うには、NKC_BackMapchip.cppを次のように修正しなければならない

//=============================================================================
//  背景にマップチップを利用するスクリプト
//  Copyright NKC Game Staff(←自分の名前) 
//-----------------------------------------------------------------------------
・
・
・
// enum型
typedef enum DATATYPE {EASY_EDIT, MAP_EDDY};

// グローバル変数
static LPDIRECT3DTEXTURE8 gl_TXMapchip1 = NULL; // マップチップ用テクスチャ1
static MAPDATA MapData1[MAPDATA_HEIGHT_COUNT][MAPDATA_WIDTH_COUNT]; // マップデータ1
static char* MapchipFileName1 = "mapchip.bmp";	// マップチップ画像ファイル名1
static char* MapdataFileName1 = "data.dat";	// マップデータファイル名1
static DATATYPE DataType = MAP_EDDY;
・
・
・
//-----------------------------------------------------------------------------
// 関数名 : InitBackMapchip()
// 機能概要: マップデータ作成処理
//-----------------------------------------------------------------------------
static void CreateMapData(
                          char* FileName,       // マップデータファイル名
                          LPMAPDATA lpMapData,  // マップデータ格納構造体の先頭アドレス
                          int MapChipHLen, int MapChipWLen, // マップチップの長さ(高さ/幅)
                          int MapChipHCnt, int MapChipWCnt, // マップチップの数(縦/横)
                          int MapDataHCnt, int MapDataWCnt  // マップデータの数(縦/横)
                          )
{
    ・
    ・
    ・
    // マップデータの読み込み
    // (使用したマップエディタによって処理を変える)
    switch ( DataType ) {
        // 簡易汎用マップエディター
        case EASY_EDIT: 
            // ヘッダ情報の読み込み
            //      0バイト目 :マップサイズX
            //      1バイト目 :マップサイズY
            //      2バイト以降:マップデータ(1バイトずつ)
            x = fgetc(fp);
            y = fgetc(fp);
            // ヘッダ情報のチェック
            if ( FAILED(CheckHeaderData(x, y, MapDataWCnt, MapDataHCnt)) ) break;
            // マップデータの読み込み
            x = y = 0;
            while ( (data = fgetc(fp)) != EOF ) {
                InitMapData(lpMapData, x, y, data, MapChipHCnt, MapChipWCnt, MapChipHLen, MapChipWLen); // マップデータ生成
                lpMapData++;
                x++;
                if ( x >= MapDataWCnt ) {
                    y++;
                    x = 0;
                }
            }
            // 終了
            break;

        // MapEddyの場合
        case MAP_EDDY: 
            // ヘッダ情報の読み込み
            //		0〜3バイト目:マップサイズX
            //		4〜7バイト目:マップサイズY
            //		8〜11バイト目:チップリストの1行のチップ数
            //		12バイト以降:マップデータ(4バイト)
            x = GetEddyData(fp);
            y = GetEddyData(fp);
            GetEddyData(fp); // 読み飛ばし
            // ヘッダ情報のチェック
            if ( FAILED(CheckHeaderData(x, y, MapDataWCnt, MapDataHCnt)) ) break;
            // マップデータの読み込み
            x = y = 0;
            for ( i=0 ; i<MapDataWCnt*MapDataHCnt ; i++ )
            {
                data = GetEddyData(fp);
                InitMapData(lpMapData, x, y, data, MapChipHCnt, MapChipWCnt, MapChipHLen, MapChipWLen); // マップデータ生成
                lpMapData++;
                x++;
                if ( x >= MapDataWCnt ) {
                    y++;
                    x = 0;
                }
            }
            // 終了
            break;

        // それ以外
        default:
            MessageBox(hWnd, "DataTypeの値が不正です。", "ERROR", MB_OK);
            break;
    }

    // ファイルを閉じる
    fclose(fp);

}

《POINT》

《確認》

それぞれのマップエディタを使ってデータファイルを作成し、作成されたデータどおりに背景が表示されるかを確認する。マップエディタの使い方は、それぞれのヘルプを参照すること。

自動的にスクロールさせる(縦/横スクロール)

ここでは、シューティングゲームのように、ゲームの進行に関係なく自動的に背景をスクロールさせる方法を紹介する。

現在のプログラムの解説

ゲームループのたびに背景画像を描画する処理は、GameFrame()関数内でDrawBackMapchip()関数を実行することにより行われている。

//--------------------------------------------------- 描画
DrawBackMapchip(BackMoveX, BackMoveY); // 背景
MyCharaDraw(); // 自機

DrawBackMapchip()関数はNKC_BackMapchip.cpp内に作成されている関数で、2つの引数を持つ。1つ目の引数はX方向、2つ目の引数はY方向の移動量を示している。
前準備で作成したプログラムでは、初期化処理(GameInit()関数内)で、移動量を次のように設定した。

/* 背景 */
InitBackMapchip();
BackMoveX = 0.0f;
BackMoveY = 0.0f;

この場合、X方向の移動量は0.0、Y方向の移動量も0.0であるため、背景画像は一切のスクロールを行わないことになる。よって、スクロールを行いたい場合、ここの値を変化させればよいことが分かる。

自動的にスクロールするように設定するには?

例えばシューティングゲームのように自動的に背景をスクロールさせる場合、次のように指定する。

  1. 縦スクロール(右から左へ流れる)の場合
    /* 背景 */
    InitBackMapchip();
    BackMoveX = 1.0f;
    BackMoveY = 0.0f;
    
  2. 横スクロール(上から下へ流れる)の場合
    /* 背景 */
    InitBackMapchip();
    BackMoveX = 0.0f;
    BackMoveY = -1.0f;
    

横スクロールの場合はBackMoveX、縦スクロールの場合はBackMoveYに対して、スクロールする幅を指定する。また、BackMoveX、BackMoveYの値をともに指定すると、斜めにスクロールするようになる。

《確認》

BackMoveX、BackMoveYの初期値をいろいろ変更し、どのようにスクロールが行われるか確かめよう。

スクロールに対応したマップデータを作るには?

現在のマップチップデータは一画面分しかないため、スクロール処理を行うとすぐにはみ出してしまう。スクロール処理を行うには、複数面分のマップデータを作成し、データファイルを入れ替える必要がある。複数面のマップデータを作成した場合、マップチップの数などを作成したデータにあわせなければならない。

//=============================================================================
//  背景にマップチップを利用するスクリプト
//  Copyright NKC Game Staff(←自分の名前) 
//-----------------------------------------------------------------------------
#include "NKC_Common.h"

// マクロ
/* マップチップ */
#define MAPCHIP_HEIGHT          32	// マップチップの高さ(ピクセル)
#define MAPCHIP_WIDTH           32	// マップチップの幅(ピクセル)
#define MAPCHIP_HEIGHT_COUNT    15	// マップチップの縦の数
#define MAPCHIP_WIDTH_COUNT     20	// マップチップの横の数
/* マップデータ */
#define MAPDATA_HEIGHT_COUNT    15	// 縦に並べる数
#define MAPDATA_WIDTH_COUNT     20	// 横に並べる数

マップエディタを使ってデータファイルを作成すると、縦/横に並べたマップチップの数がデータファイルに登録されるため、その数とdefineで定義した数が一致するかどうかをプログラムでチェックしている。プログラム実行時、エラーメッセージが出ないように、この値を調整すること。

キャラクタの動きにあわせてスクロールさせる

背景画像描画処理(DrawBackImage()関数)を実行する際に、移動量を指定することにより背景がスクロールする。であれば、キャラクタの移動、つまりカーソルキーの入力状態によって背景の移動量を調整すれば、キャラクタを中心にして背景が移動するように見せることが可能であることが想像できる。
どのようにでもプログラムできるが、例えば次のようにプログラムすれば、キャラクタを中心にして背景をスクロールできる。

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

// マクロの定義

// グローバル変数
/* 自ソースでのみ利用するもの */
//---- 背景
static float BackMoveX, BackMoveY;  // 背景移動量
static float ScrollSpeed;           // スクロールスピード
//---- 自機
static STATUS MyChara;              // 自キャラステータス情報
//---- 敵キャラ
static ENEMYSTATUS Enemy;           // 敵キャラステータス情報

// プロトタイプ宣言
/* 自ソース(Game.cpp)内でのみ利用するもの */
static void BackDraw(void);         // 背景描画
static void MyCharaDraw(void);      // 自機描画
static void MyCharaMove(void);      // 自機移動
static void EnemyMove(void);        // 敵キャラ移動

//-----------------------------------------------------------------------------
// 関数名 : GameInit()
// 機能概要: ゲーム画面初期化処理
//-----------------------------------------------------------------------------
void GameInit(void)
{

    //--------------------------------------------------- 各変数の初期化
    // ゲーム画面で共通して使用するテクスチャの作成
    CreateGameTexture();
    // ポリゴンの初期化
    /* 背景 */
    InitBackImage();        // 背景用テクスチャの作成
    BackMoveX = 0.0f;       // スクロール幅(X座標)
    BackMoveY = 0.0f;       // スクロール幅(Y座標)
    ScrollSpeed = 1.0f;   // 移動量
    /* 自キャラ */
    InitVertex(MyChara.Vertex, 273.0f, 193.0f, 367.0f, 287.0f, 255);// 表示位置
    SetRect(&MyChara.HitRect, 10, 10, 10, 10);                   // 当たり判定矩形
    MyChara.MoveX = 2.0f;                                        // 移動量(X方向)
    MyChara.MoveY = 2.0f;                                        // 移動量(Y方向)

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

}
・
・
・
//-----------------------------------------------------------------------------
// 関数名 : MyCharaMove()
// 機能概要: 自機移動
//-----------------------------------------------------------------------------
static void MyCharaMove(void)
{
    // 初期化
    BackMoveX = BackMoveY = 0.0f;
    // 背景スクロール処理
    if ( gl_KeyTbl[VK_LEFT] & 0x80 )  BackMoveX = -ScrollSpeed;
    if ( gl_KeyTbl[VK_UP] & 0x80 )    BackMoveY = -ScrollSpeed;
    if ( gl_KeyTbl[VK_RIGHT] & 0x80 ) BackMoveX = ScrollSpeed;
    if ( gl_KeyTbl[VK_DOWN] & 0x80 )  BackMoveY = ScrollSpeed;

}
・
・
・

《確認》

上記修正を行い、キャラクタの動きにあわせて背景がスクロールすることを確かめよう。

プログラム解説

ここでは、NKC_BackMapchip.cppに作成した関数で、どのようにスクロールを実現しているかを簡単に解説する。

マップチップデータの管理

DirectX Graphicsでは、DirectDrawのようにポリゴン(DirectDrawで言うサーフェイス)の一部分に任意の画像を転送することはできない。よって、背景を構成するマップチップの数だけのポリゴンを用意し、その1つ1つに対応する画像を貼り付けることにより、実現している。例えばNKC_BackMapchip.cppをダウンロードした直後では、次のようにマップチップデータを管理している。

//=============================================================================
//  背景にマップチップを利用するスクリプト
//  Copyright NKC Game Staff(←自分の名前) 
//-----------------------------------------------------------------------------
#include "NKC_Common.h"

// マクロ
/* マップチップ */
#define MAPCHIP_HEIGHT          32  // マップチップの高さ(ピクセル)
#define MAPCHIP_WIDTH           32  // マップチップの幅(ピクセル)
#define MAPCHIP_HEIGHT_COUNT    15  // マップチップの縦の数
#define MAPCHIP_WIDTH_COUNT     20  // マップチップの横の数
/* マップデータ */
#define MAPDATA_HEIGHT_COUNT    15  // 縦に並べる数
#define MAPDATA_WIDTH_COUNT     20  // 横に並べる数

// 構造体
typedef struct _MAPDATA {
    TLVERTX Vertex[4];  // ポリゴン
    int MapNumber;      // マップチップ番号
} MAPDATA, *LPMAPDATA;

// enum型
typedef enum DATATYPE {EASY_EDIT, MAP_EDDY};

// グローバル変数
static LPDIRECT3DTEXTURE8 gl_TXMapchip1 = NULL; // マップチップ用テクスチャ1
static MAPDATA MapData1[MAPDATA_HEIGHT_COUNT][MAPDATA_WIDTH_COUNT]; // マップデータ1
static char* MapchipFileName1 = "mapchip.bmp";	// マップチップ画像ファイル名1
static char* MapdataFileName1 = "data.dat";	// マップデータファイル名1
static DATATYPE DataType = MAP_EDDY;

《POINT》

スクロールしない背景であれば、ポリゴンの表示座標は計算で求めることができ、ゲーム中にその座標が変わることはない。しかし、スクロールを考えるとマップチップごとに表示座標を持っておいたほうが便利であるため、そのようにプログラムした。

マップデータの読み込み

マップデータはマップエディタで作成し、先のMapData1に格納される。MapData1への格納処理はCreateMapData関数で行っているが、マップチップ番号を読み込む際、頂点座標も計算し、格納している

//-----------------------------------------------------------------------------
// 関数名 : InitBackMapchip()
// 機能概要: マップデータ作成処理
//-----------------------------------------------------------------------------
static void CreateMapData(
                          char* FileName,       // マップデータファイル名
                          LPMAPDATA lpMapData,  // マップデータ格納構造体の先頭アドレス
                          int MapChipHLen, int MapChipWLen, // マップチップの長さ(高さ/幅)
                          int MapChipHCnt, int MapChipWCnt, // マップチップの数(縦/横)
                          int MapDataHCnt, int MapDataWCnt  // マップデータの数(縦/横)
                          )
{
    ・
    ・
    ・
    // マップデータの読み込み
    // (使用したマップエディタによって処理を変える)
    switch ( DataType ) {
        // 簡易汎用マップエディター
        case EASY_EDIT: 
            // ヘッダ情報の読み込み
            //		0バイト目 :マップサイズX
            //		1バイト目 :マップサイズY
            //		2バイト以降:マップデータ(1バイトずつ)
            x = fgetc(fp);
            y = fgetc(fp);
            // ヘッダ情報のチェック
            if ( FAILED(CheckHeaderData(x, y, MapDataWCnt, MapDataHCnt)) ) break;
            // マップデータの読み込み
            x = y = 0;
            while ( (data = fgetc(fp)) != EOF ) {
                InitMapData(lpMapData, x, y, data, MapChipHCnt, MapChipWCnt, MapChipHLen, MapChipWLen); // マップデータ生成
                lpMapData++;
                x++;
                if ( x >= MapDataWCnt ) {
                    y++;
                    x = 0;
                }
            }
            // 終了
            break;

        // MapEddyの場合
        case MAP_EDDY: 
            ・
            ・
            ・

背景がスクロールしない場合、頂点座標は計算によって簡単に求めることができるが、ゲームループのたびに同じ計算をさせることは好ましくない。また、背景をスクロールさせる場合は、複数のポリゴンすべての頂点座標が変化するため、スクロールのたびに計算させるよりも、それぞれのポリゴンの頂点座標を変化させたほうがプログラムが簡単であるため、そのようにプログラムした。この辺りはプログラマの趣味だろう・・・

背景用ポリゴンの描画について

背景の描画はDrawBackMapchip関数で行っているが、この関数では、描画の他に移動処理も行っている。そして、描画の際、表示領域を超えているポリゴンは描画を実行しないようにプログラムされている。これにより、画面のスクロールに対応している。

//-----------------------------------------------------------------------------
// 関数名 : DrawBackMapchip()
// 機能概要: 描画・移動処理
//-----------------------------------------------------------------------------
void DrawBackMapchip(float mx, float my)
{
    int x, y;

    // 描画・移動処理
    gl_lpD3ddev->SetTexture(0, gl_TXMapchip1);
    for ( y=0 ; y < MAPDATA_HEIGHT_COUNT ; y++ ) {
        for ( x=0 ; x < MAPDATA_WIDTH_COUNT ; x++ ) {
            /* 描画 */
            if ( HitCheckRect2(gl_rcScreen, MapData1[y][x].Vertex) )
                gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, MapData1[y][x].Vertex, sizeof(TLVERTX));
            /* 移動 */
            Move(MapData1[y][x].Vertex, mx, my);
        }
    }

}

ただし、作成した画面を超えてスクロールした場合の処理は組み込んでいないため、その辺りの処理は作成しているゲームにあわせて作成する必要がある。


BACK(一枚絵を背景にしてスクロール)