I am working on some Cocos2D tutorials (doodle drop) and have downloaded the program on my device. The program is working but I have to hold the iPhone in a very specific, and not very good, angle to make the little icon move. As it is i must hold the device horizontal with a small tilt forward.

I would like to be able to hold the device horizontal to vertical and tip the device and get the little icon to move.

Could someone please give me some hints how to code this?

Here is my my code:

-(void) spiderBelowScreen:(id)sender {

// Make sure sender is actually of the right class
NSAsser([sender isKindOfClass:[CCSprite class]], @"sender is not a CCSprite!");
CCSprite *spider = (CCSprite*)sender;

// Move the spider back up outside the top of the screen
CGPoint pos = spider.position;
CGSize screenSize = [[CCDirector sharedDirector] winSize];
pos.y = screenSize.height + [spider texture].contentSize.height;
spider.position = pos;

-(void) runSpiderMoveSequence:(CCSprite*)spider {

// Slowly increase the spider speed over time

if (numSpidersMoved % 8 == 0 && spiderMoveDuration > 2.0f) {
    spiderMoveDuration -= 0.1f;

// This is the sequence which controls the spiders' movement
CGPoint belowScreenPosition = CGPointMake(spider.position.x, [spider texture].contentSize.height);
CCMoveTo *move = [CCMoveTo actionWithDuration:spiderMoveDuration position:belowScreenPosition];
CCCallFuncN *call = [CCCallFuncN actionWithTarget:self selector:@selector(spiderBelowScreen)];
CCSequence *sequence = [CCSequence actions:move, call, nil];
[spider runAction:sequence];

-(void) spidersUpdate:(ccTime)delta {

// Try to find a spioder which isn't currently moving
for (int i = 0; i < 10; i++) {
    int randomSpiderIndex = CCRANDOM_0_1() * [spiders count];
    CCSprite *spider = [spiders objectAtIndex:randomSpiderIndex];

    // If the spider isn't moving it won't have any running actions
    if ([spider numberOfRunningActions] == 0) {
        // This is the squense wich controls the spiders' movement
        [self runSpiderMoveSequence:spider];

        // Only onbe spider should start moving at a time

-(void) resetSpiders {

CGSize screenSize = [[CCDirector sharedDirector] winSize];

// Get any spider to get its image width
CCSprite *tempSpider = [spiders lastObject];
CGSize size = [tempSpider texture].contentSize;

int numSpiders = [spiders count];

for (int i = 0; i < numSpiders; i++) {

    // Put each spider at its designated position outside the screen
    CCSprite *spider = [spider objectAtIndex:i];
    spider.position = CGPointMake(size.width * i + size.width * 0.5f, screenSize.height + size.height);
    [spider stopAllActions];

// Uschedule the selector just in case. If it isn't scheduled it wont do anything
[self unschedule:@selector(spidersUpdate:)];

// Schedule the spider update logic to run at the given interval
[self schedule:@selector(spidersUpdate:) interval:0.7f];

-(void) initSpiders {

CGSize screenSize = [[CCDirector sharedDirector] winSize];

// using a temporary spider sprite is the easiest way to get the image's size
CCSprite *tempSpider = [CCSprite spriteWithFile:@"spider.png"];
float imageWidth = [tempSpider texture].contentSize.width;

// Use as many spiders as can fit next to each other over the whole screen width
int numSpiders = screenSize.width / imageWidth;

// Initialize the spider array using alloc
spiders = [[CCArray alloc] initWithCapacity:numSpiders];

for (int i = 0; i < numSpiders; i++) {
    CCSprite *spider = [CCSprite spriteWithFile:@"spider.png"];
    [self addChild:spider z:0 tag:2];

    // Also add the spider to the spider array
    [spiders addObject:spider];
// call the method to reposition all spiders
[self resetSpiders];


-(void) update:(ccTime)delta {

// Keep adding up the playerVelocity to the players's position
CGPoint pos = player.position;
pos.x   += playerVelocity.x;

// The player should also be stopped from going outside the screen
CGSize  screenSize  = [[CCDirector sharedDirector] winSize];
float   imageWidthHalved    = [player texture].contentSize.width * 0.5f;
float   leftBorderLimit     = imageWidthHalved;
float   rightBorderLimit    = screenSize.width - imageWidthHalved;

// Preventing the player sprite from moving outside the screen
if (pos.x < leftBorderLimit)
    pos.x   = leftBorderLimit;
    playerVelocity  = CGPointZero;
else if (pos.x > rightBorderLimit)
    pos.x   = rightBorderLimit;
    playerVelocity  = CGPointZero;

player.position = pos;


-(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {

// controls how quickly velocity decelerates (lower = quicker to change direction)
float   deceleration    = 0.2f;

// determines how sensitive the accelerometer reacts (higher = more sensitivity)
float   sensitivity     = 6.0f;

// how fast the velocity can be at most
float   maxVelocity     = 550;

// adjust velocity based on current accelerometer acceleration
playerVelocity.x    = playerVelocity.x * deceleration + acceleration.x * sensitivity;

// we must limit the maximum velocity of the player sprite, in both directions
if (playerVelocity.x > maxVelocity)
    playerVelocity.x    = maxVelocity;
else if (playerVelocity.x < -maxVelocity)
    playerVelocity.x    = -maxVelocity;

+(id)scene {
CCScene *scene = [CCScene node];
CCLayer *layer = [GameScene node];
[scene addChild:layer];
return scene;

-(id)init {
if ((self = [super init])) {
    CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);

    self.isAccelerometerEnabled = YES;

    player = [CCSprite spriteWithFile:@"alien.png"];
    [self addChild:player z:0 tag:1];

    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    float imageHeight = [player texture].contentSize.height;
    player.position = CGPointMake(screenSize.width / 2, imageHeight / 2);

    // scheduling the update method in order to adjust the player's speed every frame
    [self scheduleUpdate];
    [self initSpiders];

return self;

-(void) deallaoc {
CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);

// The spiders array must be released, it was created using [CCArray alloc]
[spiders release];
spiders = nil;

// Never forget to call [super dealloc]
[super dealloc];
  • \$\begingroup\$ I don't see in this sample where you're reading from the accelerometer input. You probably want to take the accelerometer input vectors and transform by a rotation matrix to get a transformed acceleration. If you don't have access to matrix math in this environment and you just want to hold the device horizontal, you could just swap the vertical and horizontal acceleration values. \$\endgroup\$
    – Flip
    Jul 21, 2011 at 15:14
  • 1
    \$\begingroup\$ doesnt it read from here: -(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration { \$\endgroup\$
    – PeterK
    Jul 21, 2011 at 16:28
  • \$\begingroup\$ Ah, I had missed that you posted so much code, I didn't scroll down. I feel like I still need more information though. With the current code, does tilting the device left/right move the player? (and in which direction?) Also, can you try explaining again what you mean by "I would like to be able to hold the device horizontal to vertical and tip the device and get the little icon to move" ? The answer to the question will likely involve combining more than one acceleration axis to get the resulting acceleration you want, but I need more specifics to tell which ones. \$\endgroup\$
    – Flip
    Jul 25, 2011 at 13:10
  • \$\begingroup\$ Thanks for your response, the problem i have is that i must hold the device in an exact position to get it too move. This mean that it is not convinient to play. \$\endgroup\$
    – PeterK
    Jul 25, 2011 at 18:24

1 Answer 1


It sounds like you need to transform the values you're getting from the accelerometer so the "neutral" orientation of the device is different. The more correct way of doing this is to construct a rotation matrix to transform the accelerometer input.

But if you don't want to deal with matrix multiplication and you just want a simple rotation about an axis, you can transform the input values you care about with some trig:

float holdAngle = 45.0f;
float localAccelX = acceleration.x * cos(holdAngle) - acceleration.y * sin(holdAngle);

// adjust velocity based on current accelerometer acceleration
playerVelocity.x    = playerVelocity.x * deceleration + localAccelX  * sensitivity;

You can change the angle value to suit your liking. You also may have to substitute acceleration.z for acceleration.y (I'm not sure what direction those axes point in with your device).


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .