在clojure的计时器?

时间:2013-05-05 13:32:53

标签: timer clojure

我想知道是否有广泛的计时器解决方案。

我想编写一个简单的游戏引擎,它会每20分钟处理一次用户输入(或者在 20ms(或任何其他时间段)后执行一些操作)并基本上通过以下方式更新“全局”状态事务,我也计划使用futures,所以这个解决方案应该能够处理并发警告。

你能给我一个建议吗?

3 个答案:

答案 0 :(得分:12)

这里你确实遇到了两个不同的问题。

首先是计时器的问题。你有很多选择:

  • 启动一个在操作之间休眠的线程,例如(future (loop [] (do-something) (Thread/sleep 20) (when (game-still-running) (recur))))
  • 使用Java TimerTask - 从Clojure轻松调用
  • 使用像我的小实用程序Task这样的库,其中包含用于重复任务的DSL
  • 使用您正在使用的任何游戏引擎的计时器功能 - 其中大部分都提供了一些设置游戏循环的工具

我可能只是使用简单的线程选项 - 如果需要,它可以很容易地设置并在以后轻松破解更多功能。

第二个问题是处理游戏状态。这实际上是一个棘手的问题,你需要围绕你正在制作的特定类型的游戏进行设计,所以我只想提出几点建议:

  • 如果您的游戏状态是不可变的,那么您将获得很多优势:您的渲染代码可以在游戏更新计算下一个游戏状态时独立绘制当前游戏状态。不可变性有一些性能成本,但如果你可以使其工作,并发性优势是巨大的。我的迷你Clojure游戏(Ironclad和Alchemy)都使用这种方法
  • 您应该尝试将游戏状态存储在单个顶级变量中。我发现这比在不同的vars上分割游戏状态的不同部分更好。这也意味着你并不真正需要基于ref的事务:原子或代理通常会做到这一点。
  • 您可能希望实现需要由游戏状态更新功能按顺序处理的事件队列。如果您有多个并发事件源(例如,玩家行动,计时器滴答,网络事件等),这一点尤其重要。

答案 1 :(得分:7)

现在我认为核心/异步是一个不错的选择,因为

  • 当涉及到可以分成使用渠道进行通信的活动的复杂任务时,它可以很好地扩展
  • 避免对线程的绑定活动

这是草图

(require '[clojure.core.async :refer [go-loop]])
(go-loop []
  (do
    (do-something ...)
    (Thread/sleep 1000)
    (recur))))

答案 2 :(得分:5)

此解决方案假设您在JVM上编写Clojure。 这样的事情可以奏效:

(import '(java.util TimerTask Timer))

(let [task (proxy [TimerTask] []
             (run [] (println "Here we go!")))]
  (. (new Timer) (schedule task (long 20))))