When building games, one of the most visibly easy things to do, adding buttons and controls, is often a complicated task. Luckily, Nick Pannuto, a guy from the iPhone game developer community, released SneakyInput, a group of classes that include a joystick, a dPad and very good buttons. Created with simplicity and ease of use in mind, they’re still some of the most complete and functional input classes.

Downlading SneakyInput

Luckily for you, SneakyInput is an open source project, thus is free. Keep in mind giving donations to the creator if you make money using this kit. It surely will help getting updates and more content from him.

Start by downloading the package from this page : Link. To download, click on the big “Download Source” button at the top of the page.

When you unzip the package, you’ll see both the classes and a sample project. As you can see, there isn’t much there and all is pretty simple to understand as you’ll see.

Usage


Joystick / dPad

In addition to the actual Joystick class, the developer included a class that creates colored circles dynamically. Instead of using sprites, for debugging reasons or else, you can use this class. The circles are just like sprites, but with programmed color instead of an actual texture. There are no resources needed to use it.

Start by including the necessary files :

#import "SneakyJoystick.h"
#import "SneakyJoystickSkinnedBase.h"
#import "ColoredCircleSprite.h"


Those are the needed files in order to use either the Joystick or the dPad. A dPad is basically a joystick, moving only on either X or Y axis, without 360 degrees rotation. It’s a “crippled” joystick, and is programmed almost in the same way.

In your target layer, the layer you want to add the Joystick to, start by creating the base of the joystick, which will hold the rest of the stuff.

SneakyJoystickSkinnedBase *leftJoy = [[[SneakyJoystickSkinnedBase alloc] init] autorelease];
leftJoy.position = ccp(64,64);


The second line places the Joystick in the bottom left corner, because later in the tutorial, we’ll give it a 32 pixel radius.

After creating the Joystick, you have either of 2 options. You can:

-Use your own sprites
-Use ColoredCircleSprite, a class that creates colored circles with RBGA.

In the first example, we will be using our own sprite, created from a simple PNG file.

// Sprite that will act as the outter circle. Make this the same width as joystick.
leftJoy.backgroundSprite = [CCSprite spriteWithFile:@"outerJoy.png"];
// Sprite that will act as the actual Joystick. Definitely make this smaller than outer circle.
leftJoy.thumbSprite = [CCSprite spriteWithFile:@"innerJoy.png"];


On the other hand, for debugging purposes or if a simple RBGA Joystick is enough for your project, SneakyInput includes a class to create circles out of a radius and a RBGA code.

leftJoy.backgroundSprite = [ColoredCircleSprite circleWithColor:ccc4(255, 0, 0, 128) radius:32];
leftJoy.thumbSprite = [ColoredCircleSprite circleWithColor:ccc4(0, 0, 255, 200) radius:16];


In the previous code, instead of creating CCSprites to see the Joystick, we’re using a special class called ColoredCircleSprite. As simple as can be, this class takes 2 parameters: a ccc4 color (R,B,G,A -> meaning Red, Blue, Green, Alpha) and a radius, which is half the width of the wanted Joystick.

Then, whether you used ColorCircleSprite or a regular cocos2d CCSprite, the next part is the same. We’re gonna be adding the actual Joystick do our Joystick base.

leftJoy.joystick = [[SneakyJoystick alloc] initWithRect:CGRectMake(0,0,128,128)];
leftJoystick = [leftJoy.joystick retain];
[self addChild:leftJoy];


In the first line, we assign a Joystick to the joystick property of the Joystick Base. The SneakyJoystick class actually only takes 1 parameter, it’s size and position. This parameter is in the form of a CGRect : CGRectMake(int x, int y, int width, int height). The width and height are full widths and heights, not to mix with the radius of the previous code snippets.

The second line assigns a value to our SneakyJoystick property that we need to keep in order to query the Joystick at a specified interval.

In the last line, just like any other cocos2d example, we add the Joystick to the layer. Without this, the Joystick will not be visible.

Usage

The SneakyJoystick is not delegated. This means that in order to use it and apply its movement to CCSprites or any other object, you need to query it. This can be done anywhere, anytime. The suggested usage is to create a selector that will be called every frame and do all your stuff there.

[self schedule:@selector(tick:)];


Now the selector would look something like this:

-(void)tick:(float)delta {
/* This will take the joystick and tell a special method (not listed here, outside the scope of this guide) to take the joystick, apply movement to hero (CCSprite or else) and apply the real delta (to avoid uneven or choppy movement, delta is the time since the last time the method was called, in milliseconds). */
[self applyJoystick:leftJoystick toNode:hero forTimeDelta:delta];
}


This concludes how to use SneakyJoystick! Now you’re probably wondering how do turn this into an awesome dPad for your fighting game or whatever creative game you’re tinkering up. If you’re hoping for a quick one line solution, you’re in luck! Here’s what to do to turn the Joystick into a dPad :

joystick.isDPad = YES;


That’s all there is to it! Other than that, using sprites that looks like an actual dPad will surely give it a more oldschool and realistic look and feel.

Buttons

Now that you can handle the joystick, which is the most complicated of the duo, it’s time to add some buttons. Buttons from SneakyInput are much more complete and usable in a game as buttons from cocos2d (CCMenuItem).

First, we need to include the necessary files in order to use the buttons.

#import "SneakyButton.h"
#import "SneakyButtonSkinnedBase.h"


The buttons are created and added to the layer in the same way as we did with the joystick. In the following example, we’ll be using the ColoredCircleSprite class. Don’t forget that you can easily switch those for regular CCSprites

SneakyButtonSkinnedBase *rightBut = [[[SneakyButtonSkinnedBase alloc] init] autorelease];
rightBut.position = ccp(448,32);
rightBut.defaultSprite = [ColoredCircleSprite circleWithColor:ccc4(255, 255, 255, 128) radius:32];
rightBut.activatedSprite = [ColoredCircleSprite circleWithColor:ccc4(255, 255, 255, 255) radius:32];
rightBut.pressSprite = [ColoredCircleSprite circleWithColor:ccc4(255, 0, 0, 255) radius:32];
rightBut.button = [[SneakyButton alloc] initWithRect:CGRectMake(0, 0, 64, 64)];
rightButton = [rightBut.button retain];
rightButton.isToggleable = YES;
[self addChild:rightBut];


As you can see, instead of only using 2 sprites, the button uses 3. The 3rd sprite being used is only displayed when the button is set to isToggleable (will explain later). This means that it’ll only show when the button is selected.

At the end of the code, we set isToggleable to YES. This means the button will act as a switch. It’ll activate or deactivate on touch, just like a light switch.

To use the button, you will need to use the same technique as the joystick, meaning querying the buttons, whenever you want, to get their values. Here are the different possibilities:

// pressed
>if (rightButton.active == YES){
    [this doThat]; // Button is pressed at the moment
}

else{
    [this doElse]; // Button is NOT pressed at the moment
}
// switched (only if isToggleable is set to YES)
>if (rightButton.value == 1){
    [this doThat]; // Button is activated
}

else{
    [this doElse]; // Button is NOT activated
}


 

Understanding anchorPoint in cocos2d

On July 26, 2010, in cocos2d, by admin

There’s something in cocos2d which is super easy to understand, but that most people seem to have problems with it at first : Anchor Points. Every class derived from CCNode (Ultimate cocos2d class) will have a anchorPoint property.

When determining where to draw the object (sprite, layer, whatever), cocos2d will combine both properties position and anchorPoint. Also, when rotating an object, cocos2d will rotate it around its anchorPoint, as if a pin were placed on that very spot.

Positioning

As a first example, this sprite has an anchorPoint of ccp(0,0) and a position of ccp(0,0). This rectangle sprite will be placed at the bottom left corner of its parent, the layer.

CCSprite *sprite = [CCSprite spritewithFile:@"blackSquare.png"];
sprite.position=ccp(0,0);
sprite.anchorPoint=ccp(0,0);
[self addChild:sprite];






In this second example, we will assign a anchorPoint of ccp(-1,-1) to better understand the relative value of the anchor point.

CCSprite *sprite = [CCSprite spritewithFile:@"blackSquare.png"];
sprite.position=ccp(0,0);
sprite.anchorPoint=ccp(-1,-1);
[self addChild:sprite];






As you can see in the image, the anchor point is not a pixel value. The value of X and Y are relative to the size of the node. For example, in a 30×30 pixel square, something like the image above, a anchorPoint of ccp(-1,-1) will mean “Place the anchor 1 * myWidth to the left and 1 * myHeight under the sprite

As a final example, to better understand the combination of position and anchorPoint, I’ll show you different lines of code that give exactly the same result as the first image. That piece of code will combine both position and anchorPoint, and show you how to use the contentSize property.

CCSprite *sprite = [CCSprite spritewithFile:@"blackSquare.png"];
sprite.anchorPoint=ccp(1,1);
sprite.position=ccp(sprite.contentSize.width , sprite.contentSize.height);
[self addChild:sprite];

Using this snippet, we place the anchorPoint at ccp(1,1), which places it 1 * width to the right and 1 * height over. If we kept position at ccp(0,0), the sprite would be outside the screen, to the bottom left of it.

By placing the sprite at a position equal to ccp(1 * width, 1* height), it returns to the origin, at the bottom left corner.




Rotation

When rotating, we need to be careful with anchorPoint, as it can give us some very weird results, more so when using irregular anchor points such as ccp(0,0). By default, the anchorPoint is set to ccp(0.5f,0.5f), which is the middle of the sprite on both X and Y axes (remember that anchorPoint is a relative value to the size of the sprite).

Using ccp(0.5f,0.5f) as an anchorPoint will give the simplest rotation possible, which doesn’t change the actual position of the sprite. It’ll rotate just as you would normally think.

In the following example, the anchorPoint is set to ccp(1,1), meaning the sprite will rotate around its top right corner.





Remember that since anchorPoint is relative, you can assign it to ccp(2,2) and the sprite will rotate around that point. This is the case in the following example.




Simpler than it looks

I hope this tutorial was clear and helped you better understand how to use anchor points in cocos2d, and combine them with the position to place the sprites where you like, how you like. Also, by using different anchor points, you learned that it is possible to create different rotating patterns, such as rotating around external points.

Tagged with:  

Welcome to QcMat.com

On July 21, 2010, in Uncategorized, by admin

Hello,

Welcome to QcMat.com, where I will blog about my game development and add tutorials when the need comes. I love helping people and regularly am in a chat room helping people. I think that by putting this information in a blog or website, it can help loads of other people with the same problems or questions.

I hope you enjoy my blog, and feel free to follow me on twitter @QcMatDev.

 

Archives

All entries, chronologically...

Weboy