C# 类组织/结构 - 概括执行循环线性插值的类

标签 c# oop parameters xna

我正在开发 C# XNA 游戏,并有以下代码根据线性插值的结果更新 Sprite 的 alpha 级别:

class AlphaProcess : GameProcess {

    Sprite sprite;
    public Sprite Sprite {
        get { return sprite; }
        set { sprite = value; }
    }

    float start;
    public float Start {
        get { return start; }
        set { start = value;}
    }

 ...<snip>...

    public override void Update(float elapsed) {
        if (FirstUpdate) {
            Start = sprite.Alpha;
            FirstUpdate = false;
        }

        Time += elapsed;
        if (Time >= Duration)
            Finished = true;

        sprite.Alpha = MathHelper.Lerp(start,end,Time/Duration);
    }
}

'Start' (float), 'FirstUpdate' (bool), 'Time' (float), 'Duration' (float) 都是类 AlphaProcess 的字段。 “Sprite”是一个包含比例、位置、方向、旋转等细节的类。

“更新”方法每秒调用 60 次,计算指定时间段内 Sprite 的新 alpha 值。完成后,GameProcess 将从队列中移除。

这段代码工作正常,但它非常具体。我拥有的 Sprite 类包含许多属性,可以方便地在固定时间段内进行 lerp(旋转、位置(用于缓入和缓出))。其中许多变量也是 float 。创建多个“GameProcess”扩展类来做几乎相同的事情,只是在不同的变量上,这似乎很愚蠢。但是,我想不出如何最好地重构它,以便我可以只拥有一个指向正在修改的浮点值的指针,而不是特定的 Sprite ,它是 alpha/旋转/缩放/任何值。

我已经完成了有关 SO 的 C# 引用/值/参数传递问题,并且知道在 C# 中您不能将引用存储为字段。调用 Update 的“GameProcessQueue”对正在更新的“GameProcess”的内部结构一无所知。 有没有一种更聪明的方法可以做到这一点,以便我可以概括/抽象类以更新另一个类的字段(就像这里,使用“Sprite”的“Alpha”字段)?

最佳答案

您的主要问题是您的 AlphaProcess 类的内聚性较低。它具有三个主要作用,Tweening、Lerping 和获取/设置 Sprite Alpha 值。为了改进您的设计,您需要将它们拆分为单独的解耦类。

目标:将您的 AlphaProcess 变成 TweenProcess。

不是传递给它一个 Sprite ,而是传递给它一个接口(interface),通过它它可以获取和设置它希望操作的 float 。并且不是直接调用 Lerp,而是将它传递给一个接口(interface)或委托(delegate)给一个 Tween 函数。 (我使用接口(interface)而不是委托(delegate),因为我发现委托(delegate)经常会产生垃圾,这会导致您的游戏卡顿。)

补间类是:

interface IFloatPropertySource
{
    float FloatProperty { get; set; }
}

interface ITweenFunction
{
    float Tween(float start, float end, float t);
}

class TweenProcess : GameProcess 
{
    float start;
    IFloatPropertySource floatSource;
    ITweenFunction tweenFunction;

    public TweenProcess(IFloatPropertySource floatSource, ITweenFunction tweenFunction)
    {
        this.floatSource = floatSource;
        this.tweenFunction = tweenFunction;
    }

    public override void Update(float elapsed) {
        if (FirstUpdate) {
            start = floatSource.FloatProperty;
            FirstUpdate = false;
        }

        Time += elapsed;
        if (Time >= Duration)
            Finished = true;

        floatSource.FloatProperty = tweenFunction.Tween(start, end, Time / Duration);
    }
}

获取/设置 alpha 的类是:

class SpriteAlphaSource : IFloatPropertySource
{
    Sprite sprite;

    public SpriteAlphaSource(Sprite sprite)
    {
        this.sprite = sprite;
    }

    public float FloatProperty
    {
        get
        {
            return sprite.Alpha;
        }
        set
        {
            sprite.Alpha = value;
        }
    }
}

我知道你有点想避免上这门课。但是围绕它的所有方法,比如通过反射,都非常昂贵。在具有比 sprite 更多的可呈现对象的项目中,您可能希望将其与 sprite 分离并使其在 IRenderable 等基础接口(interface)上运行。

lerping 机制是:

class Lerp : ITweenFunction
{
    public float Tween(float start, float end, float t)
    {
        return MathHelper.Lerp(start, end, t);
    }
}

关于C# 类组织/结构 - 概括执行循环线性插值的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10091098/

相关文章:

ios - 我什么时候使用自有属性(property)?

javascript - jQuery 使用对象的方法作为事件处理程序

javascript - 从 Windows 服务访问 Web 应用程序中的 SignalR Hub

c# - 字符串比较问题

c# - 如何在 Controller 中访问 IApplicationBuilder?

c - 数组 b[] 的值如何用另一个函数的另一个数组 a[] 值填充?

asp.net-mvc - 使用 RedirectToAction 传递模型和参数

c# - 在excel中扩展列的代码

c++ - 这个构造函数是可以接受的做法吗?

parameters - Struts2从Request GET类型获取参数