The Finish Line

Well it’s been a marathon that’s for sure.

Never in a million years did I imagine when I started this app process almost a YEAR ago that it’d take this long to reach the finish line.

But here I am. Finally.

This is a sight any developer is psyched to see:

uploading

It’s been a looong road. And I’m exhausted. Tomorrow the app launches all over the world. We’ll see what happens! Until then I’m gonna dream happy spider dreams and keep all my digits crossed. Here’s hoping.

readyforsale

Forever Alone

Zbrush is one of those software apps I absolutely love. I first encountered it wayyyy back in the early 2000’s or something at a WWDC SF. It was sorta new at the time but was doing crazy things with organic 3D sculpting no one had ever heard of. I was hooked.

It’s come a long way since then (although the interface is still as bizarre as ever). Over the years I’ve poked around in it and watched it develop. I don’t consider myself a master by any means, but as someone who loves design and 3D and now app development, it’s a tool that’s hard to ignore.

So recently I gave myself a learning challenge to dive in deeper. The challenge? Recreate the infamous rage comic “Forever Alone” as a 3D rendering.

Forever_Alone

His face is just perfect for modeling, wouldn’t you agree?

Here is the final result (click to enlarge). Stay tuned for a behind-the-scenes recap of how it was made!

Forever Alone

Spider Prank Feedback

I’d love to hear your thoughts on Spider Prank! Have ideas on how to make it better? Have you had some problems you want to report? Let me know in the comments and I promise to reply!

Also– do you have thoughts on what spider species I should work on next? Here’s a little poll to add your vote– but other ideas are welcome in the comments as well.

New Spiders
What new spider species should be added to Spider Prank?


Thanks so much for your feedback!

Sebastian

How Much Work in an Indie App?

As I near the end of this seven month development process, my thoughts turn to reflection. What a journey it’s been. I initially thought I’d create a fun ‘spider’ app for Halloween. I had this thought back in mid October of last year. I was working on a pretty involved game project at the time that seemed like it would take another five years to finish. So I thought why not take a break and throw together something quick?

My initial plan was to give myself ONE WEEK to see what I could pull off. I coded like crazy and even pulled an all-nighter. I was super close to having something actually publishable.

But I ended up missing Halloween by a day or so. At that point I decided there was no longer any rush. Why not tinker with it and make it perfect?

I went from a cheesy 2D sprite spider to a fully rendered 3D spider equipped with a rudimentary artificial intelligence. I spruced up the interface considerably and added a lot of bells and whistles including localization in twelve languages.

Suffice to say it’s no longer October. What I thought could take a week instead took basically an entire a year.

Now to be totally fair, I work full time as a Motion Graphics artist, so it’s not like I could work every second on this app. I’d sneak in coding time where I could on nights and weekends. But it was still quite a slog.

So how much work did I actually do?

I use to-do lists to help me stay sane with my projects. My favorite list app is Wunderlist. It’s great cuz it synchs through the cloud over my phone, desktop, ipad etc.

Anyhoo, here’s a screengrab of my Wunderlist list for my app. Each checkmark represents a stage of the development process. Some items took me an hour, some took me over a week. Moreover, I wasn’t totally committed to list-keeping… so I’d say maybe 50% of the work I didn’t even bother listing. I use lists to help me stay organized– not to punish myself in some sort of OCD ritual.

Here’s the list! Whew. Quite a lot of checkmarks for such a simple little app. And you’ll notice that it’s not finished either. Any day now I hope! Of course, that’s what I was saying seven months ago.

todolist

REJECTION – part 1

Okay– so what is every developer’s worst nightmare? Finishing a long, arduous development process only to get your app REJECTED by Apple! That’s exactly what happened to me.
rejection01
Owtch!

Hopefully Apple won’t mind if I share a few of the details just so others may learn to avoid my mistakes.

The whole point of my app was to allow users to prank their friends by putting a ‘real’ spider on their phone. To this end, I added a bunch of device screenshots to the app that simulated an ios desktop. Apparently this is a no-no.

rejection02

So according to bylaw 8.3 (which I had not read), it’s against Apple’s rules to ‘simulate an ios behavior’. Including still screenshots of ios backdrops qualified and my app was rejected.

Should I have seen this coming? I suppose so. I was caught with my pants down, that’s for sure. I thought I’d seen apps that had done this sort of thing before… ie simulated stuff that appeared to be on your actual device.

Like this one:
Volt

Or this one:
Shake Break Make

But after digging deeper I started to uncover some others who had run into the same roadblock. Specifically, I found this great post from all the way back in 2009. Some guy wanted to simulate an iphone screen like I did. And he paid the price.

I love the evolution of his app design which illustrates his harrowing rejection process (image from www.mani.de):

rejection and iteration

So how come apps like Watchdog and my app got rejected, and other apps like Volt and Shake Break Make made it past Apple’s watchful eye?

It’s well documented that sometimes Apple’s review process is a little random. Get a cranky reviewer on the wrong day and you’re just out of luck (although I can’t blame the overworked review team). But my hunch is that the real difference is that in the apps that made it through, desktop imagery did not ship with the app. Users were instructed to take a screenshot to add as a background… something that should, in theory, be entirely legal.

The problem for me, however, is that without a screenshot shipped with the app to greet the user right away, a lot of the punch of the main concept of having a spider on your phone is deflated.

As a developer, my first reaction was to drink a lot of whiskey. I’d just spent a solid six months working on a project that would never see the light of day. FAIL. It was a brutal disappointment.

BUT, after taking some time to wallow, I picked myself up, dusted myself off, and asked the question that developers MUST ask after app store rejection:

HOW DO I SAVE THIS?

After all, I appealed Apple’s decision and they wrote this:

rejection03

Granted, it seems like a boilerplate, form letter response, but it was still encouraging.

“We hope you will consider revising the app to address the issue…”

Apple WANTED my app– they just needed me to fix it. And all-in-all I think in retrospect it was a pretty fair process. Upon reflection I understood that it made little sense for them to allow apps in their store that made it seem like their devices were busted or inoperable.

So HOW DO I SAVE THIS?

Challenge accepted.

Stay tuned for part 2 where I’ll fill you in on the solution I came up with.

Dumb Coding Mistakes #632

Okay here’s a good one that had me stumped all afternoon.

I must say that as far as collections go, I’m used to using arrays. Arrays are great cuz they’re typed, they’re fast, and they’re relatively easy to set up and iterate through. The problem is they’re not dynamic. So it’s tough to quickly add and delete stuff from an array on the fly.

Enter the List. Lists are typed like arrays, but they are dynamic– meaning you can just add stuff to your List and the list grows. If you zap something from your list the list shrinks.

This is very useful for saving. In my app, users can add photos to use as backgrounds that they either take themselves or pick from their camera roll. Saving this data is great for a List. I don’t know how many different photos they will add over the course of the app’s life on their device and I don’t care. Save and delete your photos as you wish! They’ll all be stored in a List.

The dumb coding mistake is as follows.

In startup, I need to load these photos. So I iterate through the List. I also check to see if there are problems. If there is missing data or null data I simply throw up my hands and zap the thing from the List. Something went wrong, I’m destroying it. The user can import it again if need be. This isn’t like someone’s bank account.

So it goes something like this:

// ON LOAD

for (int i = 0; i < listOfBackgrounds.Count; i++) { if (listOfBackgrounds[i].IsScrewedUp()) { // list item is messed up or corrupted! // zap it! listOfBackgrounds.RemoveAt(i); } else { // everything is fine! load the background listOfBackgrounds[i].LoadBg(); } } Simple enough, right? We loop through all the items in the list. If we detect an error we zap the offending object and remove it from the list. If it's fine, we load it. ERROR! NULL REFERENCE EXCEPTION! Do you spot the mistake? It had my tearing my hair out for quite a while. Having been used to working with arrays instead of Lists, I overlooked an important quality of Lists. They are dynamic. Most of the time this is great. It allows you to add and drop stuff on the fly. But the problem with that, is the List is always CHANGING! Take the following array: myArray = new string[] {A, B, C, D}; It stores four strings. A is in index 0. B is in index 1. C is in index 2. D is in index 3. (both arrays and lists start counting their indexes at 0 -- itself the source of many dumb coding errors) If we DELETED the B at index 1, what would the value of index 3 be? Index 3 would still be D. Index 1 would have a null since we zapped the B. But I would still know what was in index 3 (and all the other indexes for that matter). A LIST on the other hand, continues to resort itself. So for a similar list with values of A,B,C,D in indexes 0,1,2,3... What would be the value at index 3 if we removed the value at index 1? It would be NULL! If we remove the value at index 1-- ie if we remove the B-- then the ENTIRE LIST changes to become: A,C,D in indexes of 0,1,2 Index 3 does not exist anymore! Everything shifts over. And thus my dumb coding mistake. I was iterating through a LIST while removing things from the list. So the list was CHANGING as I was trying to access it. The solution? Store the indexes I wanted to zap in a SEPARATE LIST which I then looped through AFTER the main for loop. After iterating through the main list and storing the numbers, only then was it safe to zap stuff from the original list and feel confident I knew what I was zapping. Even then, I had to loop through the separate list BACKWARDS. Removing index 5 wouldn't have any effect on indexes 0,1,2,3,4. So as long as I removed indexes from highest index to lowest index, even though the List was dynamically shifting, it wouldn't screw everything up. Another brainteaser for the books. I've learned that the only way through this stuff is banging your head against the keyboard until your stupidity gives up and leaves you alone.

Evolution of an Icon

Icon design is tough business. It’s gotta look good at full size, but it also has to scale down and look good when it’s just a tiny icon on your device.

Here’s my first stab at the icon for Spider Prank. It was back when I had a purple interface.


Actually I think this looks pretty good. But the purple interface wasn’t working for me. So back to the drawing board.

Here’s version #2:


I was trying to match the silver, sleek interface I’d settled on. But I think I missed the mark with this icon. The silhouette looks pretty boring. Plus the uniform legs make a visual mess when shrunk down.

A challenge I had was I wanted the icon to be really dark and menacing. But the spider was black. Hard to make black show up on black. I wondered what would happen if I tried the spider inversed. Version #3:

I kinda liked that version. But ultimately I decided that I need to showcase the hero– the spider itself in all of its 3D glory. That’s the main selling point of the app, so I figured I needed to at least feature it prominently in the icon. Version #4:

I was pretty happy with this. Decided it just need a little levels adjustment to make it pop more. So I added more contrast, and voila, version #5:

I think this one’s a keeper. But who knows? I’ll have to sit with it a little and play with it on my device(s) to see if it really does the trick. Also it’ll be important to get some feedback from testers. Almost to beta testing! Yeehaw!

Dumb Coding Mistakes #1

It’s easy to make dumb mistakes when you’re coding. Like here’s one I always make.

Say I have a slider for the interface with a knob in the middle you can slide back and forth. I need to check the position of the knob to see if it has moved left or right.

So I’m always tempted to do:


void CheckSliderPos() {
if (myKnob.transform.localposition.x > 5f) {
// do some stuff cuz the knob x pos is greater than 5 now
} else if (myKnob.transform.localposition.x < 3f) { // do some stuff cuz the knob x pos is less than 3 now } }

So what's wrong with this? Usually, NOTHING! And that's the problem. Usually this sort of check is just fine. But what if there are more things to check? What if there is a whole list of if thens. And then what if the user slides the knob REALLY FAST?

Well, in this case there is the rare possibility that the user SLIDES THE SLIDER faster than the machine can compute the code. And this leads to ugly bugs.

So imagine this:


void CheckSliderPos() {
// THE FIRST CHECK OF THE SLIDER
if (myKnob.transform.localposition.x > 5f) {
// do some stuff cuz the knob x pos is greater than 5 now

// AND NOW PRETEND THERE A BUNCH OF OTHER LOGIC CHECKS...
// } else if { (etc)
// } else if { (etc)
// } else if { (etc)

// AND PRETEND THE USER SLID THE KNOB REALLY FAST...
// Do you see the problem?

// PROBLEM!!!!
// BY THIS POINT, the knob position may very likely have changed significantly from
// where it was when we checked at the top.
} else if (myKnob.transform.localposition.x < 3f) { // do some stuff cuz the knob x pos is less than 3 now } }

This can quickly lead to whacky results.

The proper way to do it, of course, is to STORE the knob position immediately as a constant... and use the same constant to check against all the logic.

Like so:


void CheckSliderPos() {

// STORE THE POSITION so we can compare against a CONSTANT position
float knobXPos = myKnob.transform.localposition.x;

// THEN check your logic and you'll be fine.
if (knobXPos > 5f) {
// etc
} else if (knobXPos < 3f) { // etc } }

This is such an easy and basic mistake, but I find myself making it all the time. A great example, I think, of how there are little tricky pitfalls in coding that can surprise you if you're not carefully thinking everything through.

Localization

korean

Is this amazing or what? Thanks to the very simple and easy to use localization plugin for Unity3d, I can localize the text in my app at the click of a button.

localization

It’s all automated through google docs– including the translations. Here are some blurbs from my app in French, Spanish, German, Chinese, Russian, Japanese, Korean and Thai– the list goes on and on.

spider prank in korean

Spider Prank in Korean

I love living in the future. (PS– anyone know how to say ‘swipes’ in Korean??)

Procedural Logo

In my latest app, I came up with what I thought was a cool look for the logo. I created the following in After Effects. My initial thought was to render out the still frames and have them run in the app as an animated sprite:


However, rendering out all the frames led to over 200mb or so of raw assets. Granted, this number would drop after combining onto sprite sheets and compressing, but it was still far too much bandwith for a simple logo. Moreover, I’m not a fan of the aesthetics of compressed still imagery. I needed a different solution.

sprite sheet

A handful of the 90 odd images that would have gone into a sprite sheet for the animation.

I created a single god ray sprite in Photoshop (seen here).
godray

I also created two logo sprites (one normal, one glowing). So instead of 90 images, I was down to 3. In Unity3D, I duplicated the god rays several times and added a Box Collider to each one. Then I wrote a godray script. The script told each god ray object to fade up and scale depending on its relative intersection with a trigger object. I also gave each ray a little wiggle. Finally I told the glowing logo to fade up when it intersected with the trigger to boost the overall glow effect.

The last step was to write a simple script to make the trigger object move back and forth over the logo. Because it’s procedural, I got the added benefit of being able to randomize the speed and the direction of the trigger from pass to pass. Here you can see the trigger object (the longer box) and the god ray objects at work in Unity3D:


And the final result below. Since the three sprites fit on the same sprite sheet, this version of the animated logo only takes a single draw call and costs 322 KB (uncompressed).

Not quite as pretty as the original After Effects version, but worth the extra work to get the size down. Now users won’t have to wait an extra several minutes for a heavy sprite logo to download. Instead this streamlined version should load fairly instantly.