Archive for May, 2009
StickWars 1.4 is Live
You can get the latest version here or read the changelog. The new version has much cleaner graphics and runs quicker.
Unfortunately, I think I introduced a bug that can sometimes disable the in-game buttons (pause, bomber, and deploy defenders). While it auto-fixes itself at the end of the round, it is rather annoying so I’ll be rushing to finish 1.5 to correct it as soon as possible.
StickWars Status and Update
I sent 1.4 to Apple sometime last week, it should be going live pretty soon now. Also, they finally dropped StickWars off Staff Favorites today. Looks like the Apple guys got bored with StickWars already
. Let’s hope they dig the new features I’ll be rolling out next week.
On a side note, I finally got paid by Apple for the first time today, so I can finally start paying off the credit debt I built up paying for services and equipment needed to work on StickWars
. I was afraid what would happen if I didn’t get paid for some reason!
I’m really hoping to see StickWars push back into the #1 paid spot in the AppStore. I’ve been running more exchange ads, and sales are still going strong, so I believe there is still a chance to top the charts before the inevitable decline off the top 10. It’s been the top game for over a month now in many countries, including the US. I still have hope…
Secret to Success on the App Store Part 1
Posted by Eric in iPhone Development on May 24th, 2009
First of all, the title of this post is a joke. This is by no means a secret, and it will in no way guarantee the success of your app. However, I get asked this question so much that I’m slowly going to build up this post with some tips and suggestions that may or may not be obvious, but are important enough that you can’t afford to not know them. I don’t really have time to do the full post now, but I’ll add to it over time.
The first tip which I can not emphasize strongly enough: listen to all your users, and respond to their concerns (if they are legitimate). I know this is a major shortfall of the AppStore, in that it is tough to go back and forth with your users. Developers can not add a comment to a review? Seriously? A third of the one star reviews on StickWars are people too dumb to press the giant options button before complaining about ‘not being able to turn off the music’ or some other issue I fixed long ago. A one sentence reply by me would help them, and they would raise the review of my game, helping me.
That being said, you must create your own forums for users to ask you questions and receive answers. And no, don’t you dare add in a generic ‘contact us’ form and call that your support feedback. You are not some spineless, monolithic company who can afford to treat their customers like crap because you are too big to have any real competitors. Create a forum where people can post questions and you can answer them, and other people can see those answers without having to ask themselves. For every person who asked a question, there are probably 10 more who typed the same thing into google looking for an answer but was too lazy to ask the question themselves.
Best of all, these forums can be a valuable tool to get ideas how to improve your product. I’m not exaggerating when I say that 70% of the enhancements I push out with every update started as user suggestions.It’s not that I do what every user asks, but I consider every suggestion even if I initially considered the issue and decided against it. For many of the features in StickWars, there were features I really did not want to add, but many people asked for them, and after I took the trouble to add them in, the response was overwhelmingly positive. If you didn’t get the important point so far, I’ll keep it simple…listen to your customers. Separate the stupid input (example: ‘hey can you plz ad zombies, ufos, monkies, nukes, rifles, cows….’) from legitimate feedback and suggestions and weigh all of it carefully when deciding what to add to your application.
I’ve read every single review posted on the AppStore about StickWars and StickWars Lite, for all versions. In case you don’t realize how many there are, right now the number stands at about 2000+ combined. I’ve found that iTunes does some really bizarre caching of them, so I use my iPhone to read reviews each day until I read one I recognize. It’s not the best system, but it works. I don’t know whether or not most developers already do this, but either way, you should. Oftentimes I’d read 100 retarded reviews to find one guy who had a truly original and easy-to-add idea to add to StickWars. Twenty-five minutes later, I finish adding this feature that I later get hundreds of ‘awesome idea!’ reviews for. Seriously, this type of stuff happens, and with all these people offering feedback (even if 95% is ridiculous), you need to read all of it.
I’ve started using a fantastic service from www.appfigures.com that allows you to read reviews of your application from every worldwide app store. I went through and read every non-US review that was in english, and found for some bizzare reason, like 30 people all outside of the US asked where to find a link to my forums. Nobody in the US had ever asked this question, but I realized it might be a good idea to manually throw it in there (as the generic iTunes “StickWars Support” link isn’t really informative to the user).
That’s it for now…later on I’ll be adding some more comments about some of my App Store lessons learned.
StickWars Featured on iTunes – 3 Places on App Store Landing Page
For the first time (that I know of) Apple has paid some individual attention to StickWars! It is currently on the first page of ‘Staff Favorites’ on the App Store landing page. That means when you land on the App Store homepage, StickWars is in three separate locations
. Yay visibility!
As far as StickWars itself is progressing, the next update is about ready, I was able to optimize the code so I could change the graphics back from those new ‘fuzzy’ graphics that annoy some people, and I undid some of the factors which caused a little more lag for some people in version 1.3. I added in a new enemy which is a lot of fun, and fix various bugs and minor gameplay issues.
It’s hard to believe, but StickWars is really coming together and is starting to have all the features I had envisioned for it months ago. Now I just have to get on adding in the one enemy everyone keeps asking about–the giant stickman featured on the icon for the game
.
Screenshot of the triple-feature:
StickWars 1.3 Live!!!
Although you might not see it in the US store yet, 1.3 is rolling out across iTunes. You can checkout the changelog and get ready to battle the new dragons using your awesome new wizard fireball spell.
On another note, StickWars and StickWars Lite are both sitting at the #2 spot, and I’m hoping they can jump up to #1. Filling both #1 spots would be amazing! In addition, StickWars (paid and lite version combined) currently has 1 million unique players. Thanks to all the fans and players!
StickWars 1.3 Sent to Apple
You can read more information about the update on the forums. After a long and painful night, it’s time to get some sleep and wait for Apple to approve it.
StickWars 1.3 Update Status
Refer to my forums for the latest updates. You can also get a sneak peek of the features that will be added in 1.3. Long story short, I just graduated college and have been busy with all the moving around. However, I’ll finish up 1.3 over the weekend and send it to Apple by Monday. Hopefully they’ll approve it by Friday, in time for the weekend.
It fixes all the bugs people have found, and makes the game less laggy in general, as well as adding tons of new fun features. I can’t wait until people get to try it out
.
StickWars 1.2 is live, and StickWars Lite is back!
The funny part is I didn’t think Apple would approve both the Apps this quickly, so my changelog currently says “Updated version number”. I also don’t have new screenshots ready yet. I guess I’m going to have to put off working on version 1.3 tonight
.
I’ve decided to try a slightly higher price of $1.99 for the paid version, as the game is actually more polished now and the price should reflect that. Still, I’ll keep an eye on sales and make adjustments if needed. Another reason doing this is I’m tired of getting 1 star reviews from people who have no idea what the game is before they buy it. If you don’t like throwing stick figures in the air to go splat on the ground, then you shouldn’t buy StickWars. I hate that so many people bought it and left terrible reviews when they realized that the game didn’t appeal to them at all.
Hopefully now that the Lite version is out there, and the price is slightly higher making people think more about their purchase, the people who buy StickWars are those who actually will enjoy it and leave good reviews.
StickWars Drops to #2 After 12 Days as Top Paid App
Posted by Eric in StickWars, iPhone Development on May 4th, 2009
After 12 days in the top spot, StickWars has dropped to #2 in the overall paid app rankings. However, the 1.2 update was sent to Apple last Wednesday and should be live this week, and I’m expecting a great user response. Hopefully it will get bumped back up to #1!
In any case, it is still the #1 game, and I’m still working around the clock on bug fixes and enhancements. I just completed a massive graphics overhaul that ended up with the graphics look exactly the same (with maybe a few compression artifacts), but the game now runs around 20% faster. I went from using 160 separate png files for all the animations to 8 atlas sheets in the compressed pvr format. Now I can work on adding some cool fire particle-effects, since I can spare the processor usage needed.
I just finished my finals at college and am graduating in a few days, so StickWars is now getting all of the attention it deserves. There are some really cool new features coming, some ideas that are new to the genre but I think will really make it fun. I’ll give a hint: if you like the idea behind ‘Bowman’, you’ll love the new wizard spell
.
Also, after realizing that like 80% of the google searches for StickWars that land on my website contain the terms “cheat codes” I’m going to satisfy those people who don’t have the patience to put in the time to get to level 30 before trying out all the cool powerups. This will be a surprise, with hints posted on my forums.
All these new improvements will be included in version 1.3.
Using Cocos2D AtlasSpriteManager
Posted by Eric in cocos2d iPhone, iPhone Development on May 2nd, 2009
After having a lot of trouble dealing with the issue myself and seeing others having trouble on the cocos2d discussions, I’m going to go ahead and post my solution which so far is working pretty well for me. Please take into account I’m new with Objective C when looking this over.
The problem is each AtlastSpriteManager can 1) refer only to a single sheet image, and 2) each AtlasSprite can only be a child of at AtlasSpriteManager. So what happens if you a few game characters that you want to share certain animations, but not all?
I took the super-class of all my game Sprites, changed its type from a Sprite (or AtlasSpriteManager, which I tried but failed to well) to a generic CocosNode. I added in this to the header. Note that I only needed my Sprites to switch between two different sprite sheets as most.
@interface Touchable : CocosNode <Collideable> { AtlasSprite *activeSprite; AtlasSprite *sprite1; AtlasSprite *sprite2; ... } - (id)init:(CGSize)sizeOne two:(CGSize)sizeTwo; - (AtlasSpriteManager *)spriteManager1; - (AtlasSpriteManager *)spriteManager2; - (void)setSprite:(NSUInteger)newstate; - (void)setActiveSpriteOne; - (void)setActiveSpriteTwo; ...
To the implementation file…
- (AtlasSpriteManager *)spriteManager1 { return nil; } - (AtlasSpriteManager *)spriteManager2 { return nil; } - (id)init:(CGSize)sizeOne two:(CGSize)sizeTwo { self = [super init]; if(self) { sprite1 = [[AtlasSprite spriteWithRect:CGRectMake(sizeOne.width, sizeOne.height, sizeOne.width, sizeOne.height) spriteManager: [self spriteManager1]] retain]; [[self spriteManager1] addChild:sprite1]; if(![[self spriteManager1] parent]) [[[LevelController sharedSingleton] gameLayer] addChild:[self spriteManager1] z:1]; [sprite1 setVisible:NO]; sprite2 = [[AtlasSprite spriteWithRect:CGRectMake(sizeTwo.width, sizeTwo.height, sizeTwo.width, sizeTwo.height) spriteManager: [self spriteManager2]] retain]; [[self spriteManager2] addChild:sprite2]; if(![[self spriteManager2] parent]) [[[LevelControler sharedSingleton] gameLayer] addChild:[self spriteManager2] z:1]; [sprite2 setVisible:NO]; } return self; } - (void)setSprite:(NSUInteger)newstate { } - (void)setActiveSpriteOne { activeSprite = sprite1; [sprite2 setVisible:NO]; [sprite1 setVisible:YES]; } - (void)setActiveSpriteTwo{ activeSprite = sprite2; [sprite2 setVisible:YES]; [sprite1 setVisible:NO]; }
A few methods of my superclass ‘Sprite’ object that I modify slightly to take changes into account. You can no longer want to run the actions (which include animations) on yourself, but on the active sprite.
- (void)setState:(enum ActionFigureState)newstate{ [activeSprite stopAction:[stateActions objectAtIndex:state]]; [self setSprite:newstate]; [activeSprite runAction:[stateActions objectAtIndex:newstate]]; state = newstate; } - (void) setPosition:(CGPoint)pos { [super setPosition:pos]; [activeSprite setPosition:pos]; }
So what we have now is a superclass that is calling a instance method [self spriteManager1] in order to manage attach its two different sprites. Notice that no animation specific code is here in the superclass, except for the fact that a single ‘Sprite’ can work with 2 AtlasSheetManagers at most. You could easily take away this restriction, but I had no need to complicate things.
This gets helpful when I get into a child class that actually knows how to draw itself. Here is my “SmallStick.m” which has an empty header file except for being a child of Touchable. This implementation code also contains all the this object’s interaction with the game, such as collision detection, how to handle if it is touched, and how to add itself to the Chipmunk space.
#define width1 79 #define height1 68 #define columns1 7 #define width2 79 #define height2 68 #define columns2 7 @implementation SmallStick static AtlasSpriteManager *spriteManager1 = nil; static AtlasSpriteManager *spriteManager2 = nil; + (AtlasSpriteManager *)spriteManager1 { @synchronized(spriteManager1) { // I dont actually know if synchronized is needed here if (!spriteManager1) { [Texture2D saveTexParameters]; [Texture2D setAliasTexParameters]; spriteManager1 = [[AtlasSpriteManager alloc] initWithFile:@"smallstick_common.png" capacity:50]; [Texture2D restoreTexParameters]; } return spriteManager1; } return nil; } + (AtlasSpriteManager *)spriteManager2 { @synchronized(spriteManager2) { if (!spriteManager2) { [Texture2D saveTexParameters]; [Texture2D setAliasTexParameters]; spriteManager2 = [[AtlasSpriteManager alloc] initWithFile:@"smallstick_weaponless.png" capacity:50]; [Texture2D restoreTexParameters]; } return spriteManager2; } return nil; } - (AtlasSpriteManager *)spriteManager1 { return [SmallStick spriteManager1]; } - (AtlasSpriteManager *)spriteManager2 { return [SmallStick spriteManager2]; } -(id)init { self = [super init:CGSizeMake(width1, height1) two:CGSizeMake(width2, height2)]; if(self) { ... } return self; } - (void) setSprite:(NSInteger)newstate { switch (newstate) { case fState_charging: case fState_attacking: case fState_recovering: [self setActiveSpriteTwo]; break; default: [self setActiveSpriteOne]; break; } } - (void)loadActions { AtlasAnimation *chargeA = [AtlasAnimation animationWithName:@"weaponless_charge" delay:0.05f]; for(int i=0;i<18;i++) { int x= i % columns2; int y= i / columns2; [chargeA addFrameWithRect: CGRectMake(x*width2, y*height2, width2, height2) ]; } Action *charge = [RepeatForever actionWithAction:[Animate actionWithAnimation: chargeA]]; ... stateActions = [[NSArray alloc] initWithObjects: charge, dying, ..., nil];
The part I like about this is when I want to reuse the ’smallstick_common.png’ atlas sheet I can just not override the class method +(AtlasSpriteManager *)spriteManager2 in my child classes.
Don’t forget to remove the sprite from the AtlasManager when you’re done.
[[self spriteManager1] removeChild:sprite1 cleanup:YES]; [[self spriteManager2] removeChild:sprite2 cleanup:YES];
First of all, I hope this doesn’t have some hidden downside. As I said, I’m new to the platform. But I hope somebody finds this useful.

Recent Comments