1

我目前正在尝试为某些对象上的一组公共属性设置动画。通常它们是浮点类型或浮点向量(类型在编译时已知)。我希望能够:

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

关键帧应该能够接受每个帧的随机值,包括时间和属性值。

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

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

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

编辑: 可能应该在前面提到这一点,但 WPF 不是一个选项 - 它并非在所有目标平台上都可用,所以我不能依赖它。我知道它强大的数据绑定和动画功能,但我需要自己动手(或者找到一些其他轻量级的替代方案来满足我的需求)。

4

1 回答 1

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;

或者……</p>

if(mine > 0f)…

至于实例化的乏味,我认为这种场景是内部 DSL/fluent 接口的完美候选者。

你可以编造一些富有表现力和简洁的东西,比如:

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;
于 2011-01-03T21:45:13.357 回答