Sunday, December 15, 2013

The Great Big List of Things That Tick Me Off with Windows

Hi Friends.

I am a software developer, and I have a lot of "power user" uses for my computers.  I ask a lot of them.  Over the years I have found that Mac OSX gives me the least amount of pain, and the most amount of productivity.  I use Mac OSX for all my software development work, and I quite like it.

Often I have to make my software also work on Windows, so for that, I use VMWare and run a Windows instance which is virtualized.  Its pretty nice: I can switch between Windows and my Mac with a key-press; and when I don't need Windows its harmlessly stashed away as an Virtual Machine image on my Mac's hard-drive.

This works well for me, but every time I have to summon up Windows again, I am reminded of all the Things That Tick Me Off with Windows.  Its especially bad when I either have to upgrade to a new version of Windows - which I periodically am forced to do even tho' I had just got the last version doing what I wanted.

Hell is a Windows Upgrade
The Dummies Cover Generator


Normally, what I do is I say philosophically to myself - "Y'know, Mac has flaws too - some folks like Windows, I will just keep my thoughts private."

But lately I have come across a lot of folks who are starting up the pointless religious wars about Mac vs Windows, and coming out with a bunch of criticisms of Mac, which amount to
it ain't like Windows
Lately its getting hard to be philosophical about it because people seem to struggle with the notion that Windows is not some kind of de-facto standard for the way computers ought to be.

You used to hear people say that Microsoft Word was the "de facto" standard for documents.  Nowadays, not so much.  Those people got cured of such nonsense after Microsoft screwed them over with multiple changes to Office, then the arrival of Windows 8.

If it is not like Windows, then y'know what?  That alone is not enough of a reason to say its no good.  Maybe it is no good, but anyone want to bitch going to have to come up with a better justification for their claim.  Besides, these days Windows is not like Windows.  You have to do a bunch of things so that it is.

So I decided I would come up with my own list of things like.  I am going to be petulant, and narrow-minded, and generally stamp my little feet.

I know I ought to try fairly hard to not fall into the same behaviour I criticise in others where I mark it with a "fail" just because it fails to be what I'm familiar with.  But sometimes I think the way Mac does things is very good, and so in those cases, forgive me but I am going to get out the red pen.

So here then is my Great Big List of Things That Tick Me Off with Windows - and I will return to this post and update it with any new ones.

The Terminal is a red-headed step-child on Windows

  • As a developer I use the Terminal ALL THE TIME.  
    • It has to be a keystroke away
    • It has to be fast, flexible and full-screen
    • It has to have a powerful, expressive shell for commands I type
  • On windows I cannot get a full screen terminal window
    • cmd.exe never wants to give me a full screen
    • I futz about with setting the number of columns and rows
  • And the standard shell is crap - cmd.exe is NOT a decent shell
  • What the hell is up with having to right-mouse-button to paste in the shell?
    • To get even that requires drill down to "Quick Edit" mode via the window menu
  • I don't care that there's Powershell or some third party thing
    • When I upgrade Windows as I have done many many times
      • I don't get a Terminal by default.
    • With both Mac and Linux ITS RIGHT THERE OUT OF THE BOX

The Windows 8 Metro UI

  • Need I say more?
    • I have to do what now to kill an app?
  • I don't really care about the start menu
    • but finding and launching an app is a jungle

The Windows explorer is an App

  • Why do I have to start the Explorer?
  • Users are expected to use it to move files around but its not already running
  • Zip file integration used to be eye-gougingly painful
    • Now its just bad
    • Why does double-clicking a zip file take me into some bizarre UI?
    • Why am I now inside some mystical folder/app that's really an undead PKZip clone?
      • Just double-click and unzip, right?
      • And why soooo slooowwww to unzip?
    • Also - why is it so hard to unzip from the command line?
      • on Mac: "unzip filename.zip"
      • Gaaaaah!

Viruses and Virus Scanners

  • Together they are the death of any CPU performance
  • Yeah, I should probably have a virus scanner on Mac, but
    • I don't torrent and I don't use Java so...
    • the only "drive by" exploit for Mac so far is not one that would have affected me
    • I know in theory Mac's can have viruses, but in reality they're a constant pain on Windows and not something I worry about on my Mac
OK - enough for now.  But don't worry - I will be adding more totally unreasonable dummy-spits here in the future.

Stupid Idiotic Delete/Move

I right-click a large folder and click "Delete".  Does it get deleted?
No, it tries to "Move it to the Trash".
Then it tells me after 40 minutes of trying, that its "Too big - go ahead and Delete?"
Sure - that's what I asked for in the first place.  
Now it displays this nonsensical dialog where it reports how "fast" it is going with its delete process.  
Gaaaah!!!!  WTF!!!!!

I have heard a lot of people complain that with the Windows File Explorer you can right click and cut, then paste into another location.  I can do this fine on Mac, just by having two Finder windows open.  Try it - works perfectly: drag and drop.  

What else works fine on Mac is deleting, and moving - on Windows we have to apparently make a song and dance about it, with progress bars and dialogs going off everywhere.  

To be fair, deleting on the Mac will send stuff to the Trash, instead of actually deleting it.  But on the Mac I have the Terminal and "rm -Rf ~/Documents/crap_i_dont_want".

And everything to do with large folders is so incredibly slow and painful, even allowing for the virtualization it takes orders of magnitude longer to do file operations on Windows.  

Thursday, November 21, 2013

Tech Project Survival Guide

Right now I'm working out of River City Labs and meeting a lot of folks who are in start-up mode.  Full of entrepreneurial spirit, in some cases backed by other peoples cash, and all finding themselves with varying levels of skill in managing a technical project.

To try to do a an ultra-dense, nutshell presentation that compresses the top few tips I have learned about getting a tech project to success, I decided to try out PowToon.  It needs some work, but have a look and see what you think.  I may yet replace the music with a voice over.

My talking points about what I wanted to say are summarised below.  At present the video does not have voice, just the music that came with the PowToon software.

  • Tech projects involve 
    • project owners who have an idea they want realized
    • and technical experts who think in terms of what artifacts are needed
      • there is a natural tension that can result in bad outcomes
      • if you are the project owner YOU must work to fix this
      • YOU must make sure communication channels are working
      • good tech experts have lots of work to do without doing your job for you
  • As a project owner its tempting to think of your idea like a plan for a house
    • it can simply be built like other houses
      • you don't need to specify everything
      • we'll come back when its all done
    • but technical projects are not like that
      • a technical project is more like a journey 
      • project owners and tech experts must travel together
      • your spec not a house plan, is a chart into unknown territory 
      • and it will have to handle change
  • When your project is on course, completed code is piling up
    • maybe you have an in-progress app or a website 
    • that means NOTHING without the code
    • the code is what makes your screens & web pages actually work
      • without it you have nothing - what if your developer leaves?
      • no more changes can be made - the whole site/app will need to be rebuilt
      • project owners MUST track the code that is being written for them
      • NOT OPTIONAL - you MUST do this, techie or not
    • successful tech projects put their code & other artifacts in source control
      • if you already know source control, then good: 
      • if not learn:
      • NOT OPTIONAL - you MUST do this
  • Join the crew, be part of the technical team.  
    • Check your project plan - its your map of the planned project course
      • But reality is not the plan.  The plan is an idea.  It may need to change.
    • As a project owner you are expert in the goals of the project, and 
      • your technical crew are expert in the tech needed for the implementation.  
      • the cleverness/coolness of implementation comes AFTER meeting the spec
      • work to get your features the best way within the technological constraints
    • Don't treat them like "resources", and 
      • stay on board with them.  
      • Earn their respect
        • just paying on time is not enough to achieve this.
    • If you have your head in the project plan and don't talk with your team 
      • you will blow off course and your results will show it
  • Iterate with your team.  Daily.  Weekly.  Watch the artifacts pile up.
    • Check your implementation against your spec.  Look for gaps.
    • Keep your charts up to date, and map your current location.
    • Know where you are every day.  Avoid surprises.
    • If for some reason you can't be at the helm
      • find a trusted project manager
      • with no-one at the helm you'll go off course & the project will founder
In summary - if you are a project owner, don't just give your technical project team a brief and tell them to go for it.  Your idea is mostly in your head, and your technical team is not psychic - if you want the project to fulfil your vision you have to work with your team throughout the duration of the project.  Creating ever more detailed project spec's is one answer, but its no substitute for communicating with your team, checking in every day, and making sure you're on track.

This allows you to work with them to make the implementation fulfil your goals.  Your plan will likely need to change - maybe there are cheaper, easier ways to get something done technically that achieves the same goal business-wise.  You'll never know if you are not on-board with your team, working with them.  Course corrections can be made before you drift too far off track.

And.  Use source control.  Even if you're non-technical, learn what it is, why its used by every successful project; and how to access at least the web-console for your source control "repo".

Sunday, August 25, 2013

Change of Gear

Hear ye, hear ye.

I'm moving for a time into a part-time game development mode.  This means I will be time-slicing my game dev activities into a working week of contract and freelance $$$ generating work.

Initially at least I'm planning to do quite a lot of revenue positive work to get some things kicked off again, and that will mean not much game dev output for a month or so.

Longer term it means I get to continue my game development, not go crazy with financial and other constraints, and I can work on EthEx2080 and other games in a sustainable way.

The good news for me personally is that this is a circuit-breaker that allows me to take the pressure off getting EthEx2080 out the door prematurely, and with the quality impacts that that entails - as I don't need it to start paying for itself so quickly - and it also lowers my stress to a manageable level.

Will I complete it?

Yes.

I am absolutely committed to finishing EthEx2080, but the release date will be quite a bit later than December 2013.

When exactly?

I don't know.  Not a mystery or a problem - its just a case of having to find out what my rate of game dev output is once I settle in to this new part-time model.

Since I will be able to justify investing in some freelancers to do art and other content for the game, that will shorten the schedule; but obviously the lesser availability of my time to code and do the other work required will lengthen it.

I will do a new project plan once I work out how fast I'm getting through things, and that will allow me to extrapolate forwards.

Thanks to everyone who is following me, and has been encouraging me - I hope y'all keep doing so as it really helps when getting through the hard yards.

Keep posted, and happy hacking!

Monday, August 19, 2013

Cocos2D & CocosBuilder Version Decoder

Just now I got a great question from a viewer on my YouTube channel about Cocos2D & CocosBuilder versioning.  I'm going to post my answer here as it might help a few folks.

CocosBuilder icon - see below for CocosBuilder project URL
CocosBuilder for the Win!

Versions

Versions in Cocos2D can be really confusing - and its no fault of the Cocos2D guys as the stack is a collection of Open Source projects and as such the different components do not have nicely matching version numbers.

For example, right now, you need version 3.0alpha of CocosBuilder to work with version 2.1 of Cocos2D.  You read that right - v3.0 of CCB goes with v2.1 of Cocos2D.  They are different projects and although the guys are working hard to make coordinated releases now, its still confusing.

If you're using the stack I do, which is CocosBuilder and Cocos2D-iPhone then it's easy to get hold of the wrong software packages and get weird errors, with undeclared variables.  Another issue you can find is that at run-time you get an error saying that the CCB data files are from an incompatible version of CocosBuilder.

See my previous post on upgrading versions for a video about this issue and some tips about navigating the versions of Cocos2D.  Executive summary: use the Cocos2D-iphone blog posts to find the latest "coordinated release".

As I write this, for example, the versions you probably want are:
These should work together just fine.  Obviously you'll want to use the latest "known good" combination (which might be later than the above depending on when you read this post!).

Release Quality

Another issue with versioning is that while Cocos2D v2.1 has been in "release candidate" for a little while, and we've seen version quality tags like v2.1rc1 or similar as a result: now v2.1 is out and we are back to a major dot-point release.  So nice work by Ric and Birkemose and the guys for getting that up to release quality.

But: we are still in alpha on CocosBuilder - if you're like me you want to work with more stable software.  However here we have to bite the bullet and work with 3.0alpha, at the time of writing, because that is the matching CCBReader for Cocos v2.1.  It is what it is and I guess Viktor Lidholt and other volunteers are working hard on CocosBuilder with what time they have spare to get it out of alpha.  I have not found any real issues so I suggest ploughing ahead with the 3.0alpha builds at this time.

Using the CocosBuilder Source

Note that the link to CocosBuilder above is to the "full source code", not to the "application".  Once you unzip the CocosBuilder full source code, drill down into the CocosBuilder directory with Finder to locate the CocosBuilder.xcodeproj file and double-click that to open it in XCode.  

Once open in XCode you can get your shiny new CocosBuilder binary by selecting the target "CocosBuilder" > "My Mac 64bit" from the Schemes drop-down (top-left in XCode, next to the run & stop buttons) and pressing "Run".  Once CocosBuilder is running, right-click on it's icon in the Dock and choose "Keep in Dock" so you can find it again easily.  

If you lose track of it, its stored under the "build" sub-directory of wherever you unzipped your sources.

Why go through all this if you can just download the binary?

I do it this way so I can be sure I have the matching sources.  If you're just building HTML/Javascript apps, and don't care about iPhone you don't need the sources and can just use the pre-built binary.  But to work with ObjC on the iPhone you need the sources.

Could you download the pre-built binary AND the sources?  Sure.  I don't have masses of room on the SSD on my laptop so I try to save a bit my just building out of the sources but you can use the pre-built binary if you like - just make sure you get the matching one for the sources!

I also like that under the CocosBuilder unzipped source tree you'll find a full documentation set; the Cocos Player application is there and also the full sources to the Example applications.

To get the correct CCBReader that will match your CocosBuilder, use the one from the Examples.  In the case of the above the folder you want is at this path:

$unzipped_source_tree/Examples/CocosBuilderExample/libs/CCBReader

Possible CocosBuilder v3.0alpha5 Issues

One final note, is that there seem to be a couple of new experimental features like the image previewer pane, on CocosBuilder v3.0alpha5, which seemed a bit clunky - hence I am actually currently using v3.0alpha4 which I find works just great for me.

I haven't reported those issues because I have just been too busy to spend time isolating them, but if you try v3.0alpha5 and see a problem take a screenshot and report it on the CocosBuilder GitHub.  You can probably revert back to 3.0alpha4 until the problem is fixed.

Thursday, August 15, 2013

More progress with Spine

I've been working on importing Erin into Spine so that she can do all the things I need her to do in the game, like reaching for things and climbing on things.

Update: adding in the front-quarter walk-cycle animation.  There are 5 different spritesheets: front, rear, side, front-quarter, and back-quarter.

The quarter and side ones are flipped in X to give a full 8-way facing character.

Here's a GIF export straight from Spine showing the walk cycle from the front.

I find the front walk cycle particularly hard because instead of just being able to use just limb rotations, you need to do a lot of image switching and scaling.  Scaling is used to make the rear-ward leg in the walk have that limb and foot appear to go back and up.

Notice also the feet:  as the leg extends towards you the bottom of the foot becomes visible.  This does not come for free.  It is done by swapping the foot image from a top down one, to one where the foot is viewed from below.  Its a different sprite altogether and I tell Spine to switch one sprite for the other at just the right moment so that it looks completely natural for the walk.

The image switching is also used for the eye-blink that happens as Erin's right foot hits the ground.

I am pretty impressed by Spine so far - it really is a pro bit of software.  Just wish it had been around a year ago.  :-)

This video published recently on my YouTube channel explains some of the thinking behind the move to Spine, and also compares the previous tech stack's deliverables with that of Spine.


I didn't show it in that video but here below is the Spine sprite sheet:

...amazingly compact, hey?  Especially when you consider that with this set of sprites I can use Spine to create any animation I want, for example Erin reaching down, scratching her head - that is to say an "idle animation" - or anything else I need.

Friday, July 26, 2013

Upgrading a Project to a New Version of Cocos2D

A short video tutorial on this subject, since I just had to do this job myself and its not entirely obvious how to go about doing it, or how to solve some of the problems that can occur.


To check out the project used in this tutorial have a look at my earlier tutorials on Lua (linked in the panel on the right) and you'll find a reference to the GitHub repo where you can download the source.

Just to help Google searches finding this post:

  • CTFontManagerRegisterFontsForURL link error?
    • you need to add CoreText framework as this is a new dependency for Cocos
  • CCFontDefinition symbols not found link error?
    • you need to "add files" and re-add the cocos2D libs directory
    • there are some new .m files which are in the distro but not added to your project
Link errors when upgrading Cocos2D are probably due to these issues - new files and dependencies.

See my video above for how to fix 'em!

Sunday, July 21, 2013

Room to Room

This new progress update video shows a bit of a milestone with our animated door sliding open and our heroine able to move to a new room.



I did all the room background artwork for the apartment a few weeks ago and I have been coding like a demon since then ironing out all the issues with moving from room to room and persisting the game state across view and room changes.

For those of you who are coders you might be interested in this aspect of CocosBuilder and Cocos itself - since it is scene based, and your scene is effectively your entire user-interface, moving to a new room basically tears down the whole UI, and it has to be rebuilt again from the CCB file for the next room or view.

This makes for some fun and games when an item has been modified in one view and you need it to reflect those modifications in a new view on the "same item".  Like wise with items that have been added to the inventory, and which to not appear in the next view.

Lastly of course the actual opening of doors and the logic with the character having to wait for the door to slide open before walking through had to be done.

This is done with action queueing which also took quite a while to get working properly.  So for example the sequence to go through to the walk-in-wardrobe is
  • player taps the door to the wardrobe and says "Go"
  • queue a GoTo  action to the wardrobe room
  • that requires the door to be opened first so...
  • queue a GoTo the door
  • queue a Open of the door
  • when the door open occurs it plays an animation of it sliding open
  • finally execute the action to go to the wardrobe
This is all now working.  Whew!

Wednesday, July 17, 2013

CocosBuilder and CGPaths for non-rect Tap Detection

This is just a short post to frame a video how-to on detecting taps for selection on touchscreen devices, using CGPaths - and how to create those CGPaths using CocosBuilder.



What this essentially does is makes CocosBuilder into a tool that you can use to create non-rectangular bounding paths for tap detection.  As a bonus, I show how you can use the CGPath information to create a blue selection sprite image to signify the active selection in the UI.


I reference Bob Ueland's excellent CGPath tutorial, and that does include some code that you can use for the actual hit test.


For the extraction of the CGPath data from the CocosBuilder file I am not posting my code for cutting-and-pasting but if you've followed my earlier tutorials and are building your own game in Cocos2D you should have enough knowledge to follow what I have done.  It is just simply a case of traversing the nodes and using the standard method to build up a path from the CGPoint information stored in the CCNodes.

My technique for creating a selection sprite from the CGPath data is also not tricky - just check the documentation.  Give it a try and if you get really stuck feel free to ask a question here or on G+.

Hope it helps, and enjoy selecting stuff!

Sunday, July 14, 2013

New Climb Animation Sequence

I've been working on a climb animation for our heroine climbing up on to a high surface, which she does in a number of the "puzzles" in the game. 



Here she has to climb on the bed to see a screwdriver sitting on the window sill. The new 38 frame animation dovetails pretty well into the walk cycle, but there is no way to split the character into two so her front leg is "on" the bed while her back leg is behind it. 

If Spine can do that then that might be a compelling case for switching to it finally.
This is what the frames of animation look like in TexturePacker, as a sprite sheet.



Currently that is my pipeline, and of course switching to Spine would mean a big change in workflow - I might be able to reuse the artwork out of Anime Studio (which is what I animate in, and then generate PNG frames from) to create the Spine pieces.

If I do go for Spine it might have to be after I get this Beta done for early August - I'll never hit that date if I have to change now.

Wednesday, July 3, 2013

Head down, tail up - its modelling time

I'm working very hard right now trying to hit my self-imposed deadline of August 12 for having the beta ready.  That means getting all the rooms for the apartment done.

Coding is coming along well and I have killed a bunch of bugs that were stopping things working with the inventory and moving around.

This week I'm modelling the remaining rooms - which is basically the exterior of the apartment, the balcony that is, and the interior of the living room/kitchen/lounge area.  This is the area where the encounter with the "killer" character occurs and puzzles must be solved to successfully set up traps and avoid character death at the end of the first act.


This is one of the first renders and needs lots of fine tuning before I use it in the game.  But this basic scene is going to be used to introduce the killer character who comes climbing up the exterior of the building to attack our heroine.

I used Maxwell Render to do this, from a model that I built up from scratch using Sketchup.  The design for the apartment is from my original drawings.  The concrete texture and (a bit hard to see here) the wooden tile texture for the floor are all Maxwell textures - which are pretty good.  I haven't put an arris on the edge of the concrete balcony or sunshades - that probably needs doing so it matches the concrete elsewhere.

Anyway - good progress.  I have already modelled the whole internal area of the apartment so the rest of the week will mostly be fiddling with lighting, fixing up details and adding polish, while I run renders of all the views.

Tuesday, June 18, 2013

Progress update video

A thing or two dropped into place today so I thought I'd upload this progress update video showing where things are at with my game, EthEx2080.

Apologies for my halting voice-over - I am a bit weary but I get there in the end.  :-)

All constructive criticism is gratefully received.

Please bear in mind that nothing is carven in stone at present, especially the character look and animation.  I am looking at changing over to Spine for that which will give me an opportunity to redo the vector art from my original Anime Studio work.

I want to give our heroine a slightly softer look - she's kind of a hard-nosed type at present!  Also the way the vector art came out trying to allow for the face animations and neck movement made the line around the face heavier than I wanted.  Anyway - you get the idea.

By the way - if anyone followed my presentation on Lua scripting you can see a bit of that coming through here in how the game text is generated from the state of in-game items.

Let me know what you think.

Monday, June 3, 2013

Script your Game with Lua

This is a video tutorial series, based on a presentation that I did recently at the Brisbane Game Technology Group.  Big shout out to Ash and the guys there for an excellent local tech meet up.

Its about how to add in support for scripting parts of your game in Lua.  I'm not here trying to teach how to code in Lua - there's other great talks about that.  This is also not a tutorial about how to write a game in Lua - which is something you can do these days, especially with frameworks like Corona.

This tutorial is however for you if you have a game written in Objective-C, or in C++, or possibly even a Unity game, and you want to know how to start using Lua snippets or scripts in your game.  You might want to do that because:

  • you have content creators working on your team who need to add game logic
  • you have text based assets that can use scripting to add functionality
  • you just don't want to have to implement everything in a compiled language
  • you want to add configurable behaviour to some game elements, like special AI
As a case study for this tut, I added some AI - albeit very simple chasing behaviours - to an open source tutorial project done by Viktor Lidholt, maintainer of the CocosBuilder project.  Viktor's excellent CocosDragon tutorial had just the right mix of content, so I did some improvements to it, and then used that as a base for adding in some unit AI, via Lua scripting.


The tutorial is presented in Objective-C for the iOS platform, but some of the techniques will trade over to other platforms.  Please let me know if you come up with a recipe for C# that is reliable and I'll reference it here.  There are sources out there for doing that, but I haven't been able to verify then.

To save you having to peer at the code on-screen, or type it in manually, I have made the whole tutorial available as a GitHub repo, so you can download it from:  The code for the tutorial can be downloaded from here: https://github.com/sarah-j-smith/LuaTut

The presentation was over an hour, so as a screencast with <10 minute YouTube segments its as a result in 8 parts - I have tried below to break these into functional components so you can go straight to the parts that interest you most.

But to get the full context, and to learn the knowledge behind the "do this, then do that" instructions it is a great idea to go through all the videos.  If you have some questions, or something does not make sense when you just skip to the video that sounds most interesting or relevant it may be because that content was in another section.

Part 1 - Intro, Context, Scope of Tut, Why Use Lua? - Security Issues



Part 2 - What's Covered?  What do you mean a "Lua API for my game"...?



Part 3 - Coding begins.  Showing the goal project with AI scripts.  Getting Lua inside.



Part 4 - LuaEngine class - the main integration point.



Part 5 - Lua Runtime, reading a config file



Part 6 - Beginning a scripting API for Lua to call into your game, embedding scriptlets



Part 7 - More scripting API, API registration and using full scripts for game objects


Part 8 - Implementing the rest of the API, review



I hope the material here is useful, and I would love to hear from you if you wind up integrating Lua into your game, or even just try out some of the ideas here.

I'd like to thank the folks that make their work available for free including Viktor Lidholt, and Ric Quesada - the guys behind CocosBuilder and Cocos2D-iphone; and also the authors of the free music and graphics (see the in-game credits or the github project for those).

Please let me know if you find any issues so I can fix them up.

Happy game hacking!

Tuesday, May 28, 2013

Avoiding Name Collision for your Sprites

In Cocos2D when sprite sheets are imported the sprites within them come in as - for example - "alarm-clock.png" where this was the original name of the image, before it was composited into the sheet.

I believe Unity and other programs that use TexturePacker work a similar way.

So where is the problem?

Well, what if you have two different alarm clocks?  Or two different images for the same clock?

Collision avoidance!
Even if you have different sprite sheets, all images go into the same name space and because you are not using any kind of directory structure - that was all lost when it was imported into Texture Packer - then you have an issue with name collision.

You have to start prefixing the alarm clock with "blue-alarm-clock.png" or "alarm-clock-1.png" but then it becomes a tussle to figure out what the original clock was, maybe still just named without any prefix.

It becomes very easy for one sprite in your game to wind up being substituted in for another without you realising it and unless you test every branch of the game, you might not notice until its too late and the game has shipped already!

Here's a quick way to disambiguate your images for your sprites, that uses the command line on the mac: embed the sha1sum signature of the image into the filename.  That way as long as the image is different it will have a different file name from any other image sprite file in your game guaranteed.

The key to it is the shasum command which is installed in Mac by default.  If your version of MacOS doesnt' have "shasum" you will probably find that an equivalent tool is installed that you can use - try md5sum or similar.  Same if you're on Windows using Cygwin or minGW-sys.

Here's the code we're going to use, laid out on different lines:

for f in sprites/*.png; do 
    g=$(shasum $f)
    h=${g:0:7};
    b=$(basename $f .png) 
    d=$(dirname $f)
    echo mv -v $f $d/$b-$h.png
done

What this is doing is getting the variable "f" to take on the string value of every file name in your sprites directory that ends with ".png", each time through the "for" loop.  Inside the loop, we store into variable "g" the sha1sum of the file which is a long string that looks like this:

~/Documents/Artwork/seperations-game-ready/main-room sez$ shasum sprites/alarm-clock.png 
1dcd66fcb214b1875ebd28cff83dedf83960707  sprites/alarm-clock.png

Since we only need a few characters from the long sha1 string, the next line is getting a substring of our g variable taking the first 7 characters only.  That also conveniently ignores the trailing filename which is repeated.

Finally we use the basename and dirname built-in bash functions to get the parts of the file name that we need, so we can stitch it back together in the move command.

Note that as per my usual practice I use "echo" so that instead of the move actually executing it just prints out what it would do.

Now we can run this command by opening a Terminal session, changing directory to the directory containing our sprites directory, then run it all on one line like this:

for f in sprites/*.png; do g=$(shasum $f); h=${g:0:7}; b=$(basename $f .png); d=$(dirname $f); echo mv -v $f $d/$b-$h.png; done

You should be able to copy the above line from your browser and paste it into your Terminal session as one single line, with no wrapping.  It's for that reason that I have used the (otherwise horrible) 1-letter variable names.

Where I have "sprites" as the directory name substitute in your own directory name if needed.

Carefully inspect the output of the echo'ed out move commands and if necessary, up-arrow and edit the command until it works the way you like.

Then finally up-arrow, arrow back and remove the "echo" and press enter to execute it for real.

If the command works, then you should see the "mv -v" spit out a line for each file looking like this:

sprites/alarm-clock.png -> sprites/alarm-clock-1dcd66f.png

If you had 10 sprites you should see 10 lines like that you should now be able to check your sprites directory and find a nice list of completely distinctively named files, guaranteed not to collide.

Happy spriting!

Thursday, May 23, 2013

Early Results with Artboard

I've started using Artboard, a fairly simple vector graphics program for the Mac, to do some of my in-game artwork.  Basically I put my room render in as a background so I can get the scale and perspective right, then draw the artwork for the items and props in the room over the top.

I have been using Anime Studio and Manga Studio for this, at various times.  I use Anime Studio as its the vector graphics based animation package that I use for doing my characters, and I need that same look for the in-game items.  Trouble is since its an animation package its not well suited to just doing static graphics.  I therefore was using Manga Studio which is my comic drawing software - it gives lovely pen strokes and cel shading as per Manga comics, but unfortunately the resulting look is not really a match for the vector art that comes from Anime Studio.

Hence I have picked up Artboard, for $35 from the AppStore.  I would have looked at Illustrator but its very expensive and over-featured for what I want.  I also tried Inkscape and that would have been my preference but the performance going through X-Quartz on the Mac was just awful.  On bigger drawings that pen lag was just killing me.  Artboard is a nice combination of features and for price, and has great performance on my laptop.

Here's some of the things I have done with it so far.

Alarm Clock to wake our hero up out of bed

Handy screwdriver

Room render with Artboard drawings on top
It's not perfect, but there is a lot to like here.

I particularly like the expert styles - I used the ability to create copies of the stroke and outset each one to create the sort of "bevelled-in" look on the dial face for the clock.  This stroke was stacked on top of one of Artboards pre-packaged styles, a glossy black which was just right for the face of the clock.

The point editing mode of Artboard is very good too - you can quickly go from shape manipulation mode over to path mode and back again, just by double tapping on the object.  In Inkscape its not so easy to go between treating an object as a path and as a shape.

I have come across a few bugs, but the authors of Artboard - one of whom is an Australian software engineer - seem to be quite responsive, and they're producing new releases so it looks hopeful that these will get dealt with soon.

If you're looking for a simple but relatively powerful and fun graphics editor for your game work I recommend giving Artboard a try.

Wednesday, May 22, 2013

Pro-style Placeholder Image for Chooser Dialogs

I have been busy with my game development so my blog and tut video stream have been a bit quiet.


Meantime here's a quick video tutorial on creating one of those nice "chiselled grey text" placeholder images that make an image chooser dialog in your game or app so much more pro-stylee.




For this sort of job I often use the GIMP which is a great piece of open-source software and for me one that provides all the functionality I need in bit-map graphics for game development.  To get GIMP for the Mac, go here: http://www.gimp.org/downloads/ and click Download GIMP 2.8 to get Simone Karin Lehmann's build - the others I find are often missing stuff and don't work nearly as well on Mac as her builds.

If you work through the tutorial and are looking for more here are some things you can do that will give some extra nice polish to the chiselled text placeholder.

Carefully color match to your dialogs background.


You can try to get the GIMP to produce the same color for its image background as your dialog, but because of the way the map filter works with the "compensate for darkening" not always being accurate, I suggest instead setting up your GIMP image to be as close to the color you want as possible, and then adjust the dialog background color in your UI designer.  On Mac you can use the magnifying glass on the color chooser to pick up the color of the image:



If you're using XCode for example you can navigate to the color chooser for the background color of the dialog, and then click on the magnifying glass and go across into the the Preview app which you have open alongside showing the image with the color you want to match.  Then just click to sample that colour.  Your XCode dialog is now the exact same background color.

Change the Look of your Chiselled Text


Try applying a blur to your black text after you've typed it in, but before you use it as the bump map.  This will cause your chiselled letters to have a more rounded look instead of the straight sides.  Depending on what you want it might look good in your app or game.

You can also play around with the settings in the Bump Map dialog to get different effects.


Get a Smoother Look


If the aliasing and jags on this image are annoying you can get a better result by running through this exercise with everything done twice as big.  So start out with an image that is twice as wide and twice as high as described here, and use a font that is twice as big.

When you have the final result, the scaling down process will nicely smooth out the jaggies.  This produces a better smoothing result than trying to blur the image you have.

Sunday, May 5, 2013

Enabling ARC for your Cocos2D iOS projects

A quick video tutorial on how to enable Automatic Reference Counting for your Cocos2D iOS game projects.  The process is fairly simple, but its not trivial and its easy to get wrong, so I've taken the time out to record how its done in XCode.

I use the technique described by Steffen Itterheim in his book Learn cocos2d Game Development with iOS 5 which I thoroughly recommend if you're getting started with Cocos2D on iOS.

Here's the video.



Here's the why - although I do explain this in the video, you might want to know why you need it before you invest the time.

Cocos2D by default does not build as a seperate library - the Cocos2D templates just inject all the source code as a tree of files right into your new project.  That gets built alongside your own source code right into the same binary target.

Now Cocos2D currently does not support ARC since I guess the project was started before ARC came along and its a big effort to do the conversion while ensuring nothing breaks.  That means that your whole project can't use ARC - so you would have to do all your release and retains and other Objective-C memory management as per the bad old days before automatic reference counting.

To fix it we build Cocos2D as a seperate compilation unit - a static library - and it builds without ARC as before.  But now your game code is seperate and it can have ARC enabled.  Simple idea, and easy enough to do, once you know how.

Hope the video helps and happy game hacking with Cocos2D!

Update:  I just discovered that Steffen has his own video tut on this already.  Maybe you guys will still get some value from my take on this process, so I'll leave my version up for now.

Update 2: If you get a run-time error like this:

-[CCPhysicsSprite setPTMRatio:]: unrecognized selector sent to instance

...then its because you need to do one more step when you enable ARC by making Cocos2D a static library that includes Box2D.  That is to add the macro

CC_ENABLE_BOX2D_INTEGRATION=1

into the Build Settings for the Cocos2D library target.  Here's a screenshot:


Thanks to Komet163B on my YouTube channel for reporting on this issue.

Friday, May 3, 2013

Trimming Transparency Follow-up: Cropping

Just a really quick follow-up to my recent post about trimming your static images.  I got some great thoughtful comments on my G+ account regarding this and it got me thinking - I needed to clarify how you could use this same technique not just for static images but also for animation sprite sheets.

I posted an update section on that recent post, but I'll repeat it here:
Update: I realised that this post could confuse people into thinking that your sprite sheets of animations could be processed this way. This won't work. I know I said these images are coming out of my animation program but that is because they are stills that I use for the various static poses, and since I use AnimeStudio for all my character art I have to get the sprites looking consistent, so that means whether animated or still I need to use the same program.
Why not? When you trim off the transparency close to the colored pixel content that means the position of the character in the frame will change from frame to frame giving a jittery effect. Definitely not what you want for your animations. But for static poses this technique works just fine.
OK - so how could you use ImageMagick to trim your animated sprite frames?  There's two comments to make before we dive into the script I came up with to help with this:

  • First - do you really need to trim them?  TexturePacker makes a good job of ridding yourself of these extra transparent pixels, and if you already have a way of hit-testing that won't be compromised by the extra alpha may not be a problem.  Thanks to +Krzysztof Bielawski for highlighting this.
  • Second - lets use the word crop to refer to the process of cutting off unwanted parts of the image to precise pixel dimensions
    • Trimming refers to getting rid of all alpha transparency regardless of where that happens to be pixel-addressing-wise.
If your game doesn't require hit testing your animated sprites in that way - maybe you just use a simple radius test - then there's no point in worrying about this trimming probably.

If we do decide to go ahead with this lets get terminology right - ImageMagick uses these terms and from my graphics work I follow the same approach.  Trim means cutting away unwanted stuff (no matter what the dimensions) and cropping is like guillotine - once you position the bounds to the pixel that is where the cut falls.

OK - so we're going to crop?  Here is how to do it:

convert my_sprite_0001.png -crop \
    '309x518+65+238' +repage my_sprite_cropped_0001.png

By referring to my recent post, you can find out how to install ImageMagick, and what the "convert" command-line here is doing.  As before the repage is recalculating the page meta-data after the crop command.

What's new is the -crop and the strange expression in quotes.  '309x518+65+238'

The first two numbers (seperated by the "x" character) are the width and height of the area to be cropped out.  This area needs to be as large as the union of the bounding rectangles of all the sprites in your animation sequence.

The second two numbers represent the offset into your source image (my_sprite_0001.png in the above) as an x, y coordinate pair - with the top-left of the image as the origin.

Note that Cocos2D and many other OpenGL based game kits use the bottom-left as the origin - and mathematical co-ordinate systems do this too.  Take a bit of care to make sure this is right.

Wait: what?  Union of the bounding rectangles?  Yup - this just means that whatever rectangle you choose as your crop is going to be the same size and position for every crop operation done on your folder of images.  This means that in order to avoid cutting off any part of one of the animation frames it will need to be equal to all of the rectangles that would have been used in a trim operation, all overlaid over each other - this "rectangle summing" is called the "union".

In practice I found the easiest way to do this is to find a large image, say the "contact pose" - see my early "rushy animation tut" post - and put a box around that with my image editor (I use GiMP, but you might use photoshop) and check the dimensions and offset.

Then I run my crop script using those dimensions, and check the result using Preview - if an image in the sequence got some part cropped off I can open that in my image editor and adjust those dimensions.

Checking the crop by using the Preview program on Mac
Here's an example of the script running, copied straight out of my Terminal session. Just after the script does its processing I run Mac's Preview program on all the images by using the "open" command:

~/Documents/Art/animations sez$ ./cropdir.sh walk-cycle-side-12fps-fresh 309 518 65 238
About to make cropped copies of the files in walk-cycle-side-12fps-fresh and place into walk-cycle-side-12fps-fresh-converted-1367637222
The resulting cropped copies will be 309w x 518h and at offset 65, 238 in
the image.

Continue (y/n) ?  [N]: >Y
   walk-cycle-side-12fps-fresh/walk-side_00001.png    -- cropped to -->   walk-cycle-side-12fps-fresh-converted-1367637222/walk-side_00001.png
   walk-cycle-side-12fps-fresh/walk-side_00003.png    -- cropped to -->   walk-cycle-side-12fps-fresh-converted-1367637222/walk-side_00003.png
   //.... more
   walk-cycle-side-12fps-fresh/walk-side_00047.png    -- cropped to -->   walk-cycle-side-12fps-fresh-converted-1367637222/walk-side_00047.png
   walk-cycle-side-12fps-fresh/walk-side_00049.png    -- cropped to -->   walk-cycle-side-12fps-fresh-converted-1367637222/walk-side_00049.png
~/Documents/Art/animations sez$ 
~/Documents/Art/animations sez$ open walk-cycle-side-12fps-fresh-converted-1367637222/*

And this is a complete listing of the script I use. As before - caveat emptor, backup before use, all care, no responsibility.

#!/bin/bash

# Copyright Sarah Smith - http://indiegamecodingconfessions.blogspot.com

# ImageMagick is from http://www.imagemagick.org

# This script is placed in the public domain - feel free to use it how you
# want, though a link to this blog would be nice.  :-)

if [ $# != 5 ]; then
    echo "Usage: $0 <dirname> <width> <height> <x-offset> <y-offset>"
    exit 1
fi

# Halt execution the second a command fails
set -e

# Uncomment this line to get debugging info
# set -x

UNIQ_NM=$(date "+%s")
DESTDIR="$1-converted-$UNIQ_NM"

echo "About to make cropped copies of the files in $1 and place into $DESTDIR"
echo "The resulting cropped copies will be $2w x $3h and at offset $4, $5 in"
echo "the image."
echo ""
echo -n "Continue (y/n) ?  [N]: >"

read goahead

if [ "x$goahead"="xy" -o "x$goahead"="xY" ]; then

    mkdir $DESTDIR
    GEOMETRY="$2x$3+$4+$5"

    for fn in $1/*; do
        DESTNAME=$DESTDIR/$(basename $fn)
        convert $fn -crop $GEOMETRY +repage $DESTNAME
        echo "   $fn    -- cropped to -->   $DESTNAME"
    done

fi

And you can download this script from my Dropbox.  As in my previous post, just chmod it to executable and run it from the command line as above.

Happy image hacking!

Thursday, May 2, 2013

Trimming Transparency from Images

When you export images from some programs, you wind up in some cases with the actual content as a small area of coloured pixels in a sea of alpha transparent nothing.

This happens to me when I'm animating my character around and I'm doing so against a background that is say 1024x768 where the actual character's image is a tiny percentage of that size.

A 1024x768 png from my animation program
This is completely to be expected - the designers of your other programs always have to assume that your export is intended to be the size of your original canvas; but when you have dozens or maybe even hundreds of frames of animation all with wasted transparent pixels, removing it all by hand using GiMP or Photoshop is agonizing.

When you're using TexturePacker or ZwopTex your transparent pixels are probably removed nicely for you when the sprites are stored, but still they can mess up your hit testing and on-screen positioning for your game.

The image content I want with extra transparent pixels cropped away
Here is a way to crop those transparent pixels automatically in large batches, and the program to do it is free.

OK, this is what you need - the ImageMagick program from ImageMagick.org - a fantastic and very powerful set of command line tools.

I'm on MacOSX Mountain Lion and found this great installer which the guys at Cactus Labs have put together - it was just case of clicking through and it all just worked!

Once you have ImageMagick installed check that it is working by opening up a command line - on MacOSX, just do <command>-<space> to access Spotlight and type "Term" and you should be able to hit enter on the first match to get the Terminal.app program running.  Then at the command prompt type:   convert -version


~/MyArtWork sez$ convert -version
Version: ImageMagick 6.8.4-8 2013-04-08 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2013 ImageMagick Studio LLC
Features: DPC OpenMP
Delegates: bzlib jng jp2 jpeg lcms png tiff xml zlib

That shows that the ImageMagick command line tool called "convert" is up and running. The script I'm about to show you won't work if this command is not available.  If you had a Terminal running when you installed ImageMagick you may need to close and re-open it to get this to work.

Now the basic technique is to use two commands that convert knows about:
From the command line the trim command looks like this:

convert my_image.png -trim +repage my_image_trimmed.png

The trim command is what does all the work - it samples the image at the corners and assumes those pixels are what the background of your image is.  Then it crops in the image as small as it can on all four sides - providing that the only pixels it is throwing away are that background color it sampled.  It works with all colours of background, not just alpha transparent (which ImageMagick calls the colour name "none").

Now there's a trick here - what if one some of your frames the sprite just happens to be touching in the corner where the sample is made?  Oops - that will mess up ImageMagick's trim!  To counter this problem, first we add a border of transparent pixels around the image so that when it comes time to run the trim, we can be sure no valuable pixels will get sampled by mistake.  That is where the border command to convert comes in.

The whole script looks like this:
!/bin/bash

# Copyright Sarah Smith
# http://indiegamecodingconfessions.blogspot.com
# ImageMagick is from http://www.imagemagick.org
# Back up your work before running this script!
# This script is placed in the public domain
# Feel free to use it how you want, though a 
# link to this blog would be nice.  :-)

if [ $# != 1 ]; then
    echo "Usage: $0 <dirname>"
    exit 1
fi

# Halt execution the second a command fails
set -e

# Uncomment this line to get debugging info
# set -x

UNIQ_NM=$(date "+%s")
DESTDIR="$1-converted-$UNIQ_NM"
mkdir $DESTDIR

for fn in $1/*; do
    TMPDESTNAME=$DESTDIR/tmp-$(basename $fn)
    DESTNAME=$DESTDIR/$(basename $fn)
    convert $fn -bordercolor none -border 3x3 $TMPDESTNAME
    convert $TMPDESTNAME -trim +repage $DESTNAME
    rm -f $TMPDESTNAME
    echo "   $fn    -- trimmed to -->   $DESTNAME"
done

How to use the script.
  • First save all your work somewhere, make sure its backed up!
  • In a terminal, cd into the directory where your artwork is
    • you backed up this directory didn't you?
  • Download the script trimdir.sh as a file to your computer.  Try this drop box link.
    • save it into that same directory where your art is
  • Make the script executable, and run it like this:
~/Documents/my_art$ trimdir.sh my_directory_of_sprites

...where "my_directory_of_sprites" is the name of a directory containing sprites you want to trim.  The script will create an output directory and put the trimmed versions of all the files in there.

Word of warning - this script is just my own hacking so use at your own risk - and back up before you start!  See my earlier post about backups!  The script tries to avoid doing anything destructive, and never replaces the files you specify, only placing the cropped versions into a new directory.  But like all scripts with great power comes great responsibility!

Also click the topic label "command line" below for more posts about the command line, or search for tutorials on it on the web if you're not comfortable with the command line or Terminal usage.

Here's an example of me running the script on a directory called "static-poses":

~/Documents/AG-Art/erin-animations sez$ ./trimdir.sh static-poses

   static-poses/back-quarter.png    -- trimmed to -->   static-poses-converted-1367477342/back-quarter.png

   static-poses/back.png    -- trimmed to -->   static-poses-converted-1367477342/back.png

   static-poses/front-quarter.png    -- trimmed to -->   static-poses-converted-1367477342/front-quarter.png

   static-poses/front.png    -- trimmed to -->   static-poses-converted-1367477342/front.png

   static-poses/side.png    -- trimmed to -->   static-poses-converted-1367477342/side.png

Of course ImageMagick is capable of so much more than this. Please let me know if you use this technique, or my script and how it worked out for you. Have fun hacking your sprites!

Update:  I realised that this post could confuse people into thinking that your sprite sheets of animations could be processed  this way.  This won't work.  I know I said these images are coming out of my animation program but that is because they are stills that I use for the various static poses, and since I use AnimeStudio for all my character art I have to get the sprites looking consistent, so that means whether animated or still I need to use the same program.

Why not?  When you trim off the transparency close to the colored pixel content that means the position of the character in the frame will change from frame to frame giving a jittery effect.  Definitely not what you want for your animations.  But for static poses this technique works just fine.

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.