├── .eslintrc.yml ├── .npmignore ├── README.md ├── bower.json ├── example ├── assets │ ├── background.png │ ├── droid.png │ ├── dude.png │ ├── firstaid.png │ ├── heart.png │ └── rock.png ├── dat.gui.js ├── index.coffee ├── index.js └── phaser-arcade-physics.js ├── index.coffee ├── index.html ├── index.js ├── package.json ├── screenshot.png └── tests ├── .eslintrc.yml ├── index.html ├── tests.coffee └── tests.js /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | browser: yes 3 | extends: 'eslint:recommended' 4 | rules: 5 | indent: 6 | - 'off' 7 | linebreak-style: 8 | - error 9 | - unix 10 | no-console: 11 | - error 12 | - allow: 13 | - warn 14 | no-shadow: 15 | - warn 16 | no-unused-vars: 17 | - error 18 | quotes: 19 | - error 20 | - double 21 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .eslintrc* 2 | *.coffee 3 | *.html 4 | *.png 5 | bower_components 6 | bower.json 7 | example/ 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Screenshot](https://samme.github.io/phaser-sprite-gui/screenshot.png) 2 | 3 | Inspect and manipulate Phaser Sprites (via dat.gui). [Demo](https://samme.github.io/phaser-sprite-gui/) 4 | 5 | Install 6 | ------- 7 | 8 | ### Bower 9 | 10 | ```sh 11 | bower install -S samme/phaser-sprite-gui 12 | ``` 13 | 14 | ### NPM 15 | 16 | ```sh 17 | npm install -S phaser-sprite-gui 18 | ``` 19 | 20 | If [dat.gui/index.js](https://github.com/dataarts/dat.gui/blob/master/index.js) doesn't compile, use [dat.gui/build/dat.gui.js](https://github.com/dataarts/dat.gui/blob/master/build/dat.gui.js) instead. 21 | 22 | ### CommonJS / Webpack 23 | 24 | It should work. The exported constructor is identical to `Phaser.SpriteGUI`. 25 | 26 | ### Drop-in install 27 | 28 | Add [dat.gui.js](https://github.com/dataarts/dat.gui/tree/master/build/dat.gui.js) and [index.js](index.js) before your game scripts. 29 | 30 | Use 31 | --- 32 | 33 | ```javascript 34 | // In create(): 35 | var sprite = game.add.sprite(); 36 | // … 37 | var gui = new Phaser.SpriteGUI(sprite); 38 | 39 | // In shutdown(): 40 | gui.destroy(); 41 | ``` 42 | 43 | ### Options 44 | 45 | #### Pass GUI params 46 | 47 | ```javascript 48 | // Example: 320px wide panel 49 | var gui = new SpriteGUI(sprite, {width: 320}); 50 | ``` 51 | 52 | #### Filter sprite properties 53 | 54 | ```javascript 55 | // Example: Show all properties *except* `body` 56 | var gui = new SpriteGUI(sprite, null, {exclude: ['body']}); 57 | 58 | // Example: Show *only* `body.velocity.x`, `body.velocity.y` 59 | var gui = new SpriteGUI(sprite, null, {include: ['body', 'velocity', 'x', 'y']}); 60 | ``` 61 | 62 | For nested properties, `include` must contain **every** name in the property chain. 63 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phaser-sprite-gui", 3 | "description": "Inspect and manipulate Phaser Sprites (via dat.gui)", 4 | "main": "index.js", 5 | "authors": [ 6 | "samme" 7 | ], 8 | "license": "MIT", 9 | "homepage": "https://github.com/samme/phaser-sprite-gui", 10 | "private": true, 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests", 17 | "*.png", 18 | "*.coffee" 19 | ], 20 | "dependencies": { 21 | "phaser": "^2.6.2", 22 | "dat.gui": "dataarts/dat.gui#^0.6.2" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /example/assets/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samme/phaser-sprite-gui/8be8e6fa11339f768c99cd2b0d5abb36f3ce6e75/example/assets/background.png -------------------------------------------------------------------------------- /example/assets/droid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samme/phaser-sprite-gui/8be8e6fa11339f768c99cd2b0d5abb36f3ce6e75/example/assets/droid.png -------------------------------------------------------------------------------- /example/assets/dude.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samme/phaser-sprite-gui/8be8e6fa11339f768c99cd2b0d5abb36f3ce6e75/example/assets/dude.png -------------------------------------------------------------------------------- /example/assets/firstaid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samme/phaser-sprite-gui/8be8e6fa11339f768c99cd2b0d5abb36f3ce6e75/example/assets/firstaid.png -------------------------------------------------------------------------------- /example/assets/heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samme/phaser-sprite-gui/8be8e6fa11339f768c99cd2b0d5abb36f3ce6e75/example/assets/heart.png -------------------------------------------------------------------------------- /example/assets/rock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samme/phaser-sprite-gui/8be8e6fa11339f768c99cd2b0d5abb36f3ce6e75/example/assets/rock.png -------------------------------------------------------------------------------- /example/index.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | # http://phaser.io/examples/v2/arcade-physics/platformer-basics 4 | 5 | {Phaser} = this 6 | {mixin} = Phaser.Utils 7 | 8 | bg = undefined 9 | caption = undefined 10 | cursors = undefined 11 | droid = undefined 12 | guis = [] 13 | hearts = undefined 14 | jumpButton = undefined 15 | jumpTimer = 0 16 | pack = undefined 17 | player = undefined 18 | rocks = undefined 19 | score = 0 20 | 21 | window.GAME = new (Phaser.Game) 22 | antialias: no 23 | height: 600 24 | renderer: Phaser.CANVAS 25 | # resolution: 1 26 | scaleMode: Phaser.ScaleManager.NO_SCALE 27 | # transparent: false 28 | width: 600 29 | state: 30 | 31 | init: -> 32 | {game} = this 33 | game.forceSingleUpdate = off 34 | game.time.desiredFps = 30 35 | return 36 | 37 | preload: -> 38 | @load.baseURL = "example/assets/" 39 | @load.spritesheet "droid", "droid.png", 32, 32 40 | @load.spritesheet "dude", "dude.png", 32, 48 41 | @load.image "background" 42 | @load.image "firstaid" 43 | @load.image "heart" 44 | @load.image "rock" 45 | return 46 | 47 | create: -> 48 | {arcade} = @physics 49 | Phaser.Canvas.setImageRenderingCrisp @game.canvas, true 50 | arcade.checkCollision = 51 | up: off 52 | down: on 53 | left: off 54 | right: off 55 | arcade.gravity.set 0, 500 56 | @createBg() 57 | @createPlayer() 58 | @createDroid() 59 | @createRocks() 60 | @createPack() 61 | @createHearts() 62 | @createCaption() 63 | player.bringToTop() 64 | droid.bringToTop() 65 | caption.bringToTop() 66 | @addInput() 67 | guis.push new Phaser.SpriteGUI bg, {width: 300, name: "tileSprite"}, {include: ["key", "name", "x", "y", "position", "tilePosition", "tileScale"]} 68 | guis.push new Phaser.SpriteGUI player, {width: 300, name: "sprite"} 69 | guis.push new Phaser.SpriteGUI pack, {width: 300, name: "spriteWithInput"} 70 | return 71 | 72 | update: -> 73 | {world} = @game 74 | {arcade} = @physics 75 | arcade.collide player, rocks 76 | arcade.collide player, droid, -> score += 1 77 | @updatePlayer() 78 | world.wrap droid, droid.width 79 | caption.text = "Score: #{score} • [R]estart" 80 | return 81 | 82 | shutdown: -> 83 | for gui in guis 84 | # console.info "Destroy", gui 85 | gui.destroy() 86 | return 87 | 88 | # Helpers 89 | 90 | addInput: -> 91 | {game} = this 92 | keyboard = @input.keyboard 93 | cursors = keyboard.createCursorKeys() 94 | jumpButton = keyboard.addKey Phaser.Keyboard.SPACEBAR 95 | keyboard.addKey(Phaser.KeyCode.R).onUp.add game.state.restart, game.state 96 | return 97 | 98 | createBg: -> 99 | bg = @add.tileSprite 0, 0, this.game.width, this.game.height, "background" 100 | bg.alpha = 0.5 101 | bg.name = "tileSprite" 102 | bg.tilePosition.x = @rnd.between 0, 120 103 | bg 104 | 105 | createCaption: -> 106 | caption = @add.text 5, 5, "", 107 | fill: "white" 108 | font: "bold 24px monospace" 109 | 110 | createDroid: -> 111 | {physics, world} = this 112 | droid = @add.sprite world.randomX, world.height * 0.5, "droid" 113 | droid.name = "droid" 114 | physics.enable droid 115 | mixin 116 | allowGravity: no 117 | bounce: x: 0.5, y: 0.5 118 | mass: 2 119 | maxVelocity: x: 100, y: 100 120 | velocity: x: 50, y: 0 121 | , droid.body 122 | droid.body.setSize droid.width, droid.height / 2, 0, droid.height / 2 123 | droid.animations.add "!", [ 0, 1, 2, 3 ], 5, true 124 | droid.animations.play "!" 125 | droid 126 | 127 | createHearts: -> 128 | hearts = @add.emitter 0, 0, 1 129 | .setAlpha 0, 1, 1000, "Quad.easeInOut", yes 130 | .setRotation 0, 0 131 | .setScale 0, 1, 0, 1, 1000, "Quad.easeInOut", yes 132 | .setXSpeed 0, 0 133 | .setYSpeed -100, -50 134 | .makeParticles "heart" 135 | hearts.gravity = -500 136 | hearts 137 | 138 | createPack: -> 139 | {world} = this 140 | pack = @add.sprite world.randomX, world.randomY, "firstaid" 141 | pack.name = "pack" 142 | pack.inputEnabled = yes 143 | pack.input.useHandCursor = yes 144 | pack.input.enableDrag() 145 | pack 146 | 147 | createPlayer: -> 148 | player = @add.sprite 32, 32, "dude" 149 | player.name = "player" 150 | @camera.follow player 151 | @physics.enable player 152 | mixin 153 | bounce: x: 0.5, y: 0.25 154 | collideWorldBounds: true 155 | drag: x: 250, y: 0 156 | maxVelocity: x: 250, y: 1000 157 | , player.body 158 | player.body.setSize 8, 32, 12, 16 159 | player.animations.add "left", [ 0, 1, 2, 3 ], 10, true 160 | player.animations.add "turn", [ 4 ], 20, true 161 | player.animations.add "right", [ 5, 6, 7, 8 ], 10, true 162 | player 163 | 164 | createRocks: -> 165 | {physics, world} = this 166 | rocks = @add.group() 167 | r = undefined 168 | i = 4 169 | while i-- > 0 170 | r = @add.sprite world.randomX, (1 - (i * 0.25)) * world.height, "rock" 171 | r.anchor.set 0.5 172 | physics.enable r 173 | r.body.moves = no 174 | r.body.immovable = yes 175 | rocks.add r 176 | rocks 177 | 178 | updatePlayer: -> 179 | {time, world} = @game 180 | maxVelocity = player.body.maxVelocity 181 | velocity = player.body.velocity 182 | animations = player.animations 183 | onFloor = player.body.blocked.down or player.body.touching.down 184 | if cursors.left.isDown 185 | velocity.x -= maxVelocity.x / 10 186 | else if cursors.right.isDown 187 | velocity.x += maxVelocity.x / 10 188 | switch true 189 | when velocity.x > 0 190 | animations.play "right" 191 | when velocity.x < 0 192 | animations.play "left" 193 | else 194 | animations.stop null, true 195 | if jumpButton.isDown and onFloor and time.now > jumpTimer 196 | velocity.y = -maxVelocity.y / 2 197 | jumpTimer = time.now + 500 198 | world.wrap player, null, null, true, false 199 | return 200 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.10.0 2 | (function() { 3 | "use strict"; 4 | var Phaser, bg, caption, cursors, droid, guis, hearts, jumpButton, jumpTimer, mixin, pack, player, rocks, score; 5 | 6 | Phaser = this.Phaser; 7 | 8 | mixin = Phaser.Utils.mixin; 9 | 10 | bg = void 0; 11 | 12 | caption = void 0; 13 | 14 | cursors = void 0; 15 | 16 | droid = void 0; 17 | 18 | guis = []; 19 | 20 | hearts = void 0; 21 | 22 | jumpButton = void 0; 23 | 24 | jumpTimer = 0; 25 | 26 | pack = void 0; 27 | 28 | player = void 0; 29 | 30 | rocks = void 0; 31 | 32 | score = 0; 33 | 34 | window.GAME = new Phaser.Game({ 35 | antialias: false, 36 | height: 600, 37 | renderer: Phaser.CANVAS, 38 | scaleMode: Phaser.ScaleManager.NO_SCALE, 39 | width: 600, 40 | state: { 41 | init: function() { 42 | var game; 43 | game = this.game; 44 | game.forceSingleUpdate = false; 45 | game.time.desiredFps = 30; 46 | }, 47 | preload: function() { 48 | this.load.baseURL = "example/assets/"; 49 | this.load.spritesheet("droid", "droid.png", 32, 32); 50 | this.load.spritesheet("dude", "dude.png", 32, 48); 51 | this.load.image("background"); 52 | this.load.image("firstaid"); 53 | this.load.image("heart"); 54 | this.load.image("rock"); 55 | }, 56 | create: function() { 57 | var arcade; 58 | arcade = this.physics.arcade; 59 | Phaser.Canvas.setImageRenderingCrisp(this.game.canvas, true); 60 | arcade.checkCollision = { 61 | up: false, 62 | down: true, 63 | left: false, 64 | right: false 65 | }; 66 | arcade.gravity.set(0, 500); 67 | this.createBg(); 68 | this.createPlayer(); 69 | this.createDroid(); 70 | this.createRocks(); 71 | this.createPack(); 72 | this.createHearts(); 73 | this.createCaption(); 74 | player.bringToTop(); 75 | droid.bringToTop(); 76 | caption.bringToTop(); 77 | this.addInput(); 78 | guis.push(new Phaser.SpriteGUI(bg, { 79 | width: 300, 80 | name: "tileSprite" 81 | }, { 82 | include: ["key", "name", "x", "y", "position", "tilePosition", "tileScale"] 83 | })); 84 | guis.push(new Phaser.SpriteGUI(player, { 85 | width: 300, 86 | name: "sprite" 87 | })); 88 | guis.push(new Phaser.SpriteGUI(pack, { 89 | width: 300, 90 | name: "spriteWithInput" 91 | })); 92 | }, 93 | update: function() { 94 | var arcade, world; 95 | world = this.game.world; 96 | arcade = this.physics.arcade; 97 | arcade.collide(player, rocks); 98 | arcade.collide(player, droid, function() { 99 | return score += 1; 100 | }); 101 | this.updatePlayer(); 102 | world.wrap(droid, droid.width); 103 | caption.text = "Score: " + score + " • [R]estart"; 104 | }, 105 | shutdown: function() { 106 | var gui, j, len; 107 | for (j = 0, len = guis.length; j < len; j++) { 108 | gui = guis[j]; 109 | gui.destroy(); 110 | } 111 | }, 112 | addInput: function() { 113 | var game, keyboard; 114 | game = this.game; 115 | keyboard = this.input.keyboard; 116 | cursors = keyboard.createCursorKeys(); 117 | jumpButton = keyboard.addKey(Phaser.Keyboard.SPACEBAR); 118 | keyboard.addKey(Phaser.KeyCode.R).onUp.add(game.state.restart, game.state); 119 | }, 120 | createBg: function() { 121 | bg = this.add.tileSprite(0, 0, this.game.width, this.game.height, "background"); 122 | bg.alpha = 0.5; 123 | bg.name = "tileSprite"; 124 | bg.tilePosition.x = this.rnd.between(0, 120); 125 | return bg; 126 | }, 127 | createCaption: function() { 128 | return caption = this.add.text(5, 5, "", { 129 | fill: "white", 130 | font: "bold 24px monospace" 131 | }); 132 | }, 133 | createDroid: function() { 134 | var physics, world; 135 | physics = this.physics, world = this.world; 136 | droid = this.add.sprite(world.randomX, world.height * 0.5, "droid"); 137 | droid.name = "droid"; 138 | physics.enable(droid); 139 | mixin({ 140 | allowGravity: false, 141 | bounce: { 142 | x: 0.5, 143 | y: 0.5 144 | }, 145 | mass: 2, 146 | maxVelocity: { 147 | x: 100, 148 | y: 100 149 | }, 150 | velocity: { 151 | x: 50, 152 | y: 0 153 | } 154 | }, droid.body); 155 | droid.body.setSize(droid.width, droid.height / 2, 0, droid.height / 2); 156 | droid.animations.add("!", [0, 1, 2, 3], 5, true); 157 | droid.animations.play("!"); 158 | return droid; 159 | }, 160 | createHearts: function() { 161 | hearts = this.add.emitter(0, 0, 1).setAlpha(0, 1, 1000, "Quad.easeInOut", true).setRotation(0, 0).setScale(0, 1, 0, 1, 1000, "Quad.easeInOut", true).setXSpeed(0, 0).setYSpeed(-100, -50).makeParticles("heart"); 162 | hearts.gravity = -500; 163 | return hearts; 164 | }, 165 | createPack: function() { 166 | var world; 167 | world = this.world; 168 | pack = this.add.sprite(world.randomX, world.randomY, "firstaid"); 169 | pack.name = "pack"; 170 | pack.inputEnabled = true; 171 | pack.input.useHandCursor = true; 172 | pack.input.enableDrag(); 173 | return pack; 174 | }, 175 | createPlayer: function() { 176 | player = this.add.sprite(32, 32, "dude"); 177 | player.name = "player"; 178 | this.camera.follow(player); 179 | this.physics.enable(player); 180 | mixin({ 181 | bounce: { 182 | x: 0.5, 183 | y: 0.25 184 | }, 185 | collideWorldBounds: true, 186 | drag: { 187 | x: 250, 188 | y: 0 189 | }, 190 | maxVelocity: { 191 | x: 250, 192 | y: 1000 193 | } 194 | }, player.body); 195 | player.body.setSize(8, 32, 12, 16); 196 | player.animations.add("left", [0, 1, 2, 3], 10, true); 197 | player.animations.add("turn", [4], 20, true); 198 | player.animations.add("right", [5, 6, 7, 8], 10, true); 199 | return player; 200 | }, 201 | createRocks: function() { 202 | var i, physics, r, world; 203 | physics = this.physics, world = this.world; 204 | rocks = this.add.group(); 205 | r = void 0; 206 | i = 4; 207 | while (i-- > 0) { 208 | r = this.add.sprite(world.randomX, (1 - (i * 0.25)) * world.height, "rock"); 209 | r.anchor.set(0.5); 210 | physics.enable(r); 211 | r.body.moves = false; 212 | r.body.immovable = true; 213 | rocks.add(r); 214 | } 215 | return rocks; 216 | }, 217 | updatePlayer: function() { 218 | var animations, maxVelocity, onFloor, ref, time, velocity, world; 219 | ref = this.game, time = ref.time, world = ref.world; 220 | maxVelocity = player.body.maxVelocity; 221 | velocity = player.body.velocity; 222 | animations = player.animations; 223 | onFloor = player.body.blocked.down || player.body.touching.down; 224 | if (cursors.left.isDown) { 225 | velocity.x -= maxVelocity.x / 10; 226 | } else if (cursors.right.isDown) { 227 | velocity.x += maxVelocity.x / 10; 228 | } 229 | switch (true) { 230 | case velocity.x > 0: 231 | animations.play("right"); 232 | break; 233 | case velocity.x < 0: 234 | animations.play("left"); 235 | break; 236 | default: 237 | animations.stop(null, true); 238 | } 239 | if (jumpButton.isDown && onFloor && time.now > jumpTimer) { 240 | velocity.y = -maxVelocity.y / 2; 241 | jumpTimer = time.now + 500; 242 | } 243 | world.wrap(player, null, null, true, false); 244 | } 245 | } 246 | }); 247 | 248 | }).call(this); 249 | -------------------------------------------------------------------------------- /index.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | dat = dat or window?.dat or require? "dat.gui" 4 | Phaser = Phaser or window?.Phaser or require? "phaser" 5 | 6 | throw new Error "Can't find `dat`" unless dat 7 | throw new Error "Can't find `Phaser`" unless Phaser 8 | 9 | {isArray} = Array 10 | 11 | {freeze} = Object 12 | 13 | SECOND = 1000 14 | 15 | freezeDeep = (obj) -> 16 | for own val of obj 17 | freezeDeep val if typeof val is "object" 18 | freeze obj 19 | 20 | CONST = freezeDeep 21 | alpha: 22 | range: [0, 1, 0.1] 23 | anchor: 24 | range: [0, 1, 0.1] 25 | angle: 26 | range: [-180, 180, 5] 27 | step: 5 28 | bounce: 29 | range: [0, 1, 0.1] 30 | drag: 31 | range: [0, 1000, 10] 32 | dragDistanceThreshold: 33 | range: [0, 10, 1] 34 | dragOffset: 35 | range: [-100, 100, 5] 36 | dragTimeThreshold: 37 | range: [0, 100, 10] 38 | friction: 39 | range: [0, 1, 0.1] 40 | gravity: 41 | range: [-1000, 1000, 10] 42 | health: 43 | range: [1, 100, 1] 44 | lifespan: 45 | range: [0, 10 * SECOND, 100] 46 | mass: 47 | range: [0.1, 10, 0.1] 48 | maxAngular: 49 | range: [0, 1000, 10] 50 | maxVelocity: 51 | range: [0, 10000, 10] 52 | offset: 53 | range: [-100, 100, 1] 54 | rotation: 55 | range: [-Math.PI, Math.PI, Math.PI / 30] 56 | step: Math.PI / 30 57 | pixelPerfectAlpha: 58 | range: [0, 255, 5] 59 | priorityID: 60 | range: [0, 10, 1] 61 | snap: 62 | range: [0, 100, 5] 63 | snapOffset: 64 | range: [-100, 100, 5] 65 | scale: 66 | range: [-10, 10, 0.1] 67 | min: -10 68 | max: 10 69 | step: 0.1 70 | 71 | addControllerAndSaveNumericValue = (guiContainer, obj, propName, args) -> 72 | controller = guiContainer.add obj, propName, args 73 | controller.onChange saveNumericValue 74 | controller 75 | 76 | addBlendModeController = (guiContainer, obj, propName) -> 77 | addControllerAndSaveNumericValue guiContainer, obj, propName, Phaser.blendModes 78 | 79 | createMap = (arr) -> 80 | map = {} 81 | map[key] = yes for key in arr 82 | map 83 | 84 | saveNumericValue = (newValue) -> 85 | @object[@property] = Number newValue 86 | return 87 | 88 | spriteProps = (sprite) -> 89 | {world} = sprite.game 90 | {bounds} = world 91 | {animations, body, input} = sprite 92 | {width, height} = sprite.texture.frame 93 | scaleRange = [ 94 | sprite.scaleMin or CONST.scale.min 95 | sprite.scaleMax or CONST.scale.max 96 | CONST.scale.step 97 | ] 98 | worldRangeX = [bounds.left, bounds.right, 10] 99 | worldRangeY = [bounds.top, bounds.bottom, 10] 100 | worldRangeWidth = [0, bounds.width, 10] 101 | worldRangeHeight = [0, bounds.height, 10] 102 | worldRect = 103 | x: worldRangeX 104 | y: worldRangeY 105 | width: worldRangeWidth 106 | height: worldRangeHeight 107 | freezeDeep { 108 | alive: yes 109 | alpha: CONST.alpha.range 110 | autoCull: yes 111 | animations: 112 | if animations.currentAnim 113 | paused: yes 114 | stop: yes 115 | updateIfVisible: yes 116 | else 117 | no 118 | anchor: 119 | x: CONST.anchor.range 120 | y: CONST.anchor.range 121 | blendMode: addBlendModeController 122 | bringToTop: yes 123 | body: 124 | if body and body.type is Phaser.Physics.ARCADE 125 | allowGravity: yes 126 | allowRotation: yes 127 | angularAcceleration: [-body.maxAngular, body.maxAngular, CONST.angle.step] 128 | angularDrag: [0, 2 * body.maxAngular, CONST.angle.step] 129 | angularVelocity: [-body.maxAngular, body.maxAngular, CONST.angle.step] 130 | bounce: 131 | x: CONST.bounce.range 132 | y: CONST.bounce.range 133 | collideWorldBounds: yes 134 | drag: 135 | x: CONST.drag.range 136 | y: CONST.drag.range 137 | enable: yes 138 | friction: 139 | x: CONST.friction.range 140 | y: CONST.friction.range 141 | gravity: 142 | x: CONST.gravity.range 143 | y: CONST.gravity.range 144 | immovable: yes 145 | mass: CONST.mass.range 146 | maxAngular: CONST.maxAngular.range 147 | maxVelocity: 148 | x: CONST.maxVelocity.range 149 | y: CONST.maxVelocity.range 150 | moves: yes 151 | offset: 152 | x: CONST.offset.range 153 | y: CONST.offset.range 154 | rotation: CONST.angle.range 155 | skipQuadTree: yes 156 | velocity: 157 | x: [-body.maxVelocity.x, body.maxVelocity.x] 158 | y: [-body.maxVelocity.y, body.maxVelocity.y] 159 | else 160 | no 161 | cacheAsBitmap: yes 162 | cameraOffset: 163 | x: worldRangeX 164 | y: worldRangeY 165 | checkWorldBounds: yes 166 | debug: yes 167 | exists: yes 168 | fixedToCamera: yes 169 | frame: 170 | if typeof sprite.frame is "number" 171 | [0, animations.frameTotal - 1, 1] 172 | else 173 | [animations.frameData.getFrameIndexes()] 174 | frameName: yes 175 | health: [CONST.health.min, sprite.maxHealth, CONST.health.step] 176 | input: 177 | if input 178 | allowHorizontalDrag: yes 179 | allowVerticalDrag: yes 180 | boundsRect: 181 | if input.boundsRect 182 | worldRect 183 | else 184 | no 185 | dragDistanceThreshold: CONST.dragDistanceThreshold.range 186 | draggable: yes 187 | dragOffset: 188 | x: CONST.dragOffset.range 189 | y: CONST.dragOffset.range 190 | dragStopBlocksInputUp: yes 191 | dragTimeThreshold: CONST.dragTimeThreshold.range 192 | bringToTop: yes 193 | enabled: yes 194 | pixelPerfectAlpha: CONST.pixelPerfectAlpha.range 195 | pixelPerfectClick: yes 196 | pixelPerfectOver: yes 197 | priorityID: CONST.priorityID.range 198 | reset: yes 199 | snapOffsetX: CONST.snapOffset.range 200 | snapOffsetY: CONST.snapOffset.range 201 | snapOnDrag: yes 202 | snapOnRelease: yes 203 | snapX: CONST.snap.range 204 | snapY: CONST.snap.range 205 | stop: yes 206 | useHandCursor: yes 207 | else 208 | no 209 | key: yes 210 | kill: yes 211 | lifespan: CONST.lifespan.range 212 | maxHealth: CONST.health.range 213 | moveDown: yes 214 | moveUp: yes 215 | name: yes 216 | outOfBoundsKill: yes 217 | outOfCameraBoundsKill: yes 218 | pivot: 219 | x: [-bounds.width, bounds.width, 10] 220 | y: [-bounds.height, bounds.height, 10] 221 | renderable: yes 222 | reset: yes 223 | revive: yes 224 | rotation: CONST.rotation.range 225 | scale: 226 | x: scaleRange 227 | y: scaleRange 228 | sendToBack: yes 229 | smoothed: yes 230 | tilePosition: 231 | if sprite.tilePosition 232 | x: [0, width, 1] 233 | y: [0, height, 1] 234 | else 235 | no 236 | tileScale: 237 | if sprite.tileScale 238 | x: CONST.scale.range 239 | y: CONST.scale.range 240 | else 241 | no 242 | tint: yes 243 | visible: yes 244 | x: worldRangeX 245 | y: worldRangeY 246 | z: yes 247 | } 248 | 249 | freeze class SpriteGUI extends dat.GUI 250 | 251 | exclude: null 252 | 253 | include: null 254 | 255 | constructor: (@sprite, params = {}, options = {}) -> 256 | super params 257 | if options 258 | if options.include 259 | @include = createMap options.include 260 | @filter = @filterInclude 261 | else if options.exclude 262 | @exclude = createMap options.exclude 263 | @filter = @filterExclude 264 | @addAll() 265 | 266 | add: (obj, prop) -> 267 | val = obj[prop] 268 | unless val? 269 | console.warn "Skipping property '#{prop}': #{val}" 270 | return 271 | else 272 | super 273 | 274 | addAll: -> 275 | @addProps this, @sprite, spriteProps @sprite 276 | return 277 | 278 | addProps: (guiContainer, obj, props) -> 279 | for name, args of props 280 | @addProp guiContainer, obj, name, args 281 | guiContainer 282 | 283 | addProp: (guiContainer, obj, name, args) -> 284 | if args is no or not @filter name 285 | return 286 | val = obj[name] 287 | unless val? 288 | console.warn "Skipping property '#{name}': #{val}" 289 | return 290 | if typeof args is "function" 291 | result = args.call null, guiContainer, obj, name 292 | args = if isArray result then result else no 293 | switch 294 | when args is no 295 | return 296 | when args is yes 297 | field = guiContainer.add obj, name 298 | unless typeof val is "function" 299 | field.listen() 300 | when isArray args 301 | addArgs = [obj, name].concat args 302 | guiContainer.add.apply(guiContainer, addArgs).listen() 303 | when typeof args is "object" 304 | @addProps guiContainer.addFolder(name), obj[name], args 305 | else 306 | console.warn "Nothing to do: #{args}" 307 | guiContainer 308 | 309 | filter: -> 310 | yes 311 | 312 | filterExclude: (name) -> 313 | not @exclude[name] 314 | 315 | filterInclude: (name) -> 316 | @include[name] 317 | 318 | Phaser.SpriteGUI = SpriteGUI 319 | window?.SpriteGUI = SpriteGUI 320 | module?.exports = SpriteGUI 321 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | Phaser Sprite GUI demo 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.10.0 2 | (function() { 3 | "use strict"; 4 | var CONST, Phaser, SECOND, SpriteGUI, addBlendModeController, addControllerAndSaveNumericValue, createMap, dat, freeze, freezeDeep, isArray, saveNumericValue, spriteProps, 5 | hasProp = {}.hasOwnProperty, 6 | extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; 7 | 8 | dat = dat || (typeof window !== "undefined" && window !== null ? window.dat : void 0) || (typeof require === "function" ? require("dat.gui") : void 0); 9 | 10 | Phaser = Phaser || (typeof window !== "undefined" && window !== null ? window.Phaser : void 0) || (typeof require === "function" ? require("phaser") : void 0); 11 | 12 | if (!dat) { 13 | throw new Error("Can't find `dat`"); 14 | } 15 | 16 | if (!Phaser) { 17 | throw new Error("Can't find `Phaser`"); 18 | } 19 | 20 | isArray = Array.isArray; 21 | 22 | freeze = Object.freeze; 23 | 24 | SECOND = 1000; 25 | 26 | freezeDeep = function(obj) { 27 | var val; 28 | for (val in obj) { 29 | if (!hasProp.call(obj, val)) continue; 30 | if (typeof val === "object") { 31 | freezeDeep(val); 32 | } 33 | } 34 | return freeze(obj); 35 | }; 36 | 37 | CONST = freezeDeep({ 38 | alpha: { 39 | range: [0, 1, 0.1] 40 | }, 41 | anchor: { 42 | range: [0, 1, 0.1] 43 | }, 44 | angle: { 45 | range: [-180, 180, 5], 46 | step: 5 47 | }, 48 | bounce: { 49 | range: [0, 1, 0.1] 50 | }, 51 | drag: { 52 | range: [0, 1000, 10] 53 | }, 54 | dragDistanceThreshold: { 55 | range: [0, 10, 1] 56 | }, 57 | dragOffset: { 58 | range: [-100, 100, 5] 59 | }, 60 | dragTimeThreshold: { 61 | range: [0, 100, 10] 62 | }, 63 | friction: { 64 | range: [0, 1, 0.1] 65 | }, 66 | gravity: { 67 | range: [-1000, 1000, 10] 68 | }, 69 | health: { 70 | range: [1, 100, 1] 71 | }, 72 | lifespan: { 73 | range: [0, 10 * SECOND, 100] 74 | }, 75 | mass: { 76 | range: [0.1, 10, 0.1] 77 | }, 78 | maxAngular: { 79 | range: [0, 1000, 10] 80 | }, 81 | maxVelocity: { 82 | range: [0, 10000, 10] 83 | }, 84 | offset: { 85 | range: [-100, 100, 1] 86 | }, 87 | rotation: { 88 | range: [-Math.PI, Math.PI, Math.PI / 30], 89 | step: Math.PI / 30 90 | }, 91 | pixelPerfectAlpha: { 92 | range: [0, 255, 5] 93 | }, 94 | priorityID: { 95 | range: [0, 10, 1] 96 | }, 97 | snap: { 98 | range: [0, 100, 5] 99 | }, 100 | snapOffset: { 101 | range: [-100, 100, 5] 102 | }, 103 | scale: { 104 | range: [-10, 10, 0.1], 105 | min: -10, 106 | max: 10, 107 | step: 0.1 108 | } 109 | }); 110 | 111 | addControllerAndSaveNumericValue = function(guiContainer, obj, propName, args) { 112 | var controller; 113 | controller = guiContainer.add(obj, propName, args); 114 | controller.onChange(saveNumericValue); 115 | return controller; 116 | }; 117 | 118 | addBlendModeController = function(guiContainer, obj, propName) { 119 | return addControllerAndSaveNumericValue(guiContainer, obj, propName, Phaser.blendModes); 120 | }; 121 | 122 | createMap = function(arr) { 123 | var i, key, len, map; 124 | map = {}; 125 | for (i = 0, len = arr.length; i < len; i++) { 126 | key = arr[i]; 127 | map[key] = true; 128 | } 129 | return map; 130 | }; 131 | 132 | saveNumericValue = function(newValue) { 133 | this.object[this.property] = Number(newValue); 134 | }; 135 | 136 | spriteProps = function(sprite) { 137 | var animations, body, bounds, height, input, ref, scaleRange, width, world, worldRangeHeight, worldRangeWidth, worldRangeX, worldRangeY, worldRect; 138 | world = sprite.game.world; 139 | bounds = world.bounds; 140 | animations = sprite.animations, body = sprite.body, input = sprite.input; 141 | ref = sprite.texture.frame, width = ref.width, height = ref.height; 142 | scaleRange = [sprite.scaleMin || CONST.scale.min, sprite.scaleMax || CONST.scale.max, CONST.scale.step]; 143 | worldRangeX = [bounds.left, bounds.right, 10]; 144 | worldRangeY = [bounds.top, bounds.bottom, 10]; 145 | worldRangeWidth = [0, bounds.width, 10]; 146 | worldRangeHeight = [0, bounds.height, 10]; 147 | worldRect = { 148 | x: worldRangeX, 149 | y: worldRangeY, 150 | width: worldRangeWidth, 151 | height: worldRangeHeight 152 | }; 153 | return freezeDeep({ 154 | alive: true, 155 | alpha: CONST.alpha.range, 156 | autoCull: true, 157 | animations: animations.currentAnim ? { 158 | paused: true, 159 | stop: true, 160 | updateIfVisible: true 161 | } : false, 162 | anchor: { 163 | x: CONST.anchor.range, 164 | y: CONST.anchor.range 165 | }, 166 | blendMode: addBlendModeController, 167 | bringToTop: true, 168 | body: body && body.type === Phaser.Physics.ARCADE ? { 169 | allowGravity: true, 170 | allowRotation: true, 171 | angularAcceleration: [-body.maxAngular, body.maxAngular, CONST.angle.step], 172 | angularDrag: [0, 2 * body.maxAngular, CONST.angle.step], 173 | angularVelocity: [-body.maxAngular, body.maxAngular, CONST.angle.step], 174 | bounce: { 175 | x: CONST.bounce.range, 176 | y: CONST.bounce.range 177 | }, 178 | collideWorldBounds: true, 179 | drag: { 180 | x: CONST.drag.range, 181 | y: CONST.drag.range 182 | }, 183 | enable: true, 184 | friction: { 185 | x: CONST.friction.range, 186 | y: CONST.friction.range 187 | }, 188 | gravity: { 189 | x: CONST.gravity.range, 190 | y: CONST.gravity.range 191 | }, 192 | immovable: true, 193 | mass: CONST.mass.range, 194 | maxAngular: CONST.maxAngular.range, 195 | maxVelocity: { 196 | x: CONST.maxVelocity.range, 197 | y: CONST.maxVelocity.range 198 | }, 199 | moves: true, 200 | offset: { 201 | x: CONST.offset.range, 202 | y: CONST.offset.range 203 | }, 204 | rotation: CONST.angle.range, 205 | skipQuadTree: true, 206 | velocity: { 207 | x: [-body.maxVelocity.x, body.maxVelocity.x], 208 | y: [-body.maxVelocity.y, body.maxVelocity.y] 209 | } 210 | } : false, 211 | cacheAsBitmap: true, 212 | cameraOffset: { 213 | x: worldRangeX, 214 | y: worldRangeY 215 | }, 216 | checkWorldBounds: true, 217 | debug: true, 218 | exists: true, 219 | fixedToCamera: true, 220 | frame: typeof sprite.frame === "number" ? [0, animations.frameTotal - 1, 1] : [animations.frameData.getFrameIndexes()], 221 | frameName: true, 222 | health: [CONST.health.min, sprite.maxHealth, CONST.health.step], 223 | input: input ? { 224 | allowHorizontalDrag: true, 225 | allowVerticalDrag: true, 226 | boundsRect: input.boundsRect ? worldRect : false, 227 | dragDistanceThreshold: CONST.dragDistanceThreshold.range, 228 | draggable: true, 229 | dragOffset: { 230 | x: CONST.dragOffset.range, 231 | y: CONST.dragOffset.range 232 | }, 233 | dragStopBlocksInputUp: true, 234 | dragTimeThreshold: CONST.dragTimeThreshold.range, 235 | bringToTop: true, 236 | enabled: true, 237 | pixelPerfectAlpha: CONST.pixelPerfectAlpha.range, 238 | pixelPerfectClick: true, 239 | pixelPerfectOver: true, 240 | priorityID: CONST.priorityID.range, 241 | reset: true, 242 | snapOffsetX: CONST.snapOffset.range, 243 | snapOffsetY: CONST.snapOffset.range, 244 | snapOnDrag: true, 245 | snapOnRelease: true, 246 | snapX: CONST.snap.range, 247 | snapY: CONST.snap.range, 248 | stop: true, 249 | useHandCursor: true 250 | } : false, 251 | key: true, 252 | kill: true, 253 | lifespan: CONST.lifespan.range, 254 | maxHealth: CONST.health.range, 255 | moveDown: true, 256 | moveUp: true, 257 | name: true, 258 | outOfBoundsKill: true, 259 | outOfCameraBoundsKill: true, 260 | pivot: { 261 | x: [-bounds.width, bounds.width, 10], 262 | y: [-bounds.height, bounds.height, 10] 263 | }, 264 | renderable: true, 265 | reset: true, 266 | revive: true, 267 | rotation: CONST.rotation.range, 268 | scale: { 269 | x: scaleRange, 270 | y: scaleRange 271 | }, 272 | sendToBack: true, 273 | smoothed: true, 274 | tilePosition: sprite.tilePosition ? { 275 | x: [0, width, 1], 276 | y: [0, height, 1] 277 | } : false, 278 | tileScale: sprite.tileScale ? { 279 | x: CONST.scale.range, 280 | y: CONST.scale.range 281 | } : false, 282 | tint: true, 283 | visible: true, 284 | x: worldRangeX, 285 | y: worldRangeY, 286 | z: true 287 | }); 288 | }; 289 | 290 | freeze(SpriteGUI = (function(superClass) { 291 | extend(SpriteGUI, superClass); 292 | 293 | SpriteGUI.prototype.exclude = null; 294 | 295 | SpriteGUI.prototype.include = null; 296 | 297 | function SpriteGUI(sprite1, params, options) { 298 | this.sprite = sprite1; 299 | if (params == null) { 300 | params = {}; 301 | } 302 | if (options == null) { 303 | options = {}; 304 | } 305 | SpriteGUI.__super__.constructor.call(this, params); 306 | if (options) { 307 | if (options.include) { 308 | this.include = createMap(options.include); 309 | this.filter = this.filterInclude; 310 | } else if (options.exclude) { 311 | this.exclude = createMap(options.exclude); 312 | this.filter = this.filterExclude; 313 | } 314 | } 315 | this.addAll(); 316 | } 317 | 318 | SpriteGUI.prototype.add = function(obj, prop) { 319 | var val; 320 | val = obj[prop]; 321 | if (val == null) { 322 | console.warn("Skipping property '" + prop + "': " + val); 323 | } else { 324 | return SpriteGUI.__super__.add.apply(this, arguments); 325 | } 326 | }; 327 | 328 | SpriteGUI.prototype.addAll = function() { 329 | this.addProps(this, this.sprite, spriteProps(this.sprite)); 330 | }; 331 | 332 | SpriteGUI.prototype.addProps = function(guiContainer, obj, props) { 333 | var args, name; 334 | for (name in props) { 335 | args = props[name]; 336 | this.addProp(guiContainer, obj, name, args); 337 | } 338 | return guiContainer; 339 | }; 340 | 341 | SpriteGUI.prototype.addProp = function(guiContainer, obj, name, args) { 342 | var addArgs, field, result, val; 343 | if (args === false || !this.filter(name)) { 344 | return; 345 | } 346 | val = obj[name]; 347 | if (val == null) { 348 | console.warn("Skipping property '" + name + "': " + val); 349 | return; 350 | } 351 | if (typeof args === "function") { 352 | result = args.call(null, guiContainer, obj, name); 353 | args = isArray(result) ? result : false; 354 | } 355 | switch (false) { 356 | case args !== false: 357 | return; 358 | case args !== true: 359 | field = guiContainer.add(obj, name); 360 | if (typeof val !== "function") { 361 | field.listen(); 362 | } 363 | break; 364 | case !isArray(args): 365 | addArgs = [obj, name].concat(args); 366 | guiContainer.add.apply(guiContainer, addArgs).listen(); 367 | break; 368 | case typeof args !== "object": 369 | this.addProps(guiContainer.addFolder(name), obj[name], args); 370 | break; 371 | default: 372 | console.warn("Nothing to do: " + args); 373 | } 374 | return guiContainer; 375 | }; 376 | 377 | SpriteGUI.prototype.filter = function() { 378 | return true; 379 | }; 380 | 381 | SpriteGUI.prototype.filterExclude = function(name) { 382 | return !this.exclude[name]; 383 | }; 384 | 385 | SpriteGUI.prototype.filterInclude = function(name) { 386 | return this.include[name]; 387 | }; 388 | 389 | return SpriteGUI; 390 | 391 | })(dat.GUI)); 392 | 393 | Phaser.SpriteGUI = SpriteGUI; 394 | 395 | if (typeof window !== "undefined" && window !== null) { 396 | window.SpriteGUI = SpriteGUI; 397 | } 398 | 399 | if (typeof module !== "undefined" && module !== null) { 400 | module.exports = SpriteGUI; 401 | } 402 | 403 | }).call(this); 404 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phaser-sprite-gui", 3 | "version": "0.7.1", 4 | "description": "Inspect and manipulate Phaser Sprites (via dat.gui)", 5 | "main": "index.js", 6 | "scripts": { 7 | "prestart": "cp -v node_modules/dat.gui/build/dat.gui.js{,.map} example/; open index.html", 8 | "start": "coffeebar --watch *.coffee example", 9 | "preversion": "eslint *.js example/index.js", 10 | "pub": "np --no-cleanup" 11 | }, 12 | "author": "samme", 13 | "license": "MIT", 14 | "dependencies": { 15 | "dat.gui": "github:dataarts/dat.gui", 16 | "phaser": "^2.6.2" 17 | }, 18 | "devDependencies": { 19 | "chai": "^3.5.0", 20 | "coffeebar": "^1.0.0", 21 | "mocha": "^3.2.0" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git+https://github.com/samme/phaser-sprite-gui.git" 26 | }, 27 | "bugs": { 28 | "url": "https://github.com/samme/phaser-sprite-gui/issues" 29 | }, 30 | "homepage": "https://github.com/samme/phaser-sprite-gui#readme", 31 | "directories": { 32 | "example": "example" 33 | }, 34 | "keywords": [ 35 | "phaser" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samme/phaser-sprite-gui/8be8e6fa11339f768c99cd2b0d5abb36f3ce6e75/screenshot.png -------------------------------------------------------------------------------- /tests/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | browser: yes 3 | mocha: yes 4 | extends: 'eslint:recommended' 5 | globals: 6 | chai: no 7 | Phaser: no 8 | SpriteGUI: no 9 | rules: 10 | indent: 11 | - 'off' 12 | no-console: 13 | - error 14 | no-shadow: 15 | - error 16 | no-unused-vars: 17 | - error 18 | quotes: 19 | - error 20 | - double 21 | -------------------------------------------------------------------------------- /tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | SpriteGUI Tests 4 | 5 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tests/tests.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | {expect} = chai 4 | 5 | DEFAULT_IMAGE = "__default" 6 | IMAGE = 7 | key: "../example/assets/droid.png" 8 | SPRITESHEET = 9 | key: "../example/assets/dude.png" 10 | width: 32 11 | height: 48 12 | 13 | describe "hooks", -> 14 | 15 | game = null 16 | 17 | before "new game", (done) -> 18 | 19 | game = new Phaser.Game 100, 100, Phaser.HEADLESS 20 | game.state.add "boot", 21 | init: -> game.raf.stop(); Phaser.Canvas.removeFromDOM game.canvas; done() 22 | create: -> console.log "boot.create" 23 | game.state.start "boot" 24 | 25 | after "destroy game", -> 26 | 27 | game.destroy() 28 | 29 | afterEach "clear state", -> 30 | 31 | game.state.clearCurrentState() 32 | 33 | describe "window", -> 34 | 35 | it "has dat", -> 36 | 37 | expect(window).to.have.property("dat").that.is.an.object 38 | 39 | it "has Phaser", -> 40 | 41 | expect(window).to.have.property("Phaser").that.is.an.object 42 | 43 | it "has SpriteGUI", -> 44 | 45 | expect(window).to.have.property("SpriteGUI").that.is.a.function 46 | 47 | describe "Phaser", -> 48 | 49 | it "is version 2.6.2", -> 50 | 51 | expect(Phaser).to.have.property("VERSION").that.equals "2.6.2" 52 | 53 | describe "a Sprite", -> 54 | 55 | it "s key is '__default'", -> 56 | 57 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 58 | expect(sprite).to.have.property("key").that.equals "__default" 59 | 60 | it "has a valid texture", -> 61 | 62 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 63 | expect(sprite.texture).to.have.property("valid").that.is.true 64 | 65 | it "has a frame", -> 66 | 67 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 68 | expect(sprite).to.have.property("frame").that.equals 0 69 | 70 | it "has no frameName", -> 71 | 72 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 73 | expect(sprite).to.have.property("frameName").that.is.null 74 | 75 | it "has an Animation Manager", -> 76 | 77 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 78 | expect(sprite).to.have.property("animations").that.is.an.instanceOf Phaser.AnimationManager 79 | 80 | describe "sprite.animations", -> 81 | 82 | it "is loaded", -> 83 | 84 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 85 | expect(sprite.animations).to.have.property("isLoaded").that.is.true 86 | 87 | it "has a frameTotal", -> 88 | 89 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 90 | expect(sprite.animations).to.have.property("frameTotal").that.equals 1 91 | 92 | it "has frame indexes", -> 93 | 94 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 95 | expect(sprite.animations.frameData.getFrameIndexes()).to.be.an("array").with.lengthOf 1 96 | 97 | describe "SpriteGUI", -> 98 | 99 | it "is a function", -> 100 | 101 | expect(SpriteGUI).to.be.a.function 102 | 103 | describe "new SpriteGUI", -> 104 | 105 | it "returns a SpriteGUI instance", -> 106 | 107 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 108 | gui = new SpriteGUI sprite 109 | expect(gui).to.be.an.instanceOf SpriteGUI 110 | gui.destroy() 111 | 112 | it "accepts a multi-frame Sprite" 113 | 114 | it "accepts a physics-enabled Sprite", -> 115 | 116 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 117 | game.physics.enable sprite 118 | expect(sprite.body).to.be.an.instanceOf Phaser.Physics.Arcade.Body 119 | gui = new SpriteGUI sprite 120 | expect(gui).to.be.an.instanceOf SpriteGUI 121 | gui.destroy() 122 | 123 | it "accepts an input-enabled Sprite", -> 124 | 125 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 126 | sprite.inputEnabled = yes 127 | expect(sprite.input).to.be.an.instanceOf Phaser.InputHandler 128 | gui = new SpriteGUI sprite 129 | expect(gui).to.be.an.instanceOf SpriteGUI 130 | gui.destroy() 131 | 132 | it "might accept an Image", -> 133 | 134 | img = game.add.image 0, 0, DEFAULT_IMAGE 135 | gui = new SpriteGUI img 136 | expect(gui).to.be.an.instanceOf SpriteGUI 137 | gui.destroy() 138 | 139 | it "might accept a TileSprite", -> 140 | 141 | tileSprite = game.add.tileSprite 0, 0, 100, 100, DEFAULT_IMAGE 142 | gui = new SpriteGUI tileSprite 143 | expect(gui).to.be.an.instanceOf SpriteGUI 144 | gui.destroy() 145 | 146 | describe "autoPlace", -> 147 | 148 | it "sets gui.autoPlace", -> 149 | 150 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 151 | gui = new SpriteGUI sprite, {autoPlace: yes} 152 | expect(gui).to.have.property("autoPlace").that.is.true 153 | gui.destroy() 154 | 155 | it "sets gui.scrollable", -> 156 | 157 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 158 | gui = new SpriteGUI sprite, {autoPlace: yes} 159 | expect(gui).to.have.property("scrollable").that.is.true 160 | gui.destroy() 161 | 162 | describe "autoPlace=false", -> 163 | 164 | it "sets gui.autoPlace", -> 165 | 166 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 167 | gui = new SpriteGUI sprite, {autoPlace: no} 168 | expect(gui).to.have.property("autoPlace").that.is.false 169 | gui.destroy() 170 | 171 | it "doesn't set gui.scrollable", -> 172 | 173 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 174 | gui = new SpriteGUI sprite, {autoPlace: no} 175 | expect(gui).to.have.property("scrollable").that.is.undefined 176 | gui.destroy() 177 | 178 | describe "closeOnTop", -> 179 | 180 | it "sets gui.closeOnTop", -> 181 | 182 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 183 | gui = new SpriteGUI sprite, {closeOnTop: yes} 184 | expect(gui).to.have.property("closeOnTop").that.is.true 185 | gui.destroy() 186 | 187 | describe "width", -> 188 | 189 | it "sets gui.width", -> 190 | 191 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 192 | gui = new SpriteGUI sprite, {width: 320} 193 | expect(gui).to.have.property("width").that.is.within 320, 321 194 | gui.destroy() 195 | 196 | describe "include", -> 197 | 198 | it "sets gui.include", -> 199 | 200 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 201 | gui = new SpriteGUI sprite, null, {include: ["key"]} 202 | expect(gui).to.have.property("include").that.deep.equals {key: yes} 203 | gui.destroy() 204 | 205 | it "uses filterInclude", -> 206 | 207 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 208 | gui = new SpriteGUI sprite, null, {include: ["key"]} 209 | expect(gui.filter).to.equal SpriteGUI::filterInclude 210 | gui.destroy() 211 | 212 | describe "exclude", -> 213 | 214 | it "sets gui.exclude", -> 215 | 216 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 217 | gui = new SpriteGUI sprite, null, {exclude: ["key"]} 218 | expect(gui).to.have.property("exclude").that.deep.equals {key: yes} 219 | gui.destroy() 220 | 221 | it "uses filterExclude", -> 222 | 223 | sprite = game.add.sprite 0, 0, DEFAULT_IMAGE 224 | gui = new SpriteGUI sprite, null, {exclude: ["key"]} 225 | expect(gui.filter).to.equal SpriteGUI::filterExclude 226 | gui.destroy() 227 | -------------------------------------------------------------------------------- /tests/tests.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.10.0 2 | (function() { 3 | "use strict"; 4 | var DEFAULT_IMAGE, IMAGE, SPRITESHEET, expect; 5 | 6 | expect = chai.expect; 7 | 8 | DEFAULT_IMAGE = "__default"; 9 | 10 | IMAGE = { 11 | key: "../example/assets/droid.png" 12 | }; 13 | 14 | SPRITESHEET = { 15 | key: "../example/assets/dude.png", 16 | width: 32, 17 | height: 48 18 | }; 19 | 20 | describe("hooks", function() { 21 | var game; 22 | game = null; 23 | before("new game", function(done) { 24 | game = new Phaser.Game(100, 100, Phaser.HEADLESS); 25 | game.state.add("boot", { 26 | init: function() { 27 | game.raf.stop(); 28 | Phaser.Canvas.removeFromDOM(game.canvas); 29 | return done(); 30 | }, 31 | create: function() { 32 | return console.log("boot.create"); 33 | } 34 | }); 35 | return game.state.start("boot"); 36 | }); 37 | after("destroy game", function() { 38 | return game.destroy(); 39 | }); 40 | afterEach("clear state", function() { 41 | return game.state.clearCurrentState(); 42 | }); 43 | describe("window", function() { 44 | it("has dat", function() { 45 | return expect(window).to.have.property("dat").that.is.an.object; 46 | }); 47 | it("has Phaser", function() { 48 | return expect(window).to.have.property("Phaser").that.is.an.object; 49 | }); 50 | return it("has SpriteGUI", function() { 51 | return expect(window).to.have.property("SpriteGUI").that.is.a["function"]; 52 | }); 53 | }); 54 | describe("Phaser", function() { 55 | return it("is version 2.6.2", function() { 56 | return expect(Phaser).to.have.property("VERSION").that.equals("2.6.2"); 57 | }); 58 | }); 59 | describe("a Sprite", function() { 60 | it("s key is '__default'", function() { 61 | var sprite; 62 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 63 | return expect(sprite).to.have.property("key").that.equals("__default"); 64 | }); 65 | it("has a valid texture", function() { 66 | var sprite; 67 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 68 | return expect(sprite.texture).to.have.property("valid").that.is["true"]; 69 | }); 70 | it("has a frame", function() { 71 | var sprite; 72 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 73 | return expect(sprite).to.have.property("frame").that.equals(0); 74 | }); 75 | it("has no frameName", function() { 76 | var sprite; 77 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 78 | return expect(sprite).to.have.property("frameName").that.is["null"]; 79 | }); 80 | it("has an Animation Manager", function() { 81 | var sprite; 82 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 83 | return expect(sprite).to.have.property("animations").that.is.an.instanceOf(Phaser.AnimationManager); 84 | }); 85 | return describe("sprite.animations", function() { 86 | it("is loaded", function() { 87 | var sprite; 88 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 89 | return expect(sprite.animations).to.have.property("isLoaded").that.is["true"]; 90 | }); 91 | it("has a frameTotal", function() { 92 | var sprite; 93 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 94 | return expect(sprite.animations).to.have.property("frameTotal").that.equals(1); 95 | }); 96 | return it("has frame indexes", function() { 97 | var sprite; 98 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 99 | return expect(sprite.animations.frameData.getFrameIndexes()).to.be.an("array")["with"].lengthOf(1); 100 | }); 101 | }); 102 | }); 103 | return describe("SpriteGUI", function() { 104 | it("is a function", function() { 105 | return expect(SpriteGUI).to.be.a["function"]; 106 | }); 107 | return describe("new SpriteGUI", function() { 108 | it("returns a SpriteGUI instance", function() { 109 | var gui, sprite; 110 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 111 | gui = new SpriteGUI(sprite); 112 | expect(gui).to.be.an.instanceOf(SpriteGUI); 113 | return gui.destroy(); 114 | }); 115 | it("accepts a multi-frame Sprite"); 116 | it("accepts a physics-enabled Sprite", function() { 117 | var gui, sprite; 118 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 119 | game.physics.enable(sprite); 120 | expect(sprite.body).to.be.an.instanceOf(Phaser.Physics.Arcade.Body); 121 | gui = new SpriteGUI(sprite); 122 | expect(gui).to.be.an.instanceOf(SpriteGUI); 123 | return gui.destroy(); 124 | }); 125 | it("accepts an input-enabled Sprite", function() { 126 | var gui, sprite; 127 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 128 | sprite.inputEnabled = true; 129 | expect(sprite.input).to.be.an.instanceOf(Phaser.InputHandler); 130 | gui = new SpriteGUI(sprite); 131 | expect(gui).to.be.an.instanceOf(SpriteGUI); 132 | return gui.destroy(); 133 | }); 134 | it("might accept an Image", function() { 135 | var gui, img; 136 | img = game.add.image(0, 0, DEFAULT_IMAGE); 137 | gui = new SpriteGUI(img); 138 | expect(gui).to.be.an.instanceOf(SpriteGUI); 139 | return gui.destroy(); 140 | }); 141 | it("might accept a TileSprite", function() { 142 | var gui, tileSprite; 143 | tileSprite = game.add.tileSprite(0, 0, 100, 100, DEFAULT_IMAGE); 144 | gui = new SpriteGUI(tileSprite); 145 | expect(gui).to.be.an.instanceOf(SpriteGUI); 146 | return gui.destroy(); 147 | }); 148 | describe("autoPlace", function() { 149 | it("sets gui.autoPlace", function() { 150 | var gui, sprite; 151 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 152 | gui = new SpriteGUI(sprite, { 153 | autoPlace: true 154 | }); 155 | expect(gui).to.have.property("autoPlace").that.is["true"]; 156 | return gui.destroy(); 157 | }); 158 | return it("sets gui.scrollable", function() { 159 | var gui, sprite; 160 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 161 | gui = new SpriteGUI(sprite, { 162 | autoPlace: true 163 | }); 164 | expect(gui).to.have.property("scrollable").that.is["true"]; 165 | return gui.destroy(); 166 | }); 167 | }); 168 | describe("autoPlace=false", function() { 169 | it("sets gui.autoPlace", function() { 170 | var gui, sprite; 171 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 172 | gui = new SpriteGUI(sprite, { 173 | autoPlace: false 174 | }); 175 | expect(gui).to.have.property("autoPlace").that.is["false"]; 176 | return gui.destroy(); 177 | }); 178 | return it("doesn't set gui.scrollable", function() { 179 | var gui, sprite; 180 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 181 | gui = new SpriteGUI(sprite, { 182 | autoPlace: false 183 | }); 184 | expect(gui).to.have.property("scrollable").that.is.undefined; 185 | return gui.destroy(); 186 | }); 187 | }); 188 | describe("closeOnTop", function() { 189 | return it("sets gui.closeOnTop", function() { 190 | var gui, sprite; 191 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 192 | gui = new SpriteGUI(sprite, { 193 | closeOnTop: true 194 | }); 195 | expect(gui).to.have.property("closeOnTop").that.is["true"]; 196 | return gui.destroy(); 197 | }); 198 | }); 199 | describe("width", function() { 200 | return it("sets gui.width", function() { 201 | var gui, sprite; 202 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 203 | gui = new SpriteGUI(sprite, { 204 | width: 320 205 | }); 206 | expect(gui).to.have.property("width").that.is.within(320, 321); 207 | return gui.destroy(); 208 | }); 209 | }); 210 | describe("include", function() { 211 | it("sets gui.include", function() { 212 | var gui, sprite; 213 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 214 | gui = new SpriteGUI(sprite, null, { 215 | include: ["key"] 216 | }); 217 | expect(gui).to.have.property("include").that.deep.equals({ 218 | key: true 219 | }); 220 | return gui.destroy(); 221 | }); 222 | return it("uses filterInclude", function() { 223 | var gui, sprite; 224 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 225 | gui = new SpriteGUI(sprite, null, { 226 | include: ["key"] 227 | }); 228 | expect(gui.filter).to.equal(SpriteGUI.prototype.filterInclude); 229 | return gui.destroy(); 230 | }); 231 | }); 232 | return describe("exclude", function() { 233 | it("sets gui.exclude", function() { 234 | var gui, sprite; 235 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 236 | gui = new SpriteGUI(sprite, null, { 237 | exclude: ["key"] 238 | }); 239 | expect(gui).to.have.property("exclude").that.deep.equals({ 240 | key: true 241 | }); 242 | return gui.destroy(); 243 | }); 244 | return it("uses filterExclude", function() { 245 | var gui, sprite; 246 | sprite = game.add.sprite(0, 0, DEFAULT_IMAGE); 247 | gui = new SpriteGUI(sprite, null, { 248 | exclude: ["key"] 249 | }); 250 | expect(gui.filter).to.equal(SpriteGUI.prototype.filterExclude); 251 | return gui.destroy(); 252 | }); 253 | }); 254 | }); 255 | }); 256 | }); 257 | 258 | }).call(this); 259 | --------------------------------------------------------------------------------