4

我很难为我的纺车增加动力。
我有这个轮子(类似这样的东西),我通过使用单点触摸事件围绕它的中心旋转它。
这里没有问题,但是当触摸(又名拖动)结束时;我希望轮子保持它的动力并减轻它的运动。

任何人都可以给我一些指示,它不一定必须在objective-c中。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);
    };
4

3 回答 3

5

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

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

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

要从拖动中获得初始速度,您只需计算出从车轮中心到拖动开始的向量,将该向量旋转 90 度,用它和拖动向量进行点积并根据距离进行缩放中心。

于 2012-01-16T18:18:42.813 回答
1

如果您使用以下代码旋转 UIImageView:
[UIView beginAnimations:@"rotateImage" context:nil];
[UIView setAnimationDuration:4.0];
wheelImageView.transform = CGAffineTransformMakeRotation(3.14159265*5);
[UIView commitAnimations];

您可以使用[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
This makes it so 动画将快速启动并随着时间的推移开始减慢。

单击此处了解有关 UIViewAnimationCurve 的更多信息

于 2012-01-16T18:28:46.040 回答
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"];
    };
于 2012-01-17T09:47:33.187 回答