Archive for the ‘Marketing’ Category
Dapple 1.3.1 – Sale! $0.99!
Friday, September 18th, 2009
Dapple 1.3.1 was just approved and I’m putting it on sale for $0.99! The changes take a few hours to take effect, but they should be in the app store soon.
- Dapple (iTunes Link)
Owen
Dapple 1.2 Now Available! (SALE!)
Sunday, June 14th, 2009
I’m currently on vacation in San Francisco after attending WWDC, but Apple approved Dapple 1.2 today, so I thought I’d better post! Yes, Dapple 1.2 is now available on the App Store! If you already have a version of the game, just update to get the latest version free. If you haven’t bought it before, I’ve put the game on sale for $0.99 in the U.S. (and at corresponding prices around the world) for 7 days! There’s never been a better time to get Dapple, if you haven’t bought it already!
Here are the details:
Dapple 1.2 now features a Global High Scores list! Track your own personal best scores, or submit your best scores to see how they compare to other players from around the world. The leaderboards track your highest scores in both Classic and Timed modes. See the top scores in the world, as well as the people ranked immediately above you.
Dapple 1.2 is also the first game as a part of the new App Treasures label to include the new App Treasures Web View. Players can view information on all other App Treasures games right from inside Dapple.
So go check it out if you’re interested!
- Dapple (iTunes link)
Owen
App Treasures Unveiled!
Thursday, June 4th, 2009
I have some exciting news to share: the secret project I’ve been involved with for several months was unveiled today!
- App Treasures (www.apptreasures.com)
Here’s a bit from the official press release:
Five independent iPhone game developers announced today the creation of the App Treasures label: A collection of top-quality, indie games for the iPhone and iPod Touch.
The App Treasures label is a seal of quality that consumers can trust, and will help users find hidden gems in the App Store. When someone plays an App Treasures game and they like it, chances are they will also like the other games available from the label.
Developers releasing games under the App Treasures label are carefully considered and hand-picked to ensure maximum quality.
The App Treasures members are:
- The Blimp Pilots (Koi Pond, Distant Shore)
- Imangi Studios (Imangi, Word Squares, Little Red Sled)
- Snappy Touch (Flower Garden)
- Streaming Colour Studios (Dapple)
- Veiled Games (Up There, Payday Roulette)
You can find the full press release on the App Treasures website, if you want to read the whole thing.
We’ve been working on getting this project up and running for months, so it’s fantastic to see it finally launch. We’re starting to see some press about it today. I’ll post some links once we’ve got a few more stories to share.
One of the really exciting things we’re doing is allowing players to browse other App Treasures games from inside our games. The Dapple 1.2 update contains a new feature that lets you browse the other App Treasures games, read about them, and then buy them. Other App Treasures games will be rolling this feature out over the coming weeks as well.
We hope you enjoy it, and we hope that it helps you to find some fun games that you didn’t already know about.
If you want to follow updates on App Treasures, follow our new Twitter account where we’ll be posting news stories and any news we have: @AppTreasures
Owen
Dapple 1.2 and NSString Leaks
Wednesday, May 27th, 2009
Dapple 1.2
I haven’t been posting very frequently lately, mostly because I’ve been working very hard to get this Dapple 1.2 update out the door. I’m thrilled to announced that I submitted it this afternoon! Dapple and Dapple Lite 1.2 were both submitted today. If everything goes according to plan, they should be available around this time next week.
The update is quite exciting, in that it adds support for global high scores lists! Now you can see how your top score compares to other people around the world! With the update you’ll be able to see your score and the 9 people ranked directly above you, or look at the top overall scores. It’s already been exciting watching the testers’ scores roll in. I can’t wait to see how everyone does!
Dapple Lite also allows you to submit your scores online, but you’ll be using the same scoreboards as those with the full version. If you want to get near the top of the scoreboards, you’ll have to buy the full version. 😉
There are also a few user interface tweaks that I’ve made and also a few little fixes. Finally, there’s also a feature for a top secret project I’ve been involved in. You’ll have to wait for the update to find out what it is!
Leaderboards
Now I want to talk a little bit about the technology that I used for the high scores lists and then talk about a nasty memory leak I tracked down today before submitting. If you’re not interested in this kind of thing, I’ll forgive you if you want to stop reading now…
When I started thinking about implementing the leaderboards, I first looked a few existing technologies, hoping that I might be able to just “drop something in” and it would work. There are a few technologies out there that looked like the might be able to do that. Where they fell short, however, was in my ability to completely customize how I wanted to store the data and display it. Plus, I thought it would be fun to write my own system.
When I started reading up on the Google App Engine, I was convinced it would be easy to set up a server back-end using that, and I was right. Using the App Engine, I had the server-side working in about 3 days of work (and that included learning Python and how the App Engine works). It’s really easy to get things running with their system.
What took time, as usual, was the user interface. I had considered creating an in-game web view that would load a web page that had the high scores on it, but I decided (perhaps somewhat foolishly) that I didn’t want the player to have to leave the look and feel of the game. I decided to build it using my existing UI framework. This only caused a few problems, mostly around trying to find space to fit all the data. However, I also ran into some nasty string memory stuff in the code I wrote to parse the data coming from the server.
I encountered a memory leak this morning that I want to share with you, because it’s not immediately obvious why it’s a leak. When I get my data from the server, it comes in as a long string of data. I use NSString’s handy methods to chop it up and stuff the results into a dictionary, then I shove those dictionaries into a big array. Here’s a bit of the code that had the mem leak:
NSArray* recordData = [[records objectAtIndex:i]
componentsSeparatedByString:@","];
NSString* username =[[NSString alloc] initWithString:
[recordData objectAtIndex:0]];
...
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
[dict setObject:username forKey:@"name"];
...
[mCachedGlobalHighScores addObject:dict];
[username release];
This causes a memory leak that is caused at first line of code. I was baffled by what was causing this. The memory leak seemed to be happening on the string inside [recordData objectAtIndex:0] but I couldn’t figure out why. I asked around on Twitter and many people pointed me to the method [myObj retainCount] that allows you to see how many retains have been made on an object. BunnyHero pointed out that you can run this from the GDB command prompt when stopped at a breakpoint: ‘print (int)[myObj retainCount]’.
I set breakpoints on the line where username is allocated, and on the line after. When execution halted just before username was allocated, I checked the retain count on the object at index 0. It was 1. This was expected. However, right after username was allocated, it became 2! Why was allocating a new string using initWithString (which is supposed to copy the string and create a new object altogether) increasing the ref count?!
I think it had something to do with the fact that the NSArray is storing the values as type id, not NSString. When you do an initWithString, I think it was just copying the pointer, and doing a retain, so the new object allocated memory, but pointed to the same object. So, in order to fix that, I had to do this instead:
NSArray* recordData = [[records objectAtIndex:i]
componentsSeparatedByString:@","];
NSString* username =[[NSString alloc] initWithFormat:@"%@",
[recordData objectAtIndex:0]];
Now the memory leak no longer happened when recordData was created…it happened when username was created! But that’s ok, now at least the leak is happening at a more reasonable place.
So now I looked at where I was cleaning up my big array of cached data:
[mCachedGlobalHighScores removeAllObjects];
Reading the docs, removeAllObjects is supposed to call release on each removed object. I assumed that would do a deep release. Not the case. So I tried this instead:
for (int i = 0; i < [mCachedGlobalHighScores count]; i++)
{
NSMutableDictionary* record =
[mCachedGlobalHighScores objectAtIndex:i];
[record removeAllObjects];
}
[mCachedGlobalHighScores removeAllObjects];
But that still didn’t work. The username string wasn’t been released! So finally, I did this:
for (int i = 0; i < [mCachedGlobalHighScores count]; i++)
{
NSMutableDictionary* record =
[mCachedGlobalHighScores objectAtIndex:i];
NSString* name = [record objectForKey:@"name"];
[name release];
[record removeAllObjects];
}
[mCachedGlobalHighScores removeAllObjects];
And it works! You might be asking why I didn’t do an autorelease on the username NSString. I tried that. It worked most of the time. But if you flipped back and forth on the screen quickly (causing everything to delete and recreate quickly), I found that I could get into situations where sometimes that string wouldn’t release at all, causing a leak. I decided that if I managed the memory myself, at least I’d know what’s going on.
So, the lessons are:
1) If you are dealing with a string that’s stored as type id, make sure you’re careful about how you use it to init new strings.
2) When you alloc (or retain) you have to release. (Yes, I know that should be obvious by now, but sometimes you think a built-in method is releasing or retaining when it isn’t). 🙂
Well, apparently I’ve decided to make up for a lack of posts with one gigantic post. Look for more news on the Dapple 1.2 update when it gets approved. And keep your eyes and ears open for news on that secret project I may or may not have mentioned…
Owen





