Friday, April 26, 2013

Nice iOS Snippet for sayin' "Hi Mom!"

Just a quick one from the forge: when debugging my iOS code for my game I like to use the "Hi Mom!" method.

Image of elderly lady in a hat - original source seems to be Huff Post (after some Google Image searching)
Hi Mom!  (Photo credit: Huffington Post)
What's that you say?  "Hi Mom"....?

This is when you have lots of places where your code prints out something - Hi Mom is fine, tho' you often want something more informative - but the key is it prints out on the console, and you can trace its execution by checking these points, and the data output at those times.  It's the best debugging technique I know.

It's the traditional "printf" style of debugging as some call it.  An elite coder friend who coined the term did it I think because "Hi Mom" is really quick and memorable - it highlights the fact that when you're doing this kind of debugging you want a quick edit-compile-run loop so lots of typing is a pain.  And "Hi Mom" is short.  It's just flagging that you reached that point.

It seems pretty obvious perhaps, but in these days of high-powered IDE's (like XCode) and symbolic debuggers that lead you by the nose through your code as it runs, it might seem that Hi Mom is a bit past it and long in the tooth.  Far from the truth!

It might also seem like hard work - writing more code to debug the code I've already got?  Wrong again!

Symbolic debuggers are a pain sometimes - they don't always work especially if your bug has messed up the stack.  Getting a breakpoint just where and when you need it is not always straight forward.  Getting information about the variables you want to see in the right format doesn't always come easy either.  When code is multi-threaded or backgrounding, or you have to interact with the UI using the debugger is not always convenient.

So Hi Mom has some mileage here, even in these days of magic IDE's.

What about all that work typing tho' - especially when Objective-C does not give you a nice __FILE__ or __LINE__ macro to use like C++ does?

Here's a nice snippet I came up with that I'm using a lot - its a macro which uses a bit of token pasting:

#define MARK(object) NSLog(@"%@::%@ MARK - %s: %@", \
        NSStringFromClass([self class]), \
        NSStringFromSelector(_cmd), #object, object)

It gives me output that looks like this:
2013-04-26 22:21:31.994 Ethex2080[24072:c07]\
 UIStateManager::graphSearchFromNode:toNode: MARK - nodeStart: Location #501

Breaking this down:

  • The time stamp and binary name come from NSLog
  • the class name and method name come from the two "NSStringFrom..." functions
  • MARK (my version of "Hi Mom!") tells me its from a "MARK" macro call 
    • so I can see from the console what it is, if I have forgotten to remove one
  • The string nodeStart: is the name of the variable 
    • (from a c-pre-processor token paste, the #object) and 
  • then the results of calling the -(NSString *)description function on that variable.

In fact I put it in my global project declarations file which is one of the headers which gets included in my precompiled header.  That way its always available in any code I write in the project, without having to go hunting for the include or import:

//
// Prefix.pch

#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

#import "cocos2d.h"

#import "Ethex2080Utils.h"
#endif

Now in my code that I'm debugging I can quickly drop in a statement like this:

- (void)doSomethingWeird:(NSArray *)someStuff
{
    MARK(someStuff);

    // rest of stuff
}

This gives me a nice debug line with
  • the name of the class
  • the name of the function that is running
  • the name of a key variable I'm dumping
  • the description (dump) of that variable
Benefits are:
  • ultra quick to type - no need to type the name of the variable even
  • easy to find and remove before I do my git commit
  • being a macro it can capture the name of the function (a debug function could not)
Feel free to use this if it helps (I hereby place this snippet in the public domain) and good luck as you "Hi Mom" your way to bug-free code!

Saturday, April 20, 2013

What does your game dev back-up strategy look like?

It's an important question to ask.  Sorry for asking it, as I am totally sure you're all over it - but just in case some of you aren't - ahem: backups?  Offsite?  Versioned?  Tested?  :-)



So this post is just a helpful reminder - no need to teach anyone how to suck eggs as we all know the sorts of things that work:

  • source control with remote repositories
  • cloud storage (especially if its versioned)
  • offsite backups
  • multi-site replication
Mine is drop-dead simple.  Basically I use DropBox (with the pro/paid for account you get versioning) for all my directories that are full of binary stuff, like artwork, animations and so on.  And for my code I put it all under source control and push every commit to GitHub.



Obviously GitHub or DropBox could die horribly, get compromised or whatever - just as long as that does not happen on the same day that my house burns down then I'm golden.

Whatever you do choose it has to be simple, and it has to work.  If its a pain to use, and not automatic enough, then you'll forget or overlook using it.

Here's my rule: every time I do a commit to GitHub, I option drag the root folder of my artwork into a folder in my DropBox.

I also have my lap top backed up by TimeMachine to a big hard drive on my home network.  If the house does burn down then obviously both of those things are lost, but the TimeMachine is more about catching my own screw-ups where I delete a file or a folder full of stuff by mistake.

The safety net for catastrophic events is the DropBox and GitHub combo.

It's far from perfect, but I find I can work with it.

I have used both systems to restore files as well - not because I was being thorough and testing my backups like  you're supposed to - but because I'd screwed up and needed to recover stuff.

It was a good feeling knowing it works!  If by some crazy chance you're flying without backups, try making some - its a good feeling, and I'd love to hear your stories.

Thursday, April 18, 2013

CocosBuilder Revolution

A couple of months ago now I threw away all my code and started again.

Was that a bad thing?  Well, it was bad in the sense that I wish I had known back before I started writing all that code that there was a better way to do it, a way that was going to be so much more productive that even throwing away months of work was going to be sort of OK.

So what is that better way?  Using CocosBuilder.

Cocos2D is a powerful API for building your games on iOS, but it is just code, and when I started out on my game I quickly found it impossible to organise all the resources I needed and to size and position all the elements on the game screen.  As I mention in the video I had seen CocosBuilder last year but it seemed flakey and not up to doing enough of what I needed.

But the new 3.0 version is much improved and there are a number of tricks with CocosBuilder that allow you to do a lot more with it than appears at first blush.  It turns out to be well-suited to creating an adventure game like mine, if you can figure out how to game it to your ends.

To try to help anyone who is contemplating going down the path I went down, or anyone who needs a powerful game interface creation tool but is too afraid to ask, here is a video tutorial I put together looking at how to get started with CocosBuilder for iOS.  The tutorial also includes a bit of my thinking around the game editor journey for me.

The tutorial comes in 4 parts, each of around 10 minutes (due to YouTube constraints) and I have tried to make the divisions not too arbitrary.  I'd encourage watching the whole thing, but if you just want to dip into the bits you need I hope the text below will help choose the right parts to watch.

As well as watching my tutorial please also check out two other great tutorials (not videos but very good nonetheless) which I used myself during my CocosBuilder learning process:
http://code.zynga.com/2012/10/creating-a-game-with-cocosbuilder/
http://www.raywenderlich.com/23996/introduction-to-cocosbuilder

Here are download links to the software I used:




Part 1 - Installation and Setup of a Tutorial project for Cocos2D-iOS & CocosBuilder


Part 2 - CocosBuilder resources and first Run of content


Part 3 - Creating a HUD layer CCB



Part 4 - Animating the HUD & making the buttons work

Things I had to leave out

The tutorial was already up to 40 minutes so I had to leave some things out.  Maybe I need to learn how to talk faster.  :-)

Using the UI elements: I imported some UI elements in a plist file in part 1, but never got time to use them.  But if you experiment you should have no trouble in seeing how to use these.  It's pretty much a case of drag and drop.  In some cases you need to use the "Sprite frame" selector in the properties panel on the right-hand-side of CocosBuilder.

Making a layer use the targeted touch handler: I recorded some footage on this, but had to remove it to get the tut down to a reasonable size.  The trick here is that most tutorials and references tell you to implement registerWithTouchHandler in your CCLayer subclass in order to get the kCCTouchesOneAtATime behaviour.

With that behaviour you can use

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
    CCLOG(@"%@::%@ - %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), touch);
    CGPoint location = [touch locationInView: [touch view]];
    location = [[CCDirector sharedDirector] convertToGL:location];
    
    BOOL isHandled = NO;
    if (CGRectContainsPoint([self boundingBox], location))
    {
        isHandled = YES;
        // do stuff
    }
    return isHandled;
}

Now it turns out that you can get that by setting the following in CocosBuilder for your CCLayer subclass:


...and since these are set in didLoadFromCCB before the onEnter handler sets up the registration, this will cause the CCLayer's implementation of registerWithTouchHandler to set up your instance for one-at-a-time touches.  Now you can implement your touch handler (as above) and off you go.

Thanks for watching videos - I hope they're useful.  Please - if you spot any mistakes let me know so I can address them.

Happy Cocos building!

Wednesday, April 10, 2013

Resting and Seeing

No posts for a week or so because I've been having a nice restful holiday to New Zealand.  It was a chance to rest my brain, and allow myself to really see stuff again.  To see stuff, I draw - photographing stuff is good, but you don't see what is there or get your mind working on it until you draw it.

When you make a game you need a premise.  OK - we're shooting a bunch of bad guys - and why are they bad again?  They're evil zombies from a scientific experiment gone wrong?  OK - that is a premise, and without one even the most obvious game idea won't work.

My game concepts are all driven by fairly rich premises and I need something to work from to build those.  Bad guys need a back story, and good guys need one too - if players are to care at all about your game characters they need some dimensions.

Sitting in a cafe is great - I find I can easily make up stories about the folks having a coffee two tables over.  But travelling to another country, sitting in airports and travelling on ships and helicopters: hell, it doesn't get any better than that for topping up my creative reserves.

Here's some images from my trip and a few words about each - maybe it will give you some insight into how my imagination sees the world and creates a story out of it.

I flew into Wellington, NZ and started there with a trip to Weta Digitals "Weta Cave" for their "Window into Workshop" tour.  This was an absolutely amazing insight into the creative people behind movies like "Lord of the Rings" and "District 9", and I have only my memories of it as we were not allowed to take pictures.  As it was a guided tour doing drawings was not possible either, not that Weta would have been all that keen on my "taking notes" of what they were working on.  

I went to the Southward car museum and managed to strike up a conversation with the curator there.  The Corvette Stingray and Jaguar E-type next to it were pretty nice too.
Clearly you need to lend me this De Lorean so I can save the universe from evil

I went up on the Wellington Cable Car to a great vantage point and checked the harbour views.  In this picture I'm in front of an older cable car in their cable car museum.

From Wellington I went across to the South Island on the Interislander: a large roll-on, roll-off ferry.  It was a few hours so I got to relax and sketch.  My favourite activity is ninja sketching random people and making up stories about them.  I hold my sketchpad down out of sight and draw them quickly hoping I won't get sprung.
Guy on the Ferry

Guy on the Ferry: he was sitting a few seats over and had a very game-worthy face.  Strong potato of a chin and kind of a solid demeanour.  He could be like some kind of SAS guy, trying to get away from the memories of his last tour in Afghanistan.  He actually smiled a lot, but when his friends pointed at something out the Ferry window he kind of got the "thousand yard stare".
These guys were clearly spies travelling to complete an assignment.  I'm not convinced they really were human.  Maybe SAS guy was going to take them out.

As the Ferry neared the South Island there were some lovely views of the peaks of the fjords reaching up out of the water, and a few tiny yachts gliding across the water.
View out Ferry porthole
There was something about the way portholes framed the views that made them more poignant, more dramatic.
Queen Charlotte Sound
I think it is the way whoever is watching the view becomes part of the frame itself, their black silhouette and that of the ships window being a surround for the scene sliding past.  Ninjas and assassins are like that - you don't see them because they become part of the darkened frame.

Coming into Picton
The ferry itself was pretty enormous - and as it approached the South Island terminus of Picton the buildings seemed tiny compared to it.  One of its sister ships was tied up at the wharf.

We spent a few days in Picton doing the wine district and driving around the Nelson & Marlborough area, then headed down to Franz Josef Glacier.

 Our cabins in Franz Josef were right next to a miniature horse place and one of the cute little guys stuck his head all the way through the wire fence to where I was set up on a chair with my sketch pad.

The goal of Franz Josef was to get up on the glacier itself which was acheived by helicopter.  I would love to own one of these things.  Lots of game memes here.  :-)


Landing up on the glacier we met up with our guide who took us through the ice caves and crevasses.  Glaciers are very very big.  And powerful.  This is a shot of me carefully listening to the safety briefing - "Don't fall into the ice caves as we won't be able to get you out".

The ice caves can go all the way down through the glacier to its bed, but they quickly get too small for us crazy humans.  Here's me doing my best Bear Grylls/Crocodile Dundee impression as I head down into one of the crevasses.

The mountains of the Southern Alps - which featured prominently in the Weta Digital enabled "Lord of the Rings" - were pretty spectacularly beautiful too, swathed in dense green from sea-level and soaring up to snow capped peaks.

From Franz Josef it was back via the scenic Arthur's Pass national park to Christchurch.  This city of 300,000 people has been plagued by earthquakes for the past few years.  Locals have responded by deploying shipping containers as makeshift barriers to prevent rocks from nearby mountains plunging through their houses.

Post apocalyptic doesn't get any better than this.
The city itself is amazing too - shop owners have moved their businesses into shipping containers and a new cafe district is thriving in the container mall called "Re:START" in the city center.

Here a once proud landmark of Cave Rock is fenced off due to earthquake damage and this rather inexplicable steam-punk pumping device is playing some role in that.
After a couple of nights in Christchurch at a rather Agatha Christie style guest house called "The Grange" it was time to head back to Australia.

Sunday, March 24, 2013

Exporting layers from Gimp as PNG files

Gimp for MacOSX is now a "native" (-ish) application, and is a great graphics tool for game developers - especially those who can't afford Photoshop.  I've always used it and wouldn't go for PhotoShop as I know GiMP so well now.

You can create animations in layers and Gimp allows you to preview your animations when you've done them as a bunch of layers, by simply invoking the handy "Animation" option in the menu:  "Filters" > "Animation" > "Playback..." - very nice.

But now how do you export those layers as a collection of separate PNG's so you can import them via TexturePacker into your game?

It turns out there is a handy Gimp plug-in to help you - but installing it is not for the faint-hearted.

Installing Plug-ins for GiMP on Mac OSX

On Windows or Linux the process is comparatively easy and is described in a nice tutorial.  If that article happens to be unavailable the GiMP registry lists a number of others.  On MacOSX where normally things "just work" for some reason its a lot more obscure.

The first insight is to know how to find your plugin folders.  Use the Preferences menu in GiMP to find the Folders item and choose "Plugins":


I didn't use the one for just my user name because I wanted the changes in GiMP to be available to anyone using the GiMP install on this computer.  Also it saves me a step as I don't have to create that folder.  I used the GiMP internal folders.  It also has the advantage that if I copy that GiMP to another machine, its plugins go with it.  Nice.

The second thing to know is that there is a laundry list of different types of things that you can install into GiMP, and this makes things more complex for the GiMP automation newbie.  You have "scripts" which are small helpers that can automate what GiMP already knows how to do.  Then you have "plugins" which are larger actual programs which extend GiMP's functionality.  And then there is modules, brushes and the list goes on.

Confusingly enough scripts are written in scheme, but if you want to write a script in python, that is considered a plugin.  Why?  Because the GiMP authors decided it would be so.  In any case if you want to install the export_layers Python script, you have to install it in the plugins folder.

Also since it is a plugin, it has to "look" like the other plugins which maybe complied C program binaries and so on - in other words it has to be executable.  If it isn't then it won't show up when you restart GiMP.  And also - note - restarting GiMP is required, since this is a "plugin": you cannot get it to show up by selecting the "Refresh" option from the script-fu menu in GiMP.

So first step - shut down GiMP.

On MacOSX using the Terminal its then an easy 3 step process:

cd ~/Desktop
curl -O http://gimp-registry.fargonauten.de/files/export_layers-0.6.py.txt
chmod a+x export_layers-0.6.py.txt
mv export_layers-0.6.py.txt /Applications/Gimp.app/Contents/Resources/lib/gimp/2.0/plug-ins/export_layers

If you have problems using the Terminal I really strongly suggest that you start getting over them.  Seriously.  You're missing out on a lot of what Mac has to offer - all the power of Unix just a few keystrokes away.  It's much faster and much easier to capture the process to repeat or modify it.  In some cases the Terminal is the only way to do things.

I use a mixture of UI dragging-and-dropping and always have the Terminal handy to do things that the Terminal is great for.  If your Terminal is not already running, type <cmd>-<space> in Finder and then type "Term" to get hold of it with Spotlight, then press Enter.  With your fingers on the keyboard you're ready for the Terminal to do your bidding.

Let me demystify the above a bit for those of you not keen on the Terminal:

  • First I change directory to the Mac desktop - we're going to temporarily store the downloaded plug-in there. 
  • Next we use the curl command that downloads stuff
    • I use the -O (that's a capital Oh) to say that the output file should be named 
      • curl will call it after what ever it was on the server I got it from.  
    • Try typing "man curl" to find out more about curl - its a handy tool
  • Then the script has to be made executable with the chmod command
    • if you've managed to get the Python script in the right folder but it still does not appear in GiMP - you probably missed this step.
  • Finally copy the script into place.

To do most of all this graphically is possible, but its a pain.  You'll need to
  • Go to the export_layers plugin web page and right-click on the link to download it to your Desktop.
  • Now you'll need to make the file executable
    • I know of no way to do that apart from the command line - so you'll need to open the Terminal for that.  
    • See the above "chmod" command, and first cd to wherever you downloaded the file to.
  • Click on the downloaded file and rename it to export_layers
  • Now go back to Finder and open two windows.
  • In one, navigate to your Gimp program in the Applications folder, right-click and
    • choose "Show Package Contents"
    • the Finder window will change to a view of the inside of the GiMP application bundle.
  • Navigate down to through these folders
    • Contents > Resources > lib > gimp > 2.0 > plug-ins
  • In the other window navigate to your desktop
  • Drag-n-drop the executable export_layers into place in the plug-ins folder in the other Finder window
Now when you restart GiMP you will find that you have a new menu option under the "File" menu with "Export Layers" > "as PNG" which will do what you need. Note you may find some oddness/bugginess with where it drops the generated files. If that happens, use Spotlight to find them - in my case they were dropped into my home folder.

Bonus Content

There are a bunch of Mac file name changer apps out there. If you're a Terminal master you don't need 'em.

After running the file export my original sprite sheet called "process-working.xcf" had resulted in a bunch of weirdly named files as a result of the Export Layers command. The names were like "process-working_xcf-working-1.png" - where the first part was the file name and the second parts were all the layer names.

for f in *; do g=${f#process-working_xcf-}; do mv -v $f $g; done

This command will strip off the leading characters "process-working_xcf-" part and just leave the layer names. The -v just gives verbose output so you can see what it's doing. You'll need to cd into the directory where the files are located before running it.

This is using the Terminal (well, the Bash shell's) ability to do substring mangling. To find out more at the Terminal, type "man bash" and then a forward slash "/" and then "substr". Press enter a few times until it gets to the stuff with the curly braces. As explained there you can use the % instead of # do strip stuff off the end of the string instead of the beginning. For more complex things you can go from just using to f and g, to h and j as well - and so on - successively picking apart the string as you go.

When experimenting with this stuff it pays to preview your command before you run it. You can do that by prefixing it with "echo" like this:

for f in *; do g=${f#process-working_xcf-}; do echo mv -v $f $g; done

Then you'll get a nice listing of all the "mv" commands that would be run, and you can inspect them to make sure your substring mangling did what you expected. Have fun!

Wednesday, March 20, 2013

Games: Free Stuff, No Matter What the Cost?

XCode's In-App-Purchase documentation - screenshot
XCode's In-App-Purchase API doc

As an Indie game developer my livelihood depends on being able to sell what I make.  What I make has to be good, and then - so the theory goes - people will pay what its worth and I will be able to make rent and go on making games.  In this little article I am not posting because I have the answers - I guess what I'm more interested in hearing about is what people feel about the issues.  In-App-Purchasing - which is made drop-dead simple by technologies and API's like Apple's iTunes one shown here - make it easy to make money, but if people feel that is evil, that then is a thing.  Feelings can't be fixed by technology.

Thing is, a lot of people don't want to pay for games.  This is the so-called "race to the bottom" in game pricing.  One way to deal with the desire for free games, while still making money, is via In-App-Purchase - but there is a lot of contention out there amongst gamers about IAP.  I agree that there ought to be some rational perspective on IAP, but it can cause media spectacles like the kid in the UK who spent thousands of dollars buying virtual donuts on IAP.

I was having a discussion yesterday with a friend about how badly we as human beings do our calculations on what is good value.  We'll crawl over broken glass to get something "for free", even though it would actually be much better value to us to pay up front for it.  Why IAP works is that we "get something for free" and figure we'll have the judgement to not fall for the mechanisms that lie in wait to get us to pay for it.  So why is the games industry so hot on IAP?

IAP as an Anti-Piracy Mechanism


Here's another way to look at In-App-Purchase - as a response to "piracy" of games.  Below I mention the SimCity fiasco and a mention of it in an interesting article by Tommy Refenes which I link to.  That was ElectronicArts trying to do "DRM" by making SimCity players connect to a server - IAP requires connecting to a server to access game content too.  But IAP is not DRM and its not the flash-point rage causing issue that DRM is.  It's like "DRM-low-tar" and we can sort of deal with it, so industry is turning to it big time.

So let's look at this: what is "piracy"?  Note that I put that word in quotes because I think its a poor choice of word but one we seem to be stuck with.

I have some acquaintances who pirate movies.  I smile and shake my head.  One of my friends downloads her movies via torrent and when the file arrives burns it onto a DVD for watching later.  She downloads the color cover art for the movie, and prints it out on her colour printer, and tucks it into the DVD jackets she buys for the purpose.  She feels she has "got something for free" then because she has the same DVD she could have bought from JB HiFi in town, but didn't have to pull out her credit card for it.

But she did have to pay.  All that printing and stuffing about.  Even if you're not a high-rent computer pro your time is worth something.  My point is doing that downloading is not nothing - its a personal investment.  Those bytes come out of your quota.  When you torrent you advertise your IP, and expose yourself to malware.  Then there's the cost of whatever else you have to do to install and maintain the software to do the downloads, and manage and store the content.

My point is that with all these costs, why would folks do it?  Answer: our desire for free stuff.  IAP is clever because instead of defeating the human urge to get stuff for free, its exploiting it.  So - with IAP if we get stuff for free, what's the problem?  Answer - its not free because we shoulder risk.

Risk is a Hidden Cost


Downloading also involves a small but not inconsequential amount of personal risk.  When I was at the University of Queensland doing my degree (far too long ago) the RIAA showed up one day at the IT center with a bunch of lawyers, and a court order demanding the computers at a given set of IP addresses and the hides of the students & staff using them.  I know some people were identified in that fiasco, and I don't know what happened to their careers - I would not want to be part of that.  Regardless of what you personally feel the morality is of downloading, you cannot say that the personal risk is zero.

Risk is a cost.  If you shoulder a 0.1% chance that you have to pay $100,000 - then a statistician or an economist will tell you the expected outcome of that decision is $100.  Its just that as humans we are absolutely lousy at seeing this.  We are crap at figuring out if we really got something for free or if we wound up paying in some way that we did not expect.

I know some of you are pretty clued up when it comes to downloading stuff, and you know how to use torrents and other warez services so that you're not at risk: you can manage all that stuff, and make out like a bandit.  I'm impressed - I would not know how to secure myself against those risks.  I guess I could learn.  But when it comes to getting warez there's lots of folks cleverer than me, I freely admit.

But you know what?  A lot of people feel the same about IAP - they can download the free game and not be hooked in by the IAP.  But plenty of people do fall foul of these things.  I guess all those folks who wound up paying felt they would not be the ones to be hooked - but they were.  Maybe we'll be the clever ones - but we need to ask, how good am I really at assessing the chances?

Maybe I'm drawing a long bow here, but my argument is that whenever we think we're getting something for free, we should be saying "if its too good to be true, it probably is".  Google search is "free" right?  "I never click on those adverts!"  But guess what - millions and millions of people do.  Maybe you've clicked on them and not realized?  How confident are you really that a "free" app won't cost you in the long run?

Buying Up-Front versus the "Never-Never"


I don't have time to muck around searching for warez and freebies - I find it much easier to buy stuff.  I'm not rich, in fact I'm not well-off even - but I can afford to buy a movie or TV program if I want.  Certainly I can afford to buy more than enough for the time I have to watch them.

My friend that downloads stuff - I don't judge her for that.  I just smile and shake my head in wonder because the once or twice I have been at her place and seen some of that stuff the quality is pretty awful.  I know if I'm watching a 100 minute movie I don't want the key part of the movie to have some guy with  big hair stand up in front of the cam, and obscure the best part of the show.

I know its possible to get much better quality pirated stuff, but why should I bother?  I can spend a fraction of the time and buy stuff on line - in and out in seconds from Amazon or where-ever.  I have only once had issues with quality on some DVD's I bought that way - and it was a lousy cardboard jacket that a collection of X-Files DVD's came in.

But the point for me is that watching DVD's is a relaxing and fun thing to do - I don't want to be stressed out trying to deal with all the issues around pirating stuff.  LifeHacker has this interesting article about how to torrent safely - man it sounds like a lot of work.  Some of the best suggestions like using a VPN service may actually cost money, and still don't guarantee your safety.

I just feel a lot more comfortable with my nice crunchy shrink-wrapped thing I bought for some $$$$ and if there is any quality issues I know exactly how Amazon or whoever can fix it for me.

Paying for Games


Does this carry over into games?  

For me it does - I know I personally would much rather just pay up front for a game.  I just don't think in general that I am clever enough to monitor how much I would spend on IAP on games that work that way.  One $0 game is "worth" about the same as any other $0 game - but if I pay $7 for a game - like I did with Bulky Pix's "Yesterday" recently - then I know some things about what I'm buying.  I have some expectations about its quality, the amount of content, and I know if I'm not satisfied I can hit up iTunes for my money back.  That's not really an option with IAP.

Maybe this is a weird analogy - comparing downloading a free game with IAP, to "pirating".  What I am really trying to say is that what we do as humans and as gamers when we "go for free stuff" is always driven by the same desires. 

It's like loans with "pay nothing for 6 months", and credit cards with high limits.  Some people do well on those things.  Most people don't and pay a fortune.  Corporations and fancy marketing guys know how to abuse our desire to get free stuff.  They are awake up to how poor our decision making can be in that regard, and now they're in digital media gunning for our wallets with the same techniques.

As far as "piracy" of digital stuff goes - I think that word is idiotic - it is stupid to compare attacking ships on the high seas to downloading digital content.  I think it is not a crime, its just bad karma.  I think that if companies need draconian laws to protect their business model they are doing something wrong.  And I think that if they make it easy enough and cheap enough to buy good stuff, people will do that rather than pirate it.

No Harm, No Foul?


However: I think "piracy" is not innocuous and its not harmless.  I strongly suspect it hurts you and me more than it hurts Electronic Arts.  I suspect that faster than we can profit from it clever corporate types can turn the urge for free stuff into profit for them.

There is an interesting article about piracy of Super Meat Boy, from Tommy Refenes who was one of the creators of Super Meat Boy, and featured prominently in the indie movie "Indie Game" about the lives of indie game developers.

Tommy is pretty philosophical about piracy, and I agree with pretty much all of what he says.  I agree that if someone pirates 1000 copies of your game you still have infinite copies.  Tommy says "there's worse things than piracy:  like DRM and refund requests".

True that.  However I have a couple of comments.

First I think that the best industry response to piracy - "easy enough and cheap enough" - when driven to its logical conclusion means IAP and things like it.  I don't think IAP is evil, but I do think its very easy for people to spend a lot of money on IAP without being aware of it.  You need to be pretty clever to avoid paying out large on those things - I don't trust myself to be that clever and so I mostly avoid such schemes.  I'm lousy with my credit card - so I have a low limit.  And I just know I'd be lousy with IAP in my games I buy.

I think that our desire to "make out like a bandit" can be used against us by corporations to make a profit and IAP is an example of that.  We can outsmart ourselves too easily this way.

Secondly - you know what?  Ripping off digital content is Just Wrong(TM).  Do you really want to be that guy?  When something is wrong that doesn't make using DRM or laws to try to stop it right or justifiable.  "Wrong" doesn't mean - "let's bring in the DMCA and the goon squad".  Wrong means bad karma.

Play Nice with your Friendly Neighbourhood Indie


Developers of games are people, people like you and me.  People like Tommy Refenes and Edmund McMillen.  Pirating our games is just lame.  Go ahead and do it, why not?  We can't stop you.  Like Tommy in his article all I am going to do about it is say "WTF really?" and write about it.

I understand Tommy's point that there are worse things to worry about than piracy.  But just because you can find something worse, doesn't mean that its harmless.  Just because there's other stuff going on that's bad doesn't make it totally fine.

I'm going to sell my games with an up-front price and hope that folks are OK with that.

I doubt my game will be as successful as Super Meat Boy, and if I fail to make enough money to keep doing games then it won't be piracy that causes that problem.  In fact if I ever get to where my game is pirated that probably means I have finally made it to the Big Time.  :-)

But we're all gamers and I just think that our desire to Get-Stuff-For-Free-At-Any-Cost(TM) is just making our world a worse place to be in, but worse we're outsmarting ourselves when we follow that instinct without watching our hip-pocket.

Thursday, March 14, 2013

Rushy Anim Tut for Walk-cycles


Update: most of what is contained in this video is still valid as far as it goes, however I have now moved to Spine for my in-game animations.  I will still be using AS9 for cut-scenes.

Check the post I wrote about Spine character animation for more details on that amazing tech.

---

This is a very quick export of first walk-cycle animations, showing a bit of how I work.  I'm still in the middle of working on this so its rough, but I thought I would take this moment to cover what I have learned for my in-game character animations.

First can I say that AS9 Pro is very good for this job.  Combined with TexturePacker this process gives you a set of sprites in a sprite sheet that you can drop right into your Cocos2D game.

The horizontal lines show my method for getting the walk correct.  I recommend this excellent tutorial on the fundamentals of the walk-cycle at AngryAnimator.com - refer there for the meaning of the pose names and to explain the lines.  That tut is for pencil-and-paper cel animation but its by far the best of any tutorial I have seen yet.  The best insight it has that you need to base your cycle around the contact pose, which is when the legs are at their farthest apart.

There are some differences taking Angry Animator's method to the 2d-bone animation technique, but most of it is the same.  In the computer-animation your big bug-bear is skating/sliding.  To fix this I do the animation with a translation (so the character moves across the room as well as pumping his/her legs) and this allows me to mark the foot-falls and retro fit the feet to the marks.  This seems to fix skating quite nicely.

To get my sprites the right size I use one of my game rooms as a background and then I can position the character at the largest size it will need to be against that room.  Then when I do the export the Anime Studio camera is set at the same size as the background, so the PNG's that are exported have the character sprites at the correct size.  Because I use TexturePacker I don't have to worry about the vast amounts of transparent pixels all around each PNG frame exported: TP will remove that and pack the actual sprite into the sheet.  (Note, I have made a terrible job of this part in the sample files shown here -   but they are just for illustration only).

Having the game background also allows me to do the sprite sheets for other animations such as sitting down on the bed, reaching for the window and so on.  Here I'm just talking about the walk animation.

Here is my process:  I do my animations as a walk with translation by:
  • Set the animation marker to frame 0
  • Draw and rig the character
  • Draw the guide lines on a seperate layer based off your character
  • Pose the bones to the contact pose; left-leg in front
    • This counts as your first step/foot-fall
    • Mark its position on the guide line layer
  • Measure out 3 more strides to find the foot-fall points on the guide lines
    • Temporarily translate the character in its contact pose
      • Using legs & feet like a pair of dividers
      • Mark each foot-fall positioning the back foot at a mark
      • Then do mark a new foot-fall at the front foot
    • To mark I use Anime Studio's "note" feature
  • Translate the whole character so that the 4 strides take 48 frames by
    • Move the animation marker to frame 48
    • Translate to the final marked position at 4 strides completed (4 steps/foot-falls)
    • Don't use bone translate for this - use whole-character-layer translate
  • Go back to frame 0 (contact pose; left-leg in front)
  • Copy the contact pose at frame 0 to 24 and 48
  • Create the opposite contact poses at frames 12 and copy to frame 36
    • See Angry Animator's tutorial
    • Use the Z move bone tool to switch the legs over
    • Keep the character at the same height
  • Now add the recoil poses at 2 and copy to 26
    • Use the translate bone  on the root bone (not the whole character) tool
    • move the character down to the lower guide mark for the head
    • The recoil is the lowest pose so head-height  should be checked carefully
    • Adjust the feet to the foot-fall marks so they don't skate or slide
    • Adjust the legs to the "sink" pose so the feet are still on the lines despite the lowering
  • Copy the recoil pose to 14 (and dup to 38)
    • Copying key frames makes sure you get the height & attitude right
    • Switch the legs front-for-back to get the correct opposite pose
    • Make sure you don't change the height of the recoil when doing this
  • Do the high-point at 8 (and copy to 32)
    • As for the recoil use translate bone on the root bone to move character up
    • Copy these forward as for the recoil and switch to get the opposites at 20 & 44
  • Do the passing pose at 6 (and copy to 30)
    • Do the opposite passing poses at 18 & 42
  • Add in hand-arm swing, bending the elbows
  • Add in some head bob, and other movements
    • I did ponytail up in the recoil and down in the highpoint
Once complete, run the animation through on loop mode over and over, looking for timing issues, mistakes and unevenness.  Tweak as necessary.

I find its impossible to do this without the translation in the animation (as above) especially with respect to removing/reducing skating, where the characters feet slide or "moon-walk" across the ground.  Also, even though technically you could do all the above in 24 frames instead of 48 I find it much easier to have the extra framing so I can see what I'm doing.

Once everything is golden, you're ready to create game art.

Choose the key frame channel for whole-of-character translation (not bone translation) and delete it.  This will remove the character animation that does the travel across the room, and leave all of the bone translations and rotations done for the walk-cycle itself.  If this somehow removes your height adjustments done for the recoil or high-point poses (because you used whole of character translate instead of bone translate) then undo the delete, and go back - carefully remove the bad keys and replace with bone translate keys.  See the above.

At this point playing the animation should show your character doing a 48 frame in place walk-cycle, with nothing else on the screen.  Now to export game ready art, hide the guide lines, any background images used for scale and go ahead and choose "Export Animation".

Select the PNG exporter from the drop-down.

You only need to select 25 frames of the above animation.  I do a full 48 frames so I can select the part that looks good, and because I find its easier to check the animation for errors.

If you go with the passing pose as your start frame then it works well with a standing character moving into a walk because the feet are together, and then one picks up and starts walking.  To do that, in the export dialog choose 18 as the start frame and 42 as the end frame.

At this point you also have the choice to export at half-frame rate by checking "Render at half frame-rate" on the export dialog.  This will give you 13 frames when exporting frames 18 to 42, and 12 frames per-second is probably OK for most games.  If you need 24 frames a second leave this box unchecked and you'll get 25 frames.

Run the export, choosing a folder (use create folder if needed) to put the frames into.  Don't worry about background colour - PNG export by default will alpha out all the background for you.

Now you can use Texture Packer to put the frames into a sprite sheet, by dragging and dropping the folder you exported the PNG files to.  Follow Ray Wenderlich's excellent tutorial for this - I won't repeat the details here.

The sort of result you get is as here (although this is a PNG sheet).  

Note that I have done a power-of-two sheet with my crazily large sprites.  This sheet is 2048x2048 (fine for desktop but bloated for mobile).  You can (and should) do a non-power-of-two (NPOT) sheet if you know that your platform supports it.  Most new platforms do.  Also using the pvr.ccz compressed PVR format will give a good result in sprite sheet size with fast loading times as well on mobile - check the Wenderlich tutorial for more details.