Apple just gave me a little over 500 bucks for a month of Hearts Net sales. That seems pretty good to me. Plenty good enough to keep maintaining it. It appears that the iPad version of the program has boosted sales a bit.
So, I’ll be working on new features and more devious player robots in the future. Might not be for awhile, because I recently started a new full-time job which is taking most of my time. But the game is still very much on the list of my current projects.
A new version of Hearts Solo is available today. This one has all the latest stuff I’ve added to Hearts Net, including the theme selection feature, and native iPad support.
You still can’t play a game all the way through, though. This app is just a no-cost way to preview the features available in Hearts Net.
Well! I am as surprised as anyone that I have managed to jump through Apple’s series of fiery hoops and get the iPad version of my game into the App Store. And it’s still two days before normal humans will be able to get their hands on actual iPads. This version runs on iPhones and iPod Touch devices as well.
I’ve made yet another attempt to fix the two big bugs people have been reporting, and I have reason to believe I actually got them this time. So, everybody upgrade, and let me know how it works out.
Pretty soon I’ll be releasing a new version of Hearts Solo that is also iPad-capable. It still won’t let you get all the way through a game though, sorry. It’s just for demonstration purposes.
One thing I’ve learned about my hardcore players: you guys love the games played and games won counters. I thought it was a silly trifle when I added that feature, but many people consider it indispensable. Some people report they’ve played many hundreds of games, which they know due to the counters, of course. One person told me he uses a calculator to compute his win/loss ratio. So I suppose it’s not surprising that some of those same people are upset when the counters are off.
For reasons I still don’t fully understand, some players have reported that the game counts don’t always update correctly. I’m told the numbers are sometimes smaller than they should be. I haven’t been able to get a good handle on this, because the people experiencing the problem tend to be less technical, and aren’t able to give very detailed feedback. But I’ve finally found a player who was willing to perform a lengthy and involved experiment, and I’m pretty sure I’ve got it nailed down.
I asked this person to exit the program back to the home screen at the end of every game. After doing this for several days, he says that this does indeed fix the problem for him. So in the next version of the program, I’ll make it save its game counts at the end of every game, so you won’t have to do it manually. In the meantime, if the game counts are really important to you, you can do what this person did, and exit the program at the end of every game.
I’d like to say I’ll submit a new version of Hearts Net to the store right away, but I’m super busy working on the iPad version right now. Soon, though.
I am still getting a fair number of reports for two particular bugs, but nobody seems to want to get involved enough to help solve them. If you can, please take five minutes and help me fix these things.
Here’s the first one. Some people say they are still getting the “stuck robot” problem. This is when you’re playing Hearts Net and it’s all working fine, then it’s time for one of the robots to play a card, but it doesn’t. Nothing happens, the game is stuck. You can exit the game to the home screen and come back, and it’s still stuck.
I’ve gotten maybe ten reports of this bug in the last week or two. I’ve told those people the “simple” fix, and urged them to help me with the harder fix, but nobody has ever written back! I am positive I could fix this if just one person would send me her game state, so I could use it to analyze the problem. Surely one of you is willing to help?
Here’s how you do that. Play the game until it gets “stuck,” and the robots won’t play. Go to the “Settings” tab, then go all the way to the bottom, and press “Upload State.” That takes you to another screen, where you must press the “Upload State” button. Finally, send me an email to firstname.lastname@example.org so I can ask you a few follow-up questions.
I suppose it could be that everybody who has experienced this problem is still using an older version of Hearts Net? If this happens to you and your Settings view does not have an “Upload State” button, then you are not using the latest version of the program. In that case, then yes, I am already aware that older versions had this problem. I only need to hear from people who are using the latest version.
Second bug: some people say that the number of games played and games won is sometimes inconsistent. For example, one time you’re playing and the game says you’ve played 30 games and won 18 of them, then the next time you look, it says you’ve played 20 games and won 5, or something like that. This bug is trickier. I don’t think I can solve this one with the “Upload State” trick, for complicated reasons that you don’t want to hear about (heh). But if you can make this happen “at will,” every time, and explain to me how you did it, then I could fix this one, too. For example, it could be that the game is crashing for some reason, and so it doesn’t get to save its state to disk. Then, the next time you start it, you’re looking at the game state as it existed the last time it was able to save its state. Or something like that. So if you can make this bug occur “at will,” let me know how to do it too, so I can fix it.
In Hearts Net 2.1.1, I added a feature where you can upload your current game state to my web server. It’s the very last thing on the Settings view, labelled “Upload State.” Among other things, this is useful for helping me improve the robots.
Let’s say you see the robots make a card play that you consider poor. Right after it happens, use the state upload feature to send your current game to me. Then send me an email to describe what was happening in the hand, and how you think the robots should have handled the situation. If I agree with you, and it’s not too hard to fix, I’ll add that improvement in a later version of the game.
Hearts Net 2.1.1 is now available for download from the App Store. This is a free upgrade for anybody who has already purchased the program.
I tried to resolve the “shy robot” problem, described in an an earlier blog post. I can’t be sure I’ve fixed it, because that situation never happens to me personally. Perhaps somebody will let me know if I succeeded?
If you upgrade to 2.1.1 but find that games still get “stuck” sometimes, can you use the new “State Upload” feature to send me your game state? And then send me an email, to let me know who you are. When I get a state data upload to my website, I don’t know anything at all about who sent it, other than the UDID from their device. It’s nice to have a little more context.
Also, brand-new feature: You can now replay a hand from the beginning if you want. The first of many gameplay variations I’ll be adding.
February 28, 2010 5:07 pm
I just had a look, and my blog is the number one hit on google for the search phrase “iphone nibless.” That leads to a blog post I wrote on the subject last year. I linked to another blog that explained how to accomplish such a goal, but that blog post has since been taken down. Hrmph. Okay, I guess I have to cover this subject again.
Generally speaking, Apple makes beautiful apps that are elegant and easy to use. Interface Builder is a glaring exception. I can’t stand that thing. So unbelievably complicated. I can’t ever find what I’m looking for.
If you’re writing Mac apps, I guess you’re stuck with it. Most Mac windows contain a lot of controls, and you need a way to design them. If you’re writing iPhone apps, it’s a net loss. Most iPhone views contain a single control that takes up the entire view area, so Interface Builder is an unnecessary complication. So I’m going to tell you how to make an iPhone app that does not require any nibs at all. I am using Xcode 3.2.1 on Snow Leopard, but these instructions will likely work for older versions as well.
1) Start Xcode. From the File menu, pick “New Project.” In the window that opens, select the iPhone OS Application category on the left. In the group on the right, pick “Window-based Application.” This may work fine for the other project templates, but I haven’t tested that. Create the new project, name it whatever you want.
2) Remove MainWindow.xib from the project and put it into the trash. It is no longer needed. (Yay!)
3) Edit the Info.plist for your project by double-clicking on it. It will have a name similar to projectname-Info.plist. The plist file will have a key named “Main nib file base name,” with the value MainWindow. Remove this key completely: select it, and press the Delete key. Save the file.
4) Xcode will have created an app delegate class for your project, named something like niblessAppDelegate. Yuck, what a horrible name. Rename this class to AppController, by directly editing the header and source files for the class. You can of course pick a different name, or even skip this step altogether, but I’m going to assume from here on out that your app delegate class is called AppController.
5) At this point, you have destroyed the mechanism that iPhone OS normally uses to recognize the name of your app delegate class, which it needs to know to load your app. Fortunately, there is an easy way around this: you must pass your app delegate’s class name to UIApplicationMain(). Xcode created a file called main.m that contains your app’s main() function. Edit it now, and change main() so that it looks like this:
argc, char *
pool = [[NSAutoreleasePool
argc, argv, nil
pool = nil
That’s it, you’re done. You may continue modifying this project until you have a real application.
At this point, you might be thinking: Whoa, scary change. Is this really safe? Well, I can offer myself up as an example. I’ve submitted two of my own apps to the App Store that use this technique, both of which have been downloaded thousands of times. I’ve gotten hundreds of emails from users over various issues, but my apps not having nibs has never been a problem.
February 27, 2010 11:22 pm
Dear internet: I have been searching for a UIProgressHUD replacement for many, many months. Why have you failed me? I don’t suppose it was because of that other, similarly named UIProgressHUD replacement? Which I am not going to link to or name, because it sucks. Sorry, yes I am a jerk, but it does. If I have to explain to you why it’s a bad idea to make a progress view that’s launching background tasks, then there is no helping you.
So, anyway. In case you’re new to this. UIKit has a nice control called UIProgressHUD for displaying a heads-up, semi-transparent view with a spinny-control on it, and a single line of text. It looks good, it works well, it’s easy. The only down side is that it’s undocumented, so you can’t use it in apps destined for the App Store.
I used UIProgressHUD in a project I was writing for a client a few months ago. This particular app was not destined for the App Store, so it seemed like a nice shortcut. Maybe that’s not such a hot idea, but they weren’t paying much, so I couldn’t justify a detour for writing a brand-new view. But now here I am again, needing the exact same thing for my card game, and google searches still only turn up that progress view that thinks it’s an app launcher. Hrmph. Time to write my own, I guess.
My goal was to write an exact, drop-in replacement for that view I can’t use. I’ve included screenshots of Apple’s original view, and my clone view. Pretty darn close, don’t you think? The only real differences are details that I don’t want to change. For example, I think they picked a font size that’s a bit excessive.
It would be great if I could just paste the source file and header file right into this post, for your amusement. My view is mercifully short, and would lend itself to that. Alas, it requires several support modules, so I had to make it into an example Xcode project. I’ve developed a huge library of iPhone support code by this point, so it doesn’t make sense to duplicate things in every single view and controller I write.
One clever feature of my demo project: you can change one line of code and it will use either UIProgressHUD or my own WBProgressHUD. No other code has to change, because the two views are that similar, dawg. It makes for a good test bed for developing a clone view such as this one.
Download wbprogresshud.zip by clicking here. If you like this project, how about hiring me to write more stuff like it? My contact details are on my About page.
February 26, 2010 4:34 pm
I’ve heard from several players that it’s possible for Hearts Net to get into a situation where it appears “stuck,” because one robot won’t play a card when it should. This seems most likely to happen to people who play the game in short bursts, interrupted frequently with phone calls or texts or whatever. The bug also exists in Hearts Solo, but is unlikely to be experienced there, since it doesn’t let you play a game for very long. I’ve never experienced this bug personally, because I almost always play whole games at a time.
The short-term fix is easy. The game isn’t really locked up. Go to Settings, and press “New Single-Player Game.” This starts a new game, which won’t be stuck.
The long-term fix, of course, is that I have to find and fix the bug. I have an idea what it might be, but I’m not 100-percent sure. I’ve applied my hoped-for fix to the code, and I’ll submit it to the App Store pretty soon.
The reason that I haven’t already submitted this is that I’m also working on another feature, which I guess I’m calling “state upload.” The card game engine is capable of saving all its state to a block of memory about 3.5k in size. This is the mechanism used when the game saves its state between runs, so it can start up right where it left off. An interesting side effect is that, if I have the saved state file from your game, I can recreate whatever situation you might be experiencing in my local development environment.
Everyone is telling me that the “shy robot” problem persists between runs of the program. That means that the screwed-up situation is definitely stored in the game’s state data. By examining state data from somebody whose game is in “shy robot” mode, I should be able to exactly duplicate the problem locally. Any programmer can tell you that a bug with a reproducible test case is a bug that’s easily fixed. So if my first try for fixing this bug doesn’t work, it’s almost a certainty that I can fix it by examining the state data from somebody who’s experiencing the problem.
There’s another reason why I think this is a feature worth spending development time on. I now have several players who are very opinionated about perceived shortcomings in my Hearts-playing robots. They email me with very detailed situations where they had this set of cards, and a certain robot had that set of cards, and then the robot played this particular card, and oh boy that is dumb.
If I start with nothing but an explanation like that, it could take me days to determine the particular behavior that player is talking about. I’d only have about 60 percent confidence that I could ever figure it out. But if that player can send me his game state, I can reproduce the exact scenario he is talking about with basically no effort whatsoever.
I am fairly baffled that a silly card game is now my Flagship Product. But if lots of people are going to take it seriously, I guess I will too.