iPhone, cocos2d и акселерометр - PullRequest
0 голосов
/ 09 декабря 2010

Я читаю «Изучите разработку игр для iPhone и iPad Cocos2D», и в главе 4 приведен простой пример использования акселерометра. Это хорошо работает, если я использую ось X только как книгу, но с осью Y, движение спрайта не плавное, если оно на краю экрана.

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

В чем проблема?

Ответы [ 3 ]

2 голосов
/ 10 декабря 2010

Если хотите, можете попробовать то, что я сделал в моей игре:

#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 голосов
/ 17 декабря 2010

Я купил книгу и обнаружил, что обнаружение столкновений с краем экрана не работает должным образом, если у вас нет спрайта такого же размера, как в примере. Либо сделайте ваш спрайт того же размера, либо сделайте обтекание спрайта вокруг экрана вместо остановки, что я и сделал.

0 голосов
/ 14 декабря 2010

Прежде всего, спасибо за чтение моей книги!:)

Вы можете найти улучшенный метод фильтрации (легкая экспонента), который , который я использую в этой статье , также содержит основную информацию о работе акселерометра.* Вы можете узнать больше о входе акселерометра от разработчиков Tilt to Live и их подходе, поставляемом с примером проекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...