Jump to content

Health Bars?


opendevcode
 Share

Recommended Posts

Yes, scaling does effect the visual quality of an image.

You can look into cropping it, like the preloader bar in the base example template, but that may have some undesirable qualities such as changing all health bars at once.

You can also investigate masking, but I haven't looked at that enough to tell you much about it.

 

I'd go for a single colour image, with the source being as big as it can be, and scaling down from there. Or, use a graphics object and just draw solid fill rectangles.

Link to comment
Share on other sites

I suggest you use cropping.

Sample code:

var healthbar = this.game.add.sprite(0,0,'healthbar');healthbar.cropEnabled = true;healthbar.crop.width = (character.health / character.maxHealth) * healthbar.width

Just one limitation though, the crop is applied on texture level. So all Sprite using the same texture will be cropped.
Useful only if you have one healthbar to show :)

Link to comment
Share on other sites

Here's a little snippet for graphics based healthbars that go from green to red as health gets lower (copied straight out of a game and minimally edited for context so hopefully it makes sense)

this.healthbar = game.add.graphics(0,0);this.group.add(this.healthbar); // this.group being a pre-initialised group for this entity...this.hp = 20;this.totalhp = 20;this._lasthp = 0;if (this._lasthp !== this.hp) {    this.healthbar.clear();    var x = (this.hp / this.totalhp) * 100;    var colour = utils.rgbToHex((x > 50 ? 1-2*(x-50)/100.0 : 1.0) * 255, (x > 50 ? 1.0 : 2*x/100.0) * 255, 0);        this.healthbar.beginFill(colour);    this.healthbar.lineStyle(5, colour, 1);    this.healthbar.moveTo(0,-5);    this.healthbar.lineTo(config.tileSize * this.hp / this.totalhp, -5);    this.healthbar.endFill();}this._lasthp = this.hp;

Here's utils.rgbToHex:

rgbToHex: function (r, g,  {    return "0x" + ((1 << 24) + (r << 16) + (g << 8) + .toString(16).slice(1);}

(I think there's already a function somewhere in Phaser to do that part but when I wrote the code I wasn't aware of it)

 

Also config.tileSize is, predictably, the size of tiles in px (this was a top down game) but you can specify whatever width you want the full bar to be there. This was written a while ago so I have no idea if it works for later versions of Phaser but it's fairly simple so it should do.

Link to comment
Share on other sites

  • 5 months later...

Do you really need this line? It worked without that on my project.

this.healthbar.endFill()

Btw: where do these methods (beginFill/lineStyle etc.) come from? I can't find them in the phaser docs and neither in JS documentations. Would be really helpful to have explanations like in the phaser namespace doc.

Link to comment
Share on other sites

I'm using width, I have a sprite object with width = 0;

Then I add some width to it to show it grow or reduced

 

You can apply a percentage to show how much width you want to reduce  like: 

obj.width = obj.width + (damagePerc * obj.maxWidth); // damagePerc can be any percentage like 0.1(10%), 0.5(50%)
Link to comment
Share on other sites

I did it with 2 layers of sprites.

 

One is the empty bar, one is the filled.

 

When something of concern happens, I update the value backing the bar and rerender it.

 

This is the spritesheet for the bars.

3 bar sprites, empty, life and endurance.

Every bar consists of one start and end sprite and a few middle sprites.

 

post-6791-0-56006000-1407935752.png
 
This is how it looks in the game
 
post-6791-0-81986500-1407935876.jpg

 

class Game.gui.Bar  x:10px  y:10px  width:60px  max:100  current:100 # the current value of the bar  bar-parts: void # the sprites this bar currently contains  #constructor  (@x, @y, @sprite = id:'bars' start-frame:0 middle-frame:1 stop-frame:2)->    @game = Game.phaser-game    @bar-parts = []    # method used by @draw to create the sprites     @draw-bar = (x, frame)->      sprite = @game.add.sprite x, @y, @sprite.id, frame      sprite.fixed-to-camera = yes      return sprite    @draw!  #updates the tracked value, destroys the bar and renders it new  update:(@current)!~>    for bar-part in @bar-parts      bar-part.destroy!    @bar-parts = []    @draw!  #renders the whole bar new with the current value  draw:!~>    used-width = Math.round @width / (@max / @current)    @bar-parts.push @draw-bar @x, @sprite.start-frame    for i from 1 til used-width      @bar-parts.push @draw-bar @x + i * 16px, @sprite.middle-frame    if @current is @max      @bar-parts.push @draw-bar @x + used-width * 16px, @sprite.stop-frame    else      @bar-parts.push @draw-bar @x + used-width * 16px, @sprite.middle-frame

I like the cropping idea, because my approach doesn't let me use arbitrary lengths.

But on the other hand I don't have to hold a sprite for a whole bar.

 

This is from a prototype and should be reimplemented with reuse of sprites. But ATM it works for me.

post-6791-0-56006000-1407935752.png

post-6791-0-81986500-1407935876.jpg

Link to comment
Share on other sites

  • 6 months later...

I like 1-800-STAR-WARS's method. It seems a bit overkill to use an entire sprite for a healthbar. 

 

One problem I ran into with 1-800-STAR-WARS's method is that Pixi's lineStyle method changes the line style that Phaser's debug methods use. So you end up with really thick lines if you set it to something like 5 pixels. Even if you use lineStyle on a child sprite, it still affects the parent sprite's debug lines. I'm not sure why. To get around this, I just set the lineStyle width back to one on the sprite. So instead of:

if (this._lasthp !== this.hp) {this.healthbar.clear();var x = (this.hp / this.totalhp) * 100;var colour = utils.rgbToHex((x > 50 ? 1-2*(x-50)/100.0 : 1.0) * 255, (x > 50 ? 1.0 : 2*x/100.0) * 255, 0);this.healthbar.beginFill(colour);this.healthbar.lineStyle(5, colour, 1);this.healthbar.moveTo(0,-5);this.healthbar.lineTo(config.tileSize * this.hp / this.totalhp, -5);this.healthbar.endFill();}

I did this:

if (this._lasthp !== this.hp) {this.healthbar.clear();var x = (this.hp / this.totalhp) * 100;var colour = utils.rgbToHex((x > 50 ? 1-2*(x-50)/100.0 : 1.0) * 255, (x > 50 ? 1.0 : 2*x/100.0) * 255, 0);this.healthbar.beginFill(colour);this.healthbar.lineStyle(5, colour, 1);this.healthbar.moveTo(0,-5);this.healthbar.lineTo(config.tileSize * this.hp / this.totalhp, -5);this.healthbar.lineStyle(1, colour, 1);}

That way the healthbar is still 5 pixels wide and debugging lines are 1 pixels (as they should be). 

Link to comment
Share on other sites

  • 2 months later...

My example: http://codepen.io/jdnichollsc/pen/oXXRMz

 

Regards, Nicholls  :D 

Thanks for posting this, Nicholls. I like it because it has a container so you can tell what the original health was regardless of what the current health is. What I don't like about though is that it uses a BitMap data object which is not nearly as light-weight as a graphic. 

Link to comment
Share on other sites

  • 3 months later...

Your example inspired me to create this little HealthBar ,i tried to make it customizable to fit all needs, i hope that it will be helpful.

link on github.

Unless you have like, only 1 or two characters with healthbars, creating a bitmap data object and updating it for each healthbar is too expensive an operation. I just create a single Phaser.Graphic which contains all of the healthbars for all of the characters in the game world. Here's what it looks like:

http://imgur.com/CZs5fwu

 

My current implementation though has the healthbars going down incrementally (like in your example). You can do this with a tween or set interval:

 

var decrease = setInterval(function() {        if (intCount === increment) {            clearInterval(decrease);        } else {            defender.health = defender.health - (damage / increment);        }        intCount++;    }, 50);
Link to comment
Share on other sites

 

Unless you have like, only 1 or two characters with healthbars, creating a bitmap data object and updating it for each healthbar is too expensive an operation. I just create a single Phaser.Graphic which contains all of the healthbars for all of the characters in the game world. Here's what it looks like:

http://imgur.com/CZs5fwu

 

My current implementation though has the healthbars going down incrementally (like in your example). You can do this with a tween or set interval:

 

var decrease = setInterval(function() {        if (intCount === increment) {            clearInterval(decrease);        } else {            defender.health = defender.health - (damage / increment);        }        intCount++;    }, 50);

 

 

Perfect!  ^_^

Link to comment
Share on other sites

create: function() {        healthBar = this.add.sprite(0, 988, 'healthBar');        maxHealth = this.add.sprite(0, 1000, 'healthBar');        healthBar.anchor.setTo(0,1);        healthBar.scale.setTo(1, 0.5);        maxHealth.anchor.setTo(0,1);        maxHealth.alpha = 0.5;                healthBar.fixedToCamera = true;        maxHealth.fixedToCamera = true;}bulletHitPlayer: function(player, bullet) {        this.game.cameraShaker.setupShake(10);        bullet.kill();                player.health -= 10;          healthBar.scale.setTo(player.health/100, 0.5);        if (player.health <= 0) {            player.kill();                    }    }

The above is my simplistic implementation of the health bar. The maxHealthBar outlines the full health and is always visible to let the player know approximately what percentage they are at. 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...