cocos2d-x3.14中國象棋AI(四)獲取棋子和選中棋子

要獲取和選中棋子我們需要要在原來LayerGameMain基礎(chǔ)上添加多三個成員變量和六個成員函數(shù)秸苗。幾個函數(shù)和變量間依賴性比較高,大體實(shí)現(xiàn)功能分為:通過棋子id從數(shù)組獲取棋子、通過點(diǎn)擊選中棋子柱宦。

__Array *arrStone;
Sprite *selectBox;
int _selectedId;
Stone* getStoneFromArrById(int id);
int getStoneIdFromRowCol(int row, int col);
bool Screen2Plate(Point &point, int &row, int &col);
Point Plate2Screen(int row, int col);
void selectStone(Touch *pTouch);

這里先直接貼出LayerGameMain.h代碼

#ifndef __LAYERGAMEMAIN_H__
#define __LAYERGAMEMAIN_H__

#include "cocos2d.h"
#include "Plate.h"
#include "Stone.h"

/*
cocos2d-x3.14.1版本將大部分類的前綴CC去掉了总寒,不過有部分還是兼容抽米,如果用舊的命名創(chuàng)建對應(yīng)的類會有警告提示/錯誤提示
*/

USING_NS_CC;

class LayerGameMain : public Layer
{
public:
    static Scene* createScene();
    virtual bool init();
    CREATE_FUNC(LayerGameMain);

    //添加棋盤和棋子
    void addPlate();//用于在LayerGameMain上添加棋盤層/精靈
    void addStones();//用于在LayerGameMain上添加棋子層/精靈

    //觸摸事件回調(diào)函數(shù)
    bool touchBeganCallBack(Touch *pTouch, Event *pEvent);
    void touchEndedCallBack(Touch *pTouch, Event *pEvent);

    //選中棋子相關(guān)
    Sprite *selectBox;//選中款精靈
    int _selectedId;//標(biāo)記當(dāng)前選中的棋子id特占,沒有點(diǎn)中為-1
    bool Screen2Plate(Point &point, int &row, int &col);//循環(huán)棋盤上所有點(diǎn),通過Plate2Screen獲取到棋子中心點(diǎn)云茸,用引用輸出中心點(diǎn)
    Point Plate2Screen(int row, int col);//獲取棋子中心點(diǎn)返回到世界坐標(biāo)給Screen2Plate
    void selectStone(Touch *pTouch);//選中棋子是目,將選中框精靈移動到選中的棋子上

    //獲取棋子相關(guān)
    __Array *arrStone;//用于存放棋子
    Stone* getStoneFromArrById(int id);//通過棋子id從arrStone獲取對應(yīng)棋子
    int getStoneIdFromRowCol(int row, int col);//通過行列獲取棋子id
};

#endif // !__LAYERGAMEMAIN_H__

獲取棋子

想要獲取棋子就需要先將它們放進(jìn)一個數(shù)組中管理起來,然后通過一些函數(shù)方法從數(shù)組中取出我們想要的棋子标捺。這里使用的是cocos的數(shù)組類懊纳,也可以用vector存儲。

我們直接上對應(yīng)代碼亡容,因?yàn)樾枰跏蓟瘮?shù)組嗤疯,所以先貼出init函數(shù)

bool LayerGameMain::init()
{
    if (!Layer::init())
    {
        return false;
    }
    arrStone = __Array::create();
    arrStone->retain();//計(jì)數(shù)器+1,否則會被回收
    selectBox = Sprite::create("selected.png");
    selectBox->setVisible(false);
    selectBox->setZOrder(1000);//設(shè)置顯示優(yōu)先級
    this->addChild(selectBox);

    this->addPlate();
    this->addStones();

    //cocos2d-x3.14.1觸摸事件闺兢,創(chuàng)建監(jiān)聽
    EventDispatcher* eventDispatcher = Director::getInstance()->getEventDispatcher();
    auto listener = EventListenerTouchOneByOne::create();
    listener->setEnabled(true);
    listener->setSwallowTouches(true);
    listener->onTouchBegan = CC_CALLBACK_2(LayerGameMain::touchBeganCallBack, this);
    listener->onTouchEnded = CC_CALLBACK_2(LayerGameMain::touchEndedCallBack, this);
    eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

    return true;
}

通過id從數(shù)組獲取棋子函數(shù)

Stone* LayerGameMain::getStoneFromArrById(int stoneId)
{
    Stone *ret;
    ret = nullptr;
    if (stoneId > 0)
    {
        ret = (Stone *)arrStone->getObjectAtIndex(stoneId);
    }
    
    return ret;
}

有必要提一下茂缚,棋子數(shù)組初始化后并沒有掛在渲染樹上,一幀之后就會被回收屋谭,這里涉及到內(nèi)存管理計(jì)數(shù)器問題脚囊,我們需要在初始化數(shù)組時讓數(shù)組調(diào)用retain()函數(shù)使計(jì)數(shù)器+1。

選中棋子

當(dāng)我們選中棋子時桐磁,我們希望看到棋子被選中后有所反饋悔耘,那么我們就需要一個選中框精靈重疊在棋子上面以得到我們想要的效果。那么要把選中框重疊在棋子上就必需先知道棋子的行和列我擂,想得到棋子的行列就需要先知道被點(diǎn)擊棋子的中心點(diǎn)衬以,想知道棋子的中心點(diǎn)就必需先知道玩家觸摸點(diǎn)的位置。
這樣我們就可以通過倒著推過去來寫我們需要的函數(shù)校摩。玩家觸摸點(diǎn)的位置可以通過cocos的觸摸事件獲得看峻,棋子中心點(diǎn)可以通過遍歷棋盤上所有的點(diǎn)并通過觸點(diǎn)與棋盤點(diǎn)的距離是否小于半徑判斷是否選中棋盤上的點(diǎn),如果棋盤上的點(diǎn)存在棋子秧耗,那么該點(diǎn)即為棋子中心點(diǎn)备籽,在獲得棋子中心點(diǎn)后可以通過棋子自身屬性獲取棋子的行列位置,通過棋子的行列位置我們可以將其換算成世界坐標(biāo)分井,最后這個世界坐標(biāo)就是我們選中框的位置。

將棋子的相對棋盤坐標(biāo)轉(zhuǎn)換為世界坐標(biāo)

Point LayerGameMain::Plate2Screen(int row, int col)//該函數(shù)與Stone的getPositionFromPlate類似
{
    Point ret = Point(Stone::_offx + col*Stone::_d, Stone::_offy + row*Stone::_d);
    
    return ret;
}

遍歷棋盤上所有的點(diǎn)并通過觸點(diǎn)與棋盤點(diǎn)的距離判斷是否選中該點(diǎn)上的棋子霉猛,如果棋盤點(diǎn)上有棋子返回true

bool LayerGameMain::Screen2Plate(Point &point, int &row, int &col)
{
    int distance = Stone::_d/2 * Stone::_d/2;//以半徑作為距離
    for (row = 0; row <= 9; row++)
    {
        for (col = 0; col <= 8; col++)
        {
            Point ptCenter = Plate2Screen(row, col);
            if (distance > ptCenter.getDistanceSq(point))//獲取點(diǎn)距的平方并比較尺锚,如果小于半徑平方則為能選中中心點(diǎn)上的棋子
            {
                return true;
            }
        }
    }

    return false;
}

通過棋子行列獲取棋子id,當(dāng)行列上沒有棋子時返回-1

int LayerGameMain::getStoneIdFromRowCol(int row, int col)
{
    int ret = -1;
    Ref *obj;
    CCARRAY_FOREACH(arrStone,obj)
    {
        Stone *stone = (Stone *)obj;
        if (stone->_row == row && stone->_col == col)
        {
            ret = stone->_id;
            return ret;
        }
    }
    return ret;
}

選棋操作

void LayerGameMain::selectStone(Touch *pTouch)
{
    Point point = pTouch->getLocation();
    int row, col;
    if (!Screen2Plate(point, row, col))//點(diǎn)中范圍不在棋盤上直接返回
    {
        selectBox->setVisible(false);
        return;
    }
    int clickedid = getStoneIdFromRowCol(row, col);
    if (clickedid < 0)//沒選中棋子直接返回
    {
        selectBox->setVisible(false);
        return;
    }
    Stone *clickedStone = getStoneFromArrById(clickedid);

    selectBox->setPosition(Plate2Screen(row, col));
    selectBox->setVisible(true);

    _selectedId = clickedid;//記錄下棋子id
}

最后貼出修改后LayerGameMain的代碼惜浅,頭文件在上面已經(jīng)貼出瘫辩,這里就不再貼出了。
LayerGameMain.cpp

#include "LayerGameMain.h"


Scene* LayerGameMain::createScene()
{
    auto ret = Scene::create();
    auto layer = LayerGameMain::create();
    ret->addChild(layer);

    return ret;
}

bool LayerGameMain::init()
{
    if (!Layer::init())
    {
        return false;
    }
    arrStone = __Array::create();
    arrStone->retain();//計(jì)數(shù)器+1,否則會被回收
    selectBox = Sprite::create("selected.png");
    selectBox->setVisible(false);
    selectBox->setZOrder(1000);//設(shè)置顯示優(yōu)先級
    this->addChild(selectBox);

    this->addPlate();
    this->addStones();

    //cocos2d-x3.14.1觸摸事件伐厌,創(chuàng)建監(jiān)聽
    EventDispatcher* eventDispatcher = Director::getInstance()->getEventDispatcher();
    auto listener = EventListenerTouchOneByOne::create();
    listener->setEnabled(true);
    listener->setSwallowTouches(true);
    listener->onTouchBegan = CC_CALLBACK_2(LayerGameMain::touchBeganCallBack, this);
    listener->onTouchEnded = CC_CALLBACK_2(LayerGameMain::touchEndedCallBack, this);
    eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

    return true;
}

void LayerGameMain::addPlate()
{
    Plate *plate = Plate::create();
    
    this->addChild(plate);
}

void LayerGameMain::addStones()
{
    int i = 0;
    Stone *stone;
    for (i = 0; i < 32; i++)
    {
        stone = Stone::create(i);
        arrStone->addObject(stone);//將棋子添加進(jìn)數(shù)組
        this->addChild(stone);
    }
}

Stone* LayerGameMain::getStoneFromArrById(int stoneId)
{
    Stone *ret;
    ret = nullptr;
    if (stoneId > 0)
    {
        ret = (Stone *)arrStone->getObjectAtIndex(stoneId);
    }
    
    return ret;
}

bool LayerGameMain::touchBeganCallBack(Touch *pTouch, Event *pEvent)
{

    return true;
}
void LayerGameMain::touchEndedCallBack(Touch *pTouch, Event *pEvent)
{
    selectStone(pTouch);
}

bool LayerGameMain::Screen2Plate(Point &point, int &row, int &col)
{
    int distance = Stone::_d/2 * Stone::_d/2;//以半徑作為距離
    for (row = 0; row <= 9; row++)
    {
        for (col = 0; col <= 8; col++)
        {
            Point ptCenter = Plate2Screen(row, col);
            if (distance > ptCenter.getDistanceSq(point))//獲取點(diǎn)距的平方并比較承绸,如果小于半徑平方則為能選中中心點(diǎn)上的棋子
            {
                return true;
            }
        }
    }

    return false;
}
Point LayerGameMain::Plate2Screen(int row, int col)//該函數(shù)與Stone的getPositionFromPlate類似
{
    Point ret = Point(Stone::_offx + col*Stone::_d, Stone::_offy + row*Stone::_d);
    
    return ret;
}
int LayerGameMain::getStoneIdFromRowCol(int row, int col)
{
    int ret = -1;
    Ref *obj;
    CCARRAY_FOREACH(arrStone,obj)
    {
        Stone *stone = (Stone *)obj;
        if (stone->_row == row && stone->_col == col)
        {
            ret = stone->_id;
            return ret;
        }
    }
    return ret;
}

void LayerGameMain::selectStone(Touch *pTouch)
{
    Point point = pTouch->getLocation();
    int row, col;
    if (!Screen2Plate(point, row, col))//點(diǎn)中范圍不在棋盤上直接返回
    {
        selectBox->setVisible(false);
        return;
    }
    int clickedid = getStoneIdFromRowCol(row, col);
    if (clickedid < 0)//沒選中棋子直接返回
    {
        selectBox->setVisible(false);
        return;
    }
    Stone *clickedStone = getStoneFromArrById(clickedid);

    selectBox->setPosition(Plate2Screen(row, col));
    selectBox->setVisible(true);

    _selectedId = clickedid;//記錄下棋子id
}

運(yùn)行效果:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市挣轨,隨后出現(xiàn)的幾起案子军熏,更是在濱河造成了極大的恐慌,老刑警劉巖卷扮,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荡澎,死亡現(xiàn)場離奇詭異,居然都是意外死亡晤锹,警方通過查閱死者的電腦和手機(jī)摩幔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鞭铆,“玉大人或衡,你說我怎么就攤上這事〕邓欤” “怎么了封断?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長艰额。 經(jīng)常有香客問我澄港,道長,這世上最難降的妖魔是什么柄沮? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任回梧,我火速辦了婚禮,結(jié)果婚禮上祖搓,老公的妹妹穿的比我還像新娘狱意。我一直安慰自己,他們只是感情好拯欧,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布详囤。 她就那樣靜靜地躺著,像睡著了一般镐作。 火紅的嫁衣襯著肌膚如雪藏姐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天该贾,我揣著相機(jī)與錄音羔杨,去河邊找鬼。 笑死杨蛋,一個胖子當(dāng)著我的面吹牛兜材,可吹牛的內(nèi)容都是我干的理澎。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼曙寡,長吁一口氣:“原來是場噩夢啊……” “哼糠爬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起举庶,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤执隧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后灯变,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體殴玛,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年添祸,在試婚紗的時候發(fā)現(xiàn)自己被綠了滚粟。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡刃泌,死狀恐怖凡壤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情耙替,我是刑警寧澤亚侠,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站俗扇,受9級特大地震影響硝烂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜铜幽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一滞谢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧除抛,春花似錦狮杨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至喘漏,卻和暖如春护蝶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背翩迈。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工滓走, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人帽馋。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓搅方,卻偏偏與公主長得像,于是被迫代替她去往敵國和親绽族。 傳聞我的和親對象是個殘疾皇子姨涡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 我們在選中棋子之后理所當(dāng)然就是要移動棋子,要移動棋子我們不知需要知道選中的棋子點(diǎn)信息吧慢,還需要知道選中棋子后玩家下一...
    lable閱讀 534評論 0 0
  • 有做完上一篇的同學(xué)會發(fā)現(xiàn)涛漂,移動棋子存在很多bug,這也是正常检诗,我們只是寫了移動的規(guī)則匈仗,具體的細(xì)節(jié)并沒有完善,在這一...
    lable閱讀 505評論 0 0
  • 我們要通過AI類計(jì)算下一步棋該如何走的話就必需讓AI獲得當(dāng)前棋盤上棋子的局勢逢慌、輪到誰執(zhí)棋等各種棋盤上的信息悠轩,而這種...
    lable閱讀 1,489評論 1 3
  • 怎樣改掉愛說話的毛裁Σぁ何鸡? 柏拉圖說:理性是靈魂最高貴的因素。如他所說牛欢,我這個靈魂注定無法高貴骡男。 認(rèn)識我的人都知道,我...
    熊宴閱讀 5,087評論 2 3
  • 0谩8羰ⅰ!焰望!轉(zhuǎn)載請注明作者和本文鏈接Iб凇!P芾怠来屠! 最近因?yàn)楣ぷ鲀?nèi)容的變動,要去做后臺了震鹉,所以就入坑PHP俱笛。 在找PHP框架...
    CodingLady閱讀 7,644評論 0 0