一定時間経過したら、デモが流れる

03の修正により、現在の時間を様々なソースから利用できるようになった。それを使ったプログラムを作ってみる。今回はスタート画面で一定時間何もしないとデモが流れ、デモ中にスペースキーを押すと、スタート画面に戻るプログラムを作成してみる。

前準備

デモ画面処理用プログラムの追加

デモ画面を表示するプログラム(Demo.cppDemo.h)およびデモ用背景画像(back_demo.bmp)を用意した。処理別にソースを分割しているため、簡単に追加することができる。それぞれダウンロードし、プロジェクトに追加しておく。

NKC_Common.hの修正

スタート画面、ゲーム画面のほかにデモ画面が追加されたため、状態を表わすマクロを修正する。また、Demo.hをインクルードする。

// マクロ
#define SCREEN_WIDTH	640	// ウィンドウの幅
#define SCREEN_HEIGHT	480	// ウィンドウの高さ
#define RELEASE(x) if(x!=NULL){x->Release();x=NULL;}
/* デバッグオプション(完成したらコメントアウトする) */
#define DEBUG          TRUE
/* ゲームの状態を識別する(フレーム番号) */
#define START_INIT      0
#define START_FRAME     1
#define GAME_INIT       10
#define GAME_FRAME      11
#define DEMO_INIT       20
#define DEMO_FRAME      21
/* 頂点フォーマット(基本形)*/
#define FVF_TLVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)
・
・
・
// 自作ソースファイルの組み込み
// 自作ソース・ファイルの組み込み
#include "NKC_Public.h"
#include "NKC_DGraphics.h"
#include "Start.h"
#include "Game.h"
#include "Demo.h"

NKC_DGraphics.cppの修正

デモ画面用のテクスチャを作成・開放する関数を作成する。NKC_DGraphics.cppを次のように修正する。

//-----------------------------------------------------------------------------
// 関数名 : ReleaseD3D()
// 機能概要: DirectX8オブジェクトの開放
//-----------------------------------------------------------------------------
void ReleaseD3D(void)
{
    // テクスチャの開放
    ReleaseStartTexture();
    ReleaseGameTexture();
    ReleaseDemoTexture();
    //デバイスオブジェクトの開放
    RELEASE(gl_lpD3ddev);
    //DirectX8オブジェクトの開放
    RELEASE(gl_lpD3d);
}
・
・
・
//-----------------------------------------------------------------------------
// 関数名 : CreateDemoTexture()
// 機能概要: デモ画面用テクスチャの作成・再生成
//-----------------------------------------------------------------------------
void CreateDemoTexture(void)
{
    HRESULT hr;

	// 背景
    hr = D3DXCreateTextureFromFile(gl_lpD3ddev, "back_demo.bmp", &gl_TXBack);
    if ( FAILED(hr) ) {
	    MessageBox(hWnd, "back_demo.bmp をテクスチャとして読み込めませんでした", "ERROR", MB_OK);
        return;
    }

}

//-----------------------------------------------------------------------------
// 関数名 : ReleaseDemoTexture()
// 機能概要: デモ画面用テクスチャ開放処理
//-----------------------------------------------------------------------------
void ReleaseDemoTexture(void)
{
    // テクスチャの開放
    RELEASE(gl_TXBack); // 背景
}

NKC_DGraphics.hの修正

NKC_DGraphics.cppに作成した2つの関数を利用できるよう、NKC_DGraphics.hにプロトタイプ宣言を追加する。

//-----------------------------------------------------------------------------
// プロトタイプ宣言
//-----------------------------------------------------------------------------
HRESULT InitDX8(void);                  // DirectX8初期化処理
void InitRender(void);                  // 描画の設定
void ReleaseD3D(void);                  // DirectX8開放処理
void ResetWindow(void);                 // ウィンドウ再生成処理
void CreateStartTexture(void);          // スタート画面用テクスチャ作成処理
void ReleaseStartTexture(void);         // スタート画面用テクスチャ開放処理
void CreateGameTexture(void);           // ゲーム画面用テクスチャ作成処理
void ReleaseGameTexture(void);          // ゲーム画面用テクスチャ開放処理
void CreateDemoTexture(void);           // デモ画面用テクスチャ作成処理
void ReleaseDemoTexture(void);          // デモ画面用テクスチャ開放処理

WinMain.cppの修正

状態が切り替わったらデモ画面処理が実行されるよう、状態別処理関数(UpdateFrame関数)を修正する。

//-----------------------------------------------------------------------------
// 関数名 : UpdateFrame()
// 機能概要: ゲームメイン処理
//-----------------------------------------------------------------------------
void UpdateFrame(void)
{
#ifdef DEBUG
    static DWORD beforeTime = 0;    // 以前の時間を格納
    static int fps = 0;             // FTPカウンタ
    char buff[80];                  // 文字列表示用バッファ
#endif

    /* 現在の時間を取得 */
    gl_nowTime = timeGetTime();

    /* 現在のキー情報を取得 */
    if (!GetKeyboardState(KeyTbl)) return;

    /* 画面のクリア */
    gl_lpD3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255,255,255), 0.0, 0);
    /* シーン開始 */
    gl_lpD3ddev->BeginScene();
    /* 頂点フォーマットを設定 */
    gl_lpD3ddev->SetVertexShader(FVF_TLVERTEX);

    /* 処理の振り分け */
    switch (g_FrameNo) {
        case START_INIT:
            // スタート画面を表示する前に実行する初期化関数を実行
            StartInit();
        case START_FRAME:
            // スタート画面表示処理関数を実行
            StartFrame();
            break;
        case GAME_INIT:
            // ゲーム画面を表示する前に実行する初期化関数を実行
            GameInit();
        case GAME_FRAME:
            // ゲーム画面表示処理関数を実行
            GameFrame();
            break;
        case DEMO_INIT:
            // デモ画面を表示する前に実行する初期化関数を実行
            DemoInit();
        case DEMO_FRAME:
            // デモ画面表示処理関数を実行
            DemoFrame();
            break;
        default:
            OutputDebugString("g_FrameNoの値が例外です。\n");
    }

#ifdef DEBUG
    /* FPSを求めて表示する */
    fps++;
    if (gl_nowTime - beforeTime >= 1000) {
        // FPSの表示
        wsprintf(buff, "シーンNo:%2d / %04d FPS\n", g_FrameNo, fps);
        OutputDebugString(buff);
        // 初期化
        fps = 0;
        beforeTime = gl_nowTime;
    }
#endif

    /* シーン終了 */
    gl_lpD3ddev->EndScene();
    /* フリップ */
    gl_lpD3ddev->Present(NULL, NULL, NULL, NULL);

}

※以上の修正を行ったらビルドを行い、プログラムが正常に動くかどうか確かめる。ただし、デモ画面に切り替わる処理を入れていないため、デモ画面には切り替わらない。

経過時間を調べ、デモ画面に切り替える処理を追加する

スタート画面が表示されてから一定時間が経過したら、デモ画面に切り替わるようにプログラムを修正する。もちろん修正するソース・ファイルは「Start.cpp」である。

マクロとグローバル変数を宣言

スタート画面からデモ画面に切り替わるまでの時間と、計測開始時間を保存する変数を宣言する。

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

// マクロの定義
#define DEMOSTART_TIME 5000 // デモ画面に切り替わる時間(ミリ秒)

// グローバル変数
/* 自ソースでのみ利用するもの */
static TLVERTX BackVertex[4];               // 背景用頂点情報配列
static TLVERTX MenuVertex[4];               // メニュー用頂点情報配列
static TLVERTX CursorVertex[4];             // カーソル用頂点情報配列
static DWORD gl_beforeTime;                 // 計測開始時間を保存

《POINT》

初期化処理(StartInit関数)の修正

計測開始時間をセットするよう、初期化処理(StartInit関数)を修正する。

//--------------------------------------------------- 各変数の初期化
/* 背景 */
InitVertex(BackVertex, (float)gl_rcScreen.left, (float)gl_rcScreen.top, (float)gl_rcScreen.right, (float)gl_rcScreen.bottom, 255);
/* メニュー */
MenuInitVertex(MenuVertex, 200.0f, 250.0f, 400.0f, 442.0f);
/* カーソル */
MenuInitVertex(CursorVertex, 150.0f, 250.0f, 200.0f, 300.0f);
/* 時間のセット */
gl_beforeTime = gl_nowTime;

《POINT》

スタート処理(StartFrame関数)の修正

ゲームループのたびに現在の時刻と計測開始時刻を調べ、一定時間(DEMOSTART_TIME)を超えていたら状態変数を変更するようプログラムを修正する。

//-----------------------------------------------------------------------------
// 関数名 : StartFrame()
// 機能概要: スタート画面処理
//-----------------------------------------------------------------------------
void StartFrame(void)
{
    /* 描画処理 */
    // 背景
    gl_lpD3ddev->SetTexture(0, gl_TXBack);
    gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, BackVertex, sizeof(TLVERTX));
    // メニュー
    gl_lpD3ddev->SetTexture(0, gl_TXMenu);
    gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, MenuVertex, sizeof(TLVERTX));
    // カーソル
    gl_lpD3ddev->SetTexture(0, gl_TXCursor);
    gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, CursorVertex, sizeof(TLVERTX));

    // 一定時間経過したら、デモ画面に切り替える
    if ( gl_nowTime - gl_beforeTime > DEMOSTART_TIME ) {
        ReleaseStartTexture();
        g_FrameNo = DEMO_INIT;
    }

    // リターンキーが押されたら、ゲーム開始
    if ( gl_KeyTbl[VK_RETURN] & 0x80 ) {
        ReleaseStartTexture();
        g_FrameNo = GAME_INIT;
    }

}

《POINT》

※以上の修正を行ったらビルドを行い、約5秒後にデモ画面に切り替わることを確認する。

問題点

このプログラムは本来、スタート画面でカーソルによってメニューを選択することを考えている。しかし今の状態では、カーソルを動かしている間でも開始から5秒経過すると、問答無用にデモ画面に切り替わってしまう。
これでは都合が悪いので、カーソルを動かしている間はデモ画面に切り替わらないようにプログラムを修正する。

//-----------------------------------------------------------------------------
// 関数名 : StartFrame()
// 機能概要: スタート画面処理
//-----------------------------------------------------------------------------
void StartFrame(void)
{
    /* 描画処理 */
    // 背景
    gl_lpD3ddev->SetTexture(0, gl_TXBack);
    gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, BackVertex, sizeof(TLVERTX));
    // メニュー
    gl_lpD3ddev->SetTexture(0, gl_TXMenu);
    gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, MenuVertex, sizeof(TLVERTX));
    // カーソル
    gl_lpD3ddev->SetTexture(0, gl_TXCursor);
    gl_lpD3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, CursorVertex, sizeof(TLVERTX));

    // カーソルキーを押したら計測開始時間をクリアする
    if ( gl_KeyTbl[VK_UP] & 0x80 || gl_KeyTbl[VK_DOWN] & 0x80) gl_beforeTime = gl_nowTime;

    // 一定時間経過したら、デモ画面に切り替える
    if ( gl_nowTime - gl_beforeTime > DEMOSTART_TIME ) {
        ReleaseStartTexture();
        g_FrameNo = DEMO_INIT;
    }

    // リターンキーが押されたら、ゲーム開始
    if ( gl_KeyTbl[VK_RETURN] & 0x80 ) {
        ReleaseStartTexture();
        g_FrameNo = GAME_INIT;
    }

}

《POINT》

※以上の修正を行ったらビルドを行い、上または下のカーソルキーを押している間はデモ画面に切り替わらないことを確認する。


BACK(取得した時間を他のソースから利用する) NEXT(スタートボタンを押してから一定時間経過後、ゲームが開始する)