今回からは「スライドパズル」を作ります。
だいたいの場合、正方形の画像が9分割または16分割されランダムでシャッフルされているものを正しい場所にスライドして戻す、と言うルールです。
↓のような状態から、
パネルをスライドさせて元に戻すゲームです。
前回と同じく、タイトルシーンから作りたいと思います。
今回のゲームは「難易度」を変えた2つのパターンを用意しようと思っています。
1つは画面を「3×3の9分割」に、もう1つは「4×4の16分割」にします。
タイトル画面でどちらにするか選択できるように作ります。
まずは、画面の設計ですが、今回使うタイトル画像は↓です。
実際の画像サイズは「1024×1024ピクセル」ですが、大きいので縮小表示しています。
※プロジェクトフォルダの「Resource\\Textureフォルダ」に「PuzzleTitle.png」と言うファイル名で保存してください。
画像の左上にあるのがタイトルです。
タイトル文字の下にある2つの四角には、「難易度」別の画像を入れようと思っています。
次に「SceneTitle.h」「SceneTitle.cpp」を追加して、最初のシーンとして「SCENE_TITLE」を設定しましょう。
※忘れた方は前回の内容を確認して下さい。
設定が終わったら「GameBase.h」を開き、画像ファイル名を定数化しましょう。
//-----------------------------------------------------------------------------
//ゲーム中で使用するテクスチャ、BGM、SE、フォントのパス付ファイル名を書きます。
//-----------------------------------------------------------------------------
namespace KeyString
{
const std::string TEXTURE_TITLE = "Resource\\Texture\\PuzzleTitle.png";
}
|
「SceneTitle.cpp」の「Start関数」で画像を追加します。
//=============================================================================
// シーンの実行時に1度だけ呼び出される開始処理関数
//=============================================================================
void SceneTitle::Start()
{
m_pEngine->AddTexture(TEXTURE_TITLE);
}
|
この画像は結果表示にも使うので、解放はしません。
「Draw関数」にタイトルの背景画像を転送するコードを追加しますが、座標を定数化するため「SceneTitle.h」を開いてください。
private: const int TITLE_SOUR_X; //タイトルの転送元左座標 const int TITLE_SOUR_Y; //タイトルの転送元上座標 const int TITLE_DEST_X; //タイトルの転送先左座標 const int TITLE_DEST_Y; //タイトルの転送先上座標 const int TITLE_WIDTH; //タイトルの幅 const int TITLE_HEIGHT; //タイトルの高さ }; |
「SceneTitle.cpp」のコンストラクタ関数で初期値を代入します。
//=============================================================================
// コンストラクタ
// 引 数:Engine* エンジンクラスのアドレス
//=============================================================================
SceneTitle::SceneTitle(Engine *pEngine) : Scene(pEngine)
, TITLE_SOUR_X(0)
, TITLE_SOUR_Y(0)
, TITLE_DEST_X(0)
, TITLE_DEST_Y(0)
, TITLE_WIDTH(640)
, TITLE_HEIGHT(480)
{
}
|
最後に「Draw関数」に転送コードを書きましょう。
//============================================================================= // シーンの実行時に繰り返し呼び出される描画処理関数 //============================================================================= void SceneTitle::Draw() { //タイトル画像の転送 SetRect(&m_sour, TITLE_SOUR_X, TITLE_SOUR_Y, TITLE_SOUR_X + TITLE_WIDTH, TITLE_SOUR_Y + TITLE_HEIGHT); SetRect(&m_dest, TITLE_DEST_X, TITLE_DEST_Y, TITLE_DEST_X + TITLE_WIDTH, TITLE_DEST_Y + TITLE_HEIGHT); m_pEngine->Blt(&m_dest, TEXTURE_TITLE, &m_sour); } |
確認のため実行してみましょう。
<実行結果 クライアント領域のみ>
次にタイトル文字の下にある四角に別の画像を転送します。
↓の2つの画像を「Resource\\Textureフォルダ」に保存してください。
1つ目は「omelette_square.png」↓
2つ目は「gang.png」↓
※どちらも、画像サイズは「512×512ピクセル」です。
※ただし、使う画像は「480×480ピクセル」分だけです。
2つの画像のファイル名を定数化しますので「GameBase.h」を開いてください。
//----------------------------------------------------------------------------- //ゲーム中で使用するテクスチャ、BGM、SE、フォントのパス付ファイル名を書きます。 //----------------------------------------------------------------------------- namespace KeyString { const std::string TEXTURE_TITLE = "Resource\\Texture\\PuzzleTitle.png"; const std::string TEXTURE_PUZZLE3 = "Resource\\Texture\\omelette_square.png"; const std::string TEXTURE_PUZZLE4 = "Resource\\Texture\\gang.png"; } |
「オムライス」の画像を「3×3の9分割」、「ローストビーフ丼」を「4×4の16分割」で使います。
「SceneTitle.cpp」の「Start関数」で画像を追加しましょう。
//============================================================================= // シーンの実行時に1度だけ呼び出される開始処理関数 //============================================================================= void SceneTitle::Start() { m_pEngine->AddTexture(TEXTURE_TITLE); m_pEngine->AddTexture(TEXTURE_PUZZLE3); m_pEngine->AddTexture(TEXTURE_PUZZLE4); } |
次に、転送するための座標を定数化します。
「SceneTitle.h」を開き、定数を追加しましょう。
private: const int TITLE_SOUR_X; //タイトルの転送元左座標 const int TITLE_SOUR_Y; //タイトルの転送元上座標 const int TITLE_DEST_X; //タイトルの転送先左座標 const int TITLE_DEST_Y; //タイトルの転送先上座標 const int TITLE_WIDTH; //タイトルの幅 const int TITLE_HEIGHT; //タイトルの高さ const int LEFT_GRAPHIC_X; //左の画像の転送先左座標 const int LEFT_GRAPHIC_Y; //左の画像の転送先上座標 const int RIGHT_GRAPHIC_X; //右の画像の転送先左座標 const int RIGHT_GRAPHIC_Y; //右の画像の転送先上座標 const int GRAPHIC_WIDTH; //転送先領域の幅 const int GRAPHIC_HEIGHT; //転送先領域の高さ const int SOUR_GRAPHIC_X; //転送元左座標 const int SOUR_GRAPHIC_Y; //転送元上座標 const int SOUR_GRAPHIC_WIDTH; //転送元の幅 const int SOUR_GRAPHIC_HEIGHT; //転送元の高さ }; |
「SceneTitle.cpp」のコンストラクタ関数で初期値を代入します。
//============================================================================= // コンストラクタ // 引 数:Engine* エンジンクラスのアドレス //============================================================================= SceneTitle::SceneTitle(Engine *pEngine) : Scene(pEngine) , TITLE_SOUR_X(0) , TITLE_SOUR_Y(0) , TITLE_DEST_X(0) , TITLE_DEST_Y(0) , TITLE_WIDTH(640) , TITLE_HEIGHT(480) , LEFT_GRAPHIC_X(113) , LEFT_GRAPHIC_Y(270) , RIGHT_GRAPHIC_X(377) , RIGHT_GRAPHIC_Y(270) , GRAPHIC_WIDTH(150) , GRAPHIC_HEIGHT(150) , SOUR_GRAPHIC_X(0) , SOUR_GRAPHIC_Y(0) , SOUR_GRAPHIC_WIDTH(480) , SOUR_GRAPHIC_HEIGHT(480) { } |
この座標については「タイトル画像」に座標を記入してありますので、確認してみてください。
「Draw関数」で2つの画像を転送します。
//============================================================================= // シーンの実行時に繰り返し呼び出される描画処理関数 //============================================================================= void SceneTitle::Draw() { //タイトル画像の転送 SetRect(&m_sour, TITLE_SOUR_X, TITLE_SOUR_Y, TITLE_SOUR_X + TITLE_WIDTH, TITLE_SOUR_Y + TITLE_HEIGHT); SetRect(&m_dest, TITLE_DEST_X, TITLE_DEST_Y, TITLE_DEST_X + TITLE_WIDTH, TITLE_DEST_Y + TITLE_HEIGHT); m_pEngine->Blt(&m_dest, TEXTURE_TITLE, &m_sour); //左の画像を転送 SetRect(&m_sour, SOUR_GRAPHIC_X, SOUR_GRAPHIC_Y, SOUR_GRAPHIC_WIDTH, SOUR_GRAPHIC_HEIGHT); SetRect(&m_dest, LEFT_GRAPHIC_X, LEFT_GRAPHIC_Y, LEFT_GRAPHIC_X + GRAPHIC_WIDTH, LEFT_GRAPHIC_Y + GRAPHIC_HEIGHT); m_pEngine->Blt(&m_dest, TEXTURE_PUZZLE3, &m_sour); //右の画像を転送 SetRect(&m_sour, SOUR_GRAPHIC_X, SOUR_GRAPHIC_Y, SOUR_GRAPHIC_WIDTH, SOUR_GRAPHIC_HEIGHT); SetRect(&m_dest, RIGHT_GRAPHIC_X, RIGHT_GRAPHIC_Y, RIGHT_GRAPHIC_X + GRAPHIC_WIDTH, RIGHT_GRAPHIC_Y + GRAPHIC_HEIGHT); m_pEngine->Blt(&m_dest, TEXTURE_PUZZLE4, &m_sour); } |
実行してみましょう。
<実行結果 クライアント領域のみ>
「見た目」だけは完成しました!
次は、タイトルにある2つの画像のどちらかをクリックしたらゲームシーンに移行するようにしましょう。
「Update関数」にコードを追加します。
判定する2つの領域は、それぞれの「転送先座標」と同じです。
//============================================================================= // シーンの実行時に繰り返し呼び出される更新処理関数 //============================================================================= void SceneTitle::Update() { if (m_pEngine->GetMouseButtonSync(DIK_LBUTTON)) { POINT point = m_pEngine->GetMousePosition(); //左の領域を判定 if (point.x >= LEFT_GRAPHIC_X && point.x < LEFT_GRAPHIC_X + GRAPHIC_WIDTH && point.y >= LEFT_GRAPHIC_Y && point.y < LEFT_GRAPHIC_Y + GRAPHIC_HEIGHT) { m_nowSceneData.Set(Common::SCENE_GAME, false, NULL); } //右の領域を判定 if (point.x >= RIGHT_GRAPHIC_X && point.x < RIGHT_GRAPHIC_X + GRAPHIC_WIDTH && point.y >= RIGHT_GRAPHIC_Y && point.y < RIGHT_GRAPHIC_Y + GRAPHIC_HEIGHT) { m_nowSceneData.Set(Common::SCENE_GAME, false, NULL); } } } |
実行して、画像をクリックするとゲームシーン(真っ黒ですが)に移行します。
しかし、このままゲームシーンの作成は出来ません・・・
選択した画像によって「難易度」が変わりますし、使う画像自体も変わります。
タイトルシーンで選択した情報をゲームシーンに伝えるには、共用データを使わなければなりません。
では、何を共用データとして用意すれば良いでしょうか。
色々なケースが考えられますが、今回は次の2つにします。
1.画像を縦横に何分割するか 2.使用する方の画像ファイル名 |
この情報以外は、特に「難易度」によって変わる事はありません。
では、「GameData.h」を開き、CommonData構造体にメンバを追加しましょう。
//----------------------------------------------------------------------------- // 複数のシーンで共用するデータを構造体にまとめます。 //----------------------------------------------------------------------------- struct CommonData { int m_split; //縦横の分割数 std::string m_strGraphicName; //画像ファイル名 }; |
この構造体が、各シーン内で「m_gameData」と言う実体として使う事が出来ます。
「SceneTitle.cpp」に戻り、「Update関数」にコードを追加します。
//============================================================================= // シーンの実行時に繰り返し呼び出される更新処理関数 //============================================================================= void SceneTitle::Update() { if (m_pEngine->GetMouseButtonSync(DIK_LBUTTON)) { POINT point = m_pEngine->GetMousePosition(); //左の領域を判定 if (point.x >= LEFT_GRAPHIC_X && point.x < LEFT_GRAPHIC_X + GRAPHIC_WIDTH && point.y >= LEFT_GRAPHIC_Y && point.y < LEFT_GRAPHIC_Y + GRAPHIC_HEIGHT) { m_gameData.m_split = 3; m_gameData.m_strGraphicName = TEXTURE_PUZZLE3; m_nowSceneData.Set(Common::SCENE_GAME, false, NULL); } //右の領域を判定 if (point.x >= RIGHT_GRAPHIC_X && point.x < RIGHT_GRAPHIC_X + GRAPHIC_WIDTH && point.y >= RIGHT_GRAPHIC_Y && point.y < RIGHT_GRAPHIC_Y + GRAPHIC_HEIGHT) { m_gameData.m_split = 4; m_gameData.m_strGraphicName = TEXTURE_PUZZLE4; m_nowSceneData.Set(Common::SCENE_GAME, false, NULL); } } } |
実行しても「見た目」は変わりませんが、これでタイトルシーンは完成です。