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

2021/12/24

Actor touching another actor

1
2
xixEmilyxix xixEmilyxix

2021/12/24

#
I'm trying to make it so when my forager actor touches my flower actor (which is a parent class to pinkFlower, purpleFlower and yellowFlower) a method in the world class is called. However, it is not working. I also do not know how to call my stop() method from my bee class and how to remove the flower it has touched. I have nothing in my children flower classes except setting the image of them. This is the code i have for it: in the BeeWorld:
     public BeeWorld(int weatherVal)
    {
        //set background to main screen when button is pressed
        super(864, 540, 1);
        setBackground(new GreenfootImage("Background.png"));
        
        //add buttons
        btnAddDay = new Buttons();
        btnAddDay.setImage(new GreenfootImage("addDaybutton.png"));
        btnHelp = new Buttons();
        btnHelp.setImage(new GreenfootImage("helpButton.png"));
        btnEndSimulation = new Buttons();
        btnEndSimulation.setImage(new GreenfootImage("EndSimulationbutton.png"));
        addObject(btnEndSimulation, 50, 500);
        
        //run new day
        newDay();       
        
        //add the counter for the bee value
        showText("Bees: ",  810, 20);
                    
        //declare weatherValue 
        weatherValue = weatherVal;

                
        //set honey and nectar values
        nectarValue = 0;
        honeyValue = 0;       
        showText("Honey: " + honeyValue,  810, 110);
        showText("Nectar: " + nectarValue,  810, 80); 
    


public void beeTouchingFlower()
    {
        //when bee touches flower:
        //remove flower
        
        //stop bee moving
        
        
        //add to nectar value and update nectar counter
        updateNectar();
    }  

     public void updateNectar()
    {
        //add to nectar value
        nectarValue = nectarValue + 2;
        
        //add the counter for the nectar value
        showText("Nectar: " + nectarValue,  810, 80);        
    } 
    
and in the Flower class:
    public void act() 
    {
        //check if bee is touching flower
        beeTouchingFlower();        
    } 
    
    public void beeTouchingFlower()
    {
        //check if bee is touching flower
        Flower f = (Flower) getWorld().getObjects(Flower.class).get(0);
        if(f != null && f.touchingForager())
        {
            //run beeTouchFlower in world class
            BeeWorld b = (BeeWorld) getWorld();
            b.beeTouchingFlower();
        }
    }
danpost danpost

2021/12/24

#
You should probably keep code related to bee touching flower in the Forager class, including the nectar value, which can be made a public static field set to zero in your BeeWorld constructor. In Forager, with method called from act:
public static nectarValue;

public void findFlower()
{
    if (isTouching(Flower.class))
    {
        removeTouching(Flower.class);
        nectarValue += 2;
        getWorld().showText("Nectar: "+nectarValue, 810, 80);
    }
    ...
}
In BeeWorld:
public BeeWorld()
{
    super(...);
    Forager.nectarValue = 0;
    ...
}
Spock47 Spock47

2021/12/24

#
1.
xixEmilyxix wrote...
and in the Flower class:
    public void act() 
    {
        //check if bee is touching flower
        beeTouchingFlower();        
    } 
    
    public void beeTouchingFlower()
    {
        //check if bee is touching flower
        Flower f = (Flower) getWorld().getObjects(Flower.class).get(0);
        if(f != null && f.touchingForager())
        {
            //run beeTouchFlower in world class
            BeeWorld b = (BeeWorld) getWorld();
            b.beeTouchingFlower();
        }
    }
In line 10, you set f to the first flower in the world (the one at index 0). So, at any time it is always only the first flower for which the touching is checked. Replace lines 10 and 11 by:
    if (this.touchingForager())
"this" is a reference to the current flower; that way each flower is checking for itself, whether it is touching a forager. 2. To remove the touched flower, add the following line before the end of the if statement (line 16):
    b.removeObject(this);
3. It is important to differentiate between a class and an object. A class is basically just a blueprint for something, it defines what attributes all objects of this class have. An object is a concrete instance of a class. E.g. you could define a "Human" class that says "every human has a feat!" and then "Amelia Earhart" is one object of this class and "Albert Einstein" is another object of this class. Since every human has a feat, you can ask each human for her/his feat, e.g. "Hey Amelia, what's your feat?" and she can answer "Pilot". But asking just for the "feat of the human" does not make sense, since no one knows whether you ask for Albert's feat of Amelia's feat (or for any other human's feat). Therefore, if you want to ask for an attribute (e.g. "feat"), you need an object whose attribute you want to know (e.g. "Amelia Earhart"). In java, you write this question by first denoting a reference to the object, a dot and then the attribute (or getter method name), e.g. "albert.getFeat()" and this makes only sense, if there is an object "albert". -> If you want to stop the movement of A bee, you have to know WHICH bee you want to stop. You want to stop the bee that touched the flower, so you have to remember which bee touched the flower and give this information to the place, where you need it. I. Change method "beeTouchingFlower" of the BeeWorld class, so that it accepts a Bee parameter and use it to stop the bee:
    public void beeTouchingFlower(final Bee touchingBee)
    {
        //when bee touches flower:
        //remove flower
         
        //stop bee moving
        touchingBee.stop();
         
        //add to nectar value and update nectar counter
        updateNectar();
    }  
That way the method announces, that it needs to know which bee it should stop. That means, wherever you want to call the method, greenfoot will remind you to say which bee has to be stopped. II. Change the "beeTouchingFlower" method of the Flower class to determine which bee is touching the flower and to give this information to the method of the world:
    public void beeTouchingFlower()
    {
        //check if bee is touching flower
        final touchingBee = this.getOneIntersectingObject(Bee.class);
        if (touchingBee != null)
        {
            //run beeTouchFlower in world class
            BeeWorld b = (BeeWorld) getWorld();
            b.beeTouchingFlower(touchingBee);
            b.removeObject(this);
        }
    }
III. If you want to have the flower removed within the method of the world, again the world needs to know which flower should be removed. Use what you learned in steps I and II to give this information to the world method's call and to use it there. Live long and prosper, Spock47
xixEmilyxix xixEmilyxix

2021/12/24

#
danpost wrote...
You should probably keep code related to bee touching flower in the Forager class, including the nectar value, which can be made a public static field set to zero in your BeeWorld constructor. In Forager, with method called from act:
public static nectarValue;

public void findFlower()
{
    if (isTouching(Flower.class))
    {
        removeTouching(Flower.class);
        nectarValue += 2;
        getWorld().showText("Nectar: "+nectarValue, 810, 80);
    }
    ...
}
In BeeWorld:
public BeeWorld()
{
    super(...);
    Forager.nectarValue = 0;
    ...
}
Ive added what you and spock said. Im getting multple errors. In the beeworld, the methods inside beeTouchingFlower are not working - saying they cannot be applied to given types. In Forager, 'public static nectarValue' says it expects an identifier. And in the flower class, both intersecting object lines are saying they expect an identifier and in the if statement it says ''cannot find symbol variable - touchingBee' This is what i have now:
public class Flower extends Actor
{
    public Flower()
    {
        //set image of this type of flower
        setImage(new GreenfootImage("pinkFlower.png"));
        GreenfootImage image = getImage();  
        image.scale(image.getWidth() - 500, image.getHeight() - 500);  
        setImage(image);
    }
    
    public void act()
    {
        //check if bee is touching flower
        beeTouchingFlower();        
    }
    
        public void beeTouchingFlower()
    {
        //check if bee is touching flower
       final touchingBee = this.getOneIntersectingObject(Bee.class);
       final touchingFlower = this.getOneIntersectingObject(Flower.class);
       if (touchingBee != null)
          {
             //run beeTouchingFlower in world class
             BeeWorld b = (BeeWorld) getWorld();
             b.beeTouchingFlower(touchingBee);
             b.removeObject(this);
           }
    }
    
    public boolean touchingForager()
    {
        //check if touching bee then return it
        return isTouching(Forager.class);        
    }
}
public class Forager extends Bee
{
    public static nectarValue;
    public Forager()
    {
        //set image of forager
        setImage(new GreenfootImage("foragerBee.png"));
        GreenfootImage image = getImage();  
        image.scale(image.getWidth() - 1350, image.getHeight() - 750);  
        setImage(image);
    }

    public void act()
    {
        //walk randomly
        randomWalk();
        findFlower();
    }
    
    public void findFlower()
    {
        if (isTouching(Flower.class))
        {
            removeTouching(Flower.class);
            nectarValue += 2;
            getWorld().showText("Nectar: " +nectarValue, 810, 80);
        }
    }
}
public class BeeWorld extends World
{
    //declare variables
    int beeValue;
    Flower PinkFlower;
    Flower PurpleFlower;
    Flower YellowFlower;
    int weatherValue;
    Hive Hive;
    Bee Forager;
    Bee Worker;
    Bee Queen;
    public static Flower flower;
    int dayValue;
    int honeyValue;
    int nectarValue;
    Actor btnAddDay, btnHelp, btnEndSimulation;
    /**
     * Constructor for objects of class BeeWorld.
     * 
     */
    public BeeWorld(int weatherVal)
    {
        //set background to main screen when button is pressed
        super(864, 540, 1);
        
        //set nectar value
        Forager.nectarValue = 0;
        
        setBackground(new GreenfootImage("Background.png"));
        
        //add buttons
        btnAddDay = new Buttons();
        btnAddDay.setImage(new GreenfootImage("addDaybutton.png"));
        btnHelp = new Buttons();
        btnHelp.setImage(new GreenfootImage("helpButton.png"));
        btnEndSimulation = new Buttons();
        btnEndSimulation.setImage(new GreenfootImage("EndSimulationbutton.png"));
        addObject(btnEndSimulation, 50, 500);
        
        //run new day
        newDay();       
        
        //add the counter for the bee value
        showText("Bees: ",  810, 20);
                    
        //declare weatherValue 
        weatherValue = weatherVal;

                
        //set honey and nectar values
        nectarValue = 0;
        honeyValue = 0;       
        showText("Honey: " + honeyValue,  810, 110); 
    }
    public void beeTouchingFlower(final Bee touchingBee, final Flower touchingFlower)
    {
        //when bee touches flower:
        //stop bee moving
        touchingBee.stop();
        touchingFlower.removeObject(this);
    } 
danpost danpost

2021/12/24

#
xixEmilyxix wrote...
In Forager, 'public static nectarValue' says it expects an identifier.
Sorry, forgot to add the type. Should be:
public static int nectarValue;
danpost danpost

2021/12/24

#
xixEmilyxix wrote...
This is what i have now: << Codes Omitted >>
The Flower class should be pretty much bare of code:
import greenfoot.*;

public class Flower extends Actor
{
    public Flower()
    {
        //set image of this type of flower
        GreenfootImage image = new GreenfootImage("pinkFlower.png");
        image.scale(image.getWidth() - 500, image.getHeight() - 500);  
        setImage(image);
    }
}
However, you can eliminate the need in extending this class with this:
import greenfoot.*;

public class Flower extends Actor
{
    public String color;
    
    public Flower(String pigment)
    {
        color = pigment;
        GreenfootImage image = new GreenfootImage(color+"Flower.png");
        image scale(image.getWidth()-500, image.getHeight()-500);
        setImage(image);
    }
}
creating them elsewhere as follows, giving examples:
Actor flower = new Flower("pink");

// or
Actor flower = new Flower("yellow");
danpost danpost

2021/12/24

#
You can even have the world randomly pick a color for a new flower, with the following:
// with a global array listing the possible flower colors
private static final String[] FLOWER_COLOR = { "pink", "purple", "yellow" }; // add more as needed

// to creatie a random colored flower, use this
int flowerColorNum = Greenfoot.getRandomNumber(FLOWER_COLOR.length);
Actor flower = new Flower(FLOWER_COLOR[flowerColorNum]);
danpost danpost

2021/12/24

#
The // add buttons section in your BeeWorld constructor should come after the call to newDay. Or, better, they should be added to the world in your newDay method (still created from within the constructor, however).
xixEmilyxix xixEmilyxix

2021/12/24

#
danpost wrote...
You can even have the world randomly pick a color for a new flower, with the following:
// with a global array listing the possible flower colors
private static final String[] FLOWER_COLOR = { "pink", "purple", "yellow" }; // add more as needed

// to creatie a random colored flower, use this
int flowerColorNum = Greenfoot.getRandomNumber(FLOWER_COLOR.length);
Actor flower = new Flower(FLOWER_COLOR[flowerColorNum]);
Ive made these changes and i am getting an error where the flowers cannot be made. (I used the random creating flowers) this is what i have for the flower code:
    public void lowTemperature()
    {
        //add random coloured flowers to the bee world
        int flowerColorNum = Greenfoot.getRandomNumber(FLOWER_COLOR.length);
        Actor flower = new Flower(FLOWER_COLOR[flowerColorNum]);
        addObject(new Flower(), 500, 500);
        addObject(new Flower(), 100, 300);
        addObject(new Flower(), 200, 400);
        addObject(new Flower(), 100, 100);
        addObject(new Flower(), 700, 400);
        addObject(new Flower(), 800, 200);
        
        //add bees to the bee world
        Worker Worker = new Worker ();
        Queen Queen = new Queen ();
        Forager Forager = new Forager ();
        addObject(new Queen(), 500, 250);
        addObject(new Forager(), 400, 150);
        addObject(new Forager(), 450, 200);
        addObject(new Forager(), 500, 220);
        addObject(new Forager(), 550, 250);
        
        //add the hive to the bee world
        Hive Hive = new Hive ();
        addObject(new Hive(), 650, 400);        
    }
public class Flower extends Actor
{
    //create variable to be able to change colour of flowers
    public String colour;
    
    public Flower(String pigment)
    {
        //set image of flowers
        colour = pigment;
        GreenfootImage image = new GreenfootImage(colour+"Flower.png");  
        image.scale(image.getWidth() - 500, image.getHeight() - 500);  
        setImage(image);
    }
    
    public void act()
    {
        //check if bee is touching flower
        beeTouchingFlower();        
    }
    
        public void beeTouchingFlower()
    {
        //check if bee is touching flower
       final touchingBee = this.getOneIntersectingObject(Bee.class);
       final touchingFlower = this.getOneIntersectingObject(Flower.class);
       if (touchingBee != null)
          {
             //run beeTouchingFlower in world class
             BeeWorld b = (BeeWorld) getWorld();
             b.beeTouchingFlower(touchingBee);
             b.removeObject(this);
           }
    }
    
    public boolean touchingForager()
    {
        //check if touching bee then return it
        return isTouching(Forager.class);        
    }
}
I am also getting the same errors from earlier on both lines that are like: final touchingFlower = this.getOneIntersectingObject(Flower.class); in the flower class, saying identifier expected on both . And in the bee class i am getting an error for the line: Forager.nectarValue = 0; where it says it cannot find it.
xixEmilyxix xixEmilyxix

2021/12/24

#
danpost wrote...
The // add buttons section in your BeeWorld constructor should come after the call to newDay. Or, better, they should be added to the world in your newDay method (still created from within the constructor, however).
Ive also made this change here:
    public BeeWorld(int weatherVal)
    {
        //set background to main screen when button is pressed
        super(864, 540, 1);
        
        //set nectar value
        Forager.nectarValue = 0;
        
        setBackground(new GreenfootImage("Background.png"));
        
        //run new day
        newDay();       
        
        //add the counter for the bee value
        showText("Bees: ",  810, 20);
                    
        //declare weatherValue 
        weatherValue = weatherVal;

                
        //set honey and nectar values
        nectarValue = 0;
        honeyValue = 0;       
        showText("Honey: " + honeyValue,  810, 110); 
    }
  private void newDay()
    {
        //start new day
        //remove all objects
        List objects = getObjects(null);
        removeObjects(objects);
        
        //increase day value
        dayValue++;
        
        //increase honey value
        updateHoney();
        
        //add buttons
        btnAddDay = new Buttons();
        btnAddDay.setImage(new GreenfootImage("addDaybutton.png"));
        btnHelp = new Buttons();
        btnHelp.setImage(new GreenfootImage("helpButton.png"));
        btnEndSimulation = new Buttons();
        btnEndSimulation.setImage(new GreenfootImage("EndSimulationbutton.png"));
        addObject(btnEndSimulation, 50, 500);
        
        //run simulation again
        runSimulation();
        
        //random chance to see if bee dies
        
        //add bee every 5 days
        if (dayValue%5 == 0)
        {
           addObject(new Forager(), 550, 250);           
        }
    }
danpost danpost

2021/12/24

#
Remove line 22 and the field it refers to from above in the same class. After line 41, you need to add the btnAddDay into the world. Also, after line 43, you need to add the btnHelp into the world.
danpost danpost

2021/12/24

#
It might be best to add a getRandomFlower method:
private Actor getRandomFlower()
{
    int colorNum = Greenfoot.getRandomNumber(FLOWER_COLOR.length);
    return new Flower(FLOWER_COLOR[colorNum]);
}
Then replace lines 4 through 11 in the lowTemperature method with the following:
addObject(getRandomFlower(), 500, 500);
addObject(getRandomFlower(), 100, 300);
addObject(getRandomFlower(), 200, 400);
addObject(getRandomFlower(), 100, 100);
addObject(getRandomFlower(), 700, 400);
addObject(getRandomFlower(), 800, 200);
xixEmilyxix xixEmilyxix

2021/12/24

#
danpost wrote...
Remove line 22 and the field it refers to from above in the same class. After line 41, you need to add the btnAddDay into the world. Also, after line 43, you need to add the btnHelp into the world.
Ive implemented all this and it is still giving me the nectar error, also. what about the other errors i was getting that i said above? this is what i have now in regards to the nectarvalue:
public class BeeWorld extends World
{
    //declare variables
    int beeValue;
    Flower PinkFlower;
    Flower PurpleFlower;
    Flower YellowFlower;
    int weatherValue;
    Hive Hive;
    Bee Forager;
    Bee Worker;
    Bee Queen;
    public static Flower flower;
    int dayValue;
    int honeyValue;
    Actor btnAddDay, btnHelp, btnEndSimulation;
    private static final String[] FLOWER_COLOR = { "pink", "purple", "yellow" };
    /**
     * Constructor for objects of class BeeWorld.
     * 
     */
    public BeeWorld(int weatherVal)
    {
        //set background to main screen when button is pressed
        super(864, 540, 1);
        setPaintOrder(Buttons.class);
        
        //set nectar value
        Forager.nectarValue = 0;
        
        setBackground(new GreenfootImage("Background.png"));
        
        //run new day
        newDay();       
        
        //add the counter for the bee value
        showText("Bees: ",  810, 20);
                    
        //declare weatherValue 
        weatherValue = weatherVal;

                
        //set honey value
        honeyValue = 0;       
        showText("Honey: " + honeyValue,  810, 110); 
    }
public class Forager extends Bee
{
    public static int nectarValue;
    public Forager()
    {
        //set image of forager
        setImage(new GreenfootImage("foragerBee.png"));
        GreenfootImage image = getImage();  
        image.scale(image.getWidth() - 1350, image.getHeight() - 750);  
        setImage(image);
    }

    public void act()
    {
        //walk randomly
        randomWalk();
        findFlower();
    }
    
    public void findFlower()
    {
        if (isTouching(Flower.class))
        {
            removeTouching(Flower.class);
            nectarValue += 2;
            getWorld().showText("Nectar: " +nectarValue, 810, 80);
        }
    }
}
danpost danpost

2021/12/24

#
In the codes just given, I do not see any actual issues. I did notice the abundance of fields in your BeeWorld class. I get the feeling that most of them are not needed, particularly, those between lines 4 and 13, excepting line 8.
danpost danpost

2021/12/24

#
xixEmilyxix wrote...
it is still giving me the nectar error, also. what about the other errors i was getting that i said above?
These need to be resolved one at a time. However, you must supply (copy/paste) the entire error output you are getting, plus the related codes.
There are more replies on the next page.
1
2