gpt4 book ai didi

c# - 设置目标字段值

转载 作者:行者123 更新时间:2023-12-05 04:24:56 25 4
gpt4 key购买 nike

我正在制作一款游戏,我想在其中设置多个字段的目标值。比如我的Camera类有:

public double zoomLevel

目前,如果 zoomLevel是(说)1.0我想逐渐增加到(比如)2.0 ,我有以下其他领域来支持这一点:

private double targetZoomLevel
private double zoomIncrement

然后我有一个 Camera.SetZoom(double target, double increment)设置所需 furure 缩放级别的方法,然后是 Camera.Update()使用增量将当前缩放级别移向目标级别的方法。

这一切都很好,但我真的很想为其他领域(例如相机世界位置、玩家大小、玩家位置等)实现相同的行为。使用我当前的方法,我需要为每个字段添加 2 个额外的“支持”字段。

我很确定我当前的解决方案不是最优的,但不确定如何改进它。我正在考虑实现 Property<T>为一个值封装此行为的类,但不确定如何概括 Update()将当前值移向其目标的方法。

谢谢!

最佳答案

您所描述的内容听起来很像动画。动画是几个框架中的正式概念(想到 CSSWPF)。

动画的目标是将某物从一个值过渡到下一个值。

有多种方法可以实现这种转变。有时您希望 2D 点跟随 Bézier curve作为曲线的 t变量在一段时间内从 0 线性变化到 1。其他时候,您希望通过围绕 color wheel 走很长一段路,使颜色从红色平滑过渡到蓝色。 .

这是一个可以抽象出该概念的接口(interface):

public interface IAnimation<T>
{
T Current { get; }

void Update(double progress); // progress is a number between 0 and 1
}

例如,如果您想要一个 2D 点在 800 个单位宽和 2 个单位高的正弦波上动画:

public sealed class Point2DAnimation : IAnimation<Point2D>
{
public Point2D Current { get; private set; }

public void Update(double progress)
{
Current = new Point2D(progress * 800, Math.Sin(progress * Math.PI * 2));
}
}

还有多种方法可以插入转型。驱动它的一种常见方式是说“我希望这个动画在 X 秒内尽可能平滑地发生”。但有时您可能希望动画从头开始重复几次。或者您可能希望动画先向前运行,然后向后运行,然后再向前运行等等。

我们可以定义一个接口(interface)来抽象出 IAnimation<T> 的不同方式。可以驱动。并且一种实现可能在内部有一个定时器,它的滴答频率足以给人一种平滑的错觉,如progress。从 0 到 1 与每个滴答时刻耗时成比例。

但我想在这里暂停一下,问一个问题。

抽象的消费者需要什么?

如果您的所有代码需要的是对 T 的读取权限和一个名为 Update() 的方法, 然后 Property<T>听起来像你的票:

public sealed class Property<T>
{
readonly Func<T, T> _update;

public Property(T initial, Func<T, T> update)
{
Value = initial;
_update = update;
}

public T Value { get; private set; }

public void Update()
{
Value = _update(Value);
}
}

该类封装了一个可读值并为您提供了一个 Update()方法来调用。不需要 IAnimation<T>界面或任何其他花哨的陷阱。当然,您必须实例化 Property<T> 的实例。用update代表做你想做的事。但是您可以在某处添加一些静态方法,以最常见的方式进行设置。例如:

public static class PropertyHelpers
{
public Property<double> CreateZoomLevelProperty(double initial, double increment, double target)
{
return new Property<double>(initial, old =>
{
var @new = old + increment;
if (increment > 0 && @new > target || increment < 0 && @new < target)
return target;
else
return @new;
});
}
}

另一方面,如果您想将值视为由代码中的其他内容控制的值流,并且您只需要在值到达时获得对值的读取访问权限,那么可能是 IObservable<T> (和 Reactive NuGet 包)就是您所追求的。例如:

public class Camera
{
double _zoomLevel;

public IDisposable UpdateZoomLevel(IObservable<double> zoomLevels)
{
return zoomLevels.Subscribe(zoomLevel => _zoomLevel = zoomLevel);
}
}

当然,其他地方的代码有责任提出一个IObservable<double>。以您想要的方式发布缩放级别。

所以我想我的回答可以总结为:

视情况而定。

免责声明:也许上面的代码都不会编译

关于c# - 设置目标字段值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73392204/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com