Monday, November 21, 2011

Game Art for the Artistically Challenged (Part 2)

Hello again, this is Ken Vadella blogging for Five Lakes Studio, LLC (FLS).

In my last article on the subject of Game Art I discussed the FLS strategy for acquiring artwork for our iOS projects. A reader of this posting (plicatibu) provided, what looks to be, a very valuable website for hiring artists to produce custom artwork at reasonable prices - thanks plicatibu. The site is called oDesk and though we have not tried to use it as of yet we plan to give it a shot in the near future. Check it out.

This month I would like to discuss the editing tools we use to turn our art findings into usable game components. Let me start with a small sidebar discussing how we choose tools for our efforts. The following list summarizes our evaluation technique. The list is in order of importance.

Costs
We don't want to spend an arm and a leg for image editing tools.

Features
A text editor with a limited feature set isn't very useful to us. Here are some of the items we look for in our image editing tools:
  • File Format Support - PNG, JPG, etc.
  • Layers - No layers, no tool. It's really that simple for us. We love layers for image editing and find it nearly impossible to live without this feature.
  • History - No undo/redo, why bother. See above.
  • Effects - Blurs, distortion, noise, embossing, etc.
Simplicity
What is simple to some is difficult for others. Tod and I are not new to image editing but we are also far from experts; this is not a task that we do everyday so we look for easy to use tools.

Availability
A product that runs on multiple platforms is a plus but not a show-stopper. We have access to many brands of computers that run many different operating systems. If a tool meets our other criteria then we won't rule it out just because it doesn't work on a Mac OS.

The Gold Standard
For us Adobe Photoshop CS5 is the gold standard of image editing but it does not fit the shoe string budget of a startup company like FLS. Don't get me wrong, if we didn't have alternatives we would pay the money and acquire copies of CS5. But, we do have alternatives that suit our needs very well and cost significantly less money to acquire.

The List
Without further ado, let's move to that list. These are the tools that we use for our image editing tasks. This list is arranged in order of preference as it relates to FLS.

My preferred application for image editing. This may be sacrilegious to some because it does not run on a Mac OS. But, as I mentioned above, we have access to many brands of computers running many different operating systems and this tool has a lot of positive attributes:
  • It's very easy to use.
  • It performs well.
  • It's very stable - we can't remember the last time it crashed.
  • It fits all of the criteria cited above with the exception of Availability.
  • It is 100% free. Yes, free.
Tod's preferred editor and for those on Mac OS. It exhibits many of the positives cited above for Paint.NET. Some other positive things that can be said about Pixelmator include:
  • Reasonable pricing. It's not free but you won't need to do much more than skip a restaurant dinner with your significant other to save enough money to buy a copy.
  • It performs well - it's fast; really fast.
  • It reads native Adobe Photoshop files relatively well - Paint.NET does not do this.
But it comes with some minuses as well:
  • It lacks basic drawing tools. This seems like a major oversight. I have heard that newer versions of Pixelmator will support drawing tools.
  • It lacks that ease of use inherent to Paint.NET. It's not difficult to use, but it isn't as easy to use as Paint.NET.
Still, it is a wonderful editor for the money.

Pixlr is an oddity in this list. It's not a product that you put on your machine and run. Rather, it runs in the context of a web browser. It works surprisingly well and is very full-featured. But, the whole edit-in-browser experience feels, somehow, too crammed for space and for this reason we tend to use it less than the other editors mentioned above. Still, it's free, cross-platform and powerful. What more could you really ask for?

The GIMP
You can say many positive things about GIMP:
  • It is very powerful.
  • It's free. Yes, free.
  • It's cross-platofrm.
It's everything that Paint.NET is and more. And yet, we don't use it that often. We use it less than any other editor in this article. Why? Because it's lacking in simplicity and user-friendliness. At least, we feel this way about it. Maybe we are just not that bright. Give it a try though, you might find otherwise.

Snagit
We also use Snagit to take screenshots and do basic image editing to help communicate with our customers and each other.  Snagit gets heavily used for support, it's so much easier and clearer sending a picture then a bunch of text.  Snagit does a great job of taking screenshots of the iOS simulator, saving and tagging them, and allowing awesome markup.  It is affordable and works on both Mac and PC.  I should say that Tod works at TechSmith the makers of Snagit.

Final Comments
That's it for this Blog entry. I hope you find one or more of these editors to your liking.

In a future Blog entry I will discuss some additional tools that we use to make our art assets even better. I'd also be interested in what image editors you use in your development efforts. It never hurts to evaluate new products recommended by others.

Thanks for reading.

Ken


PS (7/28/2016): One thing that was missing from this review was some web based photo editors.

One of the folks over at Canva asked that give them a shout out.  They have a basic free photo editor at https://photo-editor.canva.com and their full product is at https://www.canva.com.  Ken and I haven't used it yet in a real project yet, but it might be worth checking out.  Leave some feedback and let us know if you tried it out and if you liked it or not.

- Tod

Monday, November 7, 2011

Integrating Social Media - Epic Fail

I plan on returning to my multi-part series on creating a Star Rating System in a future post. This week, I wanted to take a small side detour and talk about how Ken and I have tried to integrate social media into our games.   Or perhaps I should say, how we have failed at it miserably.  I'm hoping someone will share some words of wisdom as there must be something fundamentally wrong with our approach thus far.


iOS 5 Twitter

With iOS5 Twitter integration, I thought it would be great to add twitter to Kento.  I created a little twitter helper class based on the iDevBlogADay article by Tony Ngo.  The class source is just two files and is available for download.

I added a twitter button to two places within Kento: on the main screen and when you solve a puzzle.

On the main screen, there is a tweet button that pre-fills in the number of tokens the player has won and a link to Kento.





When the player solves a puzzle, we place a tweet button in the upper left corner that pre-fills in some nice information about the puzzle along with a picture.














The version with twitter was released about two weeks ago and we have over 17,000 updates/downloads.  Can you guess how many times I have seen #KentoApp tweeted or received a tweet to @fivelakesstudio from Kento?  The answer is .......... ZERO, if you don't count my test ones.






A Previous Attempt

We tried integrating facebook into #Lost in Space with the same result: ZERO usage.  People just don't click on the facebook icon.



We show a little icon and some game text when the player tries to share their score through Facebook.




Conclusion

The puzzle star rating system we added continues to get great usage, but we have totally failed at engaging other types of social media such as Facebook or Twitter within our games.  We have also tried things such as HeyZap which has had better results then Facebook or Twitter, but it still doesn't have the level of engagement and usage we would like to see.  Has anybody had better luck at integrating social platforms?  I'm thinking that slapping a button in a UI just isn't the right way to do this type of social integration.

Thanks,
Tod






Sunday, November 6, 2011

UIAlert with Blocks

I wish Apple would make a version of UIAlert with blocks.  I have seen a fair number of simple examples on how to do this, but I have been unhappy with most of them.  Most use Categories on UIAlert, and I would rather not do that especially when the alert handler is also involved.

This very simple implementation uses a separate class to implement a UIAlert.  Here is how you use it:
    
TCAlert *alert = [[TCAlert alloc] initWithTitle:@"Reset Puzzles" 
                                        message:@"Reset ALL puzzles in this puzzle pack?"
                              cancelButtonTitle:@"Cancel" 
                              otherButtonTitles:@"Yes", nil];
   
[alert showAlertWithCompletionBlock:^(int buttonIndex)
                                    {
                                        NSLog( @"Hello I got it %d", buttonIndex );
                                        [alert release];
                                    }];
It is important that the alert object stay retained through the life of the Alert, but that is easy to do by releasing it in the block.  The block will retain the alert!  If the system closes the alert the completion block will be called with a buttonIndex of -1 (kAlertViewCanceled).

The code is just a small source and header file.  Please feel free to download it and let me know what you think.  I haven't switched over to ARC yet, so I'm not sure what would need to be changed to support ARC.  It would be great if someone would like to do that.

Thanks,
- Tod





Monday, October 24, 2011

Star Rating System - Part 1: Google App Engine

We have been looking for ways for our users to share their experiences playing our games.  We tried things like Game Center, HeyZay, twitter, facebook, and prompting for people to rate the app on the AppStore with moderate success.

One day, I had this "inspiration" to allow people to easily rate individual puzzles and share those ratings.  I was currently working on Kento: A Distorted Jigsaw, so I decided to just do it.

This is a very simple star rating system that allows puzzles to be rated from 1 to 5 stars.  That information is sent to a server where it is combined with other people's ratings.  The server keeps track of the total of each puzzle's rating along with the number of users who rated it.  With this information, an average can be caclulated.


I broke the idea up into 3 parts:
  1. Server to collect and share ratings (Google App Engine)
  2. iOS API to access the server
  3. iOS User Interface
This first article is going to focus on writing a simple web service with Google App Engine.  I'm not going to go into how to create the full web service.  There are lots of good examples on the App Engine site that will show how to do that.  Instead, I will focus on some of the tools and tips I've learned doing this project mostly around how to deal with the datastore and transactions.

Tools

I'm just using a free GoogleAppEngine account.  You can download a developer environment for either PC or Mac.  It also supports either Java or Python.  I really haven't done much with Python, so I decided to use Python as a good learning experience.

In the past, I have tried just using a plain text editor for python which is such a throw back to the 80s.  This time, I remembered my car pool buddy, Chris, talking about an IDE for Python called PyCharm by JetBrains.

While not my favorite IDE, PyCharm has support for GoogleAppEngine development.  This includes code completion and a DEBUGGER.  This was a huge timesaver given my limited Python skills.  Make sure you checkout their quick start guide for google app engine.  Also make sure you run the GoogleAppEngineLauncher downloaded from google before trying to setup PyCharm.  You don't need it running while using PyCharm, but the launcher will finish the GoogleAppEngine install and setup symlinks on your system needed by PyCharm.


Datastore

You can configure your app to use either the High Replication Datastore (HRD) or the master/slave datastore.  I wanted to keep the application as cheap as possible, and this application doesn't require rock solid availability.  If the service goes down for maintenance for a short period of time, the end users won't notice or care.  This made the master/slave option the ideal choice.
The Master/Slave datastore uses a master-slave replication system, which asynchronously replicates data as you write it to a physical data center. Since only one data center is the master for writing at any given time, this option offers strong consistency for all reads and queries, at the cost of periods of temporary unavailability during data center issues or planned downtime. This option also offers the lowest storage and CPU costs for storing data. 
You should also be aware that the App Engine datastore's are not SQL databases.


Entity Group

One of the tricky things with Master/Slave transactions is that a transaction can't cross entity groups.  In other words, each table involved in the transaction must be part of the same entity group.  Well, that leads to an interesting question of how to put tables into the same entity group.

I made sure that the tables involved in the transaction had the same parent (they where siblings).  That was enough to put them into the same entity group.


Transaction Errors

If a transaction fails, any changes will be rolled back.  However, just because a transaction throws an exception doesn't mean it has failed.
If your app receives an exception when submitting a transaction, it does not always mean that the transaction failed. You can receiveTimeoutTransactionFailedError, or InternalError exceptions in cases where transactions have been committed and eventually will be applied successfully. Whenever possible, make your datastore transactions idempotent so that if you repeat a transaction, the end result will be the same.
When writing this service, it was important that if you run the same transaction twice the "right" thing will happen.  This means that we need to keep the average data accurate even if the same rating is applied multiple times.


The Tables
I used 3 datastore tables for this project.

The AppPuzzleDB table is used to represent each puzzle in a game.  Since I want to be able to use this for multiple games there is a gameId unique to each game.  I also tend to package groups of puzzles together so there is a packageId to represent a grouping of puzzles.  Finally, there is a puzzleId itself which uniquely identifies a single puzzle.
class AppPuzzleDB (db.Model):
    gameId    = db.StringProperty(indexed=True)
    packageId = db.StringProperty(indexed=True)
    puzzleId  = db.StringProperty(indexed=True)
The server itself doesn't calculate the average.  It just holds the data necessary to calculate an average.  The RatingAverage table keeps the current running total and number of ratings (count) for each AppPuzzleDB.
class AppPuzzleRatingAverageDB (db.Model):
    gameId          = db.StringProperty(indexed=True)
    packageId       = db.StringProperty(indexed=True)
    puzzleId        = db.StringProperty(indexed=True)
    puzzleItem      = db.ReferenceProperty(AppPuzzleDB)
    ratingCount     = db.IntegerProperty()
    ratingTotal     = db.FloatProperty()
I know it is a waste of storage and bad design to repeat the gameId, packageId, and puzzleId within this table.  However, doing so reduces the number of quires I have to perform and it just makes it easier to access this information.  I know poor excuses, but I get to be lazy sometimes!

The last table, AppPuzzleRatingDB, is the individual ratings supplied by each user.  We keep this data around for awhile so that if the user re-rates the puzzle we can back out their old rating and apply their new rating.
class AppPuzzleRatingDB (db.Model):
    puzzleRatingAverage = db.ReferenceProperty(AppPuzzleRatingAverageDB)
    userId              = db.StringProperty(indexed=True)
    rating              = db.FloatProperty()
    dateCreated         = db.DateTimeProperty(auto_now_add=True)
This design allows for really fast retrieval of the current averages, we don't need to do a bunch of lookups and summations.  It also allows us to purge the individual user ratings in the event we need to free up space.  In addition, this is what allows us to handle the same request being sent multiple times to the server.  We use this table to back out any old values before applying the new ones.


Making keys

In order to do fast lookups of the tables, I used custom keys. For example, the follow code snibbit creates a key for the AppPuzzleDB table:
def appPuzzleKey(gameId, packageId, puzzleId):
    keyName = "puzzle(" + gameId + "_" + packageId + "_" + puzzleId + ")"
    return db.Key.from_path( "AppPuzzleDB", keyName, parent=None )
It gets a bit more interesting for the child tables. You can see below that the AppPuzzleRatingAverageDB uses the puzzle key to refer back to its parent.
def appPuzzleRatingAverageKey(puzzleKey):
    keyName = "puzzleRatingAverage(" + puzzleKey.name() + ")"
    return db.Key.from_path( "AppPuzzleRatingAverageDB", keyName, parent=puzzleKey )
Finally, the AppPuzzleRatingDB also has to take into account a userId as each user can have their own rating per puzzle.
def appPuzzleRatingKey(puzzleKey, userId):
    keyName = "puzzleRating(" + userId + "_" + puzzleKey.name() + ")"
    return db.Key.from_path( "AppPuzzleRatingDB", keyName, parent=puzzleKey )

Running a Transaction

In order to run a transaction, just call run_in_transaction with a function reference.  For example:
puzzleItem = db.run_in_transaction( transactionGetAppPuzzleDBItem, gameId, packageId, puzzleId )
As a convention we prefix transactionGetAppPuzzleDBItem with the name transaction to indicate that we call this function in the context of a transaction.  We do this in a transaction so that when we create a new AppPuzzleDB entry, we can also create a corresponding AppPuzzleRatingAverageDB that is initialized correctly and ready to go for when we add items.
def transactionGetAppPuzzleDBItem(gameId, packageId, puzzleId):
    puzzleKey  = appPuzzleKey( gameId, packageId, puzzleId )
    puzzleItem = AppPuzzleDB.get( puzzleKey )

    if puzzleItem is None:
        puzzleItem = AppPuzzleDB( key_name=puzzleKey.name(),
                                  parent=None,
                                  gameId=gameId,
                                  packageId=packageId,
                                  puzzleId=puzzleId )
        puzzleItem.put()

        # Create a new AppPuzzleRatingAverageDB to go along with the puzzleItem
        puzzleRatingAverageKey  = appPuzzleRatingAverageKey( puzzleItem.key() )
        puzzleRatingAverageItem = AppPuzzleRatingAverageDB( key_name = puzzleRatingAverageKey.name(),
                                                            parent = puzzleItem.key(),
                                                            gameId = gameId,
                                                            packageId = packageId,
                                                            puzzleId = puzzleId,
                                                            puzzleItem=puzzleItem,
                                                            ratingCount = 0,
                                                            ratingTotal = 0.0 )
        puzzleRatingAverageItem.put()

    return puzzleItem

Optimization

The rating system had been live for a short awhile, and we got featured again by FreeAppMagic.  This time we ended up being number #1 in our category on the UK store.  We got a big influx of downloads and users.  Checking the status showed that we had reached 70% usage of our cpu allocation.


The server was using a Django template to form XML to send back to the client, and it was doing this every time a client asked for the average data.  Fortunately, the client was written to only ask for this information once a day.  However, even with that it was taking a good amount of CPU time to do this work.

To decrease CPU usage, we modified the server to cache the generated xml in a memcache that expires every 6 hours.  That way we can use the cached value without having to regenerate the xml.
class AppPuzzleRatingAveragePackageXML(webapp.RequestHandler):
    def get(self):
        gameId    = self.request.get('gameId')
        packageId = self.request.get('packageId')

        # See if we already have the XML document cached
        # If we do, this should save a ton of CPU time as we won't have to keep regenerating the XML document
        xmlRatingKey = appPuzzleRatingAverageXMLMemCacheKeyName( gameId, packageId )
        xmlRating = memcache.get( xmlRatingKey )

        # If not, then we need to generate a new one
        if xmlRating is None:
            puzzleRatingAverageQuery = db.GqlQuery( "SELECT * FROM AppPuzzleRatingAverageDB where gameId = :1 and packageId = :2", gameId, packageId )

            template_values = {
                'gameId' : gameId,
                'packageId' : packageId,
                'puzzleRatingAverageQuery' : puzzleRatingAverageQuery,
                }

            oneHour = 3600     # 60 * 60 = 3600
            path = os.path.join(os.path.dirname(__file__), "AppPuzzleRatingAveragePackage.xml" )
            xmlRating = template.render(path, template_values)
            memcache.add(key=xmlRatingKey, value=xmlRating, time=oneHour*6)

        self.response.headers["Content-Type"] = "text/xml"
        self.response.out.write( xmlRating )

This did have a significant effect on the overall CPU usage.




Wrap Up

It took about a day to get this implemented on the server side, and we have had over 4,000 ratings in just a few weeks.  Do you think a service like this is worthwhile?  Also be sure to check out Kento and our other iOS apps.

Thanks,
Tod

Tuesday, October 11, 2011

Rafflecopter

We are trying out a new service called Rafflecopter.  It's in beta, but it is a web service that helps you manage giveaways.   It seems like a really cool idea, so what better way to test it then do a giveaway.  I will share with you the results, and hopefully get enough people to signup to giveaway a few copies of Euchre HD.  Give it a try and signup, you may need to click see more and wait a couple seconds for Rafflecopter to show up.  Also feel free to head over to www.fivelakesstudio.com to see all our games.

Monday, October 10, 2011

Game Art for the Artistically Challenged (Part 1)

My name is Ken Vadella. By way of introduction I can tell you, with reasonable confidence, that my development skills are better than average. But I have a confession to make: I am artistically challenged. There, I've said it. At this point you may be thinking to yourself "Ken, when you say 'artistically challenged', what exactly do you mean"?

Allow me to explain. If there were a gameshow called "Is Your Artwork Better than a Fifth Grader", and I were a contestant, I have serious doubts that I could win.

Yet, despite my artistic deficiencies, I often play the role of "artist" for the software that we produce at Five Lakes Studios (FLS) - in addition to my coding duties of course. Necessity dictates that someone must fill this role and, apparently, I lost the dice roll. Our lack of art genes, as you might imagine, creates an interesting challenge for the FLS team:
  1. We create games for Apple mobile devices.
  2. Games, for such devices, are expected to exhibit artwork that is "Better than a Fifth Grader".
Maybe you know a group or an individual with similar issues? It's OK, get it off your chest, admit it: you may also be artistically challenged. Admitting you have a problem is the first step to recovery. Now that we are being honest with each other, how do we go about treating the problem?

Although I seriously doubt that we can cure the artistic deficiencies on the FLS team, we have developed a strategy to cope with our lack of talent. Our strategy did not come to us overnight. If you will indulge me for a moment I'd like to tell you where we started from and where we are today. The intent of this indulgence is to allow others to learn from our mistakes. The hope is that a retelling of the events will save others from walking the same perilous path. Let's begin.

In the beginning there was a strong-willed, experienced group of long-time developers with an idea to create great games for Apple mobile devices. The developers were veterans of the software wars with many languages and platforms trailing in the wake of their keystrokes. Objective-C and the Xcode environment were merely new hills to climb and conquer; and conquest did come quickly. But then came a revelation: The team had cool ideas and great coders, but lacked the aforementioned "artistic talents".

So they sought artists to aid in their campaign. And artists they did find. But they found something else as well. The artists they found lacked something inherent in the FLS development staff: motivation to work on an idea that might not produce a single dime of revenue. Essentially, they lacked faith in the idea - despite its greatness. To overcome this lack of faith, the team at FLS offered "cash for art" and an agreement was forged.

But, an evil even greater than lack of faith consumed our artists: lack of time. The agreement did not provide our artists with hordes of riches and so their ability to find motivation to complete FLS artwork was, shall we say, lacking. Deadlines came, dealines went. Lots of code was written, and lots of art was left uncrafted. And as time passed the development crew found it difficult to continue to make progress.

Knowing that artists are not inherently lazy, but understanding the evil which is "lack of time", we could very much relate to their lack of motivation. As a side note, if you are lucky enough to have dedicated artists on your team with faith in your ideas then we hate you as we are not so fortunate. (hehe)  Back to our story...

So, the crew of Five Lakes Studio learned some valuable lessons from this engagement that I will summarize briefly below:
  1. Time is valuable to everyone, even artists. Don't get offended, that's a joke. Lighten up art guys.
  2. Creation of artwork is time-consuming, hence valuable.
  3. Motivating moonlighting artists is not easy on a small budget. The value of their art is certainly greater than a budget capable of feeding a goldfish once or twice a week.
  4. Lack of artwork can kill an otherwise interesting, graphics-oriented game.
  5. Without faith or adequate motivation, our out-sourced art was doomed to remain in the ether, our of reach of our yearning projects.
So, how do you we about getting the artwork we needed to complete our gaming projects on a tiny budget?

The answer is really quite simple: we find it on the web. Panning for artwork on the internet is a hit and miss prospect. It's very likely that you will not find exactly what you were originally looking for. But, if you search with an open-mind and allow for changes to your original design then you may be pleasantly surprised with your findings.

The team at FLS has used this technique to successfully launch and monetize a number of games that we would call "successful". With success being measured as producing more income then we thought they might at this point in time. Nothing to write home about mind you, and no reason to quit the day job, but the proceeds and fun certainly keep us motivated to continue enhancing our current applications and producing additional applications as well.

So where do we search for quality artwork on the web? Follow the links below and start panning for artistic gold.
  1. Dreamstime - Our goto site. Most artistic panning starts here. The number of images available (photography and illustrations) is truly impressive. The images are not always cheap, but they aren't really expensive either.  We have noticed that prices here seem to be going up.
  2. morgueFile - A huge collection of public images.
  3. Clker.com - A great collection of public domain clip art.
  4. WPClipart.com - Kid friendly, public domain artwork and photos.
  5. PDClipart.org - No-frills public domain clipart.
  6. 25 Free Stock Photo Sites (article by Digital Image Magazine)
Not all of the images on these sites are free, in fact many are not, but the purchase terms for images are usually very reasonable - much more reasonable then having custom artwork rendered specifically for you. And the selection is really quite large: videos, photos, rendered images, sprite sheets, icons, etc. Dive in and see what you can find. Like I said, you might be pleasantly surprised.

We have used images from these sites for many FLS games including: Picross HD, Kento, Lost, Zombie Rush, and Juxtaprose. We would like to think that these applications do exhibit artwork that is "Better than a Fifth Grader".

I hope you enjoyed this article. In a future BLOG entry I will discuss the editing tools we use to turn our findings into usable game components. I'd also be interested in game art sites that you have found valuable.

I know that your time is valuable, thanks for using some of it to read this BLOG entry.  We would love to hear how you handle the artwork on your projects.

Note from Tod:  I love artists.

Sunday, September 25, 2011

Kento an Adventure

This is my first posting for iDevBlogADay, and I'm trying to figure out what would make a good first post.  I enjoy reading stories of how other people's apps are doing and what they are trying.  So I figured that was a good place to start.  I hope you find my story interesting...

Kento is Five Lakes Studio's 6th iOS app, but it is our first original game title.  It's a little scary releasing a unique unknown title.  So the very first decision we made was to get something to market quickly to learn if we had a good idea or a stinker.

Ken did most of the initial work on Kento, and he spent about 3 months working nights and weekends.  I came in during the last month to help do some final UI and polish, but given there are only two of us and we both have day jobs we where really happy getting the first release ready that quickly.

1.0 Ships: What will happen?

Release 1.0 shipped on May 4th.  We only had about 18 puzzles and our idea was to give Kento away for free to gather feedback.  We had a great launch with over 1,000 downloads the first day.  We didn't do any press or marketing, we just let the AppStore do what it does.

Assuming people actually downloaded the app, we where expecting to get hammered for not having enough puzzles.  When we did something similar for one of our other games called Picross HD, we got hammered with 1 and 2 star ratings by people saying we didn't have enough puzzles.  This time, people did ask for more puzzles but they were actually giving us 5 star reviews!

In usual fashion for the AppStore when we fell off the main page for our category, our downloads dropped rapidly.  And after a few more days the downloads started to drop off again.  However, we had the data we needed.  We liked Kento and it looked like others did as well.  Kento was a keeper, and we needed to get started on the next version.

Even though we where building the next version, I wasn't done with the experiment.  I decided to take the price to 99 cents, and you can guess what happened.  The sales hit the floor hard, but that's what an experiment is for.


This told us that we really needed to make the base application free, but we still wanted to monetize the title.  We haven't had much success with the ad model in the past, thus the next obvious answer was to do in-app purchases.

1.1: Rise of in-app purchases

We hadn't done in-app purchases for "real" before so we started coding.  It took us about two months to get 1.1 developed and in the market.  It included over 100 additional puzzles, the ability to import your own pictures and turn them into puzzles, and 2 in app purchases:
  • $1.99 for 100 puzzles
  • $1.99 for Photo gallery import (allows users to turn an unlimited number of their photos into Kento Puzzles)
While we where building the new features, our downloads dropped off significantly.  I started to doubt that we could really gain traction on our own game title.  So I made Kento Free on June 28th.   This gave us really good results with over 2000 downloads in the first day, eventually leading to a steady state of about 50 downloads a day.  My doubts were greatly reduced!


During this period of time, we continued to get great reviews and feedback.  We ended up a solid 5 star rating for awhile.  That was some nice motivation leading up to our 1.1 release on July 28th.

The in app purchases where generating modest revenue.  The App was free, and we where making about $45 a week on Kento through in-app purchases.

Another experiment we wanted to conduct was to see if people would prefer buying picture puzzles made by us or if they wanted to use their own photos.  We got a fair number of user requests for the latter.   Turns out picture puzzles (green), made by us, sell much better than user's photos (light blue).


1.2 Some small tweaks and a bit of luck

We quickly followed up 1.1 with a 1.2 release to fix a couple of issues.  In particular, we didn't display the prices of the in-app purchases within the App's UI thus our user's couldn't see what they were buying.  Oops!!!

We got a little lucky when we released 1.2, we were contacted by FreeAppMagic.  They liked our App and offered to feature Kento for free.  WOOT!!!  And I must say they did a great job.  We shot up within the top 50 in our category for a few days.   That's the nice sales spike in September.

1.3 Now

We have had over 25,000 downloads of Kento, and last week we just released 1.3.  So far it's doing well.  It's still too early to tell what will happen with the changes we made:
  • Added 2 different 50 picture puzzle packs $1.99 each
  • Added 1 new 100 picture puzzle pack $2.99
  • New store interface, allows users to preview the puzzle pack before purchasing
  • Changed name to "Kento: A Distorted Jigsaw"
  • Increased the price of the 1.1 puzzle packs by $1.00.
We wanted to test if 50 piece puzzle packs would sell better then 100 piece puzzle packs.  So far the 100 puzzle packs are outselling the 50 piece packs.

We got a good amount of people upgrading who decided to buy the 1.1 version's 100 piece puzzle pack when they upgraded to version 1.3.  We think this is because we updated our in-app store and added the ability to preview the puzzle packs before purchasing.

We read an article by Tim Cascio about naming an App and taking advantage of keywords in the App's name on the AppStore.  Names will be read/seen be people scanning though apps and hopefully draw their interest.  So we tried that with this release.  Too early to tell what effect that will have or if we did a good job on the new name.

1.4 Future: The next big plans for Kento

We are working with A2A3 of Ann Arbor in the fight against Lou Gehrig’s disease.  Six women are going to be swimming the English Channel in July 2012.  We are donating our time to make a special version of Kento that will promote the event and hopefully help with collecting donations.  

We are working on a project called Kento:Live that will allow puzzles to be downloaded from the web.  We would like to work with photo studios, local government municipalities, or anyone who would like to promote their work/community with a mobile app.

We will of course continue to enhance Kento with more puzzle packs and cool stuff like the ability to rate puzzles.  We are working on a halloween pack now that will be free as a thank you to all our customers.  I have to get back to work on that...

Thank You

Wow if you made it this far, I want to say thank you and I hope you enjoyed the journey.  I invite you to try out any of our games at www.fivelakesstudio.com, and be sure to give Kento a try.  Also please let us know what you think of this post or any of our games.  You can follow me on Twitter at @fivelakesstudio or send me an e-mail at tcunning@fivelakesstudio.com.

The adventure is just beginning.
- Tod and Ken

Friday, September 23, 2011

Hello from Tod

Hello,

I'm Tod Cunningham living a little north and east of Ann Arbor Michigan in the little town of New Hudson.  I've been writing software for many many years and just love it.  My first computer was a vic-20 and I have been hooked ever since.  That was a long long time ago, and now I have been working in the software business for about 19 years. 


During the day, I am the Director of Development for TechSmith's desktop products group building Camtasia, Snagit, and Morae.  I'm so lucky that I get to work for such a great company with great people.


At night, I am co-founder of Five Lakes Studio.  Ken and I started Five Lakes Studio last year to build iOS apps.  Of course, we quickly got sucked into building games, and then decided to focus on casual family friendly games.  It's been a great year learning about iOS and how to build and market mobile apps.  We love it.  We still have lots to learn. 


Feel free to contact us on twitter @fivelakesstudio or our website www.fivelakesstudio.com.  Also we love hearing from you, so please feel free to comment on our posts or feel free to send e-mail to tcunning@fivelakesstudio.com