Two apps published for app store

Recently I have written and published two iOS apps for the Apple App Store.

moa-icon

Merchants of Amsterdam Clock Utility App
A Universal iOS app replacement for the Dutch auction wind-up clock for the board game “Merchants of Amsterdam”.

The app requires version 8.1 or above. This is because some dependencies required this.

It is currently on the app store (link)

Further information can be obtained on the project page.

—-

Peak Solitaire Card Game app

peaks-icon

A solitaire card game. Uses Game Center Leaderboard to record your high scores.

This app requires version 8.1 or above.

It is on the app store (link)

What cables do you need to develop for Apple TV 4th generation?

Having recently bought an Apple TV 4th generation for development purposes, I thought it might be useful for other developers who wish to dabble with the system to know what cables are needed to deploy your apps from XCode to the actual device.

Notably the Apple TV (4th Gen) doesn’t actually come with the cable needed to connect from your machine to the device; it does come with a cable, but this is only for charging the remote.

Instead, you will need a USB male to male cable (I think it was USB 3.0, but don’t quote me on that); in addition you will need a “USB-C to USB-A convertor” cable. You can purchase this from Apple.

As with all other XCode projects; in order to deploy you will need to get a deployment provisioning profile via the Apple development website.

My first thought was that it wasn’t going to work; Apple is quite harsh on deploying apps onto devices that are not Apple-branded cables; but was pleasantly surprised to see it working.

So in short; you will need:

  • 1x USB to USB (male to male) cable
  • 1x USB-C to USB-A converter cable

I hope this helps.

cocos2d: Displaying a grid of items in a scrollview, clipping node

In a cocos2d iOS game I am currently writing, one of the things I wanted was to display a menu of items using a grid style, display the said menu in a scrollview; so I would have multiple items per page, and then finally — put the items in a clipping node.

Here is a visual representation from my game,

grid

This is a menu of 12 items displayed in a grid of 3×2, that is 6 items per page.

To make this work, I would need to use a CCScrollLayer to paginate between each page, each having 3×2 items on them.

Furthermore, I need to put them in a clipping node. By a clipping node I mean something which clips the viewport in which the grid appears in.

Imagine we have a modal pop-up window, or something where we do not want the visuals to “spill over” a certain boundary; this is what we use the clipping node for.

For all of this to work, you will need the following:

+ cocos2d-iphone v2.x (I did not test for 1.x) (cocos2d website)
+ CCScrollLayer (part of the cocos2d-iphone-extensions in github)
+ CCMenu+Layout.h (Tony Ngo)
+ Viewport (https://gist.github.com/agasiev/3908876) or ClippingNode (via cocos2d website)
+ (Optional) CCMenuAdvanced (See: cocos2d-iphone-extensions)

I used Viewport rather than ClippingNode because I couldn’t quite get it to work, whereas I found Viewport used similar code and seemed to work a bit more straightforwardly.

Anyway, my code now follows. It may not necessarily work for you, but should give you some indications of what I did.

Code:

#import "Viewport.h"
#import "CCMenu+Layout.h"
#import "CCMenuAdvanced.h"
#import "CCScrollLayer.h"
// Notes
// Apple is a custom item.
// List would be your array of custom objects ie: Apples or whatever

// Display the items in a grid            
NSMutableArray *pageArray = [NSMutableArray array];
CCLayer *page = nil;
CCMenu *itemMenu = nil;

int tag = 0;
int count = 0;

// We want a grid of 3x2, this means count must 
// reach 6 before making a new page.
for (Apple *apple in list) {
    if (count == 0) {
        page = [CCLayer node];
        itemMenu=[CCMenu menuWithItems:nil];
        [itemMenu setContentSize:CGSizeMake(300, 100)];
        [itemMenu setAnchorPoint:CGPointMake(0, 0.5)];
        [itemMenu setPosition:CGPointMake(80, 90)];
        [page addChild:itemMenu];
        [pageArray addObject:page];
    }
        
    // Avatar Button
    CCSprite *avtButton = nil;
    
    // Get the image from the custom object
    NSString *fileName = [NSString stringWithFormat:@"%@.png", apple.filename];

    avtButton = [AvatarButton spriteWithSpriteFrameName:fileName];
    [avtButton setScale:0.75];
    
    // Create menu item
    CCMenuItemSprite *btnWG = [CCMenuItemSprite itemFromNormalSprite:avtButton selectedSprite:nil target:self selector:@selector(menuButtonTapped:)];
    [btnWG setTag:tag];
    [itemMenu addChild:btnWG];
    
    count++;
    
    if (count == 6) {
        [itemMenu alignItemsInGridWithPadding:CGPointMake(15, 2) columns:3];
        count=0;
    }
    
    tag++;
} // next

// Now create the scroller and pass-in the pages (set widthOffset to 0 for fullscreen pages)
self.scroller = [[[CCScrollLayer alloc] initWithLayers:pageArray widthOffset:250] autorelease];
[self.scroller setShowPagesIndicator:YES];
[self.scroller setPagesIndicatorPosition:CGPointMake(335, 100)];            

Viewport *cn = [[Viewport alloc] initWithRect:CGRectMake(75,75, 300, 180)];
[cn setAnchorPoint:CGPointMake(0, 0.5)];
[cn addChild:scroller];
[self addChild:cn z:8];
[cn release];

Because we need a grid of 6 items, the `count` variable must reach 6 before “creating” a new page. Each page has it menu aligned to 3 columns.

The page gets added to the pageArray (a list of pages) which are used by the scroller object.

Finally, we create a clipping node and add the scroller as a child of the clipping node’s object before we add the clipping node to self (or it could be a layer).

I’ve been able to test it for 12 items, 6 per page but if you want a custom amount (say 2-4 per page) you must adjust the numbers in the code above to match your expectations.

I hope this helps in your code development.

Recursive disabling of CCNodes

This is an update of my previous post where I was attempting to lock/disable a CCScrollLayer when I launch a modal pop-up dialog.

The previous code doesn’t always work, and I’ve changed it a bit to the below;

It isn’t 100% perfect but it is a bit more recursive than the last version.

Basically the idea is:

  1. I want to disable/enable every node except my CoverLayer and her children, this is implicit because all the pop-up dialog’s appear as a child of CoverLayer
  2. I want to stop all interaction on CCScrollLayers
  3. I want to stop the user from clicking on a MenuItem within the CCScrollLayer multiple times

Again, it isn’t perfect; but its a start.

Put this in where you need to disable stuff; I put it in a singleton or a single controller instance and launch it there.

Code:

// Disabled/Enable layers
-(void) MenuStatus:(BOOL)_enable Node:(id)_node
{
    BOOL showLogs = YES;
    
    for (id result in ((CCNode *)_node).children)
    {        
        if (showLogs == YES) NSLog(@"Node result = %@", [result class]);
        
        if ([result isKindOfClass:[CoverLayer class]])
        {
            // Do nothing
            if (showLogs == YES) NSLog(@" -- Do nothing --");
            
        } else {
            
                
            // Scrolllayer
            if ([result isKindOfClass:[CCScrollLayer class]]) {
                if (showLogs == YES) NSLog(@"A. Found CCScrollLayer...");
                ((CCScrollLayer *)result).isTouchEnabled = _enable;
                [self MenuStatus:_enable Node:result];

            } // end if
            
            // Layers
            if ([result isKindOfClass:[CCLayer class]]) {
                if (showLogs == YES) NSLog(@"B.    Found CCLayer -- %@", [CCLayer class]);
                
                // Disable CCLayer and any children?
                ((CCLayer *)result).isTouchEnabled = _enable;
                
                for (id result2 in ((CCLayer *)result).children)
                {
                    if (showLogs==YES) NSLog(@"  1. child found: %@", [result2 class]);
                    [self MenuStatus:_enable Node:result2];
                } // next
            } // end if
            
            // Menus
            if ([result isKindOfClass:[CCMenu class]]) {
                ((CCMenu *)result).isTouchEnabled = _enable;
            } // end if
            
            
        } // end if
        
	} // next
    
    NSLog(@"-------------");
}

“Almost” bulletproof cocos2d modal alerts and common layers

I’ve been working on a cocos2d game for some time now, its not an arcade game; its more of a solitaire Tycoon trading game as I felt this would be good enough to get me started at least.

Working with cocos2d has been very problematic for me. Things that should be simple take bucket loads of code just to get working.

One of the main things frustrating me is the node system will only allow you add children once (depending of course on context).

In my game I have a HUD (heads-up display) which I want to share across multiple scenes.

Here is a diagram;

What’s happening here is that I have two scenes and I want to share my HUD across both of them.

The HUD also has a menu in it (for example a Settings button) that will launch a modal pop-up dialog.

The way I’ve done it up to now is to use a BaseScene concept;

Code:

@implementation BaseScene

- (id)init
{
    self = [super init];
    if (self) {
        NSLog(@"HUD Scene");        
        [self addChild:[BaseLayer node] z:0 tag:1];
    }
    return self;
}
@end

@implementation BaseLayer
@synthesize currentNode, thisLayer;
@synthesize hud;

-(id) init
{
    if ((self =[super init]))
    {
        self.hud = [HeaderHUDLayer node];        
        
        if (self.currentNode == nil)
        {
            self.currentNode = [GamePlayLayer node];
            [self changeNodeTo:self.currentNode];
        }
        [self addChild:self.hud z:TopZLayer tag:kHUDTag];

        [[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(changeHUDSceneObserver:) name: @"changeHUDScene" object: nil];
    } // end if
    return self;
}


- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}

-(void) cleanup
{
    [super cleanup];
    
    // deregister as observer
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

-(void) changeNodeTo:(CCNode *)thisNode
{
    NSLog(@"changeNodeTo...");
    [self removeChild:self.currentNode cleanup:YES];
    [self addChild:thisNode z:0];
    self.currentNode = thisNode;
}

-(void) changeHUDSceneObserver:(NSNotification *)notification
{
    NSLog(@"changeHUDSceneObserver = %@", notification.name);
    
    if ([notification.name isEqualToString:@"changeHUDScene"]==YES) {
        if ([notification object]!=nil) {
            [self changeNodeTo:[notification object]];
        }
    }
}

You can see here that I have:

  1. BaseScene
  2. A HUD included as a child of BaseScene
  3. All other subsequent layers are changed via NSNotification

Whilst this “worked”, it caused a lot of unforeseen problems.

Unforeseen problems

  1. I had NSNotifications everywhere and the whole project was becoming very unmanageable and messy
  2. I had a problem where Modal alert pop-ups were appearing underneath the HUD, and the modal alert did not disable touches on the HUD layer
  3. Modal alerts did not stop interactions on CCScrollLayers, or you could launch multiple modal alerts with lots of clicks

The solution I’ve come up with is to use class forwarding instances and use brute-force to stop all the interactions.

Class forwarding instances

I don’t know if its actually called this, but it sounds about right.

In the open-source game CastleHassle, the author sends “instances” back to the receiving layer and can pass the instance around; not only this he can call methods within the receiving class.

In summary, it means doing this:

Code:

@implementation MainMenuScene
static MainMenuScene *instance = nil;

+(MainMenuScene *) instance {
	if(instance == nil) {
		instance = [[MainMenuScene alloc] init];
	}
	
	return instance;
}

+(void) resetInstance {
    [instance release];
	instance = nil;
}

// This removes nodes I send to the instance and adds
// new things.
+(void) changeNodeTo:(CCNode *)node
{
    MainMenuScene *main = [MainMenuScene instance];
    [main removeAllChildrenWithCleanup:YES];
    //[main removeChild:self cleanup:YES];
    [main addChild:node];
}

This returns an instance and then you can use it later on.

In the HUD he has a controller, HUDActionController.

Code:

// Hud.mm
-(id) init {
	if( (self=[super init]) ) {
		
        [[HUDActionController instance] setHud:self];
        
        [self drawHeaderLayer];
        //[self drawFooterLayer];
        
	} // end if
	return self;
}

// Doesn't actually make it visible, just here for example
-(void) toggleHUDLayerVisible:(BOOL)yn
{
    NSLog(@"toggleVisible: %d", yn);
    [self scheduleUpdate];
}

-(void) update:(ccTime)delta
{
	// To be safe
	[self unscheduleAllSelectors];
}

The HUDActionController acts like a MVC (not strict MVC) deciding what to launch.

Code:

// HUDActionController.mm
@implementation HUDActionController
@synthesize hud;

static HUDActionController* instance = nil;

+(HUDActionController *) instance {
	if(instance == nil) {
		instance = [HUDActionController alloc];
		[instance init];
	}
	
	return instance;
}

-(id) init {
	if( (self=[super init]) ) {
		NSLog(@"HUDActionController");
	}
	return self;
}

-(void) goToMainMenu
{
// MainMenu needs to be included though
    [MainMenuScene resetInstance];
    [[CCDirector sharedDirector] replaceScene: [MainMenuScene instance]];
}

-(void) toggleHUDLayerVisible:(BOOL)yn {
    NSLog(@"toggleVisibility of Hud = %d", yn);
    [self.hud toggleHUDLayerVisible:yn];
}

So, I could do:

Code:

[[HUDActionController instance] toggleHUDLayerVisible:YES];

Yes, it probably isn’t proper design; like observers or factory methods but its more of a hack really then a proper scientific solution.

So, using this concept, I can create a HUD on multiple layers and launch things on referencing classes using forwarders.

Book solution

In the book “Learn cocos2d Game Development with iOS 5” by Apress at around Chapter 5, the author describes a similar solution using “MultiLayerScene”.

Quote,

Simply put, the multiLayerSceneInstance is a static global variable that will hold the current MultiLayerScene object during its lifetime. The static keyword denotes that the multiLayerSceneInstance variable is accessible only within the implementation file it is defined in. At the same time, it is not an instance variable; it lives outside the scope of any class. That’s why it is defined outside any method, and it can be accessed in class methods like sharedLayer.

The reason for this semi-singleton is that you’ll be using several layers, each with its own child nodes, but you still need to somehow access the main layer. It’s a very comfortable way to give access to the main layer to other layers and nodes of the current scene.

I’ve not used the MultiLayerScene solution, but it seems just as viable as my solution.

I will post code below at the bottom to give you an example.

Now onto the next problem — ModalAlerts.

Modal alerts

One of the biggest stumbling blocks I had were modal dialog pop-ups or “modal alerts” as I will call them.

I’ve been able to work with RombosBlog’s modal alert;

http://rombosblog.wordpress.com/2012/02/28/modal-alerts-for-cocos2d/

It uses blocks to handle callbacks, and is very easy to use.

I can have a layer call up a modal alert, get a callback and handle the rest my own way.

However, it came with its own issues I found very frustrating.

Sometimes, rarely I might add, the modal alert did not stop interaction underneath the CoverLayer (a slightly dimmed CCLayerColor which holds the modal alert).

This was very evident on CCScrollLayers. You could click on, move and interact with CCScrollLayers when the modal alert was being displayed.

The other problem I had with the modal alert if you could click on a CCMenuItem (or a button) very fast you can spawn multiple occurrences of the ModalAlert.

I found this very frustrating.

At first I used this:

Code:

// Disabled/Enable layers
-(void) MenuStatus:(BOOL)_enable Node:(id)_node
{
	for (id result in ((CCNode *)_node).children)
    {
		if ([result isKindOfClass:[CCMenu class]]) {
			for (id result1 in ((CCMenu *)result).children) {
				if ([result1 isKindOfClass:[CCMenuItem class]]) {
					((CCMenuItem *)result1).isEnabled = _enable;
				}
			} // next
		}
	} // next
}

However, it did not stop interactions on CCScrollLayers; worse still I had to put it on every layer I wanted to handle this.

The way around this was to use a BaseLayer (CCLayer) and make all my game layers inherit from this:

Code:

@interface PlayerSetupLayer : BaseLayer // BaseLayer is a CCLayer

Whilst this worked; it only worked it didn’t stop interactions with CCScrollLayers.

To resolve this problem, I ended up using a mess of NSNotifications up the chain of command (CCNodes) to change or lock layers and to display models.

Not only was this bad, its very hard to maintain. It was a mess!

So what’s the solution?

Well so far, I’ve got a “working” solution that is “almost” bulletproof. It is not perfect, though.

The way I’ve done it is to combine the sharing of HUDs across multiple scenes and use the HUDActionController to decide what to do.

For the modal alert, I used a rather hacky solution; just go through every node and disable/enable it so long as its not the CoverLayer class.

ie,

Code:

/**
* This requires the following in your cocos2d project
* CCScrollLayer extension
* @url: https://github.com/cocos2d/cocos2d-iphone-extensions/
* and
* ModalAlert - Customizable popup dialogs/alerts for Cocos2D
* @url: http://rombosblog.wordpress.com/2012/02/28/modal-alerts-for-cocos2d/ 
*/

// Disabled/Enable layers
-(void) MenuStatus:(BOOL)_enable Node:(id)_node
{
    LOG_METHOD;
    if (_enable == YES) NSLog(@"MenuStatus.Enable = YES");
    if (_enable == NO) NSLog(@"MenuStatus.Enable = NO");
    
    for (id result in ((CCNode *)_node).children)
    {
        NSLog(@"Node result = %@", [result class]);
        
        if ([result isKindOfClass:[CoverLayer class]])
        {
            // Do nothing
            
        } else {
            
            // Scrolllayer
            if ([result isKindOfClass:[CCScrollLayer class]]) {
                NSLog(@"Found CCScrollLayer...");
                ((CCScrollLayer *)result).isTouchEnabled = _enable;
                for (id result1 in ((CCScrollLayer *)result).children) {
                    NSLog(@"  result1 class = %@", [result1 class]);
                    if ([result1 isKindOfClass:[CCLayer class]]) {
                        ((CCLayer *)result1).isTouchEnabled = _enable;
                    }
                    for (id result2 in ((CCLayer *)result1).children) {
                        NSLog(@"  child found: %@", [result2 class]);
                        if ([result2 isKindOfClass:[CCMenu class]]) {
                            ((CCMenu *)result2).isTouchEnabled = _enable;
                        } // end if
                    }
                } // next
            } // end if

            // Layers
            if ([result isKindOfClass:[CCLayer class]]) {
                NSLog(@"Found CCLayer -- %@", [CCLayer class]);
                
                // Disable CCLayer and any children?
                ((CCLayer *)result).isTouchEnabled = _enable;
                for (id result2 in ((CCLayer *)result).children) {
                    NSLog(@"child found: %@", [result2 class]);
                    if ([result2 isKindOfClass:[CCMenu class]]) {
                        ((CCMenu *)result2).isTouchEnabled = _enable;
                    } // end if
                } // next
                
            } // end if
            
            
        } // end if
        
        

        
	} // next
}

Summary

In summary, I:

  • I have a base scene with multiple layer children under it (MainMenuScene -> Player Setup Layer, etc)
  • I use instances and class forwarding to change the child of MainMenuScene
  • I include a HUD, which is a CCLayer, onto the layers I need them on
  • The HUD uses an HUDActionController to decide where to go, and it also locks/unlocks things, including CCScrollLayers
  • The HUD will launch a modal pop-up dialog fine now
  • Other pop-up dialogs can appear higher than the HUD modal so long as the Z-Index is higher without any issue

In numerical format, it sorta looks like this

  1. Main Menu Scene has a Main Menu Layer.
    1. Player Setup Layer replaces child of Main Menu Layer
    2. Difficulty Setup Layer replaces child of Main Menu Layer
    3. Game confirmation Setup Layer replaces child of Main Menu Layer
  2. Game Scene has a Game Layer
    1. Game Layer has a HUD child node in it
      1. HUD uses HUDActionController to handle routing and disable/enable touches
      2. If I launch a modal it will appear on top of HUD if z-index is higher, it will also disable touches under it
      3. If I launch a modal on the HUD it will disable everything except the modal itself and her children

It isn’t perfect, but I’ve found it works for me. So far….

Mobile marketing is a booming industry

Your customers are no longer using traditional desktop computers and modern browsers to view your website, they’re using their iPhones and Android smart-phones, TV, Net-books and more devices are on the way. You need to be connecting with your customers on mobile, desktop, anywhere; everywhere…

Like any business owner, advertising is an expense to your bottom line. So, it’s important to spend your advertising dollars to your greatest advantage. And as technology changes, advertising strategies and tools must change, too.

Even if you have a website, you may not be convinced that mobile advertising is right for your business. Following are some statistics that might change your mind.

* Nielsen Mobile, which reports on trends in the wireless industry says that 50.2 percent of mobile subscribers in the US are smart phone users and make regular use of the mobile Internet on their devices.

* Nielsen also reports that these mobile customers most often use their mobile internet connection to visit websites – even more frequently than they use it to access email.

* Yahoo reports that it expects that by 2017 more users will access the internet via their mobile phones than via their home or business PC’s.

* eMarketer reports that even older baby boomers (those aged 54-62) are accessing the internet frequently, meaning that internet marketing truly appeals to all ages.

* eMarketer also reports that in the UK, restaurant advertising on mobile phones grew, and clothing ads each are growing at a rate of over 37.2% on mobile phones.

* This same report in eMarketer reports that the restaurant ads sent to mobile phones reported a 15.5% response rate. These ads utilized SMS messaging technology, rather than web browsing.

Mobile marketing is huge, and that businesses need to get out of the mindset that a website is enough — and that mobile can be ignored; when in reality, mobile is increasingly the way people search, browse and shop online.

The reality is that mobile engagement gives immediate calls to action; that is, to call you – the business owner.

The bottom line is, in today’s world, you simply cannot afford to ignore mobile any longer.

Sources:


Google “The Mobile Movement: Understanding Smartphone Users,” 2011

Lightspeed Research, 2010; Google “The Mobile Movement: Understanding Smartphone Users,” 2011

“Mobile Web Has More Users While Mobile Apps See Higher Engagement | Mobile Marketing Watch”

Gartner, “Gartner’s Top Predictions for IT Organizations and Users, 2010
and Beyond: A New Balance,” 2010

Forrester Research via Google, “What Users Want from Mobile,” July 2011

Baby Boomers: Neglected by Marketers, eMarketer

Report: The Rise of Smartphones, Apps and the Mobile Web, Nielson.com

“The Third Screen: Marketing to Your Customers in a World Gone Mobile: How to Keep Up – and Soar Ahead – in the World of M-Commerce”, Chuck Martin

Smartphones increasingly used for surfing the web

People spend more time using their smartphones for surfing the web, checking social networks or playing games than making phone calls, new research has found.

According to the Telegraph, the report has indicated that on average day, 25 mins is spent on Internet browsing, 20 minutes is spent on social media, whereas people will spend an average of 12 minutes on actual telephone calls.

Original article (Telegraph)

iOS Game coming soon!

I’m producing my first iOS game using cocos2d. I’ll be showing screenshot previews of it at the upcoming Mobile Mingle event.

In addition, I’m producing an official silentflute iPhone app, and am producing several other smaller iOS apps too!

I’ll post regular updates when the app is ready for publishing.