cocos2d里面如何实现MVC(五)

    本文基于前面两篇文章,如果您还没有看过,建议先阅读下面两篇文章:

更新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这个系列里面去了。

    如果你觉得本文章对你有所帮助,请您点一下旁边的“推荐”按钮,这样可以让更多的人看到,同时也会给我写作的动力,谢谢大家。






posted on 2012-03-18 20:30  子龙山人  阅读(6325)  评论(5编辑  收藏  举报