iPhone、cocos2d和加速计

iPhone、cocos2d和加速计,iphone,cocos2d-iphone,Iphone,Cocos2d Iphone,我正在阅读《学习iPhone和iPad Cocos2D游戏开发》,在第4章中,有一个使用加速度计的简单示例。如果我只使用x轴作为书本,效果会很好,但如果使用y轴,如果在屏幕边缘,sprite的移动会很不平滑 + (id)scene { CCScene* scene = [CCScene node]; CCLayer* layer = [GameScene node]; [scene addChild:layer]; return scene;

我正在阅读《学习iPhone和iPad Cocos2D游戏开发》,在第4章中,有一个使用加速度计的简单示例。如果我只使用x轴作为书本,效果会很好,但如果使用y轴,如果在屏幕边缘,sprite的移动会很不平滑

+ (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;
}
+(id)场景
{
CCScene*scene=[CCScene节点];
CCLayer*layer=[游戏场景节点];
[场景添加子对象:层];
返回场景;
}
-(id)init
{
if((self=[super init]))
{
CCLOG(@“%@:%@”、NSStringFromSelector(_cmd)、self);
self.isAccelerometerEnabled=是;
player=[CCSprite spriteWithFile:@“alien.png”];
[自我添加子项:玩家z:0标记:1];
CGSize screenSize=[[CCDirector sharedDirector]winSize];
float imageHeight=[player纹理].contentSize.height;
player.position=CGPointMake(screenSize.width/2,imageHeight/2);
[自计划更新];
}
回归自我;
}
-(无效)解除锁定
{
CCLOG(@“%@:%@”、NSStringFromSelector(_cmd)、self);
[super dealoc];
}
-(无效)加速计:(UIAccelerator*)加速计DID加速度:(UIAcceleration*)加速度
{   
浮动减速度=0.4f;
浮动灵敏度=6.0f;
浮点最大速度=100;
playerVelocity.x=playerVelocity.x*减速+加速.x*灵敏度;
playerVelocity.y=playerVelocity.y*减速+加速.y*灵敏度;
if(playerVelocity.x>maxVelocity)
{
playerVelocity.x=最大速度;
}
else if(playerVelocity.x<-maxVelocity)
{
playerVelocity.x=-maxVelocity;
}
if(playerVelocity.y>maxVelocity)
{
playerVelocity.y=最大速度;
}
else if(playerVelocity.y<-maxVelocity)
{
playerVelocity.y=-maxVelocity;
} 
}
-(无效)更新:(ccTime)增量
{
CGPoint pos=玩家位置;
pos.x+=playerVelocity.x;
位置y+=游戏性y;
CGSize screenSize=[[CCDirector sharedDirector]winSize];
浮动图像宽度减半=[player纹理].contentSize.width*0.5f;
浮动leftBorderLimit=图像宽度减半;
float rightBorderLimit=屏幕大小.width-图像宽度减半;
如果(位置x右边界限制)
{
位置x=右边界限制;
playerVelocity=CGPointZero;
}
float imageHeightHalved=[player纹理].contentSize.height*0.5f;
float topBorderLimit=屏幕大小.height-图像高度减半;
浮动底部边界限制=图像高度减半;
如果(位置y<底部边界限制)
{
位置y=底部边界极限;
playerVelocity=CGPointZero;
}
否则如果(位置y>顶部边界限制)
{
位置y=顶部边界限制;
playerVelocity=CGPointZero;
}
player.position=pos;
}

有什么问题吗?

如果您愿意,可以试试我在游戏中所做的:

#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];        
}
定义符号(x)((x<0.0f)?-1.0f:1.0f) -(无效)加速计:(UIAccelerator*)加速计DID加速度:(UIAcceleration*)加速度{ 浮动kFilteringFactor=0.01; 加速度[0]=加速度.x*kFilteringFactor+加速度[0]*(1.0f-kFilteringFactor); 加速度[1]=加速度.y*kFilteringFactor+加速度[1]*(1.0f-kFilteringFactor); 加速度[2]=加速度.z*kFilteringFactor+加速度[2]*(1.0f-kFilteringFactor); 浮动xx; 浮动yy; //提取加速度分量 xx=-[加速度x]; yy=[加速度y]; //方向改变了吗? 浮动加速度dirx=符号(x速度)*-1.0f; float newDirX=符号(xx); 浮动加速度=符号(yvelocity)*-1.0f; 新浮点数=符号(yy); //加速。要增加粘度,请将值降至1.0f以下 如果(accelDirX==newDirX) xaccel=(abs(xaccel)+0.99f)*符号(xaccel); 如果(加速度==newDirY) yaccel=(abs(yaccel)+0.99f)*符号(yaccel); //将加速度更改应用于当前速度 xvelocity=-xaccel*xx; yvelocity=-yaccel*yy; [sprite MoveByAccelerometrx:yvelocity Y:xvelocity]; }
首先,感谢您阅读我的书!:)

您可以找到一种改进的过滤方法(指数法),它还包含有关加速度计工作原理的基本信息


您可以通过一个示例项目了解有关加速度计输入及其方法的更多信息。

我买了这本书,发现屏幕碰撞检测边缘无法正常工作,除非您拥有与示例中相同大小的sprite。要么使你的精灵大小相同,要么让精灵环绕屏幕而不是停止,这就是我所做的。

Huhh~,如果我删除playerVelocity=CGPointZero;行(4行)在更新方法中,这工作得很好。(加上我的评论,这四行的目的是什么?