Skip navigation

Monthly Archives: July 2009

Been WAY too long since I’ve done a review.  I feel a little out of it tonight, but here it is:

Left 4 Dead

Platform: 360   PC    Rating: M    Genre: FPS/Survival Horror

What it is:

Visceral, intense, and built for friends.  Zombie hordes, gripping visuals, believable characters, and forced teamwork push the Survivors to the brink to stay on their feet.  All too often a good game of L4D has the survivors limping into the safe-house with a Tank and the horde on their heals, down to just pistols and temporary health.  Not for the faint of heart at higher difficulties.  Online play with anonymous teammates is rarely as gripping as with a group of close friends striking out to complete the current campaign.  If you can, grab some of your pals and get a game rolling on Expert, just to see who would crack in the zombie apocalypse.

What it isn’t:

Sprawling, forgiving, or for sore losers.  There is a severely limited number of maps.  While the AI Director makes them less predictable, they pretty much turn out the same way every time.  A single fortunately-placed Special Infected and you are down for the count.  With this vulnerability, you have to get used to the idea that part of the game is death.  And if not death, then injury, low ammo, desperation and no hope.  For some less-mature players, this reality of Left 4 Dead is the hardest part of the game.

Pros:

Gripping and tense, highly stylized, a great interactive story.  Still waiting for it to get boring, despite expectations.  Very fun online with friends and tolerable online with other people.  AI Director keeps the game tense and is a cool piece of tech.

Cons:

Limited number of maps makes it easy to figure out good defensive positions.  The number of frivolous achievements easily offsets the number of truly interesting achievements, making progress in your achievements feel significantly less rewarding.

Rating:

– Highly Recommended:

Splatter some zombies with your friends.  Solid, stylized horror.

Advertisements

It took an entire day to get In-App purchases to work.  TOTALLY unnecessary.  Apple’s docs on the subject are worthless, so I figure it’s time for another Coding Help Blog Post ™.

Alright, so getting a store in place is a bit involved, but I’ll do my best:

Include the StoreKit framework in your project and apply the appropriate #import.  In your main view controller, you will want to begin querying the App Store for product information as soon as possible so you can store the returned information before it’s needed to avoid network traffic slowing your user down.  You will also need to set up transaction observation in order to receive payment information.  To do this add the following lines to your main view controller:

NSSet* productIDs = [NSSet setWithObject:@”com.yourcompany.yourapplication.####”];
SKProductsRequest* productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers: productIDs];
[productsRequest setDelegate: self];
[productsRequest start];
[[SKPaymentQueue defaultQueue] addTransactionObserver: self];

This will ping the App Store for product information pertaining to the product IDs associated with the productIDs given in the set.  When the request receives a response, it will call your view controller’s -productsRequest:didReceiveResponse: method.  In this method, you will want to store the products array provided by the response object.  In this method, you should also check the invalidProductIdentifiers property of the response object to make sure that everything made it through and to respond otherwise.

You can use the information from the response array to populate your GUI and allow users to purchase.  Once the user has chosen a product to buy you will have to intercept their choice and send out for App Store information.  To do this, you create a payment object with the desired product ID and send that out to the App Store.  That will look something like this:

SKPayment* thePayment = [SKPayment paymentWithProduct: someProduct];
[[SKPaymentQueue defaultQueue] addPayment: thePayment];

This method will ping the server with a payment request or a test request if you are using the sandbox.  The request will return to your -paymentQueue:didUpdateTransaction: method.  In here you need to determine the state of the payment object that the update returned.  To do this, iterate over all of the transactions while switching on their transactionState property.  Upon SKPaymentTransactionStatePurchased, you will need to validate the receipt information, begin downloading, and close out the payment.

Most important of these is receipt validation.  To do this, create a string using the returned transaction’s receipt data and turn that into a string.  This string is actually a JSON object which can then be passed to your PHP server (or whatever) to be then forwarded to the App Store for receipt validation.  Your code will probably look something like this:

NSString* jsonObjectString = [YourClass encode: (uint8_t*)[[transaction transactionReceipt] bytes]  length: [[transaction transactionReceipt] length];

NSString* completeString = [NSString stringWithFormat: @”http://yourserverhere.com/yourValidationScript.php?receipt=%@”, jsonObjectString];

NSURL* urlForValidation = [NSURL urlWithString: completeString];

NSMutableURLRequest* validationRequest = [[NSMutableURLRequest alloc] initWithURL: urlForValidation];

[validationRequest setHTTPMethod: @”GET”];

NSData* responseData = [NSURLConnection sendRequest: validationRequest  returningResponse: nil  error: nil];

NSString* responseString = [[NSString alloc] initWithData: responseData encoding: NSUTF8StringEncoding];

int success = [responseString intValue];

You will have to add the following code to your project.  It’s recommended you put this code in as a category to NSString, but it can be place pretty much anywhere.  The following code can be found here: http://www.cocoadev.com/index.pl?BaseSixtyFour at the bottom.

+ (NSString*) encode:(const uint8_t*) input length:(NSInteger) length {
    static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
    uint8_t* output = (uint8_t*)data.mutableBytes;

    for (NSInteger i = 0; i < length; i += 3) {
        NSInteger value = 0;
        for (NSInteger j = i; j < (i + 3); j++) {
            value <<= 8;

            if (j < length) {
                value |= (0xFF & input[j]);
            }
        }

        NSInteger index = (i / 3) * 4;
        output[index + 0] =                    table[(value >> 18) & 0x3F];
        output[index + 1] =                    table[(value >> 12) & 0x3F];
        output[index + 2] = (i + 1) < length ? table[(value >> 6)  & 0x3F] : '=';
        output[index + 3] = (i + 2) < length ? table[(value >> 0)  & 0x3F] : '=';
    }

    return [[[NSString alloc] initWithData:data
                                  encoding:NSASCIIStringEncoding] autorelease];
}

This will encode your JSON string to Base64, which can then be passed to your server and on to the App Store for validation.

The variable ‘success’ can be anything your server wants to return to indicate success, but the App Store returns a 0 on success.

Hope that helps.  It was certainly a pain in the ass for me and my co-workers.  Good luck!

I have been using a really cool little utility that I’d like to share with the 3 people who read my blog: The Clang Static Analyzer.  This little command-line utility is pretty damned slick.  What it does is it parses your code and identifies possible memory leaks and logic errors.  It’s a bit of a pain to get running, but once it’s in place, it’s VERY helpful.  I should mention that it works best for Objective-C and is built with Mac OS X and Xcode in mind.  Still, if you are working on a Mac or been having memory issues on the iPhone project, ClangSA is for you!  So let’s get started:

Go here Clang Static Analyzer Page and download the Latest Build, which should be near the top.  Once that has downloaded, unzip it and rename it to something like ClangSA or whatever you want.  I will be using ClangSA for the purposes of this tutorial.  Put the newly named folder wherever you like, I would recommend your Developer folder.

Alright, so now you have the Clang build on your desktop.  Where to from here?  Well, we could just use it as is, but this means you will have to cd into your Desktop and use the analyzer’s explicit path every time you want to use it.  Instead, we are going to write a shell script (*gasp* command line?!) to make the analyzer available to you from anywhere.  I use tcsh, but we will build a script for both tcsh and bash, just for fun.

Open your Terminal application.  From your ~ directory (Home) find your /bin folder.  If one does not exist, create one with: mkdir ~/bin.

Next: cd ~/bin.  Now that we are inside the bin folder, we are going to make a symbolic link to the analyzer.  To do this type: ln -s <Location of your ClanSA directory>/scan-build.  *WARNING* moving your ClangSA directory after making this link will break it.

We now have a link to the scan-build command for the analyzer.  This command is run on your code to execute the analysis.  For this next part you will need to check your shell.  Type: echo $SHELL.  If the result of that is tcsh, read on.  If it is bash, go down to the BASH section.

TCSH

Navigate back home with: cd ~.  Next, type: emacs .cshrc.  If there is already contents in this file, add the following to the end of the file.  Type in the following:

set path = (~/bin $path)

Right.  This makes ~/bin part of the command-line’s search path for global commands.  This will allow us to invoke scan-build from anywhere, which is VERY handy.  Save the file with Ctrl-x Crtl-s.  Then exit emacs with Ctrl-x Ctrl-c.  After the bash section is more information, so skip down there and check it out.

BASH

Navigate to your home directory with: cd ~.  Then open up the editor with: emacs .profile.  If text already exists in this script, just put the following at the bottom.  Enter the following text into the script:

export PATH=~/bin:$PATH

That’s it!  Save the file with Ctrl-x Ctrl-s.  Then exit emacs with Ctrl-x Ctrl-c.  This allows us to invoke scan-build from anywhere, which is VERY handy.

NEW JUNK – STOP SCROLLING!

If you haven’t read the Clang site yet, I’ll reiterate what it says here as well as explain how to use it.  Clang is best used on a project that has not been recently built.  So before using the ClangSA, open your Xcode project and do a Clean.  This will get rid of temp files and mark all of the source as unbuilt, which is necessary for the analyzer to work.  Once you have cleaned the project, open up the Terminal again.

Cd into your project folder.  If you do an ls, you should see all of your source files and the project file.  From inside this directory, type the following command:

scan-build -k -V xcodebuild -configuration Debug

This calls the scan-build command that we made global in the scripts above.  It should start spewing out a lot of information, but none of it is really what you are looking for.  When it’s done, it should open up a browser window with bug and memory information.  Oh, yeah, you always want to use the Debug configuration.  Apparently, Clang has a nasty habit of modifying and parsing build configurations, so it’s best to break Debug should that happen.

If you are building an iPhone project you will need to include your sdk.  To do this, type in the following line:

scan-build -k -V xcodebuild -configuration Debug -sdk iphonesimulator<SDK version, such as 3.0>

And that’s it!  The analyzer is not perfect, but DAMN is it ever helpful.  And it’s also pretty smart, so work with it to improve your code.  I really hope that Apple makes this an integral part of Xcode in the future (which is the current rumor).  Code away!