基于时序的可变数字之间的转换代码

时间:2015-04-11 07:58:57

标签: c++ animation mapping transition openframeworks

我希望那里的某个人可能知道如何更好地解决我为自己创造的问题:)我目前正在寻找一种方法来编写这种逻辑: 想象一下,我有一个控制滑块,用户控制并从0到255,想象我有一个时间滑块,从0毫秒到20,000毫秒。

现在,如果我将时间滑块设置为20,000,并将控制滑块从0移动到255,我预计代码将在20秒内输出0到255之间的转换点。我有这样做的代码很好,它将在下面附上。

然而,让我们说在过渡期间10秒钟,用户将控制滑块从255移回0.在10秒后,转换点x应该是127.我想要发生的是x值在剩余的10秒内移动到新的控制滑块点,在这种情况下为0.理想情况下,这应该适用于20秒周期内的任意数量的移动。

一旦x到达控制滑块点,转换代码将停用,直到下一次移动。

这是处理我试图解决的问题的第一部分的代码:

class Fader {

public:

float newFaderValueSetTime;

float newFaderValue;

bool transitionInMotion;

float lastReturnedValueWhenNewFaderValueWasSet;

bool newFaderValueSet;

float lastOutputValue;

Fader(void) {
    lastReturnedValueWhenNewFaderValueWasSet = 0;
    newFaderValue = 0;
    lastOutputValue = 0;
    transitionInMotion = false;
}

int getValue(float delayAmount) {
    float currentTime = ofGetElapsedTimeMillis() ;
    float timePassedSinceNewFaderValue = currentTime - newFaderValueSetTime;        

    if(timePassedSinceNewFaderValue >= delayAmount) {
        transitionInMotion = false;
    }

    if(transitionInMotion) {
        lastOutputValue =  ofMap(timePassedSinceNewFaderValue, 0, delayAmount, lastReturnedValueWhenNewFaderValueWasSet, newFaderValue);
    } else {
        lastOutputValue = newFaderValue;
    }

    return lastOutputValue;
}   


void setFaderValue(int val, float delayAmount) {

    if(delayAmount > 0 && !transitionInMotion) {
        transitionInMotion = true;
        newFaderValueSetTime = ofGetElapsedTimeMillis();
        lastReturnedValueWhenNewFaderValueWasSet = lastOutputValue;         
    }   
    newFaderValue = val;    
}
};

这是使用OpenFrameworks的c ++,因此是某些函数的前缀。无论如何,我希望我对这个问题有足够的了解。

问题的代码要点,我认为值范围的映射函数的方式 - 例如,采取这一行:       lastOutputValue = ofMap(timePassedSinceNewFaderValue,0,delayAmount,lastReturnedValueWhenNewFaderValueWasSet,newFaderValue);

此行将经过的时间量作为时间位置,使其相对于延迟量,然后将其值从lastReturnedValueWhenNewFaderValueWasSet重新映射到newFaderValue ...例如,

如果在转换时,推子值为0,则移至255,然后 lastReturnedValueWhenNewFaderValueWasSet = 0,newFaderValue = 255;

然而,在10秒标记处,lastOutputValue将为127,如果我然后将newFaderValue从255移动到0,则lastReturnedValueWhenNewFaderValueWasSet仍将为0,并且映射将从0到0,而不是从转换点的当前位置,x。

我希望这能更好地解释逻辑。干杯!

1 个答案:

答案 0 :(得分:0)

我已经解决了我提出的问题。以下是寻找解决此类问题的人的逻辑和代码的概要。

如果目的地大于x

将增加 如果目的地小于x

将减少

x定义为启动计时器之前设置的值

当且仅当

时,计时器处于活动状态

计时器大于零 目的地大于或小于x

增加量定义为x,目的地之间的距离除以到达目的地的剩余时间乘以自上次设定x以来的差值。

e.g。 假设x是127,目标是200.剩余时间是10,000毫秒

正差= 200-127 = 73超过10,000

除以剩余时间,乘以自上次更新以来的时间变化。

(200-127 / 10,000)* 60(自上次更新以来的毫秒数)

=增加的数量......

假设x = 200且目的地为90.剩余时间为10,000毫秒

正差异为200-90 = 110。

(110 / 10,000)* 60(自上次更新以来的毫秒数)= 0.66 ..将从x中移除...

并且因为x在这种情况下正在减少,所以额外计算(0.66 * -1)以产生负值。

代码:

class Fader {

public:


float newFaderValueSetTime;
float destination;
float lastUpdateTime;
float x;

bool transitionInMotion;

Fader(void) {

    transitionInMotion = false;
    lastUpdateTime = -1;

    x= 0;
    destination = 0;

}

float positiveDifference(float x1, float y1) {
    if(x1>y1) {
        return x1-y1;
    } else {
        return y1-x1;
    }
}

int getValue(float delayAmount) {
    float currentTime = ofGetElapsedTimeMillis();       

    float timePassedSinceNewFaderValue = currentTime - newFaderValueSetTime;    

    if(timePassedSinceNewFaderValue >= delayAmount) {
        transitionInMotion = false;
    }

    if(transitionInMotion) {
        float timeRemaining = delayAmount - timePassedSinceNewFaderValue;

        float diff = positiveDifference(x, destination);

        float tempX = (diff / timeRemaining);

        if(lastUpdateTime == -1) {
            lastUpdateTime = currentTime;
        } else {
            tempX = tempX * (currentTime - lastUpdateTime);
        }           

        if(destination > x) {
            x = x + tempX;
        } else if (destination < x) {
            x = x + (tempX*-1); 
        } 
    } else {
        x = destination;
    }


    if(x > 0) {
        ofLogNotice("Output Value of fader is: " + ofToString(x));
    }

    lastUpdateTime = currentTime;

    return x;
}   


void setFaderValue(int val, float delayAmount) {

    if(delayAmount > 0 && !transitionInMotion) {
        transitionInMotion = true;
        newFaderValueSetTime = ofGetElapsedTimeMillis();
        lastUpdateTime = -1;
    }   
    destination = val;  
}
};