この神経衰弱は2人対戦にする予定ですので、プレイヤークラスを追加します。
「Backクラス」「Cardクラス」「Memoryクラス」と同じように「Playerクラス」を追加してください。
そんなにボリュームは無いので、一気に作ります。
「Player.h」を開いてください。
//**************************************************************************** // // プレイヤークラス // //***************************************************************************** #pragma once #include "..\\..\\GameBase.h" //----------------------------------------------------------------------------- // クラスの宣言を書きます。 //----------------------------------------------------------------------------- class Player { public: Player(); void ScoreUp(); void DrawScore(Engine *pEngine, const int destX, const int destY) const; bool operator>(const Player &rhs) const; bool operator==(const Player &rhs) const; private: const int NUM_OF_DIGIT; //桁数 const int NUMBER_SOUR_X; //転送元左座標 const int NUMBER_SOUR_Y; //転送元上座標 const int NUMBER_WIDTH; //数字1つ分の幅 const int NUMBER_HEIGHT; //数字1つ分の高さ int m_score; }; |
メンバ変数としてはスコアのみ用意しました。
定数はスコア表示に必要な「DrawNumber関数」に渡すためのものです。
メンバ関数は、得点を増やす「ScoreUp関数」、スコアを表示する「DrawScore関数」を作ります。
後は勝敗判定のための演算子オーバーロードを2つ用意します。
「Player.cpp」を開き、本体を書きましょう。
//**************************************************************************** // // プレイヤークラス // //***************************************************************************** #define _USING_V110_SDK71_ 1 #include "Player.h" using namespace KeyString; using namespace InputKey; //----------------------------------------------------------------------------- // クラスメンバの本体を書きます。 //----------------------------------------------------------------------------- Player::Player() : NUM_OF_DIGIT(2) , NUMBER_SOUR_X(0) , NUMBER_SOUR_Y(1250) , NUMBER_WIDTH(30) , NUMBER_HEIGHT(50) , m_score(0) { } void Player::ScoreUp() { m_score++; } void Player::DrawScore(Engine *pEngine, const int destX, const int destY) const { pEngine->DrawNumber(destX, destY, m_score, NUM_OF_DIGIT, false, NUMBER_SOUR_X, NUMBER_SOUR_Y, NUMBER_WIDTH, NUMBER_HEIGHT, TEXTURE_TRUMP); } bool Player::operator>(const Player &rhs) const { return m_score > rhs.m_score; } bool Player::operator==(const Player &rhs) const { return m_score == rhs.m_score; } |
これでプレイヤークラスは完成です。
ゲームシーンにプレイヤーの実体を追加しましょう。
まずは「GameBase.h」でヘッダファイルをインクルードします。
//----------------------------------------------------------------------------- // オブジェクトのヘッダファイルをインクルードします。 //----------------------------------------------------------------------------- #include "Object\\Back\\Back.h" #include "Object\\Card\\Card.h" #include "Object\\Player\\Player.h" #include "Object\\Memory\\Memory.h" |
「SceneGame.h」を開き、2人分のプレイヤーを作成します。
private: //背景クラス Back m_back; //プレイヤークラス Player m_player1; Player m_player2; //神経衰弱クラス Memory m_memory; }; |
まずはスコアの表示を作りましょう。
Playerクラスの「DrawScore関数」は転送先座標を引数として受け取るようになっています。
プレイヤーは2人いるため、転送先座標が異なる事からこのように作りました。
「SceneGame.cpp」の「Draw関数」で、「DrawScore関数」を呼び出す事も出来ますが、神経衰弱のゲーム自体は「Memoryクラス」が管理していますので、「Memoryクラス」で描画する事にします。
「Memory.h」を開き、メンバ関数と定数を追加します。
//前方参照 class Card; class Player; class Memory { public: Memory(); ~Memory(); void Initialize(); void Shuffle(); void FaceUp(const POINT &refPoint); void DrawCard(Engine *pEngine); void DrawScore(Engine *pEngine, Player &refPlayer1, Player &refPlayer2) const; private: const int ADJUST_X; //中央に転送するための調整用X座標 const int ADJUST_Y; //中央に転送するための調整用Y座標 const int SHUFFLE; //シャッフル回数 const int RIGHT_LIMIT; //領域判定用の右端 const int BOTTOM_LIMIT; //領域判定用の下端 const int SCORE_DEST_X_PLAYER1; //プレイヤー1のスコア表示左座標 const int SCORE_DEST_Y_PLAYER1; //プレイヤー1のスコア表示上座標 const int SCORE_DEST_X_PLAYER2; //プレイヤー2のスコア表示左座標 const int SCORE_DEST_Y_PLAYER2; //プレイヤー2のスコア表示上座標 //カードクラス配列用ポインタ Card *m_pCard; int m_gameStatus; //ゲームステータス int m_savePos[2]; //座標保存用 }; |
プレイヤークラスの参照を使うため「前方参照」も追加しています。
「Memory.cpp」で実体を作りましょう。
定数の初期値を代入します。
Memory::Memory()
: ADJUST_X(60)
, ADJUST_Y(120)
, SHUFFLE(2000)
, RIGHT_LIMIT(ADJUST_X + Card::NUMBER * Card::SMALL_CARD_WIDTH)
, BOTTOM_LIMIT(ADJUST_Y + Card::SUIT * Card::SMALL_CARD_HEIGHT)
, SCORE_DEST_X_PLAYER1(175)
, SCORE_DEST_Y_PLAYER1(395)
, SCORE_DEST_X_PLAYER2(495)
, SCORE_DEST_Y_PLAYER2(395)
, m_pCard(NULL)
{
}
|
「DrawCard関数」の下に「DrawScore関数」を追加します。
void Memory::DrawScore(Engine *pEngine, Player &refPlayer1, Player &refPlayer2) const { refPlayer1.DrawScore(pEngine, SCORE_DEST_X_PLAYER1, SCORE_DEST_Y_PLAYER1); refPlayer2.DrawScore(pEngine, SCORE_DEST_X_PLAYER2, SCORE_DEST_Y_PLAYER2); } |
最後に「SceneGame.cpp」の「Draw関数」で呼び出します。
//============================================================================= // シーンの実行時に繰り返し呼び出される描画処理関数 //============================================================================= void SceneGame::Draw() { m_back.Draw(m_pEngine); m_memory.DrawCard(m_pEngine); m_memory.DrawScore(m_pEngine, m_player1, m_player2); } |
実行してスコアが表示されているかどうか確認しましょう。
<実行結果 クライアント領域のみ>
今のままでは、どちらのプレイヤーがカードをめくったのか分かりません。
プレイヤーのターンを管理する仕組みを組み込みます。
ゲームの管理は「Memoryクラス」の役割ですから「Memory.h」を開いてください。
//前方参照 class Card; class Player; class Memory { public: Memory(); ~Memory(); void Initialize(); void Shuffle(); void FaceUp(const POINT &refPoint); void DrawCard(Engine *pEngine); void DrawScore(Engine *pEngine, Player &refPlayer1, Player &refPlayer2) const; private: const int ADJUST_X; //中央に転送するための調整用X座標 const int ADJUST_Y; //中央に転送するための調整用Y座標 const int SHUFFLE; //シャッフル回数 const int RIGHT_LIMIT; //領域判定用の右端 const int BOTTOM_LIMIT; //領域判定用の下端 const int SCORE_DEST_X_PLAYER1; //プレイヤー1のスコア表示左座標 const int SCORE_DEST_Y_PLAYER1; //プレイヤー1のスコア表示上座標 const int SCORE_DEST_X_PLAYER2; //プレイヤー2のスコア表示左座標 const int SCORE_DEST_Y_PLAYER2; //プレイヤー2のスコア表示上座標 //カードクラス配列用ポインタ Card *m_pCard; int m_gameStatus; //ゲームステータス int m_savePos[2]; //座標保存用 enum { PLAYER1, PLAYER2, }; int m_playerTurn; //ターン管理用 }; |
プレイヤー定数として列挙体を用意し、ターン管理用の変数を追加しました。
「Memory.cpp」の「Initialize関数」でターンの初期値を設定します。
void Memory::Initialize()
{
m_pCard = new Card[Card::SUIT * Card::NUMBER];
for (int i = 0; i < Card::SUIT; i++) {
for (int j = 0; j < Card::NUMBER; j++) {
m_pCard[i * Card::NUMBER + j].Set(j + 1, i, false);
}
}
m_gameStatus = 0;
m_playerTurn = PLAYER1;
}
|
「Memory.cpp」の「FaceUp関数」で得点の追加とターンの切り替えを追加するため、プレイヤーを引数に加えます。
「Memory.h」を開いてください。
//前方参照 class Card; class Player; class Memory { public: Memory(); ~Memory(); void Initialize(); void Shuffle(); void FaceUp(const POINT &refPoint, Player &refPlayer1, Player &refPlayer2); void DrawCard(Engine *pEngine); void DrawScore(Engine *pEngine, Player &refPlayer1, Player &refPlayer2) const; private: const int ADJUST_X; //中央に転送するための調整用X座標 const int ADJUST_Y; //中央に転送するための調整用Y座標 const int SHUFFLE; //シャッフル回数 const int RIGHT_LIMIT; //領域判定用の右端 const int BOTTOM_LIMIT; //領域判定用の下端 const int SCORE_DEST_X_PLAYER1; //プレイヤー1のスコア表示左座標 const int SCORE_DEST_Y_PLAYER1; //プレイヤー1のスコア表示上座標 const int SCORE_DEST_X_PLAYER2; //プレイヤー2のスコア表示左座標 const int SCORE_DEST_Y_PLAYER2; //プレイヤー2のスコア表示上座標 //カードクラス配列用ポインタ Card *m_pCard; int m_gameStatus; //ゲームステータス int m_savePos[2]; //座標保存用 enum { PLAYER1, PLAYER2, }; int m_playerTurn; //ターン管理用 }; |
「FaceUp関数」の引数にプレイヤーへの参照を追加しました。
「Memory.cpp」を開き、「FaceUp関数」本体にもコードを追加します。
void Memory::FaceUp(const POINT &refPoint, Player &refPlayer1, Player &refPlayer2) { if (m_gameStatus < 2) { if (refPoint.x >= ADJUST_X && refPoint.x < RIGHT_LIMIT && refPoint.y >= ADJUST_Y && refPoint.y < BOTTOM_LIMIT) { POINT idx; idx.x = (refPoint.x - ADJUST_X) / Card::SMALL_CARD_WIDTH; idx.y = (refPoint.y - ADJUST_Y) / Card::SMALL_CARD_HEIGHT; int index = idx.y * Card::NUMBER + idx.x; if (!m_pCard[index].IsFaceUp() && m_pCard[index].IsShow()) { m_pCard[index].FaceUp(); m_savePos[m_gameStatus] = index; m_gameStatus++; } } } else { if (m_pCard[m_savePos[0]] == m_pCard[m_savePos[1]]) { if (m_playerTurn == PLAYER1) { refPlayer1.ScoreUp(); } else { refPlayer2.ScoreUp(); } m_pCard[m_savePos[0]].Hide(); m_pCard[m_savePos[1]].Hide(); } else { if (m_playerTurn == PLAYER1) { m_playerTurn = PLAYER2; } else { m_playerTurn = PLAYER1; } m_pCard[m_savePos[0]].FaceDown(); m_pCard[m_savePos[1]].FaceDown(); } m_gameStatus = 0; } } |
引数の追加、得点アップ、ターン切り替えと付け加えました。
最後に「SceneGame.cpp」を開き、「Update関数」のコードを変更します。
//============================================================================= // シーンの実行時に繰り返し呼び出される更新処理関数 //============================================================================= void SceneGame::Update() { if (m_pEngine->GetMouseButtonSync(DIK_LBUTTON)) { POINT point = m_pEngine->GetMousePosition(); m_memory.FaceUp(point, m_player1, m_player2); } } |
それでは、実行してみましょう。
遊べるようになってきました。
<実行結果 クライアント領域のみ>