Monday, January 28, 2013

Game Music



Wow - nearly the end of January and I haven't posted here for a week!  Time flies when you're hacking.

This is a really quick post just to frame a quick recording I made of some basic video game music.

I didn't want to just post the music as a raw sound file so I dropped it into a quick video format so I could put it on YouTube, and that also gave me a bit of an opportunity to mention the technologies I used to make the music.

I have a Yamaha PSR-E413 Keyboard, which is a very basic guy - just fine for what I need.  I can play it stand alone as a keyboard but I mostly use it as a midi to drive Garageband.  Because I am very low on the skill level - I can do a few basic chords & scales, that is it - I love the GarageBand ability to do multiple takes until you get something you like.

For this I chose a basic scale and just fiddled about until I found some notes I liked, then worked out a rhythm to suit.  I used GarageBands metronome to get things in time, and then turned that off when I exported the recording.

As I mention in the video to get the atmospheric and futuristic feel I wanted, I used a synth pad.  GarageBand comes with a few but I wanted to be able to tweak it a bit so I picked up NLog Poly Synth from http://www.temporubato.com/

The result is pretty average but good enough to use as a place holder for the early stages of the game, and to give a pro musician an idea of the sort of thing I want if I get funds for a bit of polish on the game.

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!

Tuesday, January 15, 2013

The Solo Gig


Last week or so I've been finishing up at my last full-time paying work, and now I embark on the solo gig.

Today was my first day where my time was not dictated by a clock and a timesheet.

I want to do some drawing every day, doesn't matter how much of it is teh sux - it just gots ta be done.  Here's some rushes.

Its the only way to free up the hands, and get the mind & eye really looking and seeing.  So as painful as it is getting back into it - has to be done.

Between doing some grocery shopping and checking the mail I stopped in at a local cafe for a coffee and BLT.  I sketched a couple of things around the coffee shop.

Now back at home, I had this old shot of me (from just outside the coffee shop a few evenings ago) shot at a funny angle with my cell-phone, and I thought I'd try doing a freehand sketch loosely based off it.

Drawing faces and heads usually follows a formula but for games and comics often the characters are in a strange perspective with the camera or eye positioned underneath (as in this picture) or above - with the character jumping or flying toward it.

When this happens instead of the eyes being positioned exactly half-way down the oval of the face as is usual for a front-on depiction, you get the eyes right up around a 1/3 or so from the top of the head.  That's where you have to use extra care to make sure the perspective and proportions are right.

I didn't like my real hair in this photo so I have gone for a more manga sort of thing, and the result is that the line-work for the hair doesn't look right.  Even though I wanted a "hair falling in my eyes" look, its too heavy over the forehead.  I think from this angle you'd kind of see up under the fringe: and that's quite hard to do.

Also in the under shot like this the tendons and muscles of the neck are more prominent and occupy much more real-estate in the panel.  The jaw & mouth is also more prominent, while the eyes - usually a focus - are smaller and further away.  Here I've made the eyes a bit too small and close together tho' that may be because the hair is framing the top of the head as being too wide.  For the from down-under perspective the head winds up being more egg-shaped: getting narrower at the top, and I haven't really done that here again because of the hair.

I'm using Manga Studio here so I could easily do some work to improve the proportions by grabbing chunks of the line work and moving it round, but as its just a drawing exercise for throwaway purposes there is no point in putting that time in.

I'm hoping this will be a baseline and future posts will show some improvement in my drawing.

Oh, and welcome to 2013.  :-)

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

Traction

Finally starting to get some traction on the game creator having bullied CoreData, Key-Value coding, ArrayControllers and all the other mystical components of Cocoa into doing what I need.  Thanks to all who gave me encouragement!

Screenshot of game creator - 30% done


The game itself is still only partly set up to become data driven, but that I think will be a lot simpler than actually getting the data in there in the first place.  Because so much of it is about the rich world of objects, properties and descriptions the actual game content has to be data driven - hard coding it would have been a massive undertaking and very difficult to debug.

The buttons on the right are for creating exits from the room, and going ahead to the atoms screen to create the contents for that room.  These buttons, and the Atoms and Aspects screens are still on my todo list.  But I can use the room as a model and I'm sure it will be a lot quicker.

Things to add are a launcher button so I can launch the game from the creator, and have the game use [a copy of] the current view of the data as edited by the creator.

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!