Showing posts with label coding. Show all posts
Showing posts with label coding. Show all posts

Friday, January 2, 2015

Swift and Cocoa

The primary reasons for Apple's language gurus going to Swift as the core language for building iOS and Mac OS X applications was to make it easier for developers to create good, secure, stable applications.  It wasn't actually a conspiracy to drive us all mad, it was actually a long-game move that was very well executed.  Yes, its not "there" yet in many ways.  But here's why you should use it anyway, and a couple of things to look out for: optionals and type-safety.


Objective-C has a lot of pointers flying around, it is very easy to be loosey-goosey about when those pointers are null.  Especially since its OK to send a message to a null object, and because the clang compiler ensures initialisation in many cases, we often write sloppy code with respect to null pointers.  Apps that crash are not only a bad experience for users of iOS products, but they're also likely to have security holes.  Also apps that are light on type safety can similarly be unstable and have security problems.

Also, there's type safety.  You'd think being C-based that Objective-C was type safe, but the existence of the id type, a generic go-anywhere do-anything type based on the venerable C void * pointer type, means that a lot of the time that type safety is circumvented.  An Objective-C array for example is of type NSArray and can have any Objective-C object stored into it, as its members are all id types.

Swift does a lot for type safety, and while it does not do away with null pointers, what it does do is force you to be explicit about them.  This is done with the Optional type.  An Optional behaves like a union struct in C where you can either have a None value, or a Some<T> value. (Actually its implemented with a Swift enum).  Swifts generics have a syntactic sugar for this where instead of writing

var userAnswer : Optional<String>

you write

var userAnswer : String?

which means a var that may or may not contain a value.  In general in Swift you are encouraged to initialise variables as you declare them, and then you get the benefit of type inference like this:

var userAnswer = "Placeholder"

This is perfectly type safe: the variable userAnswer is strongly typed as String, which is inferred by the compiler from the initialisation, and the variable cannot have a value of another type assigned to it.

Some folks seeing code like this have assumed that Swift is something like Javascript where the variables are dynamically typed: they can contain data of different types at different times. Nope.  Swift is not a scripting language.  Its not even a managed language in the true sense of that term.  Its a compiled language that has a powerful and expressive syntax, and a rich standard library, but its not a scripting language.

OK, so what does all this fancy footwork with Optionals actually buy you?  For my money its like trading one problem for another that is easier to solve.  I like to write invariants in to my comments in code:
"Such and such a condition will always hold here."  
By putting such things into the class definition you remind yourself that you are in control: there is not some spooky stuff going on.

Superstitious coding is a terrible disease.  If you hear someone saying "I don't know how I fixed it but I had to type that to get it to work" or "I know that variable should always have a value, but what if someone sets it to null?" then you know superstition and magical beliefs have taken hold in your team and its time to call the exorcist.  In other words abandon all hope and compile your code with a ouija board because you don't control it any more.

Instead, use invariants.  Yes comments are not code, but you can type them in nonetheless and at least enforce them during debug builds using asserts.  This is coding by contract and if you start out as you mean to continue then your code will make sense as it continues to be modified long into the future.

This is where Optionals come in.  They allow you to make contracts and invariants succinctly and naturally as you write code.  If you use a Swift implicitly unwrapped optional by writing:

var userAnswer : String!

func displayTheAnswer()
{
    myAlert(title: "Got it!", text: "You said \(userAnswer)")
}

...then what you are doing is effectively writing the following invariants and asserts:

/* Invariant: I undertake and swear & declare that I will make sure this has a value by the time its used! */
var userAnswer : String!

func displayTheAnswer()
{
    /* kaboom if I didn't live up to my promise */
    assert(userAnswer != nil, "You failed to stick to the invariant!")
    myAlert(title: "Got it!", text: "You said \(userAnswer)")
}

And while this can still crash at run-time if the assertion is wrong, its much much easier to read what you are intending, and to locate the cause of the crash at the site of the error, not at some point much later where the result of the null finally propagates to.

In fact when you write UI code in Swift such as the following:

@IBOutlet var surnameLabel : UILabel!

you are using an Optional, and an implicitly unwrapped one at that.  This is what you get if you use Interface Builder to control drag a control into your Swift NSViewController.

Because you know that you controller will spend most of its life-time running with the surnameLabel set to the value obtained from the NIB file, this is a sound invariant promise to make.  Superstitious coding where you run around checking to see if this is null all the time makes no sense.

So I like the idea.  Its a bit weird at first, but its a good language feature, and once the idiomatic use settles down will make for more stable and more secure software.

Where things are a little rough is at the interface between Swift and Apple's now long-in-the-tooth User Interface library, Cocoa.  Cocoa is full of crufty, bizarre, unsafe and down-right confusing APIs that no matter what modern language you used would always behave badly.

Here's an example:


Here I'm trying to implement an NSValueTransformer to use in the Swift project I'm working on that uses Cocoa and bindings.  The class method transformedValueClass (where class means "+" instead of "-" or instance method) returns a Class as a result.  Because Swift's Array type is actually implemented as a Swift Struct it does not conform to the AnyObject protocol; and since AnyClass - the return type from this function - is actually a type alias for AnyObject.Type - you cannot return the type "array of strings" from this function.

Instead to work around you need to return an NSArray - the old Objective-C type - which will get transparently bridged to a Swift array, but which of course is not type safe.


Other issues are the difficulties working with key technologies like Key-Value Coding, which is critical to the Cocoa bindings used by Interface Builder, and the cryptic type messages that can come out of the type system at the interface with Objective-C.

Its here at the interface between Cocoa and Swift that the new language really runs into rough terrain.  Still, its worth persevering with, and the online community is abuzz with new pundits who are happy to drop knowledge bombs on your gnarliest conundrums, providing you've put some time into scratching your head over them yourself.

Also, my prediction is that while at present the Cocoa layer for Swift is mostly just ultra-thin bridging-headers and wrappers, we'll slowly see more pure Swift classes put in front of these things and kludgy Cocoa issues will slowly be solved.

At present it is perfectly do-able to write your new apps in Swift and I think starting out greenfield projects using Objective-C is probably a mistake, all things considered.

What do you think?

Wednesday, March 26, 2014

Getting a Qt/C++ App in the Mac App Store

Short story: yes, despite what you may have heard getting a Qt/C++ application into the Mac App Store is possible.  Its not simple, there are some traps but my app, Plistinator, is proof it can be done even the new world of Mavericks with its increasingly more stringent sandboxing regime.

Update: 29 June 2015 - with Qt 5.4 the macdeployqt application has greatly improved and not only has many of the bugs fixed, it also can help with the actual signing.  I've left the links to scripts and patches on here, but you likely will not need them all.

Mac App Store?


Do you really want your app in the Mac App Store?  If  you can, in my opinion - yes.  The cost in terms of Apple's commission is very reasonable since you get
  • fulfillment
    • download to an end-user's hands in exchange for zapping their credit card
  • licensing
    • get a license receipt for the app so you can deal with usage issues
  • handle reviews, charge-backs, upgrades
    • charge-backs and other post-sale customer issues are a part of e-commerce
  • captive audience
    • App Store is on every Mac
Doing all these things to a commercial grade is Hard(TM).  Sure you can use PotionStore and dump some binaries on Amazon S3 but are you ready to take the phone calls if your instance goes down after the credit card is billed, but before the download is served up?

Matt Gemmell has written an excellent article on the pro's and con's and I agree with pretty much everything he says.  My conclusion was that I wanted to go with the Store still, but I also sell my other versions outside.  If you are not sure about the App Store read it and see where you fall on the issues he raises.

I want to clarify the licensing thing: licenses are not DRM, licenses are not evil, Open Source has licenses.  In the App Store drafting the legalese of the license is done for you, so you don't need to hire a lawyer for that.  When the packagemanager installs it from the store the app is receipted, with the system storing its license key automatically - you don't need to do anything to manage that.  If you want to check the license key (Apple calls it a receipt) you can use their API.

By way of comparison, if you use CocoaFob what you can do is create your own keys and make a nag screen to enter the key if it has not been receipted for that installation.  You'll need to store the receipted key into some prefs file yourself.

I think a nag screen is a good way of dealing with the license key entry issue, because you can just have a "Later" button and if the person has torrented your app they can click "Later", or when they're ready "Buy" to go and get a key.  Without this a person could have a copy of your app and never realise they were even supposed to pay for it, or if they do have no way to complete a transaction to "buy" the app.  License keys give you this.  It means torrents become another marketing channel for you, instead of a dead-end to any revenue from your app.

For my app store binaries I just decided not to bother with checking receipts.  If I get the feeling its becoming an issue I'll deal with it then.  For my Windows binaries I absolutely want to do license keys so I do that with CocoaFob.

Sand-Boxing your App

Before you start to build the .pkg file that you'll be pushing up for App Store review, you'll need to make sure your code is sand-boxing compliant.  I love this article by Cocoa-in-the-Shell which is not so happy about Mac sandboxing.  :-)

I used Qt 5.2 which includes the latest fixes to Qt and also has specific Qt for Mac features.  It seems to work well with Mavericks.

In the Digia article (which I suggest following as a general guide) it seems your only problem is the preferences file location, and the storage of cache files.  As of Qt 5.2 you really don't need to worry about these things.  Just make sure that you have lines like this in your main.cpp:

QApplication::setApplicationName("Plistinator");
QApplication::setOrganizationDomain("smithsoft.com.au");

and Qt will put your preferences and settings in the right place.  Make sure your apps bundle id in the Info.plist file match this.  If you use the new QStandardPath API in Qt you'll get the right paths to things like caches and file stores.

As the Digia article says you may use the Qt File open dialog so that the user can by inference provide permission to access any files that your app wants to open that is outside the sandbox.

The issue with this is that the Qt file dialogs return a QString which means you cannot save the Security Scoped Bookmark.  Converting the QString to an NSURL does not fix this, because the original URL has magic pixie dust embedded in it so as to make the bookmark and the QString returned does not preserve that.

To fix this you'll need to build a small Qt C++ wrapper for NSOpenPanel and NSSavePanel which presents the dialog to get the users response (and sandbox permission) and then saves the Security Scoped Bookmark.

Note that in the case of the NSSavePanel, if the file has not been written to (because you got a name to save a file to but there's no file there yet) you will not be able to save a bookmark.  My workaround is to write a file with a single byte in it as a placeholder, then save the Security Scoped Bookmark, then return from the wrapper and save the users file by over-writing the placeholder back in your main app code.  See my gists for some ideas.

Times you'll need the Security Scoped Bookmarks are:

  • recent files menus
  • opening the last edited file on relaunch
  • re-displaying a directory view after relaunching the app
basically any time you need to open a file or folder that you did not have the user open via a dialog, and can not now logically display an open file dialog for.

How to Build your App for the Store

Follow the pointers in this excellent article by the folks who are now behind Qt, Digia plc.  There are a few gotchas and wrinkles, but unfortunately doing a complete step by step tutorial is not really possible for me right now, and making it very specific would mean it was out of date when Qt or Apple change something anyway.

Here are the gotcha's I am aware of (read the Digia article):
  • I suggest using bash to create a build script
    • instead of trying to put the signing into your pro file
  • Setting flags for debug symbols via your "myapp.pro" file
    • Qt mkspecs are a bit off and I had to patch them to get it to work.  
    • See this Qt-Project bug report for my patches
    • You can probably get it to work more simply by hard coding the switches
    • Use my qmake line as shown below in your build script
    • I create a "appstore" stanza in my .pro, used to switch on App Store specific code
  • Building - as per normal 
  • Running macdeployqt
  • Extract the dsym with the utility
    • see below
  • Sign the macdeployqt bundle - if it helps using my script here
  • Run the productbuild command to create a signed package of your app
    • see snippet below
It's not obvious where the dsym file should go.  It needs to be right next to your app, for productbuild to find it, that is

ls $BUILD
myapp.app/
myapp.app.dSYM

Here is my qmake line from my build script:

qmake $SRC_DIR/${DEV_APP}.pro CONFIG+=release CONFIG+=x86_64 CONFIG+=force_debug_info CONFIG+=appstore

Here is a snippet from my build scripts for making the package:

/usr/bin/productbuild \
    --component $TMP_APP /Applications \
    --sign "$PKG_SIGN_CERT" \
    --version "$VERSION_NO" \
    $PACKAGE

Hope that all helps.  If you get stuck feel free to post a comment here, and I will try to assist.  I'll feel especially motivated to help if you tweet or G+ my little app for me!  :-D

Thanks for reading!

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!

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!

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!

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!

Thursday, January 17, 2013

A couple of notes about stores

A few posts ago I talked about how you can use Apple's core data in games by employing the techniques shown in the XCode Core-Data command line example.

That example works well because it doesn't assume any code templates - and if you're coding a game you're probably not using a core data template - and also it doesn't assume using utility classes like NSPersistentDocument.

However some of the file saving semantics of Core Data stores are pretty weird, so I thought I would document my current findings here.  The relationship between the NSPersistentStore object, and the on-disk file are also a bit obscure in the documentation.  So call this the "what they don't tell you in the Apple documentation" article.

Stores and Coordinators

All the three functions I discuss below are on NSPersistentStoreCoordinator.  I suggest never saving a reference to your store object.  The action of saving or moving a store will likely invalidate any instance of NSPersistentStore you have saved.  Instead do something like this:

- (NSPersistentStore *)store
{
    NSArray *stores = [[m_managedObjectContext persistentStoreCoordinator] persistentStores];
    
    NSAssert([stores count] <= 1, @"Each world can have (at most) one backing store!");
    return [stores lastObject];
}


In other words, use the coordinator as the place for all your store operations - not the instances of the stores themselves.  Weird - maybe but that is how Cocoa does it.

Who ya Gonna Call?

The documentation says: Adds a new persistent store of a specified type at a given location, and returns the new store.

What the documentation doesn't make specifically clear is that this function will create the on-disk file, in this case an SQLite data store if required - but it will also just transparently open the existing on-disk file if there is one there.  Nice.

Here the relation with the store object is clear: it creates the on-disk file (or opens an existing one) and returns a new store object.  You can use the returned store object for checking success, but as mentioned above I suggest not saving a reference to it.

This is your go-to function for opening a data store file, existent or not, given its location.  In the simple case you know your type and can simply specify it - eg NSSQLiteStoreType, and you don't have any configuration or options.

There's no need to use NSFileManager's exists functions or anything like that, to check for existence of the file first.  Of course you will need to make sure that any intermediate directories in the path for the URL do exist.

If you want to do basic error checking just test the returned value for nil - there's no need to get the error argument unless you want verbose error reporting.  To understand how this works simply doing the two modes (initial creation versus subsequent re-opening) checkout the main.cpp of the XCode Core-Data command line example.  Might not seem like a big deal, but as these are databases which normally require a bunch of setup, its nice to have a one-stop-shop for opening like this.

The Mad and the Bad

The documentation says: Sets the URL for a given persistent store.

No shit, Sherlock!  This is one of the least useful functions, and most poorly documented, on NSPersistentStoreCoordinator.  Basically the intent of it seems to be a very cheap way to open already existing data store files, where you absolutely know your existing store object has the right setup, and you know for sure you have an existing store file.  The fact it has a BOOL return looks promising for light-weight error detection (but it turns out not to be).

Here you must already have a store object.  Even though these calls are on NSPersistentStoreCoordinator, which can make new store objects, this call is not going to do that - you must have an existing store.  What if you don't save before calling this?  Changes to the store might get lost - in some cases.  See the documentation but its got to do with whether or not you have an atomic store - basically SQLite is non-atomic.

The arguments are the URL to open, and an existing store object - that is an instance of NSPersistentStore.  But what beats me is in what circumstances would you have a valid instance of a store object, but either not have it opened to a backing store URL, or want to just cut that store file loose?

Another problem is you must have an existing backing file - which the documentation says.  What it doesn't say is what happens if you don't?  Well, the function quite happily returns true if the file doesn't exist - huh??? - and then when you try to call save on your NSManagedObjectContext at a later point you get an exception.  Joy.

If anyone can find a great use for this function tell me - because as far as I can tell its mad, bad and dangerous to know.

Saving As

The documentation says: Moves a persistent store to a new location, changing the storage type if necessary.

This call is basically a addPersistentStoreWithType:configuration:URL:options:error: call using your old stores type, followed by a removePersistentStore:error: call on the old store (assuming you don't change the store type).

What I mean by that is if you have a store saved at URL A and  you want to make a copy of it at URL B, and do subsequent saves and operations on that new URL B, then this call will do what you need.

Here you are going to lose the store you pass in - but if you follow the idiom above of not saving a reference to your stores that is no problem.  Rather than BOOL this returns a new store which you can check against nil if you want to determine success.

Obviously its also the go to function if you need to migrate between store types for some reason - though I'm not really sure why you'd want to do that so much.  In most applications you decide on say SQLite and stay with it.

Conclusions

  • Use addPersistentStoreWithType:configuration:URL:options:error: to open all your data files, and also to create them the first time.  Don't keep a member variable of the store it returns.
  • Once a file is open, you can save the data to it by calling save: on your NSManagedObjectContext.  That will cause the attached stores to save to whatever URL's they're opened onto.
  • To do a save as use migratePersistentStore:toURL:options:withType:error: and pass in your existing store object, obtained from the - (NSPersistentStore *)store function listed above.
  • Closing files is not necessary - just let the objects go out of scope and ARC plus their destructors will clean everything up.  Make sure you save first obviously.
  • I suggest hiding all references to stores inside a class, and doing everything through NSPersistentStoreCoordinator.
Farewell and may all your data persist!

Friday, December 28, 2012

Do game creators get holidays?


My hubby Raymond, a black fine line art drawing done with Manga Studio
Raymond - who is a Saint
Well, I sort of had some.

I tried to spend some quality time with my long-suffering hubby Raymond, and caught up with my in-laws for a big turkey lunch.

My last day at my current paying gig is not for a couple of weeks yet, but I said "Happy holidays" to my colleagues on Friday last week, and since then I have had a full week on my own recognisance.

In that time I've made a fair bit of progress on getting to grips with Cocoa, and with actually getting useful functionality into the GameCreator tool.

It has 4 screens: Rooms, Atoms, Aspects and Identifiers.  I've done 3 now, with the Atoms screen now pretty much working.  There's a couple of bugs with the Undo but I can add new Atoms to a room, delete them and so on.

I figured having done the Rooms one the Atoms would be easy: not so much.  When I select a room I want the Atoms screen to show only the Atoms for that room, and that turned out to be a real pain.

Cocoa bindings would not play ball at all and I had to refactor quite a bit to get what I needed working. The problem was that each screen is a seperate xib file, and its loaded by its own controller - I switch between controllers using a top-level screen.  Trying to communicate from one screen controller to the next turned out to be nasty.

I go back to work on Wednesday next week and have sort of two half-weeks before I'm full time on my own stuff.  Maybe I should take some of that time between now and when I go back to actually rest.


 *** Terminating due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[GameDeveloper rest]: target does not implement selector'
:-)

Monday, December 24, 2012

Re-org Your Source Tree in XCode

This is a video tut I just did on reorganizing your tree of source code in the XCode environment, so that it makes sense and plays nice with source control.  Its not rocket science but it gave me pause the first time I did it so maybe this'll be helpful for some folks.

Wednesday, December 19, 2012

Primal Scream

Right now I'm bogged down trying to get some infrastructure stuff done for my game and its very frustrating.

Later in January my time will be mine to schedule as it suits, but right now I'm still working days and coding on my game at nights.  It means I'm tired and not as on top of my game as I should be.

Things that seem conceptually simple and had looked like being fun to do, turned out to be a real pain in the neck.

And literally, as my home work setup is not ergonomically great.  Now I'm walking round like Quasimodo.

Its discouraging.  Why with all these amazing productivity tools can the simplest things be so painful to achieve?

I have a bunch of stuff hard-coded in the game and I'm trying to make it data driven.  The theory is I change a few values in a file, and hey presto the game springs to life with a whole new scene.  Minimal coding, just drop in the artwork and away we go.

Nuh.  Not so much.

To sum it up I've crossed a watershed in Objective-C where I know enough to start coding up things beyond the bounds of the tutorials and example code - and I absolutely have to do that because none of the things I want to do fit neatly into those examples.  So I can see what I need to do, but don't know it well enough to quickly write and debug the code to achieve it.

Things that ought to be simple - wiring up a few data structures to some UI elements - are painful beyond belief.  CoreData's magic binding stuff is not doing what I want, and even where I thought I had it nailed its not working how I thought.

There are a few API's and languages I know really well - those I am used to being able to express myself in quickly.  I can get stuff done fast.

And I will get to that point sometime with Objective-C but right now.... I want to throw the whole thing at the wall!  Grrrr!!!

Oh well.  Hopefully by the next blog things will be better!

Monday, December 10, 2012

Customizing the core data store.

CoreData is a pretty awesome way to manage and persist your game objects, especially for a game with complex inter-related items, such as an adventure game.

Trouble is there is a helluva learning curve getting going with CoreData.  I just solved one little thing that was driving me crazy and wanted to share: how do you customize aspects of the CoreData store?

Image of apple core courtesy of http://www.wpclipart.com/


In my game I have two project targets: one is the game itself written in Cocos2D, and the other target is a game data editor written in Objective-C & Cocoa for the Mac.  They share a lot of classes, and the idea is that I can edit the games data, save it out as a SQLite file (which is one of CoreData's persistence formats) and then when someone goes to play the game for the first time they get a fresh instance of that data as the initial game state.

Trouble is, how do I tell the Mac Cocoa gui, to create my custom instance of an SQLite database, instead of popping up a dialog - which is the default thing you get using XCode's CoreData enabled app wizard?

And for that matter how do I get my database of game objects into my Cocos2D app?

If you're a CoreData beginner like me I suggest:
  • The answer begins with having to understand the bare essentials of CoreData.  For that I recommend Bob Uelands video tutorials.  He has a patient and careful manner that is a bit frustrating but his clarity is hard to beat.  If you've some familiarity with CoreData you can probably fast forward or even skip his stuff.
  • You could try Ray Wenderlich's tutorials - but I find they're a bit too specific and don't always give me the "why am I doing this" answers I want so I can build my own stuff.  But have a look and they may just have exactly what you need.
  • Go and run through Apple's CoreData command line tutorial.  It builds a CoreData app up from first principles all inside main.m.  If its all gobble-de-gook to you, then maybe skipping patient Bob's tutorials was a bit hasty...
What is great about the Apple CoreData tutorial is that the final result - a CoreData app that does not start with any of AppKit or UIKit, or any XCode scaffolding - is exactly what you need for dropping CoreData into a Cocos2D app.  If you have the time and want a good understanding work through the tutorial building up the code in the order given, and resist the temptation to just past the whole source.

Seriously - if you're used to skipping the boring documentation in the Apple developer site you're missing a buried gem with this tutorial.  They give the steps to building a whole data persistence stack.

I found working through these gave me the answers I needed.  So for example to solve my problem with customising the data store, I took the code from Apple's CoreData tutorial managedObjectContext() function and overrode the managedObjectContext function in the NSPersistentDocument sub-class I was using in my Mac OSX game editor GUI.

Edit:  OK, this looked like it was working but wasn't - my apologies.  Basically you can use this code, but you need to create your own window controller and UI class, not use the NSPersistentDocument - which is built to handle arbitrary "documents", not one well-known path for a database.  Sigh.

That let me specify the details of my store:

- (NSManagedObjectContext*)managedObjectContext
{
    static NSManagedObjectContext *moc = nil;
    if (moc != nil) {
        return moc;
    }
    
    NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc]
                                                 initWithManagedObjectModel:[self managedObjectModel]];
    
    NSString *STORE_TYPE = NSSQLiteStoreType;
    NSString *STORE_FILENAME = @"GameData.sqlite";
    
    NSError *error;
    NSString *path = [[PreferenceValues sharedPreferenceValues] saveGamePath];
    NSURL *url = [NSURL fileURLWithPath:path isDirectory:YES];
    url = [url URLByAppendingPathComponent:STORE_FILENAME];
    
    NSLog(@"Setting up the store with type %@ - at %@", STORE_TYPE, [url path]);
    
    NSPersistentStore *newStore = [coordinator addPersistentStoreWithType:STORE_TYPE
                                                            configuration:nil
                                                                      URL:url
                                                                  options:nil
                                                                    error:&error];
    
    if (newStore == nil)
    {
        NSLog(@"Store Configuration Failure\n%@",
              ([error localizedDescription] != nil) ?
              [error localizedDescription] : @"Unknown Error");
    }
    
    moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    [moc setPersistentStoreCoordinator:coordinator];
    
    return moc;
}

Wait, what is that PreferenceValues thing doing in there? That is my own NSUserDefaults front-end. More on that in another post.

How do I get my data into Cocos2D?  I'll show you how I did it, but that's for another blog post.  Subscribe - give me feedback and I will post more!  Thanks for reading!