★神経衰弱 プレイヤーの追加★


この神経衰弱は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);
    }
}

それでは、実行してみましょう。


遊べるようになってきました。

<実行結果 クライアント領域のみ>


次へ

戻る

目次へ