简体   繁体   English

iPhone,cocos2d和加速度计

[英]iPhone, cocos2d and accelerometer

I'm reading 'Learn iPhone and iPad Cocos2D Game Development' and in chapter 4, there's a simple sample using accelerometer. 我正在阅读'学习iPhone和iPad Cocos2D游戏开发',在第4章中,有一个使用加速度计的简单示例。 It works well if I use x-axis only as the book but with y-axis, sprite's movement is not smooth if it on the edge of the screen. 如果我仅将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;
}

What's the problem? 有什么问题?

If you want you can try what I did in my game: 如果你想要你可以尝试我在游戏中所做的事情:

#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];        
}

First of all, thanks for reading my book! 首先,感谢您阅读我的书! :) :)

You can find an improved filtering method (ease exponential) that I'm using in this article , it also contains basic info on how the accelerometer works. 您可以找到我在本文中使用的改进的过滤方法(易指数),它还包含有关加速度计如何工作的基本信息。

You can learn more about accelerometer input from the Tilt to Live developers and their approach, comes with a sample project. 您可以从Tilt to Live开发人员及其方法中了解有关加速计输入的更多信息,并附带一个示例项目。

I have bought the book and I found that the edge of screen collision detection doesn't work properly unless you have the same size sprite as in the example. 我已经买了这本书,发现屏幕碰撞检测的边缘无法正常工作,除非您具有与示例中相同的大小精灵。 Either make your sprite the same size or make the sprite wrap around the screen instead of stopping, which is what I did. 要么让您的精灵大小相同,要么让精灵环绕屏幕而不是停下来,这就是我所做的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM