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

2021/2/20

What's wrong with my counter

BlueHand BlueHand

2021/2/20

#
I made a counter to represent the number of balls in the world, which starts at 5. When they collide, the counter goes down. When they are added through a mouse click, the counter goes up. Right now, my counter is stuck at 5. Is there a problem in the counter class or the ball class?
public class Counter extends Actor
{
    private int target;
    private GreenfootImage background;
    private static final Color TRANSPARENT = new Color (0,0,0,0);
    /**
     * Counter - constructor, initializes beginning variables and counter image to display zero
     */
    public Counter() 
    {
        target = 5;
        background = getImage();
        updateImage();
    }    
    
    /**
     * updateImage - updates the image on the screen to show the current counter value.
     */
    public void updateImage() 
    {
        GreenfootImage image = new GreenfootImage(background);
        GreenfootImage text = new GreenfootImage("" + target, 22, Color.BLACK, TRANSPARENT);
        image.drawImage(text, (image.getWidth() - text.getWidth())/2, (image.getHeight() - text.getHeight())/2);
        setImage(image);
    } 
    
    /**
     * Add - adds a new value to the current counter value
     */
    public void add(int score) 
    {
        target = target + score;
        updateImage();
    }
    
}
danpost danpost

2021/2/20

#
Show World subclass codes.
BlueHand BlueHand

2021/2/21

#
public class MyWorld extends World
{

    /**
     * Constructor for objects of class MyWorld.
     * 
     */
    public MyWorld()
    {    
        // Create a new world with 600x400 cells with a cell size of 1x1 pixels.
        super(600, 400, 1); 
        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()
    {
        Counter counter = new Counter();
        addObject(counter,50,20);
        for(int i = 1; i <= 5; i++)
        {
            int rand = Greenfoot.getRandomNumber(10);
            if(rand % 2 == 0) { // we got an even number
                Ball ball = new Ball(Greenfoot.getRandomNumber(360));
                addObject(ball,Greenfoot.getRandomNumber(520),Greenfoot.getRandomNumber(320));
            } else if (rand % 2 == 1) { // we got an odd number
                Ball ball = new Ball(Greenfoot.getRandomNumber(360));
                addObject(ball,Greenfoot.getRandomNumber(520),Greenfoot.getRandomNumber(320)); 
            }
        }
    }
    
 
    /**
     * Act - clicking the screen will cause a new ball to appear with a noise
     * it will be a random color and direction
     */
    public void act() 
    {  
        if (Greenfoot.mouseClicked (null))
        {  
            MouseInfo mouse = Greenfoot.getMouseInfo();
            for (int i = 0; i < 1; i++)
            {
                int direction = Greenfoot.getRandomNumber(360);
                addObject (new Ball(direction),mouse.getX(),mouse.getY());   
                Greenfoot.playSound("Harp.wav");
            } 
        }
    }
}
danpost danpost

2021/2/21

#
danpost wrote...
Show World subclass codes.
... and the ball class.
BlueHand BlueHand

2021/2/21

#
public class Ball extends Actor
{
    private int imgNum;
    private static int ballNumber = 5;
    private Counter myCounter;
    
    /**
     * Constructor - build the ball object with a counter object passed to it 
     */
    public Ball(Counter counter)
    {
        myCounter = counter;
    }
    
    /**
     * canSee - Return true if we can see an object of class right where we are.
     * False if there is no such object here.
     */
    public boolean canSee(Class className) 
    {
        Actor actor = getOneObjectAtOffset(0,0,className);
        return actor != null;
    }
    /**
     * hit - Try to hit an object of Class.
     * Only successful if there's such an object where we currently are. Otherwise it won't work
     */
    public void hit(Class className) 
    {
        Actor actor = getOneObjectAtOffset(0,0,className);
        if (actor != null)
        {
            getWorld().removeObject(actor);
        }
    }
    
    /**
     * Constructor1 - builds a Ball object with a specific direction that
     * can be different for each ball added to the world
     */
    public Ball() 
    {
        int rand = Greenfoot.getRandomNumber(7)+1;
        while (rand==2) 
        {
            rand = Greenfoot.getRandomNumber(7)+1;
        }
        if (rand % 2 == 0) 
            setImage("ball2.png");
        else
        {
            setImage("ball"+rand+".png");
        }
        checkCanSee();
        setRotation(Greenfoot.getRandomNumber(61) + 150);
    }
    
    /**
     * Constructor2 - builds a Ball object with a specific direction that
     * can be different for each ball added to the world
     * Building more than one constructor is called overloading.
     * Each constructor must have a different parameter list
     */
    public Ball(int direction) 
    {
        setRotation(direction);  
        imgNum = Greenfoot.getRandomNumber(7) +1;
        setImage("ball"+imgNum+".png");
    }
    
    /**
     * Act - do whatever the Ball wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        move (4);
        checkCanSee();
        if (atWorldEdge())
        {
            turn (153);
            changeImage();
        }   
        if (Greenfoot.mouseClicked (null))
        {  
            MouseInfo mouse = Greenfoot.getMouseInfo();
            ballNumber = ballNumber + 1;
            //there are more balls 
        }
    }
    
    /**
     * atWorldEdge - test if we're close to one of the edges of the world. 
     * Return true if we are otherwise return false.
     */
    public boolean atWorldEdge() 
    {
        if(getX() < 25 || getX()> getWorld().getWidth() - 25)
            return true;
        if(getY() < 25 || getY()> getWorld().getHeight() - 25)
            return true;
        return false;
    }
    
    /**
     * changeImage - change the image of the ball after it hits the edge of 
     * the world
     */
    public void changeImage() 
    {
        int rand = Greenfoot.getRandomNumber(7)+1;
        while (imgNum==rand) 
        {
            rand = Greenfoot.getRandomNumber(7)+1;
        }
        setImage("ball"+rand+".png");
    }
    
    /**
     * checkCanSee - checks if can see the balls and hits them.
     * the game is over
     */
    public void checkCanSee() 
    {
        if (canSee(Ball.class))
        {
            hit(Ball.class);
            Greenfoot.playSound("ClockChime.wav");
            ballNumber = ballNumber - 1;
        }
    }
}
danpost danpost

2021/2/21

#
BlueHand wrote...
Is there a problem in the counter class or the ball class?
Actually, neither. Although, you could remove lines 5 through 13 in the Ball class as they are not being used at all. There is an easy way to see how many balls are in the world. The World class instance method getObjects can be used to get a list of all balls in the world. The size of the list is the value your counter should be displaying at all times. Use a Counter field in MyWorld. Assign the Counter object that you add to the world to this field. Add a getScore method to Counter class. Have MyWorld act method compare and adjust count as needed. In MyWorld code above, you can remove lines 46, 47 and 51. A loop that executes exactly once is not a loop.
BlueHand BlueHand

2021/2/23

#
How would this look like? (I am new to Greenfoot and I have not heard of this before)
danpost danpost

2021/2/23

#
BlueHand wrote...
How would this look like? (I am new to Greenfoot and I have not heard of this before)
You would use the following line in the act code of your MyWorld class:
int ballCount = getObjects(Ball.class).size();
BlueHand BlueHand

2021/2/23

#
What's next? What should I put in my getScore method? Also why is it that there is size() at the end?
danpost danpost

2021/2/23

#
BlueHand wrote...
What should I put in my getScore method?
return ttargett;
Also why is it that there is size() at the end?
Because the size of the list tells you how many balls are in the world.
BlueHand BlueHand

2021/2/24

#
It says that it's an incompatible type with an unexpected return value
Super_Hippo Super_Hippo

2021/2/24

#
public int getScore()
{
    return target;
}
You need to login to post a reply.