2012-01-16 43 views
4

我在向我的纺车添加动力时遇到困难。
我有这个轮子(类似于this),我用一个触摸事件围绕它的中心旋转它。
这里没有问题,但是当触摸(又名拖动)结束时;我想让车轮保持动力并缓解它的运动。

任何人谁可以给我一些指针,它不一定要在objective-c。 AS3,javascript或JAVA也足够了。iPhone车轮(财富)旋转势头

* UPDATE(用于旋转轮代码)*

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
     rotation = _startAngle = atan2(384 - touchPoint.y, 512 - touchPoint.x); 
    }; 

    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
     CGPoint touchPoint = [[touches anyObject] locationInView:self.view]; 
     rotation = atan2(384 - touchPoint.y, 512 - touchPoint.x); 
     rotation = fmod(rotation - _startAngle, M_PI * 2.0f); 
     [wheel setTransform:CGAffineTransformMakeRotation(_circleRotationOffset + rotation)]; 
    }; 

    -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
     _circleRotationOffset = fmod(_circleRotationOffset + rotation, M_PI * 2); 
    }; 
+0

到底是如何处理你的旋转?发布一些代码。 – Jumhyn 2012-01-16 17:58:35

+0

^更新了我的文章w /代码 – basvk 2012-01-17 07:44:49

回答

5

你想要的势头,以减少因摩擦;摩擦力是速度的函数。所以在技术上你有一个微分方程。但这并不值得投入太多的思考,因为解决方案可能更容易通过挥手来达成。

因此:存储当前角度和当前角速度。 ñ每秒(可能通过NSTimerCADisplayLink)将角速度添加到角度,然后乘以角速度使其更小 - 例如0.995。接近1.0的常量会使其放慢速度需要更长的时间;如果你高于1.0,它显然会加速。这实际上是欧拉整合的一种形式,但同样不值得担忧。

它可能也值得在角速度上设置一个最小值,这样如果它下降到0.01弧度/秒以下,那么你将它降低到0.这就有效地修改了你的摩擦模型,从动态跳跃到静摩擦在适当的时候,并充当浮点精度缓冲区。

要从拖动中获得初始速度,您只需计算出从轮子中心到拖动起点的矢量,将该矢量旋转90度,使用该矢量做点积,拖动矢量和比例根据距离中心的距离。

+0

乘以分数并减去一小部分。这将确保你在有限的时间内达到零。 – 2012-01-16 18:20:47

+0

感谢您让我朝着正确的方向前进,我做了类似的事情,但没有得到正确的结果。在我的回答中,我使用接触点进行计算而不是(当前)旋转 – basvk 2012-01-17 09:50:02

1

如果您正在使用的代码纺的UIImageView像:
[UIView beginAnimations:@"rotateImage" context:nil];
[UIView setAnimationDuration:4.0];
wheelImageView.transform = CGAffineTransformMakeRotation(3.14159265*5);
[UIView commitAnimations];

你可以使用[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
这使得这样的动画将快速启动关闭,并开始放缓随着时间的推移。

Click Here for More info on UIViewAnimationCurve

+1

这不是问题。问题是'外推'或'势头' – basvk 2012-01-17 07:30:50

1

我设法得到了一些不错的成绩。
我怎么做的,应该进行调整更多,但是这是最基础的:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
     CGPoint touchPoint = [[touches anyObject] locationInView:self.view]; 
     rotation = _startAngle = atan2(384 - touchPoint.y, 512 - touchPoint.x); 
     [_history removeAllObjects]; 
    }; 

    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
     CGPoint touchPoint = [[touches anyObject] locationInView:self.view]; 
     [_history insertObject:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithDouble:CFAbsoluteTimeGetCurrent()], @"time", [NSValue valueWithCGPoint:touchPoint], @"point", [NSNumber numberWithFloat: _circleRotationOffset + rotation], @"rotation", nil] atIndex:0]; 
     if ([_history count] == 3) { 
      [_history removeLastObject]; 
     } 

     rotation = atan2(384 - touchPoint.y, 512 - touchPoint.x) - _startAngle; 
     [circleImage setTransform:CGAffineTransformMakeRotation(_circleRotationOffset +   rotation)]; 
    }; 

    -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
     CGPoint tp = [[touches anyObject] locationInView:self.view]; 
     _circleRotationOffset += rotation; 

     NSDictionary *lo = [_history lastObject]; 
     CGPoint pp = [[lo objectForKey:@"point"] CGPointValue]; 
     double timeDif = CFAbsoluteTimeGetCurrent() - [[lo objectForKey:@"time"] doubleValue]; 
     float lastRotation = [[lo objectForKey:@"rotation"] floatValue]; 

     // Calculate strength 
     float dist = sqrtf(((pp.x - tp.x) * (pp.x - tp.x)) + ((pp.y - tp.y) * (pp.y - tp.y))); 
     float strength = MIN(1.0f, dist/80.0f) * (timeDif/.025) * M_PI; 

     float p = _circleRotationOffset; 
     float dif = _circleRotationOffset - lastRotation; 
     BOOL inc = dif > 0; 
     if (dif > 3 || dif < -3) { // Some correction 
      inc = !inc; 
     } 

     if (inc) { 
      _circleRotationOffset += strength; 
     } else { 
      _circleRotationOffset -= strength; 
     } 

     [circleImage.layer removeAllAnimations]; 
     CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"]; 
     animation.duration = MAX(strength/2.5, 1.0f); 
     animation.cumulative = YES; 
     animation.repeatCount = 1; 
     animation.values = [NSArray arrayWithObjects:   
        [NSNumber numberWithFloat:p], 
        [NSNumber numberWithFloat: _circleRotationOffset], nil]; 
     animation.keyTimes = [NSArray arrayWithObjects:  
         [NSNumber numberWithFloat:0], 
         [NSNumber numberWithFloat:1.0], nil]; 
     animation.timingFunctions = [NSArray arrayWithObjects: 
          [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut], nil]; 
     animation.removedOnCompletion = YES; 
     animation.delegate = self; 
     animation.fillMode = kCAFillModeForwards; 

     [circleImage.layer addAnimation:animation forKey:@"rotate"]; 
    }; 
+0

你能解释一下这里发生了什么? _circleRotationOffset是从0到手指的角度,并且您正在添加从手指到手指的小旋转?如果你不介意的话,更具描述性会更好。 – Daniel 2012-08-22 15:06:07

+0

'_circleRotationOffset'将是车轮的'当前'旋转。这将从'0'开始,并将在整个触摸中更新。所有解决这个问题的方法都是计算动量。 – basvk 2012-08-22 16:30:31

+0

但是当前角度不应该很重要。我写了一个手势识别器,用于围绕中心点旋转一个手指。当我结束时,我可以检查委托符合我的可选“继续旋转”协议,如果是的话,我沿着速度和方向传递。代表说,视图控制器,现在有一个速度(弧度/秒)和方向(顺时针/逆时针)。我试图使用CAKeyframeAnimation来实现像你一样的动量旋转。在CA上遇到困难。不想发布另一个问题,因为它与你的重复。所以试图使用这里的东西。提示? – Daniel 2012-08-22 17:39:59