功能实现

  1. 卡牌类实现
  2. 玩家类实现
  3. 绘制卡牌
  4. 抽牌

卡牌类

我们定义一个卡牌类,让它继承自按钮类,因为仔细想想,卡牌其实就类似于可拖拽的按钮。

在 Card.h 中把我们能想到的之后会用到的属性都写出来,值得注意的是,卡牌的类型定义了一个null,这是因为我们玩家类有手牌的属性,我们把初始手牌都设定为null的状态

#pragma once
#include "Button.h"
class Card : public Button {
public:
    enum e_cardType {
        attack, mp, magic, movePower, fightBack, equip, null //红色攻击牌,法力牌,咒术牌,行动力牌,反制牌,装备牌,空
    };
    enum e_cardState {
        cardPool, handPool, disCardPool, noPool            //卡牌的状态,卡池,手牌区,弃牌区,被移除
    };
    int cost;            //消耗点数
    int damage;            //物理伤害
    int getMp;            //获得魔法
    int reduceMagic;    //消耗魔法
    int getMovePower;    //获得行动力
    int getHp;            //加血
    int superHp;        //血量上限
    bool destory;        //是否“移除”卡牌
    bool getCard;        //抽牌
    int getCardNum;        //抽牌数
    int cardType;        //卡牌种类
    int cardState;        //卡牌状态
    bool discard;        //是否可弃牌
    Card();
};

在 Card.cpp 中完成构造函数

#include "Card.h"
Card::Card() {
    cardState = 0;        //默认状态为在卡池中
    destory = false;    //是否销毁(放入移除区)
    discard = true;        //是否放入弃牌区
}

玩家类

首先是Player.h

跟卡牌类一样,把我们暂时能想到的都先写上去~

这里我们定义一个表示手牌的指针数组,直接指向我们加载的卡牌们,对它们的属性进行修改来达到“手牌”的效果

#pragma once
#include "Card.h"
class Player {
public:
    Player();
    int handMaxNum = 8;
    Card *handCards[8];                //手牌[数量上限]
    int handCardNums;                //手牌数目
    int getCardNum;                    //抽牌数目
    void getCard(Card[], int);            //抽牌
    void disCard();                    //弃牌
    bool getCardState;                    //玩家可否抽牌
};

然后完善Player.cpp

#include "Player.h"
Player::Player() {
    getCardState = true;                        //可否抽牌
    handCardNums = 0;                            //目前手牌数目
    getCardNum = 5;                                //抽牌数目
}
int getRandom(int min, int max) {                    //获取从min到max的随机数
    int random = rand() % (max - min + 1) + min;
    return random;
}
void Player::getCard(Card card[], int cardsLength) {
    for (int i = handCardNums; i < handCardNums + getCardNum; i++) {        //从 handCards[手牌数] 到 handCards[手牌数+抽牌数]给handCards赋值
        int index = getRandom(0, cardsLength);                                //获取范围(0,卡牌数量)的随机数
        if (card[index].cardState == 0) {                                    //如果卡牌在卡池里
            card[index].cardState = 1;                                        //卡牌移到手牌区
            handCards[handCardNums] = &card[index];                            //手牌数组赋值
            handCardNums += 1;                                                //手牌数加一
        }
    }
}

然后在Game.h中定义我们的贴图啊,卡牌啊,玩家啊啥的

这里我们先加载三张卡牌试下水

Card cards[3], nullCard;                                        //卡牌数组,“空“卡牌
Texture tCard1[3][100];                                            //卡牌纹理数组
Player humanPlayer, aiPlayer;                                    //人类玩家与ai玩家

然后是Game.cpp,先暂时这么写,之后我们会优化代码

抽牌的实现

加载卡片

void Game::Initial() {
    ////
    nullCard.cardState = nullCard.null;
    for (int i = 0; i < humanPlayer.handMaxNum; i++) {        //填充手牌数组
        humanPlayer.handCards[i] = &nullCard;
    }
}
void Game::loadMediaData() {
    ///
    loadCards();
}
void Game::loadCards() {
    tCard1[0][0].loadFromFile("data/card1/card0.png");
    tCard1[1][0].loadFromFile("data/card1/card1.png");
    tCard1[2][0].loadFromFile("data/card1/card2.png");
    tCard1[0][1].loadFromFile("data/card1/card3.png");
    tCard1[1][1].loadFromFile("data/card1/card4.png");
    tCard1[2][1].loadFromFile("data/card1/card5.png");
    tCard1[0][2].loadFromFile("data/card1/card6.png");
    tCard1[1][2].loadFromFile("data/card1/card7.png");
    tCard1[2][2].loadFromFile("data/card1/card8.png");
    cards[0].setTextures(tCard1[0][0], tCard1[1][0], tCard1[2][0]);
    cards[1].setTextures(tCard1[0][1], tCard1[1][1], tCard1[2][1]);
    cards[2].setTextures(tCard1[0][2], tCard1[1][2], tCard1[2][2]);
}

交互事件

void Game::fightInput(Vector2i mousePosition, Event event) {
    ////
    for (int i = 0; i <= humanPlayer.handCardNums; i++) {
        if (humanPlayer.handCards[i]->cardState != humanPlayer.handCards[i]->null) {
            humanPlayer.handCards[i]->checkMouse(mousePosition, event);        //卡片事件
        }
    }
}

绘制卡牌

void Game::drawFight() {                    //战斗场景
    ////
    drawCard();
}
void Game::drawCard() {
    cards[0].setPosition(600, 500);
    cards[1].setPosition(700, 500);
    cards[2].setPosition(800, 500);
    if (humanPlayer.getCardState) {
        humanPlayer.getCard(cards, sizeof(cards) / sizeof(cards[0]));                //抽牌  获取数组大小
        humanPlayer.getCardState = false;
    }
    window.draw(*humanPlayer.handCards[0]);        //绘制手牌
    window.draw(*humanPlayer.handCards[1]);        //绘制手牌
    window.draw(*humanPlayer.handCards[2]);        //绘制手牌
    window.display();                        //展示屏幕
}

看下效果

好像出了点问题,怎么切换到战斗场景时卡牌还绘制的是退出战斗场景时的普通的状态

这里我找了将近4个 小时的bug,一直到凌晨4点,终于以为找到问题了,在某个地方加了一行代码后,试了几次可以正常绘制了,第二天再一测试,发现昨天其实是洗牌洗的和上次一样。。。

后来终于知道怎么解决了

在抽牌后立即设定卡牌贴图是普通状态

void Game::Draw() {
    ////
    switch (gameSceneState) {        //场景判断
        case SCENE_FIGHT:
            if (humanPlayer.getCardState) {
                humanPlayer.getCard(cards, sizeof(cards) / sizeof(cards[0]));                //抽牌  获取数组大小
                humanPlayer.getCardState = false;
                humanPlayer.handCards[0]->setState(0);        //设置贴图为普通状态
                humanPlayer.handCards[1]->setState(0);
                humanPlayer.handCards[2]->setState(0);
            }
            drawFight();
            break;
        default:
            break;
    }
}

最后是效果,已经可以实现随机抽牌了

Last modification:February 12th, 2021 at 06:14 am