Thursday, June 7, 2012

How I learned to program an iOS game using cocos2d



I just wanted to share my experiences learning how to program in objective-c, learning how to work with cocos2d, and creating my first game. Warning: the following is a very long post. About 4 months ago, I had little to no experience in programming and I am here to support the claim that anyone can make (and program) video games. The game is called "Tower Heroes" and its a tower defense-style game available for iPhone/iPod touch (unfortunately, nothing for Android). A small twist I added to the gameplay was adding "Heroes" which the player can select and use during the game. Each of the available heroes have a certain set of abilities which can be used during the game. The heroes also gain experience over time and can level up. Once a hero levels up, they gain "talent points" which can be used to upgrade powers.

Long story short, I was working in the biotech/market research industry for about 2.5 years, life was stable but it was not the most interesting work and I decided that I needed a change. I've always thought that programming a game would be pretty awesome, and experimenting with iOS seemed like a good choice. So, I started learning objective-c from scratch. For those with very little experience in programming but would like to learn objective-c, I would recommend:
  • Learning Objective-C on the Mac by Mark Dalrymple and Scott Knaster (Appress Series)

I know there are a lot of other great books out there, but this is what I went with. I went through this book in little over a week trying to absorb as much as I can. I found the explanations very clear and I feel the authors gave a great introduction to objective-c. However, I felt it didn't adequately cover memory management issues and using properties and how they affect retains/releases. This really tripped me up later during my game development. Anyways, overall, I would highly recommend this book.

Now, at this time, I had this idea in my head that I needed to learn OpenGL, otherwise I couldn't make a cool game. So I found some OpenGL tutorials online. After several hours of reading through gobble-de-gook and not understanding a single thing about shaders and buffers, I came across the term "cocos2d." I checked it out in more detail and found it to be an easy to use and versatile framework for developing games with a lot of the OpenGL stuff being done behind the scenes for you. Cocos2d really helps you focus on learning how to program game logic while keeping the graphics-related jargon to a minimum. If you're more interested in how graphics are rendered, working through OpenGL may be better than using something like cocos2d. Anyways, overall, I would recommend cocos2d to anyone interested in developing a 2D game in iOS. I would not recommend diving into OpenGL if you're a new game developer.
I was also browsing forums and tutorials during this time as well. I would say one of the most useful tutorial sites I found is the iPhone tutorials offered by Ray Wenderlich:
He offers tutorials from learning objective-c as an absolute beginner, to developing your first iOS games, to learning how to use the cocos2d framework, to marketing your app, to saving/loading data.. basically, this site should keep you interested and busy for a long time. Of course, I also recommend using Stack Overflow and the cocos2d documentation and forums as I used those quite often, if this is the route you choose.

Anyways, I spent some time going through these tutorials until I decided to purchase Ray's book on cocos2d:
  • Learning Cocos2D by Ray Wenderlich and Rod Strougo

I was not disappointed. This is where I would say I learned the core of my cocos2d knowledge. I would definitely recommend this book.

Of course, you can't simply learn how to program a game by reading books and forums. The single most important thing to do in order to become familiar with a language is to code, code, code. I know there are people out there who aren't really textbook people, but I'm the type of person who likes to sort of "ease" my way into learning new material by by reading through a book and supplementing that with online tutorials and documentation. Every person is different though -- this is what worked for me.

About 2 months into working through tutorials and creating example games (and after taking a couple days off to beat Mass Effect 3), I decided to develop a game of my own. My friend suggested a "tower defense" type game to start and I thought that was a good idea for a beginning developer so then it began. It took about 1.5 weeks to work out most of the game logic I needed, but I quickly realized that I needed art to animate. I would not consider myself and artist and I've never used any professional art-making software before so I felt stuck. But I did some research and decided that using Adobe Illustrator was the way to go. What I liked about Illustrator was that it allows you to create vector-based art which essentially does not lose resolution whenever you need to resize it (I had to play around with resizing images A LOT trying to find the perfect balance between optimizing iPhone screen real estate and making sure things weren't too small). I took about a week off from programming/game development to learn how to use Illustrator and create most of the final art. Fortunately there are tons and tons of Illustrator tutorials available on the internet. This is the power of the internet. In addition to learning how to use Illustrator, here's a couple other cool programs I learned how to use while hooking up the art:
  • Tiled -- a program used create tilemaps for your games. You can export this data easily and use it as part of your cocos2d project. I ultimately ended up not "tiling" my background maps, but learned a valuable tool to use for any future tile-based games I work on.
  • Texture Packer -- an awesome program that allows you to group all your individual images (like hero images, game items, powers, etc) into one huge image. Texture Packer creates this image as well as a data file that maps all the images to specific coordinate which you can then use as part of your cocos2d project. The frequent use for this in cocos2d is give OpenGL the ability to "draw" things all at once instead of individually drawing each necessary item on the screen which takes more time (and can cause lag if there are too many items that need to be drawn on the screen). If that doesn't make sense to you, that's okay. It didn't make sense to me at first. It still doesn't fully make sense to me as I'm not very familiar with OpenGL yet.
  • Glyph Designer -- another awesome program that allows you to customize the fonts for in-game text as part of your cocos2d project. Custom fonts can make the game look much more professional and polished -- it may take a couple tries to get the font just right. You can also create direct images from the text, if needed, which I did at times. Note: Glyph Designer isn't free but there are free alternatives like Hiero Font Builder Tool.

I spent a couple days hooking up the art with the code. Then, I came to another serious stopping point: how do I add sound to the game? Fortunately, I had a musician friend who was kind enough to help develop the music. Cocos2d also provides an easy way to implement music within a game (using the class SimpleAudioEngine). There are definitely articles/resources available on explaining some of the finer points of formatting your audio to play nice with your iOS game such. Here's one brief example:



I spent another week having my friend develop the music as well as combining it with my game. Surprisingly, I was really shocked how much of a difference it made to have sound in the game. I guess I took it for granted in all the games I've played. I spent a couple more weeks refining the art, UI, and balancing the game. Feedback from friends during this time was really helpful. They really helped in keeping me focused and making sure that the UI was at an acceptable state before I decided the game was complete.

I decided at this point that before I submit the game to the App Store, I wanted to test the game. In retrospect, this was actually a very good decision because learning how to "beta test" your game and actually send the game to others is very similar to actually submitting the game to the App Store for approval. It's a bit different from testing the app on your personal mac or iPod touch and you have to be careful you are building the app the right way. Otherwise, it won't work on your friend's device for testing and ultimately, you may unknowingly send a bad file for Apple to review only to have it rejected because it wouldn't work. Get this part right. A tool that was very useful during this beta testing process is called TestFlight. They have a quick tutorial there on how to properly package your game for beta testing and it also makes the distribution process much less painful.

One of the hardest aspects of this project was balancing the game. It's still not too balanced (a good amount of people have complained that the 1st level is too hard), but I think it is possible to beat.. I can definitely modify the levels if it becomes a real issue.

Something I realized while creating the game is that providing some sort of "gameplay feedback" that the player can see seems to be very important. For example, simply adding health bars to my enemies and having them decrease as the enemies took damage seemed to make the gameplay feel more fun. Having damage text appear as enemies took damage. Adding this feature made the gameplay feel more fun as well. Providing information on which round in the level the player was on seemed to make it things less frustrating, etc. Again, these are all things I have probably taken for granted as a gamer but in designing a game, especially as a beginning developer, these were things that were not obvious to me. Lesson learned.

Anyways, I know this was an extremely long post, but I hope someone finds this helpful. All in all, it took about 4 months to get where I'm at today as a game developer. It has been a great learning experience, a huge change from what i was doing before, and I hope to be producing more polished and fun games in the future. I started out feeling that I could not get myself to learn anything after being "burned out" from my previous job, but that wasn't true at all. It took some time to adjust but if you have the desire to learn, your brain will follow. If you want to create a game using a programming language, you can do it!

If you have an iPhone/iPod touch and would like to check out my game, here are some links. Feedback appreciated!:
Thanks for listening!

tl;dr:
  • quit my day job; decided to learn how to program an iOS game
  • the book I used for learning objective-c: Learn Objective-C on the Mac (Dalrymple, Knaster)
  • one of the most important aspects of using objective-c is good memory management; do read up on that (I realize iOS 5 introduces automatic reference counting, or ARC, which I'm not too familiar with, but it's still very helpful to learn good memory management, esp. if you're using cocos2d as (I think) it doesn't support ARC yet and it will also help you with debugging memory issues if things go wrong
  • the book I used for learning cocos2d: "Learning Cocos2D" (Wenderlich, Strougo)
  • if you're a beginning game developer, I would not recommend trying to learn OpenGL at the outset (but you're free to try!)
  • my favorite tutorial site for learning iOS/cocos2d: Ray Wenderlich Tutorials
  • if you want to learn cocos2d effectively, do read the online documentation as well as the cocos2d documentation in your project (sometimes the online documentation is outdated)
  • A couple great programs I learned about along the way which I used while developing the game: Tiled (tile-editing program), Texture Packer (packs smaller images into one large image; frequently used to speed up OpenGL draws in cocos2d, Glyph Designer (used to create custom fonts for use in your game), Adobe Illustrator (flexible program that allows you to draw vector-based art; I found it to be a great tool while creating characters for my 2D game)
  • a great program for "beta testing" your iOS game: TestFlight

Tuesday, March 27, 2012

Potential solution to EXC_BAD_ACCESS issue using CCLayer / CCNode

A recent problem I ran into, I was getting EXC_BAD_ACCESS issues when switching scenes in cocos2d. The problem was in the CCLayer's dealloc method. In particular this line (it may look a bit different in different versions of cocos2d):


- (void) dealloc {
...
    CCNode *child;
    CCARRAY_FOREACH(children_, child)
        child.parent = nil;
    [children_ release];
    [super dealloc];
}


OR


- (void) dealloc {
...
    for (CCNode *child in children_) {
        child.parent = nil;    
    }
    [children_ release];
    [super dealloc];
...
}


What it's basically doing is setting each child's (e.g., CCSprite) reference to its parent to nil and then releasing all the child objects from memory. What I was doing wrong was "fastidiously" releasing the child objects from CCLayer's dealloc method without thinking (I had declared them as instance variables of my CCLayer so I was then mindlessly releasing them in my dealloc method); then, when [super dealloc] is called in my CCLayer's dealloc method (which calls CCNode's dealloc method, since CCNode is CCLayer's superclass), there were no child objects to release since I already released them. Solution: remove my mindlessly written releases for the child objects from my CCLayer's dealloc method. High level points: (1) CCLayer will increase the retain count on objects you add as child objects (using the addChild: method), (2) CCLayer will clean up the child objects when CCLayer is deallocated.


It gave me a better understanding of memory management. Hope this helps someone.