├── bin ├── kaocha ├── proj └── bb ├── tests.edn ├── CHANGELOG.md ├── dev └── user.clj ├── demo ├── resources │ └── public │ │ ├── pacman_sprites.png │ │ ├── index.html │ │ └── pacman_sprites.min.json ├── package.json ├── .gitignore ├── src │ └── puck_demo │ │ ├── scratch.cljs │ │ ├── circle_packing.cljs │ │ ├── pacman.cljs │ │ └── pixel_editor.cljs ├── dev │ ├── cljs │ │ └── user.cljs │ └── user.clj ├── deps.edn ├── shadow-cljs.edn ├── .dir-locals.el ├── README.md └── package-lock.json ├── .gitignore ├── src └── lambdaisland │ ├── puck │ ├── util.cljc │ ├── geom.cljc │ ├── daedalus.cljs │ ├── math.cljs │ ├── collisions.cljs │ ├── sprite_splitter.clj │ └── types.cljs │ ├── puck.clj │ └── puck.cljs ├── deps.edn ├── README.md ├── .dir-locals.el └── LICENSE.txt /bin/kaocha: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | clojure -A:test -m kaocha.runner "$@" 3 | -------------------------------------------------------------------------------- /tests.edn: -------------------------------------------------------------------------------- 1 | #kaocha/v1 2 | {:plugins [:notifier :print-invocations :profiling]} 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Unreleased 2 | 3 | ## Added 4 | 5 | ## Fixed 6 | 7 | ## Changed 8 | -------------------------------------------------------------------------------- /dev/user.clj: -------------------------------------------------------------------------------- 1 | (ns user) 2 | 3 | (defmacro jit [sym] 4 | `(requiring-resolve '~sym)) 5 | -------------------------------------------------------------------------------- /demo/resources/public/pacman_sprites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambdaisland/puck/HEAD/demo/resources/public/pacman_sprites.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cpcache 2 | .nrepl-port 3 | target 4 | repl 5 | scratch.clj 6 | .shadow-cljs 7 | target 8 | yarn.lock 9 | node_modules/ 10 | .DS_Store 11 | resources/public/ui 12 | .store 13 | -------------------------------------------------------------------------------- /demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "pixi.js": "^5.3.9", 4 | "collisions": "^2.0.13" 5 | }, 6 | "devDependencies": { 7 | "shadow-cljs": "^2.11.26" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/lambdaisland/puck/util.cljc: -------------------------------------------------------------------------------- 1 | (ns lambdaisland.puck.util) 2 | 3 | (defn keypaths [m] 4 | (mapcat (fn [[k v]] 5 | (if (map? v) 6 | (map #(into [k] %) (keypaths v)) 7 | [[k]])) 8 | m)) 9 | -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | .cpcache 2 | .nrepl-port 3 | target 4 | repl 5 | scratch.clj 6 | .shadow-cljs 7 | target 8 | yarn.lock 9 | node_modules/ 10 | .DS_Store 11 | resources/public/ui 12 | .store 13 | .clj-kondo/.cache 14 | .clj-kondo/cache 15 | .lsp 16 | .calva 17 | .#* 18 | -------------------------------------------------------------------------------- /demo/src/puck_demo/scratch.cljs: -------------------------------------------------------------------------------- 1 | (ns puck-demo.scratch 2 | (:require [clojure.datafy :refer [datafy]] 3 | [lambdaisland.puck :as p] 4 | [lambdaisland.puck.math :as m] 5 | [lambdaisland.thicc :as thicc] 6 | [kitchen-async.promise :as promise] 7 | [applied-science.js-interop :as j])) 8 | -------------------------------------------------------------------------------- /bin/proj: -------------------------------------------------------------------------------- 1 | #!bin/bb 2 | 3 | (ns proj 4 | (:require [clojure.java.shell :as sh] 5 | [lioss.main :as lioss] 6 | [lioss.shellutil :as shellutil])) 7 | 8 | (lioss/main 9 | {:license :mpl 10 | :inception-year 2021 11 | :description "ClojureScript wrapper around Pixi.js"}) 12 | 13 | ;; Local Variables: 14 | ;; mode:clojure 15 | ;; End: 16 | -------------------------------------------------------------------------------- /demo/dev/cljs/user.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.user 2 | (:require [portal.web :as portal])) 3 | 4 | (def portal-instance nil) 5 | 6 | (defn portal 7 | "Open a Portal window and register a tap handler for it. The result can be 8 | treated like an atom." 9 | [] 10 | (let [p (portal/open portal-instance)] 11 | (set! portal-instance p) 12 | (add-tap #'portal/submit) 13 | p)) 14 | -------------------------------------------------------------------------------- /demo/deps.edn: -------------------------------------------------------------------------------- 1 | {:paths ["src" "resources"] 2 | :deps {lambdaisland/puck {:local/root ".."} 3 | lambdaisland/webstuff {:sha "fae90bc1d280dfe14f6259aae9428774fa549c4e" 4 | :git/url "https://github.com/lambdaisland/webstuff"} 5 | djblue/portal {:mvn/version "0.12.0"}} 6 | 7 | :aliases 8 | {:dev 9 | {:extra-paths ["dev"] 10 | :extra-deps {thheller/shadow-cljs {:mvn/version "2.11.26"}}}}} 11 | -------------------------------------------------------------------------------- /deps.edn: -------------------------------------------------------------------------------- 1 | {:paths ["src" "resources"] 2 | 3 | :deps 4 | {applied-science/js-interop {:mvn/version "0.2.7"} 5 | mhuebert/kitchen-async {:mvn/version "0.1.0"} 6 | lambdaisland/dom-types {:sha "4c35f25ba4446a4b2c29b349ddc4ba1e353d3b9e" 7 | :git/url "https://github.com/lambdaisland/dom-types"}} 8 | 9 | :aliases 10 | {:dev 11 | {:extra-paths ["dev"] 12 | :extra-deps {thheller/shadow-cljs {:mvn/version "2.11.14"}}} 13 | 14 | :test 15 | {:extra-paths ["test"] 16 | :extra-deps {lambdaisland/kaocha {:mvn/version "1.0.732"}}}}} 17 | -------------------------------------------------------------------------------- /demo/shadow-cljs.edn: -------------------------------------------------------------------------------- 1 | {:deps 2 | {:aliases [:dev]} 3 | 4 | :dev-http 5 | {8008 "classpath:public"} 6 | 7 | :builds 8 | {:main 9 | {:target :browser 10 | :modules {:main {:entries [#_puck-demo.pacman 11 | #_puck-demo.circle-packing 12 | puck-demo.pixel-editor]}} 13 | :output-dir "resources/public/ui" 14 | :asset-path "/ui" 15 | :devtools {:infer-externs :auto 16 | :repl-pprint true 17 | :warnings-as-errors #{:undeclared-var} 18 | :after-load puck-demo.pixel-editor/reinit!}}}} 19 | -------------------------------------------------------------------------------- /src/lambdaisland/puck/geom.cljc: -------------------------------------------------------------------------------- 1 | (ns lambdaisland.puck.geom 2 | "Several libraries implement some version of geometric shapes, this namespace 3 | introduces protocols so we can treat them uniformly. It's also meant to make 4 | conversion between them easier. Not sure yet if this will hold water.") 5 | 6 | (defprotocol IPosition 7 | (x [o]) 8 | (y [o])) 9 | 10 | (defprotocol IScale 11 | (scale [o])) 12 | 13 | (defprotocol IScaleXY 14 | (scale-x [o]) 15 | (scale-y [o])) 16 | 17 | (defprotocol IRect 18 | (width [o]) 19 | (height [o])) 20 | 21 | (defprotocol ICircle 22 | (radius [o])) 23 | 24 | (defprotocol IPolygon 25 | (vertices [o])) 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Puck 2 | 3 | 4 | 5 | 6 | 7 | [](https://en.wikipedia.org/wiki/Puck_(folklore)) 8 | 9 | ClojureScript wrapper around Pixi.js. Work in progress. 10 | 11 | ## License 12 | 13 | Copyright © 2021 Arne Brasseur and Contributors 14 | 15 | Licensed under the term of the Mozilla Public License 2.0, see LICENSE. 16 | -------------------------------------------------------------------------------- /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((nil . ((cider-clojure-cli-global-options . "-A:dev:test") 2 | (cider-custom-cljs-repl-init-form . "(user/cljs-repl)") 3 | (cider-default-cljs-repl . custom) 4 | (cider-preferred-build-tool . clojure-cli) 5 | (cider-redirect-server-output-to-repl . t) 6 | (cider-repl-display-help-banner . nil) 7 | (clojure-toplevel-inside-comment-form . t) 8 | (eval . (progn 9 | (make-variable-buffer-local 'cider-jack-in-nrepl-middlewares) 10 | (add-to-list 'cider-jack-in-nrepl-middlewares "shadow.cljs.devtools.server.nrepl/middleware"))) 11 | (eval . (define-clojure-indent 12 | (assoc 0) 13 | (ex-info 0)))))) 14 | -------------------------------------------------------------------------------- /demo/.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((nil . ((cider-clojure-cli-global-options . "-A:dev:test") 2 | (cider-custom-cljs-repl-init-form . "(user/cljs-repl)") 3 | (cider-default-cljs-repl . custom) 4 | (cider-preferred-build-tool . clojure-cli) 5 | (cider-redirect-server-output-to-repl . t) 6 | (cider-repl-display-help-banner . nil) 7 | (clojure-toplevel-inside-comment-form . t) 8 | (eval . (progn 9 | (make-variable-buffer-local 'cider-jack-in-nrepl-middlewares) 10 | (add-to-list 'cider-jack-in-nrepl-middlewares "shadow.cljs.devtools.server.nrepl/middleware"))) 11 | (eval . (define-clojure-indent 12 | (assoc 0) 13 | (ex-info 0)))))) 14 | -------------------------------------------------------------------------------- /demo/resources/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /demo/dev/user.clj: -------------------------------------------------------------------------------- 1 | (ns user) 2 | 3 | (defmacro jit [sym] 4 | `(requiring-resolve '~sym)) 5 | 6 | (defn start-cljs 7 | ([] 8 | (start-cljs :main)) 9 | ([build-id] 10 | (when (nil? @@(jit shadow.cljs.devtools.server.runtime/instance-ref)) 11 | ((jit shadow.cljs.devtools.server/start!)) 12 | ((jit shadow.cljs.devtools.api/watch) build-id) 13 | (loop [] 14 | (when (nil? @@(jit shadow.cljs.devtools.server.runtime/instance-ref)) 15 | (Thread/sleep 250) 16 | (recur)))))) 17 | 18 | (defn cljs-repl 19 | ([] 20 | (cljs-repl :main)) 21 | ([build-id] 22 | (start-cljs build-id) 23 | ((jit shadow.cljs.devtools.api/nrepl-select) build-id))) 24 | 25 | (defn browse [] 26 | ((jit clojure.java.browse/browse-url) "http://localhost:8008")) 27 | 28 | (def portal-instance (atom nil)) 29 | 30 | (defn portal 31 | "Open a Portal window and register a tap handler for it. The result can be 32 | treated like an atom." 33 | [] 34 | ;; Portal is both an IPersistentMap and an IDeref, which confuses pprint. 35 | (prefer-method @(jit clojure.pprint/simple-dispatch) clojure.lang.IPersistentMap clojure.lang.IDeref) 36 | ;; Portal doesn't recognize records as maps, make them at least datafiable 37 | (extend-protocol clojure.core.protocols/Datafiable 38 | clojure.lang.IRecord 39 | (datafy [r] (into {} r))) 40 | (let [p ((jit portal.api/open) @portal-instance)] 41 | (reset! portal-instance p) 42 | (add-tap (jit portal.api/submit)) 43 | p)) 44 | -------------------------------------------------------------------------------- /src/lambdaisland/puck.clj: -------------------------------------------------------------------------------- 1 | (ns lambdaisland.puck 2 | (:refer-clojure :exclude [let]) 3 | (:require [applied-science.js-interop :as j] 4 | [kitchen-async.promise :as promise] 5 | [lambdaisland.puck.util :as util] 6 | [cljs.core :as cljs])) 7 | 8 | (defmacro assign! 9 | "Recursively merge values into a JavaScript object. Useful interop addition 10 | since pixi often requires setting values several levels deep into an object 11 | hierarchy." 12 | [obj m] 13 | (if (map? m) 14 | (cons 'do 15 | (for [p (util/keypaths m) 16 | :let [v (get-in m p)]] 17 | `(j/assoc-in! ~obj ~p ~v))) 18 | `(doseq [p# (util/keypaths ~m) 19 | :let [v# (get-in ~m p#)]] 20 | (j/assoc-in! ~obj p# v#)))) 21 | 22 | (defmacro with-fill 23 | "Fill-opts: `:color`, `:alpha`" 24 | [[graphics fill-opts] & body] 25 | `(do 26 | (begin-fill ~graphics ~fill-opts) 27 | ~@body 28 | (end-fill ~graphics))) 29 | 30 | (defmacro let 31 | "Like regular let, but you can mark up right-hand values with ^js or ^await. ^js 32 | wraps the object in a js-interop/lookup so you can destructure or do keyword 33 | lookup on it, ^await rewrites the code to resolve promise. If you use any 34 | ^await then the whole `let` will return a promise." 35 | [bindings & body] 36 | (first 37 | (reduce 38 | (fn [body [a b]] 39 | (if (= 'await (:tag (meta b))) 40 | `((promise/->promise (promise/then ~b (cljs/fn [~a] ~@body)))) 41 | `((let* ~(cljs/destructure [a b]) ~@body)))) 42 | body 43 | (reverse 44 | (map (fn [[a b]] 45 | [a (if (= 'js (:tag (meta b))) 46 | `(j/lookup ~b) 47 | b)]) 48 | (partition 2 bindings)))))) 49 | -------------------------------------------------------------------------------- /demo/README.md: -------------------------------------------------------------------------------- 1 | # puck demo 2 | 3 | This demo uses shadow-cljs to setup puck, and in-turn pixi.js dependencies. 4 | 5 | We are also using the clojure cli & dep tools `clj` instead of using `lein`. 6 | 7 | To run this demo, first ensure you have `clj` [installed](https://clojure.org/guides/getting_started). 8 | 9 | Then do an npm install once 10 | 11 | ``` 12 | npm install 13 | ``` 14 | 15 | Now depending on your workflow you can get this up and running in the following ways: 16 | 17 | ## Emacs + CIDER 18 | 19 | If you use emacs + cider, simply open any clj[s] file in the demo folder and run `cider-jack-in-cljs`. This will start up shadow-cljs in watch mode with auto reload. 20 | 21 | Visit http://localhost:8008 22 | 23 | ## Terminal 24 | 25 | You can also get the build running directly from the terminal like this: 26 | 27 | ``` 28 | clj -A:dev:test 29 | ``` 30 | 31 | Then in the repl type `(cljs-repl)` 32 | 33 | ``` 34 | user=> (cljs-repl) 35 | shadow-cljs - HTTP server available at http://localhost:8008 36 | shadow-cljs - server version: 2.11.26 running at http://localhost:9630 37 | shadow-cljs - nREPL server started on port 44123 38 | [:main] Configuring build. 39 | [:main] Compiling ... 40 | [:main] Build completed. (186 files, 15 compiled, 0 warnings, 5.77s) 41 | ``` 42 | 43 | Everytime you save a file, it will recompile itself and if possible hot-reload the code. 44 | 45 | ## Changing entry scripts 46 | 47 | There are 3 different demo scripts. Currently only one is loaded at a time. 48 | 49 | To change that you can comment/uncomment the scripts inside `shadow-cljs.edn` file 50 | example: 51 | 52 | ``` 53 | ... 54 | :modules {:main {:entries [#_puck-demo.pacman 55 | puck-demo.circle-packing 56 | #_puck-demo.pixel-editor]}} 57 | ... 58 | ``` 59 | -------------------------------------------------------------------------------- /src/lambdaisland/puck/daedalus.cljs: -------------------------------------------------------------------------------- 1 | (ns lambdaisland.puck.daedalus 2 | "Bridging Pixi/Puck and Daedalus path finding" 3 | (:require [lambdaisland.daedalus :as dae] 4 | [lambdaisland.puck :as puck] 5 | [lambdaisland.puck.math :as math])) 6 | 7 | (defrecord PixiBasicCanvas [graphics] 8 | Object 9 | (clear [this] 10 | (.clear graphics)) 11 | (lineStyle [this thickness color alpha] 12 | (.lineStyle graphics thickness color alpha)) 13 | (beginFill [this color alpha] 14 | (.beginFill graphics color alpha)) 15 | (endFill [this] 16 | (.endFill graphics)) 17 | (moveTo [this x y] 18 | (.moveTo graphics x y)) 19 | (lineTo [this x y] 20 | (.lineTo graphics x y)) 21 | (quadTo [this cx cy ax ay] 22 | (.quadraticCurveTo graphics cx cy ax ay)) 23 | (drawCircle [this cx cy radius] 24 | (.drawCircle graphics cx cy radius)) 25 | (drawRect [this x y width height] 26 | (.drawRect graphics x y width height)) 27 | (drawTri [this points] 28 | (.drawPolygon graphics (into-array (map (fn [[x y]] (puck/point x y)) 29 | (partition 2 points)))))) 30 | 31 | (defn simple-view 32 | "Wraps a pixi Graphics object so that it can be passed 33 | to [[lambdaisland.daedalus/draw-mesh]], [[lambdaisland.daedalus/draw-entity]], 34 | and [[lambdaisland.daedalus/draw-path]], for easy debugging." 35 | [pixi-graphics] 36 | (dae/simple-view (PixiBasicCanvas. pixi-graphics) {})) 37 | 38 | (defn with-radius 39 | "Add a get_radius() method to the given JavaScript object. This is enough to 40 | make a pixi DisplayObject (like a Sprite) compatible with Daedalus's 41 | path-finder/path-sampler, so you can forgo copying coordinates between a 42 | Daedalus EntityAI and your display-object." 43 | [entity radius] 44 | (specify! entity 45 | Object 46 | (get_radius [this] radius))) 47 | -------------------------------------------------------------------------------- /src/lambdaisland/puck/math.cljs: -------------------------------------------------------------------------------- 1 | (ns lambdaisland.puck.math 2 | "Operations over pixi/Point and pixi/Matrix" 3 | (:require ["pixi.js" :as pixi] 4 | [applied-science.js-interop :as j])) 5 | 6 | (defn distance [this that] 7 | (let [dx (- (:x that) (:x this)) 8 | dy (- (:y that) (:y this))] 9 | (Math/sqrt (+ (* dx dx) (* dy dy))))) 10 | 11 | (defn length [v] 12 | (distance {:x 0 :y 0} v)) 13 | 14 | (defn !v+ [a b] (j/assoc! a :x (+ (:x a) (:x b)) :y (+ (:y a) (:y b)))) 15 | (defn v+ [a b] (doto (.clone a) (!v+ b))) 16 | (defn !v- [a b] (j/assoc! a :x (- (:x a) (:x b)) :y (- (:y a) (:y b)))) 17 | (defn v- [a b] (doto (.clone a) (!v- b))) 18 | (defn !v* [a b] (j/assoc! a :x (* (:x a) b) :y (* (:y a) b))) 19 | (defn v* [a b] (doto (.clone a) (!v* b))) 20 | (defn !vdiv [a b] (j/assoc! a :x (/ (:x a) b) :y (/ (:y a) b))) 21 | (defn vdiv [a b] (doto (.clone a) (!vdiv b))) 22 | 23 | (defn perpendicular [{:keys [x y]}] 24 | (pixi/Point. (- y) x)) 25 | 26 | (defn dot-product [a b] 27 | (+ (* (:x a) (:x b)) 28 | (* (:y a) (:y b)))) 29 | 30 | (defn winding 31 | "AKA the Perp Dot Product AKA the Cross Product on the XY-plane with Z=0, 32 | equivalent to |a| × |b| × sin(θ)" 33 | [a b] 34 | (dot-product a (perpendicular b))) 35 | 36 | (defn clockwise? 37 | ([path] 38 | (let [triples (partition 3 1 (concat path (take 2 path))) 39 | ;; Find the three vertices that form the top-right corner 40 | [a b c] (reduce (fn [[_ a _ :as ta] [_ b _ :as tb]] 41 | ;; Get the lowest y. In case of tie, get highest x 42 | (cond 43 | (< (:y a) (:y b)) 44 | ta 45 | (> (:y a) (:y b)) 46 | tb 47 | :else 48 | (if (< (:x a) (:x b)) 49 | tb 50 | ta))) 51 | triples)] 52 | ;; Check the angle between the two edges formed by these three vertices 53 | (clockwise? (v- b c) (v- b a)))) 54 | ([v1 v2] 55 | (< (winding v1 v2) 0))) 56 | -------------------------------------------------------------------------------- /bin/bb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Wrapper script for babashka to be dropped into projects, will run `bb` from 4 | # the PATH if it exists, or otherwise download it and store it inside the 5 | # project. 6 | 7 | name=babashka 8 | version="0.0.94" 9 | install_dir="$(pwd)/.store/$name-$version" 10 | 11 | system_bb="$(which bb)" 12 | 13 | # https://stackoverflow.com/questions/4023830/how-to-compare-two-strings-in-dot-separated-version-format-in-bash 14 | vercomp () { 15 | if [[ $1 == $2 ]] 16 | then 17 | return 0 18 | fi 19 | local IFS=. 20 | local i ver1=($1) ver2=($2) 21 | # fill empty fields in ver1 with zeros 22 | for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)) 23 | do 24 | ver1[i]=0 25 | done 26 | for ((i=0; i<${#ver1[@]}; i++)) 27 | do 28 | if [[ -z ${ver2[i]} ]] 29 | then 30 | # fill empty fields in ver2 with zeros 31 | ver2[i]=0 32 | fi 33 | if ((10#${ver1[i]} > 10#${ver2[i]})) 34 | then 35 | return 1 36 | fi 37 | if ((10#${ver1[i]} < 10#${ver2[i]})) 38 | then 39 | return 2 40 | fi 41 | done 42 | return 0 43 | } 44 | 45 | if [[ -f "$system_bb" ]]; then 46 | bb_path="$system_bb" 47 | elif [[ -f "$install_dir/bb" ]]; then 48 | bb_path="$install_dir/bb" 49 | else 50 | case "$(uname -s)" in 51 | Linux*) platform=linux;; 52 | Darwin*) platform=macos;; 53 | esac 54 | 55 | echo "$name $version not found, installing to $install_dir..." 56 | download_url="https://github.com/borkdude/babashka/releases/download/v$version/babashka-$version-$platform-amd64.zip" 57 | 58 | mkdir -p $install_dir 59 | echo -e "Downloading $download_url." 60 | curl -o bb.zip -sL "$download_url" 61 | unzip -qqo "bb.zip" -d $install_dir 62 | rm "bb.zip" 63 | bb_path="$install_dir/bb" 64 | fi 65 | 66 | actual_version="$($bb_path --version | sed 's/babashka v//')" 67 | 68 | vercomp $actual_version $version 69 | case $? in 70 | 0) ;; # = 71 | 1) ;; # > 72 | 2) echo "WARNING: babashka version is $actual_version, expected $version" ;; # < 73 | esac 74 | 75 | if [[ -f bb_deps.edn ]]; then 76 | deps="$(cat bb_deps.edn)" 77 | mv deps.edn deps.edn.bak 78 | cp="$(clojure -Srepro -Sdeps "${deps}" -Spath)" 79 | mv deps.edn.bak deps.edn 80 | 81 | exec "rlwrap" "$bb_path" "-cp" "${cp}" "$@" 82 | else 83 | exec "rlwrap" "$bb_path" "$@" 84 | fi 85 | -------------------------------------------------------------------------------- /demo/src/puck_demo/circle_packing.cljs: -------------------------------------------------------------------------------- 1 | (ns puck-demo.circle-packing 2 | (:require [lambdaisland.puck :as p] 3 | [lambdaisland.puck.math :as m] 4 | [lambdaisland.thicc :as thicc] 5 | [kitchen-async.promise :as promise] 6 | [applied-science.js-interop :as j])) 7 | 8 | (defonce game (p/full-screen-app {})) 9 | (defonce g (p/graphics)) 10 | (def padding 1) 11 | (defonce init 12 | (do 13 | (conj! (thicc/query "body") (:view game)) 14 | (conj! (:stage game) g))) 15 | 16 | (defn rand-circle [] 17 | (let [{:keys [width height]} (-> game :renderer :screen) 18 | radius 2] 19 | {:x (+ radius (rand-int (- width radius radius))) 20 | :y (+ radius (rand-int (- height radius radius))) 21 | :r radius 22 | :line (+ 0x098555 (rand-int 100)) 23 | :fill (- 0x098555 (rand-int 100))})) 24 | 25 | (defn draw-circle [{:keys [x y r line fill]}] 26 | (p/line-style g {:color 0xFFFFFF #_line :width 0.5 :alpha 1}) 27 | (p/with-fill [g {:color fill 28 | :alpha 0.9}] 29 | (p/draw-circle g x y r))) 30 | 31 | (defn can-grow? [{:keys [x y r done?] :as this} circles] 32 | (and (not done?) 33 | (let [{:keys [width height]} (-> game :renderer :screen)] 34 | (and (< padding (- x r) (+ x r) (+ padding width)) 35 | (< padding (- y r) (+ y r) (+ padding height)) 36 | (not (some (fn [that] 37 | (and (not= this that) 38 | (< (m/distance this that) 39 | (+ (:r this) (:r that) 1 padding)))) 40 | circles)))))) 41 | 42 | (defn safe-spot? [this circles] 43 | (not (some (fn [that] 44 | (< (m/distance this that) 45 | (+ (:r this) (:r that) 2))) 46 | circles))) 47 | 48 | (defn grow-circles [circles] 49 | (for [this circles] 50 | (if (can-grow? this circles) 51 | (update this :r inc) 52 | (assoc this :done? true)))) 53 | 54 | (defn add-circle [circles] 55 | (loop [circle (rand-circle)] 56 | (if (safe-spot? circle circles) 57 | (conj circles circle) 58 | (recur (rand-circle))))) 59 | 60 | (defonce circles (atom [(rand-circle)])) 61 | 62 | (p/unlisten! (:ticker game) ::tick 63 | #_ (fn [_] 64 | (p/clear! g) 65 | (swap! circles (comp grow-circles #_#_ grow-circles add-circle)) 66 | (run! draw-circle @circles) 67 | )) 68 | 69 | 70 | (swap! circles #(nth (iterate add-circle %) 200)) 71 | (p/clear! g) 72 | (run! draw-circle @circles) 73 | -------------------------------------------------------------------------------- /src/lambdaisland/puck/collisions.cljs: -------------------------------------------------------------------------------- 1 | (ns lambdaisland.puck.collisions 2 | (:require ["collisions" :as collisions] 3 | [applied-science.js-interop :as j] 4 | [lambdaisland.puck.types :as types])) 5 | 6 | (def Collisions collisions/Collisions) 7 | (def Circle collisions/Circle) 8 | (def Polygon collisions/Polygon) 9 | (def Point collisions/Point) 10 | (def Result collisions/Result) 11 | 12 | (types/register-keys-printer ^js Collisions 'collisions/Collisions [:_bvh]) 13 | (types/register-keys-printer ^js (type (.-_bvh (Collisions.))) 'collisions/BVH [:_bodies]) 14 | (types/register-keys-printer ^js Circle 'collisions/Circle [:x :y :radius :scale :padding]) 15 | (types/register-keys-printer ^js Point 'collisions/Point [:x :y :padding]) 16 | (types/register-keys-printer ^js Polygon 'collisions/Polygon [:x :y :_points :angle :scale_x :scale_y :padding]) 17 | (types/register-keys-printer ^js Result 'collisions/Result [:collision :a :b :a_in_b :b_in_a :overlap :overlap_x :overlap_y]) 18 | 19 | (extend-type Collisions 20 | ITransientCollection 21 | (-conj! [coll obj] 22 | (.insert ^js coll obj) 23 | coll) 24 | ITransientSet 25 | (-disjoin! [coll obj] 26 | (.remove ^js coll obj) 27 | coll)) 28 | 29 | (defn system [] 30 | (Collisions.)) 31 | 32 | (defn update! [^js sys] 33 | (.update sys)) 34 | 35 | (defn potentials [^js obj] 36 | (.potentials obj)) 37 | 38 | (defn collides? [^js a b result] 39 | (.collides a b result)) 40 | 41 | (defn rectangle 42 | "Create a collisions rectangular polygon, you can pass a Pixi.js Rect in here." 43 | ([{:keys [x y width height]}] 44 | (rectangle x y width height)) 45 | ([x y width height] 46 | (Polygon. x y (j/lit [[0 0] [width 0] [width height] [0 height]])))) 47 | 48 | (defn polygon [x y points] 49 | (Polygon. x y (into-array (map #(j/lit [(:x %) (:y %)]) points)))) 50 | 51 | (comment 52 | (Circle. 10 20 30 40 50) 53 | ;; => #collisions/Circle {:x 10, :y 20, :radius 30, :scale 40, :padding 50} 54 | (Point. 10 20 30) 55 | ;; => #collisions/Point {:x 10, :y 20, :padding 30} 56 | (Polygon. 10 20 (j/lit [[1 2] [3 4]]) 30 40 50) 57 | ;; => #collisions/Polygon {:x 10, :y 20, :_points #object[Float64Array 1,2,3,4], :angle 30, :scale_x 40, :scale_y 50, :padding 0} 58 | 59 | (Result.) 60 | ;; => #collisions/Result {:collision false, :a nil, :b nil, :a_in_b false, :b_in_a nil, :overlap 0, :overlap_x 0, :overlap_y 0} 61 | 62 | (def player (Circle. 100 100 10)) 63 | 64 | (def sys (doto (system) 65 | (conj! 66 | player 67 | (Polygon. 400 500 (j/lit [[-60 -20] [60 -20] [60 20] [-60 20]]) 1.7) 68 | (Polygon. 200 100 (j/lit [[-60 -20] [60 -20] [60 20] [-60 20]]) 2.2) 69 | (Polygon. 400 50 (j/lit [[-60 -20] [60 -20] [60 20] [-60 20]]) 0.7)))) 70 | 71 | (update! sys) 72 | (let [r (Result.)] 73 | (doseq [obj (potentials player) 74 | :when (collision? player obj)] 75 | (j/let [{:keys [overlap overlap_x]} r] 76 | )))) 77 | -------------------------------------------------------------------------------- /demo/src/puck_demo/pacman.cljs: -------------------------------------------------------------------------------- 1 | (ns puck-demo.pacman 2 | (:require [lambdaisland.puck :as p] 3 | [lambdaisland.thicc :as thicc] 4 | [kitchen-async.promise :as promise] 5 | [applied-science.js-interop :as j])) 6 | 7 | (def state (atom {})) 8 | 9 | (def resources 10 | {:sprites "pacman_sprites.min.json"}) 11 | 12 | ;; Initialize the pixi/Application, full-screen-app makes sure you get a canvas 13 | ;; that is always exactly the size of the browser viewport. We also add some CSS 14 | ;; to make sure we never get scrollbars or stray maring/padding. 15 | (defonce game (p/full-screen-app {})) 16 | 17 | ;; Tell pixi not to blur when scaling 18 | (p/pixelate!) 19 | 20 | ;; Add the view (canvas) to the DOM 21 | (conj! (thicc/query "body") (:view game)) 22 | 23 | ;; Load the sprite sheet, this returns a promise, but thanks to kitchen-async 24 | ;; that makes little difference. 25 | ;; This spritesheet JSON was created with TexturePacker. 26 | (defn move-sprite 27 | "Move a sprite based on its current velocity, and the amount of time that has 28 | passed." 29 | [sprite delta] 30 | (j/update! sprite :x + (* (j/get-in sprite [:velocity :x] 0) delta)) 31 | (j/update! sprite :y + (* (j/get-in sprite [:velocity :y] 0) delta))) 32 | 33 | ;; p/let is like regular let, unless you sprinkle in some ^await and ^js, then 34 | ;; it gets magical powers. 35 | (p/let [;; load-resources takes a map from keyword to resource-url, and returns 36 | ;; a promise to a map with the same keys, but with the loaded resources 37 | ;; as values 38 | {:keys [sprites]} ^await (p/load-resources! game resources) 39 | 40 | ;; A lot of pixi object can already be destructured because we make them 41 | ;; implement ILookup, but if not then p/let can help you. Just tag it as 42 | ;; ^js and you can now destructure to your heart's content. 43 | {:keys [pacman__281_41 pacman__281_1]} ^js (:textures sprites) 44 | 45 | ;; Create an animation out of these frames 46 | pacman (p/animated-sprite [pacman__281_41 pacman__281_1])] 47 | (tap> pacman) 48 | ;; assign! deeply assigns values, you do a lot of this in pixi, so we added a 49 | ;; macro to make this easy. When you pass assign! a literal map it will emit 50 | ;; efficient code to set each nested property individually 51 | (p/assign! pacman {:animationSpeed 0.1 52 | :anchor {:x 0.5 :y 0.5} 53 | :position {:x 200 :y 200} 54 | ;; Velocity is not a pixi thing, it's something we add 55 | ;; ourselves to know which direction a sprite should move 56 | :velocity {:x 1 :y 1}}) 57 | ;; Start the animation 58 | (p/play! pacman) 59 | ;; Add the sprite to the stage container 60 | (conj! (:stage game) pacman) 61 | ;; Also store it for later reference 62 | (swap! state assoc :pacman pacman) 63 | 64 | (p/listen! (:ticker game) ::on-tick 65 | (fn [delta] 66 | (run! #(move-sprite % delta) (:stage game))))) 67 | 68 | ;; Listen to game "ticks" to do animation and handle game events 69 | -------------------------------------------------------------------------------- /src/lambdaisland/puck/sprite_splitter.clj: -------------------------------------------------------------------------------- 1 | (ns lambdaisland.puck.sprite-splitter 2 | (:require [clojure.java.io :as io] 3 | [clojure.string :as str]) 4 | (:import java.awt.Image 5 | java.awt.image.BufferedImage 6 | java.awt.image.Raster 7 | java.awt.image.DataBufferByte 8 | java.io.IOException 9 | javax.imageio.ImageIO)) 10 | 11 | (set! *warn-on-reflection* true) 12 | 13 | (def ^"[F" float4 (make-array Float/TYPE 4)) 14 | 15 | (defn image-raster ^Raster [^BufferedImage img] 16 | (.. img getRaster)) 17 | 18 | (defn raster-data [img] 19 | (.getData ^DataBufferByte (.getDataBuffer (image-raster img)))) 20 | 21 | (defn find-slices [raster-data width] 22 | (let [alpha (vec (map first (partition 4 raster-data)))] 23 | (loop [idx 0 24 | slices [] 25 | start nil] 26 | (if (<= (count alpha) idx) 27 | (if start 28 | (conj slices [start (dec idx)]) 29 | slices) 30 | (let [v (get alpha idx)] 31 | (if (= 0 v) 32 | (if start 33 | (recur (inc idx) (conj slices [start (dec idx)]) nil) 34 | (recur (inc idx) slices nil)) 35 | (if start 36 | (if (= 0 (mod idx width)) 37 | (recur (inc idx) (conj slices [start (dec idx)]) idx) 38 | (recur (inc idx) slices start)) 39 | (recur (inc idx) slices idx)))))))) 40 | 41 | (defn join-region-slice [[x y w h] [start end] width] 42 | (let [start (mod start width) 43 | end (mod end width)] 44 | (if (or (<= x start (+ x w)) 45 | (<= x end (+ x w)) 46 | (< x start end (+ x w))) 47 | (let [new-x (min x start) 48 | new-w (- (max (+ x w) end) new-x) 49 | new-h (inc h)] 50 | [new-x new-h ])))) 51 | 52 | (defn touches-region? [[start end] [x1 y1 x2 y2]] 53 | (or (<= x1 start x2) 54 | (<= x1 end x2) 55 | (< x1 start end x2))) 56 | 57 | (defn regions-touch? [[ax1 ay1 ax2 ay2] 58 | [bx1 by1 bx2 by2]] 59 | (not (or (< (inc ax2) bx1) 60 | (< (inc bx2) ax1) 61 | (< (inc ay2) by1) 62 | (< (inc by2) ay1)))) 63 | 64 | (defn merge-regions 65 | ([r1 r2] 66 | (let [[x11 y11 x12 y12] r1 67 | [x21 y21 x22 y22] r2] 68 | [(min x11 x21) (min y11 y21) (max x12 x22) (max y12 y22)])) 69 | ([[region & rs]] 70 | (if (seq rs) 71 | (if (next rs) 72 | (merge-regions [region (merge-regions rs)]) 73 | (merge-regions region (first rs))) 74 | region))) 75 | 76 | (defn slice->region [[start end] width] 77 | [(mod start width) 78 | (quot start width) 79 | (mod end width) 80 | (quot end width)]) 81 | 82 | (defn find-sprite [result] 83 | (loop [sprite #{(first result)} 84 | remain (disj (set result) (first sprite))] 85 | (let [matches (filter (fn [region] 86 | (some #(regions-touch? % region) sprite)) 87 | remain)] 88 | (if (seq matches) 89 | (recur (into sprite matches) 90 | (apply disj remain matches)) 91 | [(reduce merge-regions sprite) remain])))) 92 | 93 | (defn all-sprite-regions [^BufferedImage img] 94 | (let [width (.getWidth img)] 95 | (loop [sprites #{} 96 | regions (-> img 97 | raster-data 98 | (find-slices width) 99 | (->> (map #(slice->region % width))))] 100 | (if (seq regions) 101 | (let [[sprite remain] (find-sprite regions)] 102 | (recur (conj sprites sprite) 103 | remain)) 104 | sprites)))) 105 | 106 | (defn img-slice [img [x1 y1 x2 y2]] 107 | (let [src-raster (image-raster img) 108 | width (inc (- x2 x1)) 109 | height (inc (- y2 y1)) 110 | dest (BufferedImage. width height BufferedImage/TYPE_INT_ARGB) 111 | ^java.awt.image.WritableRaster dest-raster (image-raster dest)] 112 | (doseq [x (range width) 113 | y (range height) 114 | px (.getPixel src-raster (int (+ x1 x)) (int (+ y1 y)) float4)] 115 | (.setPixel dest-raster (int x) (int y) float4)) 116 | dest)) 117 | 118 | 119 | (defn split-img! [path dest] 120 | (let [img (ImageIO/read (io/file path))] 121 | (doseq [[x1 y1 x2 y2 :as sprite] (all-sprite-regions img)] 122 | (try 123 | (ImageIO/write 124 | ^java.awt.image.RenderedImage (img-slice img sprite) 125 | "png" 126 | (io/file (str dest "_" x1 "_" y1 "_" (inc (- x2 x1)) "x" (inc (- y2 y1)) ".png"))) 127 | (catch Exception e 128 | (prn sprite)))))) 129 | 130 | (defn pack-tiles [path dest min-size max-size] 131 | (let [img (ImageIO/read (io/file path))] 132 | (doseq [[x1 y1 x2 y2 :as sprite] (all-sprite-regions img)] 133 | (try 134 | (ImageIO/write 135 | ^java.awt.image.RenderedImage (img-slice img sprite) 136 | "png" 137 | (io/file (str dest "_" x1 "_" y1 "_" (inc (- x2 x1)) "x" (inc (- y2 y1)) ".png"))) 138 | (catch Exception e 139 | (prn sprite)))))) 140 | 141 | (comment 142 | (split-img! "/home/arne/GameAssets/pacman/pacman.png" "/home/arne/GameAssets/pacman/pacman_") 143 | (split-img! "/tmp/minispel/tekening.png" "/tmp/minispel/sprite_") 144 | (split-img! "/home/arne/GameAssets/tavern inn by CBL/sprites/tilableFloorsAndWalls.png" 145 | "/home/arne/GameAssets/tavern inn by CBL/individual/floors_walls_") 146 | (split-img! "/home/arne/GameAssets/tavern inn by CBL/sprites/originalIndoorSprites.png" 147 | "/home/arne/GameAssets/tavern inn by CBL/individual/indoor_") 148 | (split-img! "/home/arne/GameAssets/tavern inn by CBL/sprites/update01.png" 149 | "/home/arne/GameAssets/tavern inn by CBL/individual/indoor_update_")) 150 | -------------------------------------------------------------------------------- /src/lambdaisland/puck/types.cljs: -------------------------------------------------------------------------------- 1 | (ns lambdaisland.puck.types 2 | "Extend Pixi and DOM types with ClojureScript protocols." 3 | (:require ["pixi.js" :as pixi] 4 | ["resource-loader" :as resource-loader] 5 | [clojure.string :as str] 6 | [applied-science.js-interop :as j] 7 | [camel-snake-kebab.core :as csk] 8 | [lambdaisland.data-printers :as data-printers] 9 | [lambdaisland.dom-types] 10 | [clojure.core.protocols :as protocols])) 11 | 12 | (defn lookupify 13 | "Access object properties via keyword access, and allow destructuring with 14 | `:keys`" 15 | [type] 16 | (extend-type type 17 | ILookup 18 | (-lookup 19 | ([this k] 20 | (j/get this k)) 21 | ([this k not-found] 22 | (j/get this k not-found))) 23 | ITransientAssociative 24 | (-assoc! [this k v] 25 | (j/assoc! this k v) 26 | this) 27 | ITransientMap 28 | (-dissoc! [this k] 29 | (js-delete this k) 30 | this))) 31 | 32 | (defn register-printer [type tag to-edn] 33 | (data-printers/register-print type tag to-edn) 34 | (data-printers/register-pprint type tag to-edn)) 35 | 36 | (defn register-keys-printer [type tag keys] 37 | (register-printer type tag (fn [obj] 38 | (reduce (fn [m k] 39 | (assoc m k (j/get obj k))) 40 | {} 41 | keys))) 42 | (extend-type type 43 | protocols/Datafiable 44 | (datafy [obj] 45 | (into ^{:type type} {} 46 | (comp 47 | ;; We start from all properties currently defined on the object, 48 | ;; but then clean it up a bit 49 | (remove #(and 50 | ;; Never remove the keys we defined 51 | (not (some #{(keyword %)} keys)) 52 | ;; Pixi uses _ to mark private variables 53 | (or (= "_" (first %)) 54 | ;; ClojureScript protocols contain a $ 55 | (some #{"$"} %) 56 | ;; Don't show computed properties 57 | (some-> 58 | (js/Object.getOwnPropertyDescriptor obj %) 59 | .-get) 60 | ;; Remove instance methods 61 | (fn? (j/get obj %))))) 62 | (map (juxt keyword #(j/get obj %)))) 63 | (js-keys obj))) 64 | protocols/Navigable 65 | (nav [obj k v] 66 | (j/get obj k)))) 67 | 68 | 69 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 70 | ;; Pixi 71 | 72 | (register-keys-printer pixi/Application 'pixi/Application [:stage :renderer]) 73 | (register-keys-printer pixi/Renderer 'pixi/Renderer [:view :screen :options]) 74 | (register-keys-printer pixi/Loader 'pixi/Loader [:baseUrl :resources :progress :loading]) 75 | (register-keys-printer pixi/resources.Resource 'pixi/Resource [:name :url :type :metadata :spritesheet :textures]) 76 | 77 | (register-keys-printer pixi/Point 'pixi/Point [:x :y]) 78 | 79 | (extend-type pixi/Point 80 | protocols/Datafiable 81 | (datafy [obj] 82 | {:x (j/get obj :x) 83 | :y (j/get obj :y)})) 84 | 85 | (register-keys-printer pixi/ObservablePoint 'pixi/ObservablePoint [:x :y]) 86 | (register-keys-printer pixi/Matrix 'pixi/Matrix [:a :b :c :d :tx :ty]) 87 | (register-keys-printer pixi/Transform 'pixi/Transform [:worldTransform :localTransform :position :scale :pivot :skew]) 88 | 89 | (register-keys-printer pixi/Container 'pixi/Container [:children :transform :visible]) 90 | (register-keys-printer pixi/Sprite 'pixi/Sprite [:position :anchor :scale :texture]) 91 | (register-keys-printer pixi/AnimatedSprite 'pixi/AnimatedSprite [:position :anchor :scale :textures :animationSpeed :autoUpdate :currentFrame :loop :playing :totalFrames]) 92 | (register-keys-printer pixi/Spritesheet 'pixi/Spritesheet [:baseTexture :textures :animations :data :resolution]) 93 | (register-keys-printer pixi/Texture 'pixi/Texture [:baseTexture :orig :trim]) 94 | (register-keys-printer pixi/BaseTexture 'pixi/BaseTexture [:width :height :resolution :resource]) 95 | (register-keys-printer pixi/Rectangle 'pixi/Rectangle [:x :y :width :height]) 96 | (register-keys-printer pixi/Graphics 'pixi/Graphics [:fill :line :tint]) 97 | (register-keys-printer pixi/FillStyle 'pixi/FillStyle [:alpha :color :matrix :texture :visible]) 98 | (register-keys-printer pixi/LineStyle 'pixi/LineStyle [:alignment :cap :join :miterLimit :native :width :alpha :color :matrix :texture :visible]) 99 | 100 | (register-keys-printer pixi/GraphicsData 'pixi/GraphicsData [:shape :lineStyle :fillStyle :matrix :type :points :holes]) 101 | 102 | (register-keys-printer resource-loader/Resource 'resource-loader/Resource [:name :url :type :metadata :spritesheet :textures :width :height]) 103 | (register-keys-printer pixi/resources.BufferResource 'pixi/BufferResource [:width :height :data]) 104 | (register-keys-printer pixi/resources.Resource 'pixi/Resource [:name :url :type :metadata :spritesheet :textures :width :height]) 105 | (register-keys-printer pixi/resources.ImageResource 'pixi/ImageResource [:url :width :height]) 106 | 107 | (register-keys-printer pixi/Ticker 'pixi/Ticker [:deltaTime :deltaMS :elapsedMS :lastTime :speed :started]) 108 | 109 | 110 | (extend-type pixi/Container 111 | ISeqable 112 | (-seq [this] 113 | (seq (.-children this))) 114 | ;; Lookup by keyword for js obj attributes, but also lookup display objects as 115 | ;; if it's a set, so you can use `contains?` 116 | ILookup 117 | (-lookup 118 | ([this k] 119 | (if (keyword? k) 120 | (j/get this k) 121 | (when (= -1 (.indexOf (.-children this) k)) 122 | k))) 123 | ([this k not-found] 124 | (if (keyword? k) 125 | (j/get this k) 126 | (if (not= -1 (.indexOf (.-children this) k)) 127 | k 128 | not-found)))) 129 | ITransientAssociative 130 | (-assoc! [this k v] 131 | (j/assoc! this k v) 132 | this) 133 | ITransientMap 134 | (-dissoc! [this k] 135 | (js-delete this k) 136 | this) 137 | ITransientCollection 138 | (-conj! [^js this v] 139 | (.addChild this v) 140 | this) 141 | ITransientSet 142 | (-disjoin! [^js this v] 143 | (.removeChild this v))) 144 | 145 | (extend-type pixi/Loader 146 | ITransientCollection 147 | (-conj! [^js this [k v]] 148 | (.add this k v))) 149 | 150 | (register-keys-printer pixi/InteractionEvent 'pixi/InteractionEvent [:type :target :stopped :stopsPropagationAt :stopPropagationHint :currentTarget :date]) 151 | 152 | (register-keys-printer pixi/InteractionData 'pixi/InteractionData [:global :target :originalEvent :identifier :isPrimary :button :buttons :width :height :tiltX :tiltY :pointerType :pressure :rotationAngle :twist :tangentialPressure]) 153 | 154 | (extend-protocol IAssociative 155 | pixi/Point 156 | (-assoc [coll k v] 157 | (doto (.clone coll) 158 | (j/assoc! k v))) 159 | pixi/Matrix 160 | (-assoc [coll k v] 161 | (doto (.clone coll) 162 | (j/assoc! k v))) 163 | pixi/Rectangle 164 | (-assoc [coll k v] 165 | (doto (.clone coll) 166 | (j/assoc! k v)))) 167 | 168 | (doseq [t [pixi/Application pixi/Renderer pixi/Loader pixi/resources.Resource pixi/Point pixi/ObservablePoint 169 | pixi/Matrix pixi/Transform #_pixi/Container pixi/Sprite pixi/Texture pixi/BaseTexture pixi/Rectangle 170 | resource-loader/Resource pixi/resources.Resource pixi/resources.ImageResource pixi/Ticker 171 | pixi/InteractionEvent pixi/InteractionData js/Window js/PointerEvent 172 | js/MouseEvent js/WheelEvent js/DragEvent]] 173 | (lookupify t)) 174 | 175 | (extend-type js/Node 176 | ITransientCollection 177 | (-conj! [^js this child] 178 | (.appendChild this child))) 179 | -------------------------------------------------------------------------------- /demo/src/puck_demo/pixel_editor.cljs: -------------------------------------------------------------------------------- 1 | (ns puck-demo.pixel-editor 2 | (:require [clojure.datafy :refer [datafy]] 3 | [clojure.string :as str] 4 | [lambdaisland.puck :as p] 5 | [lambdaisland.puck.math :as m] 6 | [lambdaisland.thicc :as thicc] 7 | [kitchen-async.promise :as promise] 8 | [applied-science.js-interop :as j])) 9 | 10 | ;; https://www.procjam.com/tutorials/wfc/ 11 | ;; https://github.com/mxgmn/WaveFunctionCollapse 12 | 13 | (defn fixed-color-pixels [width height rgba] 14 | (vec 15 | (for [x (range width)] 16 | (vec 17 | (for [y (range height)] 18 | rgba))))) 19 | 20 | (def size 8) 21 | 22 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 23 | ;; Viewers 24 | 25 | (defn hiccup [html] 26 | (with-meta 27 | html 28 | {:portal.viewer/default :portal.viewer/hiccup})) 29 | 30 | (defn pixel-grid [pixels] 31 | (hiccup 32 | [:div {:style {:display "flex"}} 33 | (for [col pixels] 34 | [:div {:style {:display "flex" :flex-direction "column"}} 35 | (for [color col] 36 | [:div {:style {:width "5px" :height "5px" :background-color (str "rgba(" (str/join "," color) ")")}}])])])) 37 | 38 | (def pixels> (comp tap> pixel-grid)) 39 | 40 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 41 | 42 | (defn pixel-buffer-resource [{:keys [width height pixels]}] 43 | (p/buffer-resource 44 | (p/->u8a 45 | (for [y (range height) 46 | x (range width) 47 | x (get-in pixels [x y])] 48 | x)) 49 | {:width width 50 | :height height})) 51 | 52 | (defn update-buffer [buffer {:keys [width height pixels]}] 53 | (let [u8a (.-data buffer)] 54 | (doseq [x (range width) 55 | y (range height) 56 | z (range 4)] 57 | (aset u8a (+ z (* (+ x (* y height)) 4)) (get-in pixels [x y z])))) 58 | (.update ^js buffer)) 59 | 60 | (defn editor-handlers 61 | "Generate stateful handlers by closing over the state atoms" 62 | [state pixi-state id] 63 | (let [handle-draw-event 64 | (fn [e] 65 | (let [{:keys [sprite buffer]} (get @pixi-state id)] 66 | (when (= sprite (:target e)) 67 | (j/let [{:keys [x y]} (p/local-position (:data e) sprite)] 68 | (swap! state assoc-in 69 | [id :pixels (Math/floor x) (Math/floor y)] 70 | (-> @state id :color)) 71 | (update-buffer buffer (get @state id))))))] 72 | {:mousedown (fn [e] 73 | (swap! state assoc-in [id :drawing?] true) 74 | (handle-draw-event e)) 75 | :mousemove (fn [e] 76 | (when (:drawing? (get @state id)) 77 | (handle-draw-event e))) 78 | :mouseup (fn [e] 79 | (swap! state assoc-in [id :drawing?] false))})) 80 | 81 | ;; End stateful editor functions 82 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 83 | 84 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 85 | ;; Init function, take [state pixi-state options], 86 | ;; return updates [state pixi-state] 87 | 88 | (defn init-pixi-app [state pixi-state {:keys [parent]}] 89 | (p/pixelate!) 90 | (let [app (p/full-screen-app {})] 91 | (conj! parent (:view app)) 92 | [state 93 | (assoc pixi-state :app app)])) 94 | 95 | (defn init-pixel-sprite [state 96 | {:keys [app] :as pixi-state} 97 | {:keys [id 98 | x y scale 99 | width height 100 | background foreground 101 | handlers 102 | pixels] 103 | :or {x 10 y 10 scale 20}}] 104 | (let [my-state (merge {:width width 105 | :height height 106 | :pixels (fixed-color-pixels width height background) 107 | :color foreground} 108 | (get state id)) 109 | buffer (pixel-buffer-resource my-state) 110 | sprite (doto (-> buffer 111 | p/base-texture 112 | (p/texture (p/rectangle 0 0 width height)) 113 | p/sprite) 114 | (p/assign! {:x x 115 | :y y 116 | :scale {:x scale :y scale} 117 | :interactive true})) 118 | {:keys [mousedown mousemove mouseup]} handlers] 119 | 120 | (conj! (:stage app) sprite) 121 | 122 | (when mousedown 123 | (p/listen! sprite 124 | [:mousedown :touchstart] 125 | mousedown)) 126 | (when mousemove 127 | (p/listen! sprite 128 | [:mousemove :touchmove] 129 | mousemove)) 130 | (when mouseup 131 | (p/listen! sprite 132 | [:mouseup :mouseupoutside :touchend :touchendoutside] 133 | mouseup)) 134 | 135 | [(assoc state id my-state) 136 | (assoc pixi-state id {:sprite sprite :buffer buffer})])) 137 | 138 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 139 | ;; Wave function collapse 140 | 141 | (defn pixel-patterns 142 | ([state size] 143 | (pixel-patterns state size size)) 144 | ([{:keys [width height pixels]} pattern-width pattern-height] 145 | (for [x (range (- width (dec pattern-width))) 146 | y (range (- height (dec pattern-height)))] 147 | (vec 148 | (for [x (range x (+ x pattern-width))] 149 | (vec 150 | (for [y (range y (+ y pattern-height))] 151 | (get-in pixels [x y])))))))) 152 | 153 | (comment 154 | (pixel-patterns {:width 4 155 | :height 4 156 | :pixels 157 | (vec 158 | (for [x (range 4)] 159 | (vec 160 | (for [y (range 4)] 161 | (symbol (str (nth "abcd" x) (nth "abcd" y)))))))} 162 | 3)) 163 | 164 | (defn composit 165 | "Composit two rgba pixels 166 | https://ciechanow.ski/alpha-compositing/" 167 | [d s] 168 | (let [da (/ (last d) 255) 169 | sa (/ (last s) 255) 170 | ra (+ sa (* da (- 1 sa)))] 171 | (conj 172 | (mapv 173 | (fn [d s] 174 | (/ (+ (* s sa) (* d da (- 1 sa))) ra)) 175 | (butlast d) 176 | (butlast s)) 177 | ra))) 178 | 179 | #_(tap> (map pixel-grid (set (pixel-patterns @state 3)))) 180 | 181 | (defn init-wave 182 | "Initial \"wave\", completely unobserved, all patterns are still possible at all 183 | positions." 184 | [{:keys [width height pattern-width pattern-height pattern-count]}] 185 | (vec 186 | (for [x (range (- width (dec pattern-width)))] 187 | (vec 188 | (for [y (range (- height (dec pattern-height)))] 189 | (vec 190 | (for [z (range pattern-count)] 191 | true))))))) 192 | 193 | #_(init-wave {:width 3 194 | :height 3 195 | :pattern-width 3 196 | :pattern-height 3 197 | :pattern-count 1}) 198 | 199 | (defonce state (atom {})) 200 | (defonce pixi-state (atom {})) 201 | 202 | (defn init1! [f opts] 203 | (let [[s ps] (f @state @pixi-state opts)] 204 | (reset! state s) 205 | (reset! pixi-state ps))) 206 | 207 | (defn init-all! [] 208 | (init1! init-pixi-app {:parent (thicc/query "body")}) 209 | (init1! init-pixel-sprite {:id :editor 210 | :x 10 211 | :y 10 212 | :scale 20 213 | :width 7 214 | :height 7 215 | :background [255 255 255 255] 216 | :foreground [0 0 125 255] 217 | :handlers (editor-handlers state pixi-state :editor)}) 218 | (init1! init-pixel-sprite {:id :wfc 219 | :x 10 220 | :y 170 221 | :scale 20 222 | :width 10 223 | :height 10 224 | :background [0 100 0 255]})) 225 | 226 | (defn reinit! 227 | ([] 228 | (reinit! false)) 229 | ([hard?] 230 | (when hard? 231 | (reset! state {})) 232 | (reset! pixi-state {}) 233 | (run! #(.remove %) (thicc/query-all "canvas")) 234 | (init-all!))) 235 | 236 | (defonce init-once (init-all!)) 237 | 238 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 239 | ;; REPL API 240 | 241 | (defn clear! [id color] 242 | (let [{:keys [width height]} (get @state id) 243 | {:keys [buffer]} (get @pixi-state id)] 244 | (swap! state 245 | assoc-in [id :pixels] 246 | (fixed-color-pixels width height color)) 247 | (update-buffer buffer (get @state id)))) 248 | 249 | #_(clear! :editor [100 0 0 255]) 250 | 251 | (comment 252 | (tap> (pixel-grid pixels1)) 253 | (tap> (pixel-grid (mapv (fn [col1 col2] 254 | (map composit col1 col2)) 255 | pixels1 pixels2))) 256 | (tap> @state) 257 | 258 | (tap> (pixel-grid (get-in @state [:editor :pixels]))) 259 | 260 | 261 | (run! pixels> (pixel-patterns (:editor @state) 3 3)) 262 | (count (pixel-patterns (:editor @state) 3 3))) 263 | 264 | (let [{:keys [editor wfc]} @state 265 | {:keys [width height]} wfc 266 | pwidth 3 267 | pheight 3 268 | patterns (vec (pixel-patterns editor pwidth pheight)) 269 | wfc (assoc wfc 270 | :patterns patterns 271 | :pattern-width pwidth 272 | :pattern-height pheight 273 | :pattern-count (count patterns))] 274 | (swap! state assoc :wfc (assoc wfc :wave (init-wave wfc)))) 275 | 276 | (defn composit-equal [pixels] 277 | (reduce composit 278 | (map #(assoc % 3 112) pixels))) 279 | 280 | (defn render-wfc [{:keys [width 281 | height 282 | pattern-width 283 | pattern-height 284 | wave 285 | patterns 286 | pattern-count] :as wfc}] 287 | (vec 288 | (for [x (range width)] 289 | (vec 290 | (for [y (range height)] 291 | (composit-equal 292 | (for [px (range (min (inc x) pattern-width (- width x))) 293 | py (range (min (inc y) pattern-height (- height y))) 294 | pz (range pattern-count) 295 | :when (get-in wave [(+ x px) (+ y py) pz])] 296 | (get-in patterns [pz 297 | (- (dec pattern-width) px) 298 | (- (dec pattern-height) py)])))))))) 299 | 300 | 301 | (defn collapse [{:keys [pattern-count] :as wfc} x y pz] 302 | (update wfc 303 | :wave 304 | assoc-in [x y] 305 | (assoc (vec (repeat pattern-count false)) 306 | pz true))) 307 | (comment 308 | (doseq [x (range 10) 309 | y (range 10)] 310 | (swap! state update :wfc collapse x y 2)) 311 | 312 | (run! pixels> (:patterns (:wfc @state))) 313 | 314 | (pixels> (get-in @state [:wfc :patterns 2])) 315 | (pixels> (render-wfc (:wfc @state))) 316 | 317 | (get-in (:patterns (:wfc @state)) [23 2 2]) 318 | 319 | (:wave (:wfc @state)) 320 | 321 | (swap! state update-in [:wfc :wave] (fn [w] (mapv #(mapv (constantly [false false false false false false false false false false false false false false false false false false false false false false true false false]) %) w))) 322 | 323 | (swap! state assoc-in [:wfc :wave 1 0] [false false true false false false false false false false false false false false false false false false false false false false false false false]) 324 | (get-in @state [:wfc :wave]) 325 | [false false true false false false false false false false false false false false false false false false false false false false false false false] 326 | ;; => 327 | ;; => true 328 | ;;=> 47 329 | 330 | #_(tap> (:wfc @state)) 331 | ) 332 | (tap> @pixi-state) 333 | -------------------------------------------------------------------------------- /src/lambdaisland/puck.cljs: -------------------------------------------------------------------------------- 1 | (ns lambdaisland.puck 2 | (:require ["pixi.js" :as pixi] 3 | ["@pixi/utils" :as pixi-utils] 4 | [clojure.string :as str] 5 | [applied-science.js-interop :as j] 6 | [kitchen-async.promise :as p] 7 | [lambdaisland.puck.types] 8 | [camel-snake-kebab.core :as csk] 9 | [lambdaisland.puck.util :as util]) 10 | (:require-macros [lambdaisland.puck :refer [assign! with-fill]])) 11 | 12 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 13 | ;; Helpers 14 | 15 | (defn opts->js [m] 16 | (clj->js m :keyword-fn csk/->camelCaseString)) 17 | 18 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 19 | ;; Initialization 20 | 21 | (defn application ^js [pixi-opts] 22 | (pixi/Application. (opts->js pixi-opts))) 23 | 24 | (defn full-screen-app 25 | ([] 26 | (full-screen-app nil)) 27 | ([opts] 28 | (application (merge {:width js/window.innerWidth 29 | :height js/window.innerHeight 30 | :resolution js/window.devicePixelRatio 31 | :auto-density true 32 | :auto-resize true 33 | :resize-to js/window} 34 | opts)))) 35 | 36 | (defn say-hello! [] 37 | (.sayHello ^js pixi/utils (if (.isWebGLSupported ^js pixi/utils) 38 | "WebGL" 39 | "canvas"))) 40 | 41 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 42 | ;; Settings 43 | 44 | (defn pixelate! 45 | "Tell pixi to not blur when scaling." 46 | [] 47 | (j/assoc-in! pixi/settings [:SCALE_MODE] pixi/SCALE_MODES.NEAREST)) 48 | 49 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 50 | ;; Event / callback handling 51 | 52 | (defonce listeners (atom {})) 53 | 54 | (defprotocol EventSource 55 | (-listen! [source type key callback]) 56 | (-unlisten! [source type key])) 57 | 58 | (defn listen! 59 | "Add a callback/event listener to an event source. Works on pixi/Application, or 60 | on display objects like sprites. 61 | 62 | Adding a new listener for the same source/type/key will replace the previous 63 | one (similar to `add-watch`, handy for REPL or hot reload). The key defaults 64 | to `type`, so if you want multiple listeners with the same source and event 65 | type you have to distinguish them by key. 66 | 67 | You can pass a collection for `type` to listen to multiple signals in one go." 68 | ([source type callback] 69 | (if (coll? type) 70 | (run! #(listen! source % % callback) type) 71 | (-listen! source type type callback))) 72 | ([source type key callback] 73 | (if (coll? type) 74 | (run! #(listen! source % key callback) type) 75 | (-listen! source type key callback)))) 76 | 77 | (defn unlisten! 78 | "Unregister a previously registered listener." 79 | ([source type] 80 | (if (coll? type) 81 | (run! #(unlisten! source % %) type) 82 | (-unlisten! source type type))) 83 | ([source type key] 84 | (if (coll? type) 85 | (run! #(unlisten! source % key) type) 86 | (-unlisten! source type key)))) 87 | 88 | (defn- key-str [k] 89 | (cond 90 | (string? k) 91 | k 92 | (simple-keyword? k) 93 | (name k) 94 | (qualified-keyword? k) 95 | (str (namespace k) "/" (name k)) 96 | :else 97 | (str k))) 98 | 99 | (extend-protocol EventSource 100 | pixi/Application 101 | (-listen! [app signal key callback] 102 | (-listen! (j/get (get-in app [:renderer :runners]) signal) signal key callback)) 103 | (-unlisten! [app signal key] 104 | (-unlisten! (j/get (get-in app [:renderer :runners]) signal) signal key)) 105 | 106 | ;; Hook into pixi's \"Runners\", event listeners attached to the renderer. Known signals: 107 | ;; - `:destroy` 108 | ;; - `:contextChange` 109 | ;; - `:reset` 110 | ;; - `:update` 111 | ;; - `:postrender` 112 | ;; - `:prerender` 113 | ;; - `:resize` 114 | pixi/Runner 115 | (-listen! [runner signal key callback] 116 | (-unlisten! runner signal key) 117 | (let [signal (key-str signal) 118 | key (key-str key) 119 | item (j/lit {signal callback})] 120 | (j/assoc-in! runner [:__listeners signal key] item) 121 | (.add ^js runner item))) 122 | (-unlisten! [runner signal key] 123 | (let [signal (key-str signal) 124 | key (key-str key)] 125 | (when-let [item (j/get-in runner [:__listeners signal key])] 126 | (js-delete (j/get-in runner [:__listeners signal]) key) 127 | (.remove ^js runner item)))) 128 | 129 | ;; In the case of Ticker there is no signal as such, it's only used to 130 | ;; differentiate listeners 131 | pixi/Ticker 132 | (-listen! [ticker signal key callback] 133 | (-unlisten! ticker signal key) 134 | (let [signal (key-str signal) 135 | key (key-str key)] 136 | (j/assoc-in! ticker [:__listeners signal key] callback) 137 | (.add ^js ticker callback))) 138 | (-unlisten! [ticker signal key] 139 | (let [signal (key-str signal) 140 | key (key-str key)] 141 | (when-let [callback (j/get-in ticker [:__listeners signal key])] 142 | (js-delete (j/get-in ticker [:__listeners signal]) key) 143 | (.remove ^js ticker callback)))) 144 | 145 | ;; Listen to events like :mousedown or :touchstart. Works on sprites, 146 | ;; graphics, containers, etc. Make sure to `(j/assoc! sprite :interactive 147 | ;; true)` so the InteractionManager kicks in. 148 | pixi-utils/EventEmitter 149 | (-listen! [obj signal key callback] 150 | (-unlisten! obj signal key) 151 | (j/assoc-in! obj [:__listeners (key-str signal) (key-str key)] callback) 152 | (.on ^js obj (key-str signal) callback)) 153 | (-unlisten! [obj signal key] 154 | (when-let [callback (j/get-in obj [:__listeners (key-str signal) (key-str key)])] 155 | (js-delete (j/get-in obj [:__listeners (key-str signal)]) (key-str key)) 156 | (.removeListener ^js obj (key-str signal) callback))) 157 | 158 | ;; Add listener to a Loader, signal can be one of `:error`, `:load`, `:start`, 159 | ;; `:complete`, `:progress` 160 | pixi/Loader 161 | (-listen! [loader signal key callback] 162 | (-unlisten! loader signal key) 163 | (let [binding (.add ^js (j/get loader (case signal 164 | :error :onError 165 | :load :onLoad 166 | :start :onStart 167 | :complete :onComplete 168 | :progress :onProgress)) 169 | callback)] 170 | (j/assoc-in! loader [:__listeners (key-str signal) (key-str key)] binding))) 171 | (-unlisten! [loader signal key] 172 | (when-let [binding (j/get-in loader [:__listeners (key-str signal) (key-str key)])] 173 | (js-delete (j/get-in loader [:__listeners (key-str signal)]) (key-str key)) 174 | (.detach ^js binding))) 175 | 176 | ;; Also implement listen! / unlisten! for dom elements, so you can use it e.g. 177 | ;; for global keyboard events. 178 | js/Element 179 | (-listen! [el sig key cb] 180 | (-unlisten! el sig key) 181 | (j/assoc-in! el [:__listeners (key-str sig) (key-str key)] cb) 182 | (.addEventListener el (key-str sig) cb)) 183 | (-unlisten! [el sig key] 184 | (when-let [listener (j/get-in el [:__listeners (key-str sig) (key-str key)])] 185 | (js-delete (j/get-in el [:__listeners (key-str sig)]) (key-str key)) 186 | (.removeEventListener el sig listener))) 187 | 188 | js/Window 189 | (-listen! [win sig key cb] 190 | (-unlisten! win sig key) 191 | (j/assoc-in! win [:__listeners (key-str key)] cb) 192 | (.addEventListener win (key-str sig) cb)) 193 | (-unlisten! [win sig key] 194 | (when-let [listener (j/get-in win [:__listeners (key-str sig) (key-str key)])] 195 | (js-delete (j/get-in win [:__listeners (key-str sig)]) (key-str key)) 196 | (.removeEventListener win sig listener)))) 197 | 198 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 199 | ;; Resources / Textures / Resource loading 200 | 201 | (defn resource 202 | "Gets a resource from the app's resource loader by name, only does a simple key 203 | lookup, you have to make sure the resource is loaded first." 204 | [app resource-name] 205 | (j/get (get-in app [:loader :resources]) (key-str resource-name))) 206 | 207 | (defn resource-texture 208 | "Get a texture by name from a resource that contains multiple textures (i.e. a 209 | sprite sheet)." 210 | [app resource-name texture-name] 211 | (j/get (:textures (resource app resource-name)) texture-name)) 212 | 213 | (defn base-texture 214 | "Construct a new BaseTexture" 215 | ([resource] 216 | (base-texture resource nil)) 217 | ([resource options] 218 | (pixi/BaseTexture. resource options))) 219 | 220 | (defn texture 221 | "Construct a texture based on a base texture and a rect." 222 | [base rect] 223 | (pixi/Texture. base rect)) 224 | 225 | (defn load-resources! 226 | "Convenience helper for loading resources, takes a map of resource-name => url, 227 | returns a promise which resolves to a map of resource-name => resource when 228 | the loading has finished." 229 | [app resources] 230 | (let [rkeys (keys resources) 231 | ^js loader (:loader app)] 232 | (p/promise [resolve reject] 233 | (when-let [missing (seq (remove #(resource app %) rkeys))] 234 | (doseq [k missing] 235 | (.add loader (name k) (get resources k)))) 236 | (.load loader 237 | (fn [] 238 | (resolve (into {} (map (juxt identity #(resource app %))) rkeys))))))) 239 | 240 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 241 | ;; Geometry 242 | 243 | (defn bounds 244 | [^js renderable] 245 | (.getBounds renderable)) 246 | 247 | (defn local-bounds 248 | "Retrieves the local bounds of the displayObject or container as a rectangle object. 249 | 250 | - `^pixi/Rectangle rect` Optional rectangle to store the result of the bounds calculation 251 | - `^boolean skip-update-children?` Only for containers, stop re-calculation of children transforms, defaults to false 252 | - returns `pixi/Rectangle`" 253 | ([^js renderable] 254 | (.getLocalBounds renderable)) 255 | ([^js renderable ^js rect] 256 | (.getLocalBounds renderable rect)) 257 | ([^js renderable ^js rect ^boolean skip-update-children?] 258 | (.getLocalBounds renderable rect skip-update-children?))) 259 | 260 | (defn local-position [interaction-data display-object] 261 | (.getLocalPosition ^js interaction-data ^js display-object)) 262 | 263 | (defn global-position [display-object] 264 | (.getGlobalPosition display-object)) 265 | 266 | (defn point 267 | "Create a pixi/Point (2D vector)" 268 | [x y] 269 | (pixi/Point. x y)) 270 | 271 | (defn rectangle 272 | "Create a new pixi/Rectangle" 273 | [x y w h] 274 | (pixi/Rectangle. x y w h)) 275 | 276 | (defn rect-overlap? 277 | "Do the AABB boxes of the two display objects overlap/touch. Useful for 278 | rudimentary collision detection." 279 | [a b] 280 | (let [ab (bounds a) 281 | bb (bounds b)] 282 | (and (< (:x bb) (+ (:x ab) (:width ab))) 283 | (< (:x ab) (+ (:x bb) (:width bb))) 284 | (< (:y bb) (+ (:y ab) (:height ab))) 285 | (< (:y ab) (+ (:y bb) (:height bb)))))) 286 | 287 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 288 | ;; Display objects 289 | 290 | (defn sprite 291 | "Turn a resource or texture into a sprite" 292 | [resource-or-texture] 293 | (pixi/Sprite. (if-let [texture (:texture resource-or-texture)] 294 | texture 295 | resource-or-texture))) 296 | 297 | (defn animated-sprite 298 | "Create an animated sprite from a sequence of textures" 299 | [textures] 300 | (pixi/AnimatedSprite. (into-array textures))) 301 | 302 | (defn text 303 | "Create a text display object with a given message and, optionally, style." 304 | ([msg] (pixi/Text. msg)) 305 | ([msg style] (pixi/Text. msg style))) 306 | 307 | (defn container 308 | "Create a container and populate it" 309 | [opts & children] 310 | (let [c (pixi/Container.)] 311 | (assign! c opts) 312 | (apply conj! c children) 313 | c)) 314 | 315 | (defn graphics 316 | "Create a new Graphics drawing context" 317 | ([] 318 | (pixi/Graphics.)) 319 | ([geometry] 320 | (pixi/Graphics. geometry))) 321 | 322 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 323 | ;; Operations 324 | 325 | (defn remove-children 326 | "Remove all children from a container" 327 | [^js container] 328 | (.removeChildren container)) 329 | 330 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 331 | ;; Graphics API 332 | 333 | (defn js-object [m] 334 | (let [obj #js {}] 335 | (reduce-kv (fn [_ k v] 336 | (unchecked-set obj 337 | (if (keyword? k) 338 | (name k) 339 | (str k)) 340 | v)) 341 | nil 342 | m) 343 | obj)) 344 | 345 | (defn begin-fill [g fill-opts] 346 | (if (number? fill-opts) 347 | (.beginFill ^js g fill-opts) 348 | (.beginTextureFill ^js g (js-object fill-opts)))) 349 | 350 | (defn end-fill [g] 351 | (.endFill ^js g)) 352 | 353 | (defn line-style 354 | "- alignment 355 | - alpha 356 | - cap 357 | - color 358 | - join 359 | - matrix 360 | - miterLimit 361 | - native 362 | - texture 363 | - visible 364 | - width" 365 | [g line-opts] 366 | (.lineStyle g (js-object line-opts))) 367 | 368 | (defn draw-line 369 | ([g p1 p2] 370 | (.drawPolygon ^js g (j/lit [p1 p2]))) 371 | ([g x1 y1 x2 y2] 372 | (draw-line g (point x1 y1) (point x2 y2)))) 373 | 374 | (defn draw-rect [g x y width height] 375 | (.drawRect ^js g x y width height)) 376 | 377 | (defn draw-circle [g x y radius] 378 | (.drawCircle ^js g x y radius)) 379 | 380 | (defn draw-ellipse [g x y width height] 381 | (.drawEllipse ^js g x y width height)) 382 | 383 | (defn clear! 384 | "Clear the graphics object and reset fill/line styles" 385 | [g] 386 | (.clear ^js g)) 387 | 388 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 389 | ;; Animation 390 | 391 | (defn play! [animated-sprite] 392 | (.play ^js animated-sprite)) 393 | 394 | (defn stop! [animated-sprite] 395 | (.stop ^js animated-sprite)) 396 | 397 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 398 | ;; Direct manipulation of textures 399 | 400 | (defn ->u32a 401 | "Convert to Uint32Array" 402 | [coll] 403 | (cond 404 | (and (or (seq? coll) (seqable? coll)) 405 | (not (array? coll))) 406 | (->u32a (into-array coll)) 407 | (instance? js/ArrayBuffer coll) 408 | (js/Uint32Array. coll) 409 | :else 410 | (js/Uint32Array.from coll))) 411 | 412 | (defn ->u8a 413 | "Convert a seq/seqable with 32-bit integers into a Uint8Array" 414 | [coll] 415 | (cond 416 | (and (or (seq? coll) (seqable? coll)) 417 | (not (array? coll))) 418 | (->u8a (into-array coll)) 419 | (instance? js/ArrayBuffer coll) 420 | (js/Uint8Array. coll) 421 | :else 422 | (js/Uint8Array.from coll))) 423 | 424 | (defn buffer-resource 425 | "Create a BufferResource from a Uint8Array 426 | 427 | size-options: 428 | - `:width` 429 | - `:height`" 430 | [u8a size-options] 431 | (pixi/resources.BufferResource. 432 | u8a 433 | (if (map? size-options) 434 | #js {:width (:width size-options) 435 | :height (:height size-options)} 436 | size-options))) 437 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /demo/resources/public/pacman_sprites.min.json: -------------------------------------------------------------------------------- 1 | {"frames":{"pacman__2_82":{"frame":{"x":42,"y":105,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__2_102":{"frame":{"x":109,"y":91,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__2_122":{"frame":{"x":0,"y":105,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__2_142":{"frame":{"x":14,"y":105,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__2_162":{"frame":{"x":28,"y":105,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__2_225":{"frame":{"x":37,"y":20,"w":5,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":5,"h":7},"sourceSize":{"w":5,"h":7}},"pacman__2_244":{"frame":{"x":80,"y":27,"w":13,"h":9},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":13,"h":9},"sourceSize":{"w":13,"h":9}},"pacman__3_2":{"frame":{"x":48,"y":49,"w":12,"h":13},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":12,"h":13},"sourceSize":{"w":12,"h":13}},"pacman__4_203":{"frame":{"x":45,"y":0,"w":4,"h":5},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":5},"sourceSize":{"w":4,"h":5}},"pacman__8_225":{"frame":{"x":20,"y":27,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__10_203":{"frame":{"x":25,"y":0,"w":4,"h":5},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":5},"sourceSize":{"w":4,"h":5}},"pacman__12_181":{"frame":{"x":35,"y":6,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__12_191":{"frame":{"x":42,"y":6,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__13_225":{"frame":{"x":49,"y":6,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__16_268":{"frame":{"x":24,"y":0,"w":1,"h":4},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":1,"h":4},"sourceSize":{"w":1,"h":4}},"pacman__20_191":{"frame":{"x":63,"y":13,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__21_245":{"frame":{"x":35,"y":27,"w":15,"h":8},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":15,"h":8},"sourceSize":{"w":15,"h":8}},"pacman__22_22":{"frame":{"x":30,"y":49,"w":9,"h":13},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":9,"h":13},"sourceSize":{"w":9,"h":13}},"pacman__22_46":{"frame":{"x":54,"y":27,"w":13,"h":9},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":13,"h":9},"sourceSize":{"w":13,"h":9}},"pacman__22_61":{"frame":{"x":67,"y":27,"w":13,"h":9},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":13,"h":9},"sourceSize":{"w":13,"h":9}},"pacman__22_82":{"frame":{"x":95,"y":91,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__22_102":{"frame":{"x":39,"y":91,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__22_122":{"frame":{"x":53,"y":91,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__22_142":{"frame":{"x":67,"y":91,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__22_162":{"frame":{"x":81,"y":91,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__22_225":{"frame":{"x":117,"y":13,"w":5,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":5,"h":7},"sourceSize":{"w":5,"h":7}},"pacman__23_181":{"frame":{"x":20,"y":20,"w":6,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":6,"h":7},"sourceSize":{"w":6,"h":7}},"pacman__24_206":{"frame":{"x":33,"y":0,"w":4,"h":5},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":5},"sourceSize":{"w":4,"h":5}},"pacman__26_2":{"frame":{"x":39,"y":49,"w":9,"h":13},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":9,"h":13},"sourceSize":{"w":9,"h":13}},"pacman__28_191":{"frame":{"x":26,"y":20,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__28_225":{"frame":{"x":33,"y":20,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__30_206":{"frame":{"x":37,"y":0,"w":4,"h":5},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":5},"sourceSize":{"w":4,"h":5}},"pacman__30_263":{"frame":{"x":93,"y":27,"w":7,"h":9},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":9},"sourceSize":{"w":7,"h":9}},"pacman__32_181":{"frame":{"x":42,"y":20,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__33_225":{"frame":{"x":49,"y":20,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__37_191":{"frame":{"x":53,"y":20,"w":6,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":6,"h":7},"sourceSize":{"w":6,"h":7}},"pacman__41_247":{"frame":{"x":0,"y":6,"w":15,"h":6},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":15,"h":6},"sourceSize":{"w":15,"h":6}},"pacman__42_2":{"frame":{"x":60,"y":49,"w":13,"h":13},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":13,"h":13},"sourceSize":{"w":13,"h":13}},"pacman__42_82":{"frame":{"x":112,"y":105,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__42_102":{"frame":{"x":56,"y":105,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__42_122":{"frame":{"x":70,"y":105,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__42_142":{"frame":{"x":84,"y":105,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__42_162":{"frame":{"x":98,"y":105,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__42_181":{"frame":{"x":59,"y":20,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__42_225":{"frame":{"x":66,"y":20,"w":5,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":5,"h":7},"sourceSize":{"w":5,"h":7}},"pacman__44_206":{"frame":{"x":41,"y":0,"w":4,"h":5},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":5},"sourceSize":{"w":4,"h":5}},"pacman__46_263":{"frame":{"x":100,"y":27,"w":11,"h":9},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":11,"h":9},"sourceSize":{"w":11,"h":9}},"pacman__48_225":{"frame":{"x":71,"y":20,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__50_206":{"frame":{"x":49,"y":0,"w":4,"h":5},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":5},"sourceSize":{"w":4,"h":5}},"pacman__52_181":{"frame":{"x":75,"y":20,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__53_225":{"frame":{"x":82,"y":20,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__60_191":{"frame":{"x":86,"y":20,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__61_225":{"frame":{"x":93,"y":20,"w":1,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":1,"h":7},"sourceSize":{"w":1,"h":7}},"pacman__61_248":{"frame":{"x":53,"y":0,"w":15,"h":5},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":15,"h":5},"sourceSize":{"w":15,"h":5}},"pacman__62_82":{"frame":{"x":56,"y":119,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__62_102":{"frame":{"x":0,"y":119,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__62_122":{"frame":{"x":14,"y":119,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__62_142":{"frame":{"x":28,"y":119,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__62_162":{"frame":{"x":42,"y":119,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__62_181":{"frame":{"x":94,"y":20,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__63_225":{"frame":{"x":101,"y":20,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__64_263":{"frame":{"x":111,"y":27,"w":13,"h":9},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":13,"h":9},"sourceSize":{"w":13,"h":9}},"pacman__66_206":{"frame":{"x":68,"y":0,"w":4,"h":5},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":5},"sourceSize":{"w":4,"h":5}},"pacman__68_191":{"frame":{"x":105,"y":20,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__68_225":{"frame":{"x":112,"y":20,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__72_181":{"frame":{"x":116,"y":20,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__72_206":{"frame":{"x":72,"y":0,"w":4,"h":5},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":5},"sourceSize":{"w":4,"h":5}},"pacman__73_225":{"frame":{"x":123,"y":20,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__77_191":{"frame":{"x":0,"y":27,"w":6,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":6,"h":7},"sourceSize":{"w":6,"h":7}},"pacman__81_249":{"frame":{"x":76,"y":0,"w":15,"h":5},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":15,"h":5},"sourceSize":{"w":15,"h":5}},"pacman__82_22":{"frame":{"x":112,"y":119,"w":13,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":13,"h":14},"sourceSize":{"w":13,"h":14}},"pacman__82_43":{"frame":{"x":73,"y":49,"w":14,"h":13},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":13},"sourceSize":{"w":14,"h":13}},"pacman__82_61":{"frame":{"x":87,"y":49,"w":14,"h":13},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":13},"sourceSize":{"w":14,"h":13}},"pacman__82_82":{"frame":{"x":0,"y":133,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__82_102":{"frame":{"x":70,"y":119,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__82_122":{"frame":{"x":84,"y":119,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__82_142":{"frame":{"x":98,"y":119,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__82_181":{"frame":{"x":6,"y":27,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__83_2":{"frame":{"x":14,"y":133,"w":13,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":13,"h":14},"sourceSize":{"w":13,"h":14}},"pacman__84_163":{"frame":{"x":82,"y":37,"w":10,"h":11},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":10,"h":11},"sourceSize":{"w":10,"h":11}},"pacman__84_191":{"frame":{"x":13,"y":27,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__90_267":{"frame":{"x":91,"y":0,"w":7,"h":5},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":5},"sourceSize":{"w":7,"h":5}},"pacman__92_181":{"frame":{"x":24,"y":27,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__101_249":{"frame":{"x":98,"y":0,"w":15,"h":6},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":15,"h":6},"sourceSize":{"w":15,"h":6}},"pacman__102_22":{"frame":{"x":28,"y":63,"w":11,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":11,"h":14},"sourceSize":{"w":11,"h":14}},"pacman__102_45":{"frame":{"x":0,"y":37,"w":14,"h":11},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":11},"sourceSize":{"w":14,"h":11}},"pacman__102_61":{"frame":{"x":14,"y":37,"w":14,"h":11},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":11},"sourceSize":{"w":14,"h":11}},"pacman__102_82":{"frame":{"x":39,"y":63,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__102_102":{"frame":{"x":101,"y":49,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__102_122":{"frame":{"x":0,"y":63,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__102_142":{"frame":{"x":14,"y":63,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__102_181":{"frame":{"x":15,"y":6,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__105_2":{"frame":{"x":53,"y":63,"w":11,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":11,"h":14},"sourceSize":{"w":11,"h":14}},"pacman__121_2":{"frame":{"x":64,"y":63,"w":15,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":15,"h":14},"sourceSize":{"w":15,"h":14}},"pacman__121_185":{"frame":{"x":28,"y":37,"w":22,"h":11},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":22,"h":11},"sourceSize":{"w":22,"h":11}},"pacman__121_205":{"frame":{"x":50,"y":37,"w":21,"h":11},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":21,"h":11},"sourceSize":{"w":21,"h":11}},"pacman__122_22":{"frame":{"x":28,"y":77,"w":15,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":15,"h":14},"sourceSize":{"w":15,"h":14}},"pacman__122_42":{"frame":{"x":43,"y":77,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__122_61":{"frame":{"x":27,"y":133,"w":14,"h":15},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":15},"sourceSize":{"w":14,"h":15}},"pacman__122_82":{"frame":{"x":57,"y":77,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__122_102":{"frame":{"x":79,"y":63,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__122_122":{"frame":{"x":93,"y":63,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__122_142":{"frame":{"x":107,"y":63,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__122_162":{"frame":{"x":0,"y":77,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__122_222":{"frame":{"x":14,"y":77,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__122_249":{"frame":{"x":22,"y":6,"w":13,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":13,"h":7},"sourceSize":{"w":13,"h":7}},"pacman__127_37":{"frame":{"x":0,"y":0,"w":3,"h":1},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":3,"h":1},"sourceSize":{"w":3,"h":1}},"pacman__142_82":{"frame":{"x":14,"y":91,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__142_102":{"frame":{"x":71,"y":77,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__142_122":{"frame":{"x":85,"y":77,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__142_142":{"frame":{"x":99,"y":77,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__142_162":{"frame":{"x":113,"y":77,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__142_222":{"frame":{"x":0,"y":91,"w":14,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":14,"h":14},"sourceSize":{"w":14,"h":14}},"pacman__144_249":{"frame":{"x":53,"y":6,"w":9,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":9,"h":7},"sourceSize":{"w":9,"h":7}},"pacman__166_249":{"frame":{"x":62,"y":6,"w":5,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":5,"h":7},"sourceSize":{"w":5,"h":7}},"pacman__167_105":{"frame":{"x":67,"y":6,"w":5,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":5,"h":7},"sourceSize":{"w":5,"h":7}},"pacman__167_125":{"frame":{"x":72,"y":6,"w":5,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":5,"h":7},"sourceSize":{"w":5,"h":7}},"pacman__167_145":{"frame":{"x":77,"y":6,"w":5,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":5,"h":7},"sourceSize":{"w":5,"h":7}},"pacman__169_25":{"frame":{"x":82,"y":6,"w":5,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":5,"h":7},"sourceSize":{"w":5,"h":7}},"pacman__169_45":{"frame":{"x":87,"y":6,"w":5,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":5,"h":7},"sourceSize":{"w":5,"h":7}},"pacman__169_65":{"frame":{"x":92,"y":6,"w":5,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":5,"h":7},"sourceSize":{"w":5,"h":7}},"pacman__169_85":{"frame":{"x":97,"y":6,"w":3,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":3,"h":7},"sourceSize":{"w":3,"h":7}},"pacman__171_5":{"frame":{"x":100,"y":6,"w":3,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":3,"h":7},"sourceSize":{"w":3,"h":7}},"pacman__171_163":{"frame":{"x":92,"y":37,"w":12,"h":12},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":12,"h":12},"sourceSize":{"w":12,"h":12}},"pacman__171_223":{"frame":{"x":104,"y":37,"w":12,"h":12},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":12,"h":12},"sourceSize":{"w":12,"h":12}},"pacman__172_183":{"frame":{"x":116,"y":37,"w":11,"h":12},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":11,"h":12},"sourceSize":{"w":11,"h":12}},"pacman__172_203":{"frame":{"x":0,"y":49,"w":11,"h":12},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":11,"h":12},"sourceSize":{"w":11,"h":12}},"pacman__173_85":{"frame":{"x":115,"y":6,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__173_105":{"frame":{"x":103,"y":6,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__173_125":{"frame":{"x":107,"y":6,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__173_145":{"frame":{"x":111,"y":6,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__175_5":{"frame":{"x":0,"y":13,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__175_25":{"frame":{"x":119,"y":6,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__175_45":{"frame":{"x":123,"y":6,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__175_65":{"frame":{"x":4,"y":13,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__178_85":{"frame":{"x":20,"y":13,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__178_105":{"frame":{"x":8,"y":13,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__178_125":{"frame":{"x":12,"y":13,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__178_145":{"frame":{"x":16,"y":13,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__180_5":{"frame":{"x":32,"y":13,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__180_25":{"frame":{"x":24,"y":13,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__180_45":{"frame":{"x":28,"y":13,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__180_65":{"frame":{"x":36,"y":13,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__183_85":{"frame":{"x":52,"y":13,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__183_105":{"frame":{"x":40,"y":13,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__183_125":{"frame":{"x":44,"y":13,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__183_145":{"frame":{"x":48,"y":13,"w":4,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":7},"sourceSize":{"w":4,"h":7}},"pacman__188_249":{"frame":{"x":113,"y":0,"w":1,"h":6},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":1,"h":6},"sourceSize":{"w":1,"h":6}},"pacman__202_1":{"frame":{"x":56,"y":13,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__203_251":{"frame":{"x":3,"y":0,"w":2,"h":1},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":2,"h":1},"sourceSize":{"w":2,"h":1}},"pacman__204_248":{"frame":{"x":8,"y":0,"w":2,"h":2},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":2,"h":2},"sourceSize":{"w":2,"h":2}},"pacman__204_253":{"frame":{"x":10,"y":0,"w":2,"h":2},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":2,"h":2},"sourceSize":{"w":2,"h":2}},"pacman__206_247":{"frame":{"x":12,"y":0,"w":2,"h":2},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":2,"h":2},"sourceSize":{"w":2,"h":2}},"pacman__206_255":{"frame":{"x":14,"y":0,"w":2,"h":2},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":2,"h":2},"sourceSize":{"w":2,"h":2}},"pacman__209_247":{"frame":{"x":16,"y":0,"w":2,"h":2},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":2,"h":2},"sourceSize":{"w":2,"h":2}},"pacman__209_255":{"frame":{"x":18,"y":0,"w":2,"h":2},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":2,"h":2},"sourceSize":{"w":2,"h":2}},"pacman__211_1":{"frame":{"x":70,"y":13,"w":6,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":6,"h":7},"sourceSize":{"w":6,"h":7}},"pacman__211_202":{"frame":{"x":11,"y":49,"w":12,"h":13},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":12,"h":13},"sourceSize":{"w":12,"h":13}},"pacman__211_249":{"frame":{"x":20,"y":0,"w":2,"h":2},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":2,"h":2},"sourceSize":{"w":2,"h":2}},"pacman__211_254":{"frame":{"x":22,"y":0,"w":2,"h":2},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":2,"h":2},"sourceSize":{"w":2,"h":2}},"pacman__212_162":{"frame":{"x":28,"y":91,"w":11,"h":14},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":11,"h":14},"sourceSize":{"w":11,"h":14}},"pacman__212_184":{"frame":{"x":71,"y":37,"w":11,"h":11},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":11,"h":11},"sourceSize":{"w":11,"h":11}},"pacman__212_252":{"frame":{"x":5,"y":0,"w":2,"h":1},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":2,"h":1},"sourceSize":{"w":2,"h":1}},"pacman__214_81":{"frame":{"x":76,"y":13,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__214_223":{"frame":{"x":23,"y":49,"w":7,"h":13},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":13},"sourceSize":{"w":7,"h":13}},"pacman__215_71":{"frame":{"x":83,"y":13,"w":6,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":6,"h":7},"sourceSize":{"w":6,"h":7}},"pacman__215_105":{"frame":{"x":31,"y":27,"w":4,"h":8},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":8},"sourceSize":{"w":4,"h":8}},"pacman__218_1":{"frame":{"x":89,"y":13,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__221_106":{"frame":{"x":114,"y":0,"w":2,"h":6},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":2,"h":6},"sourceSize":{"w":2,"h":6}},"pacman__222_71":{"frame":{"x":96,"y":13,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__222_81":{"frame":{"x":103,"y":13,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__222_104":{"frame":{"x":124,"y":27,"w":3,"h":10},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":3,"h":10},"sourceSize":{"w":3,"h":10}},"pacman__226_1":{"frame":{"x":110,"y":13,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__230_71":{"frame":{"x":0,"y":20,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__230_81":{"frame":{"x":7,"y":20,"w":7,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":7,"h":7},"sourceSize":{"w":7,"h":7}},"pacman__235_1":{"frame":{"x":14,"y":20,"w":6,"h":7},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":6,"h":7},"sourceSize":{"w":6,"h":7}},"pacman__235_105":{"frame":{"x":50,"y":27,"w":4,"h":8},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":8},"sourceSize":{"w":4,"h":8}},"pacman__241_106":{"frame":{"x":116,"y":0,"w":6,"h":6},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":6,"h":6},"sourceSize":{"w":6,"h":6}},"pacman__243_7":{"frame":{"x":7,"y":0,"w":1,"h":1},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":1,"h":1},"sourceSize":{"w":1,"h":1}},"pacman__244_1":{"frame":{"x":29,"y":0,"w":4,"h":5},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":4,"h":5},"sourceSize":{"w":4,"h":5}},"pacman__281_1":{"frame":{"x":41,"y":133,"w":24,"h":32},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":24,"h":32},"sourceSize":{"w":24,"h":32}},"pacman__281_41":{"frame":{"x":65,"y":133,"w":30,"h":32},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":30,"h":32},"sourceSize":{"w":30,"h":32}},"pacman__281_81":{"frame":{"x":95,"y":133,"w":32,"h":32},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":32,"h":32},"sourceSize":{"w":32,"h":32}}},"animations":{},"meta":{"app":"https://www.codeandweb.com/texturepacker","version":"1.0","image":"pacman_sprites.png","format":"RGBA8888","size":{"w":127,"h":165},"scale":"1","smartupdate":"$TexturePacker:SmartUpdate:f476c844155f9b6873cfedae2f61dd4b:ad9778a69a9d256e8f48455b9a1dd940:3766cade1c1c6c439a7e910fc2224367$"}} 2 | -------------------------------------------------------------------------------- /demo/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "@pixi/accessibility": { 6 | "version": "5.3.9", 7 | "resolved": "https://registry.npmjs.org/@pixi/accessibility/-/accessibility-5.3.9.tgz", 8 | "integrity": "sha512-Y0+gjfq1ZJl4O6hC6O9KMCLvjAwSy3p9motZvfYs2x2QNLPI9IAafjn2qnM2Cp/Q86ySvqD6DCvLJZ/ni9tyVQ==", 9 | "requires": { 10 | "@pixi/core": "5.3.9", 11 | "@pixi/display": "5.3.9", 12 | "@pixi/utils": "5.3.9" 13 | } 14 | }, 15 | "@pixi/app": { 16 | "version": "5.3.9", 17 | "resolved": "https://registry.npmjs.org/@pixi/app/-/app-5.3.9.tgz", 18 | "integrity": "sha512-5SDMFjCqX0TCMgjuDxLRNpphpIUC3mtTatw06PGf9OUgxMuRwy/PqamYArFosIhnoU4R9ubeo4dE1tQaeYniQw==", 19 | "requires": { 20 | "@pixi/core": "5.3.9", 21 | "@pixi/display": "5.3.9" 22 | } 23 | }, 24 | "@pixi/constants": { 25 | "version": "5.3.9", 26 | "resolved": "https://registry.npmjs.org/@pixi/constants/-/constants-5.3.9.tgz", 27 | "integrity": "sha512-ItYz91qkQdklsjVMHFBPjxE2qiuhv8M8A1c+j3oSBIvRR2/usjwJ24ppYe9TeISa/ONmM24EIW9u9X8WZ0fF8g==" 28 | }, 29 | "@pixi/core": { 30 | "version": "5.3.9", 31 | "resolved": "https://registry.npmjs.org/@pixi/core/-/core-5.3.9.tgz", 32 | "integrity": "sha512-a2W/tqbMGeaNgkcZ2F4930W6OSFwZcOza/z0U9/Pw1JQRgzpJw1ZjZWM+XP0zI0BYcAI+jQUqleBxg5lp3L9HQ==", 33 | "requires": { 34 | "@pixi/constants": "5.3.9", 35 | "@pixi/math": "5.3.9", 36 | "@pixi/runner": "5.3.9", 37 | "@pixi/settings": "5.3.9", 38 | "@pixi/ticker": "5.3.9", 39 | "@pixi/utils": "5.3.9" 40 | } 41 | }, 42 | "@pixi/display": { 43 | "version": "5.3.9", 44 | "resolved": "https://registry.npmjs.org/@pixi/display/-/display-5.3.9.tgz", 45 | "integrity": "sha512-5oNJjZp2if+cm1Wc19OjnO5yDmJozg0ctcxonT7YV2zMkfYc3M1C8svgpkKq5zJILjwSKio2lYbTa/6pGSgtBA==", 46 | "requires": { 47 | "@pixi/math": "5.3.9", 48 | "@pixi/settings": "5.3.9", 49 | "@pixi/utils": "5.3.9" 50 | } 51 | }, 52 | "@pixi/extract": { 53 | "version": "5.3.9", 54 | "resolved": "https://registry.npmjs.org/@pixi/extract/-/extract-5.3.9.tgz", 55 | "integrity": "sha512-h74fAPyiRgZudysbd1Jss3uKtl89wprRxRVbTQHWzSeu382qBGPXONHmT7RIQRk4hRMAASxeWltibVtKMphelQ==", 56 | "requires": { 57 | "@pixi/core": "5.3.9", 58 | "@pixi/math": "5.3.9", 59 | "@pixi/utils": "5.3.9" 60 | } 61 | }, 62 | "@pixi/filter-alpha": { 63 | "version": "5.3.9", 64 | "resolved": "https://registry.npmjs.org/@pixi/filter-alpha/-/filter-alpha-5.3.9.tgz", 65 | "integrity": "sha512-qfPJeKViLl/55dGzqX7qzTXy7XLIURw8kOdr89BssoQnGLosI7gEcKXMk2ib+tKk2KYzlGCScmcx1TU+sC++xQ==", 66 | "requires": { 67 | "@pixi/core": "5.3.9" 68 | } 69 | }, 70 | "@pixi/filter-blur": { 71 | "version": "5.3.9", 72 | "resolved": "https://registry.npmjs.org/@pixi/filter-blur/-/filter-blur-5.3.9.tgz", 73 | "integrity": "sha512-Xr5/irGK70oF4Xw3wabeKecq9oFTZDJ/oKPKotFgG+Dxiy2DmBh+oHpOsteCJ18QLHvKLrr0AJt6AkpoNFcKnQ==", 74 | "requires": { 75 | "@pixi/core": "5.3.9", 76 | "@pixi/settings": "5.3.9" 77 | } 78 | }, 79 | "@pixi/filter-color-matrix": { 80 | "version": "5.3.9", 81 | "resolved": "https://registry.npmjs.org/@pixi/filter-color-matrix/-/filter-color-matrix-5.3.9.tgz", 82 | "integrity": "sha512-02Bj4TPhLl5PneZh9eaAhJgWjKv4HfR/4+gJxzp4/Es61aW/fz+38DD5JywmXNDV39RnUhLpvnMrbqYzdHXZIw==", 83 | "requires": { 84 | "@pixi/core": "5.3.9" 85 | } 86 | }, 87 | "@pixi/filter-displacement": { 88 | "version": "5.3.9", 89 | "resolved": "https://registry.npmjs.org/@pixi/filter-displacement/-/filter-displacement-5.3.9.tgz", 90 | "integrity": "sha512-VWwk1jyrS2VMprzknaqA9PqNda7TS2qp3tAVt97qadM5sRE0LzkhYvd+w4/b2TzvrHcu+0q5odmKuFuiSSE51Q==", 91 | "requires": { 92 | "@pixi/core": "5.3.9", 93 | "@pixi/math": "5.3.9" 94 | } 95 | }, 96 | "@pixi/filter-fxaa": { 97 | "version": "5.3.9", 98 | "resolved": "https://registry.npmjs.org/@pixi/filter-fxaa/-/filter-fxaa-5.3.9.tgz", 99 | "integrity": "sha512-fuOADEHVn9XVyo8o88TiPgHRQ7P3NpGkQmS95mFW9SIP//QuQ8ikj3yYuBKtNM6TsCsJe7/bTv4i7uX8l00kVQ==", 100 | "requires": { 101 | "@pixi/core": "5.3.9" 102 | } 103 | }, 104 | "@pixi/filter-noise": { 105 | "version": "5.3.9", 106 | "resolved": "https://registry.npmjs.org/@pixi/filter-noise/-/filter-noise-5.3.9.tgz", 107 | "integrity": "sha512-FtVbg49p0DLoaW2ua4no8ACgBJkip5yVYDqBkuZIPUP6PrXssCSjpU0w060TtcL6qQI9GpUqOBxffN3Qhn+VHg==", 108 | "requires": { 109 | "@pixi/core": "5.3.9" 110 | } 111 | }, 112 | "@pixi/graphics": { 113 | "version": "5.3.9", 114 | "resolved": "https://registry.npmjs.org/@pixi/graphics/-/graphics-5.3.9.tgz", 115 | "integrity": "sha512-JWzMabJI4iy3Wynv26VcgMvTN/QH6w2qoYS2WQZlA9YYPLrdIpRoArHUlSU4bAoc9AqrTuOI6Xd6xHZspLH36A==", 116 | "requires": { 117 | "@pixi/constants": "5.3.9", 118 | "@pixi/core": "5.3.9", 119 | "@pixi/display": "5.3.9", 120 | "@pixi/math": "5.3.9", 121 | "@pixi/sprite": "5.3.9", 122 | "@pixi/utils": "5.3.9" 123 | } 124 | }, 125 | "@pixi/interaction": { 126 | "version": "5.3.9", 127 | "resolved": "https://registry.npmjs.org/@pixi/interaction/-/interaction-5.3.9.tgz", 128 | "integrity": "sha512-sDxS6/MXY3zhIJKbKCwHMhO7+2hbXGydIkZtn6LtpKN2X19z69M/C9Ka+5ckPfbmrKf25ohjvcGS8xWqf0sNOw==", 129 | "requires": { 130 | "@pixi/core": "5.3.9", 131 | "@pixi/display": "5.3.9", 132 | "@pixi/math": "5.3.9", 133 | "@pixi/ticker": "5.3.9", 134 | "@pixi/utils": "5.3.9" 135 | } 136 | }, 137 | "@pixi/loaders": { 138 | "version": "5.3.9", 139 | "resolved": "https://registry.npmjs.org/@pixi/loaders/-/loaders-5.3.9.tgz", 140 | "integrity": "sha512-qepjJ/aup+A5do26yj13Ma3z8kKp+HhkQL2F4uPeIm019DytO8vfKntjmNzU7obw2FMKbn1PRUmX8METLC6DOA==", 141 | "requires": { 142 | "@pixi/core": "5.3.9", 143 | "@pixi/utils": "5.3.9", 144 | "resource-loader": "^3.0.1" 145 | } 146 | }, 147 | "@pixi/math": { 148 | "version": "5.3.9", 149 | "resolved": "https://registry.npmjs.org/@pixi/math/-/math-5.3.9.tgz", 150 | "integrity": "sha512-Ka5ypD22Te+DEx2572Zsct7mYnbl0em+lzvJBdbQnddCfvW9JBILAwULFa4Z8KxeeLT2PMCgp1wxwG1yQaiS6A==" 151 | }, 152 | "@pixi/mesh": { 153 | "version": "5.3.9", 154 | "resolved": "https://registry.npmjs.org/@pixi/mesh/-/mesh-5.3.9.tgz", 155 | "integrity": "sha512-fyKlk1AKJHwQ/0u+4+4nxScstreH05yHmCyDVM2fc1e9VbJy2Z7ZOueZCgguRfJrDvMqMqtkfKTWTzDvcADsYQ==", 156 | "requires": { 157 | "@pixi/constants": "5.3.9", 158 | "@pixi/core": "5.3.9", 159 | "@pixi/display": "5.3.9", 160 | "@pixi/math": "5.3.9", 161 | "@pixi/settings": "5.3.9", 162 | "@pixi/utils": "5.3.9" 163 | } 164 | }, 165 | "@pixi/mesh-extras": { 166 | "version": "5.3.9", 167 | "resolved": "https://registry.npmjs.org/@pixi/mesh-extras/-/mesh-extras-5.3.9.tgz", 168 | "integrity": "sha512-Xl7rXSjS048r8x1ZJ0s0DmKARqUhUPLp0VVhZho38IZKRFyEj1dkiOFYkamovxrVYdmZ12GvhdS74NSKiX1wEA==", 169 | "requires": { 170 | "@pixi/constants": "5.3.9", 171 | "@pixi/core": "5.3.9", 172 | "@pixi/math": "5.3.9", 173 | "@pixi/mesh": "5.3.9", 174 | "@pixi/utils": "5.3.9" 175 | } 176 | }, 177 | "@pixi/mixin-cache-as-bitmap": { 178 | "version": "5.3.9", 179 | "resolved": "https://registry.npmjs.org/@pixi/mixin-cache-as-bitmap/-/mixin-cache-as-bitmap-5.3.9.tgz", 180 | "integrity": "sha512-udmyHkc8FIRlHzAg29kmvSFlbkO7Q9B3G3Oxiw5g/c8L2HE45iXpasor7o0gSAz90+gwWxieBK60uDKr4vX8sQ==", 181 | "requires": { 182 | "@pixi/core": "5.3.9", 183 | "@pixi/display": "5.3.9", 184 | "@pixi/math": "5.3.9", 185 | "@pixi/settings": "5.3.9", 186 | "@pixi/sprite": "5.3.9", 187 | "@pixi/utils": "5.3.9" 188 | } 189 | }, 190 | "@pixi/mixin-get-child-by-name": { 191 | "version": "5.3.9", 192 | "resolved": "https://registry.npmjs.org/@pixi/mixin-get-child-by-name/-/mixin-get-child-by-name-5.3.9.tgz", 193 | "integrity": "sha512-rGjPrKSdr84iHMxQp26ZHYEc1BStLsNsxyQLcKCxOGZzzzP7g2X8Wwsw66Ie51U/ue4OpcxcUoGOlh88hVJtNw==", 194 | "requires": { 195 | "@pixi/display": "5.3.9" 196 | } 197 | }, 198 | "@pixi/mixin-get-global-position": { 199 | "version": "5.3.9", 200 | "resolved": "https://registry.npmjs.org/@pixi/mixin-get-global-position/-/mixin-get-global-position-5.3.9.tgz", 201 | "integrity": "sha512-HPhb7gI3XnO8bJonqXYt/dEesh7TD6EkLHzKq8d7GdrB+JebfK4RMwgbL6vliVQianmTzl2J/1NgZ96fKg8HAw==", 202 | "requires": { 203 | "@pixi/display": "5.3.9", 204 | "@pixi/math": "5.3.9" 205 | } 206 | }, 207 | "@pixi/particles": { 208 | "version": "5.3.9", 209 | "resolved": "https://registry.npmjs.org/@pixi/particles/-/particles-5.3.9.tgz", 210 | "integrity": "sha512-NAB3to0Om5LicwUpMeMsjxaXZYXi9mdTOgucXirf7I+RKPEp8wZg9g10esXjFjCryQYSlr2YPTpfANiK2pzdJw==", 211 | "requires": { 212 | "@pixi/constants": "5.3.9", 213 | "@pixi/core": "5.3.9", 214 | "@pixi/display": "5.3.9", 215 | "@pixi/math": "5.3.9", 216 | "@pixi/utils": "5.3.9" 217 | } 218 | }, 219 | "@pixi/polyfill": { 220 | "version": "5.3.9", 221 | "resolved": "https://registry.npmjs.org/@pixi/polyfill/-/polyfill-5.3.9.tgz", 222 | "integrity": "sha512-y5DLSWtIMafET1o4C1xfNyXvZGC5HZLqRoQ7ypmvjcn7owk2C+61KPV0rrH5kyK5ncWaI6utnoVyvivo/Shp8A==", 223 | "requires": { 224 | "es6-promise-polyfill": "^1.2.0", 225 | "object-assign": "^4.1.1" 226 | } 227 | }, 228 | "@pixi/prepare": { 229 | "version": "5.3.9", 230 | "resolved": "https://registry.npmjs.org/@pixi/prepare/-/prepare-5.3.9.tgz", 231 | "integrity": "sha512-ykb5YI06rYPQm5ZC8ymmVprjyno4WskRdr8DRuq/z8008ZqL1+YN0Yw/8v0aXpOdh43uPYUPHvHj77tLuV8BRQ==", 232 | "requires": { 233 | "@pixi/core": "5.3.9", 234 | "@pixi/display": "5.3.9", 235 | "@pixi/graphics": "5.3.9", 236 | "@pixi/settings": "5.3.9", 237 | "@pixi/text": "5.3.9", 238 | "@pixi/ticker": "5.3.9" 239 | } 240 | }, 241 | "@pixi/runner": { 242 | "version": "5.3.9", 243 | "resolved": "https://registry.npmjs.org/@pixi/runner/-/runner-5.3.9.tgz", 244 | "integrity": "sha512-AN36mZivER12D1wmjoAf7scjK1JLO/uA9PyzfAResccafkev4W/PtjAYODSYUbNf3SnxvQMlpdVK7NHSwnxifQ==" 245 | }, 246 | "@pixi/settings": { 247 | "version": "5.3.9", 248 | "resolved": "https://registry.npmjs.org/@pixi/settings/-/settings-5.3.9.tgz", 249 | "integrity": "sha512-4moUuiDOibv/Fm2QVUg2TUL/6ZmYEi6OSifV4OlzMkaoyEtpc//4YC6nm+a0zDoQ2SxCWn9ADUexkNGsKNwi6Q==", 250 | "requires": { 251 | "ismobilejs": "^1.1.0" 252 | } 253 | }, 254 | "@pixi/sprite": { 255 | "version": "5.3.9", 256 | "resolved": "https://registry.npmjs.org/@pixi/sprite/-/sprite-5.3.9.tgz", 257 | "integrity": "sha512-NCBl53D3OGuXyBzsDY5j4tzyMhXo9x3B9tGkZTaPamy6LFuJAHKz1rJLCft0dhQG0mCRihDHA7RVJF6t2NcQag==", 258 | "requires": { 259 | "@pixi/constants": "5.3.9", 260 | "@pixi/core": "5.3.9", 261 | "@pixi/display": "5.3.9", 262 | "@pixi/math": "5.3.9", 263 | "@pixi/settings": "5.3.9", 264 | "@pixi/utils": "5.3.9" 265 | } 266 | }, 267 | "@pixi/sprite-animated": { 268 | "version": "5.3.9", 269 | "resolved": "https://registry.npmjs.org/@pixi/sprite-animated/-/sprite-animated-5.3.9.tgz", 270 | "integrity": "sha512-8s4Y8eHMbzwDX62LuvW0E8TV5mNnLcrqYGXxh5AkY5pp2b33ob9LD6ajs9vfVAaAXLwCjNCWy6N8K7jB07NzhQ==", 271 | "requires": { 272 | "@pixi/core": "5.3.9", 273 | "@pixi/sprite": "5.3.9", 274 | "@pixi/ticker": "5.3.9" 275 | } 276 | }, 277 | "@pixi/sprite-tiling": { 278 | "version": "5.3.9", 279 | "resolved": "https://registry.npmjs.org/@pixi/sprite-tiling/-/sprite-tiling-5.3.9.tgz", 280 | "integrity": "sha512-3KgsYJcdR4VCHNa9vdsbrJOpAFg9ggNvGhHfU2zrZqv54b2NK1ieBLgFLXsefB2/1SYpgWjQUQ9wWzoc8Z5NXQ==", 281 | "requires": { 282 | "@pixi/constants": "5.3.9", 283 | "@pixi/core": "5.3.9", 284 | "@pixi/display": "5.3.9", 285 | "@pixi/math": "5.3.9", 286 | "@pixi/sprite": "5.3.9", 287 | "@pixi/utils": "5.3.9" 288 | } 289 | }, 290 | "@pixi/spritesheet": { 291 | "version": "5.3.9", 292 | "resolved": "https://registry.npmjs.org/@pixi/spritesheet/-/spritesheet-5.3.9.tgz", 293 | "integrity": "sha512-N7wK8qQMI8rBpLXO1QalA9HOJ8j0+jM/ZYl2JWewo8rbxKpXTllOazr8QdSaofxAhCCsmG2QBzfR//tZS+WfGg==", 294 | "requires": { 295 | "@pixi/core": "5.3.9", 296 | "@pixi/loaders": "5.3.9", 297 | "@pixi/math": "5.3.9", 298 | "@pixi/utils": "5.3.9" 299 | } 300 | }, 301 | "@pixi/text": { 302 | "version": "5.3.9", 303 | "resolved": "https://registry.npmjs.org/@pixi/text/-/text-5.3.9.tgz", 304 | "integrity": "sha512-QT1XRqLpaN0IsIHCbL8hgvRQSoHTodgvjeMCfAbp8KC0fLYxxKaD7RIU02Ito1Vl0cGON65/lg/qQMegQocgsg==", 305 | "requires": { 306 | "@pixi/core": "5.3.9", 307 | "@pixi/math": "5.3.9", 308 | "@pixi/settings": "5.3.9", 309 | "@pixi/sprite": "5.3.9", 310 | "@pixi/utils": "5.3.9" 311 | } 312 | }, 313 | "@pixi/text-bitmap": { 314 | "version": "5.3.9", 315 | "resolved": "https://registry.npmjs.org/@pixi/text-bitmap/-/text-bitmap-5.3.9.tgz", 316 | "integrity": "sha512-s33Y+iiiLIIe4d9Tevn8VQ9HZfmpud0GU1OdoWRhMAKiXXsoI12e+hzVS6bOS5rsD0iyyS7Bcs4zxbBezSU24A==", 317 | "requires": { 318 | "@pixi/core": "5.3.9", 319 | "@pixi/display": "5.3.9", 320 | "@pixi/loaders": "5.3.9", 321 | "@pixi/math": "5.3.9", 322 | "@pixi/mesh": "5.3.9", 323 | "@pixi/settings": "5.3.9", 324 | "@pixi/text": "5.3.9", 325 | "@pixi/utils": "5.3.9" 326 | } 327 | }, 328 | "@pixi/ticker": { 329 | "version": "5.3.9", 330 | "resolved": "https://registry.npmjs.org/@pixi/ticker/-/ticker-5.3.9.tgz", 331 | "integrity": "sha512-t7hc72X70lAp3H+m5BY6fS3U6XOdMqQrv6+5z4vfqBBr1lOuJGWUhgIpGXk0qhOl4F88LQlXkOsfk/qqUN+NCQ==", 332 | "requires": { 333 | "@pixi/settings": "5.3.9" 334 | } 335 | }, 336 | "@pixi/utils": { 337 | "version": "5.3.9", 338 | "resolved": "https://registry.npmjs.org/@pixi/utils/-/utils-5.3.9.tgz", 339 | "integrity": "sha512-yvwaRo9VtSTAQsEFkYHjz12h3eW5Ww8Emk6XunEOiGPlByvs7AUsDpDGcym7DcKlePszHBSDPOj6gW56pZLzdA==", 340 | "requires": { 341 | "@pixi/constants": "5.3.9", 342 | "@pixi/settings": "5.3.9", 343 | "earcut": "^2.1.5", 344 | "eventemitter3": "^3.1.0", 345 | "url": "^0.11.0" 346 | } 347 | }, 348 | "asn1.js": { 349 | "version": "5.4.1", 350 | "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", 351 | "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", 352 | "dev": true, 353 | "requires": { 354 | "bn.js": "^4.0.0", 355 | "inherits": "^2.0.1", 356 | "minimalistic-assert": "^1.0.0", 357 | "safer-buffer": "^2.1.0" 358 | }, 359 | "dependencies": { 360 | "bn.js": { 361 | "version": "4.12.0", 362 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", 363 | "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", 364 | "dev": true 365 | } 366 | } 367 | }, 368 | "assert": { 369 | "version": "1.5.0", 370 | "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", 371 | "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", 372 | "dev": true, 373 | "requires": { 374 | "object-assign": "^4.1.1", 375 | "util": "0.10.3" 376 | }, 377 | "dependencies": { 378 | "util": { 379 | "version": "0.10.3", 380 | "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", 381 | "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", 382 | "dev": true, 383 | "requires": { 384 | "inherits": "2.0.1" 385 | } 386 | } 387 | } 388 | }, 389 | "async-limiter": { 390 | "version": "1.0.1", 391 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", 392 | "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", 393 | "dev": true 394 | }, 395 | "base64-js": { 396 | "version": "1.5.1", 397 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 398 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 399 | "dev": true 400 | }, 401 | "bn.js": { 402 | "version": "5.2.0", 403 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", 404 | "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", 405 | "dev": true 406 | }, 407 | "brorand": { 408 | "version": "1.1.0", 409 | "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", 410 | "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", 411 | "dev": true 412 | }, 413 | "browserify-aes": { 414 | "version": "1.2.0", 415 | "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", 416 | "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", 417 | "dev": true, 418 | "requires": { 419 | "buffer-xor": "^1.0.3", 420 | "cipher-base": "^1.0.0", 421 | "create-hash": "^1.1.0", 422 | "evp_bytestokey": "^1.0.3", 423 | "inherits": "^2.0.1", 424 | "safe-buffer": "^5.0.1" 425 | } 426 | }, 427 | "browserify-cipher": { 428 | "version": "1.0.1", 429 | "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", 430 | "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", 431 | "dev": true, 432 | "requires": { 433 | "browserify-aes": "^1.0.4", 434 | "browserify-des": "^1.0.0", 435 | "evp_bytestokey": "^1.0.0" 436 | } 437 | }, 438 | "browserify-des": { 439 | "version": "1.0.2", 440 | "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", 441 | "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", 442 | "dev": true, 443 | "requires": { 444 | "cipher-base": "^1.0.1", 445 | "des.js": "^1.0.0", 446 | "inherits": "^2.0.1", 447 | "safe-buffer": "^5.1.2" 448 | } 449 | }, 450 | "browserify-rsa": { 451 | "version": "4.1.0", 452 | "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", 453 | "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", 454 | "dev": true, 455 | "requires": { 456 | "bn.js": "^5.0.0", 457 | "randombytes": "^2.0.1" 458 | } 459 | }, 460 | "browserify-sign": { 461 | "version": "4.2.1", 462 | "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", 463 | "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", 464 | "dev": true, 465 | "requires": { 466 | "bn.js": "^5.1.1", 467 | "browserify-rsa": "^4.0.1", 468 | "create-hash": "^1.2.0", 469 | "create-hmac": "^1.1.7", 470 | "elliptic": "^6.5.3", 471 | "inherits": "^2.0.4", 472 | "parse-asn1": "^5.1.5", 473 | "readable-stream": "^3.6.0", 474 | "safe-buffer": "^5.2.0" 475 | }, 476 | "dependencies": { 477 | "inherits": { 478 | "version": "2.0.4", 479 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 480 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 481 | "dev": true 482 | }, 483 | "readable-stream": { 484 | "version": "3.6.0", 485 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 486 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 487 | "dev": true, 488 | "requires": { 489 | "inherits": "^2.0.3", 490 | "string_decoder": "^1.1.1", 491 | "util-deprecate": "^1.0.1" 492 | } 493 | } 494 | } 495 | }, 496 | "browserify-zlib": { 497 | "version": "0.2.0", 498 | "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", 499 | "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", 500 | "dev": true, 501 | "requires": { 502 | "pako": "~1.0.5" 503 | } 504 | }, 505 | "buffer": { 506 | "version": "4.9.2", 507 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", 508 | "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", 509 | "dev": true, 510 | "requires": { 511 | "base64-js": "^1.0.2", 512 | "ieee754": "^1.1.4", 513 | "isarray": "^1.0.0" 514 | } 515 | }, 516 | "buffer-xor": { 517 | "version": "1.0.3", 518 | "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", 519 | "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", 520 | "dev": true 521 | }, 522 | "builtin-status-codes": { 523 | "version": "3.0.0", 524 | "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", 525 | "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", 526 | "dev": true 527 | }, 528 | "cipher-base": { 529 | "version": "1.0.4", 530 | "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", 531 | "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", 532 | "dev": true, 533 | "requires": { 534 | "inherits": "^2.0.1", 535 | "safe-buffer": "^5.0.1" 536 | } 537 | }, 538 | "collisions": { 539 | "version": "2.0.13", 540 | "resolved": "https://registry.npmjs.org/collisions/-/collisions-2.0.13.tgz", 541 | "integrity": "sha512-KOTVGrIlzTkgmZp/OlYruqVpuAuBGcGTWurLp56n4+9c7NHBYWlF3TtNZc6hTr22GiGPE34+frBugQV4OEmFjQ==" 542 | }, 543 | "console-browserify": { 544 | "version": "1.2.0", 545 | "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", 546 | "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", 547 | "dev": true 548 | }, 549 | "constants-browserify": { 550 | "version": "1.0.0", 551 | "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", 552 | "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", 553 | "dev": true 554 | }, 555 | "core-util-is": { 556 | "version": "1.0.2", 557 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 558 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 559 | "dev": true 560 | }, 561 | "create-ecdh": { 562 | "version": "4.0.4", 563 | "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", 564 | "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", 565 | "dev": true, 566 | "requires": { 567 | "bn.js": "^4.1.0", 568 | "elliptic": "^6.5.3" 569 | }, 570 | "dependencies": { 571 | "bn.js": { 572 | "version": "4.12.0", 573 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", 574 | "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", 575 | "dev": true 576 | } 577 | } 578 | }, 579 | "create-hash": { 580 | "version": "1.2.0", 581 | "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", 582 | "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", 583 | "dev": true, 584 | "requires": { 585 | "cipher-base": "^1.0.1", 586 | "inherits": "^2.0.1", 587 | "md5.js": "^1.3.4", 588 | "ripemd160": "^2.0.1", 589 | "sha.js": "^2.4.0" 590 | } 591 | }, 592 | "create-hmac": { 593 | "version": "1.1.7", 594 | "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", 595 | "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", 596 | "dev": true, 597 | "requires": { 598 | "cipher-base": "^1.0.3", 599 | "create-hash": "^1.1.0", 600 | "inherits": "^2.0.1", 601 | "ripemd160": "^2.0.0", 602 | "safe-buffer": "^5.0.1", 603 | "sha.js": "^2.4.8" 604 | } 605 | }, 606 | "crypto-browserify": { 607 | "version": "3.12.0", 608 | "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", 609 | "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", 610 | "dev": true, 611 | "requires": { 612 | "browserify-cipher": "^1.0.0", 613 | "browserify-sign": "^4.0.0", 614 | "create-ecdh": "^4.0.0", 615 | "create-hash": "^1.1.0", 616 | "create-hmac": "^1.1.0", 617 | "diffie-hellman": "^5.0.0", 618 | "inherits": "^2.0.1", 619 | "pbkdf2": "^3.0.3", 620 | "public-encrypt": "^4.0.0", 621 | "randombytes": "^2.0.0", 622 | "randomfill": "^1.0.3" 623 | } 624 | }, 625 | "des.js": { 626 | "version": "1.0.1", 627 | "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", 628 | "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", 629 | "dev": true, 630 | "requires": { 631 | "inherits": "^2.0.1", 632 | "minimalistic-assert": "^1.0.0" 633 | } 634 | }, 635 | "diffie-hellman": { 636 | "version": "5.0.3", 637 | "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", 638 | "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", 639 | "dev": true, 640 | "requires": { 641 | "bn.js": "^4.1.0", 642 | "miller-rabin": "^4.0.0", 643 | "randombytes": "^2.0.0" 644 | }, 645 | "dependencies": { 646 | "bn.js": { 647 | "version": "4.12.0", 648 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", 649 | "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", 650 | "dev": true 651 | } 652 | } 653 | }, 654 | "domain-browser": { 655 | "version": "1.2.0", 656 | "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", 657 | "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", 658 | "dev": true 659 | }, 660 | "earcut": { 661 | "version": "2.2.2", 662 | "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.2.tgz", 663 | "integrity": "sha512-eZoZPPJcUHnfRZ0PjLvx2qBordSiO8ofC3vt+qACLM95u+4DovnbYNpQtJh0DNsWj8RnxrQytD4WA8gj5cRIaQ==" 664 | }, 665 | "elliptic": { 666 | "version": "6.5.4", 667 | "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", 668 | "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", 669 | "dev": true, 670 | "requires": { 671 | "bn.js": "^4.11.9", 672 | "brorand": "^1.1.0", 673 | "hash.js": "^1.0.0", 674 | "hmac-drbg": "^1.0.1", 675 | "inherits": "^2.0.4", 676 | "minimalistic-assert": "^1.0.1", 677 | "minimalistic-crypto-utils": "^1.0.1" 678 | }, 679 | "dependencies": { 680 | "bn.js": { 681 | "version": "4.12.0", 682 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", 683 | "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", 684 | "dev": true 685 | }, 686 | "inherits": { 687 | "version": "2.0.4", 688 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 689 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 690 | "dev": true 691 | } 692 | } 693 | }, 694 | "es6-promise-polyfill": { 695 | "version": "1.2.0", 696 | "resolved": "https://registry.npmjs.org/es6-promise-polyfill/-/es6-promise-polyfill-1.2.0.tgz", 697 | "integrity": "sha1-84kl8jyz4+jObNqP93T867sJDN4=" 698 | }, 699 | "eventemitter3": { 700 | "version": "3.1.2", 701 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", 702 | "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==" 703 | }, 704 | "events": { 705 | "version": "3.3.0", 706 | "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", 707 | "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", 708 | "dev": true 709 | }, 710 | "evp_bytestokey": { 711 | "version": "1.0.3", 712 | "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", 713 | "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", 714 | "dev": true, 715 | "requires": { 716 | "md5.js": "^1.3.4", 717 | "safe-buffer": "^5.1.1" 718 | } 719 | }, 720 | "hash-base": { 721 | "version": "3.1.0", 722 | "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", 723 | "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", 724 | "dev": true, 725 | "requires": { 726 | "inherits": "^2.0.4", 727 | "readable-stream": "^3.6.0", 728 | "safe-buffer": "^5.2.0" 729 | }, 730 | "dependencies": { 731 | "inherits": { 732 | "version": "2.0.4", 733 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 734 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 735 | "dev": true 736 | }, 737 | "readable-stream": { 738 | "version": "3.6.0", 739 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 740 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 741 | "dev": true, 742 | "requires": { 743 | "inherits": "^2.0.3", 744 | "string_decoder": "^1.1.1", 745 | "util-deprecate": "^1.0.1" 746 | } 747 | } 748 | } 749 | }, 750 | "hash.js": { 751 | "version": "1.1.7", 752 | "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", 753 | "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", 754 | "dev": true, 755 | "requires": { 756 | "inherits": "^2.0.3", 757 | "minimalistic-assert": "^1.0.1" 758 | }, 759 | "dependencies": { 760 | "inherits": { 761 | "version": "2.0.4", 762 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 763 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 764 | "dev": true 765 | } 766 | } 767 | }, 768 | "hmac-drbg": { 769 | "version": "1.0.1", 770 | "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", 771 | "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", 772 | "dev": true, 773 | "requires": { 774 | "hash.js": "^1.0.3", 775 | "minimalistic-assert": "^1.0.0", 776 | "minimalistic-crypto-utils": "^1.0.1" 777 | } 778 | }, 779 | "https-browserify": { 780 | "version": "1.0.0", 781 | "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", 782 | "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", 783 | "dev": true 784 | }, 785 | "ieee754": { 786 | "version": "1.2.1", 787 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 788 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 789 | "dev": true 790 | }, 791 | "inherits": { 792 | "version": "2.0.1", 793 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", 794 | "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", 795 | "dev": true 796 | }, 797 | "isarray": { 798 | "version": "1.0.0", 799 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 800 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 801 | "dev": true 802 | }, 803 | "isexe": { 804 | "version": "2.0.0", 805 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 806 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 807 | "dev": true 808 | }, 809 | "ismobilejs": { 810 | "version": "1.1.1", 811 | "resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz", 812 | "integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw==" 813 | }, 814 | "md5.js": { 815 | "version": "1.3.5", 816 | "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", 817 | "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", 818 | "dev": true, 819 | "requires": { 820 | "hash-base": "^3.0.0", 821 | "inherits": "^2.0.1", 822 | "safe-buffer": "^5.1.2" 823 | } 824 | }, 825 | "miller-rabin": { 826 | "version": "4.0.1", 827 | "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", 828 | "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", 829 | "dev": true, 830 | "requires": { 831 | "bn.js": "^4.0.0", 832 | "brorand": "^1.0.1" 833 | }, 834 | "dependencies": { 835 | "bn.js": { 836 | "version": "4.12.0", 837 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", 838 | "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", 839 | "dev": true 840 | } 841 | } 842 | }, 843 | "mini-signals": { 844 | "version": "1.2.0", 845 | "resolved": "https://registry.npmjs.org/mini-signals/-/mini-signals-1.2.0.tgz", 846 | "integrity": "sha1-RbCAE8X65RokqhqTXNMXye1yHXQ=" 847 | }, 848 | "minimalistic-assert": { 849 | "version": "1.0.1", 850 | "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", 851 | "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", 852 | "dev": true 853 | }, 854 | "minimalistic-crypto-utils": { 855 | "version": "1.0.1", 856 | "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", 857 | "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", 858 | "dev": true 859 | }, 860 | "node-libs-browser": { 861 | "version": "2.2.1", 862 | "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", 863 | "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", 864 | "dev": true, 865 | "requires": { 866 | "assert": "^1.1.1", 867 | "browserify-zlib": "^0.2.0", 868 | "buffer": "^4.3.0", 869 | "console-browserify": "^1.1.0", 870 | "constants-browserify": "^1.0.0", 871 | "crypto-browserify": "^3.11.0", 872 | "domain-browser": "^1.1.1", 873 | "events": "^3.0.0", 874 | "https-browserify": "^1.0.0", 875 | "os-browserify": "^0.3.0", 876 | "path-browserify": "0.0.1", 877 | "process": "^0.11.10", 878 | "punycode": "^1.2.4", 879 | "querystring-es3": "^0.2.0", 880 | "readable-stream": "^2.3.3", 881 | "stream-browserify": "^2.0.1", 882 | "stream-http": "^2.7.2", 883 | "string_decoder": "^1.0.0", 884 | "timers-browserify": "^2.0.4", 885 | "tty-browserify": "0.0.0", 886 | "url": "^0.11.0", 887 | "util": "^0.11.0", 888 | "vm-browserify": "^1.0.1" 889 | } 890 | }, 891 | "object-assign": { 892 | "version": "4.1.1", 893 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 894 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 895 | }, 896 | "os-browserify": { 897 | "version": "0.3.0", 898 | "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", 899 | "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", 900 | "dev": true 901 | }, 902 | "pako": { 903 | "version": "1.0.11", 904 | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", 905 | "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", 906 | "dev": true 907 | }, 908 | "parse-asn1": { 909 | "version": "5.1.6", 910 | "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", 911 | "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", 912 | "dev": true, 913 | "requires": { 914 | "asn1.js": "^5.2.0", 915 | "browserify-aes": "^1.0.0", 916 | "evp_bytestokey": "^1.0.0", 917 | "pbkdf2": "^3.0.3", 918 | "safe-buffer": "^5.1.1" 919 | } 920 | }, 921 | "parse-uri": { 922 | "version": "1.0.3", 923 | "resolved": "https://registry.npmjs.org/parse-uri/-/parse-uri-1.0.3.tgz", 924 | "integrity": "sha512-upMnGxNcm+45So85HoguwZTVZI9u11i36DdxJfGF2HYWS2eh3TIx7+/tTi7qrEq15qzGkVhsKjesau+kCk48pA==" 925 | }, 926 | "path-browserify": { 927 | "version": "0.0.1", 928 | "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", 929 | "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", 930 | "dev": true 931 | }, 932 | "pbkdf2": { 933 | "version": "3.1.2", 934 | "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", 935 | "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", 936 | "dev": true, 937 | "requires": { 938 | "create-hash": "^1.1.2", 939 | "create-hmac": "^1.1.4", 940 | "ripemd160": "^2.0.1", 941 | "safe-buffer": "^5.0.1", 942 | "sha.js": "^2.4.8" 943 | } 944 | }, 945 | "pixi.js": { 946 | "version": "5.3.9", 947 | "resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-5.3.9.tgz", 948 | "integrity": "sha512-MLczwbhFmFBXImy9TlUbjnQb8nQK3Zez/UHs2z3cBqXDLx9wSZ0kwJbeY4XAWuJNy3WeZtqKeDoteonNaDxMUQ==", 949 | "requires": { 950 | "@pixi/accessibility": "5.3.9", 951 | "@pixi/app": "5.3.9", 952 | "@pixi/constants": "5.3.9", 953 | "@pixi/core": "5.3.9", 954 | "@pixi/display": "5.3.9", 955 | "@pixi/extract": "5.3.9", 956 | "@pixi/filter-alpha": "5.3.9", 957 | "@pixi/filter-blur": "5.3.9", 958 | "@pixi/filter-color-matrix": "5.3.9", 959 | "@pixi/filter-displacement": "5.3.9", 960 | "@pixi/filter-fxaa": "5.3.9", 961 | "@pixi/filter-noise": "5.3.9", 962 | "@pixi/graphics": "5.3.9", 963 | "@pixi/interaction": "5.3.9", 964 | "@pixi/loaders": "5.3.9", 965 | "@pixi/math": "5.3.9", 966 | "@pixi/mesh": "5.3.9", 967 | "@pixi/mesh-extras": "5.3.9", 968 | "@pixi/mixin-cache-as-bitmap": "5.3.9", 969 | "@pixi/mixin-get-child-by-name": "5.3.9", 970 | "@pixi/mixin-get-global-position": "5.3.9", 971 | "@pixi/particles": "5.3.9", 972 | "@pixi/polyfill": "5.3.9", 973 | "@pixi/prepare": "5.3.9", 974 | "@pixi/runner": "5.3.9", 975 | "@pixi/settings": "5.3.9", 976 | "@pixi/sprite": "5.3.9", 977 | "@pixi/sprite-animated": "5.3.9", 978 | "@pixi/sprite-tiling": "5.3.9", 979 | "@pixi/spritesheet": "5.3.9", 980 | "@pixi/text": "5.3.9", 981 | "@pixi/text-bitmap": "5.3.9", 982 | "@pixi/ticker": "5.3.9", 983 | "@pixi/utils": "5.3.9" 984 | } 985 | }, 986 | "process": { 987 | "version": "0.11.10", 988 | "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", 989 | "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", 990 | "dev": true 991 | }, 992 | "process-nextick-args": { 993 | "version": "2.0.1", 994 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 995 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", 996 | "dev": true 997 | }, 998 | "public-encrypt": { 999 | "version": "4.0.3", 1000 | "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", 1001 | "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", 1002 | "dev": true, 1003 | "requires": { 1004 | "bn.js": "^4.1.0", 1005 | "browserify-rsa": "^4.0.0", 1006 | "create-hash": "^1.1.0", 1007 | "parse-asn1": "^5.0.0", 1008 | "randombytes": "^2.0.1", 1009 | "safe-buffer": "^5.1.2" 1010 | }, 1011 | "dependencies": { 1012 | "bn.js": { 1013 | "version": "4.12.0", 1014 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", 1015 | "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", 1016 | "dev": true 1017 | } 1018 | } 1019 | }, 1020 | "punycode": { 1021 | "version": "1.3.2", 1022 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", 1023 | "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" 1024 | }, 1025 | "querystring": { 1026 | "version": "0.2.0", 1027 | "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", 1028 | "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" 1029 | }, 1030 | "querystring-es3": { 1031 | "version": "0.2.1", 1032 | "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", 1033 | "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", 1034 | "dev": true 1035 | }, 1036 | "randombytes": { 1037 | "version": "2.1.0", 1038 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 1039 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 1040 | "dev": true, 1041 | "requires": { 1042 | "safe-buffer": "^5.1.0" 1043 | } 1044 | }, 1045 | "randomfill": { 1046 | "version": "1.0.4", 1047 | "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", 1048 | "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", 1049 | "dev": true, 1050 | "requires": { 1051 | "randombytes": "^2.0.5", 1052 | "safe-buffer": "^5.1.0" 1053 | } 1054 | }, 1055 | "readable-stream": { 1056 | "version": "2.3.7", 1057 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 1058 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 1059 | "dev": true, 1060 | "requires": { 1061 | "core-util-is": "~1.0.0", 1062 | "inherits": "~2.0.3", 1063 | "isarray": "~1.0.0", 1064 | "process-nextick-args": "~2.0.0", 1065 | "safe-buffer": "~5.1.1", 1066 | "string_decoder": "~1.1.1", 1067 | "util-deprecate": "~1.0.1" 1068 | }, 1069 | "dependencies": { 1070 | "inherits": { 1071 | "version": "2.0.4", 1072 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1073 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1074 | "dev": true 1075 | }, 1076 | "safe-buffer": { 1077 | "version": "5.1.2", 1078 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1079 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 1080 | "dev": true 1081 | }, 1082 | "string_decoder": { 1083 | "version": "1.1.1", 1084 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1085 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1086 | "dev": true, 1087 | "requires": { 1088 | "safe-buffer": "~5.1.0" 1089 | } 1090 | } 1091 | } 1092 | }, 1093 | "readline-sync": { 1094 | "version": "1.4.10", 1095 | "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", 1096 | "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==", 1097 | "dev": true 1098 | }, 1099 | "resource-loader": { 1100 | "version": "3.0.1", 1101 | "resolved": "https://registry.npmjs.org/resource-loader/-/resource-loader-3.0.1.tgz", 1102 | "integrity": "sha512-fBuCRbEHdLCI1eglzQhUv9Rrdcmqkydr1r6uHE2cYHvRBrcLXeSmbE/qI/urFt8rPr/IGxir3BUwM5kUK8XoyA==", 1103 | "requires": { 1104 | "mini-signals": "^1.2.0", 1105 | "parse-uri": "^1.0.0" 1106 | } 1107 | }, 1108 | "ripemd160": { 1109 | "version": "2.0.2", 1110 | "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", 1111 | "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", 1112 | "dev": true, 1113 | "requires": { 1114 | "hash-base": "^3.0.0", 1115 | "inherits": "^2.0.1" 1116 | } 1117 | }, 1118 | "safe-buffer": { 1119 | "version": "5.2.1", 1120 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1121 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1122 | "dev": true 1123 | }, 1124 | "safer-buffer": { 1125 | "version": "2.1.2", 1126 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1127 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1128 | "dev": true 1129 | }, 1130 | "setimmediate": { 1131 | "version": "1.0.5", 1132 | "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", 1133 | "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", 1134 | "dev": true 1135 | }, 1136 | "sha.js": { 1137 | "version": "2.4.11", 1138 | "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", 1139 | "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", 1140 | "dev": true, 1141 | "requires": { 1142 | "inherits": "^2.0.1", 1143 | "safe-buffer": "^5.0.1" 1144 | } 1145 | }, 1146 | "shadow-cljs": { 1147 | "version": "2.12.5", 1148 | "resolved": "https://registry.npmjs.org/shadow-cljs/-/shadow-cljs-2.12.5.tgz", 1149 | "integrity": "sha512-o3xo3coRgnlkI/iI55ccHjj6AU3F1+ovk3hhK86e3P2JGGOpNTAwsGNxUpMC5JAwS9Nz0v6sSk73hWjEOnm6fQ==", 1150 | "dev": true, 1151 | "requires": { 1152 | "node-libs-browser": "^2.2.1", 1153 | "readline-sync": "^1.4.7", 1154 | "shadow-cljs-jar": "1.3.2", 1155 | "source-map-support": "^0.4.15", 1156 | "which": "^1.3.1", 1157 | "ws": "^3.0.0" 1158 | } 1159 | }, 1160 | "shadow-cljs-jar": { 1161 | "version": "1.3.2", 1162 | "resolved": "https://registry.npmjs.org/shadow-cljs-jar/-/shadow-cljs-jar-1.3.2.tgz", 1163 | "integrity": "sha512-XmeffAZHv8z7451kzeq9oKh8fh278Ak+UIOGGrapyqrFBB773xN8vMQ3O7J7TYLnb9BUwcqadKkmgaq7q6fhZg==", 1164 | "dev": true 1165 | }, 1166 | "source-map": { 1167 | "version": "0.5.7", 1168 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1169 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 1170 | "dev": true 1171 | }, 1172 | "source-map-support": { 1173 | "version": "0.4.18", 1174 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", 1175 | "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", 1176 | "dev": true, 1177 | "requires": { 1178 | "source-map": "^0.5.6" 1179 | } 1180 | }, 1181 | "stream-browserify": { 1182 | "version": "2.0.2", 1183 | "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", 1184 | "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", 1185 | "dev": true, 1186 | "requires": { 1187 | "inherits": "~2.0.1", 1188 | "readable-stream": "^2.0.2" 1189 | } 1190 | }, 1191 | "stream-http": { 1192 | "version": "2.8.3", 1193 | "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", 1194 | "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", 1195 | "dev": true, 1196 | "requires": { 1197 | "builtin-status-codes": "^3.0.0", 1198 | "inherits": "^2.0.1", 1199 | "readable-stream": "^2.3.6", 1200 | "to-arraybuffer": "^1.0.0", 1201 | "xtend": "^4.0.0" 1202 | } 1203 | }, 1204 | "string_decoder": { 1205 | "version": "1.3.0", 1206 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 1207 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 1208 | "dev": true, 1209 | "requires": { 1210 | "safe-buffer": "~5.2.0" 1211 | } 1212 | }, 1213 | "timers-browserify": { 1214 | "version": "2.0.12", 1215 | "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", 1216 | "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", 1217 | "dev": true, 1218 | "requires": { 1219 | "setimmediate": "^1.0.4" 1220 | } 1221 | }, 1222 | "to-arraybuffer": { 1223 | "version": "1.0.1", 1224 | "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", 1225 | "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", 1226 | "dev": true 1227 | }, 1228 | "tty-browserify": { 1229 | "version": "0.0.0", 1230 | "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", 1231 | "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", 1232 | "dev": true 1233 | }, 1234 | "ultron": { 1235 | "version": "1.1.1", 1236 | "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", 1237 | "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", 1238 | "dev": true 1239 | }, 1240 | "url": { 1241 | "version": "0.11.0", 1242 | "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", 1243 | "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", 1244 | "requires": { 1245 | "punycode": "1.3.2", 1246 | "querystring": "0.2.0" 1247 | } 1248 | }, 1249 | "util": { 1250 | "version": "0.11.1", 1251 | "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", 1252 | "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", 1253 | "dev": true, 1254 | "requires": { 1255 | "inherits": "2.0.3" 1256 | }, 1257 | "dependencies": { 1258 | "inherits": { 1259 | "version": "2.0.3", 1260 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 1261 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 1262 | "dev": true 1263 | } 1264 | } 1265 | }, 1266 | "util-deprecate": { 1267 | "version": "1.0.2", 1268 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1269 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 1270 | "dev": true 1271 | }, 1272 | "vm-browserify": { 1273 | "version": "1.1.2", 1274 | "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", 1275 | "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", 1276 | "dev": true 1277 | }, 1278 | "which": { 1279 | "version": "1.3.1", 1280 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1281 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1282 | "dev": true, 1283 | "requires": { 1284 | "isexe": "^2.0.0" 1285 | } 1286 | }, 1287 | "ws": { 1288 | "version": "3.3.3", 1289 | "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", 1290 | "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", 1291 | "dev": true, 1292 | "requires": { 1293 | "async-limiter": "~1.0.0", 1294 | "safe-buffer": "~5.1.0", 1295 | "ultron": "~1.1.0" 1296 | }, 1297 | "dependencies": { 1298 | "safe-buffer": { 1299 | "version": "5.1.2", 1300 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1301 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 1302 | "dev": true 1303 | } 1304 | } 1305 | }, 1306 | "xtend": { 1307 | "version": "4.0.2", 1308 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 1309 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", 1310 | "dev": true 1311 | } 1312 | } 1313 | } 1314 | --------------------------------------------------------------------------------