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

2017/1/23

Why isn't my health reducing?

1
2
Jillis Jillis

2017/1/23

#
When i intersect my character (User) with an enemy (EnemyNormal), my health bar isn't decreasing? I can't find where i've gone wrong, help would be much appreciated! Healthbar class:
public class Healthbar extends Actor
{
    int health = 4;
    int healthBarWidth = 80;
    int healthBarHeight = 15;
    int healthPointPixels = (int)healthBarWidth/health;
    /**
     * Act - do whatever the Healthbar wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public Healthbar()
    {
        update();
    }
        public void act() 
    {
        update();
    }    
    public void update ()
    {
        setImage(new GreenfootImage(healthBarWidth + 2, healthBarHeight + 2));
        GreenfootImage myImage = getImage();
        myImage.setColor(Color.WHITE);
        myImage.drawRect(0, 0, healthBarWidth + 1, healthBarHeight + 1);
        myImage.setColor(Color.RED);
        myImage.fillRect(1, 1, health*healthPointPixels, healthBarHeight);
    }
    public void loseHealth()
    {
        health--;
    }
}
User:
public void hitEnemy()

Enemy:

 move(4);
        if (Greenfoot.getRandomNumber(100) < 10)
        {
            turn(Greenfoot.getRandomNumber(90) - 45);
        }
        if (getX() <= 100 || getX() >= getWorld().getWidth() - 100)
        {
            turn(180);
        }
        if (getY() <= 100 || getY() >= getWorld().getWidth() - 100)
        {
            turn(180);
        }
    {
        Actor enemynormal = getOneIntersectingObject(EnemyNormal.class);
        if(enemynormal != null)
        {
            World myWorld = getWorld();
            World1 world1 = (World1)myWorld;
            Healthbar healthbar = world1.getHealthBar();
            if(touchingenemy == false)
            {
                healthbar.loseHealth();
                touchingenemy = true;
                if(healthbar.health <=0)
                {
                    getWorld().removeObject(this);
                }
            }
        } else {
            touchingenemy = false;
        }
    }
World1: public Healthbar getHealthBar() { return healthbar; } Also, if i am to get this working in world1, will it also work in other created world classes? What will I need to do to enable it to work? just add the getHealthbar subroutine?
Super_Hippo Super_Hippo

2017/1/23

#
Try to use this line after line 22:
myImage.clear();
You can remove the act method and call the update method after losing health in the loseHealth method. For other worlds, it won't work exactly like it is right now. You either have to check in which world it is to cast getWorld to the right world class or you have a superclass for all your world and the getHealth method in that superclass.
Jillis Jillis

2017/1/24

#
Super_Hippo wrote...
Try to use this line after line 22:
myImage.clear();
You can remove the act method and call the update method after losing health in the loseHealth method. For other worlds, it won't work exactly like it is right now. You either have to check in which world it is to cast getWorld to the right world class or you have a superclass for all your world and the getHealth method in that superclass.
Ah thank you for your help but it still doesn't seem to work:(
public class Healthbar extends Actor
{
    int health = 4;
    int healthBarWidth = 80;
    int healthBarHeight = 15;
    int healthPointPixels = (int)healthBarWidth/health;
    /**
     * Act - do whatever the Healthbar wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public Healthbar()
    {
        update();
    } 
    public void update ()
    {
        setImage(new GreenfootImage(healthBarWidth + 2, healthBarHeight + 2));
        GreenfootImage myImage = getImage();
        myImage.clear();
        myImage.setColor(Color.WHITE);
        myImage.drawRect(0, 0, healthBarWidth + 1, healthBarHeight + 1);
        myImage.setColor(Color.RED);
        myImage.fillRect(1, 1, health*healthPointPixels, healthBarHeight);
    }
    public void loseHealth()
    {
        health--;
        update ();
    }
}
This is what I have changed (only the healthbar class) I added the line after line 22, removed the act method, and called the update method within the loseHealth method. Any more ideas? thanks a lot for your interest.
Jillis Jillis

2017/1/24

#
Also, i'm new to greenfoot, could you please explain to me how A superworld would work? So i have the superworld which contains all things that are in every World, then within each world subclass, can i create a prepare method to add on top of the superclass? Edit: Just realised I can stop being lazy and test this myself
Super_Hippo Super_Hippo

2017/1/24

#
Could you show the code in your World1 class?
Jillis Jillis

2017/1/24

#
Super_Hippo wrote...
Could you show the code in your World1 class?
{
    Healthbar healthbar = new Healthbar();
    /**
     * Constructor for objects of class World1.
     * 
     */
    public World1()
    {    
        // Create a new world with 600x600 cells with a cell size of 1x1 pixels.
        super(600, 600, 1); 
        prepare();
    }
    public Healthbar getHealthBar()
    {
        return healthbar;
    }
    /**
     * Prepare the world for the start of the program.
     * That is: create the initial objects and add them to the world.
     */
    private void prepare()
    {
        Wall wall1 = new Wall();
        addObject(wall1,300,30);
        
        Wall wall2 = new Wall();
        addObject(wall2,300,570);
        
        Wall wall3 = new Wall();
        wall3.turn(90);
        addObject(wall3,29,300);
        
        Wall wall4 = new Wall();
        wall4.turn(90);
        addObject(wall4,570,300);
        
        addObject(healthbar, 200, 570);
        
        setPaintOrder(Healthbar.class,Door.class,Wall.class);
    }
}
Super_Hippo Super_Hippo

2017/1/24

#
Oh... I see the problem now. You need a 'setImage(myImage)' at the end of the 'update' method.
danpost danpost

2017/1/24

#
Super_Hippo wrote...
Oh... I see the problem now. You need a 'setImage(myImage)' at the end of the 'update' method.
No -- that is not the problem. The first line creates and sets an image and the second gets a reference to it in 'myImage'. The image gets modified on the remaining lines; but, the image itself is still the one set to the actor.
Jillis Jillis

2017/1/24

#
Super_Hippo wrote...
Oh... I see the problem now. You need a 'setImage(myImage)' at the end of the 'update' method.
That would make sense... but for some reason it is still not changing! :( thank you for your help so far. This is what my latest version looks like:
public class Healthbar extends Actor
{
    int health = 4;
    int healthBarWidth = 80;
    int healthBarHeight = 15;
    int healthPointPixels = (int)healthBarWidth/health;
    /**
     * Act - do whatever the Healthbar wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
   public Healthbar()
    {
        update();
    }
   public void update ()
    {
        setImage(new GreenfootImage(healthBarWidth + 2, healthBarHeight + 2));
        GreenfootImage myImage = getImage();
        myImage.clear();
        myImage.setColor(Color.WHITE);
        myImage.drawRect(0, 0, healthBarWidth + 1, healthBarHeight + 1);
        myImage.setColor(Color.RED);
        myImage.fillRect(1, 1, health*healthPointPixels, healthBarHeight);
        setImage(myImage);
    }
   public void loseHealth()
    {
        health--;
        update();
    }
}
could it be something to do with touching the enemy not triggering? User:
public void hitEnemy()
    {
        Actor enemynormal = getOneIntersectingObject(EnemyNormal.class);
        if(enemynormal != null)
        {
            World myWorld = getWorld();
            World1 world1 = (World1)myWorld;
            Healthbar healthbar = world1.getHealthBar();
            if(touchingenemy == false)
            {
                healthbar.loseHealth();
                touchingenemy = true;
                if(healthbar.health <=0)
                {
                    getWorld().removeObject(this);
                }
            }
        } else {
            touchingenemy = false;
        }
    }
EnemyNormal:
public class EnemyNormal extends Actor
{
    /**
     * Act - do whatever the EnemyNormal wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        move(4);
        if (Greenfoot.getRandomNumber(100) < 10)
        {
            turn(Greenfoot.getRandomNumber(90) - 45);
        }
        if (getX() <= 100 || getX() >= getWorld().getWidth() - 100)
        {
            turn(180);
        }
        if (getY() <= 100 || getY() >= getWorld().getWidth() - 100)
        {
            turn(180);
        }
    }
}
Jillis Jillis

2017/1/24

#
oh just seen your post dan, so what can I do to create the image but not reset it each time?
Jillis Jillis

2017/1/24

#
perhaps set the image, then remove the first line of update () ?
danpost danpost

2017/1/24

#
Jillis wrote...
perhaps set the image, then remove the first line of update () ?
You could move line 17 to before line 13; but, it is not going to really change anything (other than that fact that you will not be creating a new image every act cycle).
Jillis Jillis

2017/1/24

#
Hm yeah. Is it something to do with when I return healthbar in the world class? Can I call that only once and then will it reduce?
danpost danpost

2017/1/24

#
Jillis wrote...
Hm yeah. Is it something to do with when I return healthbar in the world class? Can I call that only once and then will it reduce?
The World1 class code looks fine as far as the health bar is concerned (until you add more worlds, which can be dealth with later -- let us get the healthbar working first); and your Healthbar class looks good too. That leaves any and all places where you acquire the HealthBar object from the world. The code in the User class 'hitEnemy' method appears to decrease the health bar by 1 unit each time a new EnemyNormal object is touched. As a quick test, comment out the first and last 3 lines inside that method (lines 3 through 5 and lines 18 through 20); compile the world and then right click on the User object; manually execute the 'hitEnemy' method and observe the healthbar object (it should only work one timer per reset of the project when done manually if it works at all). Then, report back your findings.
Jillis Jillis

2017/1/24

#
Thanks dan for your help. And yes, I commented out those lines, and the healthbar executed once on each startup.
There are more replies on the next page.
1
2