2013-05-05 50 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