cocos2d-x 3.2 之 三消類遊戲——萬聖大作戰 (第三篇),cocos2d-x三消

來源:互聯網
上載者:User

cocos2d-x 3.2 之 三消類遊戲——萬聖大作戰 (第三篇),cocos2d-x三消

***************************************轉載請註明出處:http://blog.csdn.net/lttree********************************************




這是第三篇了,

前面已經建立了介面,建立的精靈,並且能自動消除精靈。

現在就要做我們的觸摸事件了

本文內容:

> 實現觸摸事件

> 實現交換的功能



1.觸摸事件

我們玩三消遊戲,就要對螢幕進行滑動,所以需要做一個觸摸事件來處理對螢幕的觸摸。

這裡主要是要獲得 開始觸摸 和 觸摸方向兩個,

因為只需要知道移動的起始精靈 和 移動的終止精靈。

所以,在遊戲介面的初始函數,進行觸摸事件的設定(綁定函數 和 添加監聽器)

// 觸摸事件處理    auto touchListener = EventListenerTouchOneByOne::create();    touchListener->onTouchBegan = CC_CALLBACK_2(GameScene::onTouchBegan, this);    touchListener->onTouchMoved = CC_CALLBACK_2(GameScene::onTouchMoved, this);    _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);


PS:關於這個監聽器,共有五種   觸摸事件、鍵盤響應事件、加速記錄事件、滑鼠響應事件 和 自訂事件。而且 觸摸事件的監聽器 還分為兩種,單點觸摸 和 多點觸摸。

而且,在3.0版本以前,之前所用的 CCTouchBegan、CCTouchMoved、CCTouchEnd這些都已經被OUT了,現在是讓監聽器自己綁定函數。


再回到本文,之前說過,觸摸事件最重要的是得到 起始精靈 和 終止精靈,所以要定義這兩個變數,然後在onTouchBegan和onTouchMoved進行操作。

先是 onTouchBegan函數:

bool GameScene::onTouchBegan(Touch *touch, Event *unused){staSprite = NULL;endSprite = NULL;if ( isTouchEna ) {        auto location = touch->getLocation();staSprite = spriteOfPoint(&location);    }return isTouchEna;}


這裡出現了一個新變數——isTouchEna,從名字中可以看出它的作用,是否可以觸摸。

什麼時候不可以呢? 檢測是否有可消除精靈的時候,精靈正在下落的時候,均不可以觸摸。

這個變數還需要在前面設定一下,

要在建構函式中,設定變數為 true,

然後在 update函數中  isTouchEna = !isAction;    (如果精靈正在移動中,就應該忽視觸摸事件)

在這裡,又出現了一個工具函數——spriteOfPoint(根據觸摸點的位置,返回是地圖中哪個精靈)

// 根據觸摸的點位置,返回是地圖中哪個精靈SpriteShape *GameScene::spriteOfPoint(Point *point){    SpriteShape *spr = NULL;    Rect rect = Rect(0, 0, 0, 0);Size sz;sz.height=SPRITE_WIDTH;sz.width=SPRITE_WIDTH;for( int r = 0 ; r < ROWS ; ++r ){for( int c = 0 ; c < COLS ; ++c ){spr = map[r][c];if( spr ){rect.origin.x = spr->getPositionX() - ( SPRITE_WIDTH / 2);rect.origin.y = spr->getPositionY() - ( SPRITE_WIDTH / 2);rect.size = sz;if (rect.containsPoint(*point)) {return spr;}}}}        return NULL;}


然後是 onTouchMoved函數:

// 觸摸後移動的方向void GameScene::onTouchMoved(Touch *touch, Event *unused){// 如果沒有初始精靈 或者 觸摸事件不可行,直接返回if (!staSprite || !isTouchEna) {        return;    }    // 擷取 初始精靈 的行列    int row = staSprite->getRow();    int col = staSprite->getCol();    // 擷取移動到的 點 的位置    auto location = touch->getLocation();    auto halfSpriteWidth = SPRITE_WIDTH / 2;    auto halfSpriteHeight = SPRITE_WIDTH / 2;        auto  upRect = Rect(staSprite->getPositionX() - halfSpriteWidth,                        staSprite->getPositionY() + halfSpriteHeight,                        SPRITE_WIDTH,                        SPRITE_WIDTH);    // 判斷是在向哪個方向移動,    if (upRect.containsPoint(location)) {        ++row;        if ( row < ROWS ) {            endSprite = map[row][col];        }        swapSprite();        return;    }        auto  downRect = Rect(staSprite->getPositionX() - halfSpriteWidth,                        staSprite->getPositionY() - (halfSpriteHeight * 3),                        SPRITE_WIDTH,                        SPRITE_WIDTH);        if (downRect.containsPoint(location)) {        --row;        if ( row >= 0 ) {            endSprite = map[row][col];        }        swapSprite();        return;    }        auto  leftRect = Rect(staSprite->getPositionX() - (halfSpriteWidth * 3),                          staSprite->getPositionY() - halfSpriteHeight,                          SPRITE_WIDTH,  SPRITE_WIDTH);        if (leftRect.containsPoint(location)) {        --col;        if ( col >= 0 ) {            endSprite = map[row][col];        }        swapSprite();        return;    }        auto  rightRect = Rect(staSprite->getPositionX() + halfSpriteWidth,                          staSprite->getPositionY() - halfSpriteHeight,                          SPRITE_WIDTH,                          SPRITE_WIDTH);        if (rightRect.containsPoint(location)) {        ++col;        if ( col < COLS ) {endSprite = map[row][col];        }        swapSprite();        return;    }        // 否則,並非一個有效移動}


這裡還有一個函數 swapSprite,顧名思義,就是判斷好向哪個方向移動後,直接交換這兩個精靈。




2. 交換精靈

關於交換精靈,有兩種情況

> 交換後,滿足消除條件,消除

> 交換後,不滿足消除條件,返回原樣

所以,函數是這樣的:

// 交換精靈void GameScene::swapSprite(){// 移動中,不允許再次觸摸,執行動作設定為true    isAction = true;    isTouchEna = false;// 初始精靈 和 終止精靈 均不可為空if (!staSprite || !endSprite) {        return;    }    Point posOfSrc = staSprite->getPosition();Point posOfDest = endSprite->getPosition();    float time = 0.2;        // 在數組中交換位置map[ staSprite -> getRow() ][staSprite -> getCol() ] = endSprite;map[ endSprite -> getRow() ][endSprite -> getCol() ] = staSprite;    int tmpRow = staSprite->getRow();    int tmpCol = staSprite->getCol();    staSprite->setRow(endSprite->getRow());    staSprite->setCol(endSprite->getCol());    endSprite->setRow(tmpRow);    endSprite->setCol(tmpCol);        // 檢查是否能消除std::list<SpriteShape *> colChainListOfFirst;    getColChain(staSprite, colChainListOfFirst);        std::list<SpriteShape *> rowChainListOfFirst;    getRowChain(staSprite, rowChainListOfFirst);        std::list<SpriteShape *> colChainListOfSecond;    getColChain(endSprite, colChainListOfSecond);        std::list<SpriteShape *> rowChainListOfSecond;    getRowChain(endSprite, rowChainListOfSecond);        if (colChainListOfFirst.size() >= 3        || rowChainListOfFirst.size() >= 3        || colChainListOfSecond.size() >= 3        || rowChainListOfSecond.size() >= 3) {        // 如果能夠消除,僅僅進行移動(不會移動回來)        staSprite->runAction(MoveTo::create(time, posOfDest));        endSprite->runAction(MoveTo::create(time, posOfSrc));        return;    }        // 不能消除,則移動過去還要返回map[ staSprite -> getRow()][staSprite -> getCol() ] = endSprite;map[ endSprite -> getRow()][endSprite -> getCol() ] = staSprite;    tmpRow = staSprite->getRow();    tmpCol = staSprite->getCol();    staSprite->setRow(endSprite->getRow());    staSprite->setCol(endSprite->getCol());    endSprite->setRow(tmpRow);    endSprite->setCol(tmpCol);        staSprite->runAction(Sequence::create(                                      MoveTo::create(time, posOfDest),                                      MoveTo::create(time, posOfSrc),                                      NULL));    endSprite->runAction(Sequence::create(                                      MoveTo::create(time, posOfSrc),                                      MoveTo::create(time, posOfDest),                                      NULL));}



這裡,在看一下這個函數,

就是先擷取  初始精靈 和 終止精靈 的位置,

然後,只是單純在地圖中交換(後台交換,數組變動,在遊戲介面中還是沒有變動的)

判斷是否可以消除,如果可以消除了,那就執行動作 交換兩個精靈位置。

如果不可以消除,不要忘了把後台交換過的兩個精靈再交換過來,然後在執行兩個動作(就是交換一次,再交換回來)。

這裡,並不是先交換,再判斷,再執行接下來的動作;

而是,先後台數組交換,然後判斷,然後執行 交換一次加消除 還是 交換兩次動作。


好啦,編寫到這裡,我們可以運行一下,看看效果。

到這,精靈的交換已經完成了。



本文的代碼:  >這裡 <


***************************************轉載請註明出處:http://blog.csdn.net/lttree********************************************

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.