Cocos2d-x裏面如何實現MVC(五)

本文基於前面兩篇文章,如果您還沒有看過,建議先閱讀下面兩篇文章:

· cocos2d-x裏面如何實現mvc(三)

· cocos2d-x裏面如何實現mvc(四)

更新Model

    當用戶從工具箱中選一個小工具,然後把它放置到game board上面去時,我們需要編碼響應這些事件。在上一篇文章中,我們已經實現了GameBoardViewDelegate的touchedAtRow方法。我們還需要給這個協議再添加一個接口方法。如下所示:

class GameBoardViewDelegate
{
public:
     virtual void touchAtGrid(GameBoard *gameBoard, int row, int column) = 0;
 virtual void touchWithToolBoxItemAtIndex(GameBoard *gameBoard, int index) = 0;
};
    我們需要修改touch事件處理器,這樣就可以判斷我們到底是觸摸了工具箱還是game board。
void GameBoardView::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
{
     CCTouch *touch = (CCTouch*) pTouches->anyObject();
     if(touch == NULL)
          return;
 
     // 置換座標,等效如下
     //CCPoint location = touch->locationInView(touch->view());
     //location = CCDirector::sharedDirector()->convertToGL(location);
     CCPoint point = this->convertTouchToNodeSpace(touch);
 
     // 下面假設遊戲區與工具區8:2來劃分寬度
     CCSize size = CCDirector::sharedDirector()->getWinSize();
     CCRect *gameBoardRectangle = new CCRect(0, 0, size.width*0.8, size.height);
     CCRect *toolBoxRectangle = new CCRect(size.width*0.8, 0, size.width*0.2, size.height);
 
     if(CCRect::CCRectContainsPoint(*gameBoardRectangle, point)){
          // calculate row and column touched by the user and call a delegate method 
          int row = 0;
          int column = 0;
          // ...
          this->gameBoardViewDelegate->touchAtGrid(gameBoard, row, column);
     } else if (CCRect::CCRectContainsPoint(*toolBoxRectangle, point)){
          int index = 0;
          // calculate toolbox item index based on a touch coordinate
          this->gameBoardViewDelegate->touchWithToolBoxItemAtIndex(gameBoard, index);
     }
}
    在controller類裏面處理touch事件是非常簡單的,我們只需要持有一個model的引用,然後基於touch事件來調用model的方法就行了。我們的接口看起來和下面差不多,只是省略掉了一些實現細節:

class GameBoard : public CCObject
{
public:
     // ...
     GamePiece* getGamePieceFromToolBoxItemAtIndex(int index);
public:
     // ...
     int selectedToolBoxItemIndex;
};
    然後,我們在GameBoardController裏面完全實現GameBoardViewDelegate的兩個方法。
void GameBoardController::touchAtGrid(GameBoard *gameBoard, int row, int column)
{
     // if the toolbox item is selected move item from toolbox to game board
     if(gameBoard->selectedToolBoxItemIndex != -1){
          GamePiece *gamePiece = gameBoard->getGamePieceFromToolBoxItemAtIndex(gameBoard->selectedToolBoxItemIndex);
          gameBoard->putGamePiece(gamePiece, row, column);
     }
}
 
void GameBoardController::touchWithToolBoxItemAtIndex(GameBoard *gameBoard, int index) {
    // keep the toolbox selection state in the Model
    gameBoard->selectedToolboxItemIndex = index;
}

    到目前爲止,我們實現了,用戶可以點擊工具箱中的小工具,然後把它們放置到game board中的一個小方塊上面,同時model類在中間起了橋樑作用。

通知view關於model的改變

    爲了在view裏面反映出model的狀態更改,我們可以在model有變化的時候給view發送通知消息,然後view就可以根據不同的消息來作出不同的響應了。和我們在實現view通過controller一樣,這裏我們也定義了一個GameBoardDelegate,用來通知view model的變化。

class GameBoardDelegate
{
public:
     virtual void didPutGamePiece(GamePiece *gamePiece, int row, int column) = 0;
};
 
class GameBoard : public CCObject
{
     // ...
public:
    void setGameBoardDelegate(GameBoardDelegate *aGameBoardDelegate);
private:
     GameBoardDelegate *gameBoardDelegate;
};
 
void GameBoard::putGamePiece(GamePiece *gamePiece, int row, int column)
{
     // ...   
     // store game piece    
     // notify that the game piece was put on a gameboard
     this->gameBoardDelegate->didPutGamePiece(gamePiece, row, column);
}
 
void GameBoard::setGameBoardDelegate(GameBoardDelegate *aGameBoardDelegate)
{
     this->gameBoardDelegate = aGameBoardDelegate;
}
    在GameBoardView裏面實現GameBoardDelegate的時候,當我們需要在game board上面放置一個小工具的時候,我們定義了一個CCSprite。
class GameBoardView :
    public CCLayer, public GameBoardDelegate
{
     // ...
};
 
void GameBoardView::initWithGameBoard(GameBoard *aGameBoard, GameBoardViewDelegate *aDelegate)
{
     // ...
     this->gameBoard = aGameBoard;
     this->gameBoard->retain();
     this->gameBoard->setGameBoardDelegate(this);
     this->gameBoardViewDelegate = aDelegate;
     // ...
}
 
void GameBoardView::didPutGamePiece(GamePiece *gamePiece, int row, int column)
{
     // create CCSprite and put it on a game board at corresponding position   
     CCSprite *gamePieceSprite = CCSprite::spriteWithFile("CloseNormal.png");
     // ...
     this->addChild(gamePieceSprite, 1);
}

總結

    現在框架中所有的部分都聯繫起來了,model、view和controller三者組成了著名的MVC模式

· View接收touch事件,然後把事件傳遞給controller,

· Controller 響應用戶的touch事件,然後更新model

· model 更新它自身的狀態, 處理遊戲邏輯,然後告訴view它改變了哪些東西。

· View則基於Model當前的狀態來更新自己的顯示 





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章