Oskar <[email protected]> writes:
> I have not heard much about records and protocols. What is a typical
> use case in idiomatic Clojure code for them? Is it a good idea, for
> example, to make a "Character" protocol and "Player" and "Monster"
> records or something in a game. It feels a bit too much like OOP for
> me to be comfortable with it, but I can't immediately see why that
> would be bad. I just don't know how they are supposed to be used.
The primary purpose of protocols is efficient, extensible polymorphism:
handling different data types using a uniform interface.
Rather than a composite idea like "Character" it is preferable to use
many fine-grained protocols that each cover a single indivisible
concept. Depending on the mechanics in your game you might have
protocols like Damagable, Listener, Throwable, Describable, Capturable,
Clickable, Edible, Castable and Container.
(defprotocol Damagable
(alive? [damagable])
(damage [damagable weapon]))
(defprotocol Describable
(describe [describable]))
(defrecord Monster [strength color]
Damagable
(alive? [m] (pos? health)
(damage [m weapon] (update-in m [:health] - (weapon :power))))
Describable
(describe [m] (str (if (> health 90) "a healthy " "an injured ")
(if (> strength 50) "powerful " "weak ")
color " monster")))
(defrecord Tree [age species]
Describable
(describe [t] (str (when (> age 100) "an ancient " "a ")
species " tree")))
One of the lovely things about protocols is that they are very
extensible. Suppose you want to write some graphics code for drawing
different game entities. You can define a rendering protocol and extend
it to your entities all in a different file. You don't have to clutter
up your game logic files with the ugly drawing code.
;; gfx.clj
(ns game.gfx
(:require [game.enemies :as enemies]
[game.scenary :as scenary]))
(defprotocol Renderable
(paint [x canvas])
(pixel-width [x]))
(extend-protocol Renderable
scenary/Rock
(paint [tree canvas] (blit canvas "rock.png"))
(pixel-width [tree] 30)
scenary/Tree
(paint [tree canvas] (blit canvas "tree.png"))
(pixel-width [tree] 150)
enemies/Monster
(paint [m canvas] (blit canvas (get icons (:activity m))))
(pixel-width [m] 70))
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en