0

A Game Idea Machine

Did you ever get stuck when trying to come up with new game ideas? Try out my little tool I put together:

What Game should I make?

It generates new game ideas by randomly choosing from genre, visual style and other parameters. You can also preselect each parameter, e.g. if you just want to make 8bit 2D games.
Feel free to use it, share it or do whatever you like with it!

0

Sneak Peek: First Screenshot of Rotron

My new game I am working on is called “Rotron” and is nearing its completion. After some polishing, tweaking and balancing I hope to submit it by next weekend to the App Store for review. It is an iPhone/iPod Touch arcade game made with Cocos2D. Here is the first public screenshot:

0

Using a physical Joystick in a Cocos2D (for Mac) Game (Part 2)

In the previous post I explained how to intercept joystick events in a Cocos2D for Mac project using DDHidLib. Now we will use this foundation to control a space ship.

Adding a Space Ship

Download the zip file containing the image of a space ship and a bullet to shoot here. Extract the zip and add both files to the Resources group in your Xcode project.

Now add a new class derived from CCNode and name it “Ship”. Open Ship.m. Add an init method:

- (id)init
{
    self = [super init];
    if (self)
    {
        // add ship sprite
        CCSprite *ship = [CCSprite spriteWithFile:@"ship.png"];
        [self addChild:ship];
    }
    return self;
}

Open HelloWorldLayer.m. Remove the code which adds the “Hello World” label in the init-method. We don’t need that any more. Now add the following code at the end of init:

        CGSize winSize = [CCDirector sharedDirector].winSize;

        self.ship = [[[Ship alloc] init] autorelease];
        self.ship.position = ccp(30.0, winSize.height / 2.0f);
        [self addChild:self.ship];

Build an run the project. You should now see the space ship on the screen.

Moving the Ship

We will implement ship movement using booleans to control the directions. Open Ship.h and modify it so that it looks like this:

#import <Foundation/Foundation.h>
#import "cocos2d.h"

@interface Ship : CCNode
{
    BOOL moveUp;
    BOOL moveDown;
    BOOL moveLeft;
    BOOL moveRight;
}

@property (nonatomic, assign) BOOL moveUp;
@property (nonatomic, assign) BOOL moveDown;
@property (nonatomic, assign) BOOL moveLeft;
@property (nonatomic, assign) BOOL moveRight;

@end

In Ship.m add the @synthesize directives:

@synthesize moveUp;
@synthesize moveDown;
@synthesize moveLeft;
@synthesize moveRight;

The actual movement will be handled in a Cocos2D standard update method:

- (void)update:(ccTime)dt
{
#define VELOCITY    150
   
    CGPoint position = self.position;
   
    if(self.moveUp)
        position.y += VELOCITY * dt;
    if(self.moveDown)
        position.y -= VELOCITY * dt;
    if(self.moveRight)
        position.x += VELOCITY * dt;
    if(self.moveLeft)
        position.x -= VELOCITY * dt;
       
    self.position = position;
}

VELOCITY is the amount of pixels per second the ship should move. The ship’s position is updated depending on which direction is currently active.

Register the ship object to be included in Cocos2D’s update calls by adding

[self scheduleUpdate];

to the init method. To clean up, also add a dealloc with the according unscheduleUpdate:

- (void)dealloc
{
    [self unscheduleUpdate];
    [super dealloc];
}

Open HelloWorldLayer.m and scroll down to the DDHidLib delegate methods. The ship can be controlled either with an analog stick or a d-pad, so we will implement movement behavior in the according delegate methods.

Analog:

#define THRESHOLD   2<<13   // this threshold defines the dead zone of analog sticks

- (void)ddhidJoystick:(DDHidJoystick *)joystick
                stick:(unsigned)stick
             xChanged:(int)value
{
    // this method gets called when an analog stick is moved on the x axis.
   
    if(value < -THRESHOLD)
        self.ship.moveLeft = YES;
    else if(value > THRESHOLD)
        self.ship.moveRight = YES;
    else
    {
        self.ship.moveLeft = NO;
        self.ship.moveRight = NO;
    }
}

- (void)ddhidJoystick:(DDHidJoystick *)joystick
                stick:(unsigned)stick
            yChanged:(int)value
{
    // this method gets called when an analog stick is moved on the y axis.
   
    if(value < -THRESHOLD)
        self.ship.moveUp = YES;
    else if(value > THRESHOLD)
        self.ship.moveDown = YES;
    else
    {
        self.ship.moveUp = NO;
        self.ship.moveDown = NO;
    }
}

d-pad:

- (void)ddhidJoystick:(DDHidJoystick *)joystick
                stick:(unsigned)stick
            povNumber:(unsigned)povNumber
         valueChanged:(int)value
{
    // This method gets called when d-pad buttons are pressed. The value is direction in degrees * 100

    // reset movement
    self.ship.moveUp = NO;
    self.ship.moveDown = NO;
    self.ship.moveLeft = NO;
    self.ship.moveRight = NO;

    switch (value)
    {
        case -1:
            // no movement
            break;
           
        case 0:
            self.ship.moveUp = YES;
            break;
       
        case 4500:
            self.ship.moveUp = YES;
            self.ship.moveRight = YES;
            break;
           
        case 9000:
            self.ship.moveRight = YES;
            break;

        case 13500:
            self.ship.moveRight = YES;
            self.ship.moveDown = YES;
            break;

        case 18000:
            self.ship.moveDown = YES;
            break;

        case 22500:
            self.ship.moveDown = YES;
            self.ship.moveLeft = YES;
            break;

        case 27000:
            self.ship.moveLeft = YES;
            break;
           
        case 31500:
            self.ship.moveLeft = YES;
            self.ship.moveUp = YES;
            break;
           
        default:
            break;
    }
}

Build and run. You should now be able to move the ship around using an analog stick or a d-pad.

Shooting

Open HelloWorldLayer.h and add a member variable:

BOOL shoot;

The BOOL flag will determine if new bullets should be fired or not.
Open HelloWorldLayer.m and in the init method register the object to receive update: calls:

[self scheduleUpdate];

Unregister in dealloc:

[self unscheduleUpdate];

Add a new method that shoots a bullet:

- (void)shootBullet
{
    CGSize winSize = [CCDirector sharedDirector].winSize;
   
    CCSprite *bullet = [CCSprite spriteWithFile:@"bullet.png"];
    bullet.position = ccpAdd(self.ship.position, ccp(bullet.contentSize.width / 2.0f, 0));
    [self addChild:bullet];
   
    [bullet runAction:[CCSequence actions:
                       [CCMoveBy actionWithDuration:1.0 position:ccp(winSize.width, 0)],
                       [CCCallFuncN actionWithTarget:self selector:@selector(removeBullet:)],
                       nil]];
}

A new sprite is instantiated and added to the layer. A CCMoveBy action is used to animate the bullet until it is out of view. Then the removeBullet: method is called:

- (void)removeBullet:(CCNode *)node
{
    [node stopAllActions];
    [self removeChild:node cleanup:YES];
}

This method stops all active actions and removes the bullet from the layer.
Add the upadte: method which simply shoots bullets if the shoot flag is YES:

- (void)update:(ccTime)dt
{
    if(shoot)
        [self shootBullet];
}

To set the values for the shoot flags we implement two DDHidLib delegate methods which handle button presses:

- (void)ddhidJoystick:(DDHidJoystick *)joystick buttonDown:(unsigned)buttonNumber
{
    // this method would be a good place to start shooting bullets
    shoot = YES;
}

- (void)ddhidJoystick:(DDHidJoystick *)joystick buttonUp:(unsigned)buttonNumber
{
    // this method would be a good place to stop shooting bullets
    shoot = NO;
}

Build and run. Now you can move your ship AND shoot bullets!

You can download the complete Xcode project here: JoystickTest_Final.zip

0

Using a physical Joystick in a Cocos2D (for Mac) Game (Part 1)

Quite a while ago I started playing around with Cocos2D for Mac and so far I love it. As a first test project I am making a retro style side-scrolling space shoot-em’-up.
While processing keyboard input is quite easy, the only thing I was really missing is built-in support for joysticks and gamepads. I could not find anything related to this topic on the official Cocos2D forums. You only get plenty of articles describing how to implement a soft-gamepad on the iPhone or iPad. I guess this is because the Mac port of Cocos2D is quite new.

After doing some research I found out that a joystick is a HID (Human Interface Device) and there is a crude, low level C API on the Mac to interface HIDs called IOHIDLib. Then I found out about Dave Dribin’s excellent DDHidLib library, an Objective-C wrapper around IOHIDLib. You can download it here: DDHidLib. In the first part of the tutorial I’ll show you how to integrate it in your Cocos2D project (I assume you use Xcode 4).

Building the Framework

  1. Download and extract the source code of DDHidLib from the above link.
  2. Open the DDHidLib Xcode project.
  3. Select the DDHidLib scheme.
  4. Edit the scheme so it uses the Release build configuration.
  5. Build the framework. If you run into problems here make sure the Base SDK is set to “Latest Mac OS X” in the target’s build settings.
  6. Locate the framework in Finder for later use.

Demo Project

Now I’ll take you through the process of integrating DDHidLib into a Cocos2D project.
Create a new project in Xcode using the template called “cocos2d_macosx” and name it “JoystickTest”. Build and run. This should just display a Hello World label. Now to the fun part.

Adding the Framework

  1. Drag DDHidLib.framework into the Frameworks group of your demo project and make sure “Copy items” is checked. The framework will now be linked to the target.
  2. Go to you project settings, select the JoystickTest target.
  3. Select the “Build Phases” tab and add a new “Copy Files” phase.
  4. Select destination “Frameworks” and also rename the phase to “Frameworks”.
  5. Drag DDHidLib.framework from the project navigator into the build phase.
  6. Build and run the project to see if everything works.

Intercepting Joystick Events

  1. Open HelloWorldLayer.h and add a member variable:
    @interface HelloWorldLayer : CCLayer
    {
        NSArray *joysticks;
    }
  2. Open HelloWorldLayer.m and add these pieces:

    #import <DDHidLib/DDHidLib.h>

    At the end of the init method add

    // allJoysticks returns an array of all connected joysticks
    joysticks = [[DDHidJoystick allJoysticks] retain];

    // we want to be the delegate of the joysticks
    [joysticks makeObjectsPerformSelector:@selector(setDelegate:) withObject:self];

    // start listening to all joystick events
    [joysticks makeObjectsPerformSelector:@selector(startListening) withObject:nil];
  3. Now we can receive delegate methods which are called when the user interacts with the joystick.
    Add the following code at the end of the file. Use these delegate methods to set states or trigger actions in your game logic. The methods are pretty self explanatory.

    #pragma mark - Joystick stuff

    - (void)ddhidJoystick:(DDHidJoystick *)joystick buttonDown:(unsigned)buttonNumber
    {
        // this method would be a good place to start shooting bullets
        NSLog(@"button down: %d", buttonNumber);
    }

    - (void)ddhidJoystick:(DDHidJoystick *)joystick buttonUp:(unsigned)buttonNumber
    {
        // this method would be a good place to stop shooting bullets
        NSLog(@"button up: %d", buttonNumber);
    }


    #define THRESHOLD   2<<13   // this threshold defines the dead zone of analog sticks

    - (void)ddhidJoystick:(DDHidJoystick *)joystick
                    stick:(unsigned)stick
                 xChanged:(int)value
    {
        // this method gets called when an analog stick is moved on the x axis.
       
        if(value < -THRESHOLD)
            NSLog(@"stick left");
        else if(value > THRESHOLD)
            NSLog(@"stick right");
        else
            NSLog(@"x axis neutral zone");
    }

    - (void)ddhidJoystick:(DDHidJoystick *)joystick
                    stick:(unsigned)stick
                yChanged:(int)value
    {
        // this method gets called when an analog stick is moved on the y axis.
       
        if(value < -THRESHOLD)
            NSLog(@"stick up");
        else if(value > THRESHOLD)
            NSLog(@"stick down");
        else
            NSLog(@"y axis neutral zone");
    }

    - (void)ddhidJoystick:(DDHidJoystick *)joystick
                    stick:(unsigned)stick
                otherAxis:(unsigned)otherAxis
             valueChanged:(int)value
    {
        NSLog(@"otherAxis: %u   value: %d", otherAxis, value);
    }

    - (void)ddhidJoystick:(DDHidJoystick *)joystick
                    stick:(unsigned)stick
                povNumber:(unsigned)povNumber
             valueChanged:(int)value
    {
        // This method gets called when d-pad buttons are pressed. The value is direction in degrees * 100
       
        switch (value)
        {
            case -1:
                text = @"d-pad none";
                break;
               
            case 0:
                text = @"d-pad N";
                break;
           
            case 4500:
                text = @"d-pad NE";
                break;
               
            case 9000:
                text = @"d-pad E";
                break;

            case 13500:
                text = @"d-pad SE";
                break;

            case 18000:
                text = @"d-pad S";
                break;

            case 22500:
                text = @"d-pad SW";
                break;

            case 27000:
                text = @"d-pad W";
                break;
               
            case 31500:
                text = @"d-pad NW";
                break;
               
            default:
                break;
        }
    }
  4. Connect a joystick or pad to your Mac and try it out!

You can download the finished Xcode project here: JoystickTest.zip