Dec 222010
 

I have been contacted by Packt Publishing to review a new book on game programming on the iPhone with Cocos2d titled Cocos2d for iPhone 0.99 Beginner’s Guide. I will be reviewing the book in a future post, but in the mean time, please check out the sample chapters. There are not too many books on the subject, and it looks to be a great addition to an aspiring game programmer’s library. Please subscribe to my RSS feed or check back later for a detailed review of the book. Here is the press release for the book.

Make captivating games for the iPhone using Packt’s new book on Cocos2d

Packt is pleased to announce Cocos2d for iPhone 0.99 Beginner’s Guide, a new book which helps in building fun and exciting iPhone games using the cocos2d for iPhone framework. Written by Pablo Ruiz, this book will help programmers make their first iPhone game in no time.

Cocos2d for iPhone is a robust but simple-to-use game framework for building 2D games, demos, and other graphical/interactive applications for the iPhone. Its API comes integrated with Box2D and Chipmunk physics engines. Being an open source platform, it is compatible both with closed and open source games. Over 1500 AppStore games have been built with cocos2d for iPhone.

Cocos2d for iPhone 0.99 Beginner’s Guide explains in detail, all the key concepts of the iPhone framework and game programming required for readers to build their very first iPhone game. Readers will learn to add animations, sounds, and particle effects to their games which will help enhance their games with a lot of cool features and eye candy while making the game behave realistically using a physics engine.

This book is filled with illustrations, diagrams, and tips for building iPhone games, with clear step-by-step instructions and practical examples. It covers basic features such as sprites, actions, menu design creation and also helps readers utilize Cocos2d for pasting labels, integrating it with Social Networks and surfing through scenes, layers and transitions.

Seasoned and beginner programmers with a desire to enter the iPhone industry, who possess some basic programming experience with Objective-C and a good understanding of OOP, will find this book to be an interesting and beneficial read. The book is out now and available from Packt. For more information please visit: –
www.packtpub.com/cocos2d-games-for-iphone-0-99-beginners-guide/book

 Posted by at 11:57 pm  Tagged with:
Dec 212010
 

Although it has gotten better with the new generation of the iPhone, programmers must continue to be vigilant when it comes to memory usage if they want to avoid their applications crashing mysteriously. The best way to avoid the didReceiveMemoryWarning is to minimize memory usage from the get-go. Safest sex being abstinence and all that… eh? :)

Tip 1: Do not use UIImage imageNamed: method

UIImage’s imageNamed method caches the image. This is a handy feature that can beneficial, but depending on your needs, it may be better for you to manage the cache yourself. For example, if you are loading huge images that do not get used often, then it would be better for you to release the image after each use. I would suggest extending UIImage with a new method that does not cache the image like this:

The header file:

#import 
@interface UIImage (DoNotCache)
+ (UIImage *)newImageNotCached:(NSString *)filename;
@end

The implementation file:

@implementation UIImage (DoNotCache)
+ (UIImage *)newImageNotCached:(NSString *)filename {
    NSString *imageFile = [[NSString alloc] initWithFormat:@"%@/%@", [[NSBundle mainBundle] resourcePath], filename];
    UIImage *image = [[UIImage alloc] initWithContentsOfFile:imageFile];
    [imageFile release];
    return image;
}
@end

This way, you have complete control over the memory used by your images. You can then cache these images into a NSMutableArray and then release them when you no longer need them.

Tip 2: Break out your views into separate XIB / NIB files

If your view can be separated into multiple views, then create a separate UIViewController for each of them. This way, you can unload the views when not needed, instead of it consuming valuable memory even when they’re not visible. So always think about how your view can be separated into multiple views that can be loaded lazily.

Tip 3: Manually trigger didReceiveMemoryWarning

You can manually trigger didReceiveMemoryWarning from the simulator so make sure to test it in the simulator! The option is under Hardware / Simulate Memory Warning.

Tip 4: Use a local NSAutoRelease Pool

If you are autoreleasing lot of objects, you may run into situations where your objects may not be released until your program terminates. If so, think about using a local autorelease pool. Autorelease pools are staked, so if you create a new autorelease pool, it gets inserted into the top of the stack.

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *string = [[[NSString alloc] init] autorelease];
[pool drain];

Tip 5: Be mindful of container classes retaining and releasing objects

Pay attention to whether the library class you are using is retaining or releasing your objects. For example, when you add an object into a NSMutableArray, it is automatically retained. So you want to send the object that you are adding a release message to avoid memory leaks.

NSMutableArray *array = [[NSMutableArray alloc] init];

// obj has retain count of +1
MyObject *obj = [[MyObject alloc] init];

// obj has retain count of +2, so make sure to release it
[array addObject:array];     

// obj has retain count of +1
[obj release];

This also means when you remove an object from the array, it will automatically be released. If you are not sure whether the method you are calling is retaining or releasing, then make sure to look up the documentation for that peace of mind.

Also check out my original entry titled Handling didReceiveMemoryWarning.

 Posted by at 9:50 am
Dec 172010
 

While playing around with various sample codes downloaded from the interwebs, I noticed that the addAnimation method of CCSprite has been deprecated. Though it continues to compile and run without a hitch, my OCD comes to the rescue. If you refer to the API reference for version 0.99.5 of Cocos2D (here if anyone is interested), you will notice that it says “Deprecated: Use CCAnimationCache instead. Will be removed in 1.0.1″.

So let’s use CCAnimationCache!

So let’s say that you have a class derived from CCSprite for each game object, and that you load the animations for the game object during initialization by calling CCSprite addAnimation. Now you’ll have to change it to use CCAnimationCache instead. It’s pretty simple. Note that I only load the animation into the cache once by checking a boolean variable to see if it has already been loaded. I do this because there can be many instances of the game object on the screen at once (imagine bullets), and the application would crash if you tried to load the same animation twice. You could initialize the animation outside of your game object, but if you wanted to initialize it when your game object is instantiated, just remember to load it once as it is done here.

@implementation SomeGameObject 
static BOOL animationLoaded = NO;

// Some other code...

- (void) initializeAnimations {
    if (NO == animationLoaded) {
        animationLoaded = YES;
        CCAnimation *anim1 = [CCAnimation animationWithFrames:some_array1];
        [[CCAnimationCache sharedAnimationCache] addAnimation:anim1 name:@"anim1"];

        CCAnimation *anim2 = [CCAnimation animationWithFrames:some_array2];
        [[CCAnimationCache sharedAnimationCache] addAnimation:anim2 name:@"anim2"];

        CCAnimation *anim3 = [CCAnimation animationWithFrames:some_array3];
        [[CCAnimationCache sharedAnimationCache] addAnimation:anim3 name:@"anim1"];   
    }
}
@end

Then when you are ready to use the animation, it’s simple to retrieve them by name like so:

CCAnimation *anim1 = [[CCAnimationCache sharedAnimationCache] animationByName:@"anim1"];
CCAnimation *anim2 = [[CCAnimationCache sharedAnimationCache] animationByName:@"anim2"];
CCAnimation *anim3 = [[CCAnimationCache sharedAnimationCache] animationByName:@"anim3"];

Hope this simple tip was helpful to someone. Happy coding!

 Posted by at 2:01 pm  Tagged with:
Dec 162010
 

This is a continuation of yesterday’s entry Animation in Cocos2D (running across the screen). I want to achieve the same animation but use a texture atlas instead of loading individual sprites.

What is it?

A texture atlas (sometimes called a texture sheet) is simply a single image which contains all (or some) of the sprites used by the game.

Take a look at the image to the left. The program I’m using is called Zwoptex which is a tool that helps you make a texture atlas out of individual images. There is another application called Texture Packer which does the same thing with a few extra options. They are both great tools for the task. I won’t bore you with the details on how to use these programs because they are fairly simple to use and self-explanatory.

Notice the images of Mega Man in Zwoptex above. I imported the 5 individual images (mega1.png through mega5.png) into the program, clicked on the “Apply” button and the program ordered the images as you see it in the screenshot. Then the program will export the images into a single image (texture atlas) and also create a plist file that contains all the meta information about the images such as the image name, sprite size and the location to find that particular image in the sprite sheet. Take a look at the screenshot below which shows the contents of megaman.plist that was created by the program. Cocos2D then loads the plist file to be used by the engine.

It is recommended to use texture atlases instead of individual sprites because texture atlases can help you save memory and increase performance when used along with the CCSpriteBatchNode. When animating a game character, all you are doing is moving to a new location on the sprite sheet for each animation frame instead of loading a new image. Think of it as kind of a sliding window on a big sheet of paper. The only thing you see is the image through that window that slides around that sheet of paper. There is one important thing to remember about texture atlases though. The dimension of the texture image must be in powers of 2 (16×32, 32×32, 512×512, etc — and there is a maximum dimension too at 2048×2048 for the iPhone 4 and the iPad, and 1024×1024 for the previous generations).

Show me the code!

Again, I’m using Cocos2D version 0.99.5. I created a Cocos2D application from the template, and I’m simply using the HelloWorldScene class and modifying the init method. The first thing that must be done is to load the plist and the sprite sheet image. The code to achieve this is below.

[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"megaman.plist"];
CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:@"megaman.png"];
[self addChild:spriteSheet];

Next, a CCSpriteFrame must be created for each animation frame. Notice how much simpler this step is compared to the way it was being done in Animation in Cocos2D (running across the screen). The code is pretty simple. We load 5 images so we loop 5 times and fetch the CCSpriteFrame from the CCSpriteFrameCache. Keep in mind that the filename comes from the megaman.plist file. Cocos2D uses the information in megaman.plist file to locate the image inside the texture atlas (megaman.png).

NSMutableArray *animFrames = [NSMutableArray array];
for (int i = 1; i <= 5; i++) {
	NSString *file = [NSString stringWithFormat:@"mega%d.png", i];
	CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:file];
	[animFrames addObject:frame];
}

The remaining code is exactly the same as the version that didn't use the texture atlas. The player is positioned and then animated.

CCSprite *player = [CCSprite spriteWithSpriteFrameName:@"mega1.png"];		
player.position = ccp(10.0f, 50.0f);
[spriteSheet addChild:player];
		
CCAnimation *anim = [CCAnimation animationWithFrames:animFrames delay:0.05f];
CCRepeatForever *repeat = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:anim restoreOriginalFrame:NO]];
CCAction *moveAction = [CCMoveBy actionWithDuration:2.0f position:CGPointMake(500.0f,0.0f)];
		
[player runAction:repeat];
[player runAction:moveAction];

Source Code and Video

The video looks exactly the same as before. And here is the sample code.

Mega Man running from Min K on Vimeo.

Happy coding!

 Posted by at 9:13 pm  Tagged with:
Dec 152010
 

Introduction

I have always been mesmerized by video games and have wanted to make games since I started programming. The kind of games that I wanted to make were the kinds that were being produced by big studios with multi-million dollar budgets. So every time I tried to venture into it, I let myself get overwhelmed and discouraged. But the iPhone has made indie game development possible again, and it has once again sparked my interest in game coding.

It’s been a long time since I programmed a game. The last game I created was a Tetris clone that I named after myself called Mintris. It was back in the days when DOS was limited to 64KB of memory, and all the graphics routines were hand written in C and inline assembly. I remember writing directly to the VGA memory to put pixels on the screen. I was really proud of Mintris. It even had music and sound effects. I don’t know if anyone will remember, but there was a computer music format called MODs, and I used that as the background music. Good times! Not too long after that, 3D engines started popping up and it seemed like all the games were first person shooter DOOM clones.

Video games have come such a long way. It has exceeded my wildest imagination. But my fondest memories are of the 8-bit Nintendo days, when, as a young lad, I spent my days arguing with friends about how 16-bit game consoles will change the gaming world. And imagine what a 32-bit gaming console would do! Those 2D NES games were a blast though! And it makes me very happy to see a thriving 2D game market on the iPhone. So I have once again decided to try programming a game. But first, I need to learn the tools. And it seems that Cocos2D is the 2D game engine of choice.

Let’s Start!

When learning something new, I usually like to start off very simple. All programming books start off with the “Hello World!” program. This is my version of the “Hello World!” program of Cocos2D and sprite animation. All I wanted to achieve was a character moving across the screen. But it wasn’t enough to simply move an image across the screen. I wanted the character to “run” across the screen. That would mean that the character needs a “run” animation and also must be translated across the screen simultaneously.

I searched the interwebs for a public domain sprite and came across these images that kind of resemble Mega Man.

I titled them mega1.png, mega2.png, mega3.png, mega4.png and mega5.png and added them into my project. I am aware of the sprite sheet or the sprite atlas, but I purposely avoided using it for this sample. I will convert this project to use one in the future and write a future post about it.

For this project, all I was interested in was creating the simplest running animation possible, which means no code design. I simply created a new Cocos2D application template and used the template code as it is. When you create a new Cocos2D application project from the template, it will create a HelloWorldScene.m file. Inside that file you will see an init method. This is where I placed all my code.

Setting up the CCSpriteFrames

I am using version 0.99.5 of Cocos2D. The first thing that must be done is to create a series of CCSpriteFrame objects that will be played back as an animation. It turns out that it’s not as straight forward as simply adding a sprite. You will have to create a CCTexture2D object because it is needed to create the CCSpriteFrame object. I do this 4 more times, one for each remaining sprites (mega2.png, mega3.png, mega4.png and mega5.png), and add each CCSpriteFrame into an array. The code below is for the first one (mega1.png).

CCTexture2D *texture;
CGSize textureSize;
CGRect textureRect;
CCSpriteFrame *spriteFrame;
NSMutableArray *animationFrames = [NSMutableArray arrayWithCapacity:5];

// Repeat block of code below
animationFrames = [NSMutableArray arrayWithCapacity:5];
texture = [[CCTextureCache sharedTextureCache] addImage:@"mega1.png"];
textureSize = [texture contentSize];
textureRect = CGRectMake(0, 0, textureSize.width, textureSize.height);
spriteFrame = [CCSpriteFrame frameWithTexture:texture rect:textureRect];
[animationFrames addObject:spriteFrame];

// Repeat block of code above for mega2,png, mega3.png, mega4.png, mega5.png

Then I add the initial sprite and display it on the screen, at position (10, 50). In Cocos2D, (0, 0) is the lower-left corner of the screen.

CCSprite *mega = [CCSprite spriteWithFile:@"mega1.png"];
mega.position = ccp(10.0f, 50.0f);
[self addChild: mega];

Setting up the CCAnimations and CCActions

The next step is to define the animation and the actions. The running animation is set to repeat forever with CCRepeatForever action (CCRepeatForever is a subclass of CCAction). The second action simply moves Mega Man from (10, 50) to (500, 50) in 2 seconds. Mega Man actually runs past the right edge of the screen, because the iPhone’s resolution is 320×480 (for a non-retina display). By the way, this is in landscape orientation if you are wondering why I used such a huge number like 500.

CCAnimation *animation = [CCAnimation animationWithFrames:animationFrames delay:0.05f];
CCAnimate *animate = [CCAnimate actionWithAnimation:animation];
CCRepeatForever *repeat = [CCRepeatForever actionWithAction:animate];
CCAction *moveAction = [CCMoveBy actionWithDuration:2.0f position:CGPointMake(500.0f,0.0f)];

Running the Animation

Finally, the two actions are run together to create the running across the screen animation.

[mega runAction:repeat];
[mega runAction:moveAction];

I still have a long way to go before I can create a full fledged game :) I’ll be posting what I learn for my own reference here so please feel free to check back regularly.

Source Code and Video

Here is the sample code. And here is a ghetto video of the animation:

Mega Man running from Min K on Vimeo.

Happy coding!

 Posted by at 9:09 pm  Tagged with:
Dec 122010
 

Here is a very simple but a useful tip. Instead of using NSLog to print out debugging information, define a custom macro that prints out the message along with the class name from which it is being printed only when it is in debug mode. This is very convenient because you do not have to manually remove all your logging messages when you are ready to build your code in release mode.

You can define a preprocessor called “__DEBUG__” that is only defined in debug mode. So set your active configuration to debug mode, and then right click on your project and choose the “Get Info” menu item. You will see a window like the picture on the left. Scroll down and search for a section called “User-Defined”. Locate the item “GCC_PREPROCESSOR_DEFINITIONS” and then add “__DEBUG__” (without the quotes) as a preprocessor.

Next comes the macro. Create a header file called Debug.h and then copy and paste the code below into the file.

#if __DEBUG__
#define DEBUG(format,...) NSLog([NSString stringWithFormat:@"%@: %@", NSStringFromClass ([self class]), [NSString stringWithFormat:format, ##__VA_ARGS__]]) 
#else
#define DEBUG(format,...) 
#endif

#if __DEBUG__
#define DEBUG_C(format,...) NSLog(format, ##__VA_ARGS__) 
#else
#define DEBUG_C(format,...)
#endif

There are two macros defined – DEBUG and DEBUG_C. This is because DEBUG uses Objective-C specific function call that does not exist in pure C. So if you are printing debugging information from pure C, then use DEBUG_C instead.

You can now use DEBUG in place of NSLog. You still need to prepend the string with the ‘@’ sign:

DEBUG(@"Entry number %d.", entryNum);

If the statement above was called in the class SayaSecretAppDelegate, then the code above will print:

2010-12-13 01:44:14.015 SaS Pro[60796:207] SayaSecretAppDelegate: Entry number 2.

As you can see, it prints the class from which it was printed, which in this case is the class SayaSecretAppDelegate. When you compile and run the code in release mode, none of the debugging output will be present. In fact, they will not even be part of the compiled code because it is excluded by the preprocessor.

Happy coding!

Dec 112010
 

Every now and then I run into a issue that ends up taking disproportionately inordinate amount of time to the simplicity of the problem. I ran into such an issue a couple days ago. I checked and rechecked but I continued to get an error message in my console whenever I ran the project.

The problem arose when I added a new UIControllerView class and a corresponding XIB resource file to my project. I had two targets, one for the free and the other for the paid version of the app. My free version compiled and ran without any issues. The paid version, however, compiled fine but when I ran it, I kept seeing a message in the console that said:

“Unknown class SOME CLASS NAME in Interface Builder file.”

After spending more time than I would have liked to on this annoying problem, I was close to giving up until I noticed two sections under the targets for the project named Copy Bundle Resources and Compile Sources. You will see what I am talking about if you refer to the picture at the bottom.

I discovered that the free version’s target had all the classes and resources account for under these sections, but the paid version was missing a class and a resource. So I simply dragged and dropped the missing items to these sections. And presto — I was happy again.

Hopefully I was able to save someone from the same annoyance and frustration.

Happy coding everyone!

Dec 092010
 

I would like to announce the launch of our companion web site for Say a Secret at www.sayasecret.com. Please check it out!

Along with the web site, we just had two of our apps approved by Apple yesterday. Please look for it in the app store. They are called Say a Secret Pro and Say a Secret Pro HD (iPad version). There are a lot of new features in this release, including the ability to leave text secrets and a text-to-speech feature.

I have around 25 promotional codes remaining if you would like to try it for free. Please drop me a line and I’ll be more than happy to send you one!

Disclaimer: The App and the site is intended for mature audiences only. The content is socially driven, so we are not responsible for the content.

 Posted by at 5:18 am
Dec 042010
 

I told myself that I would keep this blog updated, but I’ve been derelict in keeping my self-made promise. So I am putting forth the effort to post more regularly.

Even before the iPhone was released to the public, I saw a demo video of the iPhone and one of the things that blew me away about it was the smooth animation. Windows were sliding in and out and bouncing plus all sort of different animation effects that I never witnessed on a phone before. One of the animations that I really like is when a screen slides into view from the bottom of the phone. But it doesn’t just slide into view from the bottom! It slides into view, hits the top of the screen, and then it bounces a couple times before finally coming to rest. I wanted to achieve this effect in a recent iPhone application I just released. Here is the code to achieve this effect.

The code below uses Core Animation to achieve the effect of a window sliding in from the bottom. On line 1, I set the alpha value to 0.46 because I also fade-in the view as it’s sliding into view. Also notice on line 6 the call CGAffineTransformMakeTranslation(0, -380). You will see that the the “y” component is set to -380. This is because the view is initially positioned at 380 — outside the visible area, all the way at the bottom of the screen. I have some other controls taking up space at the top and bottom of the screen, so 380 pixels suffice even though the iPhone’s screen resolution is 320 x 480 (for non-retina displays).

[recordTextSecretViewController.view setAlpha:0.46];
[UIView setAnimationDelegate:self];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.4];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
recordTextSecretViewController.view.transform =
               CGAffineTransformMakeTranslation (0, -380);
[UIView commitAnimations];


The code below is the bounce animation. It bounces for 0.2 seconds, for a total of 2 times.

CABasicAnimation *bounceAnimation =
                    [CABasicAnimation animationWithKeyPath:@"position.y"];
bounceAnimation.duration = 0.2;
bounceAnimation.fromValue = [NSNumber numberWithInt:0];
bounceAnimation.toValue = [NSNumber numberWithInt:20];
bounceAnimation.repeatCount = 2;
bounceAnimation.autoreverses = YES;
bounceAnimation.fillMode = kCAFillModeForwards;
bounceAnimation.removedOnCompletion = NO;
bounceAnimation.additive = YES;
[recordTextSecretViewController.view.layer addAnimation:bounceAnimation
                                           forKey:@"bounceAnimation"];


Finally, the block of code below will fade-in the view as it’s sliding into view (and bouncing).

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
recordTextSecretViewController.view.alpha = 1.0;
[UIView commitAnimations];


If you are curious about what all the different properties mean, check out the documentation in XCode. For example, to see the documentation for CABasicAnimation, alt-double click the word in XCode and you will be able to open the on-line manual. I made a simple example XCode project to show this effect. You can download it here and try out the effect. I hope that this has been useful to someone!

Happy coding!

 Posted by at 10:21 pm
Dec 012010
 

It is trivially easy to trim beginning and trailing spaces in Java. You just call

"   some string   ".trim()

and that’s the end of it. It’s not hard in Objective-C, but it’s a bit more verbose.

NSString *s = @"    I am a string to be trimmed     ";
NSString *trimmed= [s stringByTrimmingCharactersInSet:
                       [NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(trimmed);
 Posted by at 11:30 am