├── resources └── public │ ├── images │ ├── chain.png │ ├── clouds.jpg │ ├── diamond.png │ ├── metalslug_mummy37x45.png │ ├── tmw_desert_spacing.png │ └── metalslug_monster39x40.png │ ├── js │ ├── ui.js │ └── highlight.js │ ├── css │ ├── zenburn.css │ └── style.css │ ├── index.html │ └── tilemaps │ └── desert.json ├── src └── phzr_demo │ ├── macros.clj │ ├── animation_demo.cljs │ ├── core.cljs │ ├── physics_chain_demo.cljs │ └── paint_tiles_demo.cljs ├── .gitignore ├── LICENSE ├── README.md └── project.clj /resources/public/images/chain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dparis/phzr-demo/HEAD/resources/public/images/chain.png -------------------------------------------------------------------------------- /resources/public/images/clouds.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dparis/phzr-demo/HEAD/resources/public/images/clouds.jpg -------------------------------------------------------------------------------- /resources/public/images/diamond.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dparis/phzr-demo/HEAD/resources/public/images/diamond.png -------------------------------------------------------------------------------- /resources/public/images/metalslug_mummy37x45.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dparis/phzr-demo/HEAD/resources/public/images/metalslug_mummy37x45.png -------------------------------------------------------------------------------- /resources/public/images/tmw_desert_spacing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dparis/phzr-demo/HEAD/resources/public/images/tmw_desert_spacing.png -------------------------------------------------------------------------------- /resources/public/images/metalslug_monster39x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dparis/phzr-demo/HEAD/resources/public/images/metalslug_monster39x40.png -------------------------------------------------------------------------------- /src/phzr_demo/macros.clj: -------------------------------------------------------------------------------- 1 | (ns phzr-demo.macros 2 | (:refer-clojure :exclude [slurp])) 3 | 4 | (defmacro slurp [file] 5 | (clojure.core/slurp file)) 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /resources/public/js/compiled/** 2 | figwheel_server.log 3 | pom.xml 4 | *jar 5 | /lib/ 6 | /classes/ 7 | /out/ 8 | /target/ 9 | .lein-deps-sum 10 | .lein-repl-history 11 | .lein-plugins/ 12 | .repl 13 | .nrepl-port 14 | -------------------------------------------------------------------------------- /resources/public/js/ui.js: -------------------------------------------------------------------------------- 1 | (function (window, document) { 2 | 3 | var layout = document.getElementById('layout'), 4 | menu = document.getElementById('menu'), 5 | menuLink = document.getElementById('menuLink'); 6 | 7 | function toggleClass(element, className) { 8 | var classes = element.className.split(/\s+/), 9 | length = classes.length, 10 | i = 0; 11 | 12 | for(; i < length; i++) { 13 | if (classes[i] === className) { 14 | classes.splice(i, 1); 15 | break; 16 | } 17 | } 18 | // The className is not found 19 | if (length === classes.length) { 20 | classes.push(className); 21 | } 22 | 23 | element.className = classes.join(' '); 24 | } 25 | 26 | menuLink.onclick = function (e) { 27 | var active = 'active'; 28 | 29 | e.preventDefault(); 30 | toggleClass(layout, active); 31 | toggleClass(menu, active); 32 | toggleClass(menuLink, active); 33 | }; 34 | 35 | }(this, this.document)); 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Dylan Paris 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # phzr-demo 2 | 3 | Demo page showing examples of phzr usage taken from 4 | [phaser.io](http://phaser.io) examples. 5 | 6 | 7 | ## What is phzr? 8 | 9 | The [phzr library](https://github.com/dparis/phzr) is a ClojureScript wrapper 10 | around the [Phaser](http://phaser.io) HTML5 game framework. 11 | 12 | 13 | ## Setup 14 | 15 | To get an interactive development environment run: 16 | 17 | lein figwheel 18 | 19 | and open your browser at [localhost:3449](http://localhost:3449/). 20 | This will auto compile and send all changes to the browser without the 21 | need to reload. After the compilation process is complete, you will 22 | get a Browser Connected REPL. An easy way to try it is: 23 | 24 | (js/alert "Am I connected?") 25 | 26 | and you should see an alert in the browser window. 27 | 28 | To clean all compiled files: 29 | 30 | lein clean 31 | 32 | To create a production build run: 33 | 34 | lein cljsbuild once min 35 | 36 | And open your browser in `resources/public/index.html`. You will not 37 | get live reloading, nor a REPL. 38 | 39 | 40 | ## License 41 | 42 | Copyright © 2015 Dylan Paris 43 | 44 | Distributed under the MIT license. 45 | -------------------------------------------------------------------------------- /src/phzr_demo/animation_demo.cljs: -------------------------------------------------------------------------------- 1 | (ns phzr-demo.animation-demo 2 | (:require [phzr.core :as p :refer [pset!]] 3 | [phzr.animation-manager :as pam] 4 | [phzr.game :as pg] 5 | [phzr.game-object-factory :as pgof] 6 | [phzr.loader :as pl] 7 | [phzr.point :as ppo] 8 | [phzr.signal :as psg] 9 | [phzr.sprite :as ps])) 10 | 11 | (defn ^:private preload 12 | [game] 13 | (let [loader (:load game)] 14 | (doto loader 15 | (pl/spritesheet "mummy" "images/metalslug_mummy37x45.png" 37 45 18) 16 | (pl/spritesheet "monster" "images/metalslug_monster39x40.png" 39 40)))) 17 | 18 | (defn ^:private change-sprite 19 | [pointer event sprite] 20 | (if (= "monster" (:key sprite)) 21 | (ps/load-texture sprite "mummy" 0 false) 22 | (ps/load-texture sprite "monster" 0 false))) 23 | 24 | (defn ^:private create 25 | [game] 26 | (let [gof (:add game) 27 | sprite (pgof/sprite gof 300 200 "monster")] 28 | (pam/add (:animations sprite) "walk" (range 0 16)) 29 | (pam/play (:animations sprite) "walk" 20 true) 30 | (ppo/set (:scale sprite) 6) 31 | (pset! sprite :smoothed false) 32 | 33 | (psg/add (get-in game [:input :on-down]) 34 | change-sprite nil 0 35 | sprite))) 36 | 37 | (defn start-demo 38 | [id] 39 | (pg/->Game 800 600 (p/phaser-constants :auto) id 40 | {"preload" preload 41 | "create" create})) 42 | -------------------------------------------------------------------------------- /src/phzr_demo/core.cljs: -------------------------------------------------------------------------------- 1 | (ns ^:figwheel-always phzr-demo.core 2 | (:require [dommy.core :as d] 3 | [phzr.game :as pg] 4 | [phzr-demo.animation-demo :as pad] 5 | [phzr-demo.paint-tiles-demo :as ptd] 6 | [phzr-demo.physics-chain-demo :as pcd]) 7 | (:require-macros [dommy.core :as d] 8 | [phzr-demo.macros :refer [slurp]])) 9 | 10 | 11 | (enable-console-print!) 12 | 13 | (defonce demo (atom nil)) 14 | 15 | (defn ^:private init-code-display! 16 | [] 17 | (.initHighlightingOnLoad js/hljs)) 18 | 19 | (def ^:private demo-div-id 20 | "phzr-demo") 21 | 22 | (defn ^:private reset-code-display! 23 | [code] 24 | (let [code-node (d/sel1 :#code-display)] 25 | (d/set-text! code-node code) 26 | (.highlightBlock js/hljs code-node))) 27 | 28 | (def ^:private animation-code 29 | (slurp "src/phzr_demo/animation_demo.cljs")) 30 | 31 | (defn ^:private start-animation-demo! 32 | [] 33 | (println "Starting animation demo") 34 | (when-let [cur-demo @demo] 35 | (pg/destroy cur-demo)) 36 | (reset! demo (pad/start-demo demo-div-id)) 37 | (reset-code-display! animation-code)) 38 | 39 | (def ^:private paint-tiles-code 40 | (slurp "src/phzr_demo/paint_tiles_demo.cljs")) 41 | 42 | (defn ^:private start-paint-tiles-demo! 43 | [] 44 | (println "Starting paint tiles demo") 45 | (when-let [cur-demo @demo] 46 | (pg/destroy cur-demo)) 47 | (reset! demo (ptd/start-demo demo-div-id)) 48 | (reset-code-display! paint-tiles-code)) 49 | 50 | (def ^:private physics-chain-code 51 | (slurp "src/phzr_demo/physics_chain_demo.cljs")) 52 | 53 | (defn ^:private start-physics-chain-demo! 54 | [] 55 | (println "Starting physics chain demo") 56 | (when-let [cur-demo @demo] 57 | (pg/destroy cur-demo)) 58 | (reset! demo (pcd/start-demo demo-div-id)) 59 | (reset-code-display! physics-chain-code)) 60 | 61 | (defn ^:private init-buttons! 62 | [] 63 | (d/listen! (d/sel1 :#animation-btn) :click start-animation-demo!) 64 | (d/listen! (d/sel1 :#paint-tiles-btn) :click start-paint-tiles-demo!) 65 | (d/listen! (d/sel1 :#physics-chain-btn) :click start-physics-chain-demo!)) 66 | 67 | (defn ^:private init-page! 68 | [] 69 | (println "Setting up UI handlers") 70 | (init-buttons!)) 71 | 72 | (init-page!) 73 | 74 | (defn on-js-reload 75 | []) 76 | -------------------------------------------------------------------------------- /resources/public/css/zenburn.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Zenburn style from voldmar.ru (c) Vladimir Epifanov 4 | based on dark.css by Ivan Sagalaev 5 | 6 | */ 7 | 8 | .hljs { 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | background: #3f3f3f; 13 | color: #dcdcdc; 14 | -webkit-text-size-adjust: none; 15 | } 16 | 17 | .hljs-keyword, 18 | .hljs-tag, 19 | .css .hljs-class, 20 | .css .hljs-id, 21 | .lisp .hljs-title, 22 | .nginx .hljs-title, 23 | .hljs-request, 24 | .hljs-status, 25 | .clojure .hljs-attribute { 26 | color: #e3ceab; 27 | } 28 | 29 | .django .hljs-template_tag, 30 | .django .hljs-variable, 31 | .django .hljs-filter .hljs-argument { 32 | color: #dcdcdc; 33 | } 34 | 35 | .hljs-number, 36 | .hljs-date { 37 | color: #8cd0d3; 38 | } 39 | 40 | .dos .hljs-envvar, 41 | .dos .hljs-stream, 42 | .hljs-variable, 43 | .apache .hljs-sqbracket, 44 | .hljs-name { 45 | color: #efdcbc; 46 | } 47 | 48 | .dos .hljs-flow, 49 | .diff .hljs-change, 50 | .python .exception, 51 | .python .hljs-built_in, 52 | .hljs-literal, 53 | .tex .hljs-special { 54 | color: #efefaf; 55 | } 56 | 57 | .diff .hljs-chunk, 58 | .hljs-subst { 59 | color: #8f8f8f; 60 | } 61 | 62 | .dos .hljs-keyword, 63 | .hljs-decorator, 64 | .hljs-title, 65 | .hljs-type, 66 | .diff .hljs-header, 67 | .ruby .hljs-class .hljs-parent, 68 | .apache .hljs-tag, 69 | .nginx .hljs-built_in, 70 | .tex .hljs-command, 71 | .hljs-prompt { 72 | color: #efef8f; 73 | } 74 | 75 | .dos .hljs-winutils, 76 | .ruby .hljs-symbol, 77 | .ruby .hljs-symbol .hljs-string, 78 | .ruby .hljs-string { 79 | color: #dca3a3; 80 | } 81 | 82 | .diff .hljs-deletion, 83 | .hljs-string, 84 | .hljs-tag .hljs-value, 85 | .hljs-preprocessor, 86 | .hljs-pragma, 87 | .hljs-built_in, 88 | .smalltalk .hljs-class, 89 | .smalltalk .hljs-localvars, 90 | .smalltalk .hljs-array, 91 | .css .hljs-rule .hljs-value, 92 | .hljs-attr_selector, 93 | .hljs-pseudo, 94 | .apache .hljs-cbracket, 95 | .tex .hljs-formula, 96 | .coffeescript .hljs-attribute { 97 | color: #cc9393; 98 | } 99 | 100 | .hljs-shebang, 101 | .diff .hljs-addition, 102 | .hljs-comment, 103 | .hljs-annotation, 104 | .hljs-pi, 105 | .hljs-doctype { 106 | color: #7f9f7f; 107 | } 108 | 109 | .coffeescript .javascript, 110 | .javascript .xml, 111 | .tex .hljs-formula, 112 | .xml .javascript, 113 | .xml .vbscript, 114 | .xml .css, 115 | .xml .hljs-cdata { 116 | opacity: 0.5; 117 | } 118 | 119 | -------------------------------------------------------------------------------- /resources/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 31 |
32 |
33 |

PHZR DEMO

34 |

Click on the demos to the left to see phzr in action

35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | 51 | 53 | 55 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/phzr_demo/physics_chain_demo.cljs: -------------------------------------------------------------------------------- 1 | (ns phzr-demo.physics-chain-demo 2 | (:require [phzr.core :as p :refer [pset!]] 3 | [phzr.game :as pg] 4 | [phzr.game-object-factory :as pgof] 5 | [phzr.loader :as pl] 6 | [phzr.physics :as pp] 7 | [phzr.physics.p2 :as pp2] 8 | [phzr.physics.p2.body :as pp2b] 9 | [phzr.sprite :as ps])) 10 | 11 | (defn ^:private preload 12 | [game] 13 | (let [loader (:load game)] 14 | (doto loader 15 | (pl/image "clouds" "images/clouds.jpg") 16 | (pl/spritesheet "chain" "images/chain.png" 16 26)))) 17 | 18 | (defn ^:private add-link-sprite 19 | [game x y width height frame] 20 | (let [gof (:add game) 21 | rect (pgof/sprite gof x y "chain" frame) 22 | p2 (get-in game [:physics :p2])] 23 | (pp2/enable p2 rect false) 24 | (pp2b/set-rectangle (:body rect) width height) 25 | rect)) 26 | 27 | (defn ^:private create-rope 28 | [game length x-anchor y-anchor] 29 | (let [height 20 30 | width 16 31 | max-force 20000 32 | p2 (get-in game [:physics :p2])] 33 | (loop [n 0 34 | prev-link nil] 35 | (when (< n length) 36 | (let [x x-anchor 37 | y (+ y-anchor (* n height)) 38 | frame (mod n 2) 39 | cur-link (add-link-sprite game x y width height frame)] 40 | ;; Bring previous link to the top of the z-order 41 | (when prev-link 42 | (ps/bring-to-top prev-link) 43 | (pp2/create-revolute-constraint p2 44 | cur-link [0 -10] 45 | prev-link [0 10] 46 | max-force)) 47 | 48 | ;; Anchor the first link, set up the rest appropriately 49 | (if (= n 0) 50 | (pset! (:body cur-link) :static true) 51 | (do 52 | (pset! (get-in cur-link [:body :velocity]) :x 400) 53 | (pset! (:body cur-link) :mass (/ length n)))) 54 | 55 | (recur (inc n) cur-link)))))) 56 | 57 | (defn ^:private create 58 | [game] 59 | (let [gof (:add game) 60 | phys (:physics game)] 61 | (pgof/tile-sprite gof 0 0 800 600 "clouds") 62 | (pp/start-system phys (pp/const :p2-js)) 63 | (pset! (get-in phys [:p2 :gravity]) :y 1200) 64 | (create-rope game 40 400 64))) 65 | 66 | (defn start-demo 67 | [id] 68 | (pg/->Game 800 600 (p/phaser-constants :auto) id 69 | {"preload" preload 70 | "create" create})) 71 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject phzr-demo "1.0.0" 2 | :description "Demo page showing examples of phzr usage" 3 | :url "https://github.com/dparis/phzr-demo" 4 | :license {:name "MIT License" 5 | :url "http://opensource.org/licenses/MIT"} 6 | 7 | :dependencies [[org.clojure/clojure "1.7.0"] 8 | [org.clojure/clojurescript "1.7.48"] 9 | [org.clojure/core.async "0.1.346.0-17112a-alpha"] 10 | [prismatic/dommy "1.1.0"] 11 | [phzr "0.1.0-SNAPSHOT"]] 12 | 13 | :plugins [[lein-cljsbuild "1.0.5"] 14 | [lein-figwheel "0.3.5"]] 15 | 16 | :source-paths ["src"] 17 | 18 | :clean-targets ^{:protect false} ["resources/public/js/compiled" "target"] 19 | 20 | :cljsbuild { 21 | :builds [{:id "dev" 22 | :source-paths ["src"] 23 | 24 | :figwheel { :on-jsload "phzr-demo.core/on-js-reload" } 25 | 26 | :compiler {:main phzr-demo.core 27 | :asset-path "js/compiled/out" 28 | :output-to "resources/public/js/compiled/phzr_demo.js" 29 | :output-dir "resources/public/js/compiled/out" 30 | :source-map-timestamp true }} 31 | {:id "min" 32 | :source-paths ["src"] 33 | :compiler {:output-to "resources/public/js/compiled/phzr_demo.js" 34 | :main phzr-demo.core 35 | :optimizations :advanced 36 | :pretty-print false}}]} 37 | 38 | :figwheel { 39 | ;; :http-server-root "public" ;; default and assumes "resources" 40 | ;; :server-port 3449 ;; default 41 | ;; :server-ip "127.0.0.1" 42 | 43 | :css-dirs ["resources/public/css"] ;; watch and update CSS 44 | 45 | ;; Start an nREPL server into the running figwheel process 46 | ;; :nrepl-port 7888 47 | 48 | ;; Server Ring Handler (optional) 49 | ;; if you want to embed a ring handler into the figwheel http-kit 50 | ;; server, this is for simple ring servers, if this 51 | ;; doesn't work for you just run your own server :) 52 | ;; :ring-handler hello_world.server/handler 53 | 54 | ;; To be able to open files in your editor from the heads up display 55 | ;; you will need to put a script on your path. 56 | ;; that script will have to take a file path and a line number 57 | ;; ie. in ~/bin/myfile-opener 58 | ;; #! /bin/sh 59 | ;; emacsclient -n +$2 $1 60 | ;; 61 | ;; :open-file-command "myfile-opener" 62 | 63 | ;; if you want to disable the REPL 64 | ;; :repl false 65 | 66 | ;; to configure a different figwheel logfile path 67 | ;; :server-logfile "tmp/logs/figwheel-logfile.log" 68 | }) 69 | -------------------------------------------------------------------------------- /src/phzr_demo/paint_tiles_demo.cljs: -------------------------------------------------------------------------------- 1 | (ns phzr-demo.paint-tiles-demo 2 | (:require [phzr.core :as p :refer [pset!]] 3 | [phzr.game :as pg] 4 | [phzr.game-object-factory :as pgof] 5 | [phzr.graphics :as pgr] 6 | [phzr.keyboard :as pk] 7 | [phzr.loader :as pl] 8 | [phzr.tilemap :as pt] 9 | [phzr.tilemap-layer :as ptl] 10 | [phzr.utils.debug :as pud])) 11 | 12 | 13 | (enable-console-print!) 14 | 15 | (defn ^:private preload 16 | [game] 17 | (let [loader (:load game)] 18 | (doto loader 19 | (pl/tilemap "desert" "tilemaps/desert.json" nil (pt/const :tiled-json)) 20 | (pl/image "tiles" "images/tmw_desert_spacing.png")))) 21 | 22 | (defn ^:private init-tilemap! 23 | [gof tmap] 24 | (reset! tmap (pgof/tilemap gof "desert")) 25 | (pt/add-tileset-image @tmap "Desert" "tiles")) 26 | 27 | (defn ^:private init-current-tile! 28 | [current-tile tmap] 29 | (reset! current-tile (pt/get-tile @tmap 2 3))) 30 | 31 | (defn ^:private init-layer! 32 | [tmap layer] 33 | (reset! layer (pt/create-layer @tmap "Ground")) 34 | (ptl/resize-world @layer)) 35 | 36 | (defn ^:private init-marker! 37 | [gof marker] 38 | (let [initialized-marker (reset! marker (pgof/graphics gof))] 39 | (doto initialized-marker 40 | (pgr/line-style 2 0x000000 1) 41 | (pgr/draw-rect 0 0 32 32)))) 42 | 43 | (defn ^:private init-cursors! 44 | [cursors game] 45 | (reset! cursors (pk/create-cursor-keys (get-in game [:input :keyboard])))) 46 | 47 | (defn ^:private build-create-fn 48 | [current-tile cursors layer marker tmap] 49 | (fn [game] 50 | (let [gof (:add game)] 51 | (init-tilemap! gof tmap) 52 | (init-current-tile! current-tile tmap) 53 | (init-layer! tmap layer) 54 | (init-marker! gof marker) 55 | (init-cursors! cursors game)))) 56 | 57 | (defn ^:private update-layer! 58 | [game layer marker] 59 | (let [world-x (get-in game [:input :active-pointer :world-x]) 60 | world-y (get-in game [:input :active-pointer :world-y]) 61 | tile-x (ptl/get-tile-x @layer world-x) 62 | tile-y (ptl/get-tile-y @layer world-y)] 63 | (pset! @marker :x (* tile-x 32)) 64 | (pset! @marker :y (* tile-y 32)))) 65 | 66 | (defn ^:private update-current-tile! 67 | [current-tile layer marker tmap] 68 | (let [tile-x (ptl/get-tile-x @layer (:x @marker)) 69 | tile-y (ptl/get-tile-y @layer (:y @marker))] 70 | (reset! current-tile (pt/get-tile @tmap tile-x tile-y)))) 71 | 72 | (defn ^:private draw-tile! 73 | [current-tile layer marker tmap] 74 | (let [tile-x (ptl/get-tile-x @layer (:x @marker)) 75 | tile-y (ptl/get-tile-y @layer (:y @marker))] 76 | (when-not (= @current-tile (pt/get-tile @tmap tile-x tile-y)) 77 | (pt/put-tile @tmap @current-tile tile-x tile-y)))) 78 | 79 | (defn ^:private handle-draw! 80 | [current-tile game layer marker tmap] 81 | (let [pointer-down? (get-in game [:input :mouse-pointer :is-down]) 82 | keyboard (get-in game [:input :keyboard]) 83 | shift-down? (pk/is-down keyboard (pk/const :shift))] 84 | (when pointer-down? 85 | (if shift-down? 86 | (update-current-tile! current-tile layer marker tmap) 87 | (draw-tile! current-tile layer marker tmap))))) 88 | 89 | (defn ^:private update-camera! 90 | [cursors game] 91 | (cond 92 | (get-in @cursors [:left :is-down]) 93 | (pset! (:camera game) :x (- (get-in game [:camera :x]) 4)) 94 | 95 | (get-in @cursors [:right :is-down]) 96 | (pset! (:camera game) :x (+ (get-in game [:camera :x]) 4))) 97 | 98 | (cond 99 | (get-in @cursors [:up :is-down]) 100 | (pset! (:camera game) :y (- (get-in game [:camera :y]) 4)) 101 | 102 | (get-in @cursors [:down :is-down]) 103 | (pset! (:camera game) :y (+ (get-in game [:camera :y]) 4)))) 104 | 105 | (defn ^:private build-update-fn 106 | [current-tile cursors layer marker tmap] 107 | (fn [game] 108 | (update-layer! game layer marker) 109 | (handle-draw! current-tile game layer marker tmap) 110 | (update-camera! cursors game))) 111 | 112 | (defn ^:private render 113 | [game] 114 | (let [debug (:debug game)] 115 | (pud/text debug (str "Left-click to paint. Shift + Left-click " 116 | "to select tile. Arrows to scroll.") 117 | 32 32 118 | "#efefef"))) 119 | 120 | (defn ^:private build-states 121 | [] 122 | (let [tmap (atom nil) 123 | layer (atom nil) 124 | marker (atom nil) 125 | current-tile (atom nil) 126 | cursors (atom nil) 127 | create (build-create-fn current-tile cursors layer marker tmap) 128 | update (build-update-fn current-tile cursors layer marker tmap)] 129 | {:preload preload 130 | :create create 131 | :render render 132 | :update update})) 133 | 134 | (defn start-demo 135 | [id] 136 | (pg/->Game 800 600 (p/phaser-constants :auto) id (build-states))) 137 | -------------------------------------------------------------------------------- /resources/public/css/style.css: -------------------------------------------------------------------------------- 1 | /* some style */ 2 | 3 | body { 4 | background-color: #191818; 5 | color: #777; 6 | } 7 | 8 | .pure-img-responsive { 9 | max-width: 100%; 10 | height: auto; 11 | } 12 | 13 | 14 | /* 15 | Add transition to containers so they can push in and out. 16 | */ 17 | 18 | #layout, 19 | #menu, 20 | .menu-link { 21 | -webkit-transition: all 0.2s ease-out; 22 | -moz-transition: all 0.2s ease-out; 23 | -ms-transition: all 0.2s ease-out; 24 | -o-transition: all 0.2s ease-out; 25 | transition: all 0.2s ease-out; 26 | } 27 | 28 | 29 | /* 30 | This is the parent `
` that contains the menu and the content area. 31 | */ 32 | 33 | #layout { 34 | position: relative; 35 | padding-left: 0; 36 | } 37 | 38 | #layout.active #menu { 39 | left: 150px; 40 | width: 150px; 41 | } 42 | 43 | #layout.active .menu-link { 44 | left: 150px; 45 | } 46 | 47 | 48 | .header { 49 | margin: 0; 50 | color: #333; 51 | text-align: center; 52 | padding: 2.5em 2em 0; 53 | border-bottom: 1px solid #eee; 54 | } 55 | 56 | .header h1 { 57 | margin: 0.2em 0; 58 | font-size: 3em; 59 | font-weight: 300; 60 | } 61 | 62 | .header h2 { 63 | font-weight: 300; 64 | color: #ccc; 65 | padding: 0; 66 | margin-top: 0; 67 | } 68 | 69 | /* 70 | The `#menu` `
` is the parent `
` that contains the `.pure-menu` that 71 | appears on the left side of the page. 72 | */ 73 | 74 | #menu { 75 | margin-left: -150px; 76 | /* "#menu" width */ 77 | width: 150px; 78 | position: fixed; 79 | top: 0; 80 | left: 0; 81 | bottom: 0; 82 | z-index: 1000; 83 | /* so the menu or its navicon stays above all content */ 84 | background: #191818; 85 | overflow-y: auto; 86 | -webkit-overflow-scrolling: touch; 87 | } 88 | 89 | 90 | /* 91 | All anchors inside the menu should be styled like this. 92 | */ 93 | 94 | #menu a { 95 | color: #999; 96 | border: none; 97 | padding: 0.6em 0 0.6em 0.6em; 98 | } 99 | 100 | 101 | /* 102 | Remove all background/borders, since we are applying them to #menu. 103 | */ 104 | 105 | #menu .pure-menu, 106 | #menu .pure-menu ul { 107 | border: none; 108 | background: transparent; 109 | } 110 | 111 | 112 | /* 113 | Add that light border to separate items into groups. 114 | */ 115 | 116 | #menu .pure-menu ul, 117 | #menu .pure-menu .menu-item-divided { 118 | border-top: 1px solid #333; 119 | } 120 | 121 | 122 | /* 123 | Change color of the anchor links on hover/focus. 124 | */ 125 | 126 | #menu .pure-menu li a:hover, 127 | #menu .pure-menu li a:focus { 128 | background: #333; 129 | } 130 | 131 | 132 | /* 133 | This styles the selected menu item `
  • `. 134 | */ 135 | 136 | #menu .pure-menu-selected, 137 | #menu .pure-menu-heading { 138 | background: #1f8dd6; 139 | } 140 | 141 | 142 | /* 143 | This styles a link within a selected menu item `
  • `. 144 | */ 145 | 146 | #menu .pure-menu-selected a { 147 | color: #fff; 148 | } 149 | 150 | 151 | /* 152 | This styles the menu heading. 153 | */ 154 | 155 | #menu .pure-menu-heading { 156 | font-size: 110%; 157 | color: #fff; 158 | margin: 0; 159 | } 160 | 161 | 162 | /* -- Dynamic Button For Responsive Menu -------------------------------------*/ 163 | 164 | 165 | /* 166 | The button to open/close the Menu is custom-made and not part of Pure. Here's 167 | how it works: 168 | */ 169 | 170 | 171 | /* 172 | `.menu-link` represents the responsive menu toggle that shows/hides on 173 | small screens. 174 | */ 175 | 176 | .menu-link { 177 | position: fixed; 178 | display: block; 179 | /* show this only on small screens */ 180 | top: 0; 181 | left: 0; 182 | /* "#menu width" */ 183 | background: #000; 184 | background: rgba(0, 0, 0, 0.7); 185 | font-size: 10px; 186 | /* change this value to increase/decrease button size */ 187 | z-index: 10; 188 | width: 2em; 189 | height: auto; 190 | padding: 2.1em 1.6em; 191 | } 192 | 193 | .menu-link:hover, 194 | .menu-link:focus { 195 | background: #000; 196 | } 197 | 198 | .menu-link span { 199 | position: relative; 200 | display: block; 201 | } 202 | 203 | .menu-link span, 204 | .menu-link span:before, 205 | .menu-link span:after { 206 | background-color: #fff; 207 | width: 100%; 208 | height: 0.2em; 209 | } 210 | 211 | .menu-link span:before, 212 | .menu-link span:after { 213 | position: absolute; 214 | margin-top: -0.6em; 215 | content: " "; 216 | } 217 | 218 | .menu-link span:after { 219 | margin-top: 0.6em; 220 | } 221 | 222 | 223 | /* -- Responsive Styles (Media Queries) ------------------------------------- */ 224 | 225 | 226 | /* 227 | Hides the menu at `48em`, but modify this based on your app's needs. 228 | */ 229 | 230 | @media (min-width: 48em) { 231 | .header, 232 | .content { 233 | padding-left: 2em; 234 | padding-right: 2em; 235 | } 236 | #layout { 237 | padding-left: 150px; 238 | /* left col width "#menu" */ 239 | left: 0; 240 | } 241 | #menu { 242 | left: 150px; 243 | } 244 | .menu-link { 245 | position: fixed; 246 | left: 150px; 247 | display: none; 248 | } 249 | #layout.active .menu-link { 250 | left: 150px; 251 | } 252 | } 253 | 254 | @media (max-width: 48em) { 255 | /* Only apply this when the window is small. Otherwise, the following 256 | case results in extra padding on the left: 257 | * Make the window small. 258 | * Tap the menu to trigger the active state. 259 | * Make the window large again. 260 | */ 261 | #layout.active { 262 | position: relative; 263 | left: 150px; 264 | } 265 | } 266 | 267 | /* Demo Container */ 268 | 269 | 270 | 271 | #phzr-demo { 272 | background-color: #C9C9C9; 273 | margin: 20px; 274 | padding: 5px; 275 | width: 800px; 276 | height: 600px; 277 | } 278 | 279 | 280 | /* Code Display */ 281 | 282 | #code-display { 283 | height: 600px; 284 | } 285 | -------------------------------------------------------------------------------- /resources/public/tilemaps/desert.json: -------------------------------------------------------------------------------- 1 | { "height":40, 2 | "layers":[ 3 | { 4 | "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 14, 15, 16, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 46, 30, 30, 30, 30, 30, 30, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 46, 14, 15, 16, 30, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 14, 15, 16, 30, 30, 30, 30, 30, 30, 30, 30, 30, 32, 30, 30, 30, 30, 30, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 22, 23, 24, 30, 30, 30, 30, 30, 30, 30, 30, 32, 30, 30, 32, 30, 30, 30, 30, 30, 30, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 1, 3, 30, 30, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 30, 9, 11, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 30, 9, 11, 30, 30, 30, 30, 6, 7, 7, 7, 8, 30, 46, 30, 30, 30, 30, 30, 30, 30, 30, 40, 30, 30, 30, 30, 33, 34, 36, 42, 37, 34, 34, 34, 34, 34, 34, 34, 35, 30, 9, 11, 30, 30, 30, 30, 14, 15, 15, 15, 16, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 33, 34, 35, 30, 33, 34, 34, 34, 34, 34, 34, 34, 35, 30, 9, 11, 30, 30, 30, 30, 14, 15, 15, 15, 12, 8, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 38, 30, 30, 33, 34, 35, 31, 33, 34, 34, 34, 34, 34, 34, 34, 35, 30, 9, 11, 30, 30, 30, 30, 22, 23, 5, 15, 15, 16, 30, 30, 30, 30, 30, 30, 30, 30, 48, 38, 30, 30, 30, 30, 33, 34, 44, 26, 45, 34, 34, 34, 34, 34, 34, 34, 35, 30, 9, 11, 30, 30, 30, 30, 30, 30, 14, 15, 15, 16, 30, 30, 30, 30, 30, 30, 40, 30, 30, 30, 40, 30, 30, 30, 33, 34, 34, 34, 34, 34, 34, 34, 36, 42, 37, 34, 35, 30, 9, 11, 30, 30, 30, 30, 30, 31, 22, 23, 23, 24, 30, 30, 30, 40, 30, 30, 30, 30, 40, 38, 30, 30, 38, 30, 41, 42, 42, 42, 42, 37, 34, 34, 44, 26, 45, 34, 35, 30, 9, 11, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 39, 30, 30, 30, 38, 30, 40, 30, 30, 30, 30, 30, 30, 30, 30, 41, 42, 42, 42, 42, 42, 42, 43, 30, 9, 11, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 39, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 9, 11, 30, 30, 30, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 7, 7, 8, 1, 2, 2, 2, 2, 2, 3, 30, 30, 30, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 29, 11, 30, 30, 30, 30, 31, 30, 31, 30, 30, 30, 30, 30, 30, 15, 15, 16, 9, 10, 10, 10, 10, 10, 11, 30, 30, 30, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 30, 30, 30, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 23, 23, 24, 17, 18, 18, 18, 18, 18, 19, 30, 30, 30, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 30, 30, 30, 30, 30, 30, 32, 30, 30, 30, 30, 30, 30, 30, 30, 39, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 32, 30, 30, 30, 30, 30, 30, 30, 30, 32, 31, 30, 30, 30, 30, 39, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 32, 39, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 32, 30, 30, 30, 30, 30, 30, 30, 30, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 46, 30, 33, 34, 34, 34, 34, 34, 34, 34, 34, 36, 42, 37, 35, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 32, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 33, 34, 34, 34, 34, 34, 34, 34, 34, 35, 48, 33, 35, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 32, 30, 30, 30, 30, 30, 30, 30, 47, 33, 34, 34, 34, 34, 34, 34, 34, 34, 35, 48, 33, 35, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 39, 30, 30, 30, 33, 34, 34, 34, 34, 34, 34, 34, 34, 35, 48, 33, 35, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 33, 34, 34, 34, 34, 34, 34, 34, 34, 44, 26, 45, 35, 30, 30, 30, 30, 30, 30, 39, 30, 39, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 47, 30, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 48, 30, 30, 30, 30, 30, 39, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 30, 30, 30, 38, 30, 38, 30, 30, 30, 30, 32, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 38, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 40, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 32, 30, 30, 30, 30, 30, 30, 38, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 40, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 32, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 40, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 32, 30, 30, 30, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 6, 7, 7, 7, 7, 8, 30, 30, 30, 30, 30, 30, 30, 40, 30, 40, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 32, 30, 30, 26, 26, 26, 26, 26, 26, 26, 45, 34, 34, 34, 34, 44, 27, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 30, 30, 30, 30, 40, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 30, 30, 30, 32, 30, 30, 30, 30, 30, 30, 30, 30, 32, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], 5 | "height":40, 6 | "name":"Ground", 7 | "opacity":1, 8 | "type":"tilelayer", 9 | "visible":true, 10 | "width":40, 11 | "x":0, 12 | "y":0 13 | }], 14 | "orientation":"orthogonal", 15 | "properties": 16 | { 17 | 18 | }, 19 | "tileheight":32, 20 | "tilesets":[ 21 | { 22 | "firstgid":1, 23 | "image":"C:\/Program Files (x86)\/Tiled\/examples\/tmw_desert_spacing.png", 24 | "imageheight":199, 25 | "imagewidth":265, 26 | "margin":1, 27 | "name":"Desert", 28 | "properties": 29 | { 30 | 31 | }, 32 | "spacing":1, 33 | "tileheight":32, 34 | "tilewidth":32 35 | }], 36 | "tilewidth":32, 37 | "version":1, 38 | "width":40 39 | } -------------------------------------------------------------------------------- /resources/public/js/highlight.js: -------------------------------------------------------------------------------- 1 | !function(e){"undefined"!=typeof exports?e(exports):(window.hljs=e({}),"function"==typeof define&&define.amd&&define("hljs",[],function(){return window.hljs}))}(function(e){function n(e){return e.replace(/&/gm,"&").replace(//gm,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0==t.index}function a(e){return/no-?highlight|plain|text/.test(e)}function i(e){var n,t,r,i=e.className+" ";if(i+=e.parentNode?e.parentNode.className:"",t=/\blang(?:uage)?-([\w-]+)\b/.exec(i))return E(t[1])?t[1]:"no-highlight";for(i=i.split(/\s+/),n=0,r=i.length;r>n;n++)if(E(i[n])||a(i[n]))return i[n]}function o(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t];return r}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3==i.nodeType?a+=i.nodeValue.length:1==i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!=r[0].offset?e[0].offset"}function u(e){f+=""}function c(e){("start"==e.event?o:u)(e.node)}for(var s=0,f="",l=[];e.length||r.length;){var g=i();if(f+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g==e){l.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g==e&&g.length&&g[0].offset==s);l.reverse().forEach(o)}else"start"==g[0].event?l.push(g[0].node):l.pop(),c(g.splice(0,1)[0])}return f+n(a.substr(s))}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var u={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");u[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?c("keyword",a.k):Object.keys(a.k).forEach(function(e){c(e,a.k[e])}),a.k=u}a.lR=t(a.l||/\b\w+\b/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),void 0===a.r&&(a.r=1),a.c||(a.c=[]);var s=[];a.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(o(e,n))}):s.push("self"==e?a:e)}),a.c=s,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var f=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=f.length?t(f.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){for(var t=0;t";return i+=e+'">',i+n+o}function p(){if(!L.k)return n(y);var e="",t=0;L.lR.lastIndex=0;for(var r=L.lR.exec(y);r;){e+=n(y.substr(t,r.index-t));var a=g(L,r);a?(B+=a[1],e+=h(a[0],n(r[0]))):e+=n(r[0]),t=L.lR.lastIndex,r=L.lR.exec(y)}return e+n(y.substr(t))}function d(){var e="string"==typeof L.sL;if(e&&!x[L.sL])return n(y);var t=e?f(L.sL,y,!0,M[L.sL]):l(y,L.sL.length?L.sL:void 0);return L.r>0&&(B+=t.r),e&&(M[L.sL]=t.top),h(t.language,t.value,!1,!0)}function b(){return void 0!==L.sL?d():p()}function v(e,t){var r=e.cN?h(e.cN,"",!0):"";e.rB?(k+=r,y=""):e.eB?(k+=n(t)+r,y=""):(k+=r,y=t),L=Object.create(e,{parent:{value:L}})}function m(e,t){if(y+=e,void 0===t)return k+=b(),0;var r=o(t,L);if(r)return k+=b(),v(r,t),r.rB?0:t.length;var a=u(L,t);if(a){var i=L;i.rE||i.eE||(y+=t),k+=b();do L.cN&&(k+=""),B+=L.r,L=L.parent;while(L!=a.parent);return i.eE&&(k+=n(t)),y="",a.starts&&v(a.starts,""),i.rE?0:t.length}if(c(t,L))throw new Error('Illegal lexeme "'+t+'" for mode "'+(L.cN||"")+'"');return y+=t,t.length||1}var N=E(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var R,L=i||N,M={},k="";for(R=L;R!=N;R=R.parent)R.cN&&(k=h(R.cN,"",!0)+k);var y="",B=0;try{for(var C,j,I=0;;){if(L.t.lastIndex=I,C=L.t.exec(t),!C)break;j=m(t.substr(I,C.index-I),C[0]),I=C.index+j}for(m(t.substr(I)),R=L;R.parent;R=R.parent)R.cN&&(k+="");return{r:B,value:k,language:e,top:L}}catch(O){if(-1!=O.message.indexOf("Illegal"))return{r:0,value:n(t)};throw O}}function l(e,t){t=t||w.languages||Object.keys(x);var r={r:0,value:n(e)},a=r;return t.forEach(function(n){if(E(n)){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}}),a.language&&(r.second_best=a),r}function g(e){return w.tabReplace&&(e=e.replace(/^((<[^>]+>|\t)+)/gm,function(e,n){return n.replace(/\t/g,w.tabReplace)})),w.useBR&&(e=e.replace(/\n/g,"
    ")),e}function h(e,n,t){var r=n?R[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function p(e){var n=i(e);if(!a(n)){var t;w.useBR?(t=document.createElementNS("http://www.w3.org/1999/xhtml","div"),t.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):t=e;var r=t.textContent,o=n?f(n,r,!0):l(r),s=u(t);if(s.length){var p=document.createElementNS("http://www.w3.org/1999/xhtml","div");p.innerHTML=o.value,o.value=c(s,u(p),r)}o.value=g(o.value),e.innerHTML=o.value,e.className=h(e.className,n,o.language),e.result={language:o.language,re:o.r},o.second_best&&(e.second_best={language:o.second_best.language,re:o.second_best.r})}}function d(e){w=o(w,e)}function b(){if(!b.called){b.called=!0;var e=document.querySelectorAll("pre code");Array.prototype.forEach.call(e,p)}}function v(){addEventListener("DOMContentLoaded",b,!1),addEventListener("load",b,!1)}function m(n,t){var r=x[n]=t(e);r.aliases&&r.aliases.forEach(function(e){R[e]=n})}function N(){return Object.keys(x)}function E(e){return x[e]||x[R[e]]}var w={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},x={},R={};return e.highlight=f,e.highlightAuto=l,e.fixMarkup=g,e.highlightBlock=p,e.configure=d,e.initHighlighting=b,e.initHighlightingOnLoad=v,e.registerLanguage=m,e.listLanguages=N,e.getLanguage=E,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e});hljs.registerLanguage("clojure",function(e){var t={built_in:"def cond apply if-not if-let if not not= = < > <= >= == + / * - rem quot neg? pos? delay? symbol? keyword? true? false? integer? empty? coll? list? set? ifn? fn? associative? sequential? sorted? counted? reversible? number? decimal? class? distinct? isa? float? rational? reduced? ratio? odd? even? char? seq? vector? string? map? nil? contains? zero? instance? not-every? not-any? libspec? -> ->> .. . inc compare do dotimes mapcat take remove take-while drop letfn drop-last take-last drop-while while intern condp case reduced cycle split-at split-with repeat replicate iterate range merge zipmap declare line-seq sort comparator sort-by dorun doall nthnext nthrest partition eval doseq await await-for let agent atom send send-off release-pending-sends add-watch mapv filterv remove-watch agent-error restart-agent set-error-handler error-handler set-error-mode! error-mode shutdown-agents quote var fn loop recur throw try monitor-enter monitor-exit defmacro defn defn- macroexpand macroexpand-1 for dosync and or when when-not when-let comp juxt partial sequence memoize constantly complement identity assert peek pop doto proxy defstruct first rest cons defprotocol cast coll deftype defrecord last butlast sigs reify second ffirst fnext nfirst nnext defmulti defmethod meta with-meta ns in-ns create-ns import refer keys select-keys vals key val rseq name namespace promise into transient persistent! conj! assoc! dissoc! pop! disj! use class type num float double short byte boolean bigint biginteger bigdec print-method print-dup throw-if printf format load compile get-in update-in pr pr-on newline flush read slurp read-line subvec with-open memfn time re-find re-groups rand-int rand mod locking assert-valid-fdecl alias resolve ref deref refset swap! reset! set-validator! compare-and-set! alter-meta! reset-meta! commute get-validator alter ref-set ref-history-count ref-min-history ref-max-history ensure sync io! new next conj set! to-array future future-call into-array aset gen-class reduce map filter find empty hash-map hash-set sorted-map sorted-map-by sorted-set sorted-set-by vec vector seq flatten reverse assoc dissoc list disj get union difference intersection extend extend-type extend-protocol int nth delay count concat chunk chunk-buffer chunk-append chunk-first chunk-rest max min dec unchecked-inc-int unchecked-inc unchecked-dec-inc unchecked-dec unchecked-negate unchecked-add-int unchecked-add unchecked-subtract-int unchecked-subtract chunk-next chunk-cons chunked-seq? prn vary-meta lazy-seq spread list* str find-keyword keyword symbol gensym force rationalize"},r="a-zA-Z_\\-!.?+*=<>&#'",n="["+r+"]["+r+"0-9/;:]*",a="[-+]?\\d+(\\.\\d+)?",o={b:n,r:0},s={cN:"number",b:a,r:0},i=e.inherit(e.QSM,{i:null}),c=e.C(";","$",{r:0}),d={cN:"literal",b:/\b(true|false|nil)\b/},l={cN:"collection",b:"[\\[\\{]",e:"[\\]\\}]"},m={cN:"comment",b:"\\^"+n},p=e.C("\\^\\{","\\}"),u={cN:"attribute",b:"[:]"+n},f={cN:"list",b:"\\(",e:"\\)"},h={eW:!0,r:0},y={k:t,l:n,cN:"keyword",b:n,starts:h},b=[f,i,m,p,c,u,l,s,d,o];return f.c=[e.C("comment",""),y,h],h.c=b,l.c=b,{aliases:["clj"],i:/\S/,c:[f,i,m,p,c,u,l,s,d]}}); --------------------------------------------------------------------------------