Tag Archives: Xcode

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).

  

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…

  

Git

Work.

Today’s task is getting Xcode working with a remote Git repository, so that I can collaborate with others – and use a laptop and a desktop to program.

  • The instructions on github.com are good, and I used them to set up a new username, SSH key, and a repository for a free open-source account.
  • I then followed the instructions at “Xcode 4 and Git for newbies“, which are also good.  The main things to keep in mind seem to be:
    • in Xcode, to set up the repository in the Organizer, you need to press the little plus button at the bottom of the list on the left, and then choose the “Checkout or Clone” drop down – not “add a repository”.  The location is git@github.com:<username>/<repository name>.git .
    • Save the project as “origin”, which sets up an “origin” directory.
    • The password Xcode asks for is the pass phrase used earlier.
  • I then created a new Xcode project, and saved it so that it all went into a subdirectory of the origin directory.
  • Then committing and pushing the files worked perfectly, and they showed up in my github repository on the web.

The next step was to checkout the repository with the same username but onto a different computer.  Trying the naive approach – just opening Xcode and following the same series of steps in the Organizer – led me to the error “Authentication failed because the name or password was incorrect.”  The answer was to copy my private and public SSH keys from the first machine to the second, at ~/.ssh/id_rsa*. Note the terminal command “mount” shows the path to any mounted drives, which is helpful for copying.  Once copied, I tested the connection to github in the terminal with ssh -T git@github.com.  This informed me I had the wrong permissions for my private key, which I fixed with a chmod.  Then I tested the ssh connection as described in the github intro with ssh -vT git@github.com.  This did not work the first time without the “v” flag.  For some reason with the “v” it worked, and I was then able to continue in Xcode and connect to the repository.

One other issue when using multiple machines is making sure you export your developer profile from the Xcode Organizer on the original Mac, and import it into the second Mac’s Organizer.

Off to learn about the functional programming language Haskell this evening, to broaden the mind.