Category Archives: iOS

Lua for scripting NPC behaviour

With character movement looking good, now it’s time to give the non-player-characters (NPCs in role-playing game parlance) some behaviour.

I have the idea that monkeys might chase after bananas, foxes after chickens, etc.  And what platform game would be complete without animals mindlessly going back and forth patrolling their platform?

After reading this post at Stoked Software, I like the idea of using Lua to script NPC behaviour, even though I’m sure the simple behaviours above could be much more easily done without it.  I downloaded Lua following the instructions in the second part of that post, and added it to my project by renaming the src folder lua, and dragging it into my XCode project. (Unlike the post, I downloaded Lua 5.2.1, not 5.1.)

Note this is the bare bones DIY approach, not using any existing wrappers like Wax or Corona, which are nicely described at Lua Nova. I’ll try it this way until I get frustrated.

Some initial set up decisions:

  • I decided to include the header files directly into the GameModel, since we only want one Lua state.  I was originally thinking of having one per animal.
  • Whereas the post adds an instance variable lua_State *l, I am adding a @property (readwrite) lua_State *luaState.
  • Also, to keep the NPC control separate from the rest of my code (in case I decide one day to use something other than Lua), I have added an NPC category to GameElement.

Some hurdles:

  • I get lots of “Undefined symbols for architecture i386:” errors, starting with one for luaL_error, the first Lua call I was trying to make. I posted a question on stack overflow which quickly sorted this out: it is because Box2D is in C++, but Lua is in C.  So you need to wrap the Lua includes with an extern "C" command. (See stack overflow for the precise solution.) In fact you’ll also need to wrap all the upcoming C code in this.
  • I get the error “Use of undeclared identifier ‘self‘” when the static C function which communicates with Lua tries to access the GameElement self. This is OK, the C code doesn’t have any concept of self; it means you have to pass the relevant object from Lua to C. Fortunately, the Stoked Software blog explains how to do this in Part 3, for enemy ships.
  • ARC – I have used __bridge everywhere so there is no transfer of ownership, would appreciate any thoughts on whether that’s correct.
  • Lua 5.2 does not use luaL_register, but instead luaL_setfuncs.  There’s a good discussion on the Lua users wiki, but in the end I could not make this work, so had to go back to Lua 5.1. Any advice on how to apply this to Lua 5.2 would be gratefully received.
  • The Stoked Software blog gives great examples of how to send position data from Objective C to the Lua script, and how to get the Lua script to trigger methods in Objective C so long as the only parameter is a single object.  However, I want to set a target point using Lua.  I have stumbled upon one way to do this, hinted at by the Lua users wiki, using luaL_checknumber, e.g.
    static int setTarget(lua_State *luaState) {
        //
        // Parameters: The GameElement whose target you want to set
        //             The x-coordinate of the target
        //             The y-coordinate of the target
        //
        // Returns: nothing
        //
        GameElement *element = (__bridge GameElement *)lua_touserdata(luaState, 1);
        float x = luaL_checknumber(luaState, 2);
        float y = luaL_checknumber(luaState, 3);
        NSLog(@"target (%6.2f, %6.2f) %@ %p",x,y, element.appearName, element);
        [element touchLocation:Point3DMake(x,y,0.)];
        return 0;
    }

    and then from the Lua script, it’s just:

    function process(gameElement)
      game.setTarget(gameElement, 1.1, 0.5)
    end

    I have no idea if this is a good way to do it, but it works.

     

With those hurdles surmounted, I can now use Lua to script my NPC behaviour.  I just need to think what that should be…

One last note – I see that the license for Lua requests that users give Lua credit (see the download page).

  

Saving objects as property lists

Previously I have saved objects in Cocoa using NSEncoding.  However, for my game I want to save the GameModel’s layout as an intelligible text file.

One way to do this is to save the object as a property list (or plist), which is simply an NSDictionary.  The result is an XML file.

My game has a GameModel class and this has an NSArray of GameElements. So to pull this off, I added two methods to each of these classes.  The first returns a dictionary which describes the layout of the object.  For GameElement, it looks like this:

-(NSDictionary*) layoutDictionary {
  //
  // Returns keys and values of all the parts of the object 
  //    that need to be saved to define this game layout.
  // This only needs to be overridden by subclasses 
  //    if special structs need to be added (e.g. Point3D).
  // Apart from this, instead, subclasses should add to layoutKeys.
  //
  NSDictionary* dict1 = [self dictionaryWithValuesForKeys:self.layoutKeys];
  NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithDictionary:dict1];
  dict[@"where"] = NSStringFromPoint3D(self.where);
  dict[@"class"] = NSStringFromClass([self class]);
  return dict;
}

It uses the key-value coding (KVC) method dictionaryWithValuesForKeys, which returns the values of the object’s own methods or variables.  I declare which properties are important to save in the layoutKeys variable, which I set up in the GameElement initialisation.

However… you can see there is some special handling of the where struct above.  The reason is that while an NSDictionary can happily have any object in it, if you want to write it out as a plist file, you must only have “plist objects” – NSData, NSString, NSNumber, NSDate, NSArray, NSDictionary and the like. If “where” was in the layoutKeys, the first line above would happily add an NSValue object containing the where struct’s data.  But you could not write this out.

It would be great if you could add custom plist objects.  Please let me know if you know how to do this.  In the absence of this, I have written functions to convert the struct into a plist object (an NSString), and back again, instead. For CGPoint these functions already exist.

The second function then creates an object from a dictionary, for example:

+(GameElement*) elementWithLayoutDictionary:(NSDictionary*)dict inModel:(GameModel*)model {
    //
    // Creates an element, given the relevant piece of the game layout dictionary, and the model.
    // This needs to be overridden by subclasses
    //
    Point3D where = Point3DFromNSString([dict valueForKey:@"where"]);
    GameElement* element = [[self class] elementNamed:dict[@"name"] at:where inModel:model];
    element.scale = [[dict valueForKey:@"scale"] floatValue];
    return element;
}

The GameModel also has layoutDictionary and modelWithLayoutDictionary: functions, which loop through the array of GameElements, e.g.

+(GameModel*) modelWithLayoutDictionary:(NSDictionary*)dict {
    int elementNumber = 1;
    while (NSDictionary* elementDict = [dict valueForKey:
                [NSString stringWithFormat:@"Element-%d", elementNumber]]) {
        [self addElement:[NSClassFromString(elementDict[@"class"]) 
                elementWithLayoutDictionary:elementDict inModel:self]];
        elementNumber++;
    }
}

(You can see that this implementation allows for subclassing of the GameElements.)

That’s basically it.  I then write this out to a plist file using
[layoutDict writeToFile:path atomically:YES];
and read it in using
[NSDictionary dictionaryWithContentsOfFile:path].

I suspect this could be improved:

  • KVC allows for a one-to-many relationship.  Can I use this to remove my custom handling of the array?
  • Is there a way to remove the custom handling of non-plist-objects like the Point3D struct?
  • Perhaps this all comes for free if I used CoreData… but do you then lose control of the data format?

Any thoughts?

  

Cocos2D, Box2D and MVC

As I indicated in my last post, I am going to write my kids’ game in Cocos2D. After implementing the simple bear animation tutorial from Ray Wenderlich, I had a few questions:

  1. How do you use automatic reference counting (ARC) with Cocos2D? The approach I’ve taken is to follow this blog by Steffen Itterheim.
  2. How do you write code with Cocos2D (and maybe with Box2D) in an MVC (model-view-controller)-compliant way?  The approach I’ve taken is to follow this blog and its sequel by Bartek Wilczyński.
  3. How do you add Box2D to the project once you’ve already started it (and continue to use ARC)?  The approach I’ve taken is to make it a static library by following this blog by Red Glasses. This is a pretty involved procedure but does the job. I imagine you can do point (1) above using this approach too – it would be nice to be consistent – but I have not tried this.

I’ve done all this and got it all running, and I thought others may find it helpful, so I have put the result on github at https://github.com/RacingTadpole/Cocos2D-Box2D-MVC-example. You are welcome to download it as a starting point for your own projects, or just to poke holes in it (but please tell me what they are!). The frame rate seems to be only 20-30 frames per second on the simulator, but on a real device it is close to 60, and I have read elsewhere that this stat should be ignored on the simulator anyway. Edit – the project on GitHub was compiled using a slightly older version of XCode, and the latest XCode complains when I try to run it on a device (ld: file is universal (2 slices) but does not contain a(n) armv7s slice: …./libbox2d-lib.a for architecture armv7s ). For now I am solving this by setting “Build Active Architecture Only” to “Yes” in the target’s build settings (see this stackoverflow question), but in the long run it looks like I’ll need to redo step 3 above using the latest XCode.

The game as it stands (called Zambazi) simply involves a host of monkeys and bears falling from the sky onto a grassy foreground, and bouncing like rubber balls. When you touch anywhere, all the animals are hit with random forces.  It’s not much, but my kids find it surprisingly engrossing! They decided you win if you can make all the bears run off the screen before the monkeys… Maybe I’m not so far from the App Store after all? :-)

All images are from Ray & Vicki Wenderlich’s sites – thank you both for making these freely available!

Here’s the basic structure/flow:

GameController

When PLAY is pressed, a GameController is initialized.  The gameController has a GameView and a GameModel, each of which is initialized. The gameController also schedules the updates.

GameView

The gameView has a delegate (actually the gameController) which currently does nothing, because it doesn’t need to know which sprite you’ve touched. This delegate may be useful if you do need to know – see Bartok’s blog for his vision here. In fact I’m planning instead to remove this delegate and simply register the controller with Cocos2D as a touch delegate, as described here.

The view creates the necessary layers:

GameLayer

The gameLayer is in charge of all the sprites. It knows nothing about the view or the controller, but does have a reference to the model. It also registers itself as an observer of notifications from the model. The notifications are:

  • Model initialization – this is so that the gameLayer can get a reference to the model in the first place.
  • Revise game elements – this is so that it can set up the sprites that correspond to the model.

The gameLayer starts by loading in all the sprites for the game, and setting up their actions (CCAction).  I am sure there is a much better way to do this – but this does the job for now.

It also keeps track of which actions are running. This seems an unfortunate complication, but as far as I know, you need to do this so that you can stop the action later. If you can get away with stopping all actions on a sprite – and maybe you can – then you could remove this stuff and use stopAllActions instead.

The gameLayer does not know about Box2D – I see that as a model-level thing.  The gameElements provide their own velocity, where, rotation etc methods.  I have defined a Point3D structure to pass around points – this was when I was thinking the model may have a 3D world even if the view is only 2D.  However, with Box2D, the third dimension is irrelevant – so it would be simpler to just use CGPoint for example.  I am leaving Point3D nonetheless so that if you want to use this code with a 3D model (without Box2D), it shouldn’t be too hard to adapt it.

The other trick is that gameLayer has an NSDictionary (called sprites), with the gameElements as keys and the sprites as the objects. The complication is that NSDictionary copies its keys before it uses them, so that the key winds up being a different object to what you requested.  The solution (implemented in my code) is to override copyWithZone: to return self, without copying, as described in this stack overflow post.  I am assured this is good practice if the object is immutable. All this may be too tricky by half, but it seemed sensible at the time, and works fine.

GameModel

The game model is the Box2D world, and an array of the game elements. When createGameObjects is called (by the Controller – this could equally well be part of the initialization), it sets up some default game elements. It has an update: method which uses Box2D to update the physics; optionally each element may have its own additional update behaviour (I have adopted Bartok’s “Updatable” protocol).

GameElement

The gameElements are the models of the platforms, the enemies, etc.  They basically have a Box2D body and a name.  The name is used by the gameLayer to work out what sprite to show. The gameElement uses Box2D to provide where, velocity and rotation methods, so the body variable itself is kept private (i.e. in a class extension).

I am subclassing GameElement (e.g. Animal) to provide different behaviour for different models.

Technical note – so that subclasses can still access the body variable, I have declared body in a class extension header file called GameElements_Private.h.  Then GameElements.m and Animal.m both import GameElements_Private.h instead of GameElements.h, so that they can refer to body.

Further ideas

As I start to turn this into a functioning game, I have found two further issues, one conceptual, one practical:

  • It’s nice to cleanly separate the model from the view – but the image you are using is a particular size, and I’m finding the model sometimes needs to know this size (so you don’t have to scale the image). I’m solving this with another delegate pattern.  I’ve introduced a NaturalSizeProtocol, which the GameLayer and the GameView follow.  The GameModel then has a naturalSizeDelegate.  When a gameElement needs to know its natural size (i.e. the size the view wants to make it), it asks its naturalSizeDelegate.  This returns the size in model co-ordinates (as a Point3D).  This feels like a contortion of MVC, so I’d love to hear if anyone has a better solution to this.  It has left me wondering if MVC is more trouble than it’s worth after all for image-intensive games.
  • Getting a background image to repeat in Cocos2D is hard.  I have only managed it so far by loading the background image multiple times, which doesn’t seem right.

That’s it for now.  Please let me know if you find this useful, or have any suggestions.

Edit – I have just come across Steffen Itterheim’s excellent post on exactly this subject, which inspired him to write KoboldTouch. Together with problems I am having getting Lua to compile in my Cocos2D/Box2D project, I am starting to wish I had used Kobold2D…

  

Unit testing private functions in Xcode 4

I have found myself in the uncomfortable position of declaring private methods in my .h files so that I can run tests on them, and have been looking for ways around this.

I’ve found discussions about handling this in C++ which have me thinking it is bad programming style to need to test private functions: instead, complex private functions should be moved to a new class where they are public. I like the intellectual purity of this approach, but I have to think about how to apply it in my case.

In the meantime, I would like to have two types of unit tests, those on private functions and those on public functions.  Only the public functions define what the class does, of course, but unexpected failure of tests on the private functions can help me quickly find and debug problems.

Fortunately, another Stack Overflow post pointed me to a solution for Objective C.  I declared a new category (“Private”), put the private methods in the classname+Private.h header file, and deleted the classname+Private.m file.  I then import this .h file in classname.m, as well as the unit tests.

[Note the first time I read that post, I misinterpreted it, and created a .h and a .m file for the new category, and tried to implement the private functions in this new .m file.  This approach doesn't solve the original problem at all.]

Using a “Private” category feels like a nice solution, since I could have declared those private functions in a class extension at the top of the classname.m file anyway.  Adding the Private category just allows the unit tests to access them too.

Nonetheless, I’d appreciate any comments on the benefits are of the purer approach of moving complex private functions into a new class…

  

My first Mac app

I decided to take a break from programming iOS apps, and wrote my first Mac OS X app today.  It was surprisingly simple.  It is based on the NSDocument class, and there is an Xcode template for this.  This template has all the menus, including cutting and pasting, formatting, etc, already built in and function. The main additions to the template were putting an NSScrollView in the window in the Document.xib file so I could edit some text, and adding some code to save and read files.

Of course, there were a few hiccups, which I mostly overcame:

  • The Document.h header file does not care about the NSScrollView; you need to hook it up to the NSTextView instead.  The formatted text sits within the text view, and can be accessed via the textStorage method. This has class NSTextStorage, which is a subclass of NSAttributedString.
  • The vaguely named dataOfType:error: method is for saving data, and the readFromData:ofType:error: method for reading data.
  • I posted the approach I used for reading and writing at Stack Overflow here, because I suspect the way I came up with is not guaranteed to work.
  • You should not set the text in the text view in the reading routine, because it may not exist yet.  Save it to an instance variable.  Set the text to this ivar in the windowControllerDidLoadNib: method.
  • I saved two icons, icon_128x128.png and docIcon_128x128.png, into my project.  In my <app name>-Info.plist I set the icon file to the first file name (including the .png), and under Document types, the Icon File Name to the second file name.  This associates those pictures with my app in some places (e.g. the about box, and within Xcode), but it does not ultimately set my app’s icon in the Finder.  How do I do this?
  • It was surprisingly hard to get the compiled program out of the Xcode environment and into a finished app that appears in the Finder on my Mac. The trick is to archive it, then press “Distribute…” (of course!).  You can choose to distribute it directly, and ad-hoc, and export as “Application”.
  

Compressing data

I had occasion today to compress some data (in the form of an NSData object).  Thanks to many people who have gone before me, this is fairly easy to do:

  1. Add “libz.dylib” to your project’s frameworks.
  2. Unfortunately this library only comes with some low-level functions, e.g.inflateInit2 and deflate.  However, the good people at CocoaDev have created a category on NSData which hides all this.  I only copied the two short methods gzipInflate and gzipDeflate. I can’t work out their formatting – I copied the text from the View Source page, and had to go through it afterwards to re-insert asterisks and take out square brackets.
  3. These two functions work!  I wrote out the data to a file using two path extensions, my original one and “gzip”, and this seems to work; the Finder recognises these files as compressed and does the right thing by them.
  

Dismissing the keyboard

I dragged a UITextField onto my xib file, and hooked up the “Editing did end” action to my view controller, and put some code in there. When I ran it, touching in the text field brings up a keyboard… but the keyboard does nothing, and pressing return does not dismiss it.

The solution is straightforward, but not obvious. You need to set up a delegate which follows the UITextFieldDelegate protocol, and add the following method to it:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange: 
            (NSRange)range replacementString:(NSString *)string {
    if ([string isEqualToString:@"n"]) {
        [textField resignFirstResponder];
        return NO;
    }
    return YES;
}

Note if you are adding a UITextView though, the process is a little more subtle. First up, you probably want to allow carriage returns in the text, so you need to hook up a Done button somewhere else which resigns the first responder. You also need to set yourself up as a delegate for the UITextView, and then implement:

# pragma mark - UITextViewDelegate notifications

- (void)textViewDidBeginEditing:(UITextView *)textView {
    self.activeView = textView;
}

- (void)textViewDidEndEditing:(UITextView *)textView {
    self.activeView = nil;
}

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range 
                replacementText:(NSString *)text {
    // do anything you need, e.g. resize in response to a return key
    return YES;
}

Also, it’s recommended you do this inside a UIScrollView so you can scroll the field out from under the keyboard if needed – see Apple’s docs for more.

  

Animating UIViews

I’ve been searching around for the best way to animate a button so that it would pulse continuously, and then how to stop it animating – without using the deprecated “commit” animation style.  It took some searching, so to save time next time, here is the way I settled on. The tricks are: there are options you can pass that keep the animation repeating, and autoreversing. There is also an option you need to pass if you want the button to still be pressable. And finally, to cancel the animation, just start a short new one which takes it back to its original size, which you must have saved somewhere beforehand. (Do not use an empty final animation though, as that doesn’t seem to stop the old one.)

[UIView animateWithDuration:0.3 delay:0
   options:(UIViewAnimationOptionCurveEaseInOut |
            UIViewAnimationOptionRepeat |
            UIViewAnimationOptionAutoreverse |
            UIViewAnimationOptionAllowUserInteraction)
   animations:^{
      CGFloat inset = -self.myButton.frame.size.width * .1;
      self.myButton.frame = CGRectInset(self.myButton.frame, inset, inset);
   }
   completion:NULL
];
[UIView animateWithDuration:0.15 delay:0
   options:(UIViewAnimationOptionBeginFromCurrentState |
            UIViewAnimationOptionCurveEaseInOut)
   animations:^{self.myButton.frame = self.origFrame;}
   completion:NULL];

One pitfall – I found if the button has an image, and it is already showing at full size, then the above code will not do anything – the image cannot be made larger than full size.

  

Using Gimp

I mentioned before I’d downloaded Gimp, a free paint-style program, to help make graphics for my apps.  I’ve struggled to use it for anything much though, but last night I was able to make a simple tab-bar icon.

To make a tab-bar icon in Gimp:

  • Choose File -> New an make a new 60×60 (for retina) image.
  • Choose Layer -> New Layer and choose layer fill type “Transparency”.
  • Delete the original background layer over in the “Histogram” window: drag the old layer from its position about halfway down the window to the tiny garbage bin in the bottom right corner (on my Mac this is half covered by the window-resizer).
  • Now paint into this layer with black where you want the image.  You should only use one colour.  I tried using black and white, and only union of the two shows up in the tab bar.
  • File -> Export the picture.

To take an existing image and set a background colour:

  • Use the magic wand tool, which selects regions by colour.
  • Select the coloured region you want to make transparent.
  • Choose Layer -> Transparency -> Add Alpha Channel (if you can).
  • Choose Edit -> Clear.

I expect you can use this directly as a tab bar icon now – just the remaining colour information will be ignored.  But I have yet to test this.

  

Reloading table data in a UITableView

Work.

I have been using a UITableView and had quite a bit of trouble getting its entries to update.  Just calling the table view’s reloadData method didn’t seem change anything on-screen.  In the end I found it works fine to manually call tableView:cellForRowAtIndexPath: for each entry you want to update; the following sample code (placed in the relevant view controller) works for a table with only one section in it. myTableView is an IBOutlet.

-(void) entriesUpdated:(NSNotification*) notification {
    int numRows = [self.myTableView numberOfRowsInSection:0];
    [self.myTableView reloadData];
    for (int i=0; i < numRows; i++) {
        [self tableView:self.myTableView cellForRowAtIndexPath:
              [NSIndexPath indexPathForRow:i inSection:0]];
    }
    [self.myTableView reloadSections:
          [NSIndexSet indexSetWithIndex:0] withRowAnimation:
          UITableViewRowAnimationNone];
}

Note this code has (at least) one drawback – it can call tableView:cellForRowAtIndexPath: with a row beyond the table’s size, if rows have been deleted. As a result, that code must explicitly check that the row is valid.

Surely this is not the way you’re meant to do it though? Has anyone else had this problem, and can you point me to a cleaner solution?