开发者

Trouble tying a CCSprite deceleration to the ccTime dt

开发者 https://www.devze.com 2023-03-07 21:57 出处:网络
I\'ve got a subclass of CCSprite that knows how to move itself based on two float properties, velX and velY.I call the subclass\'s - (void)update:(ccTime)dt method from the method of the same name in

I've got a subclass of CCSprite that knows how to move itself based on two float properties, velX and velY. I call the subclass's - (void)update:(ccTime)dt method from the method of the same name in my game layer.

I use dt to scale how much I move the player and it works great. I'd like to use dt to scale a deceleration factor to make how the player slows down consistent regardless of how often it's updated.

But it just makes my CCSprite not even show up.

Here's the CCSprite class...


#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 *开发者_如何学Python= 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

The problem is in the // decelerate section. If I leave out the * 0.0165 / dt part of the two lines that decelerate the player, it works, but it's way faster on the phone than the simulator due to framerate differences. This should scale it, but it just screws it up.

I've tried all kinds of NSLogging and if I use dt at all, I get nan for the value of my velX and velY properties.

Could it have something to do with using the method name -update?


Try using this formula instead:

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

The logic behind the math:

Suppose the framerate on simulator is at 30fps compared to the normal 60fps on device. Thus, for every frame on simulator, the device already shows 2 frames. Thus every call on the update on simulator should give the same result for 2 calls on device. After two calls on device, self.velX has been multiplied by kDeceleration two times, meaning the new value is equal to self.velX * kDeceleration * kDeceleration. By same logic, if the framerate on simulator is 1/3 of that on device, the new value is self.velX * kDeceleration * kDeceleration * kDeceleration. Thus, we can generalize it as self.velX * pow(kDeceleration, n) where n is the number of times the update method to be called to catch up with framerate of 60fps, which is 60 * dt.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号