我正在研究a game engine,我遇到了一个相当令人困惑的行为。我确信这很简单,但我想在进展之前搞清楚。
我已经将UIImageView
子类化,并添加了对多个动画精灵的支持。我也有控制工作,但我一直看到一种奇怪的行为。当我的角色向上或向左走时,动画会跳过一帧,并且看起来移动得更快。向右或向下移动会变慢并显示正确的三帧。
我已经完成了整个调用堆栈,我无法弄明白。这是发生的事情:
精灵移动代码如下所示:
// Move in a direction
- (void)moveInDirection:(MBSpriteMovementDirection)direction distanceInTiles:(NSInteger)distanceInTiles withCompletion:(void (^)())completion{
CGRect oldFrame = [self frame];
CGSize tileDimensions = CGSizeZero;
tileDimensions = [[self movementDataSource] tileSizeInPoints];
if (tileDimensions.height == 0 && tileDimensions.width == 0) {
NSLog(@"The tile dimensions for the movement method are zero. Did you forget to set a data source?\nI can't do anything with this steaming pile of variables. I'm outta here!");
return;
}
CGPoint tileCoordinates = CGPointMake(oldFrame.origin.x/tileDimensions.width, oldFrame.origin.y/tileDimensions.height);
// Calculate the new position
if (direction == MBSpriteMovementDirectionLeft || direction == MBSpriteMovementDirectionRight) {
oldFrame.origin.x += (tileDimensions.width * distanceInTiles);
tileCoordinates.x += distanceInTiles;
}else{
oldFrame.origin.y += (tileDimensions.height * distanceInTiles);
tileCoordinates.y += distanceInTiles;
}
if (![[self movementDelegate] sprite:self canMoveToCoordinates:tileCoordinates]) {
[self resetMovementState];
if(completion){
completion();
}
return;
}
[self startAnimating];
[UIView animateWithDuration:distanceInTiles*[self movementTimeScaleFactor] delay:0 options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionBeginFromCurrentState animations:^{
[self setFrame:oldFrame];
}
completion:^(BOOL finished) {
// Perform whatever the callback warrants
if(completion){
completion();
}
[self resetMovementState];
}];
}
如果MBSpriteMovement
方向(NSUInteger
的typedef)向上或向左,distanceInTiles
为负整数。计算出正确的距离,但由于某种原因,向下和向右看似慢。我确定它在向上/向左移动时会跳过一帧。
知道为什么吗?
(这是一个开源项目,可以找到here, on GitHub。)
答案 0 :(得分:1)
您需要确保给予UIView
动画例程的持续时间是非负的。这可以通过fabs
函数轻松完成:
NSTimeInterval animationDuration = fabs(distanceInTiles*[self movementTimeScaleFactor]);
[UIView animateWithDuration:animationDuration
delay:0
options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionBeginFromCurrentState
animations:^{
//...
}];