cocos2d meets MVC – Implementing simple board game part 2
NOVEMBER 5, 2011
Introducing model In the previous part we introduced the View and the Controller. To comply with MVC paradigm we need to add a model which will represent the current state of a game board. Our implementation now should contain the following classes: 1. GameBoardView - the View, 2. GameBoardController - the Controller. 3. GameBoard – the Model.
|
GameBoard implementationOur requirement (described in the first part) is that: …A game board is defined by a number of rows and columns, which may vary for different application levels. We implement it in the following way: @interface GameBoard : NSObject { NSInteger numberOfRows; NSInteger numberOfColumns; } - (id)initWithRows:(NSInteger)aNumberOfRows columns:(NSInteger)aNumberOfColumns; @property (nonatomic) NSInteger numberOfRows; @property (nonatomic) NSInteger numberOfColumns; @end
Please notice that the model extends NSObject – the model should contain just the state of a game board (and the methods to update this state) – we shouldn’t put any view related concerns here.
|
GameBoardView implementationWe need to modify the View and pass it the Model, we do this in initWithGameBoard method. @interface GameBoardView : CCNode { GameBoard *gameBoard; } @property (nonatomic, retain) GameBoard *gameBoard; - (id)initWithGameBoard:(GameBoard *)aGameBoard; // with Model @end
Our implementation of a GameBoardView can look like this (rendering game board spaces omitted to simplify the code): - (id)initWithGameBoard:(GameBoard *)aGameBoard { if ((self = [super init])) { // retain gameboard self.gameBoard = aGameBoard; // render gameboard background CCSprite *gameboardSprite = [CCSprite spriteWithFile:@"gameboard.png"]; gameboardSprite.anchorPoint = CGPointMake(0, 0); [self addChild:gameboardSprite]; // render spaces for (int i = 0; i < gameBoard.numberOfRows; i++) { for (int j = 0; j < gameBoard.numberOfColumns; j++) { // position and render game board spaces } } } return self; }
|
GameBoardControllerFinally the implementation of an init method in the Controller should be updated – the View needs to have the GameBoard model injected in its init method so we construct the game board in Controller (just for now) and pass it to the View (later on we will create a game board based on a level definition). - (id)init { if ((self = [super init])) { // initialize model gameBoard = [[GameBoard alloc] initWithRows:7 columns:9]; // initialize view view = [[GameBoardView alloc] initWithGameBoard:gameBoard]; [self addChild:view]; } return self; }
|
Handling touches |
GameBoardView updatesIn order to handle touches we need to slightly modify the View. We make it extend CCLayer instead of CCNode to have a possibility to handle touch events inside of it: @interface GameBoardView : CCLayer { ... }
The View itself should not be responsible for handling the actions that are results of user interaction with the game board so we will pass it to the Controller using protocol. @protocol GameBoardViewDelegate - (void)gameBoard:(GameBoard *)gameBoard touchedAtRow:(int)row column:(int)column; @end
We also modify the init method of a GameBoardView so we can pass a delegate object that will be responsible for handling the touches: - (id)initWithGameBoard:(GameBoard *)aGameBoard delegate:(id)aDelegate; And the implementation is: - (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint point = [self convertTouchToNodeSpace:touch]; // calculate row and column touched by the user and call a delegate method // ... [self.delegate gameBoard:self.gameBoard touchedAtRow:row column:column]; }
|
GameBoardController updatesGameBoardController will be responsible for handling user touches, so we need to implement a GameBoardViewDelegate in a GameBoardController: @interface GameBoardController : CCNode - (void)gameBoard:(GameBoard *)gameBoard touchedAtRow:(int)row column:(int)column { // do the game logic here and update view accordingly }
The last step is to modify the View initialization in the following way (in init method): // initialize view view = [[GameBoardView alloc] initWithGameBoard:gameBoard delegate:self];
|
source - 실제 구현한 부분 |
// // GameBoard.h // Mvc // // Created by James Yu on 12. 7. 6.. // Copyright (c) 2012년 __MyCompanyName__. All rights reserved. //
#import <Foundation/Foundation.h>
@interface GameBoard : NSObject {
NSInteger numberOfRows; NSInteger numberOfColumns; }
-(id)initWithRows:(NSInteger)aNumberOfRows columns:(NSInteger)aNumberOfColumns;
@property (nonatomic) NSInteger numberOfRows; @property (nonatomic) NSInteger numberOfColumns;
@end |
// // GameBoard.m // Mvc // // Created by James Yu on 12. 7. 6.. // Copyright (c) 2012년 __MyCompanyName__. All rights reserved. //
#import "GameBoard.h"
@implementation GameBoard
@synthesize numberOfRows; @synthesize numberOfColumns;
-(id)initWithRows:(NSInteger)aNumberOfRows columns:(NSInteger)aNumberOfColumns { self=[super init]; if(self) { } return self; }
@end |
// // GameBoardView.h // Mvc // // Created by James Yu on 12. 7. 6.. // Copyright 2012년 __MyCompanyName__. All rights reserved. //
#import <Foundation/Foundation.h> #import "cocos2d.h"
#import "GameBoard.h"
@protocol GameBoardViewDelegate -(void)gameBoard:(GameBoard*)gameBoard touchedAtRow:(int)row column:(int)column; @end
// need to modify the View and pass it the Model, // we do this in initWithGameBoard method.
@interface GameBoardView : CCLayer {
GameBoard *gameBoard; id<GameBoardViewDelegate> delegate; }
-(id)initWithGameBoard:(GameBoard *)aGameBoard delegate:(id)aDelegate;
@property (nonatomic, retain) GameBoard *gameBoard; @property (nonatomic, retain) id<GameBoardViewDelegate> delegate;
@end |
// // GameBoardView.m // Mvc // // Created by James Yu on 12. 7. 6.. // Copyright 2012년 __MyCompanyName__. All rights reserved. //
#import "GameBoardView.h"
@implementation GameBoardView
@synthesize gameBoard; @synthesize delegate;
-(id)initWithGameBoard:(GameBoard *)aGameBoard delegate:(id)aDelegate {
self =[super init];
if ( self ) {
self.isTouchEnabled=YES;
// retain gameboard self.gameBoard = aGameBoard; self.delegate = aDelegate;
// render gameboard background CCSprite *gameBoardSprite= [CCSprite spriteWithFile:@"icon.png"]; gameBoardSprite.anchorPoint=CGPointMake(0,0); [self addChild:gameBoardSprite];
// render spaces for( int i =0; i < gameBoard.numberOfRows; i++) { for( int j=0 ; i < gameBoard.numberOfColumns; j++ ) { // position and render game board spaces
} }
} return self; }
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"touch"); //UITouch *touch=[touches anyObject]; //CGPoint point=[self convertToNodeSpace:touch];
// calculate row and columns touched by the user and call a delegate method
//[self.delegate gameBoard:self.gameBoard touchedAtRow:row column:column]; [self.delegate gameBoard:self.gameBoard touchedAtRow:1 column:1];
}
@end |
// // GameBoardController.h // Mvc // // Created by James Yu on 12. 7. 6.. // Copyright 2012년 __MyCompanyName__. All rights reserved. //
#import <Foundation/Foundation.h> #import "cocos2d.h"
#import "GameBoardView.h"
#import "GameBoard.h"
@interface GameBoardController : CCNode<GameBoardViewDelegate> {
GameBoardView *view; GameBoard *gameBoard; }
-(void)gameBoard:(GameBoard*)gameBoard touchedAtRow:(int)row column:(int)column;
@end |
// // GameBoardController.m // Mvc // // Created by James Yu on 12. 7. 6.. // Copyright 2012년 __MyCompanyName__. All rights reserved. //
#import "GameBoardController.h"
// is responsible for initializing the view. // also holds a reference to GameBoardView for future needs.
@implementation GameBoardController
-(id)init {
self =[super init];
if ( self ) {
//view = [GameBoardView node]; //[self addChild:view];
// initialize model gameBoard=[[GameBoard alloc] initWithRows:7 columns:9];
// initialize view view = [[GameBoardView alloc] initWithGameBoard:gameBoard delegate:self];
[self addChild:view];
Protocol *p=@protocol(GameBoardViewDelegate); if ( [self conformsToProtocol:p] == YES ) { NSLog(@"app supports delegate protocol"); }
} return self; }
-(void)gameBoard:(GameBoard*)gameBoard touchedAtRow:(int)row column:(int)column {
NSLog(@"touch row[%d] column[%d]", row, column);
} @end |
'0.일반개발' 카테고리의 다른 글
Spring MVC (0) | 2015.04.29 |
---|---|
Spring MVC 개념 (0) | 2015.04.28 |
cocos2d 기초 강좌 - 기본 함수 (0) | 2012.06.01 |
Xcode 4.0 시뮬레이터에서 리소스가 반영되지 않을떄. (0) | 2012.05.30 |
Texture Packer (0) | 2012.05.25 |