斗地主源码下载
链接:https://pan.baidu.com/s/1b_ADdWrLE8di1SSlFfuYPQ 密码:uavm
1、创建一副扑克牌,写代码首先创建一张牌的类。如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
class Poker : public Sprite { public: Poker(); ~Poker(); static Poker* create(const char *pszFileName, const CCRect& rect); virtual void onEnter(); virtual void onExit(); virtual bool onTouchBegan(CCTouch *pTouch, CCEvent *pEvent); virtual void onTouchMoved(CCTouch *pTouch, CCEvent *pEvent); virtual void onTouchEnded(CCTouch *pTouch, CCEvent *pEvent); virtual void onTouchCancelled(CCTouch *pTouch, CCEvent *pEvent); void showFront();//显示正面 void showLast();//显示背面 Poker* copy();//拷贝 void setTouchPriority(int num); void SelectPkLuTou();//如果选择了牌就露出头 void SelectPkSuoTou();//如果选择了牌就缩头 private: CC_SYNTHESIZE(bool,m_isSelect,Select);//是否已选 CC_SYNTHESIZE(GameScene*,m_gameMain,GameMain); CC_SYNTHESIZE(bool,m_isDianJi,DianJi);//是否能被点击 CC_SYNTHESIZE(int,m_huaSe,HuaSe);//花色 CC_SYNTHESIZE(int,m_num,Num);//牌值 EventListenerTouchOneByOne* touchListener; }; |
然后我们用这个类写了一个函数来生成一张牌,该函数如下(位于源码GameScene中):
|
2、接下来我们就用来创建一副扑克牌了,请看代码(在GameScene文件中)GameScene
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
bool GameScene::createPokers(){ bool isRet = false; do { Size size = Director::sharedDirector()->getVisibleSize(); Poker* pk; //创建52个除大鬼小鬼外的牌 for (int i=0; i<4; ++i) { for (int j=0; j<13; ++j) { pk = selectPoker(i,j); pk->setPosition(ccp(size.width/2/*+j*20*/,size.height/2/*-i*20*/)); pk->showLast(); this->addChild(pk); this->m_arrPokers->addObject(pk); } } //创建小鬼 pk = selectPoker(Gui,XiaoGui); pk->setPosition(ccp(size.width/2,size.height/2/*-4*20*/)); pk->showLast(); this->addChild(pk); this->m_arrPokers->addObject(pk); //创建大鬼 pk = selectPoker(Gui,DaGui); pk->setPosition(ccp(size.width/2/*+20*/,size.height/2/*-4*20*/)); pk->showLast(); this->addChild(pk); this->m_arrPokers->addObject(pk); isRet = true; } while (0); return isRet; } |
3、洗牌
bool GameScene::xiPai(){
bool isRet = false;
do
{
for(int i=0; i<54; ++i)
{
Poker* pk1 = (Poker*)m_arrPokers->randomObject();
Poker* pk2 = (Poker*)m_arrPokers->randomObject();
m_arrPokers->exchangeObject(pk1,pk2);
}
isRet = true;
} while (0);
return isRet;
}
随机取两张牌并使之交换,进行54次,这样就把原先顺序打乱了。
牌洗完之后,下面就该一个一个向玩家发牌了,请看下面代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
void GameScene::SendPk(){ Poker* pk; if(m_iSendPk<51 && m_isSend)//前51张牌发给玩家 { pk = (Poker*)m_arrPokers->objectAtIndex(m_iSendPk); if(m_iSendPk%3 == 0)//给玩家发牌 MovePk(m_player,pk); else if(m_iSendPk%3 == 1)//给电脑1发牌 MovePk(m_npcOne,pk); else if(m_iSendPk%3 == 2)//给电脑2发牌 MovePk(m_npcTwo,pk); ++m_iSendPk; m_isSend = false; }else if (m_iSendPk>50 && m_iSendPk<54 && m_isSend)//留下三张地主牌 { pk = (Poker*)m_arrPokers->objectAtIndex(m_iSendPk); pk->showFront(); MovePk(m_Three,pk); ++m_iSendPk; m_isSend = false; } else if(m_iSendPk>53)//牌发完分析电脑玩家的牌型 { FenChaiNpcPai(m_npcOne); FenChaiNpcPai(m_npcTwo); m_iSendPk = 0; m_iState = 1; } } |
m_isSend的变量了,这个变量就是指发给某一个玩家的牌动画是否完成。我们再来看一下MovePk()的代码就有些明白了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void GameScene::MovePk(Player* play,Poker* pk) { CCMoveTo* move; CCCallFuncND* func; float time = 0.05; play->getArrPk()->addObject(pk);//从一副牌中选择pk这张牌 move = CCMoveTo::create(time,play->getPoint()); func = CCCallFuncND::create(this,callfuncND_selector(GameScene::func),play); CCSequence* sequence = CCSequence::create(move,func,NULL); pk->runAction(sequence); }
void GameScene::func(CCNode* pSender, void* pData){ Player* play = (Player*)pData; play->updatePkWeiZhi();//整理一个玩家手中的牌 m_isSend = true; } |
4、
头文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class Player : public CCObject { public: Player(); ~Player(); void updatePkWeiZhi();//设置牌的位置
private: CC_SYNTHESIZE(bool,m_isDiZhu,IsDiZhu);//是否为地主 CC_SYNTHESIZE(bool,m_isCall,Call);//是否已叫地主 CC_SYNTHESIZE(int,m_iCallNum,CallNum);//叫地主的分数 CC_SYNTHESIZE(CCArray*,m_arrPk,ArrPk);//手里拥有的扑克牌 CC_SYNTHESIZE(CCPoint,m_point,Point);//牌在桌面的初始位置 CC_SYNTHESIZE(int,m_iPlayerClass,PlayerClass);//玩家种类:0为玩家,1为电脑,2为显示的三张牌,3为玩家要出的牌,4为电脑1要出的牌,5为电脑2要出的牌 std::vector<PaiXing> m_vecPX;//保存牌型 CC_SYNTHESIZE(bool,m_isOutPk,IsOutPk);//玩家是否出牌true:出 false:不出 }; |
源文件
1 2 3 |
void Player::updatePkWeiZhi(){ CCSize size = CCDirector::sharedDirector()->getVisibleSize(); int x,y; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
//计算玩家牌和出的牌的初始位置 if(m_iPlayerClass == 0 || m_iPlayerClass == 3) { x = size.width/2-((m_arrPk->count()-1)*pkJianJu+pkWidth)/2; y = m_point.y; } else if(m_iPlayerClass == 1 || m_iPlayerClass == 4 || m_iPlayerClass == 5) { x = m_point.x; y = m_point.y; } else if(m_iPlayerClass == 2) { x = size.width/2-(m_arrPk->count()*pkWidth+(m_arrPk->count()-1)*pkJianJu)/2; y = m_point.y; } int num = 0; CCObject* object; //对牌进行排序 if(m_iPlayerClass != 3 && m_iPlayerClass != 4 && m_iPlayerClass != 5) for(int i=0; m_arrPk->count()!=0 && i<m_arrPk->count()-1; ++i) { for(int j=0; j<m_arrPk->count()-1-i; ++j) { Poker* pk1 = (Poker*)m_arrPk->objectAtIndex(j); Poker* pk2 = (Poker*)m_arrPk->objectAtIndex(j+1); if(pk1->getNum() < pk2->getNum()) m_arrPk->exchangeObject(pk1,pk2); } } //更新位置 CCARRAY_FOREACH(m_arrPk,object){ Poker* pk = (Poker*)object; if (m_iPlayerClass == 0 || m_iPlayerClass == 3) { pk->showFront(); pk->setPosition(ccp(x+num*pkJianJu+pkWidth/2,y)); } else if(m_iPlayerClass == 1 || m_iPlayerClass == 4 || m_iPlayerClass == 5) { pk->showFront(); if(m_iPlayerClass == 1) pk->showLast(); pk->setPosition(ccp(x,y-num*pkJianJu)); } else if(m_iPlayerClass == 2) { pk->setPosition(ccp(x+num*pkJianJu+num*pkWidth+pkWidth/2,y)); } ++num; } //改变牌的z值或牌的触摸优先 int i=m_arrPk->count()-1; CCARRAY_FOREACH(m_arrPk,object){ Poker* pk = (Poker*)object; //改变z值 if (m_iPlayerClass == 1 || m_iPlayerClass == 4 || m_iPlayerClass == 5) pk->setZOrder(size.height - pk->getPositionY()); if (m_iPlayerClass == 0 || m_iPlayerClass == 3) pk->setZOrder(pk->getPositionX()); //改变优先级 /* Poker* pk1 = (Poker *)m_arrPk->objectAtIndex(i--); pk->setTouchPriority(pk1->getPositionX());*/ } } |
这个类最主要的是 updatePkWeiZhi(),它是为了把玩家手中的牌从大到小排序并居中显示。请注意最后一块代码“改变牌的z值或牌的触摸优先级”,为什么要这么做呢?这是因为牌的顺序换了之后,底下的牌有的会覆盖到另一个牌之上,改变触摸优先级也是同理。
发完牌,下面就该叫地主了,首先从玩家(人)开始叫地主,下一回合所有玩家(包括电脑玩家)按逆时针顺序叫地主。我们来看一下叫地主的模块:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
void GameScene::Call(float dt){ //是否都叫过地主 if(!m_player->getCall() || !m_npcOne->getCall() || !m_npcTwo->getCall()) {
|