1

我目前正在开发一个系统,其中对象沿着贝塞尔曲线动画。在曲线上的各种用户定义点处,可能存在动画对象必须响应的事件。这可能是速度的变化,动画例程的变化,面对方向的变化等......

到目前为止,我有以下 AnimationEvent 类。

class AnimationEvent
{
private:
    unsigned int    m_eventID;

    float   m_InteroplationPoint;

    float   m_SpeedInMPS;

public:
    AnimationEvent(unsigned int id, float interpolationPoint);
    ~AnimationEvent(void);

    const unsigned int getEventID();
    void setInterpolationPoint(float interpPoint);
    const float getInterpPoint();

    const float getSpeed();
};

每个事件都被分配为沿曲线的对象,当到达其插值点时,曲线类调用该getSpeed()函数以更改当前动画速度。

我真正想做的是实现一个系统,例如使用装饰器设计模式,其中事件可以用多个对象装饰,当达到时,将应用所有装饰。我遇到的问题是我无法将指向父对象的指针传递给子对象,因为这会创建一个循环依赖项,但我也有一个问题,我不知道(在编译时)什么类型的动作活动将被装饰。

任何关于如何克服这个问题的想法将不胜感激!如果我忘记了任何可能有帮助的信息,我会尝试编辑它。

4

2 回答 2

2

如果您愿意跟踪以前发生在对象上的所有事件,则可以将类似装饰器的模式应用于此问题。您需要做的就是将每个事件存储在某种向量中。然后你可以做任何你想做的操作。

#include <iostream>
#include <vector>
using namespace std;

class Animatee;
class AnimateEvent
{
public:
    virtual Animatee & perform(Animatee & on) = 0;
};

class Animatee
{
public:
    Animatee() : value(0){};

    void addEvent(AnimateEvent * event)
    {
        if(event != NULL)
        {
            events.push_back(event);
        }

    }

    Animatee & act()
    {
        for(vector<AnimateEvent * >::iterator it = events.begin(); it != events.end();++it)
        {
            AnimateEvent * event = *it;
            event->perform(*this);
        }

        return *this;
    }

    double value;   //don't do this, but something more encap'ed
private:

    vector<AnimateEvent * > events;
};

class Add : public AnimateEvent
{
    virtual Animatee & perform(Animatee & on)
    {
        on.value = on.value + 1;
        return on;
    }
};

class Subtract : public AnimateEvent
{
    virtual Animatee & perform(Animatee & on)
    {
        on.value = on.value - 1;
        return on;
    }
};

class Multiply : public AnimateEvent
{
    virtual Animatee & perform(Animatee & on)
    {
        on.value = on.value * 2;
        return on;
    }
};

class Div : public AnimateEvent
{
    virtual Animatee & perform(Animatee & on)
    {
        on.value = on.value / 2.0;
        return on;
    }
};

int main() {
    Animatee matee;
    matee.addEvent(new Add());

    //cout << "Before: " << matee.value << " After: " << matee.act().value << endl; <~~~ Undefined btw, acting on the object twice in one "statement"
    double before = matee.value;
    cout << "Before: " << before << " After: " << matee.act().value << endl;

    matee.addEvent(new Subtract());
    before = matee.value;
    cout << "Before: " << before << " After: " << matee.act().value << endl;

    matee.addEvent(new Subtract());
    before = matee.value;
    cout << "Before: " << before << " After: " << matee.act().value << endl;

    matee.addEvent(new Add());
    matee.addEvent(new Add());
    matee.addEvent(new Add());
    before = matee.value;
    cout << "Before: " << before << " After: " << matee.act().value << endl;

    matee.addEvent(new Multiply());
    before = matee.value;
    cout << "Before: " << before << " After: " << matee.act().value << endl;

    before = matee.value;
    cout << "Before: " << before << " After: " << matee.act().value << endl;

    return 0;
}
于 2013-02-25T20:20:48.350 回答
0

如上所述,您只支持一次可微分的速度函数,这看起来很可怕,除非有很多点。

有两个不同的问题。第一个是内部动画参数的可能变化(这可能对定位引擎来说应该是不透明的),第二个是速度的变化(这不是不透明的)。

我会正交地解决这两个问题。

关注速度,下一个问题是你希望装饰器如何相互组合。它们是否添加、乘法、替换、形成输出速度的上限或下限?

他们可以访问哪些有关当地状态的信息?

假设他们是沿着曲线的位置,并且只有最后一个速度装饰器意味着任何东西,std::function<double(double)>作为速度装饰器类型会做得很好。

virtual这与调用一个或两个函数的效率相同。注入器或装饰器可以捕获任何它想要的内部状态......

于 2013-02-25T18:45:03.563 回答