Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Health bar in right side bar or in a status passage

edited January 2017 in Help! with 2.0
Hey,

I'm trying to add a health and a mana bar to my game. The healthbar and manabar supposed to change their lengths when the $health and $mana values change. I have a "stowable" right side bar that uses the Sugarcube 2 style to open and close. Now, I simply add the HTML code as is:
<div class="health-bar" data-total="1000" data-value="1000">
  <div class="bar">
  	  <div class="hit"></div>
  </div>
</div>

to the story passage that is tasked to display status related data to the player. At this point I became to suspect that the structure of the HTML code (more precisely the class hierarchy) was not respected by SugarCube 2. This is because the result ended up being all over the place. Meanig that the elements did not line up on eachother rather got scattered.

Here's the CSS code:
health-bar {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  width: 200px;
  height: 20px;
  padding: 5px;
  background: #ddd;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px;
  position: relative;
}
.bar {
  background: #c54;
  width: 100%;
  height: 10px;
  position: relative;
  
  transition: width .5s linear;
}

.hit {
  background: rgba(255,255,255,0.6);
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 0px;
  
  transition: width .5s linear;
}

This was obviously added to the stylesheet of the story. It addresses all 3 html elements that were declared above. We are creating a healthbar that plays a transition (we could call animation) that decreases the health bar over time leaving a lower opacity (shadow) of the health bar behind, which then aligns with the health bar that overlays it as it decreases.

Now the JavaCode is a macro that I simply add to a link and use it to decrease the health bar using a fixed value.
/% Main passage %/
<<decrease_HP>>

JS code:
// Reference the elements of the health bar
$(document).ready(function()
{
  var hitBtn = hBar = $('.health-bar'),
      bar = hBar.find('.bar'),
      hit = hBar.find('.hit');
}

// Define macro to test the health bar:
Macro.add( "decrease_HP",
 {
    handler : function(){
// grab HTML defined data values
var total = hBar.data('total'),
        value = hBar.data('value');
    
    if (value < 0) {
	// we are dead transition to game end
      return;
    }
    // max damage is essentially quarter of max life
    damage = 100;
    var newValue = value - damage;
    // calculate the percentage of the total width
    var barWidth = (newValue / total) * 100;
    var hitWidth = (damage / value) * 100 + "%";
    
    // show hit bar and set the width
    hit.css('width', hitWidth);
    hBar.data('value', newValue);
    
    setTimeout(function(){
      hit.css({'width': '0'});
      bar.css('width', barWidth + "%");
    }, 500);
    
    if( value < 0){
      // dead, dead and dead, go to Game End
    }
}
  });

Now, the code will most likely not work, because I've just written it on my phone without syntax check or linting. I only wanted to provide as much info as I could out of the top of my head until I get back to my computer.

Anyways, I have two problems with my solution:
1. The health bar HTML elements are not aligned as they are supposed (on top of eachother overlaying one another) instead they are rendered below eachother. I suspect there's a better way to define HTML in sugarcube passages, but no idea how.

2. The health bar does not react to value change, meaning the transition can't be seen nor the result of the transition (a lower health value presented on the health bar). Now, the transition part is not that important to me, but I at least want to see the results of a decreased health bar in my RightSideBar passage.

Any help would be welcome!
Thank you!

Comments

  • You forgot to state which method you are using to add a right sidebar to your story, knowing this lets us know the exact HTML structure of the page which could be important when trying to work out why CSS is not working correctly. Based on your comment history I am going to assume you are using the method decribed in the [SugarCube 2.7.2] Creating A Panel Similar To The UI-Bar thread.

    re: your CSS

    Some care is needed when adding Line-break in your passage code because by default they are converted into br elements and these elements can effect how CSS works. If you inspect the HTML generated for the example you gave you will see it looks like the following:
    <div class="health-bar" data-total="1000"><br>  <div class="bar" style="width: 100%;"><br>  	  <div class="hit" style="width: 0%;"></div><br>  </div><br></div>
    
    ... you can suppress those br elements by adding Line Continuation markup to your StoryRightSidebar example.
    <div class="health-bar" data-total="1000">\
    	<div class="bar">\
    		<div class="hit"></div>\
    	</div>\
    </div>\
    

    re: everything else

    All your other issues are a result of timing.

    A. The assignment of variables on document ready.

    This code wont work for three reasons

    1. That event occurs before the contents of your Story Javascript passage is processed so you can't use it to do something, but even if that was not the case...

    2. Those elements don't exist until after the first passage and the StoryRightSidebar are rendered, but even if this was not the case...

    3. Those elements are destroyed and recreated each time the Reader traverses from one passage to another.

    note: Moving the declaration of those variable into the body of the decrease_HP macro won't help for the reasons described in the next point.

    B. Calling your decrease_HP macro

    1. Within the first passage of your story:

    Again the elements you are trying to reference won't exist yet because the contents of the StoryRightSidebar passage is not processed until after the contents of the first passage is rendered thus your code gets run too early.

    2. Within any passage other than the first passage of your story:

    In this case the elements will exist so your code will work on them BUT those modified elements will be destroyed and replaced with new ones when the contents of the StoryRightSidebar passage is processed and rendered.

    The following solution uses variables to track the current state of health and damage.

    a. StoryInit passage
    <<set $totalHealth to 1000>>
    <<set $health to $totalHealth>>
    <<set $damage to 0>>
    

    b. StoryRightSidebar passage
    <div class="health-bar">\
    	<div class="bar">\
    		<div class="hit"></div>\
    	</div>\
    </div>\
    

    c. Story Javascript area
    postrender["Update Health Bar"] = function (content, taskName) {
    	var hBar = $('#right-ui-bar-body .health-bar'),
    			bar = hBar.find('.bar'),
    			hit = hBar.find('.hit');
    	var total = State.variables.totalHealth,
    			value = State.variables.health,
    			damage = State.variables.damage,
    			hitWidth = 0,
    			barWidth = (value / total) * 100,
    			delayReset = false;
    	
    	if (damage != 0) {
    		hitWidth = (damage / value) * 100;
    		value -= damage;
    		barWidth = (value / total) * 100;
    		State.variables.health = value;
    		State.variables.damage = 0;
    		delayReset = true;
    	}
    
    	hBar.data('total', total);
    	hBar.data('value', value);
    	hit.css('width', hitWidth + "%");
    	bar.css('width', barWidth + "%");
    	
    	if (delayReset) {
    		setTimeout(function(){
    			hit.css({'width': '0'});
    			bar.css('width', (State.variables.health / State.variables.totalHealth) * 100 + "%");
    		}, 500);
    	}
    };
    

    d. To test add the following to a passage, it can be the first passage of your story.
    <<set $damage to 100>>
    
  • edited January 2017
    This code seems really neat, both the right sidebar and the HP tracking. Might have to use this.

    That said, when HP drops to the same value as the damage or below, the bar disappears, which is a bit odd. Might also be interesting if there was a darker section behind the healthbar indicating the total HP size compared to your current HP once it starts dropping.
  • An issue not touched on by anyone else so far as I've noticed. The CSS selector for the health bar element itself is incorrect in your example, since health-bar is a class.

    Your example showed:
    health-bar {
    
    When it should have been the following:
    .health-bar {
    

    That said, you'd probably be better of using an ID for the health bar element itself, rather than a class since it's a unique element.
  • The CSS selector for the health bar element...
    thank you for pointing this out to @DairynGM.

    I did notice that fact and corrected it in my own test-case but I forgot to remark on it during my write-up. (I blame this oversight on the wife, who started tapping her foot with impatient about 2/3 the way through the construction of my previous comment, she wanted to go out for lunch. lol)
  • edited January 2017
    Hmm. So what would you use to heal HP then?

    Also thinking about duplicating this code and using it for a mana bar.
  • edited January 2017
    Thank you for the long exhaustive explanation. I learned more from that than reading the documentation for an hour.

    About the code (missing "."): as mentioned before, I wrote this down on my phone without checks. I just needed to communicate a detailed idea.

    Yes, your assumption about the right side bar is correct! I'm using that code indeed.

    I assume this healthbar implementation that you presented here is scalable. Meaning that I can place more items like these on my side bar and assign them to different values. In order to do that I simply need to specify the structure of the new healthbar and use the same CSS styling (maybe even grab some element using JS to color the bar to blue) and then implement the Update Mana Bar postrender task.

    Anyways, I'll definitely try it out, but more importantly read the reasons and understand why my solution never would've worked and try and build on the newly gained knowledge.

    Thanks again for the help, all of your help. I really appreciate it!

    Btw.: Does anyone know how to accept answers on the forum? I don't see any prompt popping up about accepting the answer on my phone or tablet.
  • Disane wrote: »
    Does anyone know how to accept answers on the forum?
    If this topic was created using the Ask a Question (or similar) option then there should be an option within the relevant comment. If the topic with created using the New Discussion option then you cant.
  • edited January 2017
    oh, thank you. I think this one is s discussion, but I'd really like to give you points or something for answering and giving such a hands-on solution.
  • edited January 2017
    I think if there was a points system, you'd look at greyelf and TheMadExile and be like...

    it__s_over_9000_.png
  • hehe, I see. Anyways, here's a screenshot of the UI that I made quickly thanks to the code that was posted:

    11b6a2dc9c.jpg
  • edited February 2017
    Mind posting that test scenario up? I'd be interested to see the code for the second bar and healing stuff.

    Also, did you notice when you retract or expand the right sidebar, it makes the text 'jump' instead of the smooth push the left sidebar traditionally gives the body text? I was wondering if there was a way to fix that.

    Also looking for a way to make sure the right sidebar starts the game hidden instead of visible. Currently I use Config.ui.stowBarInitially = true; for the left one, but no idea how to do it for the right.

  • DairynGM wrote: »
    Also looking for a way to make sure the right sidebar starts the game hidden instead of visible.
    Add the following to the end of the Right Sidebar's Javascript code.
    $rightUiBar.addClass('stowed');
    
  • Hey there! So, I kept experimenting with this healthbar by adding more than two. My code became a little bit overloaded with redundant code.

    Is there a way to instantiate this healthbar and have and assign a new current value and value to subtract from the bar length?
  • Basically what I want is something like
    var HealthBar = new Bar(health_bar, health_value, health_decrease);
    var StaminaBar = new Bar(stamina_bar, stamina_value, stamina_decrease);
    var Mana = new Bar(mana_bar, mana_value, mana_decrease);

    where mana_bar would be name of the bar: #mana-bar, mana_value would be the current mana value being displayed on by the Bar object, mana_decrease is the value that needs to be decreased from the mana_value (for the animation thingie, see code posts above.)

    I need to say, I have not looked up the instantiation of DOM stuff and how to apply this to already existing HTML and CSS, but I guess that is what I need to do here, but no idea how.
Sign In or Register to comment.