这是我能想到的最佳方式。你能否给我这样的提示:这是否是正确的方法,或者是否有更有效的方式。
我的情况是: 每次帧都是Update()'ed(就像在XNA中一样)我想检查是否发生了某些事情。就像该屏幕的计时器已经运行超过2000毫秒一样。但我只想要它一次,而不是每次更新帧。这会导致问题:
if(totalMilliseconds > 2000)
{
this.Fader.FadeIn();
}
所以我想出了我在GameScreen类中实现的这个方法,如下所示:
public bool RunOnce(string Alias, bool IsTrue)
{
if (!this.Bools.ContainsKey(Alias))
this.Bools.Add(Alias, false);
if (IsTrue && !this.Bools[Alias])
{
this.Bools[Alias] = true;
return true;
}
else
return false;
}
这基本上检查传递的if语句boolean是否为true,如果是,则它会触发一次而不是再次触发,除非将Bool [“Alias”]设置回false。我这样用它:
if(this.RunOnce("fadeInStarted", totalMilliseconds > 2000))
{
this.Fader.FadeIn();
}
这将只运行一次,我认为代码很容易阅读。
我发布这个的原因有两个原因。首先是因为我想表明我是如何克服这个问题的,因为它可能对那些遇到同样问题的人有所帮助。其次是看我是否有错过了一种明显的方法,没有为它创建一个手动方法,或者它可以更有效地完成。
答案 0 :(得分:0)
你的方法很有趣,我没有看到它的问题,你基本上创建了一个新的编程结构。
我没有遇到过这种情况,所以在这种情况下我所做的总是从不整洁的方法开始:
bool _hasFadedIn = false;
if(totalMilliseconds > 2000 && !_hasFadedIn)
{
this.Fader.FadeIn();
_hasFadedIn = true;
}
90%的时间我都是这样离开的。如果班级开始变得太大,我只会改变一些事情。那我要做的是:
_faderControl.Update(totalMilliseconds);
将推子控制的逻辑放入一个单独的类中,所以:
class FaderControl
{
bool _hasFadedIn=false;
public void Update(int totalMilliseconds)
{
if (_hasFadedIn)
return;
if (totalMilliseconds <= 2000)
return;
this.Fader.FadeIn();
_hasFadedIn=true;
}
}
可对其进行修改以使其可配置,例如重置,设置“开始”,“结束”,淡出时间或控制淡出。
答案 1 :(得分:0)
以下是我如何解决这个问题。
这些是您的要求:
Update()
。这里的核心概念是“带有关联谓词的动作”,因此创建一个代表该概念的数据结构:
public class ConditionalAction
{
public ConditionalAction(Action action, Func<Boolean> predicate)
{
this.Action = action;
this.Predicate = predicate;
}
public Action Action { get; private set; }
public Func<Boolean> Predicate { get; private set; }
}
现在,您的示例变为
var action = new ConditionalAction(
() => this.Fader.FadeIn(),
() => totalMilliseconds > 2000);
在Update()
中,您需要能够执行这些条件操作的内容:
public void Update(GameTime time)
{
// for each conditional action that hasn't run yet:
// check the action's predicate
// if true:
// execute action
// remove action from list of pending actions
}
因为它们的谓词可能不相关,所以操作不一定按顺序运行。所以这不是一个简单的行动队列。它是一个操作列表,可以从中以任意顺序删除操作。
为了演示这个概念,我将把它作为一个链表来实现,但这可能不是在生产代码中实现它的最好方法。链接列表在托管堆上分配内存,这通常是XNA中要避免的。然而,为此目的提出一个更好的数据结构是最好留一天的练习。
private readonly LinkedList<ConditionalAction> pendingConditionalActions =
new LinkedList<ConditionalAction>();
public void Update(GameTime time)
{
for (var current = pendingConditionalActions.First; current != null; current = current.Next)
{
if (current.Value.Predicate())
{
current.Value.Action();
pendingConditionalActions.Remove(current);
}
}
}
public void RegisterConditionalAction(ConditionalAction action)
{
pendingConditionalActions.AddLast(action);
}
注册的操作将等到其谓词变为真,此时它们将被执行并从待处理操作列表中删除,确保它们只运行一次。