我在为我的纺车增加动力方面遇到了困难
我有这个轮子(类似于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);
};
答案 0 :(得分:5)
你希望动力因摩擦而减少;摩擦力是速度的函数。所以从技术上讲,你已经有了一个微分方程式。然而,这并不值得投入太多的思考,因为解决方案可能更容易通过手挥手达到。
所以:存储当前角度和当前角速度。 n 次秒(可能通过NSTimer
或CADisplayLink
)将角速度加到角度,然后将角速度乘以某个值使其变小 - 例如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"];
};