How to implement MVC pattern in cocos2d game–part 2

My last post about implementing MVC pattern in cocos2d was definitely lacking some code examples. I must admit – I was writing it on my PC notebook when I was on a business trip and I didn’t have an access to my game source code. This is a follow-up post to the previous one, so I suggest that you read it before this one.

Model classes

As described previously GameModel class stores information about game world properties, such as current gravity but it also is responsible for building and coordinating all other game models, such as Player and Platforms.

MVC in cocos2d - model

You may notice that all of my model classes implement update method from Updateable protocol. This is to ensure that all of my model class can update its status accordingly during game loop. For example in Player class I need to update player’s position based on its current velocity along x and y axes. In my example I delegate it to my Physics component which is a simple physics engine implementation of my own, but if your game is simpler and you don’t need to separate your physics code you can also do necessary calculations directly in your update method.

@implementation Player
- (void)update:(ccTime)dt
{
    [_physics updateModel:self dt:dt];
    // detect collisions with game objects, etc.
}

GameModel implementation of update method not only updates its own state, but it also needs to delegate update call to Player and Platforms. This method will be later on called by Controller game loop.

@implementation GameModel
- (void)update:(ccTime)dt
{
    // modify game model properties here
    // update player
    [self.player update:dt];
    // update platforms
    for (Platform *platform in _platforms) {
        [platform update:dt];
    }
    // ...
}

View and controller classes

For each of my game scene I have a separate Controller class which is responsible for handling user interactions, creating views and managing screen flow. Controller also schedules a main game loop from which the model and view is updated.

@implementation GameplayController
- (id)init
{
    if((self=[super init])) {
        GameplayView *view = [[GameplayView alloc] initWithDelegate:self];
	// retain view in controller
	self.view = view;
	// release view
	[view release];
 
	// init model
	GameModel *model = [GameModel sharedModel];
	[model createGameObjects];
	[model.player run];
 
	[self scheduleUpdate];
    }
}
 
- (void)update:(ccTime) dt
{
    GameModel *model = [GameModel sharedModel];
 
    if (model.isGameOver) {
	[[CCDirector sharedDirector] replaceScene:[GameOverController node]];
    }
 
    // process model
    [model update:dt];
 
    // update view
    [self.view update:dt];
}

View main responsibility is to render a model on screen but also, because of the way cocos2d is built, we need to also delegate touch events to Controller class from CCLayer classes. You should notice that view doesn’t directly depend on a Controller. View class calls controller methods via GameViewDelegate protocol that controller implements, that’s why we need to pass it as a parameter to init method.

@implementation GameplayView
- (id)initWithDelegate:(id)theDelegate
{
    if ((self = [super init])) {
        self.delegate = theDelegate;
 
	// initialize layers
	_backgroundLayer = [GameplayBackgroundLayer node];
	[self.delegate addChild: _backgroundLayer];
 
	_platformLayer = [GameplayPlatformLayer node];
	[self.delegate addChild:_platformLayer];
 
	_playerLayer = [GameplayPlayerLayer node];
	_playerLayer.delegate = theDelegate;
	[self.delegate addChild: _playerLayer];
 
	_hudLayer = [GameplayHudLayer node];
	_hudLayer.delegate = theDelegate;
        [self.delegate addChild:_hudLayer];
    }
 
    return self;
}

// EDIT: I realized I forgot to mention (thanks Zenkimoto) how the implementation of a layer itself look like
In a layer itself I pretty much do the standard stuff, like creating the sprites, actions, animations etc.

@implementation GameplayPlayerLayer
- (id)init
{
    if ((self = [super init])) {
        self.isTouchEnabled = YES;
	self.isAccelerometerEnabled = YES;
        ResourceManager *resources = [ResourceManager sharedResourceManager];
 
	[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:PLAYER_SPRITE_SHEET_PLIST];
 
	CCSpriteBatchNode *spriteSheet = [resources playerSpriteSheet];
	[self addChild:spriteSheet];
        // ... 
       // initialize sprites
       // initialize animations
}

Sprites on layers are updated in update method that all layers implement. In this method sprites properties are updated from the model in the following way:

- (void)update:(ccTime)dt 
{
    // update player sprite based on model
    GameModel *model = [GameModel sharedModel];
 
    _playerSprite.position = ccp((model.player.position.x - model.viewPort.rect.origin.x) * PPM_RATIO,  (model.player.position.y - model.viewPort.rect.origin.y) * PPM_RATIO);
}

Notice that in order to render sprite position I am using PPM_RATIO that I use to convert meters to points.
// end EDIT
Touch events are delegated to controller class via layer’s delegate as following:

@implementation GameplayPlayerLayer
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.delegate playerBeginJump];
}

And here is a complete picture of view and controller classes in a sample class diagram.

MVC in cocos2d - controllers

Handling model events

Open question from my last post was how to handle communication between model and controller classes. The answer is in dotted arrow between model and controller in MVC diagram – we can publish events from Model to which controller subscribes and responds accordingly. For example in Player model we can raise an event that player has just begun jumping:

@implementation Player
- (void)beginJump
{
    if ([_gameModel isOnGround:self]) {
        [[NSNotificationCenter defaultCenter] postNotificationName:EVENT_PLAYER_BEGIN_JUMP object:nil];
    ...
}

Controller observes the event, and when it happens it calls appropriate event handler to play sound.

@implementation GameplayController
- (id)init
{
    if ((self = [super init])) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onPlayerBeginJumpNotification:) name:EVENT_PLAYER_BEGIN_JUMP object:nil];
        ...
    }
}
 
- (void)onPlayerBeginJumpNotification:(NSNotification *)notification
{
    [[SimpleAudioEngine sharedEngine] playEffect:PLAYER_JUMP_SOUND];
}

That’s it

It might look a little bit complicated at first and you may be a bit scared with all of those classes that you need to add in order to make it work. But you need to remember that the belief that adding many classes makes the design complicated is a well known anti-pattern known as Fear of Adding Classes so if you are not such a believer I suggest you give this pattern a try – from my experience separating concerns and making different components responsible only for single thing is a principle that makes your design much better and pays off in future.

Be Sociable, Share!
This entry was posted in iPhone and tagged , , , , , , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

42 Comments

  1. Zenkimoto
    Posted November 5, 2010 at 2:47 am | Permalink

    Thanks for posting an example. Just a question, where are the CCSprites? Logic would tell me that they would be in the CCLayer, but how do you tie the model object back to the CCSprite?

    • Posted November 5, 2010 at 8:43 pm | Permalink

      Thanks for your comment. Your logic tells you well. CCSprites are created in CCLayer and positions and other properties of sprites and a layer itself are updated based on a model state. What’s the benefit here is that you don’t need to map model properties 1-1 to your sprite properties – in my example (that I updated based on your feedback :) I am multiplying x, y coordinates by points per meter ratio, but it’s just an example. In the other layer I might not want to update each sprites separately but rather update a position of a layer instead and move all containing sprites together.

  2. Jackson
    Posted November 28, 2010 at 3:11 am | Permalink

    Hi Bartek,
    Love the posts, got a question: Why is it on your model’s class diagram you have public + methods like + update but on your code examples you have them as private -? I’m thinking this might be a mistake on the diagrams since the model’s instantiated objects may not be accessible via public methods and since I’m trying to implement a project using the design pattern you’re discussing on these posts- I can confirm that the private update methods are correct.

    I’ve got another question too, in your posts you’ve mentioned if a game size is small it may be worth it to place the calculation on the update method. I have 2 rotating sprites that are supposed to be simulating 2 spools feeding from one to the other (maintaining a specific feed speed) and hence the 2 sprite’s angular speed is dependent on the amount of spooled radius on each of the sprites. Do you think that the calculation is better off done in the model or view? I think the model should handle this but I’m wondering if there is going to be any performance advantages. Would love to hear your comments on this.

    Cheers,
    Jackson

    • Posted November 29, 2010 at 5:16 pm | Permalink

      Hi Jackson,

      It’s not an mistake. Diagrams are done using UML notation in which “+” represents a public member. However in Obj-C “+” means a static (class) member and “-” instance member. Public / private modifier can be applied in a header file but by default methods are public. What’s more, update method is executed from external components that’s why it needs to be public. I hope it clarifies.

      Regarding your second question – I believe it’s better to do it in a model since model should always be responsible for handling its own logic and view should only be responsible for display. From the performance perspective it should not be a problem and you gain a lot having a game logic separated from a presentation when it comes to code maintanability.

      Regards,
      Bartek

  3. Jackson
    Posted December 3, 2010 at 4:08 am | Permalink

    Thanks for clarifying that for me. I understand it better now. Is it possible for you to explain the sharedModel method on your model?

  4. susim
    Posted December 7, 2010 at 3:47 pm | Permalink

    View class calls controller methods via “GameViewDelegate” protocol that controller implements, that’s why we need to pass it as a parameter to init method.
    @implementation GameplayView
    - (id)initWithDelegate:(id)theDelegate
    {
    if ((self = [super init])) {
    self.delegate = theDelegate;

    ……….

    I can’t understand that delegate part and ” “GameViewDelegate” protocol part.Can you explain that part. I am new in iphone developing .

    • Posted December 7, 2010 at 11:43 pm | Permalink

      View needs to invoke methods on controller (like adding layers to scene or pass touch events). Instead of passing Controller directly to a view we instead create a protocol called GameViewDelegate that Controller needs to implement. View then doesn’t call Controller methods directly but through a protocol.

    • susim
      Posted December 8, 2010 at 3:20 am | Permalink

      Thanks for reply.
      It is very good post.Your problem statement is exactly matched with my game.When logic grows code becomes more difficult to maintain.
      So I am trying to implement it according to your MVC logic.

  5. susim
    Posted December 8, 2010 at 6:37 am | Permalink

    GameplayView *view = [[GameplayView alloc] initWithDelegate:self];
    // retain view in controller
    self.view = view;

    In “self.view” what is the “view”? Where I have to declare that “view” and how?I am confused in that section also. I can’t find out anything “view” in that structure.Please explain that part.
    In that part whenever I write [self addChild:view];(here “view” is the “GameplayView” object” ).GamePlayView appear in the scene but what I have to write in update section part of controller to update “GameplayView”.
    that you have done in the following way
    // update view
    [self.view update:dt];

    self.delegate = theDelegate;
    In self.delegate what is the delegate??Same confusion here also.

    • Posted December 8, 2010 at 9:27 pm | Permalink

      You need to declare retained property in your controller’s header file because you would need this instance in another method. This is a known pattern for retaining objects in properties -> http://xperienced.com.pl/blog/5-most-important-rules-of-memory-management-in-obj-c

      GamePlayController.h

      @interface GamePlayController
      @property (nonatomic, retain) GameplayView *view;
      @end

      The same for delegate, in your GameplayView.h file:

      @interface GameplayView
      @property (nonatomic, assign) id delegate;
      @end

      • susim
        Posted December 9, 2010 at 6:39 am | Permalink

        Thanks for reply.
        Now I understand it.Thanks for really good and helpful concept.

  6. Kevin
    Posted December 11, 2010 at 7:26 pm | Permalink

    Thanks for this article!
    Very well written. Will definitely start experimenting with this approach for my next game.

  7. Emilio
    Posted December 27, 2010 at 12:52 pm | Permalink

    Hi Bartek
    Thanks for your posts, very useful, i have been looking for something like that but somehow people think cocos2d and mvc should not get together.

    I have several questions, as i have tried to develop a game on cocos2d following my understanding of MVC without success until i read your posts; now i have a basic framework which at least works! :-)

    a) At Handling model events section you say controller should observe model events and this matches the dotted line on the MVC diagram, but there is no such dotted line among them in the traditional mvc model. In Apple MVC such relationship exists, but there is no direct relation ship between View and Model that your are using to update players position e.g.
    Which MVC Model do you think is best for a game in cocos2d?

    Accessing the model properties directly from the view seems much easier and faster but goes against apple recommendation to improve reusability.

    b) Which software are you using for the uml drawings?

    c) Can you publish the basic code of the Controller? Inteface and implementation, i am having problems extending CCScene, so i am extending CCLayer in the Controller but i am curious about how you are doing it.

    • Posted December 27, 2010 at 8:44 pm | Permalink

      Hi Emilio,

      I am happy that you find my blog post useful :) Following are my answers to your questions.

      a) There is a lot of variations of MVC implementation and most of the well-known implementations are coming from the web frameworks for which MVC is best suited. IMHO the most important thing is to keep your UI logic separated from your domain (model) and presentation logic, the rest and how would you call it is not as much important ;) Actually when I am thinking more about my current implementation it much more resembles MVP (model, view, presenter) which is also one of variation of the traditional MVC pattern.

      b) For UML I am using both Visio and sometimes VS.NET 2010 class diagrams (on my Win machine)

      c) I am thinking about open sourcing some of my source code and push it to github but it will take me some time. What problems are you exactly facing with extending CCScene?

  8. Chris
    Posted January 17, 2011 at 11:55 pm | Permalink

    Excellent post.

    If you don’t mind, I have a couple questions:

    1) In GameModel, I was wondering what viewPort is an instance of?

    2) With regards to your simple physics engine, I was also wondering what the updateModel method does?

    3) If you were to include multiple game modes, e.g., a fighting game with a Story and Survival mode, would it be correct that each mode has its own separate gameplayController implementation, e.g., storyGameplayController and survivalGameplayController?

    • Posted January 19, 2011 at 8:53 pm | Permalink

      Thanks! I am glad you like it.

      1) viewPort is an instance of ViewPort class which is not shown on my diagram. I use it to control the size and position of a currently visible part of a game world (rectangle),
      2) updateModel in my game mostly implements gravity & player movement (detecting collision with ground, changing player’s x/y velocity etc.),
      3) I believe most of the logic for both story & survival modes (like handling user interaction) will be the same so I wouldn’t define different controllers for different modes. I would rather think about seperating Story / Survival logic (not sure how those modes will affect gameplay in your game) to different classes (implementing the same protocol) and polymorphically invoke different implementations depending on a mode.

      I hope this helps.

      • Chris
        Posted January 21, 2011 at 12:33 am | Permalink

        Thanks for the reply.

        Concerning 3), I went with that approach as well, since I came to the same conclusion. :)

        After starting to re-write my game using the MVC architecture, I came upon an unforeseen issue:

        How should CCSprite animations get rendered in the View considering they are CCActions which only need to be called once per update?

        My current implementation is that I have a flag in the model, _shouldAnimate_, which I set to TRUE when the model enters a state which should show an animation. Then, when the CCSprite is updated based on the model it checks to see if _shouldAnimate_ is set. If so it checks to see which state the model is in and shows the appropriate animation (by starting the CCAction) then immediately sets _shouldAnimate_ in the model to FALSE so that it is not called again on the next update.

        I know this probably isn’t the best way to do it since it has the View modifying the Model (albeit in a small way) and I’d be very appreciative of any comments you have on this implementation.

        • Posted January 22, 2011 at 1:12 pm | Permalink

          That’s a really good question. In my game (and I believe it should be similiar in your) all my needs to execute CCAction come from the changes in model (player jumping, items falling down etc.) and I handle it the same way as I do play sounds (see “Handling model events”)

  9. ayah salman
    Posted January 19, 2011 at 8:19 pm | Permalink

    Thanks for the good explanation.

    If you don’t mind, I have one question that in the GameplayView initWithDelegate
    you call

    [self.delegate addChild: _backgroundLayer];

    isn’t the addChild a method of GameplayView??

    I think the code line must be:
    [self addChild: _backgroundLayer];

    • Posted January 19, 2011 at 8:56 pm | Permalink

      In my initial implementation my View class was not a subclass of CCNode so I had to pass a delegate (which was a CCNode) to my view in order to get access to addChild method. Much simpler would be probably to make a view subclass CCNode then your code would work as you described.

  10. Festival
    Posted January 25, 2011 at 1:18 pm | Permalink

    I don’t think this NSNotifications is good for MVC on iPhone

    Communications should be done with delegates only!! Then you have a relationship which
    GCC can verify and as delegates are callbacks you can port this easily to other platforms

    @protocol ModelDelegate;

    @interface Model : NSObject {

    //the delegate for communiction with the GameViewController
    id delegate;

    //Game ivar
    }

    //ViewController implements ModelDelgate
    @interface GameViewController : UIViewController {

    Model *gameModel;

    }
    @end

    @implementation GameViewController

    -(void) init{

    [gameModel new]
    gameModel.delegate=self;
    }
    -(void) Jump{

    gameModel.jump;
    }

    ///

    No need to use NSNotifications?!!!!!!
    }

    • Posted January 25, 2011 at 8:32 pm | Permalink

      I agree that it is one of alternatives to my approach but I don’t fully buy your arguments. Have you heard about Event Broker / Event Aggregator design pattern? If NSNotification is not available on a different platform one of my option would be to implement Event Broker pattern but I would probably pick completely different approach if I would need to implement a game using Silverlight on Win7 Phone.

      • Festival
        Posted January 26, 2011 at 8:07 pm | Permalink

        Event Broker is a good idea.

  11. Logan
    Posted January 26, 2011 at 4:54 pm | Permalink

    Great Article!

    I have one question. In your GameplayPlayerLayer class you are calling the playerBeginJump method on a delegate. Are you passing the delegate from GameplayView into all of its child layers?

    • Logan
      Posted January 26, 2011 at 5:42 pm | Permalink

      Nevermind, after reviewing your code i realize that when initializing the layers you are passing the delegate. How are you defining that delegate in the Layer’s header file? Do you just define it with “id delegate”

      • Posted January 26, 2011 at 9:23 pm | Permalink


        @property (nonatomic, assign) id < GameplayViewDelegate > delegate;

        And a protocol is defined as follows:

        @protocol GameplayViewDelegate

        - (void)playerBeginJump;
        - (void)playerEndJump;
        ...

        @end

  12. paull stanley
    Posted March 25, 2011 at 8:05 pm | Permalink

    First let me say great tutorial, it cleared up a lot of confusion for me. Naturally shortly after the confusion clear more questions budded upon attempting to implement this.

    I cannot figure out is the “Updatable protocol”, What does the method look like to get NSObject(my model) to update?

  13. Chris
    Posted April 17, 2011 at 9:49 am | Permalink

    paull, try this

    #import “ccTypes.h”

    @protocol Updateable

    - (void)update:(ccTime)dt;

    @end

  14. Ricardo
    Posted June 2, 2011 at 5:52 pm | Permalink

    Hi. Great explanation! i was wondering how to arrange all my game classes and luckly this website showed on the Google search. Haha. I have one question:

    1. Let’s say i’m creating a Super Mario Bros like game. What i can’t figure out is: should i have multiple GameModels and/or multiple GameViews (as well all the layers that it has) for each stage? If not, how should i do this implementation?

    2. On ‘update()’ method of the layers you get the GameModel singleton. But what if i’m not using a singleton?

    Looking forward to the answers. Thanks!

    • Posted June 7, 2011 at 11:17 pm | Permalink

      Hi, I am happy that you like it! :)

      1. I believe your model (in terms of a data structure) will not be different on different stages as you will always have the same type of objects like player, platforms etc. What you will probably need to do at the beginning of each stage is to initialize a model with a data that represents your stage.

      2. If you don’t use singletons that you will somehow need to pass your model to your controller and access it using property.

      I hope this helps.

  15. Posted July 21, 2011 at 7:46 pm | Permalink

    Hi, nice post!. I was just wondering, what diagramming tool are you using to make those class diagrams?
    i like the one Microsoft has in Visual Studio 2010 but haven’t find any good for mac.

    • Posted July 21, 2011 at 9:43 pm | Permalink

      I did it on my Win 7 machine in Visio :) I don’t know any Mac alternatives for VS 2010 diagrams which I also like it a lot.

  16. ashika umanga
    Posted September 4, 2011 at 5:35 am | Permalink

    thanks alot for the great tutorial,now I am carefully following and trying to adopt my game using this .
    Ive got a question.Instead of using delegates to handle touch events in Controllers , cant we use CCTouchDispatcher ?

    for eg , the Controller init method ,

    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:-1 swallowsTouches:YES ];

    • Posted September 4, 2011 at 9:01 am | Permalink

      Yes, as Steffen Itterheim commented on my previous post regarding MVC, handling touch events directly in controller using CCTouchDispatcher seems like a viable solution for this problem (but I haven’t tried it yet).

  17. Posted September 6, 2011 at 9:36 pm | Permalink

    Nice post!

    Question for you:
    1) I don’t get how the Controller gets instantiated. From this line:
    [[CCDirector sharedDirector] replaceScene:[GameOverController node]];

    I guess that your controller extends CCScene but I am not completely sure. Can you clarify?

    2) Have you checked this:
    https://github.com/jeremyflores/cocosMNC

    Thanks!

    • Posted September 18, 2011 at 8:56 pm | Permalink

      1. You’re right. Controller extends CCScene.
      2. Nope, I haven’t checked this implementation.

  18. Posted September 13, 2011 at 10:48 am | Permalink

    Great post man!!! I am always trying to find a way to organize my project in a better way and your post helped me a lot, thanks a million :)

  19. Posted November 28, 2011 at 2:43 pm | Permalink

    Bartek, Thank you very much for this tutorial.
    I have a question about an implementation of this pattern.
    How to correct restart a scene (Controller)?
    Have I to release model instance in controller’s dealloc method or it will be better to clean level manually?

    • Posted December 2, 2011 at 8:12 pm | Permalink

      I think the Controller should control the lifetime of a model. I would create it in init and dispose it in dealloc. If you want to reload the model in the same scene, than you might need to do it manually. BTW. I would recommend to look at my latest posts regarding MVC implementation. Instead of singleton for model I would stick to transient model that is allocated and deallocated within the Controller.

  20. Kirill
    Posted December 27, 2011 at 12:18 pm | Permalink

    Good post. But I have one question. What’s about syncing between animation in view and model logic. For example, there is a character which can attack enemies – it’s model logic. There is attack animation(i.e. sword attack) of the character as well – it’s view. Let’s take that “real attack”(set damage to the enemy) should be on the seventh frame.

    How it can be resolved?

    • Posted January 13, 2012 at 8:13 pm | Permalink

      The easiest way – the view notifies the controller that the real attack has just happened. Is it what you meant?

3 Trackbacks

  1. By Persisting model state in Obj-C | XPerienced Blog on January 3, 2011 at 6:14 pm

    [...] of the benefits of having the model separated from your view concerns is that you can easily persist your model state to a permanent storage – for example a file [...]

  2. [...] Click here for the full article part 2 [...]

  3. [...] How to implement MVC in cocos2d game – part 2 [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">