|
7 | 7 | :tags [:game :browser]}}} |
8 | 8 | (ns games.beginning-to-build-a-browser-game) |
9 | 9 |
|
10 | | -; Today we are pairing. We are messing around with Clojure. |
| 10 | +; I'm new to Clojure. I asked my new friend Timothy how to make a square appear on the screen: |
11 | 11 |
|
12 | | -; Instead of HTML tags, we're using Clojure data structures to say what we mean. |
13 | | -; With tags, we need to close them. It's nice to not need to close them. |
14 | | -(def thing [:svg {:style {:border "1px solid red"}} |
15 | | - [:rect {:width 50 :height 50 :stroke :blue}]]) |
| 12 | +^{:kindly/hide-code true} |
| 13 | +^:kind/code |
| 14 | +(str "^:kind/hiccup |
| 15 | +[:svg [:rect {:width 50 :height 50}]]") |
16 | 16 |
|
17 | | -; This tells Clay (our renderer) to render the HTML. |
| 17 | +^{:kindly/hide-code true} |
18 | 18 | ^:kind/hiccup |
19 | | -thing |
| 19 | +[:svg {:style {:width 50 :height 50}} |
| 20 | + [:rect {:width 50 :height 50}]] |
20 | 21 |
|
21 | | -^:kind/hiccup |
22 | | -[:div [:button "Click me"] thing] |
| 22 | +; Compared to HTML: |
23 | 23 |
|
24 | | -; Let's create a function that parametrizes thing |
25 | | -(defn create-thing [x y] |
26 | | - ^:kind/hiccup |
27 | | - [:svg {:style {:border "1px solid red"}} |
28 | | - [:rect {:width 50 :height 50 :stroke :blue :x x :y y}]]) |
29 | | -(create-thing 50 50) |
| 24 | +^{:kindly/hide-code true} |
| 25 | +^:kind/code |
| 26 | +(str "<svg><rect width=" 50 " height=" 50 " /></svg>") |
| 27 | + |
| 28 | + |
| 29 | +; It's nice to not have to close tags, but I'm not sure about the colons, nor the dependencies. |
30 | 30 |
|
31 | | -; Let's create the world |
32 | | -(def world (atom {})) |
| 31 | +; Dependencies aside, we are this square. And we want to be able to move. Timothy, how can I move? |
33 | 32 |
|
34 | | -; Let's add something to the world |
35 | | -(swap! world assoc :player {:x 75 :y 75}) |
| 33 | +; We'll separate the position data from the rendering: |
36 | 34 |
|
37 | | -; Wait, did `assoc` work? Yes. |
38 | | -@world |
| 35 | +(def world (atom {:player {:x 75 :y 75}})) |
39 | 36 |
|
40 | | -(defn render-the-world [world] |
| 37 | +(defn render [world] |
41 | 38 | ^:kind/hiccup |
42 | | - [:svg {:style {:border "1px solid red"}} |
| 39 | + [:svg {:style {:border "1px solid black"}} |
43 | 40 | (for [[_entity-id {:keys [x y]}] world] |
44 | | - [:rect {:width 50 :height 50 :stroke :blue :x x :y y}])]) |
| 41 | + [:rect {:width 50 :height 50 :x x :y y}])]) |
45 | 42 |
|
46 | | -(render-the-world @world) |
| 43 | +(render @world) |
47 | 44 |
|
48 | | -; An enemy |
| 45 | +; We'll add an enemy to see how to work with `atom`: |
49 | 46 | (swap! world assoc :enemy {:x 130 :y 75}) |
| 47 | +(render @world) |
50 | 48 |
|
51 | | -; Show the enemy |
52 | | -(render-the-world @world) |
53 | | - |
54 | | -; Let's look different from our enemy |
55 | | -(defn render-the-world [world] |
| 49 | +; Let us be different shapes: |
| 50 | +(defn render [world] |
56 | 51 | ^:kind/hiccup |
57 | 52 | [:svg {:style {:border "1px solid black"}} |
58 | 53 | (for [[entity-id {:keys [x y]}] world] |
59 | 54 | (if (= entity-id :player) |
60 | | - [:rect {:width 50 :height 50 :fill "#62b133" :x x :y y}] |
61 | | - [:circle {:r 25 :fill "#5880d9" :cx x :cy y}]))]) |
62 | | -(render-the-world @world) |
| 55 | + [:rect {:width 50 :height 50 :fill "#62b133" :x x :y y :id "player"}] |
| 56 | + [:circle {:r 25 :fill "#5880d9" :cx x :cy y :id "enemy"}]))]) |
| 57 | +(render @world) |
63 | 58 |
|
64 | | -; It was nice to work with Clojure syntax as opposed to JavaScript. |
65 | | -; The only boilerplate I/we felt was the Clojure colons: ":" |
66 | | -; The code is nice to read. I'm just looking at what I meant to say. |
67 | | -; The things I care about are listed. There they are. |
| 59 | +; Now would be a perfect time to use [Reagent](https://reagent-project.github.io/) to connect the user's keyboard to our world atom. However, I couldn't get it working with [Clay](https://scicloj.github.io/clay) (what we're using to render this page). The dependencies have won the first battle. |
68 | 60 |
|
| 61 | +; Moving on, we'll resort to a `script` element. Clay lets us use JavaScript, but I couldn't get it to work with curly braces. Suffering a one-liner, we can now move, via WASD on our keyboard. |
| 62 | + |
| 63 | +^:kind/hiccup |
| 64 | +[:script #"document.addEventListener('keydown', e => (['w', 'W'].includes(e.key) && player.setAttribute('y', parseInt(player.getAttribute('y')) - 10) || ['a', 'A'].includes(e.key) && player.setAttribute('x', parseInt(player.getAttribute('x')) - 10) || ['s', 'S'].includes(e.key) && player.setAttribute('y', parseInt(player.getAttribute('y')) + 10) || ['d', 'D'].includes(e.key) && player.setAttribute('x', parseInt(player.getAttribute('x')) + 10)))"] |
0 commit comments