Secret Lab

We convert coffee into games.

Category: Code

OSCON 2013

by Doctor Science

OSCON 2013We’re very pleased to be presenting at O’Reilly’s OSCON conference in Portland once again this year. We’re involved in two tutorials this time around!

For the first time at OSCON, Jon Manning and Paris Buttfield-Addison will be presenting a half-day tutorial on game design where they’ll discuss what makes games fun, how they work, and how you can apply game design techniques to your daily non-game related work. This tutorial is hands-on, very practical, lots of fun, and is called How Do I Game Design?

For the third year in a row Chris Neugebauer, along with Jon and Paris, will be presenting a half-day tutorial on mobile application development with a focus on user-experience. As with the last two years, we’ll be using Android as the platform we discuss the most – but everything will be applicable to all mobile platforms. The tutorial is called Level Up Your Apps: Mobile UX Design and Development.

We hope to see you at OSCON!

Using Gesture Recognizers with Cocos2D and CCNode + SFGestureRecognizer

by Jon Manning

One of the most interesting and useful features that iOS includes is the gesture recogniser. Gesture recognisers are objects that are attached to views, and look for specific patterns of touches. When a gesture recogniser notices that the user has interacted in the way that it’s looking for, it notifies a delegate.

Prior to gesture recognisers, handling complex gestures like pinching or rotation was a lot harder than it had to be. Time was, developers had to manually track the touches involved in a gesture, and measure how they were moving over time; nowadays, we just do this:

UIRotationGestureRecognizer* rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotated:)];
[self addGestureRecognizer:rotation];

And then have a method that gets run when the user interacts with the view with a rotation gesture:

- (void) rotated:(UIRotationGestureRecognizer*)rotation {
  if (rotated.state == UIGestureRecognizerStateChanged) {
       // the rotation gesture has changed, do something about it
  }
}

Gesture recognisers are one of those APIs that are completely obvious once you think about them, and solve a potentially tricky problem very cleanly. However, gesture recognisers have to work within the bounds of how views in iOS work, which can have some interesting consequences for using them in games.

To put it briefly: how can we use gesture recognisers in OpenGL-based games?

Here’s the problem: gesture recognisers work by being attached to views; when a touch lands on the screen, UIKit determines which view the finger belongs to, and this information is used for tracking gestures.

However, all OpenGL games do their main work using a single view – the OpenGL view in which all rendering takes place. This is true regardless of whether you’re drawing complex 3D graphics or simple 2D sprites. And this can mean that gesture recognisers are trickier to do, because when the finger lands on the screen, UIKit will say, “hey, the view that was touched was the OpenGL view! Job done, you’re welcome, see you later!”

So, if we want gesture recognisers, and we’re drawing using a single OpenGL view, what needs to happen is this that gesture recognisers need to be added to the OpenGL view, but are limit the areas in which they’ll look for touches to areas that depend on what’s happening in the game.

This is possible through the use of the gestureRecognizer:shouldReceiveTouch: method in the UIGestureRecognizerDelegate protocol. If a delegate implements this method, it’s possible to make a recogniser only track touches in certain areas.

This is the approach taken by Krzysztof Zabłocki’s CCNode+SFGestureRecognizers, which is a zlib-licensed extension to Cocos2D. CCNode+SFGestureRecognizers performs some very clever hacks, including dynamically creating classes that operate as delegates and using the Objective-C runtime’s new associated object support, that allow you to add gesture recognisers directly to CCNodes.

We’re using CCNode+SFGestureRecognizers in Leonardo’s Moon Ship, an adventure game that we’re looking forward to talking about further in the coming weeks and months, to support dragging items from the player’s inventory onto items in the game world.

leo-dragging

December Developer Training in Melbourne

by Jon Manning

This event has now passed! Our next training is in Sydney, February 2013!

We’re exceptionally pleased to announce another training course! Join us for three days of intense iOS training in Melbourne, where you’ll learn Objective-C and iOS development from the ground up. We’ll be running the course from December 14 to 16, in the heart of Melbourne’s CBD.

For more information, look no further than this here internet web page site link!

Captain: Add Hooks to Your Code

by Jon Manning

So, here’s another something that we’ve been working on.

Captain is a lightweight library that lets you add hooks to your code, using JavaScript. We designed it for two reasons:

  • If you’ve got a bunch of objects, each needing a small amount of custom objects, creating a subclass for each variation is cumbersome, and devising a sophisticated data-driven architecture is often overkill and sometimes impossible for your use case.
  • Extremely rapid iteration, skipping the compile/install phase, is awesome.

Many of the games we make involve a lot of special-cased behaviour. Like all halfway decent developers, we try to minimise this, but sometimes you really just need a sprite that walks two feet left, three right, and does a twirl, and there’s nothing else in the game that you can generalise into a nice, reusable system.

We’ve already found some great results in allowing field-testers and non-programmers to make modifications to iOS applications by exposing certain resources to iTunes File Sharing. For example, if you’re writing an app that has a lot of sound effects, it makes your sound designer’s life a heck of a lot easier if they can open up iTunes and drop in a replacement sound file, and see how it sounds in your app without having to get another build.

What we ended up doing was using JavaScriptCore, which is the built-in JavaScript runtime on iOS, to create a very loose binding to Objective-C, and then allow Objective-C objects to delegate parts of their behaviour out to JavaScript.

Captain isn’t a scripting bridge. This means that it’s a slightly different thing to libraries like the excellent jscocoa. Most scripting bridges allow you to write entire apps in other languages, which is super cool. However, we really like Objective-C, and find that using the native language for the iOS platform is the best way to approach most things.

Captain, therefore, lets you expose very specific parts of your application’s behaviour to scripts, effectively creating a domain-specific language for your app. Plus, it’s all designed to be super lightweight.

An important note: Apple’s rules say your app isn’t allowed to get scripts from the outside world and run them. This means that you can’t use Captain to build a plugin architecture for your app, but you can use it during development to make your edit-build-compile cycles faster and more flexible.

How to use it

The most basic use case for Captain is when you want to run a JavaScript function, and get back whatever the function returned.

When you work with Captain, you first create a JSContext object, which serves as the execution environment for all of your scripts. You can create as many contexts as you like, but each one is kept separate from each other, and variables won’t be shared between them.

Creating a JSContext looks like this:

JSContext* context = [[JSContext alloc] init];

Once a context has been set up, you can give it JavaScript code to execute. You do this using the evaluateScript:error: method:

NSError* error = nil;
[context evaluateScript:@"1+1" error:&error];

This method returns whatever the result of the script you passed in was. If the JavaScript code threw an exception for any reason, the error variable will contain information about it.

Any values returned by the evaluateScript: method are returned as Objective-C objects, and are automatically converted from their JavaScript type into the most appropriate Objective-C type. Strings are turned into NSStrings, numbers become NSNumbers, and JavaScript objects get turned into NSDictionary objects.

NSNumber* returnedNumber = [context evaluateScript:@”31337” error:nil];
   // returnedNumber == @(31337)

Calling native functions from JavaScript

Basic stuff, right? However, the fun stuff happens when you give the JavaScript code some native functions that it can call.

You can add register functions in the JavaScript context that scripts can call, by creating a block object and giving it to the JSContext. These block objects take one parameter, an NSArray that contains the parameters that were passed in from JavaScript, and return an id, which will be automatically converted back to a JavaScript value.

Example time!

JSFunction addTwoNumbers = ^(NSArray* parameters) {
        if (parameters.count < 2)
            return 0;
        NSNumber* firstNumber = parameters[0];
        NSNumber* secondNumber = parameters[1];
        return @(firstNumber.intValue + secondNumber.intValue);
    };

[context addFunction:doSomethingFunction withName:@"doSomething"];

Once you’ve added a function, you can call it from JavaScript.

NSString* code = @"doSomething(1,2)";
NSNumber* returnedNumber = [context evaluateScript:code error:nil];
// returnedNumber == @(3)

Calling JavaScript functions from native code

Things get really interesting when your native code can call JavaScript code. Because you can load the new code at run-time, or even replace code without having to re-launch your app, you get a crazy amount of flexibility.

If you run some JavaScript code that returns a function, it will be returned to as a JSFunction block, which can be called just like a function.

NSString* code = @"(function(personName) { return \"hello, \" + personName; })";
JSFunction returnedFunction = [context evaluateScript:code error:nil];

NSString* string = returnedFunction(@["world"]);
// string == @"hello, world!"

Working with native objects in JavaScript

Working in only numbers and strings is boring. What would be really awesome is if Captain could let JavaScript work with Objective-C objects in a clean, simple way that had zero programmer overhead, and let the developer write clean code in both languages.

Wait, you can? BONUS.

TestObject* myObject = [TestObject new];
myObject.name = @"Bob";

[context setProperty:@"testObject" toObject:testObject];

[context evaluateScript:@"testObject.name = \"Alice\"" error:nil];

// myObject.name == @"Alice"

Any property that uses the standard compiler-generated setter and getter methods can be modified by JavaScript code.

In addition to working with data, you can also call methods on Objective-C objects from JavaScript.

But doesn’t Objective-C have crazy weird method names that look ugly in other langauges?

That’s right, it does. That’s part of the reason why Captain only exposes certain methods to JavaScript.

If your Objective-C object has a method named handleFoo:, which takes one parameter, it will be exposed through JavaScript as “foo”. Only methods that meet these requirements are callable from JavaScript.

The reasoning behind this is that Captain is intended to be a simple way to expose limited amounts of domain-specific functionality to a scripting environment, rather than a comprehensive scripting bridge. By only having to support a limited amount of interaction between native code and the script, life is made easier for both worlds.

Example! Here’s an Objective-C object:

@interface MyObject : NSObject

- (id) handleDoSomethingUseful:(NSDictionary*)parameters;

@end

@implementation MyObject

- (id) handleDoSomethingUseful:(NSDictionary*)parameters {
    // Assume parameters[0] is a string

    return [parameters[0] stringByAppendingString:@", yes!"];
}    

@end

And here’s code that interacts with it:

MyObject* foo = [MyObject new];

[context setProperty:@"foo" toObject:foo];

NSString* code = @"foo.doSomethingUseful(\"Bruces\")"

NSString* returnedString = [context evaluateScript:code error:nil];

// returnedString == @"Bruces, yes!"

Loading scripts

The final piece to this is in loading a large number of JavaScript functions, which native objects can use.

Let’s say you’ve got a JavaScript file named “UsefulFunctions.js”, and it contains this:

this.doSomething = function () {
    log("Hello from inside JavaScript!");
    return 123;
}

this.frobnicate = function(a) {
    return a + " " + a;
}

You can register the entire set of functions contained in the script using the loadScriptNamed:error: method.

[context loadScriptNamed:@"UsefulFunctions" error:nil];

Doing this causes the JSContext to look for the file “UsefulFunctions.js”, first in the Documents folder, and then in the built-in bundle resources. Because it looks in this order, you can modify the app’s functionality by simply dropping in a replacement file with the same name in iTunes File Sharing, and re-launching the app.

Delegating behaviour to JavaScript

The functions that you load in can also be used by Objective-C objects to delegate some of their behaviour to.

For example, say you have a JavaScript file ‘Foo.js’, containing the following code:

this.doSomething = function() {
    this.name = "Bob";
}

Once Foo.js is loaded in, you can call the function, and additionally provide it with an object to use for the this variable.

MyObject* foo = [MyObject new];
[context callFunction:"Foo.doSomething" withParameters:nil thisObject:foo error:nil];

// foo.name == @"Bob"

With this method, your classes can easily call out to JavaScript when they need some work done.

Conclusion

We hope you enjoy using Captain, and we’d love to see what else you do with it. Captain is on GitHub! We welcome pull requests, and if you’ve got any questions, shoot us an email at lab@secretlab.com.au

Enjoy!

Swipe Conference 2012

by Doctor Science

Jon from Secret Lab presenting at Swipe Conference 2012Last week in Sydney was the second ever Swipe Conference –– an Australian iOS and OS X developer event. Secret Lab was again in attendance and, as always, the Apple developer community was great fun to hang out with and learn from –– and the organisers, Jake MacMullin, Mark Aufflick and Sean Woodhouse really put on a fantastic event.

We were also again fortunate enough to have a chance to contribute to the conference (Paris spoke at the first ever Swipe Conference, in Melbourne last year), with Jon presenting Cocos2D for Fun and Profit, a quick guide to the Cocos2D graphics library. Designed as a fast introduction to this time-saving library, this talk leads the audience from a minimal starting point to a full game.

Slides from Secret Lab's presentation on Cocos 2D at Swipe Conference 2012

We’re incredibly fond of Cocos2D, as it provides a very nice middle option for people who want more power than what UIKit can provide, but don’t want to deal with the.. joy that is OpenGL. With Cocos2D, it’s straightforward to create a scene comprising a number of quads, and even more trivial to animate these quads in useful ways.

We’ve uploaded the code and slides to GitHub and Speakerdeck, and encourage you to take a look! We had a number of people approach us after the talk and mention that they were now interested in making games with this library, so hooray, we’re sharing the love!

We also took a lot of photos at Swipe Conference –– you can find them on Flickr.

PyCon Australia 2012

by Paris Buttfield-Addison

PyCon AustraliaThis month we were lucky enough to sponsor and attend PyCon Australia, hosted (for the first time) in our hometown of Hobart! PyCon Australia is the national conference for users of the Python programming language. This was the third year that PyCon Australia has run since being founded in Sydney.

We greatly enjoyed meeting members of the Australian and international Python communities, hearing their stories, tips and interests. All the sessions we attended were fabulous, but amongst the many highlights were:

  • CodeWars – entertaining programming-as-a-spectator-sport problem solving to kick the conference off. Hosted and designed by our talented friends Tony and Josh, respectively. A great place to spot some amazing nerd gear!
  • What to build. How to build it. – the first keynote, presented by Mark Ramm, took us on an entertaining romp through the idea of applying experimental methodologies to product design. Great stuff!
  • Virtual robotic car racing with Python and TORCS – Python and virtual robot cars! What’s not to like?
  • Python for Humans – the second keynote, presented by Kenneth Reitz, was a thorough and useful discussion of making Python more user (programmer) friendly. Exactly the sort of stuff that should be a keynote!
  • Lightning Talks – we always love lightning talks, and these were no exception. Lots of quick talks, mostly useful, and highly entertaining!

PyCon Australia Coffee –– blended and served by Ritual Coffee Tasmania, sponsored by Secret LabWe also thoroughly enjoyed the dinner (a cruise to Peppermint Bay, followed by a fabulous meal and cruise back to Hobart!) as well as the coffee (which was a tasty blend called “African Swallow“, designed specifically for PyCon Australia by Ritual Coffee). The coffee for all attendees was sponsored by Secret Lab, and we were proud to have our logo on every cup. The attendees all really seemed to enjoy the coffee, and we’re very proud to have been involved in a small way in the running of such an excellent conference in Tasmania. PyCon Australia returns to Hobart next year as part of their 2-year cycle. We can’t wait!

Secret Lab's coffee sponsorship of PyCon Australia 2012

You can find the rest of our photos from PyCon Australia 2012 on Flickr and the videos from PyCon on YouTube. Congratulations to our friend, and frequent collaborator, Chris on the meticulous organisation he and his team undertook to bring us PyCon Australia!

Using JSON to load Objective-C objects

by Jon Manning

You want to write an iOS or OS X app that quickly and easily retrieves some data from a server and converts it to an Objective-C class. Also, you want to write the server using something standard, like Django or Ruby on Rails.

The standard way that you’d do this would be using NSCoder, where your client application would receive the data and you’d unpack it like so:

SomeObject* myObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];

However, the file format for serialised objects is internal to iOS and OS X, and is also a binary format that’s very difficult to read while in transit.

We recently had a similar problem, where we wanted to have our server send data in JSON format, which we like because JSON’s pretty human-readable. We could implement our own custom implementation of NSCoder, but we were after a more lightweight solution.

Key-value coding

This is where key-value coding comes in. Key-value coding is a feature of Cocoa that lets you access properties and instance variables of class at runtime by name, rather than simply at compile time.

For example, if you had a class that had an NSString property called “name”, you could access it like this:

NSString* name = [myObject name];

Or you could access it with key-value coding, like this:

NSString* name = [myObject valueForKey:@"name"];

Likewise, you can set the name property like this:

[myObject setName:@"Bob"];

But you could also set it using key-value coding, like this:

[myObject setValue:@"Bob" forKey:@"name"];

The advantage of key-value coding is that you can generate the keys at run-time. Your code doesn’t have to know about the properties and variables kept inside an object in order to attempt to get and set the values.

This is where our lightweight serialisation comes in. Let’s say that we’ve received some JSON data that looks like this:

{
    "name":"Bob",
    "income":75000,
    "title":"Janitor"
}

In this example, we’ve also got an Objective-C object that has matching properties:

@interface Employee
	
@property (strong) NSString* name;
@property (assign) int income;
@property (strong) NSString* title;

@end

Converting the JSON data into a dictionary is pretty easy.

NSDictionary* dictionary = [NSJSONSerialization JSONObjectWithData:JSONData options:0 error:nil];

You can then create the Objective-C class from this dictionary by creating a new Employee object, and then iterating over each of the keys in the dictionary, using setValue:forKey: to set the values.

Employee* employee = [[Employee alloc] init];
	
for (NSString* key in dictionary) {
    [employee setValue:[dictionary valueForKey:key] forKey:key];
}

This works even for non-object properties like Employee’s income property, which is an int. In this case, the dictionary loaded from the JSON contains an NSNumber object for the income field; when setValue:forKey: is used for that key, it automatically extracts the int from the NSNumber and applies it to the class.

There’s an even easier way to set all of the values:

[employee setValuesForKeysWithDictionary:dictionary]

Loading objects when you don’t know the class

Another possible use case is one where you receive a chunk of JSON, but you don’t know ahead of time what kind of object the JSON should be turned into. This is where NSClassFromString comes in handy.

If your JSON object contains a field called, say, class, you can use that to create the empty object. Like so:

Class ObjectClass = NSClassFromString([dictionary objectForKey:@"class"]);
	
if (ObjectClass == nil) {
    // the class doesn't exist; give up
    return;
}
	
NSObject* loadedObject = [[ObjectClass alloc] init];

// Load the properties as above

The reason we use NSObject in the above example is because all NSObjects support the key-value coding methods. Even though loadedObject is treated as a generic NSObject, the fact that it was created with whatever class ObjectClass is determined to be means that the object will be what you specify.

Dangers and Caveats

This technique only applies for simple properties, like strings and numbers. More complex data types or references to other Objective-C objects need to be handled differently.

If you use setValue:forKey: on a key that doesn’t exist in the target object, the object will throw an exception and crash. There are a couple of ways you can handle this; one is to implement the setValue:forUndefinedKey: method in your classes.

This method is called when you try to set a value for a property or instance variable that doesn’t exist. The default implementation throws an exception and crashes; you can implement your own that leaves a warning, for example.

A final note: this is a very quick-and-dirty solution. If you want more reliable behaviour, you’ll need to add more checks and validation code. For simply loading objects, it works pretty well.

O’Reilly Interview

by Paris Buttfield-Addison

While at OSCON this year, Jon and I were lucky enough to be interviewed by our editor, Rachel, for O’Reilly Radar. Find the interview embedded below, or check it out on O’Reilly.

Our upcoming book, Learning Cocoa with Objective-C Third Edition, can be preordered now if you’re interested! It’s going to be amazing.

Using OmniGraffle as a level editor

by Doctor Science

This was a fun one.

As we’ve mentioned before, we’re currently working on a board game for a client. Without going into the details, the game is based on nodes on a game board that are linked together; players move between connected nodes, and claim territory.

When coding up the game, we initially generated the game boards in memory, by directly instantiating ‘node’ and ‘link’ objects. Then, when it came time to make the game load different boards on demand, we created a JSON-based data structure that defines the nodes and links. It looks a little something like this:

	{
	  "nodes": [
	    {
	      "id": "Node-84578",
	      "positionX": 423,
	      "positionY": 424
	    },
	    {
	      "id": "Node-10710",
	      "positionX": 198,
	      "positionY": 424
	    }
	  ],
	  "links": [
	    {
	      "nodes": [
	        "Node-84578",
	        "Node-10710"
	      ],
	      "identifier": "Relationship-84578-10710"
	    }	    
	  ]
	}

This structure defines two nodes, including their names and positions, as well as a relationship that links the two together. (Because the graph is nondirectional, we didn’t want to define links in the node data structure itself.)

This is all well and good for simple game boards, like this:

But then the client said, “cool, can you make this?”

And we were all:

Clearly, hand-coding wasn’t an option, and a tool was needed. Writing one ourselves wouldn’t have been the best use of our time, so we looked at our favourite Mac app ever: OmniGraffle Pro. OmniGraffle already knows about objects and connections, and it exposes all of this information through AppleScript.

So, we went searching, found this excellent Gist by Michael Bianco, and adapted it into one that extracts the information we need and generates the game board data that we care about.

Loosely put, it turns this:

Into a level that can be loaded:

How it works

First, we designed the level. In this board game, there are only nodes and connections; we represented nodes as circles, and connected the nodes with lines.

The first thing the script does, we get access to OmniGraffle via the Scripting Bridge:

	# We use the json gem to render the output
	require 'rubygems'
	require 'json'

	# Import the scripting bridge so we can communicate with OmniGraffle
	require 'osx/cocoa'
	include OSX
	OSX.require_framework 'ScriptingBridge'

	# Replace "OmniGrafflePro" with "OmniGraffle" if you don't have Pro
	graffle = SBApplication.applicationWithBundleIdentifier_("com.omnigroup.OmniGrafflePro")

OmniGraffle exposes a list of shapes, which AppleScript can query for important information such as the origin point, and its text. You can also query and set a special “tag” property for each shape, which is useful for storing an identifier. We base the identifier on the text of the shape, if it has any; otherwise, we use a random number.

So, to generate the list of game nodes, we ask OmniGraffle for all shapes, and format the result into a hash, which we store in an array for later.

When generating the hash for a node, we can also make use of the user data dictionary that OmniGraffle Pro exposes. This lets you set custom key-value pairs for a shape, which is very useful for setting things like which player owns a node, or at what point in the game the node becomes active. This is a simple matter of merging in the userData hash.

	$shape_list = []

	graffle.windows[0].document.canvases[0].layers[0].shapes.select do |s|  

	  text = s.text.get.to_s
	  if text == "":
	    text = rand(100000).to_s
	  end
  
	  s.tag = text
  
	  $shape_list << {
		:positionX => s.origin.x.to_i, 
		:positionY => s.origin.y.to_i, 
		:id => "Node-" + s.tag}.merge(s.userData)
		
	end

Once all nodes have been processed, we know that all shapes have had a tag associated with them; we can then iterate over all shapes a second time, this time generating information for each connection.

	graffle.windows[0].document.canvases[0].layers[0].shapes.select do |s|

	  s.outgoingLines.each do |l|
    
	    l.tag = "Relationship-" + l.source.tag.to_s + "-" + l.destination.tag.to_s
    
	    $line_list << {:identifier => l.tag, :nodes => ["Node-" + l.source.tag, "Node-" + l.destination.tag]}
	  end
	
	end

Finally, we export the nodes and links as JSON:

	json_rep = {:nodes => $shape_list, :links => $line_list}
	puts JSON.pretty_generate json_rep

Because this script operates on the frontmost open document in OmniGraffle and outputs to stdout, saving the JSON is as simple as a one-line command:

	$ ruby graffle2board.rb > MyAwesomeBoard.board

Summary

This is a pretty powerful technique, since it lets us design the game maps with a powerful (and, more importantly, pre-existing) tool and import them exactly the way we want them. We’re definitely going to be using this more in the future.

You can see the script in GitHub!

UIView+Glow: Fancy Glowing Effects for Everyone

by Jon Manning

We recently needed to add a tutorial to a board game (see SLTutorialController), and realised that we needed a way to highlight various controls and other user interface elements that the user should interact with next. A common way that this is handled is by making things glow, often with an animation.

So, we wrote UIView+Glow. It’s a very simple category that adds two methods: startGlowing and stopGlowing. When you call startGlowing, the view will start to pulse with a soft light; this effect is removed when stopGlowing is called.

You can see a video of it in action here:


It’s available on our GitHub now!

Follow

Get every new post delivered to your Inbox.