Showing posts with label Cocos2D. Show all posts
Showing posts with label Cocos2D. Show all posts

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).

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

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).