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

2014/10/8

Too many rocks! D:

Ariadia Ariadia

2014/10/8

#
Okay, I'm trying to create a simulation where the character has to avoid these falling rocks. The problem is, the rocks keep multiplying. They're supposed to fall one at a time. Well, even two and four at a time would be fine. But, they multiply to the point that it creates a line of rocks falling from the sky. Here's the complete rock code:
public class Rock extends Antagonist
{
        private static final int EAST = 0;
        private static final int WEST = 1;
        private static final int NORTH = 2;
        private static final int SOUTH = 3;

        private int direction;
        
        private int rocksPresent;
        
        private int timer;
        
    public Rock()
    {
        timer = 100;
        rocksPresent = 0;
    }
    
    public void act() 
    {
        setDirection(3);
        move(5);
        checkTimer();
        findRocks();
        checkLocation();
    }    
   
    public void setDirection(int direction)
    {
        if ((direction >= 0) && (direction <= 3)) {
            this.direction = direction;
        }
        switch(direction) {
            case SOUTH :
                setRotation(90);
                break;
            case EAST :
                setRotation(0);
                break;
            case NORTH :
                setRotation(270);
                break;
            case WEST :
                setRotation(0);
                break;
            default :
                break;
        }
    }
    
    public void checkTimer()
    { 
        if (timer > 0)
        {
            timer --;
        }
        else
        {
            getWorld().addObject(new Rock(), Greenfoot.getRandomNumber(560), 0);
            timer =100;
            rocksPresent=rocksPresent+1;
        }
    }
    
    public void findRocks()
    {
        if (rocksPresent >=4)
        {
            Greenfoot.stop();
        }
    }
    
   public void checkLocation()
   {
      if (getY() == 283)
      {  
         getWorld().removeObject(this);  
        }  
    }
}
And the complete world code:
 

import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class PlanetEarth here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class PlanetEarth extends World
{
    
    private int timer;
    
    /**
     * Constructor for objects of class PlanetEarth.
     * 
     */
    public PlanetEarth()
    {    
        // Create a new world with 600x400 cells with a cell size of 1x1 pixels.
        super(600, 400, 1); 
        prepare();
        populateWorld();
    }

    /**
     * Prepare the world for the start of the program. That is: create the initial
     * objects and add them to the world.
     */
    private void prepare()
    {
        YOU you = new YOU();
        addObject(you, 54, 283);
        you.setLocation(47, 278);
        you.setLocation(301, 280);
        you.setLocation(304, 278);
    }
   
    public void populateWorld()
    {
        addObject(new Rock(), Greenfoot.getRandomNumber(560), 0);
    }
}
It works when compiled, but I can't seem to fix this one issue. Please help!
danpost danpost

2014/10/8

#
The problem is that each rock you create will run the code that creates a rock every (about) two seconds. So the number of rocks in your world are doubling (about) every two seconds. You should probably put the timer and the code for the creation of rocks in your world class (since you only have one world and its act method will not be executed many times per act cycle.
Ariadia Ariadia

2014/10/9

#
danpost wrote...
The problem is that each rock you create will run the code that creates a rock every (about) two seconds. So the number of rocks in your world are doubling (about) every two seconds. You should probably put the timer and the code for the creation of rocks in your world class (since you only have one world and its act method will not be executed many times per act cycle.
Thank you so much for answering so quickly. I have done what you suggested, but now the code only runs once. I would like it to loop so that every few seconds a new rock will fall from the sky. Does that make sense? How could I go about that? Please and thank you :D
danpost danpost

2014/10/9

#
Ariadia wrote...
Thank you so much for answering so quickly. I have done what you suggested, but now the code only runs once. I would like it to loop so that every few seconds a new rock will fall from the sky. Does that make sense? How could I go about that? Please and thank you :D
Please show the code you now have that is trying to add rocks every few seconds. That should be your PlanetEarth class, at this point.
Ariadia Ariadia

2014/10/9

#
danpost wrote...
Please show the code you now have that is trying to add rocks every few seconds. That should be your PlanetEarth class, at this point.
 public void checkTimer()
    { 
        if (timer > 0)
        {
            timer --;
        }
        else
        {
            addObject(new Rock(), Greenfoot.getRandomNumber(560), 0);
            timer =100;
            rocksPresent=rocksPresent+1;
        }
    }
It's the same code that was in the Rock class, but now it's just in the PlanetEarth class. Should I perhaps add a different timer?
danpost danpost

2014/10/9

#
You should not need a different timer; although the one you have should be in the PlanetEarth class with this code. Also, the call to 'checkTimer' should be in the act method of the PlanetEarth class. I do not believe that the 'rocksPresent' field is necessary. To get rocks present, use 'getObjects(Rock.class).size()'. However, from what I saw, the field is actually counting number of rocks created, as you are not subtracting from the field when a rock is removed from the world. If that is what you wanted to do, there is an easier way ... just ask how and I will instruct.
Ariadia Ariadia

2014/10/9

#
danpost wrote...
You should not need a different timer; although the one you have should be in the PlanetEarth class with this code. Also, the call to 'checkTimer' should be in the act method of the PlanetEarth class. I do not believe that the 'rocksPresent' field is necessary. To get rocks present, use 'getObjects(Rock.class).size()'. However, from what I saw, the field is actually counting number of rocks created, as you are not subtracting from the field when a rock is removed from the world. If that is what you wanted to do, there is an easier way ... just ask how and I will instruct.
Yeah, I should actually get rid of the rocksPresent because I do not need it anymore... The timer is in the PlanetEarth class, yet it does not reset. Is the act method different than the "public PlanetEarth()"? Should I add a "public void act" like in the other codes?
davmac davmac

2014/10/9

#
Is the act method different than the "public PlanetEarth()"?
I think you are very confused if you need to ask this question. Yes, the act method is different from "public PlanetEarth()" - the act method is named "act". "public PlanetEarth()" is clearly not named "act", and is in fact a constructor. Constructors are called only when an object is created.
danpost danpost

2014/10/9

#
Ariadia wrote...
The timer is in the PlanetEarth class, yet it does not reset. Is the act method different than the "public PlanetEarth()"? Should I add a "public void act" like in the other codes?
Yes. The 'public PlanetEarth' is an instance constructor executed when 'new PlanetEarth()' is called (or when your project is compiled or reset, if it is the initial world). The 'public void act()' is an instance method that greenfoot will call repeatedly, provided the world instance is active and the scenario is running. This is also true for the act methods of each and every actor within that active world. All will execute once and then repeat, creating what are called 'act cycles (or frames)'. So, yes (again) -- you should add a 'public void act' and call 'checkTimer' from it.
Ariadia Ariadia

2014/10/10

#
davmac wrote...
I think you are very confused if you need to ask this question. Yes, the act method is different from "public PlanetEarth()" - the act method is named "act". "public PlanetEarth()" is clearly not named "act", and is in fact a constructor. Constructors are called only when an object is created.
Well, I am new at using Greenfoot and programming in general. For some reason, I thought that a world didn't use an act method, because I had never seen one there. I understand now though, thank you.
danpost wrote...
Yes. The 'public PlanetEarth' is an instance constructor executed when 'new PlanetEarth()' is called (or when your project is compiled or reset, if it is the initial world). The 'public void act()' is an instance method that greenfoot will call repeatedly, provided the world instance is active and the scenario is running. This is also true for the act methods of each and every actor within that active world. All will execute once and then repeat, creating what are called 'act cycles (or frames)'. So, yes (again) -- you should add a 'public void act' and call 'checkTimer' from it.
Okay, thank you so much! It works! :D Now I just need to get them to disappear...
davmac davmac

2014/10/10

#
For some reason, I thought that a world didn't use an act method, because I had never seen one there.
Ok. You should read over the documentation for both the World and Actor classes in the API reference. You will see that they both have an "act" method. (Furthermore, you can put an "act" method in any class, though it will not have any special significance to Greenfoot unless it's in a World or Actor subclass).
You need to login to post a reply.