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

2017/3/7

How to stop a clock?

1
2
Fifilein Fifilein

2017/3/7

#
Hi! In my game there is an Actor called Schneg who escapes before an other Actor called Achtung. You need to survive 20 seconds and you win the game. If the Schneg hit the Achtung, you will lose the game and I want the clock to stop if you lose, but it does not work! Here is my code of the Achtung:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.awt.Color;
/**
 * Write a description of class Achtung here.
 * 
 * @author (Fifilein) 
 * 
 * @version (1.4)
 */
public class Achtung extends Quatrel
{
    int horizontalSpeed = Greenfoot.getRandomNumber(1)-1;
    int verticalSpeed = Greenfoot.getRandomNumber(1)-1;
    /**
     * Act - do whatever the Bananas wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        move(horizontalSpeed, verticalSpeed);
        wrapAtEdge();
     Actor getSchneg = getOneIntersectingObject (Schneg.class);
         if (getSchneg != null)
       {
         World myWorld = getWorld();
         myWorld.removeObject(getSchneg);
         GameOver gameover = new GameOver();
        myWorld.addObject(gameover, myWorld.getWidth()/2, myWorld.getHeight()/2);
        TryAgain tryagain = new TryAgain();
        myWorld.addObject(tryagain, 300, 300);
        stopClock();
        }
     
    Actor Achtung = getOneIntersectingObject (Achtung.class);
         if (Achtung != null)
      {
         World myWorld = getWorld();
            
   
        myWorld.removeObject(this);
   
       }
}

}
and a part of the code of the clock:
/**
     * Pause the clock.
     */
   public void stopClock() {
        timeSaved = System.currentTimeMillis() - lastCurrentSecond;
       count = false;
    }
I hope you can help me! Thank you, Fifilein
danpost danpost

2017/3/7

#
I do not thing you are not showing enough of the Clock class to get the help you require. However, it might be better to use an int field that counts down instead of using the system clock. Start the field at somewhere around 1100 to 1200 and have it decrement each act cycle as long as it is greater than zero and the GameOver object is not in the world. If it reaches zero, the user wins and if schneg touches achtung, the user loses. You can use a simple Actor object to display the time remaining or use 'showText'.
Fifilein Fifilein

2017/3/7

#
danpost wrote...
I do not thing you are not showing enough of the Clock class to get the help you require. However, it might be better to use an int field that counts down instead of using the system clock. Start the field at somewhere around 1100 to 1200 and have it decrement each act cycle as long as it is greater than zero and the GameOver object is not in the world. If it reaches zero, the user wins and if schneg touches achtung, the user loses. You can use a simple Actor object to display the time remaining or use 'showText'.
Here is the completely code of the clock class
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.awt.Color;
import java.awt.Font;

/**
 * Write a description of class Clock here.
 * 
 * @author (your name)
 * @version (a version number or a date)
 */
public class Clock extends Quatrel
{
    private int startingTime;
    
    private int seconds = 180;
    private int clockType = 0;
    
    private long lastCurrentSecond;
    private long timeSaved = 0;
    
    private boolean timeUp = false;
    private boolean count = false;
    private boolean displayTime;
    private boolean countDown;
    
    private String text;
    
    private Actor alertedActor;
    
    private World alertedWorld;
    
    /**
     * Create a new Clock with your own text or other values.
     * 
     * @param countDown
     *      Set the kind of the clock. If true the clock will cound down from the given starting time. Otherwise it'll count up from 0.
     * 
     * @param displayTime
     *      Set the clock's visibility. If true the clock is visible.
     * 
     * @param startingTime
     *      The starting time for countdown clocks. If you restart the clock it'll start from this value.
     * 
     * @param text
     *      The text above the clock. If text is null the clock will be centered and there is no text.
     */
    public Clock(boolean countDown, boolean displayTime, int startingTime, String text) {
        this.countDown = countDown;
        this.displayTime = displayTime;
        this.startingTime = startingTime;
        this.text = text;
        this.alertedActor = null;
        this.alertedWorld = null;
        seconds = startingTime;
        getImage().clear();
        if (!countDown) {
            seconds = 0;
        }
        if (displayTime) {
            getImage().scale(130, 70);
        }
        this.startClock();
    }
    
    /**
     * Create a new Clock with your own text or other values.
     * 
     * @param countDown
     *      Set the kind of the clock. If true the clock will cound down from the given starting time. Otherwise it'll count up from 0.
     * 
     * @param displayTime
     *      Set the clock's visibility. If true the clock is visible.
     * 
     * @param startingTime
     *      The starting time for countdown clocks. If you restart the clock it'll start from this value.
     * 
     * @param text
     *      The text above the clock. If text is null the clock will be centered and there is no text.
     * 
     * @param alertedActor
     *      The actor you want to alert if the counddown time reaches 0.
     */
    public Clock(boolean countDown, boolean displayTime, int startingTime, String text, Actor alertedActor) {
        this.countDown = countDown;
        this.displayTime = displayTime;
        this.startingTime = startingTime;
        this.text = text;
        this.alertedActor = alertedActor;
        this.alertedWorld = null;
        seconds = startingTime;
        getImage().clear();
        if (!countDown) {
            seconds = 0;
        }
        if (displayTime) {
            getImage().scale(130, 70);
        }
        this.startClock();
    }
    
    /**
     * Create a new Clock with your own text or other values.
     * 
     * @param countDown
     *      Set the kind of the clock. If true the clock will cound down from the given starting time. Otherwise it'll count up from 0.
     * 
     * @param displayTime
     *      Set the clock's visibility. If true the clock is visible.
     * 
     * @param startingTime
     *      The starting time for countdown clocks. If you restart the clock it'll start from this value.
     * 
     * @param text
     *      The text above the clock. If text is null the clock will be centered and there is no text.
     * 
     * @param alertedWorld
     *      The world you want to alert if the counddown time reaches 0.
     */
    public Clock(boolean countDown, boolean displayTime, int startingTime, String text, World alertedWorld) {
        this.countDown = countDown;
        this.displayTime = displayTime;
        this.startingTime = startingTime;
        this.text = text;
        this.alertedActor = null;
        this.alertedWorld = alertedWorld;
        seconds = startingTime;
        getImage().clear();
        if (!countDown) {
            seconds = 0;
        }
        if (displayTime) {
            getImage().scale(130, 70);
        }
        this.startClock();
    }
    
    /**
     * Create a new Clock with your own text or other values.
     * 
     * @param countDown
     *      Set the kind of the clock. If true the clock will cound down from the given starting time. Otherwise it'll count up from 0.
     * 
     * @param displayTime
     *      Set the clock's visibility. If true the clock is visible.
     * 
     * @param startingTime
     *      The starting time for countdown clocks. If you restart the clock it'll start from this value.
     * 
     * @param text
     *      The text above the clock. If text is null the clock will be centered and there is no text.
     * 
     * @param alertedActor
     *      The actor you want to alert if the counddown time reaches 0.
     * 
     * @param alertedWorld
     *      The world you want to alert if the counddown time reaches 0.
     */
    public Clock(boolean countDown, boolean displayTime, int startingTime, String text, Actor alertedActor, World alertedWorld) {
        this.countDown = countDown;
        this.displayTime = displayTime;
        this.startingTime = startingTime;
        this.text = text;
        this.alertedActor = alertedActor;
        this.alertedWorld = alertedWorld;
        seconds = startingTime;
        getImage().clear();
        if (!countDown) {
            seconds = 0;
        }
        if (displayTime) {
            getImage().scale(130, 70);
        }
        this.startClock();
    }
    
    /**
     * The act method of the class Clock.
     * Let the clock count the time. If the act mehtod is not executed the clock will count on but not change it's image. To pause the clock use the method stopClock().
     * The Clock is irrespective of the acting speed of the scenario so that it doesn't mater how fast the other act methods are executed.
     */
    public void act() {
        if (countDown) {
            if (count && !timeUp) {
                if (System.currentTimeMillis() - lastCurrentSecond >= 1000) {
                    lastCurrentSecond += 1000;
                    seconds--;
                    if (displayTime) {
                        drawTime();
                    }
                }
                if (seconds == 0) {
                    alertActor();
                    alertWorld();
                    timeUp = true;
                }
            }
        }
        else {
            if (count) {
                if (System.currentTimeMillis() - lastCurrentSecond >= 1000) {
                    lastCurrentSecond += 1000;
                    seconds++;
                    if (displayTime) {
                        drawTime();
                    }
                }
            }
        }
    }
    
    /**
     * Alert the actor you want.
     * You have to change this method to alert an other actor that the one in this demo. To alert another actor you should change the strings "Exampla_Actor" to the classname of the actor you want 
     * to alert and perhaps change the name of the called method.
     */
    private void alertActor() {
        if (alertedActor != null && alertedActor instanceof Counter) {
            ((Counter) alertedActor).alert();
        }
    }
    /**
     * Alert the world you want.
     * You have to change this method to alert an other world that the one in this demo. To alert another world you should change the strings "Clock_World" to the classname of the world you want 
     * to alert and perhaps change the name of the called method.
     */
    private void alertWorld() {
        if (alertedWorld != null && alertedWorld instanceof Clock_World) {
            ((Clock_World) alertedWorld).alert();
        }
    }
    
    /**
     * The drawing method of the clock.
     * This method draws the current value of your clock onto the clock object.
     */
    private void drawTime() {
        int min = (int) (seconds / 60);
        int sec = seconds % 60;
        String remainingTime;
        if (sec < 10) {
            remainingTime = min + ":0" + sec;
        }
        else {
            remainingTime = min + ":" + sec;
        }
        getImage().setColor(Color.yellow);
        getImage().fill();
        GreenfootImage text = new GreenfootImage((this.text == null ? "" : this.text), 24, Color.black, new Color(0, 0, 0, 0));
        GreenfootImage time = new GreenfootImage(remainingTime, 40, Color.black, new Color(0, 0, 0, 0));
        if (text.getWidth() > getImage().getWidth()) {
            getImage().clear();
            getImage().scale(text.getWidth() + 10, 70);
            getImage().setColor(Color.gray);
            getImage().fill();
        }
        getImage().drawImage(text, (getImage().getWidth()/2)-(text.getWidth()/2), 5);
        getImage().drawImage(time, (getImage().getWidth()/2)-(time.getWidth()/2), (this.text == null ? (getImage().getHeight()/2)-(time.getHeight()/2) : 24));
    }
    
    /**
     * Check whether the time is up.
     * 
     * @return
     *      Returns true if the time is up. If the clock is no countdown clock the method will return false.
     */
    public boolean timeUp() {
        return timeUp;
    }
    
    /**
     * Start the clock.
     */
    public void startClock() {
        lastCurrentSecond = System.currentTimeMillis() - timeSaved;
        count = true;
    }
    /**
     * Pause the clock.
     */
   // public void stopClock() {
      //  timeSaved = System.currentTimeMillis() - lastCurrentSecond;
     //   count = false;
   // }
    /**
     * Reset the clock.
     */
    public void resetClock() {
        seconds = startingTime;
        timeUp = false;
    }
}
danpost danpost

2017/3/7

#
There does not appear to be any way to stop the Clock object. There is currently no implementation that gives it that behavior. WAIT -- there is a method that has been commented out that appears to be what you neeed -- the 'stopClock' method.
Fifilein Fifilein

2017/3/7

#
In line 280 there is the method stopClock() which I wanted to use:
/**
     * Pause the clock.
     */
    public void stopClock() {
        timeSaved = System.currentTimeMillis() - lastCurrentSecond;
        count = false;
    }
Do you know an other way to pause or stop a clock?
danpost danpost

2017/3/7

#
Fifilein wrote...
In line 280 there is the method stopClock() which I wanted to use: Do you know an other way to pause or stop a clock?
What is wrong with that method? I would think that would be sufficient.
Fifilein Fifilein

2017/3/8

#
The thing is it does not work. When the Game Over appears the clock still counts down and does not stop. I do not know why?
Super_Hippo Super_Hippo

2017/3/8

#
If 'Achtung' extends 'Quatrel' and 'Clock' extends 'Quatrel' and the 'stopClock' method is in the 'Clock' class, then the 'Achtung' class can't use this method (line 31 in the first post). Do you have another 'stopClock' method in the 'Quatrel' class?
Fifilein Fifilein

2017/3/9

#
Yes
danpost danpost

2017/3/9

#
Fifilein wrote...
Yes
Are you going to show the code to that method or keep us waiting?
Fifilein Fifilein

2017/3/11

#
Here is the code of the Quatrel class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Quatrel here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Quatrel extends Actor
{
    private int startingTime;
    
    private int seconds = 180;
    private int clockType = 0;
    
     long lastCurrentSecond;
     long timeSaved = 0;
    
    private boolean timeUp = false;
   boolean count = false;
    private boolean displayTime;
    private boolean countDown;
    
    private String text;
    
    private Actor alertedActor;
    
    private World alertedWorld;
    
    /**
     * Act - do whatever the Quatrel 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 move(int changeX, int changeY)
    {
        int x = getX();
        int y = getY();
        int newX = x + changeX;
        int newY = y + changeY;
        setLocation(newX, newY);
    }

    /*
     * A method that tells if I hit the edge and what edge I hit
     */
    public String hitTheEdge()
    {
        int x = getX();
        int y = getY();
        World myWorld = getWorld();
        int rightSide = myWorld.getWidth() - 1;
        int bottomSide = myWorld.getHeight() - 1;
        if(y == 0)
        {
            return "top";
        } else if (x == 0)
        {
            return "left";
        } else if(x == rightSide){
            return "right";
        } else if(y == bottomSide)
        {
            return "bottom";
        } else {
            return null;
        }
    }
    public void wrapAtEdge()
    {
        String edge = hitTheEdge();
        int x = getX();
        int y = getY();
        World myWorld = getWorld();
        int rightSide = myWorld.getWidth() - 1;
        int bottomSide = myWorld.getHeight() - 1;
        if(edge == "bottom")
        {
            setLocation(x, 0);
        } else if(edge == "top")
        {
            setLocation(x, bottomSide);
        } else if(edge == "left")
        {
            setLocation(rightSide, y);
        } else if(edge == "right")
        {
            setLocation(0, y);
        }
    }
    /**
     * Pause the clock.
     */
    public void stopClock() 
    {
       timeSaved = System.currentTimeMillis() - lastCurrentSecond;
       count = false;
    }
}
danpost danpost

2017/3/11

#
Remove any and all fields and methods in the subclasses of Quatrel that you already have in the Quatrel class. By duplicating them in the subclasses, you are overshadowing them in the extended class. All non-private methods and fields in an extended class are inherited by those subclasses that extend it.
Fifilein Fifilein

2017/3/12

#
I tried it, but it does not still work.
danpost danpost

2017/3/12

#
It would be much easier to dispense with the Clock class altogether and use an int field and a simple actor to display the remaining time:
/** in world class */
// instance fields
private int timer;
private Actor timerDisplay;

// in constructor
timer = 1200;
timerDisplay = new SimpleActor();
addObject(timerDisplay, 120, 20); // change location as desired
updateTimerDisplay();

// in act
if (timer > 0)
{
    timer--;
    if (timer%60 == 0) updateTimerDisplay();
}
else // ... game over routine

// new method
private void updateTimerDisplay()
{
    timerDisplay.setImage(new GreenfootImage("Time remaining: "+(timer/60), 24, Color.BLACK, new Color(0, 0, 0, 0))); // adjust text as desired
}

/**  new class  */
public class SimpleActor extends greenfoot.Actor {}
Fifilein Fifilein

2017/3/12

#
Thank you. Now I give it a try.
There are more replies on the next page.
1
2