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

2018/12/9

Abstract World, Health Bar

fittirc04 fittirc04

2018/12/9

#
Hey guys, could use your help if you don't mind. I've been banging my head against this code for 3 hours, trying to get the healthBar to update correctly. I have a scenario with up to 6 worlds. I need the healthBar to update and carry over to the other worlds. It was working okay with just one world, prior to doing creating the abstract world. I'll post the code only pertaining to the HealthBar: AbstractWorld:
public void prepare(){
        setPlayer();
        healthBar(); 
        setEnemies();
        setWalls();
        setExit();
        showScore();
    }
public abstract HealthBar getHealthBar();
public abstract void healthBar();
All Area Worlds have a getter and method to add the bar:
public HealthBar getHealthBar(){
        return healthBar;
    }
public void healthBar(){
        HealthBar healthBar = new HealthBar();
        addObject(healthBar, 800, 25);
        showText("HEALTH", 800, 10);
    }
HealthBar code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.lang.Object;
public class HealthBar extends Actor
{
    //If you want to change the amount of health the player has, do it here
    int health = 10;
    int barWidth = 160;
    int barHeight = 15;
    int reduceHealth = (int)barWidth/health;
    
    public HealthBar()
    {
        drawBar();
    }    
    public void act() 
    {
        drawBar();       
    }    
    private void drawBar()
    {
        //Create an empty Greenfoot Image and assign it to a variable
        setImage (new GreenfootImage (barWidth, barHeight));
        GreenfootImage myImage = getImage();
        //Draw the border and fill it with a color
        myImage.setColor(Color.WHITE);
        myImage.drawRect(0, 0, barWidth + 1, barHeight + 1);
        myImage.setColor(Color.RED);
        myImage.fillRect(1, 1, health*reduceHealth, barHeight);   
    }  
    
    /*
     * Recommend setting up formal parameter for damage to accept actual paramters of damage
     * from different types of monsters.
     */
    public void loseHealth()
    {
        //Method for actor to call to lose health
        health --;
    }
    
    public void gainHealth()
    {
        health++;
    }
}
Method call from enemy actor that uses the loseHealth method:
public void damagePlayer(){
        Actor Player = getOneIntersectingObject(Player.class);
        AbstractWorld aWorld = (AbstractWorld)getWorld();
        HealthBar healthBar = aWorld.getHealthBar();
        if (Player != null){                                    
            if (touchingPlayer == false)
            {
                healthBar.loseHealth();
                touchingPlayer = true;
            }
        }
        else{
            touchingPlayer = false;
        }
    }
Any help most appreciated!
cbh4ou cbh4ou

2018/12/9

#
danpost danpost

2018/12/10

#
A couple things about your code: (1) instead of a field and a getter method in each Area World class, you can simply add them into the AbstractWorld class and inheritance apply them to all Area worlds. The getter method itself is not actually needed at all, provided the field has public access. Also, by making the field static and only creating a HealthBar object in your initial Area world, all areas can use the same health bar:
// in AbstractWorld
public static HealthBar healthBar;
// in Area worlds
public Area???()
{
    super(HEIGHT, WIDTH, CELL_SIZE);
    healthBar = new HealthBar(); // only in initial Area World
    prepare();
}

public void healthBar()
{
    addObject(healthBar, 800, 25);
    showText("HEALTH", 800, 10);
}
(2) You do not need to explicitly import the java.lang.Object class (all classes extend the Object class; so, therefore, already there); (3) In the enemy class code given, you prematurely get the abstract world and its health bar (you only need to access them if (a) there is an intersecting Player class object and (b) touchingPlayer is false). Your damagePlayer method could be written as:
public void damagePlayer()
{
    boolean lastTouching = touchingPlayer;
    touchingPlayer =  getOneIntersectingObject(Player.class) != null;
    if (!lastTouching && touchingPlayer ) AbstractWorld.healthBar.loseHealth();
}
or even as:
public void damagePlayer()
{
    if (touchingPlayer != (getOneIntersectingObject(Player.class) != null) && touchingPlayer = !touchingPlayer) AbstractWorld.healthBar.loseHealth();
}
This last way says "If there is a change in the state of intersecting a Player object and that recorded change is to a touching state, then lose health".
You need to login to post a reply.