2010-12-09 3 views
0

Je suis en train de lire 'Learn iPhone and iPad Cocos2D Game Development' et au chapitre 4, il y a un exemple simple utilisant un accéléromètre. Cela fonctionne bien si j'utilise l'axe des x seulement comme le livre mais avec l'axe des Y, le mouvement des sprites n'est pas lisse s'il est sur le bord de l'écran.iPhone, cocos2d et accéléromètre

+ (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); 

     [self scheduleUpdate]; 
    } 

    return self; 
} 

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

    [super dealloc]; 
} 

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration 
{ 
    float deceleration = 0.4f; 
    float sensitivity  = 6.0f; 
    float maxVelocity  = 100; 

    playerVelocity.x = playerVelocity.x * deceleration + acceleration.x * sensitivity; 
    playerVelocity.y = playerVelocity.y * deceleration + acceleration.y * sensitivity; 

    if (playerVelocity.x > maxVelocity) 
    { 
     playerVelocity.x = maxVelocity; 
    } 
    else if (playerVelocity.x < -maxVelocity) 
    { 
     playerVelocity.x = -maxVelocity; 
    } 

    if (playerVelocity.y > maxVelocity) 
    { 
     playerVelocity.y = maxVelocity; 
    } 
    else if (playerVelocity.y < -maxVelocity) 
    { 
     playerVelocity.y = -maxVelocity; 
    } 
} 

- (void)update:(ccTime)delta 
{ 
    CGPoint pos = player.position; 
    pos.x += playerVelocity.x; 
    pos.y += playerVelocity.y; 

    CGSize screenSize = [[CCDirector sharedDirector] winSize]; 
    float imageWidthHalved = [player texture].contentSize.width * 0.5f; 
    float leftBorderLimit  = imageWidthHalved; 
    float rightBorderLimit = screenSize.width - imageWidthHalved; 

    if (pos.x < leftBorderLimit) 
    { 
     pos.x = leftBorderLimit; 
     playerVelocity = CGPointZero; 
    } 
    else if (pos.x > rightBorderLimit) 
    { 
     pos.x = rightBorderLimit; 
     playerVelocity = CGPointZero; 
    } 

    float imageHeightHalved = [player texture].contentSize.height * 0.5f; 
    float topBorderLimit  = screenSize.height - imageHeightHalved; 
    float bottomBorderLimit = imageHeightHalved; 

    if (pos.y < bottomBorderLimit) 
    { 
     pos.y = bottomBorderLimit; 
     playerVelocity = CGPointZero; 
    } 
    else if (pos.y > topBorderLimit) 
    { 
     pos.y = topBorderLimit; 
     playerVelocity = CGPointZero; 
    } 

    player.position = pos; 
} 

Quel est le problème?

+0

Huhh ~, si je supprime playerVelocity = CGPointZero; lignes (4 lignes) dans la méthode de mise à jour, cela fonctionne bien. Qu'est-ce que ... :( –

Répondre

2

Si vous voulez, vous pouvez essayer ce que je faisais dans mon jeu:

#define SIGN(x) ((x < 0.0f) ? -1.0f : 1.0f) 


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

    float kFilteringFactor = 0.01; 

    accels[0] = acceleration.x * kFilteringFactor + accels[0] * (1.0f - kFilteringFactor); 
    accels[1] = acceleration.y * kFilteringFactor + accels[1] * (1.0f - kFilteringFactor); 
    accels[2] = acceleration.z * kFilteringFactor + accels[2] * (1.0f - kFilteringFactor); 

    float xx; 
    float yy; 

    // extract the acceleration components 
    xx = -[acceleration x]; 
    yy = [acceleration y]; 

    // Has the direction changed? 
    float accelDirX = SIGN(xvelocity) * -1.0f; 
    float newDirX = SIGN(xx); 
    float accelDirY = SIGN(yvelocity) * -1.0f; 
    float newDirY = SIGN(yy); 

    // Accelerate. To increase viscosity, lower the values below 1.0f 
    if (accelDirX == newDirX) 
     xaccel = (abs(xaccel) + 0.99f) * SIGN(xaccel); 
    if (accelDirY == newDirY) 
     yaccel = (abs(yaccel) + 0.99f) * SIGN(yaccel); 

    // Apply acceleration changes to the current velocity 
    xvelocity = -xaccel * xx; 
    yvelocity = -yaccel * yy; 

    [sprite moveByAccelerometerX:yvelocity Y:xvelocity];   
} 
0

Tout d'abord, merci d'avoir lu mon livre! :)

Vous pouvez trouver une méthode de filtrage améliorée (facilité exponentielle) que I'm using in this article, il contient également des informations de base sur le fonctionnement de l'accéléromètre.

Vous pouvez en apprendre davantage sur l'entrée de l'accéléromètre from the Tilt to Live developers et leur approche, avec un exemple de projet.

+0

plus à mon commentaire, quel est le but de ces 4 lignes? –

0

J'ai acheté le livre et j'ai trouvé que le bord de la détection de collision d'écran ne fonctionne pas correctement sauf si vous avez le même sprite de taille que dans l'exemple. Soit faire votre sprite de la même taille ou faire le sprite enrouler autour de l'écran au lieu de s'arrêter, ce qui est ce que j'ai fait.