Wednesday, December 4, 2013

From Dev to Release version

...without deleting the app from your device.

Back story:
I do a bunch of testing on all my devices AND I also use (play) live apps on my device(s). In the past I resorted to deleting my test build app and then installing my newly released version, thus loosing all my IAP's and other non-Game Center stats(2).

I've recently started using this method:
Once my new version has been released and is available on the store I take a copy of my current project and reset the version back to the previous one and build for the device. Now I install this version onto my devices. Then either with iTunes (after updating the app) or the App Store on each device, I download and install the updated (released) version. This allows me to install the new updated version without loosing any of my saved data.

1: It's worth mentioning that if you install your live (released) version on your device and then you install your new test build with Xcode, your app will not show up in the list of Applications as (I'm spit-balling here) it replaces the production version of your app. The downside is you cannot get at the app bundle via Xcode.
2: All my game have a resync Game Center functionality (I guess just for me).

Monday, October 14, 2013

GKSession didChangeState delegate not working in iOS 7

So the GKSession transfer code that has been working ever since iOS 4.0 decided to STOP working (1/2 way) under iOS 7. Yeah, right? what else is new? :-p

The specific error or problem was that the connect code to display the alert where the user drags a slider for the desired number of vouchers to transfer, was not showing on iOS 7 device.

The iOS 7 devices DID receive vouchers so that meant the GKSession WAS valid.

So, in debugging it I found that even though the delegate was set, the didConnectPeer callback was firing but the didChangeState: WAS NOT.

So.... an easy-peasy kludge of a patch now allows iOS 7 devices to transfer vouchers to their iOS 6 (and iOS 5) brethren.

- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)thePeerID toSession:(GKSession *)theSession 
self.session = theSession;
self.session.delegate = self
    self.peerID = thePeerID; 
    [self.session setDataReceiveHandler:self withContext:NULL];
    [picker dismiss];
    picker.delegate = nil;
    float sysVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (sysVersion > 6.9) {
       if (!didConnect)
           [self session:self.session peer:self.peerID didChangeState:GKPeerStateConnected];

 Full disclosure: I also added a boolean flag so that the GKPeerStateConnected "state" will only fire once, regardless of "where" it came from.

        case GKPeerStateConnected:
            if (!didConnect) {
                didConnect = TRUE;
                NSLog(@"Peer %@ Connected", self.peerID);
                [self performSelector:@selector(promptForQty) withObject:self afterDelay:1.0];
                self.statusLabel.text = @"Connected";
                [self.launchShareButton setTitle:@"Stop" forState:UIControlStateNormal];
                [self.launchShareButton setTitle:@"Stop" forState:UIControlStateHighlighted];
                [self.connectingActivityIndicatorView stopAnimating];

Thursday, September 26, 2013

Xcode 5 - Fixing Simulator Install Errors

With the GM release of Xcode 5 - building and testing seem okay with iOS 7 however many times when you build and run for iOS 6 the simulator will fail to install your build.

As a work around, INSTEAD of deleting the app from the simulator, just browse to the simulators folder, open the 6.1 (or whatever version you are having the error on), open Applications then find your app and open that folder. Now just remove the .app bundle.

This should allow your new build to install but you SHOULD NOT loose all your settings, saved games, preferences, etc.


Wednesday, September 18, 2013

Prevent Older Apps From Installing

The wonderful black-hole that is iOS development, we (as in all Developers) were informed (not by Apple but by a tech blog) that users can install older versions of apps even AFTER you have released an update.

Yeah, me too... I was like WHAT???? Anyhow, just before I got kicked off the Apple Developer forums (seems I was a bit too vocal) several developers confirmed that yes Veronica there are Angels, er wait no.... When you select the checkbox entitled "Are you upgrading for a legal reason" (<- purposely using the OLD text, notice how they have magically updated the text so it is now only 30% unclear of what it means). This will prevent a user on an older, no longer supported version of iOS, say iOS 4.x from instaling on older version of your app.

Really this IS great news for users and crap-tastic for developers. One question immediately comes to mind, though:

1. If we DO NOT check that box (like I have NEVER, because I've never had to update FOR A LEGAL REASON!) but we DO REMOVE an older version in our Game Center compatibility, what does Apple do???

So there you have it, in all it's Apple-vagueness.

Friday, September 13, 2013

Icon set Creator v2.0 (iOS7)

Previous post here: iOS Icon set Creator

So here's what the updated Automator workflow does:
Asks for your base (512x512 OR 1024x1024) icon image then duplicates it, scales it and renames it, rinse and repeat until all thirteen (13) icons are created.

Notes: If you use 1024 size you can (and should) use that icon to upload to iTunes Connect.

Icon-120.png = 120x120
Icon-144.png = 144x144
Icon-152.png = 152x152
Icon-72.png = 72x72
Icon-76.png = 76x76
Icon-Med-40.png =40x40
Icon-Med-40@2x.png = 80x80
Icon-Small-50.png = 50x50
Icon-Small-50@2x.png = 100x100
Icon-Small.png = 29x29
Icon-Small@2x.png = 58x58
Icon.png = 57x57
Icon@2x.png = 114x114

The workflow WILL NOT overwrite any existing files so make sure to put your base image in its own folder.

1000 words.....

Test folder with 1024 icon (can be named whatever you want)

Launch Automator app and click the Run button...
Browse to and select your 512 icon file
This is where the "magic" happens (lol!)

Completed folder with shiny new icons, yeah!
(Very old image)

In the zip file is a second Automator "application" named "Create iOS Iconset Droplet iOS7". You don't run this application you simply drop your 1024 icon onto it and the magic happens... sweet right? I know... :-]

To use the droplet, just drag the droplet to your Dock. Now when you need a set of icons, place your master image in a folder, then drag it on top of the droplet and give it about 3 seconds and its done. This has a permanent home in my Dock.

Updated: 14-09-2013 - removed the "[ ]" in the name - this caused a problem for some on the droplet. No need to re-download, simply rename and remove the brackets. Thanks @Dragyn at cocos2d forums!

Download link: CLICK ME

Friday, August 16, 2013

Replacement AlertView and ActionSheet

Give that iOS 7 has totally hosed any hope for custom AlertViews I hacked up a couple of nice options available on github.

Here's the finished product in a sample project.

DISCLAIMER: THIS SUITS MY NEEDS, if it doesn't suit your needs, sorry, look elsewhere...

LICENSE: matches the github MIT EXCEPT for Alex1987 - go use your fancy frackin' TSAlertView, 'mm-kay! ;)



Example of what you do by subclassing this:

This was accomplished just like how you'd do it pre-iOS 7 (code snip it below)

- (id)initWithTitle:(NSString *)title yoffset:(int)yoffset minValue:(int)minValue setValue:(int)setValue maxValue:(int)maxValue message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle okButtonTitle:(NSString *)okButtonTitle image:(NSString*)imageName {

self = [super init];
if (!(self = [self initWithTitle:title message:message delegate:delegate cancelButtonTitle:cancelButtonTitle otherButtonTitles:okButtonTitle, nil])) return nil;
    CGFloat xCenter = kTTMaxContentFrameWidth * 0.5f;
    self.mySlider = [[UISlider alloc] initWithFrame:CGRectMake(xCenter-110, kSliderOffsetForY, 220, (kIsAniPad ? 48.0 : 36.0))];
    self.mySlider.minimumValue = (float)minValue;
    self.mySlider.maximumValue = (float)maxValue;
    self.mySlider.tag = 0;
    if (yoffset == -1) {
        self.mySlider.value = 0;
    else {
        self.mySlider.value = (float)setValue;
    self.mySlider.continuous = YES;
    [self.mySlider addTarget:self action:@selector(sliderAction:) forControlEvents:UIControlEventValueChanged];
    // Setup custom slider images
    UIImage *minImage = [UIImage imageNamed:@"leftSide.png"];
    UIImage *maxImage = [UIImage imageNamed:@"rightSide.png"];
    UIImage *thumbImage = [UIImage imageNamed:@"thumb.png"];
    UIImage *thumbPressedImage = [UIImage imageNamed:@"thumbpressed.png"];
    minImage=[minImage stretchableImageWithLeftCapWidth:10.0 topCapHeight:0.0];
    maxImage=[maxImage stretchableImageWithLeftCapWidth:10.0 topCapHeight:0.0];
    // Setup the sliders
    [self.mySlider setMinimumTrackImage:minImage forState:UIControlStateNormal];
    [self.mySlider setMaximumTrackImage:maxImage forState:UIControlStateNormal];
    [self.mySlider setThumbImage:thumbImage forState:UIControlStateNormal];
    [self.mySlider setThumbImage:thumbPressedImage forState:UIControlStateHighlighted];
    [self.containerView addSubview: self.mySlider];

    if (minValue == maxValue) {
        self.mySlider.hidden = TRUE;
self.myLabel = [[UILabel alloc] initWithFrame:CGRectMake(xCenter-120, kLabelOffsetForY, 240, 22)]; //20
self.myLabel.backgroundColor = [UIColor clearColor];
self.myLabel.textColor = [UIColor blueColor];
self.myLabel.font = kTTAlertSliderFont;
self.myLabel.textAlignment = UITextAlignmentCenter;
self.myLabel.text = [NSString stringWithFormat:@"Selected Amount: %i", (int)self.mySlider.value];

if (yoffset == 23) {
self.myLabel.text = [NSString stringWithFormat:@"Selected Amount: %i", (int)self.mySlider.value];
else {
self.myLabel.text = [NSString stringWithFormat:@"Selected Amount: %i", setValue];
[self.containerView addSubview:self.myLabel];
NSString *imagePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:[NSString stringWithFormat:@"Alert/%@", imageName]];
    CGRect iframe = CGRectMake(8.0, 12.0+yoffset, 156.0, 60.0);
    if (kIsAniPad)
        iframe = CGRectMake(12.0, 14.0+yoffset, 312.0, 120.0);
self.myImageView = [[UIImageView alloc] initWithFrame:iframe];
self.myImageView.image = [UIImage imageWithContentsOfFile:imagePath];
[self.containerView addSubview:self.myImageView];    
return self;

- (void)alertView:(TTAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
pressedButton = buttonIndex;

Friday, June 21, 2013

Cocos2d with iAd bannerView

I finally got around to cleaning up my base code I've been using in nearly all my cocos2d apps. This will jump start your project to include an iAd banner (top or bottom, set by macro) along with a few other items.

Feel free to check it out.


Download Project file HERE.

Saturday, March 16, 2013

Wow, March... already!

Sorry for the lack of updates, we've been crazy busy starting last fall with our prep for X-mas games. We ended up releasing FIVE new easy to play games, all of them also being multi-player (2-player) with full Game Center leaderboards and achievements.

We've released a couple more since the rush and so far the feedback has been great!

During December we also started work on our next Space Sim (see this blog for detail) with most of the month planning, designing and checking out the available development tools.

We decided that it should be TWO things:
1. A 3D game
2. A multi-player game

3D because, well it's a lot more immersive and the devices are way more capable. Multi-player because Ella and I really enjoy playing games like Minecraft (on our own server) and Path of Exile (unique MMOG that's not MM).

That loosely defined our next (ORIGINAL) Space Sim game... Skyport-Alpha. A 3D, multi-player (2-6 players) space game that will be developed using Unity 3D and available for Mac & PC and eventually for iOS (iPad only?) devices.