2013-05-05 12 views
5

我想知道是否有任何普遍的计时器解决方案。clojure中的计时器?

我想通过交易来写一个简单的游戏引擎,将处理用户输入上打勾每20ms(或之后 20毫秒(或任何其他时期进行一次一些动作)),基本上更新“全球性”的状态,同时也我打算使用futures,所以这个解决方案应该能够处理并发警告。

你能给我一个建议吗?

回答

11

你实际上已经得到了两个不同的问题在这里。

首先是定时器问题。你有很多的选择,在这里:

  • 启动一个线程,动作之间睡觉,像(future (loop [] (do-something) (Thread/sleep 20) (when (game-still-running) (recur))))
  • 使用Java TimerTask - 很容易从Clojure的
  • 使用像我的小工具Task包括库调用对于重复任务
  • 一个DSL
  • 使用从定时器功能无论游戏引擎使用的是 - 其中大部分为建立一个游戏循环
一些工具

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

第二个问题是操控游戏状态。这实际上是棘手的问题,你就需要设计它围绕特定类型的你正在游戏的,所以我就提出建议的几点:

  • 如果您游戏状态是不可改变的,那么你会获得很多优势:当游戏更新计算下一个游戏状态时,渲染代码可以独立绘制当前游戏状态。不变性具有一定的性能成本,但如果可以使其发挥作用,并发优势是巨大的。我的两个小的Clojure的游戏(铁甲和炼金术)使用这种方法
  • 你应该尝试并存储在一个单一顶级VAR你的游戏状态。我发现这比在不同的变量中分割游戏状态的不同部分更好。这也意味着你并不需要基于ref的交易:一个原子或代理通常会这样做。
  • 你可能想实现一个队列需要得到由游戏状态更新功能顺序处理事件的。如果您有多个并发事件源(例如,玩家操作,计时器滴答声,网络事件等),这一点尤其重要。)
+0

谢谢,我同意游戏很难,我的计划体系结构使用clojure功能的路径只开始:) – asdf 2013-05-05 13:56:11

4

该解决方案假设你在JVM上写的Clojure。 像这样的东西可以工作:

(import '(java.util TimerTask Timer)) 

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

也相关和有趣http://pragprog.com/magazines/2011-07/create-unix-services-with-clojure – 2013-05-05 13:38:35

+0

谢谢,最后我得到了我的'滴答'消息出现:) – asdf 2013-05-05 13:46:51

+4

@dig,JVM考虑使用'ScheduledExecutorService':http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html。计时器有几个缺点,执行者服务没有。 – 2013-05-05 14:08:58

4

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

  • 它做的非常好,当涉及到复杂的任务可分为活动的通信使用渠道
  • 避免结合活性线程

这里是草图

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

使用'(<!(timeout 2000))'代替'Thread/sleep'并引用'<!'和' timeout' – 2016-12-07 13:13:13