Skejo Studios

Eradicate Week 16: Game Map/UI Progression

This update is more a gallery of snapshots than anything else. I think it is always instructive to our team, and other developers to see the progression of layout/design/game play. So without any further commentary, here is the progression of our main game surface from first prototype to near shipping screenshot. (one more will be added later, for the final shipped version).

Eradicate Week 15: Loadscreens and Beta Testing

We have been working hard at Skejo Studios pulling together all the loose ends as far as sounds effects, artwork, Game Center integration and QA/Beta testing our game, Operation: Eradicate.

I am super glad to announce that the load/menu screen is now completed by the artist and has been crafted into the game, as seen below.

Eradicate Week 13: The Art. Coming Together

This update is more to be seen than read. Half our main character assets have been fully colored, with the rest due next week.

Click to see the full versions, it is worth it.

Eradicate Week 12: New Menus and Messages

For this week's update on our Eradicate iPad game at Skejo Studios, I wanted show a bit of the direction we are head with the art assets.

First we have received an initial scan of a possible load screen. We might mess with it a bit, cropping or framing it, but it is done. The example below also shows the improved game setup screen where you can cycle through the commanders photos, instead of just their names. Colorized version of all assets will be delivered shortly.

Eradicate Week 11: Event Drive Tutorial

Seems I am more on a every two weeks update schedule, than even every Friday, but it will have to do. I am so excited for the direction of the game that I just keep working on it, instead of writing about it.

First, the main hand-drawn art work, by Anthony Moss at Magus Studio, www.magusstudios.com, has been completed and scanned. He will start coloring them after Christmas.

But the main topic today is that Operation: Eradicate needs an event drive tutorial to help people get into the game faster. I was in a brief conversation with a gentleman at a larger mobile game publisher who noted that even if the game play is solid (which we are sure it is), and the art is improved (which we know about and are in the works to update), he advised that a video tutorial would not be enough to on-ramp players into the game.

The One Day Help System, in Cocos2d for iOS

Since we are developing a strategy game for the iPad/iPhone at Skejo Studios, we were in need of an in game help system to quickly tutor the player with the different controls and game options. We had been putting off this mechanism for a while, since it was figured it might take a while, but surprisingly it was rather easy in Cocos2d to accomplish.

Game Layer Code

I am assuming you know how to add the correct definitions and import class headers, so I am not showing that part. Placing the below code in your init method for the Cocos2d scene or layer setups up the layer to receive touches (though I assume almost any game is receiving touches already) and adds the help layer (blank for now).

-(id) init
{
    
	if( (self=[super init])) {

        //Setup delagate for processing touches
        [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:-1 swallowsTouches:YES];
	...

    helpSystemOn = NO;
    helpLayer = [HelpLayer  node];   
    [helpLayer setGamePlayLayer: self]; //Only needed if you need to know something from your gaming layer.
    [playingLayer addChild:helpLayer z:10];

	...
}

To accept the touches, you need at least the ccTouchBegan method (required for the CCTouchDispatch call):

#pragma mark Touch Processing

-(BOOL) ccTouchBegan:(UITouch*)touch withEvent:(UIEvent *)event
{	
    CGPoint touchLocation = [self convertTouchToNodeSpace:touch];

    if (receivingTouches == YES) {
        [self selectSpriteForTouch:touchLocation];
        
        return YES;
    } else if (helpSystemOn == YES) {
        [self selectSpriteForHelp:touchLocation];
        return YES;

    } else {
        return NO;
    }
}

- (BOOL)selectSpriteForHelp:(CGPoint)touchLocation {
    BOOL processedTouch = NO;
    processedTouch = [helpLayer processTouch: touchLocation];
    return processedTouch;

}

In our game, we don't always want to be receiving touches, so we have a receivingTouches flag that we check for. If so, then we forward the touch to the correct method. We now added the check for the Help System by checking for the helpSystemOn flag and forward to the selectSpriteForHelp method which simple passes the touch to the HelpClass instance.

NOTE: The 'processedTouch' return value is use if you have multiple TouchDispatchers going at once. They will be queried in order of priority until a dispatcher returns a TRUE value.

Before moving on to the HelpLayer class, we need to add the toggle switch for the help system. Normally such a toggle should be placed with other high level game controls like 'End Turn', 'Return to Menu' or 'Restart Turn' buttons. We added the showInfo menu button with the other buttons and assign it the showInfoPressed method when pressed.

- (void) addGameControls {
	...  //Other menu items.
    
	CCMenuItem *showInfo = [[CCMenuItemImage 
                              itemFromNormalImage:@"info.png" selectedImage:@"info_pressed.png" 
                              target:self selector:@selector(showInfoPressed:)];
    
    showInfo.position = ccp(60, 300);
    
    CCMenu *controlsMenu = [CCMenu menuWithItems:pauseGameItem, showManual, restartTurn, showInfo, endTurn, nil];
    
    //Place in upper left corner
    [controlsMenu alignItemsHorizontallyWithPadding:10.0];
    controlsMenu.position = ccp(10, 700);
    [self addChild:controlsMenu z:10];

}


-(void) showInfoPressed: (CCMenuItemFont*)itemPassedIn {
    
    if (helpSystemOn == YES) {
        //Turning Off
        helpSystemOn = NO;
        [self rebuildActions]; //Used to re-enable action menu    
	} else {
        //Turning On
        [self cancelMoves]; //Used to disable any current actions
        [self rebuildActionsWithBlanks]; //Used to disable the action menu
        helpSystemOn = YES;
    }
    
    [helpLayer toggleHelp];
}

Any appropriate measures should be taken so that the game is essentially paused when the information system is on. We did this by disabling the action menu and canceling any in-progress moves.

So that is all the code that is needed inside the game play class, now we need to move to the HelpLayer class.

HelpLayer Class

//
//  HelpLayer.h
//
//  Created by Greg Holsclaw on 12/12/11.
//  Skejo Studios, www.skejo.com
//

#import 
#import "cocos2d.h"
#import "GamePlayLayer.h"
#import "Constants.h"

@class GamePlayLayer;

@interface HelpLayer : CCLayer {
    CCLayer *infoLayer;
    GamePlayLayer *gameLayer;
}

@property (nonatomic, strong) CCLayer *infoLayer;

- (void) toggleHelp;
- (BOOL) processTouch: (CGPoint)touchLocation;
- (void) setGamePlayLayer: (GamePlayLayer*) gamePlay;

@end
//
//  HelpLayer.m
//
//  Created by Greg Holsclaw on 12/12/11.
//  Skejo Studios, www.skejo.com
//

#import "HelpLayer.h"

@implementation HelpLayer
@synthesize infoLayer;

- (id) init
{
    self = [super init];
    if (self != nil)
    {
        
        infoLayer = [CCLayer node];
        CCSprite *helpBG = [CCSprite spriteWithFile:@"overlay-70.png"]; //A 1x1 pixel semi-transparent black overlay.
        [helpBG setScaleX:1024]; //Scale transparent background to appropriate size.
        [helpBG setScaleY:768];  //Scale transparent background to appropriate size.
        [self addChild:helpBG];
        [self setVisible:NO];    //Initially made invisible, only shown when info system turned on.
        
        CGSize screenSize = [CCDirector sharedDirector].winSize;
        self.position = ccp(screenSize.width/2, screenSize.height/2);
        
        [self addChild:infoLayer];
        
	}
    return self;
    
}	

-(void) setGamePlayLayer: (GamePlayLayer*) gamePlay {
    gameLayer = gamePlay;
}

- (void) toggleHelp {
    if (self.visible == YES) {
        //Remove Help system

        [infoLayer removeAllChildrenWithCleanup:YES];
        self.visible = NO;
    } else {
        //Add Help system

        self.visible = YES;        
        CCLabelTTF *helpLabel = [CCLabelTTF labelWithString:@"Info Mode On" fontName:kBaseFont fontSize:24];

        [helpLabel runAction:[CCSequence actions:[CCDelayTime actionWithDuration:2.2], [CCFadeOut actionWithDuration:1], nil]];
        
        [self addChild:helpLabel];
    }
}


-(void) dealloc {
    gameLayer = nil;
}

@end

When the toggleHelp method is called by the main game layer it makes visible the transparent overlay, and adds a disappearing message. Now we just need to implement the processTouch methods that was used when receiving touches.

Before diving into the code, I need to mention that a couple of design considerations went into this code. There are always at least two consideration in coding, ease of coding and maintainability. Usually the super easily coded solution isn't the best long term solution. We followed an easy to code method, which I admit *might* become a time sink later. But if the UI doesn't change much, then later will never come. We try not to let the perfect kill the good here.

If your game consists of items that are moving, and those items need to present information when pressed, then the code gets a bit more complicated, and the proposed solution won't work at all. See the 'Where to Go From Here section'.

For now, we simply wanted to add information for the control buttons, which are statically placed. Thus all we have to layout a set of coordinate boxes, and trigger the correct message if the touch is inside the boxes.

- (BOOL) processTouch: (CGPoint)touchLocation {
    BOOL processed = NO;
    BOOL found = NO;
    NSString *imageStr;
    NSString *text;
    CGRect boundBox;
    
         
    boundBox = CGRectMake(10, 230, 50, 50);  //Location of Move Button
    if (CGRectContainsPoint(boundBox, touchLocation)) {   
        found = YES;
        imageStr = @"help-move.png";
        text = @"HELPMOVE";
    }

    boundBox = CGRectMake(10, 280, 150, 50);  //Location of Fight Button
    if (CGRectContainsPoint(boundBox, touchLocation)) {   
        found = YES;
        imageStr = @"help-fight.png";
        text = @"HELPFIGHT";
    }

    boundBox = CGRectMake(60, 230, 50, 50);  //Location of Trade Button
    if (CGRectContainsPoint(boundBox, touchLocation)) {   
        found = YES;
        imageStr = @"help-trade.png";
        text = @"HELPTRADE";
    }

    boundBox = CGRectMake(10, 180, 50, 50);  //Location of Cure Button
    if (CGRectContainsPoint(boundBox, touchLocation)) {   
        found = YES;
        imageStr = @"help-cure.png";
        text = @"HELPCURE";
    }

	... //Other stuff if more needed. 

    [infoLayer removeAllChildrenWithCleanup:YES]; //Remove any prior message.

    if (found == YES) {
        processed = YES;
    	CCSprite *bg = [CCSprite spriteWithFile:@"bg_info_message.png"];
    	CCSprite *image = [CCSprite spriteWithFile:imageStr];
    	CCLabelTTF *label = [CCLabelTTF labelWithString: text fontName:@"Arial" fontSize:12];
    
    	label.position = ccp(0,100);
    
    	[infoLayer addChild:bg z:-1];
    	[infoLayer addChild:image z:1];
    	[infoLayer addChild:label z:2];
    }
    
    return processed;
}

Finished product

Of course, the actual help text, images and backgrounds, and their positions need to be adjusted to your use, but this should be adequate to get you very near a tailored solution.

Our solution seen in a couple of images:

Where to go from here

If the help system needs to be used on sprites/objects that move on the game surface, then above solution will not work in the slightest. You will need to interact with your game play layer and reference all the actual sprites you want to give information about.

To do this, you must assign all the 'interesting' sprites to an array and go through the array of sprites checking for collisions between the touch and the sprite's bounding box.

In some init function add the sprites to a help array:

-(id) init {
	... //regular init code
	helpSprites = [NSMutableArray arrayWithCapacity:2];
	[helpSprites addObject:…….]; //Repeat for all objects that will need help information
	...
}
 

Then in the 'processTouch' method for the HelpLayer class you would loop through the sprites looking for a collision:

	id foundSprite;
	for (id *sprite in gameLayer.helpSprites) {        
        
        //CGPoint boundOrigin = 
        CGPoint worldCoord = [sprite.infectionOverlay convertToWorldSpace: sprite.position];

        CGRect boundBox = CGRectMake(worldCoord.x, worldCoord.y, sprite.boundingBox.size.width, sprite.boundingBox.size.height);
        
        if (CGRectContainsPoint(boundBox, touchLocation)) {   
            foundSprite = sprite;
            break;
        }
    }
 
	//Determine which kind of sprite it is and display the appropriate help message.

A tailored mechanism like this will allow you to quickly add objects to the help system, and detect them anywhere on the game layer they might exist. Such code is much more maintainable because if you move any UI items later in the game design, the code isn't broken (unlike the original implementation which forces you to sync the boundBox to the location of items, which might be changed later). But this system is much more complex to setup.

Gladly, this entire process took less than a day to implement (minus cool help graphics to add), so no game should be w/o at least a rudimentary help system).

Comment below, or with Twitter,

Screenshot taken from our Eradicate project (view all posts here). Also visit Skejo Studios to see all we are doing there.

Eradicate Week 9 - Name Change and other updates

After a bit a break from blogging, I wanted to give another quick update regarding the state of this project. Skejo Studios, www.skejo.com, is moving full steam ahead on our strategy game project, but it is taking longer than we anticipated. But hopefully, the longer the bread rises, the better it tastes.

First, the project name, 'Outbreak', has now been replaced by the game name, 'Operation: Eradicate'. Various internal discussions lead to this final name. I have updated many of the various links and names around the site to reflect the update.

We are now shooting for an end of January or mid February release to the app store.

Lastly, here are two uncolored pics of the commanders that will be used in the game and in marketing materials.



Should indie game devs do it all?

Running in the game dev circles for the last three months has exposed me to a ton of one or two man shops that undertake the entire development and production of a game on their own. Some are doing well, but others are struggling.

It almost seems like some developers purposely handicap themselves by 'doing it all' just so they can claim the elusive 'indie developer' mantel. I don't want to touch the What is an indie game developer? topic again, but I do want to target the thinking behind doing it all yourself.

Is going it alone wise, productive, or profitable?

Coming from the startup world of Silicon Valley, it is regularly frowned upon to hear about a startup with only one founder (#1 mistake startups make). The reasons are broad, but generally distill down to three core issues:

1) If nobody has partnered with you, you might be a pain to work with.
2) If nobody has partnered with you, your idea probably isn't very good.
3) One person just can't do it all.

I don't really want to touch the first issue as it is a personal issue. I want to assume that all indie developers and designers aren't doing the indie scene because they have been fired from every job they have ever held, but instead choose this path for themselves.

Moving to the second point, I think it is valid to ask a solo dev if they have really tried to flesh out their game idea, bouncing it off their circle of friends and family. If none of them wanted to join, or at least refer a co-developer/co-artist to help the game idea along, maybe the idea doesn't have legs. Listen to this signal. Refine your concepts and ideas until people start biting, and offering to help you. Remember, most likely, your idea sucks anyway.

Is it Productive?

But, assuming your idea is awesome, which will result in the next Zynga or Rovio, why would you still want to do it alone?

Will you, as the one man show be able to produce that quality game that you see in your mind?

Or will have to settle when you hit the roadblocks of your weaknesses?

Art is hard for analytical coders. Game design and balancing is hard for the more artistic among us. Pulling together all the aspects of a game is not a skill everyone has.

Stop thinking that your awesome strengths are going to mask the other weaknesses in your game development process. It won't. Don't be surprised that your product is judged against its weakest aspect, the stuff you aren't good at, not its strengths.

Pull together a team, use your strengths to compliment the rest of your team's strengths.

Is it Profitable?

Finally, assuming you have the best idea, should you keep it to yourself, doing all the work? Will the payout be bigger by keeping the whole pie for yourself?

A widely noted survey also backs up the team theory, versus one man show. Scroll to around Figure 7, which show more returns for more developers working together. / Owen Goss, the author's take:

"The conclusion that I draw from this is that, in general, larger groups of developers are able to create games that earn more money. Wagering a guess, this is perhaps because they are able to create games that are larger in scope, more technically interesting, and more polished, because they have more people to work on the game and provide input into its improvement."

General experience shows that partnerships of 2-5 definitely outperforms solo developers in most situations. As Owen notes, along with many startup founders and investors, a team compensates for the weak links of the individuals. In the same way, a game development team should have a higher standard of quality, polish and completeness when compared to an otherwise average game.

If you don't want to partner with someone, at least use contractors to fill your holes. If you, yourself are not willing to invest $500-$1000 for decent graphics and music/sounds, is your idea really that awesome? Or, if you can't convince your closest family and friends that your game idea really is the next best thing, to help by filling art needs when you are mediocre artist or worse, or at least by buying decent art, should you spend all your time to craft top notch code and crown it with so-so artwork?

If you really are the rock star artist/game designer/developer, I will cheer you on to success. But if you are like me, great a few things, good at some other and down right horrible at many thing, surround yourself with folks whose strengths amplify your own. Stop trying to it all yourself.

The composition of a team is a different articles, so I won't even touch that, and there a few articles already written:
http://www.gamasutra.com/blogs/AlistairDoulin/20100107/4040/Building_A_S...
http://www.lorekings.com/blogs/2011/oct/3rd/ig_building/team-pg1.html
http://www.indiezen.org/index.php?option=com_content&view=article&id=119...

Are there are great examples for one man shows that have succeeded in the long term (I have a few in mind)? Are they the exception to the rule? Any brave souls wanting to describe examples of one man shows that resulted in burn out or unpolished games?

Comment below, or with Twitter,

Eradicate Week 7: Turn Based Gaming

This week I want to talk about how two issues converged: saving game state and turn based match play. Saving the state of a strategy game is an obvious feature. If every time you turn off the game you have to restart the game, people stop playing.

As a selling point, we are also going to implement Turn Based Matches (Apple API not quite updated, check this tutorial to get started), which is also a prefect fit for turn based strategy games.

The reason these two issues converge is because the current packet size limit for the turn based game, see http://www.idownloadblog.com/2011/08/19/new-in-beta-6/, check the Game Kit section. Hopefully Apple increases the limit later, but until then, I had to work with the 4KB limitations.

Eradicate Week 6: Quick Update

We have had a super busy week, working on art, and documentation and other stuff, but I don't have any really cool stuff to talk about in detail. So I will just post a couple more pieces of artwork, and list some features that we nailed down.

FEATURES:
Save/Resume game - data stored when game pause by iOS as well
Turn Based Matches - groundwork set play a game with the new iOS 5 turn based matches system
Completed more animations backend code for city markers

Syndicate content