Reputation: 744
I know that it's usually a good idea to keep away from state when programming clojure. However, time seems to me something very stateful.
My goal is to represent time in my game I am writing in clojure. My idea was to run a timer as a seperate process and read its value whenever needed but there doesn't seem to be any natural way of acheiving this in clojure.
How would you implement time in a simple roleplaying game in clojure?
Upvotes: 0
Views: 184
Reputation: 83680
Timer is pretty stateless. Actually timer is a point in time in which it started.
I will use clj-time
here for simplicity.
(require '[clj-time.core :as t]
'[clj-time.coerce :as c])
(defn timer
[]
(let [now-sec #(-> (t/now) c/to-long (/ 1000) int)
start (now-sec)]
#(- (now-sec) start)))
(def my-timer (timer))
;; after a second
(my-timer)
;;=> 1
;; and after 2 seconds more
(my-timer)
;;=> 3
Upvotes: 2
Reputation: 1447
I've adapted the code from this Java answer into my date-dif function:
(defn date-dif [d1 d2]
(let [tu java.util.concurrent.TimeUnit/SECONDS
t1 (. d1 getTime)
t2 (. d2 getTime)]
(. tu convert (- t2 t1) java.util.concurrent.TimeUnit/MILLISECONDS)))
(defn start-timer []
(let [cur-time (new java.util.Date)]
(fn [] (date-dif cur-time (new java.util.Date)))))
start-timer
will create and return a function that, when called, returns the number of seconds since the function was created. To use it, do something like this:
rpg-time.core> (def my-timer (start-timer))
#'rpg-time.core/my-timer
rpg-time.core> (my-timer)
3
rpg-time.core> (my-timer)
5
rpg-time.core> (my-timer)
6
If you want a different unit of time, instead of seconds, replace SECONDS with something more appropriate from here.
There are certainly other options you can consider. This is just the first one I thought of, and it isn't very hard to code or use.
Upvotes: 2