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

2014/9/29

Trouble with spawning (not so) random object

christinem024 christinem024

2014/9/29

#
Hi! I've been in a programming class working with Greenfoot for about a month, and our first project is due next week. For reference, these are the instructions for the project: Create a Car class that represents a car running horizontally back and forth. 1. Modify the Car class to make the car image displayed correctly when it runs towards left side. 2. Add code to Car class to catch the “down” key. When user presses down key once, it drops an apple, pear or banana from the top of the “world”. The position of the starting point of dropped fruit is random. Which fruit that is dropped is also random. 3. Create a Fruit class that represents apple, pear, or banana based on which image is picked. The speed of fruit moving down should be slow (so we can call method move(1) in act() method of Fruit class. I'm having trouble with #2, in which I'm supposed to have the Car class catch the down key in order to drop the fruit. What should I do? The relevant code is as follows (The compiler stops at the Fruit class and says it does not recognize):
    String key = Greenfoot.getKey();  
    {
        if ("down".equals(key));
        int x = Greenfoot.getRandomNumber(getX());    
        int y = 0;
        addObject(new Fruit(), x, y);
    }
Thank you for your help!
danpost danpost

2014/9/29

#
If it says it does not recognize class Fruit, then you do not have a Fruit class in the project (spelling and case are important -- 'Fruit' is not 'fruit'). If it says it does not recognize method addObject, then the code is not in a class that extends World and the method needs a world instance to be executed on -- that is:
worldReference.addObject(...);
where 'worldReference' is a field declared by:
World worldReference;
that has a world instance assigned to it.
christinem024 christinem024

2014/9/29

#
Okay so I modified my world to add what you suggested, but I don't think I put it in the correct place. I have 2 classes: Car and Fruit (and yes, I made sure that the capitalization was correct, thank you for the suggestion). My World code:
import greenfoot.*;

public class CarWorld extends World
{

    public CarWorld()
    {    
        super(600, 400, 1);
        int w = 300;
        int h = 330;
        addObject(new Car(), w, h);
    }
    
    World WorldReference;
    worldReference.addObject(Fruit())
}
My Fruit class code looks like:
import greenfoot.*;
public class Fruit extends Actor
{

private int vSpeed = (1);
    
public void act()
{
    fall();
    if (Greenfoot.getRandomNumber(3) == 1) {
      setImage("pear.png");
    }
    if (Greenfoot.getRandomNumber(3) == 2) {
      setImage("bananas.png");
    }
    else {
      setImage("apple1.png");
    }
}

public void fall()
{  
     setLocation (getX() , getY() + vSpeed);
}
}
danpost danpost

2014/9/29

#
I am sorry if you misunderstood. I did not suggest you modify your world and the pseudo-code I gave was just a representation of what was involved in creating the correct code. Remove those lines, 14 and 15, that you just added to your CarWorld class. Your instructions say to put the code that adds the fruit into the world in your Car class, not the world class. However, because 'addObject' is a World class method, you cannot just say 'addObject(...)' in your Actor subclass, the Car class. You need to give the world instance that the fruit will be added into. The Car instance that the code is being executed for is in that world and that world can be referenced by using the Actor class method 'getWorld()', which returns the world that the car in currently in. Lines 10 through 18 of your Fruit class is first-off misplaced. You do not want the images of your fruit to be constantly changing as it falls. You want to have one of the images set when the fruit is being created and to remain constant during the fall. Just as your World subclass has a constructor that is run once each time your project is re-compiled or reset, your Actor subclasses can have constructors that executed once when an instance of that class is created (a world instance is created during re-compiling or resetting of the project, which causes the constructor of that class to execute; exactly the same way, the constructor of the actor class is executed when an actor instance is created). The constructor is called by using the 'new' keyword followed by the class name of the object to create and a pair of parenthesis. The code 'new Fruit()' will call the Fruit class constructor that starts with 'public Fruit()' (similar to line 6 of your CarWorld class above). This constructor for the Fruit class is where you want to set the images of your fruit. I suggest you get one random number and hold it in an int variable and check its value for which image to use. The way you coded it (lines 10 through 18) above, lines 10 throught 12 will act like they are not there at all because the rest of the code-set will completely ignore what it had done (a new random number is generated and checked, and you will average twice as many apples as bananas, with no pears).
christinem024 christinem024

2014/9/29

#
Thank you so much for your response!!! I didn't understand the difference between world and actors before. I'm going to try working on the code for a while.
christinem024 christinem024

2014/9/30

#
Hi! So I edited my CarWorld and it ended up like this:
import greenfoot.*;

public class CarWorld extends World
{

    public CarWorld()
    {    
        super(600, 400, 1);
        int w = 300;
        int h = 330;
        addObject(new Car(), w, h);
    }
    
    String key = Greenfoot.getKey();  
    {
        if ("down".equals(key));
        int x = Greenfoot.getRandomNumber(getHeight());    
        int y = 0;
        addObject(new Fruit(), x, y);
        int z = Greenfoot.getRandomNumber(3);
    {
    if (int z = 1);
        setImage("pear.png");
    }
    {
    if (int z = 2);
        setImage("bananas.png");
    }
    }
}
At line 22 it says ".class expected" I tried a couple of different edits but nothing worked. Any suggestions? Also, should the if statements regarding the pear and bananas be in a different place? (not part of the String Key section?)
Super_Hippo Super_Hippo

2014/9/30

#
Replace line 22 with
if (z == 1)
danpost danpost

2014/9/30

#
Again, you are using methods without objects within classes of different types -- that is, now you are using an Actor class method, 'setImage', in a World class, where the World class does not have a 'setImage' method (only the Actor class has one). There should be no more code within your CarWorld class beyond line 12 (except line 30 to end the class code). Your Car class should have an 'act' method with lines 14 through 19 (and line 29 to end the act method); and your Fruit class should have a constructor with the code that lines 20 through 28 are attempting. When your world is created, a Car instance is added to it. (done when world instance is created -- CarWorld constructor) When the Car object finds the 'down' key pressed, it creates a Fruit instance and adds it to the world. (done while the simulation is running -- act method of Car class) When a Fruit object is created, it gives itself a random image (pear, apple or banana). (done when fruit is created -- Fruit constructor)
christinem024 christinem024

2014/9/30

#
1
Super_Hippo Super_Hippo

2014/9/30

#
By the way, writing something outside methods which should actually do something, won't work.
christinem024 christinem024

2014/10/7

#
Hey everyone, So it's been a crazy week and I lost the flash drive that had my project on it (I learned my lesson). So I've been trying to recreate what I made and finish up the project. This is my CarWorld world
import greenfoot.*;
public class CarWorld extends World
{
    public CarWorld()
    {
        super(600, 400, 1);  
        int w = 300;  
        int h = 330;  
        addObject(new Car(), w, h); 
    }
}
Here is my Fruit Class (I have no image assigned to it and have three subclasses of fruit: apple, bananas, and pear)
import greenfoot.*;  

public class Fruit extends Actor  
{  

private GreenfootImage image1;
private GreenfootImage image2;
private GreenfootImage image3;

private int vSpeed = (1);

int z = Greenfoot.getRandomNumber(3);

    public Fruit()
    {
        image1 = new GreenfootImage("apple1.png");
        image2 = new GreenfootImage("bananas.png");
        image3 = new GreenfootImage("pear.png");
        if (z == 1) 
        {  
            setImage(image1);  
        }  
        if (z == 2) 
        {  
            setImage(image2);  
        }  
        if (z == 3) 
        {  
            setImage(image3);  
        }  
    }
      
    public void act()  
    {  
        fall();
    }  
  
    public void fall()  
    {    
        setLocation (Greenfoot.getRandomNumber(600) , 1 + vSpeed);  
    }  
}
Here is my Car class:
import greenfoot.*;
public class Car extends Actor
{
    public void act() 
    {
        move();
        dropFruit();
    }    
    
    public int speed = 5;
    
    public void move()
    {
        if ((speed > 0 && getX() == getWorld().getWidth()-1) ||  
            (speed < 0 && getX() == 0)) speed = -speed;  
        move(speed); 
        setImage(new GreenfootImage("carCopy.png"));
    }
    
    public void dropFruit()
    {
        String key = Greenfoot.getKey();    
        {  
            if ("down".equals(key));  
            {
                int x = Greenfoot.getRandomNumber(599);      
                int y = 1;  
                addObject(new Fruit(), x, y);  
            }
        }
    }
}
When I compile it, I get an issue with the "addObject(new Fruit(), x, y); " part (I understand now that this is not a method for Actors, but I don't know what to use instead to cause a Fruit instance when the Car class catches the down key). Any suggestions? Thank you danpost and Super_Hippo for your help.
danpost danpost

2014/10/7

#
All actors, like your Car object, hold hidden references to the worlds they are in. Refer to the Actor class API documentation and see what methods might help in this regard.
christinem024 christinem024

2014/10/7

#
I added
    public Fruit getFruit()
    {
        return Fruit;
    }
to CarWorld... I don't know what to do next.
danpost danpost

2014/10/7

#
Here is what you did to your CarWorld class. You added a method called 'getFruit' that should return a Fruit instance, but has code, 'return Fruit;', that returns a reference to the class named 'Fruit', not an instance of that class. I think, for now, you should remove that method from your CarWorld class. It is not related in any way with your problem of adding fruit into the world using code in your Car class, which is the class you should be working in. Review my first two posts.
davmac davmac

2014/10/7

#
When I compile it, I get an issue with the "addObject(new Fruit(), x, y); " part (I understand now that this is not a method for Actors, but I don't know what to use instead to cause a Fruit instance when the Car class catches the down key). Any suggestions?
Because the 'addObject' method is a World method, you need to qualify the method call with a World instance. In this case you can use the 'getWorld()' method to obtain a reference to such an instance. The code would look like this:
getWorld().addObject(new Fruit(), x, y); 
This really should have been covered in your class, I think.
You need to login to post a reply.