The Ultimate Cocos2D Project: Kobold2D

On March 19, 2011, in Kobold2D, by Steffen Itterheim

What is Kobold2D?

It’s the Ultimate Cocos2D Project, of course. Or more precisely, the official name for it. Right now, the website www.kobold2.com is only a “coming soon” page while development is under way.

What’s in a name?

Calling it “The Ultimate Cocos2D Project” all the time would have become tedious rather quickly. I wanted a name that is reminiscent of Cocos2D yet completely different. As luck would have it, I’ve recently watched a lot of Battlestar Galactica episodes. You might remember that in this show humanity’s home planet is called Kobol. I couldn’t help but think of COBOL all the time. 😉

From there it was a small step to Kobold, which in germany is widely associated with a famous cartoon Kobold called Pumuckl. As a kid, I was a big fan of Pumuckl, so picking Kobold2D as the name was a no brainer. Even more so since it has the same ring to it than Cocos2D.

Why create a new brand name?

For one, giving the project a name of its own clearly makes it more attractive. It expresses a certain dedication to the project. It should also signal that it’s no longer just about Cocos2D. With all those extra libraries and additional glue code, plus an experimental project I’m working on, I’m tempted to call it a Game Development Kit (GDK). That’s the long term vision for Kobold2D: more power, easier – for everyone!

Speaking of long term, that’s another reason to give it its own brand name. The visionary thought being that ultimately, something like Kobold2D could be implemented for other game engines as well, with the same core values: give the developers more power, greater flexibility but at the same time make it easier for them to get started.

The Kobold Team

I’m not the only developer who is aching for a more professional work environment. Kobold2D is a joint-venture with another senior software developer and a couple helping hands who help out wherever and whenever they can. We agreed to share the development burden on a voluntary basis. We all have different stakes and interests in the development of Kobold2D.

For me personally the most important aspect is my ambition to develop a project for its users, both professional and casual. I know I can build professional systems that are easy to use, well documented and thus get the job done painlessly. This basically sums up what I’ve been doing for the past 10 years.

What we’re not doing …

There’s one issue I think i going to come up, which might confuse some people, so I want to be clear about this: we are not creating a branch of Cocos2D. We have no intention to do so. We use the library as is, and we stick to the stable builds. The same goes for all other libraries of course.

At the same time, we don’t push each and every line of our additional code back or even contribute to the development of the libraries in Kobold2D. That’s not what we set out to do, and we simply don’t want to spend too much time consulting with and compromising on changes with others when our code is already there and working for us. Our code uses the MIT License, so it’s there for the taking.

In very few cases we can’t get around to modify library code. We only do this where necessary, for example if it breaks our build and the fix is rather simple. Other than that, if a library doesn’t work to our satisfaction, we try to add our fixes and improvements on top, either by subclassing or by making use of Objective-C categories. So far this has been working very well and allows us to keep updating the underlying libraries with far fewer hassles.

Next steps

One big task that I set myself out to complete before continuing with Kobold2D is figuring out the Xcode 4 template format for File Templates and Project Templates. I almost have everything together after spending practically the whole week on it. I’m also documenting all my findings and I’m going to publish the Xcode 4 Template Tutorial / Reference / Documentation / Manual (not sure about the name yet) by the end of the month.

The goal for Kobold2D is to have various project templates, which is why I’m doing extensive research on the new Xcode 4 template format. Unfortunately at the moment it seems that it will not work satisfactory with cross-referenced Xcode projects, but I remain positive that I can find a solution.

Kobold2D private beta!

There will also be a private beta test for Kobold2D starting in a couple weeks (couple == definitely more than 2 weeks). Reply to the private beta sign-up thread if you want a chance to be picked for the private beta test.

Tagged with:  

Another Great Cocos2D Tool: PhysicsEditor

On March 15, 2011, in cocos2d, tools, by Steffen Itterheim

In my book I explained how to create collision shapes for physic engines using the freely available version of VertexHelper Pro. Granted, it works, but as soon as you need to update your shapes frequently or you have many different shapes to edit it’s going to be a lot of manual work and error-prone copy & paste between VertexHelper’s code generator and your source code.

VertexHelper, meet your replacement: PhysicsEditor

PhysicsEditor was written by Andreas Löw, the author of the very popular TexturePacker tool. He has proved again that he can create powerful yet easy to use tools for game developers.

The greatest part about PhysicsEditor: it can automatically trace your shapes to generate collision shapes and it works flawlessly! You can even tweak the amount of vertices (and a lot of other things) as needed, for example if your physics engine has a limitation on how many vertices can be used for a collision shape (Box2D default: 8 vertices).

But it doesn’t just create the collision shapes, it also allows you to edit physics properties of a shape that often go along with it. Density, friction, “bouncyness”, and other parameters can be tweaked in the GUI.

As they say, an image speaks louder than words, so I suppose a video speaks in a thousand images:

Not just Cocos2D

PhysicsEditor currently exports to Cocos2D + Box2D (Chipmunk/SpaceManager support is forthcoming and should be available soon) and also to Sparrow Framework + Chipmunk and of course Corona SDK.

And it works on Windows, too! Which makes sense given that Corona supports Android development under Windows.

I also found this post about PhysicsEditor with a working Flash example (at the bottom). It seems that even exporting respectively using PhysicsEditor with Flash + Box2D seems to work well. Wow!

Brace for impact!

Check out the PhysicsEditor Features page to learn more about what this great tool can do for you! You can get PhysicsEditor alone for $17.94 but you can also grab a bundle deal which includes TexturePacker for $29.99, or almost 20% off.

Tagged with:  

The Ultimate Cocos2D Project: Startup

On March 12, 2011, in Kobold2D, by Steffen Itterheim

The Ultimate Cocos2D Project is: Kobold2D!

Put simply: Kobold2D is designed to make Cocos2D developers more productive.

Original Post

Time for a weekly update. This time about startup code and configuration. One of the things that I frequently encountered following the development of Cocos2D and working with it, is how any change to the startup code – the main function, the App delegate and the root ViewController – caused issues and headscratching among developers.

I decided it doesn’t need to be this way.

The main() function

A code snippets speaks more than words:

[cc lang=”ObjC”]
int main(int argc, char *argv[])
{
return KKMain(argc, argv, NULL);
}
[/cc]

That’s right, all of the startup code is now part of the project’s source code. You can still do whatever you need to do before and after the call to KKMain (probably nothing, except maybe anti-piracy code). And the third parameter (NULL) to KKMain is reserved for future use, to pass in any configuration parameters if the need arises.

Let’s see what KKMain does:

[cc lang=”ObjC” height=”650″]
int KKMain(int argc, char* argv[], SMainParameters* userParameters)
{
SMainParameters parameters;
initMainParameters(&parameters, userParameters);

#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
#else
// Mac OS X specific startup code
[MacGLView load_];
#endif

// This makes the CCDirector class known to wax:
[CCDirector class];
// wax setup is sufficient for all intents and purposes
wax_setup();

[KKLua doString:kLuaInitScript];
[KKLua doString:kLuaInitScriptPlatformSpecific];
[KKLua doString:kLuaInitScriptForWax];

// This loads the config.lua file
[KKConfig loadConfigLua];

// run the app with the provided general-purpose AppDelegate which handles a lot of tedious stuff for you
#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
int retVal = UIApplicationMain(argc, argv, nil, parameters.appDelegateClassName);
[pool release];
#else
int retVal = NSApplicationMain(argc, (const char**)argv);
#endif

return retVal;
}
[/cc]

The usual, really, except that it also initializes Wax and thus Lua for your App as well as providing the necessary startup code for both supported platforms: iOS and Mac OS X. The KKLua class is an Objective-C wrapper around the most imortant Lua functions, most notably it has the doString and doFile methods which allow you to run any Lua code or file containing Lua code.

KKConfig is a class that loads a Lua table and stores it in a NSDictionary for fast access to Lua parameters at runtime. I’ll discuss it in detail another time. The main purpose of KKConfig is to loadConfigLua, which loads the config.lua script returning a table containing startup parameters and making those parameters available to Objective-C.

Config.lua in detail

Let’s have a quick look at an excerpt of the config.lua file. It contains all of the startup parameters a developer using Cocos2D would ever want to tweak in a conveniently editable Lua script:

[cc lang=”Lua” height=”400″]
local config =
{
KKStartupConfig =
{
— load first scene from a class with this name, or from a Lua script with this name with .lua appended
FirstSceneClassName = “GameScene”,

— set the director type, and the fallback in case the first isn’t available
DirectorType = DirectorType.DisplayLink,
DirectorTypeFallback = DirectorType.NSTimer,

MaxFrameRate = 60,
DisplayFPS = YES,
DisplayFPSInAdHocBuilds = NO,

— Render settings
DefaultTexturePixelFormat = TexturePixelFormat.RGB565,
GLViewColorFormat = GLViewColorFormat.RGB565,
GLViewDepthFormat = GLViewDepthFormat.DepthNone,
GLViewPreserveBackBuffer = NO,
GLViewMultiSampling = NO,
GLViewNumberOfSamples = 0,

Enable2DProjection = NO,
EnableRetinaDisplaySupport = YES,

— … and many more settings!
},
}

return config
[/cc]

Since you don’t want to guess what those settings mean, I’ve documented them for you:

Config.lua Parameter Documentation (PDF)

This should also illustrate the kind of documentation I’m striving for. Documentation will be available online. It’s created in a Confluence Wiki with the help of ScreenSteps for more visual, step-by-step documentation.

App Delegate & Root ViewController

You may be wondering how you can modify and tweak the App Delegate and Root ViewController if they’re both part of the distribution, rather than copied into each project? That’s actually very simple: both are regular Objective-C classes, so they can be subclassed and methods overridden as needed.

Both KKAppDelegate and KKRootViewController provide a default implementation which you can tweak with the config.lua parameters. If that shouldn’t be enough, for example if you have to plug in some 3rd party code into the App Delegate, each project will have a subclass of KKAppDelegate and KKRootViewController in which you can override any of the UIApplicationDelegate and UIViewController protocol methods. Usually you would first call the super implementation, unless you want to entirely replace the default behavior.

The KKAppDelegate method calls one specific method called initializationComplete at the end of the delegate method applicationDidFinishLaunching. This allows you to run any custom code right before the first scene is shown. You can use that to call the CCDirector runWithScene method manually, in case you have more than one scene which might be run as first scene depending on certain conditions.

If you set the FirstSceneClassName config.lua setting, the project will first check if there’s a classname.lua file. If so, it will run this Lua script, assuming it contains the implementation of the first scene (more on that some other time). Otherwise it checks if there’s an existing Objective-C class derived from CCScene with that name, and if so allocates and initializes this scene and calls runWithScene for you.

In essence

From your point of view, the execution of the App now starts with the first scene, before that there’s no code that you’ll have to concern yourself with. Any startup configuration tweaks that you need to do can be done comfortably via the config.lua file, and the only setting you’ll need to change is the name of the first scene’s class name or Lua script. In addition you’ll get access to some features out of the box, for example adding iAd banners is now a simple on/off switch.

Moreover, any time there’s a change in Cocos2D’s startup code, or the startup code in any other library (most notably Wax), I can just make those changes for you and release a new version. This isn’t something you need to concern yourself with anymore, and makes upgrading existing projects to new versions of Cocos2D and other libraries even easier.

Flash for iPad? It just makes no sense!

On March 9, 2011, in Technology, by Steffen Itterheim

With each new iOS device you’ll be sure to hear this argument:

“It doesn’t support Flash! Baaaaah, piece of crap!”

What bothers me most is that this mantra is repeated even by intelligent people, even developers fall into that behavior. But they don’t have an argument other than “I want it, I want it”. No really, it’s actually “I think I want it, I think I want it”. Why?

“Uh … well, Flash games!”

Here’s the problem …

If you like playing Flash games, either some in particular or generally consuming the daily new dose of throwaway games, you’ll be emotionally connected to these games. Of course you would want to play them on any device that seems perfectly capable of running Flash. So I understand the notion of wanting to have Flash on an iOS device. It’s entirely understandable.

What really bothers me, is how little even intelligent people put into what they’re actually demanding. Here’s a smack in the face – think about it!

Other examples include:

“Press any key to continue.”

“Use WASD to control your character, Space to jump, Ctrl to shoot.”

“Move the mouse cursor to the edge of the screen area to scroll in that direction.”

First of all …

All games that make use of the keyboard are out. Add to that the games which require a mousewheel or the distinction of left and right mouse clicks. I bet this will disqualify at least half of all Flash games. I expect that estimate is likely to be much higher if someone were to compile actual statistics of Keyboard and Mouse input use in Flash games.

Next, any game that relies on the concept of “mouse over” won’t work satisfactory, or not at all. There is no “mouse over” on a touchscreen device, there is only “drag & drop”. You have to touch the screen to move the cursor – it’s possible that games will interpret this as some kind of click and click, or drag and drop operation.

Finally, there’s the matter of precision. A mouse cursor has a hotspot that has an exact pixel position. A finger has a touch area, and although you can calculate the center point to be the touch location, it will be quite imprecise. Especially when you consider that users don’t see the exact point they’re touching – their finger is blocking the view. No Flash game has been designed to take into account that the clickable area will have a relatively large range of uncertainty. Many hidden objects games require you to touch locations to almost pixel-perfect accuracy – not to mention the unspeakable horrors of Flash UI Design with small fonts and even smaller buttons.

If you go into details, I’m sure there’ll be plenty more design issues. They may be subtle but overall important enough to make some games less enjoyable, unfair, unplayable or allow for exploits which could skew the highscores towards either mobile or web users. That’s bad.

Technical reasons

There are of course technical reasons why Flash, and specifically Flash games, won’t work well on an iPad or iPhone. The 1 GHz Dual-Core CPU of the iPad 2 is still an order of a magnitude slower than the slowest, Intel-based Mac Mini which clocks in at around 1.8 GHz (also Dual-Core). On older iDevices there’s only a single core ARM CPU with around 500 MHz. And surely you’ve experienced Flash games that didn’t run too well on a Mac mini, right? Imagine how they would perform on a mobile device.

Then we have the memory issue. The iOS devices have at most 512 MB of memory down to 128 MB. Not that bad, unless you consider how much is actually available for Apps. On a 128 MB device it’s just 30-35 MB. Not much you can do with that, and I don’t expect any Flash game to be optimized for this constrained amount of memory. Worse yet, a Flash game won’t receive memory warnings from the device and it’s developer certainly won’t respond to this warning. Plus, since running in the browser, the browser on the iDevice will consume some of the available memory itself. So what you get is some content-heavy Flash games and apps which will simply crash at a certain point, or not run at all because they’re out of memory. That’s not a good user experience.

We also have to consider the issue of screen resolution. Most Flash games run in a window with varying dimensions. On an iOS device, first of all you’d never get the fullscreen experience because the native resolution will almost always be different. Since Flash runs in the browser, the Flash games will have to be zoomed and scaled to fit the screen. In the worst case, the user has to do this manually because double-tapping inside the Flash window probably would be interpreted by Flash as a command, rather than by the browser as the command to zoom and fit the double-tapped content. In any case scaling the content will degrade visual quality while consuming more power because the content needs to be scaled (in most cases: up) by either the CPU or GPU.

What about Loading bars? Do you like loading bars? I’m sure you do. Because on an iDevice, the best you’ll get is a WiFi connection. I suppose that’ll be acceptable. But what if you’re on the road and only get 3G or even Edge? Do you like waiting several minutes for your Flash game to start up every time you run it? I don’t think so. Just try to remember how Flash websites felt back in the 90s when all we had were dial-up connections.

This could be better if …

Yes, if the iOS devices or even the iPads supported Flash, I’m sure Flash developers would take a little more care of the details that they actually can take care of. For example providing a real touch-aware user interface, or designing the whole game with touchscreen devices in mind.

However, only a minority of Flash developers would do so. The low costs of developing Flash apps and games doesn’t make cross-platform compatibility a real possibility for most. They make 90% or more of their revenue from hosting them on ad-supported gaming websites like Kongregate. Any other platform than the web has no relevance to Flash developers, and the iPad simply wouldn’t change that.

Once you do have a successful Flash game, it’s also much more lucrative to simply make an iOS version of it. Take for example Canabalt. It’s free on the web, but it sells for a relatively high price of $2,99 on iTunes. It’s also wildly successful. And it’s also a good example of why many Flash games simply won’t work on an iDevice – the screenshot further up is from the Flash version of Canabalt.

But Flash is good for other things!

Yes, if you like Ads, sure.

Oh, you mean those designer websites that you can’t even figure out how to use on your desktop? No?

What then … don’t tell me Youtube or those other movie sites. For one, there’s an App for that. And trust me, you’ll be too busy doing other stuff with your iPad than watching Youtube videos.

“There’s this site that won’t work …” – Really, you visit www.disney.com every day? You’re adorable! :)

So far I have not come across a website that’s entirely Flash-driven (eg won’t work without Flash) and that has you coming back. The one that gets closest is github.com – but no point in downloading source code to your iDevice, is there? Most Flash-only websites are once-in-a-lifetime show-off events. A comedy act, if you so will. The second time, it’s just not as much fun. And you can absolutely live without them.

I run a Flashblocker on my browsers, all I’m missing are Ads and rarely a few gizmos that I don’t even notice aren’t there. Almost all websites are intelligent enough to default back to a non-Flash version, which not only works better, it’s also easier to use, loads faster and consumes less memory and CPU time. There you go.

To put it bluntly

Flash has no place on the iPad, or any iDevice.

My real problem with that is the people who repeat the “no Flash support” mantra don’t stop to think about the actual problems in supporting Flash apps and games on a device like the iPad. It just won’t deliver the same experience as it does on the desktop. Those experiences can not be brought over to a mobile device by merely supporting a specific technology.

Moreover, I wish those in favor of Flash support for iPad would actually make an argument, rather than repeating “But that’s what I want.” – you’re like little kids who can literally only be dragged past a candy shop or toy store, crying all along. No toys for you, grow up!

Tagged with:  

iPhone Performance Killers

On March 8, 2011, in Programming, by Steffen Itterheim

Have a look at the following code, and then answer these questions before reading on:

  1. Which function will run faster?
  2. What will be the framerate for each function when run 100 times per frame on an iPhone 3G?
  3. Will wrapping the 100 calls to function1 in an NSAutoreleasePool show any difference?

[cc lang=”ObjC” height=”465″]
-(void) function1
{
CGPoint pos = [self position];
id x = [NSNumber numberWithFloat:pos.x];
id y = [NSNumber numberWithFloat:pos.y];
id objects = [NSArray arrayWithObjects:x, y, nil];
id keys = [NSArray arrayWithObjects:@”x”, @”y”, nil];
id dict = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
dict; // avoid compiler warning, is a noop
}

-(void) function2
{
CGPoint pos = [self position];
id x = [[NSNumber alloc] initWithFloat:pos.x];
id y = [[NSNumber alloc] initWithFloat:pos.y];
id objects = [[NSArray alloc] initWithObjects:x, y, nil];
id keys = [[NSArray alloc] initWithObjects:@”x”, @”y”, nil];
id dict = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
[x release];
[y release];
[objects release];
[keys release];
[dict release];
}
[/cc]

The Answers

  1. Which function will run faster? Answer: function1
  2. What will be the framerate for each function when run 100 times per frame on an iPhone 3G? Answer: 27 fps for function1 and 24 fps for function2.
  3. Will wrapping the 100 calls to function1 in an NSAutoreleasePool show any difference? Answer: no, but memory of temporary objects is released immediately.

Needless to say, on an iPod (4th Generation) and an iPad these tests all run at 60 fps and give no indication whatsoever that the performance on an iPhone 3G would suffer this much (and neither does the Simulator, of course). All the more reason to test early and often on older devices.

To autorelease or not?

Common wisdom may tell you that alloc/release is faster than autorelease. Even Apple recommends avoiding autorelease, right?

Not quite, because this is often misunderstood: Apple recommends to avoid autorelease but only for functions which create a lot of temporary objects and because of the constrained memory – not because it’s slow or even dangerous – autorelease is not dangerous.

Since memory is so constrained on 1st and 2nd generation iOS devices, it’s best to release that memory as soon as possible and don’t leave it allocated for longer than necessary. To achieve this, you can choose to do two things in this case: use alloc/release or enclose the loop in an NSAutoreleasePool. The latter option is preferred since it will release the memory right away, and not some time later. And autorelease is generally preferable because you will never, ever forget to send a release message to an object – which means it’ll be leaked and forever use up memory.

You can write well-performing, even better-performing code by using autorelease and using NSAutoreleasePool around tight loops creating many temporary autorelease objects.

Innocent looking code kills framerate

Did you expect that creating 100 rather simple NSDictionary instances each frame would drag the framerate down to around 24-27 fps? Me neither. I knew the code wasn’t going to be blazing fast, but I never expected it to have such an impact. However, it can be optimized somewhat since I’m unnecessarily creating two NSArray instances to hold the keys and values respectively before using them to create the NSDictionary. In fact we can get rid of them by using dictionaryWithObjectsAndKeys and doing this in a single step:

[cc lang=”ObjC”]
-(void) function1Optimized
{
CGPoint pos = [self position];
id x = [NSNumber numberWithFloat:pos.x];
id y = [NSNumber numberWithFloat:pos.y];
id dict = [NSDictionary dictionaryWithObjectsAndKeys:x, @”x”, y, @”y”, nil];
dict; // avoid compiler warning, is a noop
}
[/cc]

Sometimes it helps to look around what other ways there are to run the same code. In terms of performance this is an order of a magnitude faster and now clocks in at 42 fps. Still not good enough for realtime rendering obviously but an improvement of over 50% by cutting two NSArray allocations is a very simple and effective optimization.

Just as a general guideline, when I get rid of the two NSNumber instances and simply pass empty strings for x and y the framerate went back up to 60 fps. Of course that’s over-optimizing to the point where the code doesn’t work anymore. It just goes to show how expensive the creation of NSDictionary and NSArray are, as is wrapping simple types in NSNumber or NSValue objects.

If you can avoid allocation and temporary objects, avoid it. If you can’t, at least avoid creating temporary objects every frame. Re-use objects as much as possible. Unfortunately, that’s not an option for NSNumber objects since you can’t change the value of a NSNumber instance.

The Ultimate Cocos2D Project: Libraries

On March 4, 2011, in cocos2d, Kobold2D, by Steffen Itterheim

The Ultimate Cocos2D Project is: Kobold2D!

Put simply: Kobold2D is designed to make Cocos2D developers more productive.

Original Post

Last week I wrote that I’m Building The Ultimate Cocos2D Xcode Project. In today’s weekly update I wanted to give you some more details on the use of libraries in that project.

Cocos3D included

So there happens to be a Cocos3D now. Rather than being part of the Cocos2D distribution, it’s an extension project. Guess what that means? Right, installing Cocos3D means fumbling with the dreaded install-templates.sh script (see this Cocos3D tutorial). Of course the first user reactions were: how do I install it? Installation failed, what am I doing wrong? And so on …

The Ultimate Cocos2D Project wouldn’t be ultimate if it didn’t include Cocos3D out of the box. And unmodified of course, as with all included libraries I want to make it as simple as possible to replace one library version with another. Once you get to half a dozen of included libraries, maintaining them all can become a hassle, so the very least I can do is to make it easy for everyone to upgrade specific libraries.

Obviously: Cocos2D included

Of course Cocos2D is also included as a static library as opposed to cluttering your project with all of its source files. Xcode project references make it very convenient to add external code and keeping it seperate. I’ve described the process in detail in my Cocos2D Xcode Project tutorial but since then I’ve learned a couple more things about how to make this even better.

For example, I no longer include cocos2d-iphone directly, instead there’s a seperate Xcode project in between so that I have full control over build settings (using XCConfig files) and make it possible to build both iOS and Mac OS targets in the same Xcode project. I will also include the current version of Cocos2D in the download because my goal is to make everything work out of the box.

No fumbling with install scripts, no additional downloads necessary, no need to modify any Xcode build settings – including developer certificates and header search paths. Build configurations for Ad Hoc and App Store release builds are also included, which will create .IPA and .ZIP files for you ready for Ad Hoc distribution respectively upload on iTunes Connect.

Popular libraries included

Now let’s get to the juicy part. Early on I realized that Cocos2D users often needed (or wanted) to include other libraries. Some of them have become so popular among the Cocos2D crowd that they could as well be part of the official distribution. Alas, they’re not. That’s a service I want to provide.

Often those libraries require special and non-obvious steps to successfully add them to an existing project. All too often those steps are either undocumented, untested, hard to follow, refer to outdated versions of Xcode, iOS SDK, etc. and generally require technical expertise of project configuration and compiler settings.

This is all taken care of for you. Here’s the list of libraries that are already included in the Ultimate Cocos2D Xcode Project:

That is quite a list. All you need to do to use these libraries is to either enable them in code or merely include the header file and start using them. If you worry that all these libraries will bloat your App, rest assured that Xcode is very clever: if you don’t actually make use of a static library (eg don’t include any of its header files), it will not be linked with your App and not waste any space or performance. I verified that.

Update policy

These are a lot of libraries to keep up to date. I plan to make about 4-8 point releases each year, usually triggered by a major (speak: non-beta) release of Cocos2D. If updating other libraries justifies an update depends on the library’s importance and the significance of the update.

Your libraries

Adding your own libraries to the project will be easy and the process will be documented. This will encourage code-sharing because your library will just work with other user’s project, it only needs to follow a few simple guidelines to become plugin-capable. This opens the door for better and tighter integration of 3rd party code into your projects. Even if you don’t intend to share your code, you’ll still benefit because your code will be easier to re-use and maintain.

Also, if you like you can make a request for a specific library or additional source code that should be included in the project, please leave a comment. I’ll see what I can do. :)

Scheduling multiple update selectors

On March 2, 2011, in cocos2d, Programming, by Steffen Itterheim

I have a seemingly simple requirement for my project: each node should have preUpdate and postUpdate methods in addition to the regular update method. Preprocessing and postprocessing before and after all entities have run their “update” logic is a common requirement in game development. Sometimes called the setup stage before processing all entities in the world, and the finalize stage to complete the current game step and possibly resolve collisions or check any win, lose or achievements conditions.

Of course there are alternative and some may argue “better” implementations, after all an experienced game dev might argue that using pre and post update methods are merely signs of a badly designed game update loop (the jury is out on that one). However beginning game developers definitely understand this concept much better and every game-making tool I know implements pre and post updates, so it has its validity. Plus I find it more convenient than “outsourcing” some logic to a central game loop.

On the other hand it’s also bad practice to rely on one node’s update method to be called before or after all others. Especially once you get to prioritizing update method calls among various groups of nodes it’s just going to get you into trouble. If you set the priority wrong just once you can introduce very subtle issues that’ll be hard to track down. Think of some objects not colliding with the player, or some monsters crashing when you shoot at them with a specific weapon. Scheduled methods should never rely on the order they are called for various entities.

Not so easy …

It turns out the system in Cocos2D only allows one update method per node. That means for each node you can only have one update selector, and via the priority parameter you can only control when its update method is called relative to all other nodes’ update method. In that way you can at least ensure that the player’s update method is always called first, or last, depending on your requirements. But it’s bad programming practice to do so.

I thought, why not just schedule a “regular” selector with CCScheduler? Well, they don’t have a priority, and they are always called after any update method, so you could never schedule a “before update” method this way. And those scheduled selectors aren’t meant to be used for selectors that are called every frame due to the additional processing overhead (eg allocating, updating and releasing the CCTimer object, and comparing & updating time elapsed every frame).

So I had to write a class called ScheduleMultiUpdate which creates proxy instances, registers them with CCScheduler to receive an update message of their own, and then they forward that message to the actual node implementing the special update selector. By using the priority you can define if the selector is called before or after the regular update by using a negative (before) respectively a positive priority (after, must be 1 or greater).

Example Code

Here’s an example usage scheduling the beforeUpdate and afterUpdate selectors to be called before and after the regular update method.

[cc lang=”ObjC” height=”550″]
// in interface (.h)
KKScheduleMultiUpdate* multiUpdate;

// in implementation (.m)
-(void) scheduleUpdateMethods
{
multiUpdate = [[KKScheduleMultiUpdate alloc] initWithNode:self];
[multiUpdate scheduleUpdateSelector:@selector(beforeUpdate:) priority:-1];
[self scheduleUpdateWithPriority:priority];
[multiUpdate scheduleUpdateSelector:@selector(afterUpdate:) priority:1];
}

// this has to be cleanup because CCScheduler retains scheduled targets
// we have to give KKScheduleMultiUpdate a chance to unschedule its selectors or it won’t be deallocated
-(void) cleanup
{
[multiUpdate release];
multiUpdate = nil;
[super cleanup];
}

-(void) beforeUpdate:(ccTime)delta
{
}
-(void) update:(ccTime)delta
{
}
-(void) afterUpdate:(ccTime)delta
{
}
[/cc]

Here’s the actual implementation of KKScheduleMultiUpdate and its proxy class. Notice how the KKScheduleMultiUpdate simply retains a list of proxies and creates new ones, while the proxy class registers itself with CCScheduler to schedule its own update method based on the given priority, and then forwards the message to the baseNode. There’s currently no way to unschedule an update selector, but it should be fairly easy to add if you ever need to unschedule an update method while the game is running (I’d rather just use a bool and skip update).

@interface

[cc lang=”ObjC” height=”500″]
#import “cocos2d.h”

/** Allows you to schedule multiple update methods per node. */
@interface KKScheduleMultiUpdate : NSObject
{
CCNode* baseNode;
CCArray* updateProxies;
}

-(id) initWithNode:(CCNode*)node;
-(void) scheduleUpdateSelector:(SEL)selector priority:(int)priority;

@end

/** Since there can be only one update selector scheduled per instance, this proxy will implement
that update method and forward the message to the desired selector. */
@interface KKScheduleMultiUpdateProxy : NSObject
{
id target;
SEL selector;
TICK_IMP impMethod;
}

-(id) initWithTarget:(id)target selector:(SEL)selector priority:(int)priority;

@end
[/cc]

@implementation

[cc lang=”ObjC” height=”500″]
#import “KKScheduleMultiUpdate.h”

@implementation KKScheduleMultiUpdate

-(id) initWithNode:(CCNode*)node
{
if ((self = [super init]))
{
NSAssert(node != nil, @”%@ %@ – node is nil!”, NSStringFromClass([self class]), NSStringFromSelector(_cmd));
baseNode = [node retain];

updateProxies = [[CCArray alloc] initWithCapacity:1];
}
return self;
}

-(void) dealloc
{
CCLOG(@”%@ %@”, NSStringFromSelector(_cmd), self);

[baseNode release];
baseNode = nil;

// must do a cleanup to unschedule CCSelector, this is because CCScheduler retains scheduled targets
[updateProxies makeObjectsPerformSelector:@selector(cleanup)];
[updateProxies release];
updateProxies = nil;

NSAssert([self retainCount] == 1, @”%@ %@ – retainCount on cleanup should be 1 but is %i”, NSStringFromClass([self class]), NSStringFromSelector(_cmd), [self retainCount]);

[super dealloc];
}

-(void) scheduleUpdateSelector:(SEL)selector priority:(int)priority
{
NSAssert([baseNode respondsToSelector:selector], @”%@ %@ – node %@ does not respond to selector”, NSStringFromClass([self class]), NSStringFromSelector(_cmd), baseNode);
// TODO: might want to check here if the selector happens to be already scheduled

KKScheduleMultiUpdateProxy* proxy = [[KKScheduleMultiUpdateProxy alloc] initWithTarget:baseNode selector:selector priority:priority];
[updateProxies addObject:proxy];
[proxy release];
}

@end

@implementation KKScheduleMultiUpdateProxy

-(id) initWithTarget:(id)target_ selector:(SEL)selector_ priority:(int)priority
{
if ((self = [super init]))
{
NSAssert(target_ != nil, @”target is nil”);
NSAssert(selector_ != nil, @”selector is nil”);

target = target_; // weak ref
selector = selector_; // weak ref

impMethod = (TICK_IMP)[target methodForSelector:selector];
NSAssert(impMethod != nil, @”selector is not an instance method of target %@”, target);

[[CCScheduler sharedScheduler] scheduleUpdateForTarget:self priority:priority paused:NO];
}
return self;
}

-(void) cleanup
{
CCLOG(@”%@ %@”, NSStringFromSelector(_cmd), self);

[[CCScheduler sharedScheduler] unscheduleUpdateForTarget:self];
impMethod = nil;

NSAssert([self retainCount] == 1, @”%@ %@ – retainCount after cleanup should be 1 but is %i”, NSStringFromClass([self class]), NSStringFromSelector(_cmd), [self retainCount]);
}

-(void) dealloc
{
CCLOG(@”%@ %@”, NSStringFromSelector(_cmd), self);

[super dealloc];
}

-(void) update:(ccTime)delta
{
impMethod(target, selector, delta);
}

@end
[/cc]

As always, you’re free to use this code. I release it under the MIT License. You do not need to include a copyright notice, but I’d appreciate any mention or backlink to this website.

Building The Ultimate Cocos2D Project

On February 25, 2011, in Kobold2D, by Steffen Itterheim

The Ultimate Cocos2D Project is: Kobold2D!

Put simply: Kobold2D is designed to make Cocos2D developers more productive.

Original Post

First Friday update after the teaser post. I’m working on a new project. I’m still fleshing out the details of the “killer-feature” and making tests, so I can’t really talk about that. But I can tell you what I have already up and running.

The Ancestor: cocos2d-project

You may remember the Xcode Cocos2D project tutorial I wrote almost a year ago. The goal of that was to use Cocos2D as an external library in order to be able to update Cocos2D simply by pulling a new version from git, or just by replacing the Cocos2D folder. I gave the resulting project a boring, uninteresting, generic name (so typical for a programmer): cocos2d-project.

The new and improved cocos2d-project not only has a spiffy name (to be announced) but also raises the bar not one but two or maybe even three levels, depending on perceived value. It’s definitely leaps and bounds ahead of the Cocos2D distribution project, especially if you care for how source code projects should be composed.

One Xcode project for both iOS & Mac OS X Targets

One thing that really bothered me when Cocos2D became capable to build Mac OS X applications was that it required a separate Xcode project for each platform. If you’ve ever done cross-platform development you know this isn’t going to make you happy. Every action needs to be done twice, add a resource in one project, then you must also add it in the other. Change a build setting in one project, also change it in the other. Build and run in one project, then build and run the other project with a completely different window layout and probably duplicating all the floating windows aka “Is that the Mac OS debugger or is it the one for the iOS project?”. You name it.

I did some research, then a test, and It turns out: it’s entirely possible to target both the Mac OS X and iOS platform from within the same Xcode project. It works like a charm!

Really the only thing you need to keep in mind is that Xcode doesn’t give you the option to change the Active SDK by default. But if you click the Overview dropdown while holding down the Option key, you can select any SDK that’s installed on your system (see the image). The key here is to first change the Active Target to the Mac target, then Option-Click again and select Mac OS X 10.6 as the Active SDK. And the other way around to change back to iOS. So it’s a two step process but still way more comfortable than managing two seperate Xcode projects.

XCConfig Build Configuration

Behind the scenes there’s an additional step required to make this work, which I’ve been wanting to do for a long time: to use XCConfig files for build settings. Cocoaphony has a blog post Abandoning the Build Panel describing the technique. The good part is: there’s less confusion between project-wide and target-specific build settings. Even more importantly, if you build several different libraries you want to build them with the exact same settings – with XCConfig files this is easy to do, manually changing the build settings of several projects with multiple targets simply isn’t practical.

Plus you can document each setting and you can still use the Build Settings Panel for your own needs while allowing me to use system-critical changes to the Build Settings. For example, if a certain build setting causes issues (eg like the switch to LLVM GCC) then I can change the setting and release a new version of the project, or just the build config file separately. You can then replace that file and it should fix the build (assuming you haven’t change that exact setting in the Build Panel). All of your customized Build Settings will remain untouched of course.

Those are only two very fundamental improvements on a system engineering level which probably won’t excite you too much if you focus on making games with any means necessary. I’m keeping the good stuff for a future update, hopefully in 3 to 4 weeks I’ll be able to give you some first details about the “killer-feature”. :)

Page 24 of 37« First...10...2223242526...30...Last »