├── .gitignore ├── HealthBar.js ├── HealthBar.standalone.js ├── README.md ├── example ├── .bowerrc ├── .editorconfig ├── .jshintrc ├── Gruntfile.js ├── assets │ └── plus_minus.png ├── bower.json ├── config.json ├── dist │ ├── assets │ │ └── plus_minus.png │ ├── css │ │ └── styles.css │ ├── index.html │ └── js │ │ ├── game.js │ │ ├── phaser.js │ │ └── phaser.min.js ├── game │ ├── main.js │ ├── prefabs │ │ └── HealthBar.js │ └── states │ │ └── play.js ├── index.html ├── package.json └── templates │ └── _main.js.tpl ├── license.txt ├── package.json └── phaser.healthbar.config.png /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | bower_components 4 | .idea 5 | -------------------------------------------------------------------------------- /HealthBar.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Belahcen Marwane (b.marwane@gmail.com) 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | var HealthBar = function(game, providedConfig) { 24 | this.game = game; 25 | this.group = null; 26 | 27 | this.setupConfiguration(providedConfig); 28 | this.setPosition(this.config.x, this.config.y); 29 | this.drawBackground(); 30 | this.drawBorder(); 31 | this.drawHealthBar(); 32 | this.setFixedToCamera(this.config.isFixedToCamera); 33 | }; 34 | HealthBar.prototype.constructor = HealthBar; 35 | 36 | HealthBar.prototype.setupConfiguration = function (providedConfig) { 37 | this.config = this.mergeWithDefaultConfiguration(providedConfig); 38 | this.flipped = this.config.flipped; 39 | }; 40 | 41 | HealthBar.prototype.mergeWithDefaultConfiguration = function(newConfig) { 42 | var defaultConfig= { 43 | width: 250, 44 | height: 40, 45 | x: 0, 46 | y: 0, 47 | bg: { 48 | color: '#651828' 49 | }, 50 | bar: { 51 | color: '#FEFF03' 52 | }, 53 | border: { 54 | color: "#000000", 55 | width: 1 56 | }, 57 | animationDuration: 200, 58 | flipped: false, 59 | isFixedToCamera: false 60 | }; 61 | 62 | return mergeObjetcs(defaultConfig, newConfig); 63 | }; 64 | 65 | function mergeObjetcs(targetObj, newObj) { 66 | for (var p in newObj) { 67 | try { 68 | targetObj[p] = newObj[p].constructor==Object ? mergeObjetcs(targetObj[p], newObj[p]) : newObj[p]; 69 | } catch(e) { 70 | targetObj[p] = newObj[p]; 71 | } 72 | } 73 | return targetObj; 74 | } 75 | 76 | HealthBar.prototype.drawBorder = function() { 77 | var border = this.config.border.width * 2; 78 | 79 | var bmd = this.game.add.bitmapData(this.config.width + border, this.config.height + border); 80 | bmd.ctx.fillStyle = this.config.border.color; 81 | bmd.ctx.beginPath(); 82 | bmd.ctx.rect(0, 0, this.config.width + border, this.config.height + border); 83 | bmd.ctx.stroke(); 84 | bmd.update(); 85 | 86 | this.borderSprite = this.game.add.sprite(this.x, this.y, bmd); 87 | this.borderSprite.anchor.set(0.5); 88 | }; 89 | 90 | HealthBar.prototype.drawBackground = function() { 91 | 92 | var bmd = this.game.add.bitmapData(this.config.width, this.config.height); 93 | bmd.ctx.fillStyle = this.config.bg.color; 94 | bmd.ctx.beginPath(); 95 | bmd.ctx.rect(0, 0, this.config.width, this.config.height); 96 | bmd.ctx.fill(); 97 | bmd.update(); 98 | 99 | this.bgSprite = this.game.add.sprite(this.x, this.y, bmd); 100 | this.bgSprite.anchor.set(0.5); 101 | 102 | if(this.flipped){ 103 | this.bgSprite.scale.x = -1; 104 | } 105 | }; 106 | 107 | HealthBar.prototype.drawHealthBar = function() { 108 | var bmd = this.game.add.bitmapData(this.config.width, this.config.height); 109 | bmd.ctx.fillStyle = this.config.bar.color; 110 | bmd.ctx.beginPath(); 111 | bmd.ctx.rect(0, 0, this.config.width, this.config.height); 112 | bmd.ctx.fill(); 113 | bmd.update(); 114 | 115 | this.barSprite = this.game.add.sprite(this.x - this.bgSprite.width/2, this.y, bmd); 116 | this.barSprite.anchor.y = 0.5; 117 | 118 | if(this.flipped){ 119 | this.barSprite.scale.x = -1; 120 | } 121 | }; 122 | 123 | HealthBar.prototype.setPosition = function (x, y) { 124 | this.x = x; 125 | this.y = y; 126 | 127 | if(this.bgSprite !== undefined && this.barSprite !== undefined && this.borderSprite !== undefined){ 128 | this.bgSprite.position.x = x; 129 | this.bgSprite.position.y = y; 130 | 131 | this.barSprite.position.x = x - this.config.width/2; 132 | this.barSprite.position.y = y; 133 | 134 | this.borderSprite.position.x = x; 135 | this.borderSprite.position.y = y; 136 | } 137 | }; 138 | 139 | 140 | HealthBar.prototype.setPercent = function(newValue){ 141 | if(newValue < 0) newValue = 0; 142 | if(newValue > 100) newValue = 100; 143 | 144 | var newWidth = (newValue * this.config.width) / 100; 145 | 146 | this.setWidth(newWidth); 147 | }; 148 | 149 | /* 150 | Hex format, example #ad3aa3 151 | */ 152 | HealthBar.prototype.setBarColor = function(newColor) { 153 | var bmd = this.barSprite.key; 154 | bmd.update(); 155 | 156 | var currentRGBColor = bmd.getPixelRGB(0, 0); 157 | var newRGBColor = hexToRgb(newColor); 158 | bmd.replaceRGB(currentRGBColor.r, 159 | currentRGBColor.g, 160 | currentRGBColor.b, 161 | 255 , 162 | 163 | newRGBColor.r, 164 | newRGBColor.g, 165 | newRGBColor.b, 166 | 255); 167 | 168 | }; 169 | 170 | HealthBar.prototype.setWidth = function(newWidth){ 171 | if(this.flipped) { 172 | newWidth = -1 * newWidth; 173 | } 174 | this.game.add.tween(this.barSprite).to( { width: newWidth }, this.config.animationDuration, Phaser.Easing.Linear.None, true); 175 | }; 176 | 177 | HealthBar.prototype.setFixedToCamera = function(fixedToCamera) { 178 | this.bgSprite.fixedToCamera = fixedToCamera; 179 | this.barSprite.fixedToCamera = fixedToCamera; 180 | this.borderSprite.fixedToCamera = fixedToCamera; 181 | }; 182 | 183 | HealthBar.prototype.setAnchor = function(xAnchor, yAnchor) { 184 | this.bgSprite.anchor.set(xAnchor, yAnchor); 185 | this.barSprite.position.x = this.bgSprite.position.x - this.config.width * this.bgSprite.anchor.x; 186 | this.borderSprite.anchor.set(xAnchor, yAnchor); 187 | this.barSprite.anchor.y = yAnchor; 188 | if (this.flipped){ 189 | this.barSprite.anchor.x = 1; 190 | this.barSprite.position.x = this.bgSprite.position.x; 191 | } 192 | }; 193 | 194 | 195 | HealthBar.prototype.setToGroup = function(group) { 196 | group.add(this.bgSprite); 197 | group.add(this.barSprite); 198 | 199 | this.group = group; 200 | }; 201 | 202 | HealthBar.prototype.removeFromGroup = function() { 203 | this.game.world.add(this.bgSprite); 204 | this.game.world.add(this.barSprite); 205 | 206 | this.group = null; 207 | }; 208 | 209 | HealthBar.prototype.kill = function() { 210 | this.bgSprite.kill(); 211 | this.barSprite.kill(); 212 | this.borderSprite.kill(); 213 | }; 214 | 215 | module.exports = HealthBar; 216 | 217 | 218 | 219 | /** 220 | Utils 221 | */ 222 | 223 | function hexToRgb(hex) { 224 | // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") 225 | var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; 226 | hex = hex.replace(shorthandRegex, function(m, r, g, b) { 227 | return r + r + g + g + b + b; 228 | }); 229 | 230 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 231 | return result ? { 232 | r: parseInt(result[1], 16), 233 | g: parseInt(result[2], 16), 234 | b: parseInt(result[3], 16) 235 | } : null; 236 | } -------------------------------------------------------------------------------- /HealthBar.standalone.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Belahcen Marwane (b.marwane@gmail.com) 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | var HealthBar = function(game, providedConfig) { 24 | this.game = game; 25 | this.group = null; 26 | 27 | this.setupConfiguration(providedConfig); 28 | this.setPosition(this.config.x, this.config.y); 29 | this.drawBackground(); 30 | this.drawBorder(); 31 | this.drawHealthBar(); 32 | this.setFixedToCamera(this.config.isFixedToCamera); 33 | }; 34 | HealthBar.prototype.constructor = HealthBar; 35 | 36 | HealthBar.prototype.setupConfiguration = function (providedConfig) { 37 | this.config = this.mergeWithDefaultConfiguration(providedConfig); 38 | this.flipped = this.config.flipped; 39 | }; 40 | 41 | HealthBar.prototype.mergeWithDefaultConfiguration = function(newConfig) { 42 | var defaultConfig= { 43 | width: 250, 44 | height: 40, 45 | x: 0, 46 | y: 0, 47 | bg: { 48 | color: '#651828' 49 | }, 50 | bar: { 51 | color: '#FEFF03' 52 | }, 53 | border: { 54 | color: "#000000", 55 | width: 1 56 | }, 57 | animationDuration: 200, 58 | flipped: false, 59 | isFixedToCamera: false 60 | }; 61 | 62 | return mergeObjetcs(defaultConfig, newConfig); 63 | }; 64 | 65 | function mergeObjetcs(targetObj, newObj) { 66 | for (var p in newObj) { 67 | try { 68 | targetObj[p] = newObj[p].constructor==Object ? mergeObjetcs(targetObj[p], newObj[p]) : newObj[p]; 69 | } catch(e) { 70 | targetObj[p] = newObj[p]; 71 | } 72 | } 73 | return targetObj; 74 | } 75 | 76 | HealthBar.prototype.drawBorder = function() { 77 | var border = this.config.border.width * 2; 78 | 79 | var bmd = this.game.add.bitmapData(this.config.width + border, this.config.height + border); 80 | bmd.ctx.fillStyle = this.config.border.color; 81 | bmd.ctx.beginPath(); 82 | bmd.ctx.rect(0, 0, this.config.width + border, this.config.height + border); 83 | bmd.ctx.stroke(); 84 | bmd.update(); 85 | 86 | this.borderSprite = this.game.add.sprite(this.x, this.y, bmd); 87 | this.borderSprite.anchor.set(0.5); 88 | }; 89 | 90 | HealthBar.prototype.drawBackground = function() { 91 | 92 | var bmd = this.game.add.bitmapData(this.config.width, this.config.height); 93 | bmd.ctx.fillStyle = this.config.bg.color; 94 | bmd.ctx.beginPath(); 95 | bmd.ctx.rect(0, 0, this.config.width, this.config.height); 96 | bmd.ctx.fill(); 97 | bmd.update(); 98 | 99 | this.bgSprite = this.game.add.sprite(this.x, this.y, bmd); 100 | this.bgSprite.anchor.set(0.5); 101 | 102 | if(this.flipped){ 103 | this.bgSprite.scale.x = -1; 104 | } 105 | }; 106 | 107 | HealthBar.prototype.drawHealthBar = function() { 108 | var bmd = this.game.add.bitmapData(this.config.width, this.config.height); 109 | bmd.ctx.fillStyle = this.config.bar.color; 110 | bmd.ctx.beginPath(); 111 | bmd.ctx.rect(0, 0, this.config.width, this.config.height); 112 | bmd.ctx.fill(); 113 | bmd.update(); 114 | 115 | this.barSprite = this.game.add.sprite(this.x - this.bgSprite.width/2, this.y, bmd); 116 | this.barSprite.anchor.y = 0.5; 117 | 118 | if(this.flipped){ 119 | this.barSprite.scale.x = -1; 120 | } 121 | }; 122 | 123 | HealthBar.prototype.setPosition = function (x, y) { 124 | this.x = x; 125 | this.y = y; 126 | 127 | if(this.bgSprite !== undefined && this.barSprite !== undefined && this.borderSprite !== undefined){ 128 | this.bgSprite.position.x = x; 129 | this.bgSprite.position.y = y; 130 | 131 | this.barSprite.position.x = x - this.config.width/2; 132 | this.barSprite.position.y = y; 133 | 134 | this.borderSprite.position.x = x; 135 | this.borderSprite.position.y = y; 136 | } 137 | }; 138 | 139 | 140 | HealthBar.prototype.setPercent = function(newValue){ 141 | if(newValue < 0) newValue = 0; 142 | if(newValue > 100) newValue = 100; 143 | 144 | var newWidth = (newValue * this.config.width) / 100; 145 | 146 | this.setWidth(newWidth); 147 | }; 148 | 149 | /* 150 | Hex format, example #ad3aa3 151 | */ 152 | HealthBar.prototype.setBarColor = function(newColor) { 153 | var bmd = this.barSprite.key; 154 | bmd.update(); 155 | 156 | var currentRGBColor = bmd.getPixelRGB(0, 0); 157 | var newRGBColor = hexToRgb(newColor); 158 | bmd.replaceRGB(currentRGBColor.r, 159 | currentRGBColor.g, 160 | currentRGBColor.b, 161 | 255 , 162 | 163 | newRGBColor.r, 164 | newRGBColor.g, 165 | newRGBColor.b, 166 | 255); 167 | 168 | }; 169 | 170 | HealthBar.prototype.setWidth = function(newWidth){ 171 | if(this.flipped) { 172 | newWidth = -1 * newWidth; 173 | } 174 | this.game.add.tween(this.barSprite).to( { width: newWidth }, this.config.animationDuration, Phaser.Easing.Linear.None, true); 175 | }; 176 | 177 | HealthBar.prototype.setFixedToCamera = function(fixedToCamera) { 178 | this.bgSprite.fixedToCamera = fixedToCamera; 179 | this.barSprite.fixedToCamera = fixedToCamera; 180 | this.borderSprite.fixedToCamera = fixedToCamera; 181 | }; 182 | 183 | HealthBar.prototype.setAnchor = function(xAnchor, yAnchor) { 184 | this.bgSprite.anchor.set(xAnchor, yAnchor); 185 | this.barSprite.position.x = this.bgSprite.position.x - this.config.width * this.bgSprite.anchor.x; 186 | this.borderSprite.anchor.set(xAnchor, yAnchor); 187 | this.barSprite.anchor.y = yAnchor; 188 | if (this.flipped){ 189 | this.barSprite.anchor.x = 1; 190 | this.barSprite.position.x = this.bgSprite.position.x; 191 | } 192 | }; 193 | 194 | 195 | HealthBar.prototype.setToGroup = function(group) { 196 | group.add(this.bgSprite); 197 | group.add(this.barSprite); 198 | 199 | this.group = group; 200 | }; 201 | 202 | HealthBar.prototype.removeFromGroup = function() { 203 | this.game.world.add(this.bgSprite); 204 | this.game.world.add(this.barSprite); 205 | 206 | this.group = null; 207 | }; 208 | 209 | HealthBar.prototype.kill = function() { 210 | this.bgSprite.kill(); 211 | this.barSprite.kill(); 212 | this.borderSprite.kill(); 213 | }; 214 | 215 | /** 216 | Utils 217 | */ 218 | 219 | function hexToRgb(hex) { 220 | // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") 221 | var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; 222 | hex = hex.replace(shorthandRegex, function(m, r, g, b) { 223 | return r + r + g + g + b + b; 224 | }); 225 | 226 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 227 | return result ? { 228 | r: parseInt(result[1], 16), 229 | g: parseInt(result[2], 16), 230 | b: parseInt(result[3], 16) 231 | } : null; 232 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Phaser.HealthBar 2 | 3 | An attempt to create a simple and customizable health bar for Phaser.js games. 4 | 5 | I made a tutorial in French that explain how to create this health bar from scratch, you can check it out [here](http://apprendre-le-js.com/phaser-js-healthbar-tutorial/ "apprendre-le-js.com healthbar tutorial"). 6 | 7 | ## Demo 8 | 9 | [Demo](http://apprendre-le-js.com/tuto_examples/healthbar/4/) 10 | 11 | ## Usage 12 | 13 | ### 1 - Import HealthBar file 14 | 15 | If you are using a CommonJS implementation (Browserify) : 16 | 17 | ```javascript 18 | var HealthBar = require('path/to/HealthBar.js'); 19 | ``` 20 | 21 | if not, just include the HealthBar.standalone.js in the html file. 22 | example : 23 | ``` html 24 | 25 | ``` 26 | 27 | ### 2 - create a HealthBar : 28 | 29 | in the game/state create function instantiate a HealthBar like this: 30 | 31 | ```javascript 32 | create: function() { 33 | var barConfig = {x: 200, y: 100}; 34 | this.myHealthBar = new HealthBar(this.game, barConfig); 35 | } 36 | ``` 37 | ## Configuration 38 | 39 | ![](https://raw.githubusercontent.com/bmarwane/phaser.healthbar/master/phaser.healthbar.config.png) 40 | 41 | - **width** 42 | - **height** 43 | - **x:** initial x position 44 | - **y:** initial y position 45 | - **bg.color:** background color 46 | - **bar.color:** color of the actual bar 47 | - **animationDuration:** control the animation when the bar value is changed 48 | - **flipped:** if true the bar will change size from left to right 49 | 50 | this is the default configuration : 51 | ```javascript 52 | { 53 | width: 250, 54 | height: 40, 55 | x: 0, 56 | y: 0, 57 | bg: { 58 | color: '#651828' 59 | }, 60 | bar: { 61 | color: '#FEFF03' 62 | }, 63 | animationDuration: 200, 64 | flipped: false 65 | }; 66 | ``` 67 | 68 | ## Methods 69 | 70 | ### setPercent(value): 71 | 72 | set the width of the bar to the passed percentage value. 73 | 74 | **example:** 75 | 76 | ```javascript 77 | this.myHealthBar = new HealthBar(this.game, {x: 200, y: 200, width: 120}); 78 | 79 | // the width will be set to 50% of the actual size so the new value will be 60 80 | this.myHealthBar.setPercent(50); 81 | ``` 82 | 83 | ### setPosition(x, y): 84 | change the position of the bar to the provided coordinates. 85 | 86 | ### setBarColor(newColor) 87 | 88 | change the bar color, use the hex color format. 89 | example : 90 | ```javascript 91 | this.myHealthBar.setBarColor('#fc9802'); 92 | ``` 93 | 94 | ### setFixedToCamera(fixedToCamera); 95 | fixedToCamera must be true or false value (boolean type). 96 | method allows fixed to camera. 97 | 98 | ### setToGroup(group); 99 | add bar to some group 100 | 101 | ### removeFromGroup(); 102 | remove bar from current group and add back to game.world group 103 | 104 | ### kill(); 105 | will kill the HealthBar. 106 | 107 | # License 108 | 109 | Phaser.HealthBar is released under the [MIT License](https://opensource.org/licenses/MIT). 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /example/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components" 3 | } -------------------------------------------------------------------------------- /example/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /example/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 2, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "regexp": true, 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "trailing": true, 19 | "smarttabs": true, 20 | "white": true 21 | } 22 | -------------------------------------------------------------------------------- /example/Gruntfile.js: -------------------------------------------------------------------------------- 1 | // Generated on 2014-03-28 using generator-phaser-official 0.0.8-rc-2 2 | 'use strict'; 3 | var config = require('./config.json'); 4 | var _ = require('underscore'); 5 | _.str = require('underscore.string'); 6 | 7 | // Mix in non-conflict functions to Underscore namespace if you want 8 | _.mixin(_.str.exports()); 9 | 10 | var LIVERELOAD_PORT = 35729; 11 | var lrSnippet = require('connect-livereload')({port: LIVERELOAD_PORT}); 12 | var mountFolder = function (connect, dir) { 13 | return connect.static(require('path').resolve(dir)); 14 | }; 15 | 16 | module.exports = function (grunt) { 17 | // load all grunt tasks 18 | require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks); 19 | 20 | grunt.initConfig({ 21 | watch: { 22 | scripts: { 23 | files: [ 24 | 'game/**/*.js', 25 | '!game/main.js' 26 | ], 27 | options: { 28 | spawn: false, 29 | livereload: LIVERELOAD_PORT 30 | }, 31 | tasks: ['build'] 32 | } 33 | }, 34 | connect: { 35 | options: { 36 | port: 9000, 37 | // change this to '0.0.0.0' to access the server from outside 38 | hostname: 'localhost' 39 | }, 40 | livereload: { 41 | options: { 42 | middleware: function (connect) { 43 | return [ 44 | lrSnippet, 45 | mountFolder(connect, 'dist') 46 | ]; 47 | } 48 | } 49 | } 50 | }, 51 | open: { 52 | server: { 53 | path: 'http://localhost:9000' 54 | } 55 | }, 56 | copy: { 57 | dist: { 58 | files: [ 59 | // includes files within path and its sub-directories 60 | { expand: true, src: ['assets/**'], dest: 'dist/' }, 61 | { expand: true, flatten: true, src: ['game/plugins/*.js'], dest: 'dist/js/plugins/' }, 62 | { expand: true, flatten: true, src: ['bower_components/**/build/*.js'], dest: 'dist/js/' }, 63 | { expand: true, src: ['css/**'], dest: 'dist/' }, 64 | { expand: true, src: ['index.html'], dest: 'dist/' } 65 | ] 66 | } 67 | }, 68 | browserify: { 69 | build: { 70 | src: ['game/main.js'], 71 | dest: 'dist/js/game.js' 72 | } 73 | } 74 | }); 75 | 76 | grunt.registerTask('build', ['buildBootstrapper', 'browserify','copy']); 77 | grunt.registerTask('serve', ['build', 'connect:livereload', 'open', 'watch']); 78 | grunt.registerTask('default', ['serve']); 79 | grunt.registerTask('prod', ['build', 'copy']); 80 | 81 | grunt.registerTask('buildBootstrapper', 'builds the bootstrapper file correctly', function() { 82 | var stateFiles = grunt.file.expand('game/states/*.js'); 83 | var gameStates = []; 84 | var statePattern = new RegExp(/(\w+).js$/); 85 | stateFiles.forEach(function(file) { 86 | var state = file.match(statePattern)[1]; 87 | if (!!state) { 88 | gameStates.push({shortName: state, stateName: _.capitalize(state) + 'State'}); 89 | } 90 | }); 91 | config.gameStates = gameStates; 92 | console.log(config); 93 | var bootstrapper = grunt.file.read('templates/_main.js.tpl'); 94 | bootstrapper = grunt.template.process(bootstrapper,{data: config}); 95 | grunt.file.write('game/main.js', bootstrapper); 96 | }); 97 | }; -------------------------------------------------------------------------------- /example/assets/plus_minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmarwane/phaser.healthbar/645f22aff1e3ce541eb69aa040e4d3541069d7c9/example/assets/plus_minus.png -------------------------------------------------------------------------------- /example/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo", 3 | "version": "0.0.0", 4 | "dependencies": { 5 | "phaser-official": "2.4.3" 6 | } 7 | } -------------------------------------------------------------------------------- /example/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "demo", 3 | "gameWidth": "600", 4 | "gameHeight": "280" 5 | } 6 | -------------------------------------------------------------------------------- /example/dist/assets/plus_minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmarwane/phaser.healthbar/645f22aff1e3ce541eb69aa040e4d3541069d7c9/example/dist/assets/plus_minus.png -------------------------------------------------------------------------------- /example/dist/css/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #333; 3 | margin:0; 4 | } 5 | -------------------------------------------------------------------------------- /example/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Healthbar Step 1 8 | 9 | 10 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /example/dist/js/game.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 100) newValue = 100; 135 | 136 | var newWidth = (newValue * this.config.width) / 100; 137 | 138 | this.setWidth(newWidth); 139 | }; 140 | 141 | /* 142 | Hex format, example #ad3aa3 143 | */ 144 | HealthBar.prototype.setBarColor = function(newColor) { 145 | var bmd = this.barSprite.key; 146 | bmd.update(); 147 | 148 | var currentRGBColor = bmd.getPixelRGB(0, 0); 149 | var newRGBColor = hexToRgb(newColor); 150 | bmd.replaceRGB(currentRGBColor.r, 151 | currentRGBColor.g, 152 | currentRGBColor.b, 153 | 255 , 154 | 155 | newRGBColor.r, 156 | newRGBColor.g, 157 | newRGBColor.b, 158 | 255); 159 | 160 | }; 161 | 162 | HealthBar.prototype.setWidth = function(newWidth){ 163 | if(this.flipped) { 164 | newWidth = -1 * newWidth; 165 | } 166 | this.game.add.tween(this.barSprite).to( { width: newWidth }, this.config.animationDuration, Phaser.Easing.Linear.None, true); 167 | }; 168 | 169 | HealthBar.prototype.setFixedToCamera = function(fixedToCamera) { 170 | this.bgSprite.fixedToCamera = fixedToCamera; 171 | this.barSprite.fixedToCamera = fixedToCamera; 172 | }; 173 | 174 | HealthBar.prototype.kill = function() { 175 | this.bgSprite.kill(); 176 | this.barSprite.kill(); 177 | }; 178 | 179 | module.exports = HealthBar; 180 | 181 | 182 | 183 | /** 184 | Utils 185 | */ 186 | 187 | function hexToRgb(hex) { 188 | // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") 189 | var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; 190 | hex = hex.replace(shorthandRegex, function(m, r, g, b) { 191 | return r + r + g + g + b + b; 192 | }); 193 | 194 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 195 | return result ? { 196 | r: parseInt(result[1], 16), 197 | g: parseInt(result[2], 16), 198 | b: parseInt(result[3], 16) 199 | } : null; 200 | } 201 | 202 | },{}],3:[function(require,module,exports){ 203 | 'use strict'; 204 | 205 | var HealthBar = require('../prefabs/HealthBar.js'); 206 | 207 | function Play() {} 208 | Play.prototype = { 209 | preload: function() { 210 | this.game.load.spritesheet('button', 'assets/plus_minus.png', 31, 31); 211 | }, 212 | 213 | create: function() { 214 | this.game.stage.backgroundColor = '#1D70EF'; 215 | 216 | var barre1_x = 150; 217 | var barre1_y = 115; 218 | 219 | var barre2_x = 450; 220 | var barre2_y = 115; 221 | 222 | this.healthValue = 100; 223 | this.healthValue2 = 100; 224 | this.myHealthBar = new HealthBar(this.game, {x: barre1_x, y: barre1_y}); 225 | this.myFlippedHealthBar = new HealthBar(this.game, {x: barre2_x, y: barre2_y, flipped: true}); 226 | 227 | this.minusButton = this.game.add.button(barre1_x - 50, barre1_y + 30, 'button', this.onMinusClick, this, 1, 1, 1, 1); 228 | this.plusButton = this.game.add.button(barre1_x , barre1_y + 30, 'button', this.onPlusClick, this, 0); 229 | 230 | this.minusButton2 = this.game.add.button(barre2_x - 50, barre2_y + 30, 'button', this.onMinus2Click, this, 1, 1, 1, 1); 231 | this.plusButton2 = this.game.add.button(barre2_x , barre2_y + 30, 'button', this.onPlus2Click, this, 0); 232 | 233 | }, 234 | 235 | onPlusClick: function(){ 236 | this.healthValue = this.healthValue + 10; 237 | if(this.healthValue > 100) this.healthValue = 100; 238 | this.myHealthBar.setPercent(this.healthValue); 239 | }, 240 | onMinusClick: function(){ 241 | this.healthValue = this.healthValue - 10; 242 | if(this.healthValue < 0) this.healthValue = 0; 243 | this.myHealthBar.setPercent(this.healthValue); 244 | 245 | if(this.healthValue < 70) { 246 | this.myHealthBar.setBarColor('#fc9802'); 247 | } 248 | }, 249 | onPlus2Click: function(){ 250 | this.healthValue2 = this.healthValue2 + 10; 251 | if(this.healthValue2 > 100) this.healthValue2 = 100; 252 | this.myFlippedHealthBar.setPercent(this.healthValue2); 253 | }, 254 | onMinus2Click: function(){ 255 | this.healthValue2 = this.healthValue2 - 10; 256 | if(this.healthValue2 < 0) this.healthValue2 = 0; 257 | this.myFlippedHealthBar.setPercent(this.healthValue2); 258 | } 259 | }; 260 | module.exports = Play; 261 | 262 | },{"../prefabs/HealthBar.js":2}]},{},[1]) -------------------------------------------------------------------------------- /example/game/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | //global variables 4 | window.onload = function () { 5 | var game = new Phaser.Game(600, 280, Phaser.AUTO, 'demo'); 6 | 7 | // Game States 8 | game.state.add('play', require('./states/play')); 9 | 10 | 11 | game.state.start('play'); 12 | }; 13 | -------------------------------------------------------------------------------- /example/game/prefabs/HealthBar.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 Belahcen Marwane (b.marwane@gmail.com) 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | var HealthBar = function(game, providedConfig) { 24 | this.game = game; 25 | 26 | this.setupConfiguration(providedConfig); 27 | this.setPosition(this.config.x, this.config.y); 28 | this.drawBackground(); 29 | this.drawHealthBar(); 30 | this.setFixedToCamera(this.config.isFixedToCamera); 31 | }; 32 | HealthBar.prototype.constructor = HealthBar; 33 | 34 | HealthBar.prototype.setupConfiguration = function (providedConfig) { 35 | this.config = this.mergeWithDefaultConfiguration(providedConfig); 36 | this.flipped = this.config.flipped; 37 | }; 38 | 39 | HealthBar.prototype.mergeWithDefaultConfiguration = function(newConfig) { 40 | var defaultConfig= { 41 | width: 250, 42 | height: 40, 43 | x: 0, 44 | y: 0, 45 | bg: { 46 | color: '#651828' 47 | }, 48 | bar: { 49 | color: '#FEFF03' 50 | }, 51 | animationDuration: 200, 52 | flipped: false, 53 | isFixedToCamera: false 54 | }; 55 | 56 | return mergeObjetcs(defaultConfig, newConfig); 57 | }; 58 | 59 | function mergeObjetcs(targetObj, newObj) { 60 | for (var p in newObj) { 61 | try { 62 | targetObj[p] = newObj[p].constructor==Object ? mergeObjetcs(targetObj[p], newObj[p]) : newObj[p]; 63 | } catch(e) { 64 | targetObj[p] = newObj[p]; 65 | } 66 | } 67 | return targetObj; 68 | } 69 | 70 | HealthBar.prototype.drawBackground = function() { 71 | 72 | var bmd = this.game.add.bitmapData(this.config.width, this.config.height); 73 | bmd.ctx.fillStyle = this.config.bg.color; 74 | bmd.ctx.beginPath(); 75 | bmd.ctx.rect(0, 0, this.config.width, this.config.height); 76 | bmd.ctx.fill(); 77 | bmd.update(); 78 | 79 | this.bgSprite = this.game.add.sprite(this.x, this.y, bmd); 80 | this.bgSprite.anchor.set(0.5); 81 | 82 | if(this.flipped){ 83 | this.bgSprite.scale.x = -1; 84 | } 85 | }; 86 | 87 | HealthBar.prototype.drawHealthBar = function() { 88 | var bmd = this.game.add.bitmapData(this.config.width, this.config.height); 89 | bmd.ctx.fillStyle = this.config.bar.color; 90 | bmd.ctx.beginPath(); 91 | bmd.ctx.rect(0, 0, this.config.width, this.config.height); 92 | bmd.ctx.fill(); 93 | bmd.update(); 94 | 95 | this.barSprite = this.game.add.sprite(this.x - this.bgSprite.width/2, this.y, bmd); 96 | this.barSprite.anchor.y = 0.5; 97 | 98 | if(this.flipped){ 99 | this.barSprite.scale.x = -1; 100 | } 101 | }; 102 | 103 | HealthBar.prototype.setPosition = function (x, y) { 104 | this.x = x; 105 | this.y = y; 106 | 107 | if(this.bgSprite !== undefined && this.barSprite !== undefined){ 108 | this.bgSprite.position.x = x; 109 | this.bgSprite.position.y = y; 110 | 111 | this.barSprite.position.x = x - this.config.width/2; 112 | this.barSprite.position.y = y; 113 | } 114 | }; 115 | 116 | 117 | HealthBar.prototype.setPercent = function(newValue){ 118 | if(newValue < 0) newValue = 0; 119 | if(newValue > 100) newValue = 100; 120 | 121 | var newWidth = (newValue * this.config.width) / 100; 122 | 123 | this.setWidth(newWidth); 124 | }; 125 | 126 | /* 127 | Hex format, example #ad3aa3 128 | */ 129 | HealthBar.prototype.setBarColor = function(newColor) { 130 | var bmd = this.barSprite.key; 131 | bmd.update(); 132 | 133 | var currentRGBColor = bmd.getPixelRGB(0, 0); 134 | var newRGBColor = hexToRgb(newColor); 135 | bmd.replaceRGB(currentRGBColor.r, 136 | currentRGBColor.g, 137 | currentRGBColor.b, 138 | 255 , 139 | 140 | newRGBColor.r, 141 | newRGBColor.g, 142 | newRGBColor.b, 143 | 255); 144 | 145 | }; 146 | 147 | HealthBar.prototype.setWidth = function(newWidth){ 148 | if(this.flipped) { 149 | newWidth = -1 * newWidth; 150 | } 151 | this.game.add.tween(this.barSprite).to( { width: newWidth }, this.config.animationDuration, Phaser.Easing.Linear.None, true); 152 | }; 153 | 154 | HealthBar.prototype.setFixedToCamera = function(fixedToCamera) { 155 | this.bgSprite.fixedToCamera = fixedToCamera; 156 | this.barSprite.fixedToCamera = fixedToCamera; 157 | }; 158 | 159 | HealthBar.prototype.kill = function() { 160 | this.bgSprite.kill(); 161 | this.barSprite.kill(); 162 | }; 163 | 164 | module.exports = HealthBar; 165 | 166 | 167 | 168 | /** 169 | Utils 170 | */ 171 | 172 | function hexToRgb(hex) { 173 | // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") 174 | var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; 175 | hex = hex.replace(shorthandRegex, function(m, r, g, b) { 176 | return r + r + g + g + b + b; 177 | }); 178 | 179 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 180 | return result ? { 181 | r: parseInt(result[1], 16), 182 | g: parseInt(result[2], 16), 183 | b: parseInt(result[3], 16) 184 | } : null; 185 | } 186 | -------------------------------------------------------------------------------- /example/game/states/play.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var HealthBar = require('../prefabs/HealthBar.js'); 4 | 5 | function Play() {} 6 | Play.prototype = { 7 | preload: function() { 8 | this.game.load.spritesheet('button', 'assets/plus_minus.png', 31, 31); 9 | }, 10 | 11 | create: function() { 12 | this.game.stage.backgroundColor = '#1D70EF'; 13 | 14 | var barre1_x = 150; 15 | var barre1_y = 115; 16 | 17 | var barre2_x = 450; 18 | var barre2_y = 115; 19 | 20 | this.healthValue = 100; 21 | this.healthValue2 = 100; 22 | this.myHealthBar = new HealthBar(this.game, {x: barre1_x, y: barre1_y}); 23 | this.myFlippedHealthBar = new HealthBar(this.game, {x: barre2_x, y: barre2_y, flipped: true}); 24 | 25 | this.minusButton = this.game.add.button(barre1_x - 50, barre1_y + 30, 'button', this.onMinusClick, this, 1, 1, 1, 1); 26 | this.plusButton = this.game.add.button(barre1_x , barre1_y + 30, 'button', this.onPlusClick, this, 0); 27 | 28 | this.minusButton2 = this.game.add.button(barre2_x - 50, barre2_y + 30, 'button', this.onMinus2Click, this, 1, 1, 1, 1); 29 | this.plusButton2 = this.game.add.button(barre2_x , barre2_y + 30, 'button', this.onPlus2Click, this, 0); 30 | 31 | }, 32 | 33 | onPlusClick: function(){ 34 | this.healthValue = this.healthValue + 10; 35 | if(this.healthValue > 100) this.healthValue = 100; 36 | this.myHealthBar.setPercent(this.healthValue); 37 | }, 38 | onMinusClick: function(){ 39 | this.healthValue = this.healthValue - 10; 40 | if(this.healthValue < 0) this.healthValue = 0; 41 | this.myHealthBar.setPercent(this.healthValue); 42 | 43 | if(this.healthValue < 70) { 44 | this.myHealthBar.setBarColor('#fc9802'); 45 | } 46 | }, 47 | onPlus2Click: function(){ 48 | this.healthValue2 = this.healthValue2 + 10; 49 | if(this.healthValue2 > 100) this.healthValue2 = 100; 50 | this.myFlippedHealthBar.setPercent(this.healthValue2); 51 | }, 52 | onMinus2Click: function(){ 53 | this.healthValue2 = this.healthValue2 - 10; 54 | if(this.healthValue2 < 0) this.healthValue2 = 0; 55 | this.myFlippedHealthBar.setPercent(this.healthValue2); 56 | } 57 | }; 58 | module.exports = Play; 59 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Healthbar Step 1 8 | 9 | 10 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo", 3 | "private": true, 4 | "devDependencies": { 5 | "grunt": "~0.4.1", 6 | "bower": "~0.9.2", 7 | "grunt-contrib-connect": "~0.2.0", 8 | "grunt-contrib-watch": "~0.4.3", 9 | "grunt-contrib-copy": "*", 10 | "grunt-open": "~0.2.0", 11 | "matchdep": "~0.1.2", 12 | "connect-livereload": "~0.5", 13 | "moment": "2.19.3", 14 | "grunt-html-build": "~0.3.2", 15 | "underscore": "*", 16 | "underscore.string": "*", 17 | "browserify": "~3.38.0", 18 | "grunt-browserify": "~1.3.0" 19 | }, 20 | "engines": { 21 | "node": ">=0.8.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/templates/_main.js.tpl: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | //global variables 4 | window.onload = function () { 5 | var game = new Phaser.Game(<%= gameWidth %>, <%= gameHeight %>, Phaser.AUTO, '<%= _.slugify(projectName) %>'); 6 | 7 | // Game States 8 | <% _.forEach(gameStates, function(gameState) { %>game.state.add('<%= gameState.shortName %>', require('./states/<%= gameState.shortName %>')); 9 | <% }); %> 10 | 11 | game.state.start('play'); 12 | }; 13 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Belahcen Marwane (b.marwane@gmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phaser.healthbar", 3 | "version": "1.0.0", 4 | "main": "HealthBar.js", 5 | "directories": { 6 | "example": "example" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/bmarwane/phaser.healthbar.git" 11 | }, 12 | "keywords": [ 13 | "phaser", 14 | "healthbar" 15 | ], 16 | "author": "Belahcen Marwane ", 17 | "license": "MIT", 18 | "licenseUrl": "http://www.opensource.org/licenses/mit-license.php", 19 | "bugs": { 20 | "url": "https://github.com/bmarwane/phaser.healthbar/issues" 21 | }, 22 | "homepage": "https://github.com/bmarwane/phaser.healthbar#readme" 23 | } -------------------------------------------------------------------------------- /phaser.healthbar.config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmarwane/phaser.healthbar/645f22aff1e3ce541eb69aa040e4d3541069d7c9/phaser.healthbar.config.png --------------------------------------------------------------------------------