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

2013/2/6

Looking for a way to pause one method while another finishes

bjonesre bjonesre

2013/2/6

#
I'm working through the asteroids scenario in the book and have implemented a sound effect at the end of each level, when all the asteroids are cleared, but it keeps being played over by the sound effect from the asteroid being destroyed. I tried implementing the delay function with the following code:
if (totalNeededForOneDestroyed==asteroidsKilled)
      {

          currentLevel++;
          levelCounter.updateLevel(currentLevel);
          levelCounter.act();
          //addObject(new Scoreboard.makeImage("Next Level", "Level: ", currentLevel));

          Greenfoot.delay(20); 
          Greenfoot.playSound("level.wav");
but that just seems to pause the whole scenario and the sound is still covered up. Is there a way to delay say the space method while the asteroid method finishes? The delay just seems to pause the whole scenario. Thanks.
danpost danpost

2013/2/6

#
You may have to change the value of one of the check fields (probably 'totalNeededForOneDestroyed) so the values do not match and condition becomes false. This will prevent the sound from being started every act method (playing over itself). Also, remove the 'delay' statement.
bjonesre bjonesre

2013/2/7

#
Thanks for the quick reply. There are 2 different sounds that play at the same time. The explosion sound starts and lasts for a few seconds. After about 1 second the next sound starts playing, level.wav, which can't be heard since the asteroid exploding sound is still playing. the Explosion.wav is started when the asteroid is destroyed. If it's been completely destroyed then it calls the space method which will see if they have all been destroyed then play the sound if they have. I would either like a way to stop the Explosion.wav sound or start the level.wav sound after the explosion.wav is finished. Does this make more sense? Sorry if my earlier description was confusing.
 private void breakUp() 
    {
        Greenfoot.playSound("Explosion.wav");
        
        if(size <= 16) 
        {
            space = (Space) getWorld();
            space.countScore(10);
            space.numberOfAsteroidsKilled(); //call the space class to give the latest number of asteroids killed
            getWorld().removeObject(this);
danpost danpost

2013/2/7

#
Alright. It is a bit clumsy because of where you have everything located. The best way is to create a GreenfootSound object for the explosion and hold it in an instance object field, so you can check to see if it is playing or not. You will also need an instance boolean field to indicate the need to play the level changing sound or not. The code would be something like the following:
// add instance fields (in the Asteroid class code but outside any methods)
private GreenfootSound explosion = new GreenfootSound("Explosion.wav");
private boolean levelSoundToPlay = false;
// then your breakUp method should be:
 private void breakUp() 
{
    explosion.play();
    if(size <= 16) 
    {
        space = (Space) getWorld();
        space.countScore(10);
        levelSoundToPlay=space.numberOfAsteroidsKilled();
        getWorld().removeObject(this);
    }
}
// then add this code either to the Asteroid act method or put it in a method it calls
if (levelSoundToPlay && !explosion.isPlaying())
{
    Greenfoot.playSound("level.wav");
    levelSoundToPlay=false;
}
// next, in the Space class, change the return type of numberOfAsteroidsKilled from
public void numberOfAsteroidsKilled() // to
public boolean numberOfAsteroidsKilled()
// then your code (in the Space class, from your first post [in numberOfAsteroidsKilled method]) would be like this:
if (totalNeededForOneDestroyed==asteroidsKilled)
{
    currentLevel++;
    levelCounter.updateLevel(currentLevel);
    levelCounter.act(); // if the levelCounter object is in world, this statement not needed
    //addObject(new Scoreboard.makeImage("Next Level", "Level: ", currentLevel));
    return true;
}
return false;
bjonesre bjonesre

2013/2/7

#
Great I'll test that out and get back to you. Thank you very much.
danpost danpost

2013/2/7

#
NO. Even that is not right because if the object is being removed from the world, the code checking if the explosion sound is finished will not execute. Re-coded again:
// Change your 'breakUp' method in the Asteroid class to:
 private void breakUp() 
{
    explosion.play();
    if(size <= 16) 
    {
        space = (Space) getWorld();
        space.countScore(10);
        space.numberOfAsteroidsKilled();
        getWorld().removeObject(this);
    }
}
// now in the Space world class, add the following fields (in class code, but outside any methods)
private GreenfootSound explosion = new GreenfootSound("Explosion.wav");
private boolean levelSoundToPlay = false;
// then add this code to the Space world class 'act' method or put it in a method it calls (create the 'act' method if you do not already have one in the Space class)
if (levelSoundToPlay && !explosion.isPlaying())
{
    Greenfoot.playSound("level.wav");
    levelSoundToPlay=false;
}
// then your code (in the Space class, from your first post [in numberOfAsteroidsKilled method]) would be like this:
explosion.play();
if (totalNeededForOneDestroyed==asteroidsKilled)
{
    currentLevel++;
    levelCounter.updateLevel(currentLevel);
    levelCounter.act(); // if the levelCounter object is in world, this statement not needed
    //addObject(new Scoreboard.makeImage("Next Level", "Level: ", currentLevel));
    levelSoundToPlay=true;
}
bjonesre bjonesre

2013/2/7

#
I see what you mean, if the Asteroid is class is being removed it would make sense why I was getting a null pointer. Hopefully I'll get a chance to get it working tonight. Thanks.
You need to login to post a reply.