Проблема, связывающая замедление CCSprite с ccTime dt - PullRequest
2 голосов
/ 21 мая 2011

У меня есть подкласс CCSprite, который знает, как перемещаться, основываясь на двух свойствах float, 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?

1 Ответ

2 голосов
/ 21 мая 2011

Попробуйте использовать эту формулу вместо:

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

Логика математики:

Предположим, что частота кадров на симуляторе составляет 30 кадров в секунду по сравнению с обычными 60 кадрами в секунду на устройстве.Таким образом, для каждого кадра на симуляторе устройство уже показывает 2 кадра.Таким образом, каждый вызов на update на симуляторе должен давать один и тот же результат для 2 вызовов на устройстве.После двух вызовов на устройстве self.velX был умножен на kDeceleration два раза, что означает, что новое значение равно self.velX * kDeceleration * kDeceleration.По той же логике, если частота кадров на симуляторе составляет 1/3 от частоты кадров на устройстве, новое значение равно self.velX * kDeceleration * kDeceleration * kDeceleration.Таким образом, мы можем обобщить его как self.velX * pow(kDeceleration, n), где n - это количество раз, которое метод update должен быть вызван для достижения частоты кадров 60 кадров в секунду, что составляет 60 * dt.

...