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

2018/11/11

Accuracy Scoreboard Question

weldon weldon

2018/11/11

#
I am making a space game where rockets shoot bullets at asteroids. I have two functional scoreboards in my world: one for the number of bullets fired and another for the number of asteroids hit. I also want to make a third, however it always displays zero no matter how many bullets have been fired and how many asteroids have been hit. The code for the Accuracy class is:
public class Accuracy extends Scoreboard{
    private int accuracy;
    private int asteroids;
    private int hundredAsteroids;
    private int bullets;
    public Accuracy(){
        super("Accuracy",0);
        asteroids=AsteroidsHit.score;
        bullets=BulletsFired.score;
    }

    /**
     * Act - do whatever the Accuracy wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        if(bullets!=0){ //prevents division by 0
            hundredAsteroids=asteroids*100;
            accuracy=hundredAsteroids/bullets;
            score=accuracy;
            printScore();
            asteroids=AsteroidsHit.score;
            bullets=BulletsFired.score;
        }   
    }
}
I realize that the actual accuracy calculation could be condensed quite a bit. It was expanded in an effort to fix the problem. The code for the Scoreboard class is:
public class Scoreboard extends Actor
{
    protected static int score;
    private String text;
    
    public Scoreboard(String label, int startingScore)
    {
        GreenfootImage img = new GreenfootImage(300,40);
        img.setColor(new Color(255,255,255));
        Font f=new Font("Tahoma",true,false,24);
        img.setFont(f);
        img.drawString(label + ": " + startingScore,5,35);
        setImage(img);
        text = label;
        score = startingScore;
    }
    
    public void changeScore(int howMuch) 
    {
        score = score + howMuch;
        GreenfootImage img = getImage();
        img.clear();
        img.drawString(text + ": " + score,5,35);        
    }    
    public void printScore(){
        GreenfootImage img = getImage();
        img.clear();
        img.drawString(text + ": " + score,5,35);  
    }
    public int getScore()
    {
        return score;
    }
}
danpost danpost

2018/11/11

#
weldon wrote...
I am making a space game where rockets shoot bullets at asteroids. I have two functional scoreboards in my world: one for the number of bullets fired and another for the number of asteroids hit. I also want to make a third, however it always displays zero no matter how many bullets have been fired and how many asteroids have been hit. << Code Omitted >>
You may have 3 Scoreboard object, but (for one thing) they all use the same score field value. The keyword static used in line 3 of the Scoreboard class makes the field a class field (as opposed to an instance field). Thus, the field belongs to the class itself and not to any particular object created from the class. Another issue is the placement of your counter fields (lines 2 through 5 in your Accuracy class). Each Scoreboard object will get its own fields with those attributes (name and type). As such, a change in one object will not induce any change in another. Are AsteroidsHit and BulletsFired also classes? Why? and also, why the Accuracy class? Basically, why are you making subclasses of the Scoreboard class? Remove them and also remove the word "static" from line 3 in the Scoreboard class. For each object you create from the Scoreboard class, their 'score' field will hold the required values (accuracy, asteroids hit, bullets fired and whatever). Have your world create them:
public class MyWorld extends World
{
    Scoreboard accuracy = new Scoreboard("Accuracy", 0);
    Scoreboard bullets= new Scoreboard("Bullets", 0);
    Scoreboard asteroidsHit = new Scoreboard("Asteroids hit", 0);
    // etc.

    public MyWorld()
    {
        super(600, 400, 1);
        addObject(accuracy, 120, 20);
        addObject(bullets, 120, 20);
        addObject(asteroidsHit, 120, 20);
        // etc.
    }
    // etc
}
You will also need a setScore method in the Scoreboard class. It can then be this:
import greenfoot.*;

public class Scoreboard extends Actor
{
    private int score;
    private String text;
    
    public Scoreboard(String label, int startingScore)
    {
        text = label;
        score = startingScore;
        GreenfootImage img = new GreenfootImage(300,40);
        img.setColor(new Color(255,255,255));
        Font f=new Font("Tahoma",true,false,24);
        img.setFont(f);
        setImage(img);
        printScore();
    }
    
    public void setScore(int value)
    {
        score = value;
        printScore();
    }
    
    public void changeScore(int howMuch)
    {
        score = score + howMuch;
        printScore();
    }
    
    public void printScore()
    {
        GreenfootImage img = getImage();
        img.clear();
        img.drawString(text + ": " + score,5,35);
    }
    
    public int getScore()
    {
        return score;
    }
}
Now, it probably will not be sufficient to just have getter methods for the Scoreboard objects in your MyWorld class (because a change in some of them should induce a recalculation in another (specifically, the accuracy value). So, instead, you will need adjust methods in your world class. Something like the following:
public void adjustBullets(int adjustment)
{
    bullets.changeScore(adjustment);
    accuracy.setScore(asteroidsHit.getScore()*100/bullets.getScore());
}

public void adjustAsteroidsHit(int adjustment)
{
    asteroidsHit.changeScore(adjustment);
    accuracy.setScore(asteroidsHit.getScore()*100/bullets.getScore());
}
weldon weldon

2018/11/11

#
Thanks, I adjusted it and it works now. I'm a bit new to Greenfoot, and I forgot that just using three instances of Scoreboard could be easier.
You need to login to post a reply.