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

2012/2/25

Need help with toggling!

DHoffman94 DHoffman94

2012/2/25

#
I am working on the greenfoot book tutorial and i am under the Newton's Lab tutorial. In it, i must have an actor body pass through an obstruction and toggle it on. However, if it passes through it again it should toggle it off. Also, if it is on then the obstruction should play a sound. Oh, mine plays a sound alright. Like 10 at one time coming from the same obstruction. Then it wont toggle off for some reason and will just flicker there if a body object passes through. Here is my code for my Blinker.class (the class that should toggle) :
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Blinker here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Blinker extends SmoothMover
{
    private boolean touched = false;
    private int i = 0;
    /**
     * Act - do whatever the Blinker wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        isTouched();
    }   

    private void isTouched()
    {
        checkIsTouched();
        GreenfootSound sound = new GreenfootSound("Bass2.wav");
        if (touched && i == 0)
        {
            i = 1;
            setImage("Blinker-Light.png");
            if (!sound.isPlaying())
            {
                sound.play();    
            }
        }
        else if (!touched && i == 1)
        {
            i = 1;
            setImage("Blinker-Light.png");
            if (!sound.isPlaying())
            {
                sound.play();    
            }
        }
        else if (touched && i == 1)
        {
            i = 0;
            setImage("Blinker.png");
            sound.stop();
        }
        else
        {
            i = 0;
            setImage("Blinker.png");
            sound.stop();
        }
    }

    private boolean checkIsTouched()
    {
        Actor body = getOneIntersectingObject(Body.class);

        if(body != null && touched == false )
        {
            touched = true;   
        }
        else if (body != null && touched == true)
        {
            touched = false;    
        }
        return touched;
    }
}
danpost danpost

2012/2/25

#
Line 12 (private int i = 0;): this is rather vague; from what I can tell, it has only values '0' or '1' and probably should be something like 'private boolean toggledOn = false;'. The instructions are: (1) if touched is false and checkIsTouched returns true, then // new touch (a) set touched = true (b) set toggledON = !toggledOn; // toggles here (c) if toggledOn = true, then // only needs checked after toggling (i) set image to Blinker-Light.png (d) if toggledOn = false, then // only needs checked after toggling (i) set image to Blinker.png (2) if touched is true and checkIsTouched returns false, then // new seperation (a) set touched = false; (3) if toggledOn = true and sound is not playing, then play sound // the last line needs constant checking This outline should get you on your way. But for this: Your 'checkIsTouched' method, which you call first thing in your 'isTouched' method destroys any previous value for 'touched'. In the 'checkIsTouched' method, change the name of the returning variable, and call this method as part of the conditionals in 'if' statements (or set the returned value to a boolean variable ). Another thing about that method is that it really does not do what the name implies, which is making it all the more confusing. Let the method just return true if the body is there and false if not (the variable touched is dealt with as the other part of the 'if' statement that calls it). Therefore the code for 'checkIsTouched' should be something like:
private boolean checkIsTouched()
{
    return  (getOneIntersectingObject(Body.class) != null);
}
and the statement that calls it would be something like:
if (touched && !checkIsTouched) touched = false;
for (2)(a) above. Also, line 25 can be moved outside any methods as an instance GreenfootSound variable of private access. Again, for better meaning (do not do this, unless you think you will have no problems in doing it) 'checkIsTouched' would be better named 'isTouched', and 'isTouched' would be better names 'checkToggle' and the code for the outline above would go in 'checkToggle' (which is currently 'isTouched').
DHoffman94 DHoffman94

2012/2/25

#
So the code you posted for the toggle method :
    private boolean checkIsTouched()  
    {  
        return  (getOneIntersectingObject(Body.class) != null);  
    }  
Means that I dont have to have an if() else if() statement? It will only return as true if it intersects Body.class, and if it doesnt then it is false?
danpost danpost

2012/2/25

#
That is correct! But I would not refer to the method as a 'toggle method'. It is more of an 'isTouching' method.
DHoffman94 DHoffman94

2012/2/25

#
Honestly, I think the problem is just that it is checking constantly weather it is being touched. So if the body moves slowly through Blinker.class then it will toggle on and off at a very fast pace. Check my profile I uploaded the scenario with the problem and the source code. You will see the problem there. Sorry i know i am really bad at explaining it.
danpost danpost

2012/2/25

#
As a slight correction (I missed a pair of parenthesis), the last single line of code I provided, for the calling statement:
if (touched && !checkIsTouched()) touched = false;
danpost danpost

2012/2/25

#
You forgot to check the box indicating you would like the source code included with the scenario during upload.
danpost danpost

2012/2/25

#
You tried to complicate matters in your 'isTouched' method. Below is the Blinker class after I made the proper adjustments. I took the liberty of changing some of the method names, moving the GreenfootSound declaration, and simplifying the code. Compare it to my outline above (which was not a complete outline, but close). Here is what I came up with:
import greenfoot.*;

public class Blinker extends Actor
{
    private boolean touched = false;
    private boolean toggledOn = false;
    private GreenfootSound sound = new GreenfootSound("Bass2.wav");

    public Blinker()
    {
    }

    public void act() 
    {
        checkToggle();
    }   

    private void checkToggle()
    {
        if (!touched && isTouching()) // new touch
        {
            touched = true;
            toggledOn = !toggledOn;
            if (toggledOn)
            {
                setImage("Blinker-Light.png");
                sound.play();
            }
            else 
            {
                setImage("Blinker.png");
                sound.stop();
            }
        }
        if (touched && !isTouching())  touched = false; // new separation
        if (toggledOn && !sound.isPlaying()) sound.play(); // continues to play, if needed
    }

    private boolean isTouching()
    {
        return (getOneIntersectingObject(Body.class) != null);
    }
}
First, read it through and see how it makes sense. Then compare it to the outline (how close they are related!).
DHoffman94 DHoffman94

2012/2/27

#
Thank you! And sorry for my inactivity, i worked a lot this weekend. I will try this out and let you know if it works. Either way, I will re post the scenario so you can see what the code does.
DHoffman94 DHoffman94

2012/2/27

#
I havent had a chance to check weather the sound works, but the image works perfectly! No spazing out and blinking, just one clean on and off. Thank you very much, I cited your work as a comment on the class.
You need to login to post a reply.