iPhone轮(命运)旋转动力

时间:2012-01-16 16:36:21

标签: iphone objective-c touch angular-momentum

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

任何能给我一些指示的人,都不一定要在客观方面。 AS3,javascript或JAVA也足够了。

*更新(旋转方向的代码)*

    -(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);
    };

3 个答案:

答案 0 :(得分:5)

你希望动力因摩擦而减少;摩擦力是速度的函数。所以从技术上讲,你已经有了一个微分方程式。然而,这并不值得投入太多的思考,因为解决方案可能更容易通过手挥手达到。

所以:存储当前角度和当前角速度。 n 次秒(可能通过NSTimerCADisplayLink)将角速度加到角度,然后将角速度乘以某个值使其变小 - 例如0.995。接近1.0的常数将使得减速需要更长的时间;如果你超过1.0,它显然会加速。这实际上是欧拉整合的一种形式,但同样值得担忧。

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

要从拖动中获取初始速度,您可以计算出从滚轮中心到拖动开始的矢量,将该矢量旋转90度,使用该矢量做一个点积,拖动矢量和比例离中心的距离。

答案 1 :(得分: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

答案 2 :(得分: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"];
    };