本文基於前面兩篇文章,如果您還沒有看過,建議先閱讀下面兩篇文章:
更新Model
當用戶從工具箱中選一個小工具,然后把它放置到game board上面去時,我們需要編碼響應這些事件。在上一篇文章中,我們已經實現了GameBoardViewDelegate的touchedAtRow方法。我們還需要給這個協議再添加一個接口方法。如下所示:
@protocol GameBoardViewDelegate
- (void)gameBoard:(GameBoard *)gameBoard touchedAtRow:(int)row column:(int)column;
- (void)gameBoard:(GameBoard *)gameBoard toolboxItemTouchedAtIndex:(int)index;
@end
我們需要修改touch事件處理器,這樣就可以判斷我們到底是觸摸了工具箱還是game board。
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint point = [self convertTouchToNodeSpace:touch];
// touched on a game board
if (CGRectContainsPoint(gameBoardRectangle, point)) {
int row, column;
// calculate row and column based on a touch coordinate
// ...
// call controller
[self.delegate gameBoard:self.gameBoard touchedAtRow:row column:column];
}
// touched on a toolbox
else if (CGRectContainsPoint(toolboxRectangle, point)) {
int index;
// calculate toolbox item index based on a touch coordinate
[self.delegate gameBoard:self.gameBoard toolboxItemTouchedAtIndex:index];
}
}
在controller類里面處理touch事件是非常簡單的,我們只需要持有一個model的引用,然后基於touch事件來調用model的方法就行了。我們的接口看起來和下面差不多,只是省略掉了一些實現細節:
@interface GameBoard : NSObject {
// ...
}
// ...
- (void)putGamePiece:(GamePiece *)gamePiece row:(int)row column:(int)column;
- (GamePiece *)getGamePieceFromToolboxItemAtIndex:(int)index;
@end
然后,我們在GameBoardController里面完全實現GameBoardViewDelegate的兩個方法。
- (void)gameBoard:(GameBoard *)aGameBoard toolboxItemTouchedAtIndex:(int)index {
// keep the toolbox selection state in the Model
gameBoard.selectedToolboxItemIndex = index;
}
- (void)gameBoard:(GameBoard *)aGameBoard touchedAtRow:(int)row column:(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:row column:column];
}
}
到目前為止,我們實現了,用戶可以點擊工具箱中的小工具,然后把它們放置到game board中的一個小方塊上面,同時model類在中間起了橋梁作用。
通知view關於model的改變
為了在view里面反映出model的狀態更改,我們可以在model有變化的時候給view發送通知消息,然后view就可以根據不同的消息來作出不同的響應了。和我們在實現view通過controller一樣,這里我們也定義了一個GameBoardDelegate,用來通知view model的變化。
@protocol GameBoardDelegate;
@interface GameBoard : NSObject
// ...
@property (nonatomic, assign)
id<GameBoardDelegate> delegate;
// ...
@end
@protocol GameBoardDelegate
- (void)gameBoard:(GameBoard *)gameBoard didPutGamePiece:(GamePiece *)gamePiece row:(int)row column:(int)column;
@end
@implementation GameBoard
- (void)putGamePiece:(GamePiece *)gamePiece row:(int)row column:(int)column {
// ...
// store game piece
// notify that the game piece was put on a gameboard
[delegate gameBoard:self didPutGamePiece:gamePiece row:row column:column];
}
@end
在GameBoardView里面實現GameBoardDelegate的時候,當我們需要在game board上面放置一個小工具的時候,我們定義了一個CCSprite。
@interface GameBoardView : CCLayer
// ...
@end
@implementation GameBoardView
- (id)initWithGameBoard:(GameBoard *)aGameBoard delegate:(id)aDelegate {
if ((self = [super init])) {
// retain gameboard
self.gameBoard = aGameBoard;
self.gameBoard.delegate = self;
// assign delegate
self.delegate = aDelegate;
}
}
- (void)gameBoard:(GameBoard *)gameBoard didPutGamePiece:(GamePiece *)gamePiece row:(int)row column:(int)column {
// create CCSprite and put it on a game board at corresponding position
CCSprite *gamePieceSprite = [CCSprite spriteWithFile:fileName];
// ...
[self addChild:gamePieceSprite];
}
@end
總結
現在框架中所有的部分都聯系起來了,model、view和controller三者組成了著名的MVC模式
- View接收touch事件,然后把事件傳遞給controller,
- Controller 響應用戶的touch事件,然后更新model
- model 更新它自身的狀態, 處理游戲邏輯,然后告訴view它改變了哪些東西。
- View則基於Model當前的狀態來更新自己的顯示
后記:本文已同步更新到cocos2d mvc這個系列里面去了。
如果你覺得本文章對你有所幫助,請您點一下旁邊的“推薦”按鈕,這樣可以讓更多的人看到,同時也會給我寫作的動力,謝謝大家。