2012-01-16 77 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