This site requires JavaScript, please enable it in your browser!
Greenfoot back
programmar
programmar wrote ...

2012/2/4

Making an HP bar

1
2
programmar programmar

2012/2/4

#
I know this is quite a stretch, but I am going to try to make an HP bar in my fighting game. Whenever a projectile hits a fighter, I want to have the hp bar decrease a little, until that fighter runs out of it and dies. I'd like to know what codes I can use do this. Any help is greatly appreciated :)
programmar programmar

2012/2/4

#
I've made a variable that says " private int hp = 50 " and now I need to find out how to make this value decrease with every hit.
Builderboy2005 Builderboy2005

2012/2/4

#
It all depends on how you detect whether or not your character is being hit. Modidying the health bar is as simple as:
hp -= #amount;
But unless you already have a way to detect being hit there will be nowhere to put this code. Can you already detect being hit?
Duta Duta

2012/2/5

#
I notice danpost has made a scenario (presumably because of this topic) on this: click here
programmar programmar

2012/2/5

#
Yes, the characters can already detect being hit. They emit a little battle cry when the are :P. So I used your code, and here's what getting hit looks like for one character
private void getattacked()  
    {  
        Actor Thunderbolt;  
        Thunderbolt = getOneObjectAtOffset(0, 0, Thunderbolt.class);  
       
      if (Thunderbolt !=null)  
      {  
        World world;  
        world = getWorld();  
        world.removeObject(Thunderbolt);  
        Greenfoot.playSound("shock.wav");  
        hp -= 1;
    }  
how do I start to make the hp bar now?
programmar programmar

2012/2/5

#
Okay, I have the bar from danpost's demo. How do I tie in the HP variable to make the bar work?
danpost danpost

2012/2/5

#
Download scenario 4114, referenced above. Play with it a little, and look at the code. You may want to make minor changes to the code (where specified) and play a little more to see how it functions. Pay particular attention to the code in the Smiley class as this is the basics you will need to access/change the hp value (which I call value, being generic). Of course, you would be replacing 'int change = ...' and 'bar.add(change);' to just 'bar.subtract(1);'. Also, line 10 in the Smiley class could simply be 'Bar bar = bg.bar;'. Once you get a grasp on how everything is put together there, you can start building your hp bar. To build the bar: 1) Create a sub-class of Actor named 'Bar' 2) Download scenario 4114 as mentioned above by Duta 3) Copy/paste the code in the Bar class of download to the new Bar class in your scenario 4) Add relavent statements in World class of download to the World class of your scenario (any statements or statement groups the refer to the bar) 5) Make the appropriate change in your Actor class to change the bar value The only thing left is the final touches - adjust the parameters of the bar constructor, as needed (the strings could be "", if wanted) - adjust the location (x, y) given in the addObject(new Bar(), int, int) statement Do not hesitate to post up with questions or concerns. Best regards.
danpost danpost

2012/2/5

#
Sorry, I was building my last post when you posted in. Instead of 'hp -= 1;', you will be using 'bar.subtract(1);' as stated above. The public methods in the Bar class are void add(int), void subtract(int), and int getValue(). These are what you should use to retrieve/change the value of the bar. The only thing is, you need to get a reference to the bar first (which you will be putting in the world, and you already have a reference to the world). So, 'world.bar.subtract(1);' would work.
programmar programmar

2012/2/5

#
Alright, I have the bar and game over. However Greenfoot says "cannot find symbol- variable bar" on the fighter's page. Here's what the hit identifier on my fighter's code looks like:
private void getattacked()
    {
     Actor Ember;
     Ember = getOneObjectAtOffset(0, 0, Ember.class);
     
      if (Ember !=null)
      {
        World world;
        world = getWorld();
        world.removeObject(Ember);
        Greenfoot.playSound("burn.wav");
    }
     Actor Ember2;
     Ember2 = getOneObjectAtOffset(0, 0, Emberl.class);
     
      if (Ember2 !=null)
      {
        World world;
        world = getWorld();
        world.removeObject(Ember2);
        Greenfoot.playSound("burn.wav");
        world.bar.subtract(1);
    }
And here's what my background code looks like:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.awt.Color;
/**
 * Write a description of class bg1 here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class bg1 extends World
{
    /**
     * Constructor for objects of class bg1.
     * 
     */
    public Bar bar = new Bar("Pikachu", "Health Points", 100,100);
    public bg1()
    {    
        // Create a new world with 600x400 cells with a cell size of 1x1 pixels.
        super(600, 400, 1); 
        addObject(bar, 250,40);

        prepare();
    }
    /**
     * Prepare the world for the start of the program. That is: create the initial
     * objects and add them to the world.
     */
    private void prepare()
    {
        Ground ground = new Ground();
        addObject(ground, 293, 393);
        Platform platform = new Platform();
        addObject(platform, 291, 193);
        Platform platform2 = new Platform();
        addObject(platform2, 107, 290);
        Platform platform3 = new Platform();
        addObject(platform3, 495, 283);
        Pikachu pikachu = new Pikachu();
        addObject(pikachu, 303, 105);
        Pikachu pikachu2 = new Pikachu();
        addObject(pikachu2, 295, 123);
        pikachu2.setLocation(179, 143);
        removeObject(pikachu2);
        pikachu.setLocation(88, 210);
        Charmander charmander = new Charmander();
        addObject(charmander, 517, 198);
        
    }
    GreenfootSound music = new GreenfootSound("19 Hyrule Field Main Theme.mp3");  
    public void started()  
    {  
        music.playLoop();  
    }  
    public void act()
    {
        if (bar.getValue() == 0)
        {
            showGameOver();
            Greenfoot.stop();
            return;
        }
    }
    private void showGameOver()
    {
        addObject(new Gameover(), getWidth() / 2, getHeight() / 2);
    }
    public void stopped()  
     {  
        music.stop();  
    } 
}
What do I have to do to let the fighter's code identify "bar"?
danpost danpost

2012/2/5

#
The problem is you are getting a reference to a generic world, not the current world. Change lines 8 and 9 in the hit indentifier of your fighter's code to
bg1 world;
world = (bg1) getWorld();
and try to compile then.
programmar programmar

2012/2/6

#
Okay, it can compile now.
import greenfoot.*;
import java.awt.Color;

public class Bar extends Actor
{
//  The following six values can be adjusted to suit your needs
    final int BAR_WIDTH = 100; // the color portion of the bar
    final int BAR_HEIGHT = 10; // the color portion of the bar
    final int BREAK_PERCENT = 20; // the percentage amount that changes the color of the bar
    final boolean BREAK_LOW = true; // true: with low-percent values bar is red, else green; false: vise versa
    final Color SAFE_COLOR = Color.GREEN;
    final Color DANGER_COLOR = Color.RED;
    
    int value = 0; // updated value of bar
    int lastValue = 0; // previously recorded value of bar
    int maxValue = 0; // the maximum value of bar
    String refName = ""; // the title string (who or what the meter/bar is for)
    String units = ""; // the unit of measure of the bar (any quantitative standard of measurement)  
    
    public Bar(String referenceName, String unitType, int initValue, int maximumValue)
    {
        refName = referenceName;
        units = unitType;
        maxValue = maximumValue;
        add(initValue);
    }
    
    private void newImage()
    {
        int imgWidth = BAR_WIDTH + 10 * (units.length() + refName.length() + 1);
        int barValue = (int) (BAR_WIDTH * value / maxValue);
        GreenfootImage image = new GreenfootImage(imgWidth, 20);  
        image.setColor(Color.BLACK);
//  Un-comment the following two statements, as well as those commented in BackGround class, for a different view
//         image.fill();
//         image.setColor(Color.WHITE);
//  Do not un-comment this statement.  If the two lines above are active, activate those commented in BackGround class.
        image.drawString(refName, 5, 14);
        image.drawString("" + value + " " + units, refName.length() * 10 + BAR_WIDTH, 14);
        image.drawRect(refName.length() * 8 - 2, (int) (8 - BAR_HEIGHT / 2), BAR_WIDTH + 3, BAR_HEIGHT + 3);
        if (value > 0)
        {
            if (BREAK_LOW)
            {
                if (value > (int) (BREAK_PERCENT * maxValue / 100)) image.setColor(SAFE_COLOR);
                else image.setColor(DANGER_COLOR);
            }
            else
            {
                if (value < (int) (BREAK_PERCENT * maxValue / 100)) image.setColor(SAFE_COLOR);
                else image.setColor(DANGER_COLOR);
            }
            image.fillRect(refName.length() * 8, (int) (10 - BAR_HEIGHT / 2), barValue, BAR_HEIGHT);
        }
        setImage(image);  
    }
    
    public void add(int amount)
    {
        value += amount;
        checkValue();
        newImage();
    }
    
    public void subtract(int amount)
    {
        value -= amount;
        checkValue();
        newImage();
    }
    
    private void checkValue()
    {
        if (value < 0) value = 0;
        if (value > maxValue) value = maxValue;
    }
    
    public int getValue()
    {
        return value;
    }
}
It still doesn't make the bar go down. Do I have to change anything in this code?
danpost danpost

2012/2/6

#
The problem would be in the call to this class (in another class).
danpost danpost

2012/2/6

#
The only thing you should ever change in the Bar class are the first six final variable VALUES (lines 7 through 12) and the COMMENTING/UN-COMMENTING of lines 35 and 36. Except for, maybe, removing '+ value + " " + units' from the drawSting within line 39 (if you do not want to show the actual value next to the bar). EDITED: The above no longer applies. The newer, updated version of the Bar class is fully functional without editing. All required methods are available to modify the Bar object.
programmar programmar

2012/2/10

#
Thanks so much! I got it to work now. I'm going to try to make the second HP bar. Is this possible?
danpost danpost

2012/2/10

#
Absolutely. You could conceivably have hundreds. I guess it could be used for equalizer bars as well. With multiple bars, you might want in your world class 'Bar bars = { new Bar(...) };' and then you can refer to them as 'bars' and 'bars' and if you want to be more specific, add final ints where the index is set to a descriptive name for that bar; like 'bars' and 'bars' with 'final int PLAYER_1 = 0;' and 'final int PLAYER_2 = 1;'.
There are more replies on the next page.
1
2