Skip to content
This repository has been archived by the owner on Jun 17, 2020. It is now read-only.

Commit

Permalink
Initial thoughts on component-entity system
Browse files Browse the repository at this point in the history
  • Loading branch information
harto committed Apr 1, 2013
1 parent 8fcaae4 commit d78b02f
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 13 deletions.
15 changes: 15 additions & 0 deletions common/src/clj/enoki/component_macros.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
(ns enoki.component-macros)

(defmacro defcomponent
"Define a component-creation function, named by `type`, that accepts `params`
and returns a map consisting of the remaining key-value pairs. E.g.
(defcomponent foo [bar baz]
:bar bar
:baz (inc baz))
(foo :quux 2) ; => {:enoki.component/type :foo, :bar :quux, :baz 3}"
[type params & kvs]
`(defn ~type ~(vec params)
(into {:enoki.component/type ~(keyword type)}
(hash-map ~@kvs))))
25 changes: 25 additions & 0 deletions common/src/cljx/enoki/entity.cljx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
;; Functions for initialising and managing entities.
;; Entities are plain mappings of component types (keywords) to components (which
;; are also maps).

(ns enoki.entity)

(let [next-id (atom 0)]
(defn uid
"Reserve and return a unique numeric ID."
[]
(swap! next-id inc)))

(defn new
"Initialise an entity with some collection of components. A unique ID is
assigned and accessible via `:id`. Components are accessible by their
name as a keyword; i.e. use `:foo` to fetch components defined using
`(defcomponent foo ...)`."
[& components]
(into {:id (uid)}
(map (fn [comp] [(:enoki.component/type comp) comp]) components)))

(defn with-component
"Find all entities that include a component of a given type."
[entities component-type]
(filter #(contains? % component-type) entities))
14 changes: 14 additions & 0 deletions example/common/src/cljx/game/component.cljx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
;; Game-specific components

^:clj (ns game.component
(:use [enoki.component-macros :only [defcomponent]]))

^:cljs (ns game.component
(:use-macros [enoki.component-macros :only [defcomponent]]))

(defcomponent position [x y]
:x x
:y y)

(defcomponent sprite [image-id]
:image-id image-id)
41 changes: 28 additions & 13 deletions example/common/src/cljx/game/main.cljx
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,32 @@
(:require [clojure.string :as str]
[enoki.asset :as asset]
[enoki.engine :as enoki]
[enoki.entity :as entity]
[enoki.event :as event]
[enoki.graphics :as gfx]
[enoki.logging]
[enoki.logging-macros :as log])
[enoki.logging-macros :as log]
[game.component :as comp])
(:use [enoki.core :only [now]]))

^:cljs (ns game.main
(:require [clojure.string :as str]
[enoki.asset :as asset]
[enoki.engine :as enoki]
[enoki.entity :as entity]
[enoki.event :as event]
[enoki.graphics :as gfx]
[enoki.logging :as _])
[enoki.logging :as _]
[game.component :as comp])
(:require-macros [enoki.logging-macros :as log])
(:use [enoki.core :only [now]])
(:use-macros [enoki.cljs-macros :only [double]]))

;; ## Update

(defn initial-state []
{:alien {:position {:x 10 :y 60}}})
{:entities [(entity/new (comp/sprite "images/alien.png")
(comp/position 10 60))]})

;; ## Update

(defn movement [pressed-keys]
(let [x-offsets {:left -1 :right 1}
Expand All @@ -39,25 +44,35 @@

;; ## Draw

(defn print-fps [ctx fps]
(defn image [state id]
(get-in state [:assets id]))

(defn print-fps! [ctx fps]
(gfx/draw-text! ctx (format "%03.1ffps" (double fps)) 10 20))

(defn print-pressed-keys [ctx keys]
(defn print-pressed-keys! [ctx keys]
(gfx/draw-text! ctx (format "keys: %s" (str/join ", " keys)) 10 40))

(defn draw-sprite! [ctx state entity]
(let [image-id (get-in entity [:sprite :image-id])
{:keys [x y]} (get entity :position)]
(gfx/draw-image! ctx (image state image-id) x y)))

(defn draw-sprites! [ctx state]
(doseq [e (entity/with-component (:entities state) :sprite)]
(draw-sprite! ctx state e)))

(defn render [state ctx]
(-> ctx
(gfx/clear!)
(print-fps (enoki/fps state))
(print-pressed-keys (:pressed-keys state))
(gfx/draw-image! (get-in state [:assets "images/alien.png"])
(get-in state [:alien :x])
(get-in state [:alien :y]))))
(print-fps! (enoki/fps state))
(print-pressed-keys! (:pressed-keys state))
(draw-sprites! state)))

;; ## Loop

(defn enter-loop [env]
(event/subscribe! :update (fn [state _] (update state)))
;(event/subscribe! :update (fn [state _] (update state)))
(event/subscribe! :render (fn [state _ ctx] (render state ctx)))
(enoki/start (assoc env :state
;; FIXME: stupid hack to get assets into :state
Expand Down

0 comments on commit d78b02f

Please sign in to comment.