第15回:背景描画のテクニック
敵の作成が一通り終わったので、背景をゲーム画面に表示させることにしましょう。基準となるスプライトの縦幅を1ラインとし、上からライン単位でスプライトを配置していきます。1フレームが経過してExec()が呼び出されるごとに、描画開始位置を数ピクセル(スクロールスピード次第で調整)ずらした状態で再び配列していき、描画領域の外に配置していたラインが完全にウィンドウに表示された段階で、さらに1ラインを描画領域の外に追加します。あとはこの処理を繰り返していけば自然なスクロール処理が行われます。横スクロールや全方位スクロールもこのテクニックの応用に過ぎません。




#pragma once
#include "GameDef.h"
#define BACKGROUND_PRIORITY 5000
class CBackGround : public CGameObject
{
private:
CTexture tex;
int linepos; // 最上部のライン管理番号
float pos_y;
CSprite base_left, base_right;
CSprite pipe_left, pipe_right;
public:
CBackGround(void);
protected:
virtual void Init();
virtual void Exec();
};
#include "BackGround.h"
// 1ライン当たりの縦幅
#define LINEHEIGHT 150.0f
CBackGround::CBackGround(void)
{
// 正気状態で、最上部のライン管理番号が何番になるかを計算
linepos = (int)((480.0f + LINEHEIGHT) / LINEHEIGHT) + 1;
// 一番上のラインを描画する位置
pos_y = -LINEHEIGHT;
}
void CBackGround::Init()
{
// テクスチャの読み込み・関連づけ
tex.Load(_T("data\\bg.png"));
base_left.SetTexture(&tex);
base_left.SetSpriteRect(0, 0, 320, 150);
base_left.SetCenterPosition(CP_TOP | CP_LEFT);
base_right.SetTexture(&tex);
base_right.SetSpriteRect(0, 150, 320, 300);
base_right.SetCenterPosition(CP_TOP | CP_RIGHT);
pipe_left.SetTexture(&tex);
pipe_left.SetSpriteRect(320, 0, 448, 30);
pipe_left.SetCenterPosition(CP_TOP | CP_LEFT);
pipe_right.SetTexture(&tex);
pipe_right.SetSpriteRect(320, 30, 448, 60);
pipe_right.SetCenterPosition(CP_TOP | CP_RIGHT);
}
void CBackGround::Exec()
{
// ラインごとのスプライト配置
int bc = linepos;
for(float y = pos_y; y < 480.0f; y += LINEHEIGHT, bc--){
if(bc % 4 == 0){
// ライン管理番号が4で割り切れる(つまり4回に1回)
// のであれば、特別なスプライトを配置する
base_left.Draw(0.0f, y);
base_right.Draw(640.0f, y);
}else{
for(float yy = 0; yy < 150.0f; yy += 30.0f){
pipe_left.Draw(0.0f, y + yy);
pipe_right.Draw(640.0f, y + yy);
}
}
}
// スクロール処理
pos_y += 2.0f;
if(pos_y >= 0.0f){
// 一番上のラインが描画領域に入ったのであれば
// 新しいラインを追加するため、ライン管理番号を一増やす
linepos++;
pos_y = -LINEHEIGHT;
}
}
