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

2018/4/22

Unable to loop/restart code

1
2
idk1234 idk1234

2018/4/22

#
Hi, It's been a while since I last programmed and now ... I'm stuck. I'm trying to get an object to move based on timings. But such code should only be executed in random order (as I tried to do in the "crush" method. However once the whole process completes in the "timerUp method, I want it to loop back into the "pauseTimer" method and I am unable to do so. I'm not sure if it's because the values of "pauseTimer" don't reset and therefore it gets messed up or if it is something else. I'm pretty confused to say the least, sorry for the messy code. Here's the code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

public class Crusher extends Crush
{
        
    private int timer = 10;
    private int timer2 = 151;
    private int timer3 = 300;
    private int pause = 100;
   /**
     * Act - do whatever the Crusher wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        mover2();
        pauseTimer();
        //timerDown();
        //turn2();
        //timerUp();
    }    
            
   /**
    * Check whether the control keys are being pressed, and turn if they are.
    */
   public void mover2()
   {
      if (Greenfoot.isKeyDown("G"))
        {
            setLocation(getX(), getY()+20);
       }
      if (Greenfoot.isKeyDown("T"))
      {
          setLocation(getX(), getY()-5);
       }          
    }
        
   public void crush()
   {
        if (Greenfoot.getRandomNumber(100)<10)
        {
            timerDown();    
            timerUp();
        }  
        else
        {
            pauseTimer();
        }
    }
    
    public void pauseTimer()
   {     
      if(pause>0)
        pause--;
      if(pause == 0)
      {
         crush();
      }
      
      if ( pause < 0) pause = 100;
      
       
      }
  
     
   public void timerDown()
   {
        if (timer < 150)
        {
            setLocation(this.getX(), this.getY() + 4);
            timer++;

        }  
 
   }
 
    public void timerUp()
    {
        timer3--;
        if (timer3 < 150 && timer3 > - 150)
        {
         setLocation(this.getX(), this.getY() - 4);
         timer3--;                     
        } 
        if (timer3 ==-150) pauseTimer();

        }
}
danpost danpost

2018/4/22

#
I certainly do not see where timer3 is reset (or having a value greater than -150 assigned to it other than for its initial value). In fact, I do not see where timer is re-assigned any value less than 150 either. I see no usage of timer2 and pause does not decrease to under zero, so, the resetting of it on line 60 will never happen.
idk1234 idk1234

2018/4/22

#
So how exactly would I reset the timers? Timer2 is not in use, correct, pretend it's not there.
danpost danpost

2018/4/22

#
idk1234 wrote...
So how exactly would I reset the timers? Timer2 is not in use, correct, pretend it's not there.
I would presume you would use the following statements somewhere within the methods codings:
pause = 100;
and
timer3 = 300;
and maybe
timer = 10;
idk1234 idk1234

2018/4/23

#
Hi, thanks for the replies. I have tried to add the statements above but it now just results in the object moving what seems like one pixel down, stopping for about 2 seconds, and the moving one pixel down again instead of the intended response: smooth movement down, and then smooth movement up and then pauseTimer(); I'll paste my code below, sorry for the inconvenience:
public class Crusher extends Crush
{
    private int timer = 10;
    private int timer3 = 300;
    private int pause = 100;
    /**
     * Act - do whatever the Crusher wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        pauseTimer();
    }    

    public void pauseTimer()
    {     
        if(pause>0)
            pause--;
        if(pause == 0)
        {
            crush();
        }

    }
    
    public void crush()
    {
        if (Greenfoot.getRandomNumber(100)<10)
        {
            timerDown();    
            timerUp();
        }  
        else
        {
            pause = 100;
            pauseTimer();
        }
    }

    public void timerDown()
    {
        if (timer > 150)
        {
            timer = 10;
        }
        if (timer < 150)
        {
            setLocation(this.getX(), this.getY() + 4);
            timer++;

        }  

    }

    public void timerUp()
    {
        timer3--;
        if (timer3 < 150 && timer3 > - 150)
        {
            setLocation(this.getX(), this.getY() - 4);
            timer3--;                     
        } 
        if (timer3 ==-150)
        {
            pause = 100;
            pauseTimer();
            timer3 = 300;
        }
    }
}
danpost danpost

2018/4/23

#
You probably need to totally re-work the class. What you want is three continuous actions (1) move down to some point; (2) move up to some point; and (3) pause for some given amount of time. The direction of movement can be given by a simple field:
private int direction = 1;
This value can be used for when it moves:
setLocation(getX(), getY()+direction);
I initialized it to '1' so that that it initially moves downward. When it reaches some point (which could be done with a timer), you would only need to change the field to '-1'. Now, it seems a bit much to have 3 different timers when only one is active at any one time. So, lets not look at the one "timer" field we are going to use as a timer (more of a regulator). We can add direction to it when moving down and up and it will increase from 0 to some given number (I am not exactly sure what you would use as your code is a bit convoluted; but, say 150 -- edit: I double the speed and halved it to 75), and then decrease back to 0. For the pause, which apparently is some random amount of time (again, not sure exactly what you would want), we can have the field go negative until it reaches some random value (which we will also need a field for). The 3 different circumstances can then be determined by the direction field and the "timer" field (1) direction is 1; (2) direction = -1 and timer > 0; and (3) direction = -1 and timer <= 0. A speed field can be added to control movement also. So, we have this:
public class Crusher extends Crush
{
    private int timer;
    private int speed = 2; // adjust as needed
    private int direction = 1
    private int pauseLimit;
    
    public void act()
    {
        timer += direction;
        if (timer >= 0)
        {
            setLocation(getX(), getY()+direction*speed);
        }
        if (timer == 75) // adjust as needed
        {
            pauseLimit = 30 + Greenfoot.getRandom(90); // adjust as needed
            direction = -1;
        }
        if (timer == -pauseLimit)
        {
            timer = 0;
            direction = 1;
        }
    }
}
If you want the crusher to start in a paused state, change the initial value of direction to -1 and set pauseLimit to some positive value. The value could be given as in line 17.
idk1234 idk1234

2018/4/23

#
Wow, thanks for that it works! I just have 2 more questions: 1.
If you want the crusher to start in a paused state, change the initial value of direction to -1 and set pauseLimit to some positive value. The value could be given as in line 17.
^ I set the direction to -1 and it just seems to pause forever? I need it to be paused and then start. 2. I also want the down and up movements to be random. That is, the code is to randomly choose whether to execute the movements or not. If not, it is to be paused (no movement) and then after the pause, the code should then randomly choose whether to execute the movements or not. Thanks in advance, this has been really helpful.
danpost danpost

2018/4/23

#
idk1234 wrote...
I set the direction to -1 and it just seems to pause forever? I need it to be paused and then start.
Did you set a positive initial value to pauseTimer as well?
I also want the down and up movements to be random. That is, the code is to randomly choose whether to execute the movements or not. If not, it is to be paused (no movement) and then after the pause, the code should then randomly choose whether to execute the movements or not.
Sounds like what you want is a variable pause time where the time paused are of different duration. Well, that is exactly what line 17 does; it just sets the random wait time in advance instead of testing a random value every moment it is paused. The 30 is the minimum wait time (about half a second and the 90 adds the variable part, making the wait time up to about 2 seconds long. As the comment on the line states, you can adjust these value as you see fit for your project.
idk1234 idk1234

2018/4/24

#
Sorry, clumsy me! Thanks for all the help this is exactly what I needed!
idk1234 idk1234

2018/4/26

#
Hi, I'm posting here again because it is to do with the same code. I have couple of questions.. again. 1. If I am using multiple "crushers" (Crusher_1, Crusher_2, etc.), how do I make sure they do not all go down at the same time after the pause? 2. I want to change the image to "Evil Crusher_On.png" when it is going down and then "Evil Crusher_Off.png" when it is going up. I added the code below to line 14
setImage("Evil Crusher_Off.png");
but I am unable to
setImage("Evil Crusher_On.png");
3. Is there any way to slow down the Crusher when it is on its way up (not the same speed as it went down)?.
danpost danpost

2018/4/26

#
(1) they each will act independently as is; (2) better than after line 14 would be after lines 19 and 24; (3) insert after line 18:
speed = 1;
timer = 150;
and after line 23:
speed = 2;
idk1234 idk1234

2018/4/26

#
Hi, the speed works, but the crushers just keep going up - doesn't stop
danpost danpost

2018/4/26

#
idk1234 wrote...
Hi, the speed works, but the crushers just keep going up - doesn't stop
Show revised class code.
idk1234 idk1234

2018/4/29

#
    private int timer ;
    private int speed = 5; // adjust as needed
    private int direction = -1;
    private int pauseLimit = 30;
    /**
     * Act - do whatever the Crush wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        // Add your action code here.
    }   

    public void crush()
    {
        timer += direction;
        if (timer >= 0)
        {
            setLocation(getX(), getY()+direction*speed);
            setImage("Evil Crusher_On.png");
        }
        if (timer == 100) // adjust as needed
        {
            pauseLimit = 100 + Greenfoot.getRandomNumber(505); // adjust as needed
            direction = -1;
            speed = 1;//
            timer = 150;//
        }
        if (timer == -pauseLimit)
        {
            timer = 0;
            direction = 1;
            speed = 2; //
            setImage("Evil Crusher_Off.png");
        }
        touch();

    }

    public void touch()
    {
        if (isTouching(Char.class))
        {
            removeTouching(Char.class);
        }
    }
}
I have this code in a class of which the "crushers" are a subclass of. They call the crush() method in their act method.
danpost danpost

2018/4/29

#
Change line 22 to this:
if (timer == 100 && direction == 1)
and change line 27 to:
timer == 200;
The product of the max timer value and speed in each direction must be the same (down: speed*max timer value = 2*100; up: =1*200).
There are more replies on the next page.
1
2