iphone - 将 CCSprite 减速与 ccTime dt 绑定(bind)时出现问题

标签 iphone ios cocos2d-iphone benchmarking

我有一个 CCSprite 的子类,它知道如何根据两个浮点属性 velX 和 velY 移动自己。我从游戏层中的同名方法调用子类的 - (void)update:(ccTime)dt 方法。

我使用 dt 来缩放播放器的移动量,效果很好。我想使用 dt 来缩放减速因子,以使播放器的减速方式保持一致,而不管它更新的频率如何。

但这只会让我的 CCSprite 甚至不显示。

这是 CCSprite 类...


#import "Player.h"

#define kDeceleration 0.95

@implementation Player

@synthesize velX, velY;

# pragma mark

+ (id)player
{
    Player *player = nil;
    if ((player = [[[super alloc] initWithFile:@"rocket.png"] autorelease])) {
    player.velX = 0.0;
    player.velY = 0.0;
    }
    return player;
}

- (void)update:(ccTime)dt
{
    CGSize winSize = [[CCDirector sharedDirector] winSize];

    // move
    self.position = ccp(self.position.x + self.velX * dt, self.position.y + self.velY * dt);
    if (self.position.x < -self.contentSize.width/2) self.position = ccp(winSize.width + self.contentSize.width/2, self.position.y);
    if (self.position.x > winSize.width + self.contentSize.width/2) self.position = ccp(-self.contentSize.width/2, self.position.y);
    if (self.position.y < -self.contentSize.width/2) self.position = ccp(self.position.x, winSize.height + self.contentSize.width/2);
    if (self.position.y > winSize.height + self.contentSize.width/2) self.position = ccp(self.position.x, -self.contentSize.width/2);

    // decelerate
    self.velX *= kDeceleration * 0.0165 / dt; // works if the line is: self.velX *= kDeceleration;
    if (fabs(self.velX) < 1.0) self.velX = 0.0;
    self.velY *= kDeceleration * 0.0165 / dt; // works if the line is: self.velY *= kDeceleration;
    if (fabs(self.velY) < 1.0) self.velY = 0.0;

}

- (void)draw
{
    [super draw];
    glLineWidth(1);
    ccDrawCircle(ccp(self.contentSize.width/2, self.contentSize.height/2), 3*self.contentSize.width/4, CC_DEGREES_TO_RADIANS(360), 60, NO);
}

@end

问题出在 //decelerate 部分。如果我省略了使播放器减速的两条线的 * 0.0165/dt 部分,它会起作用,但由于帧率差异,它在手机上比模拟器快得多。这应该可以扩展它,但它只是把它搞砸了。

我已经尝试了所有类型的 NSLogging,如果我完全使用 dt,我会得到 nan 作为我的 velX 和 velY 属性的值。

会不会和使用方法名-update有关?

最佳答案

尝试改用这个公式:

float decelerator = pow(kDeceleration, 60 * dt);
self.velX *= decelerator;
self.velY *= decelerator;

数学背后的逻辑:

假设模拟器上的帧率为 30fps,而设备上的正常帧率为 60fps。因此,对于模拟器上的每一帧,设备已经显示 2 帧。因此,模拟器上 update 的每次调用都应为设备上的 2 次调用提供相同的结果。在设备上两次调用后,self.velX 已乘以 kDeceleration 两次,这意味着新值等于 self.velX * kDeceleration * kDeceleration。按照同样的逻辑,如果模拟器上的帧速率是设备上帧速率的 1/3,则新值是 self.velX * kDeceleration * kDeceleration * kDeceleration。因此,我们可以将其概括为 self.velX * pow(kDeceleration, n) 其中 n 是调用 update 方法以 catch 帧速率的次数60fps,即 60 * dt

关于iphone - 将 CCSprite 减速与 ccTime dt 绑定(bind)时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6079114/

相关文章:

ios - 有时 Sprite 在接触另一个 Sprite 时会被推开

iphone - 如何为充满空气的气球制作动画

iphone - 适用于 ios 的 360° 全景库

iphone - 在没有应用内购买的情况下在iPhone应用中销售产品

iphone - iOS 推送通知问题

ios - UITableView 背景 View nil 在 iOS 5 中不起作用

objective-c - 在 NSMutableArray 中比较字符串的问题

cocos2d-iphone - 为什么 iPhone 5 会在 Cocos2d 中进行简单的 Letterboxing 和显示 Default.png?

ios - UITableView 不准确地发布其内容

iphone - 如何链接到我在 App Store (iTunes) 中的应用程序?