随着时间的推移动画C#属性的方法?

时间:2011-01-03 18:11:48

标签: c# animation properties interpolation keyframe

我目前正试图在某些对象上制作一堆公共属性。通常它们是float类型或float的向量(类型在编译时是已知的)。我希望能够:

  1. 为它们分配静态值(MyObject.Duration = 10f;)或
  2. 通过指定最小值和最大值以及可选的权重(MyObject.Duration = new RandomFloat(5f,20f,2f);)或
  3. 为它们分配随机值
  4. 将此属性“绑定”到另一个对象的属性(想象一个子对象将其某些属性绑定到其父对象,如颜色或大小或某事物)或
  5. 为它们分配关键帧动画的排序,指定具有时间码的可变数量的关键帧以及该特定时间点的属性值以及有关如何在这些帧之间进行插值的信息
  6. 关键帧应该能够接受每个帧的随机值,包括时间和属性的值。

    这种系统的实用方法是什么?目前我正在考虑多态:使用公共Value-property和/或GetValue(float time)-method实现基类或接口,然后创建不同的子类,如实现此基类或接口的StaticValue,RandomValue,BindingValue和AnimatedValue 。但是,似乎并不优雅,甚至简单对象的初始化也变得有点乏味。

    另一个想法是像常规浮点数或向量一样实现这些属性,并创建绑定到这些属性的特殊“修饰符”类型。要检索属性的“真实”值,我首先调用绑定到属性的任何修改器,这将更新实际对象的属性以供我稍后检索。这很可能意味着在某些时候使用反射,这可能对性能非常不利,因为我可能有数千个属性每秒更新几十次。

    对此有何建议?作为一个新手我(希望)错过了一些比我已经玩过的更优雅和/或更实用的解决方案:(

    修改 可能应该早些提到这一点,但WPF不是一个选项 - 它并不适用于所有目标平台,所以我不能依赖它。我知道它强大的数据绑定和动画功能,但我需要自己动手(或者找一些满足我需要的轻量级替代品)。

1 个答案:

答案 0 :(得分:1)

我认为您描述的多态解决方案是执行此操作的最优雅的OO方式。你觉得它有什么不雅之处?

至于使用实际数据类型和修饰符类型,我建议你看一下使用隐式运算符重载。

您可以使用所需的所有行为定义您的类,但提供与“值”类型的转换,因此您可以获取/分配值,就好像它是该类型一样。一个例子将有所帮助:

public class MyFloat
{
    float innerValue;

    // private constructor; instantiate using a float directly
    private MyFloat(float innerValue) { this.innerValue = innerValue; }

    public string Description { get { return "some metadata"; } }

    public int NumberOfFrames { get; set; }

    // conversion from MyFloat to float
    public static implicit operator float(MyFloat mine)
    {
        return mine.innerValue; // you can access private members here
    }

    // conversion from float to MyFloat
    public static implicit operator MyFloat(float val)
    {
        return new MyFloat(val); // use the private constructor
    }
}

在使用中,您可以执行以下操作:

MyFloat mine = 9f; 
mine.NumberOfFrames = 15;

...或

if(mine > 0f)…

至于实例化的乏味,我认为这种情况是内部DSL /流畅界面的完美候选。

你可以表达一些表达和简洁的东西,比如:

var animatedObject = Sprite.with(RandomMotion.animatated_between(0f).and(10f))
    .lasts(4).seconds;
var otherObject = Sprite.with<NoMotion>().starts_at(100, 0);
var yetAnother = Sprite.with(SteadyMotion.at(7f))
    .starts_at(100, 200)
    .weighing(.5f)
    .lasts(15).frames;