This is the 3rd part from the series how to build a simple puzzle game using cocos2d and MVC pattern. If you haven’t read previous parts I suggest you do it before reading this post:
Updating the Model
When the user touches the toolbox item and then touches the space on a game board we want that the game piece represented by a toolbox item will be placed on a game board at touch position. In the previous part we already implemented touchedAtRow method in GameBoardViewDelegate. We will extend this protocol and add additional method for handling toolbox item selection.
@protocol GameBoardViewDelegate - (void)gameBoard:(GameBoard *)gameBoard touchedAtRow:(int)row column:(int)column; - (void)gameBoard:(GameBoard *)gameBoard toolboxItemTouchedAtIndex:(int)index; @end
We need to change the implementation of our touches handler, so that we now detect whether we clicked on a toolbox or on a 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]; } }
Handling events on the Controller side is easy, first of all we extend the Model to keep the state of our model and allows us to modify the state based on user touches. Our interface will look something like this (implementation details omitted for clarity):
@interface GameBoard : NSObject { // ... } // ... - (void)putGamePiece:(GamePiece *)gamePiece row:(int)row column:(int)column; - (GamePiece *)getGamePieceFromToolboxItemAtIndex:(int)index; @end
Then we finish the implementation of GameBoardViewDelegate in GameBoardController and handle our events accordingly.
- (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]; } }
What we achieved so far is that when the user touches on of the toolbox item and then touches the space on a game board the Model gets updated reflecting the desired game board state.
Notifying the View about the changes in the Model
In order to reflect the state of the Model in the View we need to send some notifications so when the Model gets changed the View will be able to react upon it.
We do this the same way we notify the Controller about the View changes. We start from the delegate declaration inside the 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
The last part is the implementation of GameBoardDelegate in the GameBoardView so that when the game piece is put on a game board the View will put a CCSprite at a given position.
@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
Summary
All the pieces are now connected together. The interaction between the Model, the Controller and the View conforms to MVC paradigm:
- The View handles the touches and notifies the Controller,
- The Controller reacts upon the user touches and updates the Model,
- The model updates its state, does the logic and tells the View that it has been changed,
- The View updates itself based on the current Model state.




7 Comments
Thank you for taking the time to create this ‘blog’. Please can you make a sample project available for download so that I can further explore how you code fits together?
I plan to do this…
We have little bit experience in cococs2d for game development and little bit experience in MVC(java struts). this blog make very helpful for integrating both….
can you bind the project for downloads…
HI,
thanks for the info, it was very useful.
Question:If you had multiple scenes, and they all have lets say a options button in common, would it make scene to have a single super-class that is a CCScene that implements the options button and have the others scenes as subclasses to inherit the superclass behavior(options button) + have their own custom stuff?
if so, how would this fit into your mvc model, would you have multiple scene instances in the controller class and also have multiple GameBoardDelegate for each scene?
thanks
Hi,
You can put a standard behavior to your base Controller class and extend it by your subclasses that also add scene specific logic to it. This also applies to views. But be aware that creating a complex inheritance tree is not a good idea so in this case you might prefer composition over inheritance.
@interface GamePiece : NSObject
//How to achieve ?
@end
Hi! thanks for creating this tutorial it has been very helpful.
I seem to be missing something i doubled checked everything but the callback never gets to my controller for some reason i fail to see, can you point me in the right direction as where to look?
Also did you get to upload the project?
Thanks in advance