次はスコアに関するプログラムを追加しましょう。
「さめがめ」のスコア計算方法は後で説明しますので、描画の準備を先に行います。
まずはスコア自体を追加しますので「Samegame.h」を開き、privateに変数を追加します。
//選択中のブロックの数 int m_selectBlockNum; //スコア int m_score; //範囲外チェック bool IsOutsideField(const POINT &refPoint) const; |
※前後関係を確認して追加してください。
「Samegame.cpp」の「Start関数」で初期値を代入します。
//ゲームの初期化 void Samegame::Initialize(const int colorNum) { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { m_field[i][j].m_color = rand() % colorNum + 1; m_field[i][j].m_bSelect = false; } } m_selectBlockNum = 0; m_score = 0; } |
次に描画するための座標用定数を追加しましょう。
「Samegame.h」に戻り、private定数を追加してください。
const int STALEMATE_SOUR_X; //手詰まりの転送元左座標 const int STALEMATE_SOUR_Y; //手詰まりの転送元上座標 const int STALEMATE_DEST_X; //手詰まりの転送先左座標 const int STALEMATE_DEST_Y; //手詰まりの転送先上座標 const int STALEMATE_WIDTH; //手詰まりの幅 const int STALEMATE_HEIGHT; //手詰まりの高さ const int NUMBER_SOUR_X; //数字の転送元左座標 const int NUMBER_SOUR_Y; //数字の転送元上座標 const int NUMBER_DEST_X; //数字の転送先左座標 const int NUMBER_DEST_Y; //数字の転送先上座標 const int NUM_OF_DIGITS; //表示桁数 const int NUMBER_WIDTH; //数字の幅 const int NUMBER_HEIGHT; //数字の高さ |
「Samegame.cpp」のコンストラクタ関数で初期値を設定します。
Samegame::Samegame()
: BLOCK_SOUR_X(0)
, BLOCK_SOUR_Y(0)
, BLOCK_DEST_X(0)
, BLOCK_DEST_Y(0)
, MESH_SOUR_X(0)
, MESH_SOUR_Y(32)
, BLOCK_WIDTH(32)
, BLOCK_HEIGHT(32)
, STALEMATE_SOUR_X(0)
, STALEMATE_SOUR_Y(96)
, STALEMATE_DEST_X(194)
, STALEMATE_DEST_Y(224)
, STALEMATE_WIDTH(252)
, STALEMATE_HEIGHT(32)
, NUMBER_SOUR_X(0)
, NUMBER_SOUR_Y(64)
, NUMBER_DEST_X(262)
, NUMBER_DEST_Y(16)
, NUM_OF_DIGITS(5)
, NUMBER_WIDTH(23)
, NUMBER_HEIGHT(32)
{
}
|
NUM_OF_DIGITSは「桁数」であり、今回は5桁分用意します。
また転送先座標は画面の真ん中に設定しています。
また「Samegame.h」に戻り、publicメンバ関数を追加します。
//ブロックの描画 void DrawBlock(Engine *pEngine); //手詰まり描画 void DrawStalemate(Engine *pEngine); //スコアの描画 void DrawScore(Engine *pEngine); |
「Samegame.cpp」の「DrawStalemate関数」の下に「DrawScore関数」の本体を追加します。
//スコアの描画
void Samegame::DrawScore(Engine *pEngine)
{
pEngine->DrawNumber(
NUMBER_DEST_X,
NUMBER_DEST_Y,
m_score,
NUM_OF_DIGITS,
true,
NUMBER_SOUR_X,
NUMBER_SOUR_Y,
NUMBER_WIDTH,
NUMBER_HEIGHT,
TEXTURE_SAMEGAME);
}
|
第5引数がtrueになっていますので、前ゼロも描画する形式になっています。
「SceneGame.cpp」の「Draw関数」から呼び出して確かめてみましょう。
//============================================================================= // シーンの実行時に繰り返し呼び出される描画処理関数 //============================================================================= void SceneGame::Draw() { m_samegame.DrawBlock(m_pEngine); m_samegame.DrawScore(m_pEngine); if (m_bStalemate) { m_samegame.DrawStalemate(m_pEngine); } } |
実行してみましょう。
<実行結果 クライアント領域のみ>
「0」が5個並んでいればOKです。
次はスコアの計算方法を説明します。
インターネット上の「さめがめ」をプレイすると、一度に消したブロックの個数によって得点が変わるのが分かります。
表にしてみると↓のような感じです。
消した個数 得点 2個 0点 3個 1点 4個 4点 5個 9点 6個 16点 7個 25点 8個 36点 9個 49点
個数と得点の関係が分かりましたか?
得点を式に変えてみると分かりやすいかも知れません。
消した個数 得点 式 2個 0点 0×0 3個 1点 1×1 4個 4点 2×2 5個 9点 3×3 6個 16点 4×4 7個 25点 5×5 8個 36点 6×6 9個 49点 7×7
消した個数から得点を求める式は、
(消した個数 − 2) * (消した個数 − 2) = 得点
で行けそうです。
書き換えると、
(消した個数 − 2)の2乗 = 得点
ですから、消した個数が多ければ多いほど高得点になります。
「Samegame.cpp」の「DeleteBlock関数」を開き、コードを追加しましょう。
//ブロックを消す void Samegame::DeleteBlock() { if (m_selectBlockNum <= 1) { return; } DeleteSelectBlock(); FallBlock(); SlideLine(); m_score += (m_selectBlockNum - 2) * (m_selectBlockNum - 2); } |
「m_selectBlockNum」には選択してあるブロックの個数が入っています。
ブロックを消した後で、得点を計算しスコアに加えていきます。
では実行してみましょう。
<実行結果 クライアント領域のみ>
上手くブロックを消していき、なるべく同じ色がつながるようにしていきます。
上の赤いブロックを一気に消すと、
3,136点入りました!