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

2013/5/28

How do i give my character health?

1
2
Neon147 Neon147

2013/5/28

#
Im gave my ship 3 lives but since i wanted a smaller image i decided to make another actor with the same image but alot smaller and depending on how many lives you have the left hand corner of the game will show how many ships you have remaining and once you reach 0 you wont come back. Problem is i keep getting a error: java.lang.NullPointerException at BadLaser.destroy(BadLaser.java:68) at BadLaser.act(BadLaser.java:30) at greenfoot.core.Simulation.actActor(Simulation.java:565) at greenfoot.core.Simulation.runOneLoop(Simulation.java:523) at greenfoot.core.Simulation.runContent(Simulation.java:213) at greenfoot.core.Simulation.run(Simulation.java:203) the class that is accessing the health task is my BadLaser: public void destroy() { spaceShip ship = (spaceShip) getOneIntersectingObject(spaceShip.class); lives life = (lives) getOneIntersectingObject(lives.class); GreenfootSound explodeAlien = new GreenfootSound("Explode.wav"); explodeAlien.setVolume(75); if(ship != null) { unlock = true; explodeAlien.play(); getWorld().removeObject(ship); getWorld().removeObject(this); life.losehealth(1); life.reset(); } } the life class itself is: private int health = 3; public lives() { GreenfootImage image = getImage(); image.scale(image.getWidth() - 1150, image.getHeight()-1150); setImage(image); setRotation(0); } public void losehealth(int loss) { health=health-loss; } public int getHealth() { return health; } public void reset() { spaceShip ship = new spaceShip(); getWorld().addObject(ship, 311,500); } I've also already placed the images depicting how many health you have left in my world class. I feel like this isnt the most efficient way of creating a health system so if someone has a better idea on how to do it im all ears, please help!
danpost danpost

2013/5/28

#
In your destroy method you are trying to get an intersecting 'lives' object, which returns null. Then later, you are trying to run methods ('loseHealth' and 'reset') on that non-existent intersecting object. You need to find another way to get a reference to the/a 'lives' object.
danpost danpost

2013/5/28

#
There are two main ways to do a health system. One is to have the field holding how many lives remain in the class of the object whose health is being tracked; the other is to have the field holding how many lives remain in the class that visually displays that value (whether it be a number or an image). I prefer the second way, mainly because it keeps things a bit more tidy. I am going to code a new Actor sub-class called ImageStrip, and its code follows:
import greenfoot.*;

public class ImageStrip extends Actor
{
  public static final boolean VERTICAL = true;
  public static final boolean HORIZONTAL = false;
  private static final int GAP = 10;
  private boolean orientation = HORIZONTAL;
  private GreenfootImage icon;
  private int initValue;
  private int value;

  public ImageStrip(String imgFilename, int count, boolean direction)
  {
    icon = new GreenfootImage(imgFilename);
    value = initValue = count;
    orientation = direction;
    updateImage();
  }

  private void updateImage()
  {
    int across = value;
    int down = 1;
    int xGap = GAP;
    int yGap = 0;
    if (orientation == VERTICAL)
    {
      across = 1;
      down = value;
      xGap = 0;
      yGap = GAP;
    }
    int wide = icon.getWidth()*across+xGap*(across+1);
    int high = icon.getHeight()*down+yGap*(down+1);
    GreenfootImage base = new GreenfootImage(wide, high);
    for (int j=0; j<down; j++) for (int i=0; i<across; i++)
    {
      int xOffset =xGap+i*(xGap+icon.getWidth());
      int yOffset = yGap+j*(yGap+icon.getHeight());
      base.drawImage(icon, xOffset, yOffset);
    }
    setImage(base);
  }

  public void adjustValue(int change)
  {
    if (value+change > initValue || value + change < 0) return;
    value += change;
    updateImage();
  }

  public int getValue()
  {
    return value;
  }
}
You can create an actor object from this class with:
ImageStrip lives = new ImageStrip("miniShip.png", 3, ImageStrip.HORIZONTAL);
This should create an actor that displays 3 small ships arranged horizontally. I did this coding on the fly, so there may be some typos (I did try to be careful). I do believe the logic is sound, however.
Neon147 Neon147

2013/5/28

#
Wow, thanks! By using this everytime my main ship will always have 3 lives in a world yes?
Neon147 Neon147

2013/5/28

#
Hmm image isnt setting no error just not showing up when i create it from the world class
danpost danpost

2013/5/28

#
Neon147 wrote...
Wow, thanks! By using this everytime my main ship will always have 3 lives in a world yes?
You will still have to control the subtracting of lives when a ship is destroyed by calling 'lives.adjustLives(-1);'; and also immediately follow that with 'if (lives.getValue() == 0) /* game over */'. Also, it might be easier if you just reset the location of the ship after the game over check (if not game over). That way, if you have any reference to objects in the spaceShip class, you will not lose them and have to reset them in the new spaceShip object.
danpost danpost

2013/5/28

#
Neon147 wrote...
Hmm image isnt setting no error just not showing up when i create it from the world class
I tested the code and it seems to work perfectly for me (no typos or errors). Displays the image appropriately; value adjustment works fine; no problems.
Neon147 Neon147

2013/5/28

#
i just placed this in my world class and nothing shows up its goes like this: public doodleLVL1() { // Create a new world with 600x400 cells with a cell size of 1x1 pixels. super.remove(); GreenfootImage image = getBackground(); image.scale(image.getWidth() - 60 , image.getHeight() - 60); //Spaceship spaceShip ship = new spaceShip(); addObject(ship,311,500); placements(); lives tot = new lives(); ImageStrip lives = new ImageStrip("mainship1.png", 3, ImageStrip.HORIZONTAL); }
danpost danpost

2013/5/28

#
I cannot say anything about the beginning of the code (as I am only familiar with the last two lines). Remove the 'lives tot = new lives();' line (in fact, you can remove the 'lives' class), and add the (ImageStrip) 'lives' object into the world.
Neon147 Neon147

2013/5/28

#
Yeah i just removed the lives class entirely, it still isnt showing up. Am i correct by placing ImageStrip lives = new ImageStrip("mainship1.png", 3, ImageStrip.HORIZONTAL); In the world class constructor? Or should it be placed elsewhere.
danpost danpost

2013/5/28

#
That is fine. Did you 'addObject(lives, /* x, y */ )' the object into the world?
Neon147 Neon147

2013/5/29

#
That's what i didn't do.
Neon147 Neon147

2013/5/29

#
Now it works, thanks so much again.
Neon147 Neon147

2013/5/29

#
Quick question could i possibly add a reset method in the imagestrip class that will place my ship back in it original location like this? public void reset() { getWorld().addObject(new spaceShip(),311,500); } and just called it whenever the ship dies?
danpost danpost

2013/5/29

#
You could, but you should probably put that code along with the call to decrement the value of the imagestrip object (which removes one of the images from the strip):
lives.adjustValue(-1);
if (lives.getValue > 0)
{
    setLocation(311, 500);
    // whatever else you might need done
}
else
{
    // game over code
}
Why bother removing the object just to add it back in!
There are more replies on the next page.
1
2