3

我正在为 iPad 开发节拍器。我将CGAffineTransformRotate用于节拍器臂动画,将NSTimer(我对高精度不感兴趣)用于声音,并使用UIPanGestureRecognizer将节拍器重量拖到节拍器臂上。在此处输入图像描述

我的问题是我不知道如何通过使用平底锅拖动重量来更新 bpm。现在我有这个:metronomeWeight.center.y是240,这个位置的默认bpm是80。重量从前140到最大450。我已经实现了这个方法,但它不正确:

-(void)updateBPM
    {
        CGFloat weightYPosition = metronomeWeight.center.y;
        NSUInteger newBPM = (weightYPosition/3);
        self.bpm = newBPM;
    }

平底锅的选择器是这样的:

-(void)handlePan:(UIPanGestureRecognizer*)gesture
{

    CGPoint translation = [gesture translationInView:metronomeArm];
    CGPoint location = [gesture locationInView:metronomeArm];

    NSLog(@"miscarea pe oy are valoare de: %f", location.y);

    CGPoint newCenter = CGPointMake(metronomeArm.frame.size.width/2, gesture.view.center.y + translation.y );

    if (newCenter.y >= 140 && newCenter.y <= 450) 
{
        gesture.view.center = newCenter;
        [gesture setTranslation:CGPointZero inView:metronomeArm];
        [self updateBPMFromWeightLocation];
        tempoLabel.text = [NSString stringWithFormat:@"%d", self.bpm];
        NSLog(@"metronomeWeight position : %f ",metronomeWeight.center.y);
    }
}

声音和动画更新但不符合要求,这意味着下限 bpm 应为 225,上限应为 1。在我的情况下,它们分别为 150 和 46。

我的计算不好,所以如果你能帮我解决这个问题,那就太棒了……我看了苹果的节拍器项目好几天了,不明白他们是怎么做到的……

谢谢

得益于@zimmryan 的建议,新的 updateBPM 方法

-(void)updateBPMFromWeightLocation
{
    CGFloat weightYPosition = metronomeWeight.center.y;
    float lengthInM = ((weightYPosition - 140) * 0.00041333);
    float time = 2 * M_PI * sqrt(lengthInM / 9.8);
    NSUInteger newBPM = floor(60.0 / time);
    self.bpm = newBPM;
}
4

1 回答 1

3

根据我对物理学和微积分的理解,钟摆周期的方程是 T=2pi sqrt(l/g),其中 T 是以秒为单位的时间,l 是以米为单位的长度,g 是重力。

您正在选择 290(像素)的基点和 120 的 BPM。120 的 BPM 转换为 0.5 秒的周期。所以 T = .5。求解方程,得到 l 的 0.062,或 6.2cm。

但是您的长度不是以 cm 为单位,而是以像素为单位,现在您必须对其进行转换。因为你的范围是从 140 到 350,你的零点是 350。所以首先你取 350 - 390 来获得 60 的偏移量。现在创建你的方程 60pixels * k = .062 所以你的 k = .001033

您的最终功能应为

-(void)updateBPM
{
    CGFloat weightYPosition = metronomeWeight.center.y;
    float lengthInM = ((350 - weightYPosition) * .001033);
    float time = 2 * M_PI * sqrt(lengthInM / 9.8);
    NSUInteger newBPM = floor(60 / time);
    self.bpm = newBPM;
}

或者

-(void)updateBPM
{
    self.bpm = floor(60 / (2 * M_PI * sqrt(((350 - metronomeWeight.center.y) * .001033) / 9.8)));
}
于 2013-05-15T15:44:37.000 回答