Tuesday, April 6, 2010

The Doodle Contest

Oh yeah. I know I mentioned this below, but in case you missed it, definitely check out the Doodle Contest. Just click on the image for more info:
As a bonus, here are a couple of pictures from the iPad launch crowds in front of the local Apple store this past Saturday. The first is just a mood shot. The second is my attempt at pretending to be sociable and hip as a local developer. Both of these masterpieces are courtesy of ReesPhoto.com.

(Here I'm the model, not the photographer - just to be clear)

iPad Impressions and Other Goodies

The weekend is over and I can start thinking more rationally about the iPad. Haha! Right... Anywho, here are some impressions.

It’s a sleek little device - thin, light, and just shiny enough to invite your fingers to rub it all over. However, the more I keep looking at it, the more it looks like an oversized iPhone. I have to laugh each time I see my iPod Touch right next to it. I can just imagine women pulling an iPad out of their purses to answer a telephone call or jocks with iPads strapped to their biceps as they jog on treadmills in the gym.

If you disregard the perf boost needed to deal with the quadruple-sized screen, the iPad doesn't seem to run that much faster than the iPhone. It doesn't run slower either, which is a good thing, but it's not the speedy bullet that Apple initially implied. If you use the same tricks you use on the iPhone, though, it runs just fast enough.

Initially, I was more than a little worried when I developed code against the iPad simulator. Using Cocos2D, whenever I plopped a large texture on the screen, say a background, the frame rate would immediately drop to 20-30 FPS, even with OpenGL blending completely disabled. If you write a game, you need at least one large background texture most of the time, so the potential frame rate limitation posed a serious problem. That said, I was very happy to find out that the actual iPad handles all OpenGL calls much more gracefully. Doodle Blast! ran on full 60 FPS with the screen mostly empty and barely dipped into the 40s with everything in motion. I must say that the game looks quite slick on the big screen, especially when the camera zooms in and out while everything is in motion. Best looking doodles five bucks can buy!
In the end, I don’t think the iPad will reach nearly the popularity levels of the iPhone (watch me be completely wrong!). It’s definitely a fun toy to play with, though.

So, what’s next? Not sure. Right now I’m taking a little bit of time to catch my breath. I can hardly believe that it has been only one month and two weeks since Doodle Blast! first hit the stores – now there is an update, and iPad version, a blog, a web site, two trailers, over 11,000 lines of code and a contest. Talk about busy!

On a different note, I was browsing through the Doodle Blast! code base and I ran into two Cocos2D utility classes that I keep using and re-using all over the place. So, I thought I would share them with you. The way I generally write code under pressure is to write and polish the code paths that I need, leaving all others to be flushed out when they are actually needed. What that means for you is that these snippets are not fully complete, but they work as a great starting point. Feel free to use them however you please. A mention of credit is always nice, but not required.

The first utility is an action, EyeBlink (EyeBlink.h, EyeBlink.m), that does just that – blinks "eyes" on sprites. Basically, it takes 1 or 2 sprite frames as input. You can either specify two frames – one with eyes open and one with eyes closed – or just a single frame of closed eyelids that will be superimposed over an image of your character. The action then switches between these frames (or hides them if only one frame is specified) with some randomness built in to simulate irregular eye blinks. Here is how you’d use it:

Option 1:
CCSpriteFrame* openFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"eyesOpen.png"];
CCSpriteFrame* closedFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"eyesClosed.png"];
CCSprite* myCharacter = [CCSprite spriteWithSpriteFrame:openFrame];
[myCharacter runAction:[EyeBlink actionWithOpenDuration:0.7 openVar:0.3 closedDuration:0.1 closedVar:0.05 openFrame:openFrame closedFrame:closedFrame repeatForever:true]];
[myLayer addChild:myCharacter];

In this case you create two frames and alternate between them. The duration of the open frame will last 0.7 +/- 0.3 seconds while the duration of the closed frame will last 0.1 +/- 0.05 seconds.

Option 2:
CCSpriteFrame* characterWithEyesOpenFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"myCharacter.png"];
CCSpriteFrame* closedEyeLidsFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"eyesClosed.png"];
CCSprite* myCharacter = [CCSprite spriteWithSpriteFrame: characterWithEyesOpenFrame];
CCSprite* eyeLids = [CCSprite spriteWithSpriteFrame:closedEyeLidsFrame];
[eyeLids runAction:[EyeBlink actionWithOpenDuration:0.7 openVar:0.3 closedDuration:0.1 closedVar:0.05 openFrame:nil closedFrame: closedEyeLidsFrame repeatForever:true]];
[myCharacter addChild:eyeLids];
[myLayer addChild:myCharacter];

The same frame duration parameters apply here as well, but instead of switching between two frames, the code shows and hides a single frame.

The second snippet is a Chipmunk / Cocos2D debug node (DebugDrawNode.h, DebugDrawNode.m) that automagically draws debug outlines of all collision shapes associated with a given cpSpace object. It’s a simple subclass of CCNode with a custom draw() method. To use it, instantiate it and add it to your layer at the proper Z-depth thusly:

cpSpace* space = … ;
[myLayer addChild:[DebugDrawNode nodeWithSpace:space] z:SOME_Z_VALUE];


Monday, April 5, 2010

Doodle Blast! Update Released

I guess Apple was busy with the avalanche of iPad apps for the past several days so it took a while longer, but Doodle Blast! update has finally hit the stores on Saturday. It took about three weeks to put together and now the code line count is up to over 11,000 from the original 7693. Phew!

By popular request, I've added a health bar and the ability to post your scores online later. I've also added a news ticker (which I'm about to test later today) and a mini-game - The Attack of Evil Vampire Bunnies . They were originally intended to be Easter bunnies, but I had to put the project on hold for about a week to port Doodle Blast! onto the iPad, so Evil Easter Bunnies became Evil Vampire Bunnies. Shhhhh!!! No one will ever know...

I was up all night last night trying to come up with a trailer and here is the result:

I should really try to find someone to do these for me. Not that I mind expressing my artistic side, but, let's face it, I'm probably a better coder than animator. Nonetheless, I hope you enjoy it and download the update if you haven't yet!

Saturday, April 3, 2010

Alive and Kicking!

Doodle Blast! HD has hit the streets today and so have I! I just came back from the Apple store in U Village in Seattle, where countless number of “early adopters” and geeks like myself spent the wee hours of the morning waiting for their shiny box. More on that tomorrow, because I'm exhausted after two weeks of very little sleep and the couch is calling my name. However, I was finally able to see Doodle Blast! HD on the device itself. All I can say is - smooth as butta'...

Thursday, April 1, 2010

Ready to Go

After some confusion and near heart-attacks yesterday when I thought that Doodle Blast! HD was rejected from the AppStore, I came to find the following message this morning:
Boys and girls, it's official! I, of course, have no clue _how_ the game runs on the iPad, but it seems that it least runs. I'm guessing that I'll be updating the iPad version sometime this weekend once I actually see it running on the device. Until then, I'm biting my nails in anticipation.

And check out the updated Game Collage web site. Brand new as of yesterday! Here is the welcoming image for you:

Tuesday, March 30, 2010

Those Pesky Crashes

Unless you have a dedicated team of testers working with you, it’s pretty easy to publish an app with bugs in it. Hopefully, the majority of your scenarios work because you’ve tried them out (that is assuming, of course, that you are not publishing titles for a device you’ve never seen - hello, iPad!). However, there is always some weird combination of user input you haven’t thought of that, apparently, everyone else has.

We’ve all been there - you write an app and a friend of yours wants to take a look. You reluctantly give up possession of your precious little baby and cringe in the background as your friend taps on all the wrong places. Three seconds later, he returns the device to you with your app all locked up or, better yet, not running at all. You and your friend never talk again.

Okay, so maybe that’s just me. However, my point is that even in these scenarios, you are pretty safe. Apart from losing a friendship or two, you can go home, try to recreate some of the issues, and fix the bugs you find along the way.

When you ship, however, chasing crashes becomes much more difficult. Apart from getting the occasional “The app crashes and it sucks! Don’t buy it” review, you don’t get much information about how your app performs. You may not even know that it crashes at all; not unless you look at Apple’s iTunes Connect portal in a little more detail.

I’ve just submitted an update for Doodle Blast! today and discovered this handy little button hiding underneath the application details:

Clicking on it, you get a nice little summary of what, if any, crashed have been reported:

Besides being told about the crashes, you can download a .crash file, which magically opens up on your machine and shows you the full stack trace of your app at the time of the crash.

That’s pretty cool! I’ve worked on a variety of platforms where you might get some core dumps but, no matter how hard you try, you can never get your hands on the actual stack trace. Either your symbols are too old, or they are from the wrong build, or you just didn’t clap your hands three times before throwing some salt over your shoulder. Whatever the case, the bottom line is that getting some useful information out of a crash log is always a challenge.

This is not the case here. You just need to know that these crash logs are available. I didn’t… until now. And, sadly, it turns out that Doodle Blast! crashes every now and then. Curious, I looked at the downloaded .crash log and discovered that if you tap on the Doodle Blast! title text in the main menu, bad things happen. Don’t do it, kids. You’ve been warned. Fix coming up in the next update…

Friday, March 26, 2010

Bigger Is Better

What a week! I always thought about porting Doodle Blast! onto the iPad at some point. But when Apple announced last Saturday that the iPad app submission deadline is on March 27th at 5pm, I realized that “at some point” has suddenly come to mean “now”.

I woke up on Sunday morning and started. I must admit, I felt a little overwhelmed. I haven’t even installed the required SDK yet, let alone read through the iPad documentation or try out the iPad Simulator. I like working on my own pace and suddenly having a hard deadline in a week felt strangely reminiscent of work.

I glanced through the docs and I ran into a very interesting point – in order to install the SDK you need to be running Snow Leopard. I was only running Leopard at the time. Hmm… Inquiring further into matter, I came to find a number of people complaining about Snow Leopard on the Internet about missing drivers and compatibility issues. Double hmm…

So I went down to the Apple store, picked up a copy of Snow Leopard, asked the sales girl whether I can boot up an Apple machine from an external hard drive, witnessed her nodding aggressively (although I had some doubts as to whether she had any clue about what I was asking), picked up an external HD and went home. Kudos to Apple, you actually can install and run an OS from an external hard drive pretty easily. The machine even shows you pretty chooser at startup time. If you are interested in doing the same, these instructions proved very useful. As a side note, though, Snow Leopard runs pretty smoothly. I was worried about having all my game-making tools work nicely with it, but they do, so my fear was unfounded.

Anyway, that killed my Sunday – lots of downloading, lots of shopping, lots of installing, and lots of reading.

What followed for the next five days was a whirlwind of coding and testing and rewriting and redrawing, an effort that eventually culminated in my iPad app submission about two hours ago, followed by a frantic re-submission about an hour later when I realized that my new code had a deadlock in it which didn’t show up in the simulator.

I’ll post some more highlights and gotcha’s in the coming days, but for now I’m getting sloshed on wine and hoping that I didn’t miss anything major (which is always possible, given that, like most mortals, I’ve never held the device in my hands). Good luck to me!

Tuesday, March 23, 2010

One Hot Doodle

The week is over (at least according to some strange iTunes clock) and Doodle Blast! is now officially out of the "New and Noteworthy" spotlight. There go the fictional millions ... *sigh*

But what's cool is that Doodle Blast! was just featured by Apple in their "What's Hot" list as well as the "Best Doodle Games" list. I wish I knew what either of these accolades actually mean, but, hey, I dig 'em! Thank you, man behind the curtain!

Saturday, March 20, 2010

Doodle Blast! score count passes 3000

Perhaps an insignificant milestone for some - yes, you, abitofcode and zombie - but Doodle Blast! has passed the "3, 000 unique scores" mark as of 5 minutes ago. Only 997, 000 more to go!

Thursday, March 18, 2010

Help Doodle Blast! hit Top 50!

You've read the story, you've played the game, you might as well admit it... you LOVE Doodle Blast! Now is your chance to get involved - help the game break into the top 50!

Doodle Blast! broke through the Top 75 games in the US store today. Given that this project started only as a weeklong last hurray for my recent dabbles with the iPhone, I'm very excited and very happy to see the game enjoy this unexpected success, however temporary it may be.

Despite the current spot light, the game is actually not generating too much money. You'd think that Top 100 is the final frontier. But, alas, no. It would be nice if the game sales managed to cover at least a portion of my hardware startup costs (I used to be a Windows junkie... I know...), but I'm not holding my breath.

Regardless, it would be a hoot to see the game make it to the top 100. Since you are reading this blog, you probably already know that Doodle Blast! is a completely indie production, with no studio backing, no advertising budget (or any budget for that matter), and, most of the time, no prior experience in working with any of the components that made Doodle Blast! into what it is (writing code on the Apple platform, creating trailers, sampling music and sound effects, ... sheesh!) How cool would it be if Doodle Blast! actually made it?

So, here is your chance to help - tell your friends, publish blogs, post tweets, and pass the word - Doodle Blast! is hella cool!

Wednesday, March 17, 2010

"New and Noteworthy" in the US Store

Alright, alright, I promise this is the last gloat (for today). Thanks for all the support!

Top 100, here we go!

Pictures are supposed to be worth a thousand words. This one is worth at least 99. Just snapped today in the US store!

Monday, March 15, 2010

Going International

Call me slow, but I just discovered that you can change the default store displayed in iTunes by clicking on the little flag icon in the corner. Who knew? So, for the first time ever, I was able to check out some of the feedback about Doodle Blast! posted by people from all over the world. For example, here is what people in the UK are saying:

"Remember drawing spaceships as a kid and then filling every available bit of their surface areas with guns? This is the tank equivalent! Photos and videos do not do this game justice. You have to play it and control the awesome firepower to really appreciate it."

"I'll take a gamble and say that this game's going to be as big as Doodle Jump and Angry Birds!"

"Cool style, not as good as doodle jump but well worth getting for a mess about"

"Omg this is the next Doodle Jump."

"...Not going to be the next Doodle Jump..."

"This is better and more addicting than Doodle Jump and Angry Birds"

First of all, thank you all for your support! It's cool to hear that UK is having some fun blasting out doodles. However, I also must say that I'm noticing an interesting debate going on. It seems that the question keeping the bulk of British population awake these nights is: Will Doodle Blast! be the next Doodle Jump?

Certainly, it's a topic worthy of a debate. Got an opinion? Let me know!

Oh, and here is a big shout out to Yasar from Turkey! He seems to be a Doodle Blast! fan as well - keep plowing through those meters, Yasar!

Friday, March 12, 2010

Skynet – How to Make The Player Fall While Having Fun Doing It

SPOILER ALERT: If you are a player of Doodle Blast!, this post will spoil some of the fun and mystique behind the game. Consider yourself warned.

One of the unexpected challenges I ran into with Doodle Blast! was difficulty. Some people picked up the game only to feel overwhelmed and lost within a few seconds. Others got bored in just about the same amount of time. Seeing these reactions, I began to wonder how I could dynamically adjust the game to adapt to the player’s abilities. If you are like me and enjoy having nice, slow starts, I wanted the game to take its time building up. If, on the other hand, you are like my brother, I wanted the game to hit you with everything it’s got as soon as possible. End result – we would both be happy because the game provided a different experience for the each of us. But how the heck do you solve this problem?

As it turns out, the solution I coded came in three parts:

  1. Variable aggressiveness – I could tell each enemy how aggressive I wanted it to be
  2. Feedback mechanism – Each enemy could report back on how effective it was at destroying the player
  3. “Skynet” – Central logic interpreted the feedback to adjust the aggressiveness of the next wave of enemies

Because I’m a geek and because it seemed right, the first two values were passed around as floats, ranging from 0 to 1. Zero in aggressiveness meant that the enemy was as passive as possible (it wouldn’t shoot, for example). Zero in feedback meant that the enemy was completely useless (it was killed before it even entered the screen). Ones indicated the opposite for both.

Since each type of enemy was its own class, each could also provide its own way of determining its effectiveness at being a killing machine. What I, then, did as a player was try playing against each of the enemies at various “aggressive” values to find a happy medium between being bored and not being able to keep up. This value (which for most enemies hovered around 0.65) was the golden standard that each enemy was trying to achieve. If it fell short, Skynet would yank up the aggressiveness of the next wave proportionately. If it overshot, Skynet would make the next wave less aggressive.

That was the basic idea. However, there are a couple of other tidbits worth mentioning.

Assaults – each wave of enemies of a similar type constituted an “assault”. If you were kicking butt across all assaults, Skynet would begin sending two or more assaults at a time to give you some extra excitement. If that proved to be too difficult, the concurrent assaults scaled back down.

Fire power – the relative aggressiveness of all enemies also adjusted based on the number of guns you carried. Basically, the more guns you had, the more indestructible you became and the more aggressive the enemies turned.

Shooting strategy – it doesn’t matter if you lose guns from your tank. The only thing that matters are the hit points of the tank itself. Hence, a particularly useful way to defeat the system was to continuously shoot only at the bottom right corner, and just pick up new guns when the old ones got destroyed. So much for Skynet. To counteract this strategy, I added "assassins". The game actually takes note of your favorite shooting spots and monitors the “histogram” it produces. Initially, it lets you get by. However, after the first 1000m, it sends a way of deadly assassins after you that target your tank directly without mercy. These assassins get spawned at the histogram minimum - meaning, at the place where you are least likely to shoot.

The end result of all this magic is that if I play poorly, I can get to about 600m. If I play really well, I can get to about 700m. And that was basically the aim – to give players an opportunity to enjoy bulk of the game play regardless of whether they were pros or rookies. But, as always, there is lots of room for error. Take “Nino", for example, topping the leader boards with a whooping 8561m under the belt. Kids these days…

Tuesday, March 9, 2010

Reaching Out to Younger Audiences

Hey Kids!
If you are digging the AWESOMENESSNESS of Doodle Blast! you are not alone! Check out this young lady kicking some serious butt...

Thanks to sowbug for sharing it!

Saturday, March 6, 2010

Doodle Blast! - Day 7 - Sweet Rest

I was done! So, on the seventh day I went to see a movie instead of sitting in front of a computer. There were a couple of pieces still missing, but all the functionality of Doodle Blast was there:
  1. Tank
  2. Stacking guns
  3. Projectiles
  4. Falling bonuses
  5. Static buildings, flickable soldiers, flying aircrafts
  6. Score counting
  7. Score tick marks
  8. Hit points, damage, and collisions
  9. Single and multi-touch support
  10. Sounds
  11. Menus
  12. Local scores
  13. Global scores
  14. Twitter integration
  15. Loading screen
What was missing was the final images (it’s hard to code and draw at the same time), a few more guns using the existing gun infrastructure (gun images along with data specifying firing frequency, aim speed, cool period, etc.), a few more enemies using the existing enemy infrastructure (images along with data specifying spawn frequency, hit points, damage, etc.), a few more buildings, and some sound tweaks.

After I took day 7 off, I spent three more days working on the above items. Yes, I know, I was cheating again.

However, I did a couple of changes that might interest you:
  1. I added logic to adjust sound volume based on game progression and the amount of mayhem on the screen.
  2. In an attempt to make the game playable by rookies as well as advanced destructionists, I added logic to monitor the user and adjust the difficulty level accordingly.
If either of these interests you, let me know and I will dig into more details with further posts. If not, there you have it folks – The Making of Doodle Blast! in a nutshell.

The final game stats were as follows:
78 code files, 7693 lines of code, 9 textures, 42 sounds, and, as of today, 1773 submitted online scores.

Friday, March 5, 2010

Doodle Blast! - Day 6 - Global Scores

Stats: 66 code files, 5811 lines of code, 6 textures, 247 world flags, 21 sounds

Today, I mostly played with global scores. iPhone has a very sexy control called UITableView. It is essentially a scrollable table of items with lots of possibilities for customization, supporting both linear and hierarchical data visualization. The trouble is that if you want to use all this goodness, you need to learn it first and that takes time. Fortunately for me, Apple has some pretty good documentation about it along with some fun sample code. Plus I found some even more interesting tutorial online. Good thing we have the internet!

Then I had to make sure that the table of scores showed up in Cocos2D mixed in with all the OpenGL goodness. Once again, I was in luck – lots of samples and, actually, a very clean way of doing it:
_tableController = [[ScoreTableController alloc] initWithStyle:UITableViewStylePlain];
UITableView* table = _tableController.tableView;
[[[CCDirector sharedDirector] openGLView] addSubview:table];
I wrote a custom ScoreTableController that subclasses UITableViewController and deals with all the custom display logic. Then I simply added the table that the controller manages as a sub-view of the root OpenGL view. I love it when frameworks actually make your life easier.

The one glitch I ran into was fading. The page that hosted the table view fades in and out of black when it first appears as well as when the user navigates back to the main menu. Cocos2D has a nice set of transitions built into it. However, the table wasn’t part of the OpenGL world and, hence, it was completely independent as far as fading was concerned. So what I ended up doing was fading in the table after the background was already fully there and, vice-versa, fading out the table before fading out the rest of the background. If you look for it in the final product, you can see it, but most people don’t notice.

Doodle Blast! - Day 5 - Menus and Scores

Stats: 60 code files, 5323 lines of code, 3 textures, 21 sounds

I’ve been checking to see how many views there are of each of the videos I post here and here is an interesting statistic:
Day 1 – prototype: 74 views
Day 2 – collisions: 105 views
Day 4 – flicks: 11 views
What’s up kids? Wanna know more about collisions or is it just the teenagers out there searching for YouTube videos that contain explosions and crashes? Flicks, on the other hand, not very popular. And here I thought that that post would be a hit. Oh well, I hope you are ready for some serious excitement, because on Day 5 I tackled the menu system!

Okay, okay, so maybe the menus are not that exciting, but they are still very important and based on some feedback, I still didn’t get it quite right. There were two big complaints. One, the game generates a random name for you to use for score keeping (picking one randomly out of a hat of about ten). That’s all nice, but it turns out that most people post their first global score without realizing that they need to change their name first, otherwise they will just end up posting their score with this generic name. And two, some people score a particular score they are proud of, but they happen to be out of WiFi / cell-phone range when that happens and can’t submit their victorious number at the time. Since there is no “post your high score later” feature, they forever lose the ability to gloat about their achievement in public leader boards. I’ll try to address both of these in the next update.

BTW, in case you were interested, all the scores are kept using the CocosLive service, which is a really nice addition to the Cocos2D library. Also, Doodle Blast is using the free Twitter access libraries published by Matt Gemmell. Thanks Matt!

Besides menus, I’ve added an About page for those 3 seconds of fame, tweaked how multi-touch fire works, and baked score markers into the game itself for extra motivation. The game currently only displays top 100 global scores as little ticks that scroll by in the background (along with top 100 local scores). However, the more people play the game and post their scores, the more out of reach these top 100 scores are getting. For example, Nino and Robin B scored 8561 and 5130 respectively. I don’t know how these guys did it, but I’m seriously impressed. My personal best is about 950. However, the point is that fewer and fewer people actually see score markers in the game any more. So, for the next update, I’m thinking of showing the top 100 scores along with the bottom 100 scores, just to give people who are still trying some hope.

And one more thing – updated gun behavior. Test players suggested to me that if you have guns that fire continuously and if you pick up a new gun by tapping on the falling bonus crate, that new gun should automatically join the continuous fire effort as soon as it’s able, without the user having to lift their fingers of the screen to engage it. Among the changes I’ve made today, I implemented that behavior. Also, I’ve added logic to monitor how many fingers are continuously pressed against the screen. When that number changes, I scan through all the guns that can fire continuously and redirect them such that each continuous touch gets its fair share of continuous gun fire, without the user having to do anything besides worry about catching all enemies. Try it out next time you play the game (but beware that not all guns fire continuously).

Wednesday, March 3, 2010

Doodle Blast! - Day 4 - Tweaks and More Flicks

Stats: 52 code files, 4588 lines of code, 2 textures, 20 sounds

Today was mostly about code clean up, bug hunting, and game play tweaks. The gist of the game was more-or-less there, but it wasn’t very playable yet and I wanted to spend some time tweaking details to make the game cuter. I was also starting to get a little tired and I needed to ease off just a touch.

One of the things I played with was flicking from the day before. You could flick the little soldiers into the air, but they looked very boring when they were falling down because I just applied a random rotation to them when they were released. So, I nixed that behavior and instead let them turn to follow the direction of their path, so that when they were falling down, they would do so head-first. And who doesn’t get a kick from seeing little stick figures falling head-first towards the ground???

I used the following method to turn a given sprite in the direction of the moving, underlying cpBody object:
cpVect direction = cpvnormalize(body->v);
float theta = -CC_RADIANS_TO_DEGREES(acosf(direction.x) * (direction.y > 0 ? 1.0f : -1.0f));
float currentAngle = sprite.rotation;
float dTheta = theta - currentAngle;
while (dTheta > 180) dTheta -= 360;
while (dTheta < -180) dTheta += 360;
Basically, the rotation of the sprite was attempting to conform to the velocity vector, but it did so over time with some easing-in baked in. The constants, in this case, were set to: DIRECTIONAL_MAX_THETA_DELTA = 5 (degrees) and DIRECTIONAL_MOVE_FACTOR = 0.3 (ie. 30%).

You will also notice that there are two types of runners here – the red ones, aka the suicide bombers, which don’t shoot but explode on contact and take away hit points, and the black ones that do shoot but don’t take any hit points when they crash into the tank (incidentally, I stole these pictures from Pop Fizz; that was before the final images were ready). The red peeps also had a count-down over them. Basically, they exploded when the count reached zero. In the final game, I cut that feature because it just polluted the UI and it didn’t really add that much more excitement to the game.

Doodle Blast! - Day 3 - Flicks

Stats: 52 code files, 4436 lines of code, 2 textures, 20 sounds

Today I introduced visual damage model on the player. Interestingly enough, most people playing Doodle Blast! for the first time completely miss it. I wanted to avoid having a health-meter bar or a number somewhere on the top of the screen, so I tried to solve this problem visually instead:

But as I said, most people miss it, so I might need to add a health bar after all.

The other big change in today’s build was the addition of flicking. Following the initial sketch of the game, I wanted to have little soldiers running around. I also wanted them to be flickable as flicking seems to be a popular gesture these days. The implementation was pretty simple.

Each soldier had a state variable, which could contain one of the following values:

  • ATTACKING – the soldier is all gong-ho in trying to get the player
  • GRABBED – the soldier is “grabbed” by a touch and is now following that touch around the screen
  • FALLING – the touch that “grabbed” a soldier ended, and the soldier is now falling
  • RECOVERING – the soldier hit the ground, but under some magic threshold speed. A timer has been set, after which the soldier will resume its attack.

To calculate how and whether a soldier was flicked after it was grabbed, I kept track of the movement of each touch. When I received a TouchMoved event, I used the last touch position along with the last touch time-stamp to compute the speed thusly:

touchSpeed = (currentLocation – lastLocation) / touchTimeDelta;

When the touch ended, I used the touchSpeed, clamped by some max value, and simply set the released soldier off in that direction.

This approach, however, created a problem. You suddenly couldn’t just shoot a soldier, because every touch near a soldier’s vicinity turned into a flick gesture. To solve this problem, I defined two constants: FLICK_TIME_EPSYLON and FLICK_DISTANCE_EPSYLON. If a given touch event took less time than FLICK_TIME_EPSYLON (0.3 secs) and if that touch event moved a total of less than FLICK_DISTANCE_EPSYLON (20 pixels), I wouldn’t consider that gesture a flick, but I would consider it a tap instead and still direct one of the guns to shoot at that location.

Finally, there was one more interesting change that I introduced the day before but didn’t get a chance to talk about yet. I wanted the tank and the stack of guns to feel like they are barely holding together as they clank along moving forward on a bumpy road. What I ended up doing was giving a random small impulse to the tank and to a random gun in the stack every 0 – 2 secs. You can see those bumps in the video from yesterday.

Monday, March 1, 2010

Doodle Blast! - Day 2 - Collisions

Stats: 50 code files, 3871 lines of code, 2 textures, 11 sounds

Today, I introduced a simple set of “enemies”. I added a helicopter I copied from the original game sketch and I also added a building that I shamelessly stole from Pop Fizz, the Airplanes world. I introduced the concept of enemy hit points, simple collision detection, and continuous fire. The final game supports continuous fire for only a certain types of guns to make the game play more varied and to prevent players from just holding their fingers at the corners of the screen as they plow forward. However, at this stage, I made every gun (namely the two that I implemented) support continuous fire. This was partly because it was fun to feel the destructive power of the tank and partly to run a preliminary test to see how many objects I could throw on the screen before the frame rate began to suffer. So far, the code faired remarkably well. Even in the craziest of situations, Cocos2D was pulling at a solid 45 fps.

The frequency at which the enemies were spawning was controlled by a constant and it was the first time I started playing with how many enemies are fun to destroy vs. how many enemies are just too overwhelming. I showed the preliminary results to my brother, pointed him to the constant and let him play. His findings were that there was no such thing as too many enemies and he was rooting for the biggest mayhem on the screen he could get. I liked the idea of having a more leisurely play. To accommodate us both as players, I’ve started scheming for an enemy-spawning logic that adapts to the player’s style, lovingly referring to it as Skynet. But I’m getting ahead of myself because Skynet didn’t get to see the light of day until a couple of days later.

The most interesting part in today’s addition was the collision detection elimination. As I mentioned before, Chipmunk has a handy way of filtering out unnecessary collisions, thus decreasing the amount of computation and boosting perf. There are three tiers at which you can filter out collisions
  • Groups
  • Layers
  • Collision handlers
You can read all about these here. But the basic idea behind them is simple. Bodies within the same group do not collide with each other. Bodies that do not share at least one layer (layer being a bit in a bit mask) do not collide with each other. And finally, bodies for which there doesn’t exist a collision handler (defined by a function pointer for a bodyType-bodyType pair) do not collide with each other. Chipmunk creates a default collision handler that is a catch-all handler for all bodies that satisfy the group and layer requirements. This default handler handles all collisions that trickle down to it. In Doodle Blast, I’ve overridden this behavior such that no bodies collided by default unless there was an explicit collision handler defined. Then, I’ve split all objects within the game into groups and layers as follows:
Item Group Layer
Player guns 1 PLAYER
Friendly fire 2 ENEMY
Enemy fire 3 PLAYER
Enemies 4 ENEMY | PLAYER
Bonuses 5 BONUS
I’ve added a collision handler (using the same generic function pointer returning “yes, please, handle this collision”) for the following types of bodies:
Player <-> Enemy
Player <-> Enemy Fire
Enemy <-> Friendly Fire
Et voila! Now I knew about all the collisions I cared about without the overhead of calculating too much of anything else.

There was one more trick. I wanted the guns to stack neatly on top of each other. So, I gave each gun a stacking shape (essentially a rectangle), didn’t assign any group to it (meaning, they all collided with each other), placed them all into their own collision layer (meaning, they all collided with each other but nothing else), and added a generic StackingShape <-> StackingShape collision handler to deal with the guns bumping into each other.

That’s it. These assignments essentially gave me all of the game interactivity for free. Chipmunk was my friend.

I added a couple of more tweaks here and there (scores, bonuses, ...) and, at the end of the day, this was the result so far:

Sunday, February 28, 2010

Doodle Blast! - Day 1 - The Prototype

Stats: 38 code files, 2562 lines of code, 2 textures, 6 sounds

As I said earlier, day 1 consisted of me cheating because instead of spending the promised one day, I actually spent a weekend getting a running prototype together. I ended up borrowing code heavily from Pop Fizz. I didn’t have to re-implement asynchronous data load, animated particle systems, and persistent state storage. What I did end up writing was the basic structure of the game, a class to abstract out the tank guns, and a class to abstract out projectiles.

The big question I wanted to answer was whether to use a full-blown physics simulation or whether it would be sufficient to just fake it. All I really needed was a position, velocity, and acceleration vectors for every item on the screen and a full physics engine seemed like an overkill, not to mention a computational overhead. I also needed to solve collision detection. Simplified collision detention can be easy to implement, but I needed it to be fast. So, I sat down and started to write a spatial hash mechanism that would help me speed up the process. Half way through that effort I realized that I’m not being very smart because a physics engine would give me all of these things for free. I hence gave up and embraced Chipmunk all the way.

In the end, that ended up being a great decision. The final game uses Chipmunk not only to move things around the screen and detect collisions, but also to simulate bumps on the ground, stack guns on top of each other, and model the final explosion of the tank when the player dies. As far as overhead goes, it turns out that Chipmunk is pretty efficient at what it does. More importantly, version 5.0 came up with some really useful enhancements that allow you disregard unnecessary computations early on. In addition to breaking objects up into layers and groups, you can specify custom collision handlers that can have up to 4 callbacks through out each collision event:

  • Begin: Two shapes just started touching for the first time this step. Chipmunk has not yet calculated collision forces for this collision, and the preSolve() and postSolve() callbacks have not yet been called.
  • Pre Solve: Two shapes are touching. Some collision force computation has already taken place.
  • Post Solve: Two shapes are touching and their collision response has been processed.
  • Separate: Two shapes have just stopped touching for the first time this frame.
(adapted from Chipmunk docs)

For the most part, all I care about is the Begin event. It signifies that a bullet has hit an enemy or a player. I don’t actually care about the collision forces, so the calculation is pretty cheap and can stop right there.

The physics decision out of the way, I wrapped some sprites around Chipmunk bodies and this was the final result:

You will notice that I added a simple tutorial place-holder right from the start. My tendency is always to leave the tutorial until the very end at which point it’s a pain in the butt to stitch it into the game. So, with this project, I wanted to make sure that tutorial was built into the game from the get-go. The final tutorial ended up being pretty much identical to this one and having it there from the start saved me some head scratching later on.

You will also notice that the guns themselves are animated. That was a big part of the visual appeal for me, so I wanted to test that behavior right away. The initial gun logic was pretty straightforward – aim, shoot, and cool. As I will talk about in a later post, this implementation was too simplistic and I had to create a whole state machine to model each gun. But more on that later.

For now, this was as far as the two days have gotten me, but the results looked promising enough to keep going.

Doodle Blast! - The Idea

Shortly after I released Pop Fizz, I ended up being sick in bed with some flu. As I was lying there, I was thinking that it would be really fun to produce something else. However, at that point I wasn’t ready to invest two more months into something that would just disappear into the app void again. That just seemed like too long of a time to waste. A week, on the other hand, didn’t seem that long. So, the thought occurred to me – what can I crank out in seven days?

I chatted with my brother and we remembered our Sybila Soft days and the game with a tank and an ever-growing stack of guns. Then, just to prove his point, he sent me the following sketch:

I was sold. More importantly, I wanted to play that tank because it looked like fun. So, I was presented with a challenge: how can I turn that picture into a game in seven days or less?

The first thing I did was I cheated. I turned the first day into a weekend to create a simple prototype and test the feasibility of the idea. And that’s where we begin our daily count-down...

Pop Fizz is born!

Skip forward to last year, when I discovered that iPhone is actually a cool platform to code against and started playing with it. I ran across Cocos2D and Chipmunk as two independent, community-supported frameworks that made the job considerably easier. Cocos2D is a well-polished set of libraries that abstracts all the OpenGLES goo away from you and gives you a clean interface to manipulate 2D sprites (along with a whole bunch of other goodness). I worked with several other frameworks in the past and I must say I was very impressed and thankful for all the good work that went into it. Similarly, Chipmunk is a simple, but powerful physics engine that takes care of all the physics goo for you so, in the end, all you have to worry about is the game dynamic itself. Here is a big shout out to the Cocos2D and Chipmunk creators and contributors – thank you!

Back to the story, though. I was on a bus from Syracuse to Boston last November. For those of you who aren’t familiar with the route, let’s just say that the trip is a full-day joyride on sketchy inter-urban buses. Fortunately for me, Greyhound just upgraded their buses to have power plugs and WiFi onboard. The WiFi was nonexistent, but the power plugs worked (at least the one at my seat), which gave me whooping 8 hours of uninterrupted computer play during which I was trying to come up with a simple game for the iPhone. This is what I came up with:

A bunch of duplicate symbols on the screen – you match two identical symbols, they pop and disappear from the screen. Simple, but fun (or at least fun enough to make an 8-hour bus ride bearable). Following that trip, I spent two months turning that idea into a game, which eventually became Pop Fizz:

I managed to squeeze in quite a few features into the original idea – three different worlds with their own set of rules each, three different game types within each world giving you nine total game permutations, close to thirty achievements, InApp purchase integration, Twitter support, global leader boards, animated menus, ... you name it. In the end, I was very excited about the result. However, the game didn’t do particularly well. A lot of people downloaded the free version, but only a handful upgraded to the paid one, and eventually Pop Fizz got lost in the sea of other arcade games out there.

The good news was that I solved a lot of common problems (like writing a silly dialog box that allows the user to enter their name – I thought that would be an iPhone freebie, but no…) and I got quite comfortable with the platform and its tools (although there are days when I still curse Xcode’s auto-completion logic or the compiler’s ability to generate warnings but then hiding them from you and claiming success).

Saturday, February 27, 2010

Good ol' 80s

The idea for Doodle Blast! has been hatching around for at least two decades. In the 80s, I was growing up in Europe and, back then, Sinclair ZX Spectrum was the pinnacle of home computing as we knew it. It was a pretty cool black box. It came with 48k of RAM (which is less than the size of most icons these days), a built-in BASIC editor and interpreter, whooping 16 colors (only two of which could occupy any 8x8 pixel area), and a jack for a tape recorder that allowed you to store programs on audiotapes as 5mins of screechy noise. In short, it was daBomb! The best parts about it were that coding it was rather simple and that an independent person could sit down and create something that maxed out the capabilities of the machine. In short, it wasn’t very different from the iPhone today.

Back then, my brother and two of our friends decided to form a “company” (and I use that term very loosely) called Sybila Soft to write games for the Spectrum and distribute it to our friends. Friend-to-friend distribution was the modus operandi of the time and we were often surprised ourselves at how far our games travelled. The best part is that those games are still alive and floating around the Internet today, ready to be downloaded and replayed in some java-based Sinclair emulator running as a widget on your desktop.

Anyway, that was the first time we came up with the idea of a tank with an ever-growing tower of more and more obscure guns. However, we grew up out of our teens, moved on with our lives, and the idea never came to fruition.

The Making of Doodle Blast!

It’s two days after I published Doodle Blast! on iTunes. Originally, I thought about writing a day-to-day blog as I was writing the app, chronicling the process and some of the decisions that went into making it. However, what ended up happening is that I spent most of my time cranking out code, having little time for anything else. So, now that I have some time on my hands, I’m going to write a little post-mortem blog instead. I have saved daily snapshots of the code base, so I can re-create the progress and share it here with you.

Now, I’m not much of a blogger, so if I’m going too slow, too fast, or too dull, lemme know. I’m open to suggestions.