New Omegapixel Upgrades & More

We are currently developing our next title, but we are also working on another Omegapixel update. In addition to bug fixes and other small improvements, we are going to add a new upgrade to the mix. I have a number of ideas floating around in my head, but I want your feedback. Please vote in the poll below and help us decide which direction to go in.

If you have any upgrade ideas or other thoughts you want to share for future Omegapixel updates (more missons, game modes, etc), please leave a comment. Thanks!

Truly Universal

In a previous post I discussed the approach that I used to make a Universal app for iPhone and iPad. That approached circumvented some problems others were having on the iPad 3 with cocos2d. Even though apps continued to run properly on the iPad 3 with that approach, we were not taking full advantage of the extra pixels.

The first thing we need to do is generate new high res assets. I am going to skip that step for now and assume you have higher resolution assets. Add the suffix "-hdpad" to the end of your high res assets or pick your own suffix and adjust the code below accordingly.

Next we need to define our Retina iPad suffix in ccConfig.h:

Then we need to edit CCFileUtils to make sure we use the "-hdpad" suffix when a Retina iPad is running our Universal app:

You will notice in the above code we are checking for the Retina iPad by checking to see if the content scale factor is equal to 4. If we load "-hd" assets and scale the points by 2 on the iPad, then we will need to double that for the Retina iPad.

We also need to update the utility function that cleans up the hd suffix:

Next we need to modify our enableRetinaDisplay flow we outlined in the previous post to enable Retina on the iPad 3.

The first thing we do is create a new enableRetinaDisplay:onPad method so we can choose not to enable the Retina Display on the iPad 3 if we don't have the assets to support it:

You will notice that the old enableRetinaDisplay method calls the new method but passes a default value of FALSE. This will keep our app working as is until we have our "-hdpad" assets ready.

The next step is to modify the content scale we will pass to setContentScaleFactor. Remember that we want to end up with a content scale factor of 4.

Notice that if we are not supporting the Retina iPad, then we set the scale exactly as we did before. If we are supporting the Retina iPad, then we set the new scale equal to the scale times the point scale factor which is set to 2 in makeUniversal. Hey Maw, look at my handy chart:

Next we have to take care of the line that saved us from having Retina iPad headaches in the first place:

Referencing out handy chart, you will see that __ccPointScaleFactor is not one. This means that __ccContentScaleFactor is ignored and we use one instead. We need to generalize this line so that it still works under the old case, but will also handle the new scenario:

Now we will still end up with a scaleFactor of 1 on the non-Retina iPad and on the Retina iPad if we did not enable Retina iPad mode. If Retina iPad mode was enabled, then we end up with a scale factor of 2 which enables retina mode on the device.

Here are all the changes to CCDirectorIOS.m in one handy gist:

Now you have a universal app that supports the full resolution of the iPad 3.

Asset Addendum

Preparing your asset pipeline to fit into the hd, hdpad, sd world will take a bit of work. If you have vector or pixel art, then your job is easier but no one wants to export every asset three times. Some of the common tools like Texture Packer will likely build in support for this in the future. In the interim you can probably get by with a few command line scripts.

Caveat: The modifications in this post were done to cocos2d 0.99.5. There are minor differences between the supplied code and the changes you should make to cocos2d 1.1.

Caveat Emptor: You aren't actually buying anything but use at your own risk anyway. There will likely be tweaks and adjustments to this code in the future.

Note: If you are building a stand alone iPad version, then I recommend you use the latest updates in the develop branch for cocos2d 1.1. They have already added Retina iPad support. This code provides a simple way to create a Universal app.

Recommendation: If you haven't had them before, I recommend you go buy some tomatillos and try them on your next taco in place of tomato. Prepare yourself for a surprising and unique flavor.

Hey Cocos2d Noob - A Letter To Past Me: Part 3

If you missed them, catch Part 1 here, and Part 2 here.

Wow, it's been a long time. I shouldn't have left you. Without a new post to review. I was sucked into a new project that started off as a Ludum Dare Jam and then turned into a full game (check it out after you read this). I learned a lot going through the process and I recommend a game jam for any aspiring game dev. Unfortunately, adding a new project into the mix meant the next installment of this series was delayed. Time to dig back into my archive of horrible mistakes...

Filename@2x.png

When the retina display came out Apple gave us a simple way to automagically load retina assets instead of "SD" assets. Adding "@2x" to the retina version of the asset solved all our woes.

When I first came to cocos2d I was already in the habit of adding "@2x" to all of my retina assets, so I continued to do so. This is not the recommended naming convention for cocos2d because Apple's special handling of the "@2x" images can cause subtle bugs when interacting with cocos2d. Instead we should add "-hd" to all retina display images. Do this from the start and avoid having to unleash your command-line-fu to rename all your images. It is amazing how many issues can be avoided by just reading the documentation.

Another bonus of the "-hd" suffix is that it works for other asset types such as plists, fonts, and TMX files. If you need to load different assets for retina than for sd, then just slap an "-hd" on the end of the retina version.

Ticking Away The Moments

Within the main game loop a monster lies in wait. It will devour noob game developers indiscriminately. It doesn't matter if you are using cocos2d, another framework, or no framework at all. This monster's name: Time.

A very important thing to recognize is that not every step through the game loop will take the same amount of time. This is especially true as you move from one device for another.

A Story: You have carefully tweaked your monster speed to charge at your player at a rate of 10.698 units per update. The time through your update loops are variable, but you haven't caught on because they are always similar enough for the effect to go unnoticed. Now you load the game on your friend's shiny new iPhone 5 with it's awesomely powerful processor. Holy badunks! You can no longer react fast enough to escape the monsters! This game is impossible!

Since you used a fixed delta per game loop iteration and since the faster device can iterate more times per second, you have ended up with a game that no longer works as intended on a faster device. Don't feel too bad about it, many older games built for a specific platform suffer the same fate when run on newer hardware.

Luckily, this is an easy to solve problem if you address it from the start. Take the delta into account with each update and you will avoid this problem entirely. If you have a step method that looks like this:

-(void) step: (ccTime) delta;

Multiply the time delta by a velocity to determine the positional delta.

If you are using a physics system like chipmunk, then the delta should be passed into the step method (cpSpaceStep). The physics engine will then take care of all of the grunt work for you, but you still need to be careful with anything you update from outside the physics system.

Aside: There are two ways that physics engines can be updated, fixed step or variable step. There are pros and cons to each approach. Engines will facilitate one or both approaches. A good starting place to learn more is this thread on gamedev.stackexchange.

Shuffling

The last tip of the day comes in the form of some FREE code. The internet is just full of this stuff! (Always check the attached licenses) Odds are you will eventually need to shuffle the elements of an array. An easy way to do this is to create a category for NSMutableArray. This will give you a highly reusable piece of code, and then you won't have to write new shuffling code everywhere you need to randomize array elements.

A discussion on shuffling an NSMutable array using a category can be found over on StackOverflow. I have included my own slightly modified version below for ease of Copy-Paste.

52616e646f6d; 52616e646f6d

If you want to randomize an array the first time you generate it, and then want to be able to regenerate that same sequence again in the future then you can make a few modifications to the code above (or add a new method).

Replace:

int n = (arc4random() % nElements) + i;

With:

int n = (rand() % nElements) + i;

Then before calling shuffle, call srand() and pass in your saved seed value.

// Our first play of Taco Madness

srand(423452345);

[tacos shuffle];

// resulting order => beef, chicken, fish, pork, brain

 

// Replaying Taco Madness later using the same seed

srand(423452345);

[tacos shuffle];

// resulting order => beef, chicken, fish, pork, brain

// same results as first run

 

// Starting a new game of Taco Madness and therefore using a new seed

srand(76864432);

[tacos shuffle];

// resulting order => pork, chicken, brain, fish, beef

// new results due to new seed

This will guarantee that shuffling will return the same result as the last time you shuffled the same array with the same seed. They call them pseudo-random for reason.

Next Time

In the next installment I am going to go through an entirely new class of errors related to process of releasing a game on the App Store. It will be chock full of mistakes you will absolutely want to avoid.

Editor's Notes:

  1. Glad to see that tacos were used in an example. I was beginning to grow worried.
  2. A video of the Melbourne Shuffle… really?
  3. I am imaginary.
  4. Speaking of tacos:

Four Hats Teaser

We've been working like around the clock like numbers one through twelve and are now wrapping up production on the full version of The Four Hats. Here is a little teaser:

The Four Hats was originally our Ludum Dare 22 Jam entry. We enjoyed playing our little creation so much, that we decided to turn it into a fully fledged game. We will be posting a gameplay trailer soon, more artwork, and details on taking a game from a 72 hour jam entry to a full game.

We will also be releasing a free version of the app, which will be the same as our LD entry plus some extra free goodness thrown in.

For now enjoy the screen shots:

Why We Have File Size Problems

When working on any type of project there are always trade offs to be considered. One that we ran into early on was art quality and quantity versus file size. When developing for the iPhone it is best to stay under 20 MB so that users don't have to be connected to WIFI to purchase your game. When developing a sprite based game it is easy to run up against that wall very quickly.

Steve hadn't been forced to deal with the painful realities of the nitty gritty details of how computers work before, so when we bumped up against the size limit it led to some initial frustration. Steve yelled, "Why are there crazy 3d games on the iPhone, but we are running into trouble with simple 2d sprites?" as he threw excrement at me from his banana tree.

It was a fair question. Unfortunately to appreciate the answer a bit of technical knowledge was needed. What follows is the email I sent to Steve explaining images (with some parts edited/redacted). Those familiar with the technical details will spot a few exaggerations, oversimplifications, inaccuracies, and bends in the space time continuum. This isn't meant for you. If however you are working with someone on a project and they want to know why they can't have hundreds of 2048x2048 pixel 32bit images, then send them this.

----

From: Chief Tacology Officer (I make them)

To: Co-Consumer of Tacos (He eats them)

Date: Back When We Started This Thing

Subject: Why We Have File Size Problems

I figured an explanation of the problem we have might help.

IMAGES:

Images are basically a big map of what color is at what pixel. So if I had a 4x4 pixel image. The data for the image would look like this:

red red red red

red red red red

red red red red

red red red red

Since computers are dumb, and we have an insane number of colors (16777216), that actually looks more like:

16711680 16711680 16711680 16711680

16711680 16711680 16711680 16711680

16711680 16711680 16711680 16711680

16711680 16711680 16711680 16711680

16711680 is the numeric representation of the brightest red. The problem gets even worse since we have to take into account the fact that all of these colors come in various levels of transparency (bringing us to a whopping 4,294,967,296 colors):

4294901760 4294901760 4294901760 4294901760

4294901760 4294901760 4294901760 4294901760

4294901760 4294901760 4294901760 4294901760

4294901760 4294901760 4294901760 4294901760

This is for a 4x4 pixel image. Many of our images are several thousand pixels in each direction. I am pretty sure my email would explode if I tried to demonstrate.

Now so far we are talking about numbers and have avoided how that relates to image size. Well each one of those colored pixels is 4 bytes. If we saved images in the simplest of ways, then we could get image size by multiplying height and width and then multiplying the product by 4.

4x4x4 = 64 bytes!!!!

2048x2048x4 = 16,777,216 bytes = 16,384 KB = 16 MB !! Holy Crap!

There is good new, there is bad news, and there is some more semi-bad news.

GOOD NEWS:

Lots of smart people have spent years figuring out really intelligent ways to store the same amount of information in less space. If the same color appears in many many places in the same image there are ways to use less room than the naive way I first showed you. It is even better if there is a lot of the same color next to each other. A very simplified explanation follows:

4 x 4294901760

4 x 4294901760

4 x 4294901760

4 x 4294901760

Basically the above structure says, repeat this color for the next 4 pixels. It would use approximately 20 bytes instead of 64 bytes. If we express the bounds of the image first we can do even better.

4 x 4

16 x 4294901760

This would use around 7 bytes. FYI, this isn't even close to the actual method they use, but it demonstrates that there are ways to express the same image with less data. If you want to jump of the deep end, read about DEFLATE (ah that's the good stuff).

BAD NEWS:

These methods work best with big blocks of solid color, but they start to fall apart on gradients or more complex textures. They still make the image much much smaller than the worst case scenario, but they aren't even close to the best case scenario. This is why the textured version is 10 times the size as the clean version.

MORE SEMI-BAD NEWS:

No matter what tricks are used to store the files on disk, when the phone actually displays the images it cannot use the compressed version. This means that it reads the compressed version off of the iPhone's hard drive and as it loads it into memory it decompresses the image. The nice small imaginary 7 byte image that we managed to create returns to it's 64 byte size in memory. That 2048x2048 image becomes 16MB in memory (RAM). Ouch!

COLORS:

This giant amount of memory usage is why we are forced to use fewer colors during gameplay. In some instances we have multiple 2048x2048 images moving around. That is a huge problem on devices with limited amounts of memory aka iPhones.

The 4 bytes that each pixel takes up is because we want to use the full range of color. If we use a reduced color set than we can use 2 bytes per pixel. This effectively halves the amount of memory we use and prevents the iPhone from having a mental breakdown. Black and white graphics anyone?

BUT HOW COME 3D GAMES HAVE AWESOME GRAPHICS AND DON'T TAKE UP MILLIONS OF TERABYTES?!?!?!

3D games don't store images of everything in the game. If they did, they most certainly would take up millions of terabytes. They would not only need an image of a tree, but an image of a tree from every angle that it could be viewed from, every lighting condition it could be under, every frame of animation of its branches blowing in the wind. The tree would take up more space than our entire game.

Instead, 3D games store a few small images and instructions on how to draw bigger images based on them:

drawTriangle <insert triangle position> 

paintWith <some shade of green>

textureWith <some file with a tree texture, some algorithm that does magic>

This looks more like code because it is (well sort of). 3D modeling programs can output a few different things:

Images - a single viewpoint of an object, follows the same rules of size as any other images

Video - a series of images

3d Data Files - a bunch of rules (code) that another program can read to draw the output of the modeling program

3d games read the 3d data file to draw the images themselves. This greatly increases the complexity of the code and the amount of CPU used to do the calculations, but it makes it possible to draw amazing things without using absurd amounts of disk space.

A COMPARISON:

I don't think the above explanation does an adequate job at demonstrating just how much space you save by giving instructions to the program to draw, rather than saving the images. So I think it is better to compare the size of the instructions (code) and images in REDACTED GAME REFERENCE, to a full resolution video.

Code & Images < 12MB

34 Second Video = 72MB

Given that the video is only one particular path the game could have taken, and there are near enough to an infinite number of possible images that that one play could generate, I think it is fair to say that by programming rather than generating images for every possibility we saved several terabytes of space.

THIS ISN'T FAIR!

Nope it sure isn't. We have sacrificed size and freedom for simplicity. It is easy for us to build a sprite based game using tools that you are familiar with. This also allowed us to build an awesome game in less than the N+ years it takes to build a serious 3d title (and they have much larger teams). We have some limitations, but we will get to make something awesome in a short amount of time.

A POSSIBLE ALTERNATIVE:

We are currently saving everything as images, which as I explained above takes up a lot of space. It would be awesome if we could save instructions for the iPhone to draw things smartly instead. Luckily for us, the clean look facilitates that (Editor's Note: What clean look? You have to wait and see). Some nice guys invented something called SVG (Scalable Vector Graphics). I believe Flash can export things to SVG (Editor's Note: Apparently I was wrong). SVG is not a list of pixels, it is a list of instructions.

There is no built in way to make the iPhone follow the list of instructions inside of an SVG, but I could write code that will read an SVG and tell the iPhone what to do. It will take time, possibly a few weeks, maybe a month. If I do it, we would save an absolutely absurd amount of space. We could have REDACTED and add in REDACTED and eat millions of tacos!

CONCLUSION:

Images take up lots of room. 3D uses magic. SVG might be our savior. (Editors Note: Turns out reading SWF directly was.)

**** Almost everything in here is oversimplified to the point of not being 100% accurate (because there are a million if/thens and contingencies, etc, etc), but I would rather work on our game than write a technical document. ****

----

Editor's Notes:

It's been awhile since I wrote the above and in the interim I have found code that will help reading SWF files directly (Steve has worked mostly inside of Flash for this project). It doesn't support everything we need, but it is open source so I am updating it so that it does. There is a decent chunk of work ahead to bring the level of support up to where we want it, but it looks like we will be getting around this road block soon.

Introductions - Steve

Hello, I’m Steve Emond, and I figure now’s a good time to introduce myself here as the other half of Taco Graveyard. Sal makes the tacos, I eat the tacos.

A little about myself, I’m a writer and artist, first published as the creator of the indie comic book series EMO BOY through SLG Publishing, later as the author of HAPPYFACE through Little, Brown Books For Young Readers, and my second book WINTER TOWN is coming out this week.

So with this burgeoning career as an author, what am I doing in this odd vaguely taco-related game design project? Well, the easy answer is I love video games, and why wouldn’t I want to make one? Sal and I knew each other for a good year or so before deciding with his programming chops and my artistic acumen we could team up and try to make something. Of course that’s never easy for me to do, as I can make stuff on my own, and do - and I’m pretty busy doing it. In fact I was trying to put together a third book when the idea of making an iPhone game came up. For me, it was an interesting idea and my head filled up with thoughts pretty quickly, but I didn’t take it too seriously at first. I’ve tried a lot of times to collaborate with people, but most of them time I end up doing all the work, or the other person drops out fast, not realizing you actually have to WORK to make things. So I told Sal I’d toss some ideas around with him over tacos and figured that would be that. We had a few interesting thoughts, and I said I’d draw him a couple things he could play around with.

Lo and behold, almost immediately he had my art moving around and interacting with things on an iPhone. I know, that’s how it works, but somehow I didn’t expect it to work, or if it did, I thought it would take a really long time. Seeing it come to fruition was exciting. One idea led to another, and before you know it, months are going by and Sal is working faster than me and my editor is asking me “What’s this about a game? Where’s your next book?”

So now I’m trying to juggle things. I’m working on this game and trying my best to keep up with Sal. I’m trying to learn exactly how to animate a game. I’m trying to get that third book going when I get the time. I’m still working a day job. Now my book WINTER TOWN is out and I’m starting promotion for that. So as you could probably guess, I’m having a tiring but awesome time. Making books, and video games! If I could only tell my 13-year old self what was coming up!