Импульс вращения колеса iPhone (фортуны)

У меня трудности с добавлением импульса к вращающемуся колесу.
У меня есть это колесо (что-то вроде этого), и я вращаю его вокруг его центра, используя одно касание.
Здесь нет проблем, но когда касание (иначе перетаскивание) заканчивается; Я хочу, чтобы колесо сохраняло свой импульс и облегчало его движение.

Любой, кто может дать мне несколько советов, не обязательно должен быть в объективе-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);
    };

3 ответа

Решение

Вы хотите, чтобы импульс уменьшился из-за трения; трение - это сила, которая является функцией скорости. Технически, у вас есть дифференциальное уравнение. Однако не стоит вкладывать в это слишком много внимания, потому что решение, вероятно, легче найти, взмахнув рукой.

Итак: сохраняем текущий угол и текущую угловую скорость. n раз в секунду (вероятно, через NSTimer или CADisplayLink) добавьте угловую скорость к углу, затем умножьте угловую скорость на что-то, чтобы уменьшить ее - например, 0,995. Константы, близкие к 1,0, замедляют процесс; если вы пойдете выше 1,0, он, очевидно, ускорится. По сути, это форма интеграции Эйлера, но, опять же, об этом не стоит беспокоиться.

Возможно, также стоит установить минимальный предел угловой скорости, чтобы, если она упадет ниже, скажем, 0,01 радиана в секунду, вы снизите ее до 0. Это эффективно немного изменит вашу модель трения для перехода от кинетического к статическому трению в подходящий момент. и действует как буферная зона точности с плавающей точкой.

Чтобы получить начальную скорость от перетаскивания, вы можете просто обработать вектор от центра колеса до начала перетаскивания, повернуть этот вектор на 90 градусов, сделать с ним точечное произведение, вектор перетаскивания и масштабировать в соответствии с расстоянием от центр.

Мне удалось получить хорошие результаты.
Как я это сделал, надо подправить еще, но это основы:

    -(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"];
    };

Если вы вращаете UIImageView с кодом вроде:
[UIView beginAnimations:@"rotateImage" context:nil];
[UIView setAnimationDuration:4.0];
wheelImageView.transform = CGAffineTransformMakeRotation(3.14159265*5);
[UIView commitAnimations];

Вы могли бы использовать [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
Это делает так, чтобы анимация начиналась быстро и начинала замедляться со временем.

Нажмите здесь для получения дополнительной информации о UIViewAnimationCurve

Другие вопросы по тегам