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

2021/1/31

Need help with delay

XApple15 XApple15

2021/1/31

#
Hello everyone! I faced a problem this night, when i tried to set some images over an actor every 1 sec while he`s pressing the "c" button , but when i run the program, this instantly finishes showing them, like i can see only the last image ( i == 6) . What could be the issue? Thanks !
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.List;
/**
 * Write a description of class Job1 here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Job1 extends Jobs
{
    boolean FinishedCutting = false;
    long LastTime, CurrentTime;  
    private int i;
    public void act() 
    {
        Cutting();
    }    
    
    public  void Cutting()
    {
        if(Greenfoot.isKeyDown("c") == true && FinishedCutting == false )
        {
            for( i=1; i<=6 ; i++ )
               { 
                 setImage( "cut" + i + ".png" );
                 if( i == 6  ) // checks if all images have been shown
                   { 
                       FinishedCutting=true;
                       Bed bed = new Bed();
                       getWorld().addObject(bed,200,200);
                   }    
                 if ( Greenfoot.isKeyDown("c") == false ) // checks if C is still pressed
                    {
                        return; 
                    }
                 LastTime = System.currentTimeMillis(); 
                 
                 while ( LastTime + 1000 <= System.currentTimeMillis() ) // delay of 1 sec between showing every image
                 { 
                     
                 }
               } 
        }
        
        if( Greenfoot.isKeyDown("x")) // deletes this object if X is pressed
        {
            getWorld().removeObject(this);  
        }
    }
        
   
}
RcCookie RcCookie

2021/1/31

#
It has to be >= in the while loop:
 while ( LastTime + 1000 <= System.currentTimeMillis() )
However this may not work properly, you will need need to manually tell the world to repaint by calling
getWorld().repaint();
after every time you change the image. Another tip: You can replace this
while(someExpression()) {

}
with this:
while(someExpression());
danpost danpost

2021/2/1

#
The use of while is primarily used to perform some action(s) repeatedly until some condition fails, all without any delay. Better, and more simply, might be the following:
import greenfoot.*;

public class Job1 extends Jobs
{
    private int i; // timer 

    public void act() 
    {
        cutting();
        removing();
    }
    
    private void cutting()
    {
        if (i == 301) return; // finished
        if (Greenfoot.isKeyDown("c"))
        {
            if (i%60 == 0) // each second (or on key press)
            {
                setImage("cut"+(i/60+1)+".png");
                if (i/60 == 5) getWorld().addObject(new Bed(), 200, 200); // on last image
            }
            i++; // run timer
        }
        else if (i%60 != 0) i = i-(i%60)+60; // allows each key press to advance image
    }
    
    private void removing()
    {
        if (Greenfoot.isKeyDown("x")) getWorld().removeObject(this);
    }
}
RcCookie RcCookie

2021/2/1

#
However this system requires a framerate of 60 FPS, not more and not less
XApple15 XApple15

2021/2/1

#
danpost wrote...
The use of while is primarily used to perform some action(s) repeatedly until some condition fails, all without any delay. Better, and more simply, might be the following:
import greenfoot.*;

public class Job1 extends Jobs
{
    private int i; // timer 

    public void act() 
    {
        cutting();
        removing();
    }
    
    private void cutting()
    {
        if (i == 301) return; // finished
        if (Greenfoot.isKeyDown("c"))
        {
            if (i%60 == 0) // each second (or on key press)
            {
                setImage("cut"+(i/60+1)+".png");
                if (i/60 == 5) getWorld().addObject(new Bed(), 200, 200); // on last image
            }
            i++; // run timer
        }
        else if (i%60 != 0) i = i-(i%60)+60; // allows each key press to advance image
    }
    
    private void removing()
    {
        if (Greenfoot.isKeyDown("x")) getWorld().removeObject(this);
    }
}
I think this is for 60fps framerate, isn’t it? I’d like for aprox 3 fps
XApple15 XApple15

2021/2/1

#
RcCookie wrote...
It has to be >= in the while loop:
 while ( LastTime + 1000 <= System.currentTimeMillis() )
However this may not work properly, you will need need to manually tell the world to repaint by calling
getWorld().repaint();
after every time you change the image. Another tip: You can replace this
while(someExpression()) {

}
with this:
while(someExpression());
This worked! Thank you!
XApple15 XApple15

2021/2/1

#
Thank you everyone!
RcCookie RcCookie

2021/2/1

#
If you want to do this properly you need to keep using System.currentTimeMillis(), but not in a while loop, for example like this:
import greenfoot.*;

public class Job1 extends Job {

    public static final long CUT_TIME_DIF = 1000;
    public static final int MAX_CUT = 6;

    long lastCutTime = 0l;
    int currentCut = 0;
    boolean finishedCutting = false;

    public void act() {
        cut();
        remove();
    }

    public void cut() {
        if(!Greenfoot.isKeyDown("c") || finishedCutting) {
            lastCutTime = 0l;
            return;
        }
        if(System.currentTimeMillis() > lastCutTime + CUT_TIME_DIF) {
            lastCutTime = System.currentTimeMillis();
            currentCut++;
            setImage("cut" + currentCut + ".png");
            if(currentCut = MAX_CUT) finishCutting();
        }
    }

    private finishCutting() {
        finishedCutting = true;
        getWorld().addObject(new Bed(), 200, 200);
    }

    public void maybeRemove() {
        if(Greenfoot.isKeyDown("x")) getWorld().removeObject(this);
    }
}
danpost danpost

2021/2/1

#
XApple15 wrote...
I’d like for aprox 3 fps
Just change all 60 to 3 and the 301 to 16.
RcCookie RcCookie

2021/2/1

#
But its still fixed to a specific framerate. That means if there occures lag it ain't delay 1 second. Also on ~3 fps you won't hit perfect 3 seconds. You are much more precise by actually measuring time
XApple15 XApple15

2021/2/1

#
Alright. Thank you for help !
danpost danpost

2021/2/1

#
RcCookie wrote...
But its still fixed to a specific framerate. That means if there occures lag it ain't delay 1 second. Also on ~3 fps you won't hit perfect 3 seconds. You are much more precise by actually measuring time
At 3fps, if there is any lag, it would be pretty much guaranteed to be a coding issue as it would have the equivalent time of 20 normal act cycles to perform just one. Also, a key could be pressed and released in as quickly as about 1/20 of a second. The user might have to hold a key down an extended amount of time for an action to occur at 3fps.
RcCookie RcCookie

2021/2/4

#
Yes but if you actually are to change the framerate you will be fine. Also I think that it’s just the much more legit version because it’s not hard-coded. And on higher framerates, it will be a lot more precise when lag occurs. If people would get away from using these slow, fixed framerates they could actually get a much smoother experience overall
danpost danpost

2021/2/4

#
XApple15 wrote...
I have like 40 pictures showing one by one with a delay of 0,5 sec , so that’s 2 FPS which is a low framerate , this should not be the issue here
You should probably run your scenario at normal speed (60fps ~ 50speed) and just change the image every 30 frames. For most scenarios, using frames makes for more consistent behavior. Any lag could throw timing of interplay of actors off when using system time.
You need to login to post a reply.