Tag Archives: cocos2d

Cocos2D, Box2D and MVC

As I indicated in my last post, I am going to write my kids’ game in Cocos2D. After implementing the simple bear animation tutorial from Ray Wenderlich, I had a few questions:

  1. How do you use automatic reference counting (ARC) with Cocos2D? The approach I’ve taken is to follow this blog by Steffen Itterheim.
  2. How do you write code with Cocos2D (and maybe with Box2D) in an MVC (model-view-controller)-compliant way?  The approach I’ve taken is to follow this blog and its sequel by Bartek Wilczyński.
  3. How do you add Box2D to the project once you’ve already started it (and continue to use ARC)?  The approach I’ve taken is to make it a static library by following this blog by Red Glasses. This is a pretty involved procedure but does the job. I imagine you can do point (1) above using this approach too – it would be nice to be consistent – but I have not tried this.

I’ve done all this and got it all running, and I thought others may find it helpful, so I have put the result on github at https://github.com/RacingTadpole/Cocos2D-Box2D-MVC-example. You are welcome to download it as a starting point for your own projects, or just to poke holes in it (but please tell me what they are!). The frame rate seems to be only 20-30 frames per second on the simulator, but on a real device it is close to 60, and I have read elsewhere that this stat should be ignored on the simulator anyway. Edit – the project on GitHub was compiled using a slightly older version of XCode, and the latest XCode complains when I try to run it on a device (ld: file is universal (2 slices) but does not contain a(n) armv7s slice: …./libbox2d-lib.a for architecture armv7s ). For now I am solving this by setting “Build Active Architecture Only” to “Yes” in the target’s build settings (see this stackoverflow question), but in the long run it looks like I’ll need to redo step 3 above using the latest XCode.

The game as it stands (called Zambazi) simply involves a host of monkeys and bears falling from the sky onto a grassy foreground, and bouncing like rubber balls. When you touch anywhere, all the animals are hit with random forces.  It’s not much, but my kids find it surprisingly engrossing! They decided you win if you can make all the bears run off the screen before the monkeys… Maybe I’m not so far from the App Store after all? :-)

All images are from Ray & Vicki Wenderlich’s sites – thank you both for making these freely available!

Here’s the basic structure/flow:

GameController

When PLAY is pressed, a GameController is initialized.  The gameController has a GameView and a GameModel, each of which is initialized. The gameController also schedules the updates.

GameView

The gameView has a delegate (actually the gameController) which currently does nothing, because it doesn’t need to know which sprite you’ve touched. This delegate may be useful if you do need to know – see Bartok’s blog for his vision here. In fact I’m planning instead to remove this delegate and simply register the controller with Cocos2D as a touch delegate, as described here.

The view creates the necessary layers:

GameLayer

The gameLayer is in charge of all the sprites. It knows nothing about the view or the controller, but does have a reference to the model. It also registers itself as an observer of notifications from the model. The notifications are:

  • Model initialization – this is so that the gameLayer can get a reference to the model in the first place.
  • Revise game elements – this is so that it can set up the sprites that correspond to the model.

The gameLayer starts by loading in all the sprites for the game, and setting up their actions (CCAction).  I am sure there is a much better way to do this – but this does the job for now.

It also keeps track of which actions are running. This seems an unfortunate complication, but as far as I know, you need to do this so that you can stop the action later. If you can get away with stopping all actions on a sprite – and maybe you can – then you could remove this stuff and use stopAllActions instead.

The gameLayer does not know about Box2D – I see that as a model-level thing.  The gameElements provide their own velocity, where, rotation etc methods.  I have defined a Point3D structure to pass around points – this was when I was thinking the model may have a 3D world even if the view is only 2D.  However, with Box2D, the third dimension is irrelevant – so it would be simpler to just use CGPoint for example.  I am leaving Point3D nonetheless so that if you want to use this code with a 3D model (without Box2D), it shouldn’t be too hard to adapt it.

The other trick is that gameLayer has an NSDictionary (called sprites), with the gameElements as keys and the sprites as the objects. The complication is that NSDictionary copies its keys before it uses them, so that the key winds up being a different object to what you requested.  The solution (implemented in my code) is to override copyWithZone: to return self, without copying, as described in this stack overflow post.  I am assured this is good practice if the object is immutable. All this may be too tricky by half, but it seemed sensible at the time, and works fine.

GameModel

The game model is the Box2D world, and an array of the game elements. When createGameObjects is called (by the Controller – this could equally well be part of the initialization), it sets up some default game elements. It has an update: method which uses Box2D to update the physics; optionally each element may have its own additional update behaviour (I have adopted Bartok’s “Updatable” protocol).

GameElement

The gameElements are the models of the platforms, the enemies, etc.  They basically have a Box2D body and a name.  The name is used by the gameLayer to work out what sprite to show. The gameElement uses Box2D to provide where, velocity and rotation methods, so the body variable itself is kept private (i.e. in a class extension).

I am subclassing GameElement (e.g. Animal) to provide different behaviour for different models.

Technical note – so that subclasses can still access the body variable, I have declared body in a class extension header file called GameElements_Private.h.  Then GameElements.m and Animal.m both import GameElements_Private.h instead of GameElements.h, so that they can refer to body.

Further ideas

As I start to turn this into a functioning game, I have found two further issues, one conceptual, one practical:

  • It’s nice to cleanly separate the model from the view – but the image you are using is a particular size, and I’m finding the model sometimes needs to know this size (so you don’t have to scale the image). I’m solving this with another delegate pattern.  I’ve introduced a NaturalSizeProtocol, which the GameLayer and the GameView follow.  The GameModel then has a naturalSizeDelegate.  When a gameElement needs to know its natural size (i.e. the size the view wants to make it), it asks its naturalSizeDelegate.  This returns the size in model co-ordinates (as a Point3D).  This feels like a contortion of MVC, so I’d love to hear if anyone has a better solution to this.  It has left me wondering if MVC is more trouble than it’s worth after all for image-intensive games.
  • Getting a background image to repeat in Cocos2D is hard.  I have only managed it so far by loading the background image multiple times, which doesn’t seem right.

That’s it for now.  Please let me know if you find this useful, or have any suggestions.

Edit – I have just come across Steffen Itterheim’s excellent post on exactly this subject, which inspired him to write KoboldTouch. Together with problems I am having getting Lua to compile in my Cocos2D/Box2D project, I am starting to wish I had used Kobold2D…

  

A kids’ game

I have an idea for a kids’ game (though there’s quite a bit of competition out there on the App Store!).  The question I’m debating is whether I should implement it as a 2D game or a 3D game. It would only have a fixed camera position, but I’d like some depth to the world, so that characters going up the screen go into the distance, and can then go behind other characters or objects. From Wikipedia’s 2.5D entry, this could be considered “scaling along the z-axis”. I actually haven’t found any games with that sort of view, perhaps because a 2D model looks dodgy (see below), and by the time you have a 3D model, there are so many cooler things you can do with one. Here are the options I’m considering:

2-dimensional graphics

This basically comes down to Cocos2D. I put some code together using Cocos2D for iOS, based on Ray Wenderlich’s tutorial for an animated bear, and made the bear smaller if it goes up the screen and bigger if it comes to the front.  This looks pretty good and is quite simple to do, as long as the bear is not going mostly up or down the screen.  In that case you’d need more animation sequences so the bear faces towards or away from you.  But what if you go on a diagonal away from you or towards you?  I think you’d need those sequences too.  That’s quite a few sequences, and of course whereas any walking angle would be allowed, graphically it would have to snap to one of the 8 available animations. So the problems with this approach are:

  1. I couldn’t use freely available art (like Vicki Wenderlich has available)
  2. It won’t look awesome – and I’m not sure it will even look good enough.

Also, no 2D physics engines (like those that come with Cocos2D) would work, since the gameplay is not actually 2D. In my case I don’t plan to have any complex physics, so I can make my own.  Potentially though I could use a 3D physics library like Bullet.

3-dimensional graphics

I think this basically comes down to Unity3D (and perhaps Unreal, but I can’t use this on a Mac so it is less appealing), although there are a few other related options out there too. Unity3D is amazing, there are lots of 3D graphical assets available on their asset store, and compiles cross-platform to boot. I have succeeded in building my own terrain in its editor, putting in an eerie sky and swaying grass, and can compile a game to my iPad which lets me look around it (in a first person view).  I followed a youTube demo for this from TechZone. I have also read about ways to layer native iOS elements on top of this – Millipede gives a good explanation of this here, and their Navy Sink’Em game is the best example I’ve found of the camera angle I want, though I didn’t intend that level of realism. Adding a iOS front-end to a Unity project is also covered by this Blurst post. The problems with a Unity3D approach are:

  1. Troubleshooting how to do things in Unity is probably harder than I’m used to with Cocoa.
  2. Will take some learning how to communicate between Unity and iOS.
  3. I can imagine the project flow getting quite complex as I want the player to be able to add assets to the scene, and associate scripts with them. I probably want an iOS interface to do this, which would need to display Unity assets.
  4. Costs a bit.
  5. I don’t like being forced to use a new development environment, and being locked into Unity’s world.

The other 3D options include:

Cocos3D. There is very little online about this – no tutorials. It also comes with the caveat that it “is not yet compatible with cocos2d 2.x. Please use cocos2d 1.x.”

SIO2. I have just come across this here. It looks promising, as it does not force you into a particular SDK.  I have not investigated this in detail.

Conclusion

I think I’m biting off more than I can chew right now if I try to make a grand 3D game. So I will adopt the 2D framework for now and try to get a good game logic happening.  Perhaps even give up and modify the game flow so that it is a true 2D game (with parallax of course… I always loved Moon Patrol).  Then, if that doesn’t look good enough to release, come back to Unity.

Any advice?