今の状態では、プレイヤーキャラクターを移動していくと画面外に出てしまいます。
本来であれば画面外に描画すると「描画用メモリ」の外にデータを転送する事になるため「クリッピング」と言う処理が必要になります。
しかし、このシステムはDirectXを使っているため「クリッピング」は自動的に行ってくれます。
今回は「クリッピング」よりも、プレイヤーキャラクターが画面外に出る事自体を問題として考えていきます。
皆さんがゲームをプレイする時にプレイヤーキャラクターが画面外に出てしまう事があったでしょうか?
画面外で出てしまった場合、座標の表示が無ければ画面内に戻ってくる事も困難です。
普通のゲームはプレイヤーキャラクターが画面外に出ないようにプログラムで制御しています。
まずは「画面端でプレイヤーキャラクターを止める」処理を考えてみましょう。
「Player.cpp」の「Move関数」を開いてください。
void Player::Move(Engine *pEngine) { if (pEngine->GetKeyState(DIK_UP)) { m_direction = UP; m_y -= m_speed; } if (pEngine->GetKeyState(DIK_RIGHT)) { m_direction = RIGHT; m_x += m_speed; } if (pEngine->GetKeyState(DIK_DOWN)) { m_direction = DOWN; m_y += m_speed; } if (pEngine->GetKeyState(DIK_LEFT)) { m_direction = LEFT; m_x -= m_speed; } } |
今は何の制限も無く座標を増減させていますので、画面外に出てしまいます。
最初は簡単な「左端」から対応を考えてみます。
画面の左端の座標は「0」です。
キャラクターの「転送先X座標」がマイナスになると画面外に出てしまいます。
座標を確認出来るように「Draw関数」に座標を表示するコードを追加します。
「GameBase.h」を開き、フォント定数を追加します。
//----------------------------------------------------------------------------- //ゲーム中で使用するテクスチャ、BGM、SE、フォントのパス付ファイル名を書きます。 //----------------------------------------------------------------------------- namespace KeyString { const std::string TEXTURE_CHARACTER = "Resource\\Texture\\Character.png"; const std::string FONT_GOTHIC = "MS ゴシック"; } |
「SceneGame.cpp」を開き、「Start関数」でフォントを追加します。
//============================================================================= // シーンの実行時に1度だけ呼び出される開始処理関数 //============================================================================= void SceneGame::Start() { m_pEngine->AddTexture(TEXTURE_CHARACTER); m_pEngine->AddFont(FONT_GOTHIC, 20); m_player.Initialize(); } |
「Player.cpp」を開き、「Draw関数」に次のコードを追加します。
void Player::Draw(Engine *pEngine)
{
SetRect(&m_sour,
m_animation * WIDTH,
m_direction * HEIGHT,
m_animation * WIDTH + WIDTH,
m_direction * HEIGHT + HEIGHT);
SetRect(&m_dest,
m_x,
m_y,
m_x + WIDTH,
m_y + HEIGHT);
pEngine->Blt(&m_dest, TEXTURE_CHARACTER, &m_sour);
pEngine->DrawPrintf(0, 0, FONT_GOTHIC, D3DCOLOR_XRGB(255, 255, 255), "X = %d : Y = %d", m_x, m_y);
}
|
実行して確認しましょう。
移動すると座標も変わります。
それでは改めて「左端」で止める処理を考えます。
考え方としては「左端からはみ出したら左端に戻す」と言う事をやります。
左に移動する箇所だけを抜き出すと、
if (pEngine->GetKeyState(DIK_LEFT)) { m_direction = LEFT; m_x -= m_speed; } |
こうなっています。
X座標を無条件で引いていますので、いつかマイナスになり画面外に出てしまいます。
そこで、if文を追加します。
if (pEngine->GetKeyState(DIK_LEFT)) {
m_direction = LEFT;
m_x -= m_speed;
if (m_x < 0) {
m_x = 0;
}
}
|
座標がマイナスになったら「0」に戻します。
こうする事で、
「左端」で止まります。
「上端」も同じように作る事が出来ます。
if (pEngine->GetKeyState(DIK_UP)) {
m_direction = UP;
m_y -= m_speed;
if (m_y < 0) {
m_y = 0;
}
}
|
「転送先Y座標」がマイナスになった場合、「0」に戻せば良いです。
残りは「右端」と「下端」です。
クライアント領域のサイズは「640×480ピクセル」ですから「右端」「下端」の座標は分かります。
極力定数値を使うようにしていますので、640や480と言った直値を使うのは避けたいです。
このシステムでは「WindowSetting名前空間」に「WINDOW_WIDTH」「WINDOW_HEIGHT」と言う定数を用意しています。
これを使って「右端」「下端」の処理を作りましょう。
if (pEngine->GetKeyState(DIK_RIGHT)) { m_direction = RIGHT; m_x += m_speed; if (m_x >= WindowSetting::WINDOW_WIDTH - WIDTH) { m_x = WindowSetting::WINDOW_WIDTH - WIDTH; } } if (pEngine->GetKeyState(DIK_DOWN)) { m_direction = DOWN; m_y += m_speed; if (m_y >= WindowSetting::WINDOW_HEIGHT - HEIGHT) { m_y = WindowSetting::WINDOW_HEIGHT - HEIGHT; } } |
クライアント領域の「右端」の座標は640ですが、キャラクターの幅を考慮しなければなりません。
キャラクターの幅は32ピクセルですから、608で止めなければ画面外に出てしまいます。
「下端」も同様にキャラクターの高さを考慮して作りました。
実行してみましょう。
右も下も画面外に出なくなりました。