0

I'm making a simple tank game and it has its background music. I need the music to stop whenever the player dies (players health int becomes 0). How do i do it?

I tried stopping the thread by declraring the thread outside of the play() function and stopping it with t.stop() but it didn't work.

package com.company;

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.*;

public class Sound implements Runnable
{

    private String fileLocation;
    public String getFileLocation() {
        return fileLocation;
    }

    public Sound() {
    }



    public void play(String fileLocation)
    {
        Thread t = new Thread(this);
        this.fileLocation = fileLocation;
        t.start();
    }

    public void run ()
    {
        playSound(fileLocation);
    }



    public void playSound(String fileName)
    {
        File soundFile = new File(fileName);
        AudioInputStream audioInputStream = null;
        try
        {
            audioInputStream = AudioSystem.getAudioInputStream(soundFile);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        AudioFormat audioFormat = audioInputStream.getFormat();
        SourceDataLine line = null;
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
        try
        {
            line = (SourceDataLine) AudioSystem.getLine(info);
            line.open(audioFormat);
        }
        catch (LineUnavailableException e)
        {
            e.printStackTrace();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        line.start();
        int nBytesRead = 0;
        byte[] abData = new byte[128000];
        while (nBytesRead != -1)
        {
            try
            {
                nBytesRead = audioInputStream.read(abData, 0, abData.length);
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            if (nBytesRead >= 0)
            {
                int nBytesWritten = line.write(abData, 0, nBytesRead);
            }
        }
        line.drain();
        line.close();
    }
}
Pavel Smirnov
  • 4,611
  • 3
  • 18
  • 28
Mati
  • 33
  • 4
  • 2
    Possible duplicate of [How to properly stop the Thread in Java?](https://stackoverflow.com/questions/10961714/how-to-properly-stop-the-thread-in-java) – JimmyB Jul 10 '19 at 11:23
  • After trying the solution from "How to properly stop the Thread in Java?" my ears almost started bleeding after trying to "terminate" the Thread. Doesn't seem to be the solution. – Mati Jul 10 '19 at 11:35
  • Then you made a mistake. Try again, it is the correct way. – JimmyB Jul 10 '19 at 11:38
  • Tried it. Couldn't get i to work. I'm a newbie when it comes to coding. Either you can just tell me how my code should look or i can keep scouting the internet for a solution which will work with my code :/ – Mati Jul 10 '19 at 12:03
  • Sorry, I can't teach you all the Java Thread basics here, and I don't have time now to write your code for you. – JimmyB Jul 10 '19 at 14:39
  • IDK if that is exactly fair. Multithreading and joins are not "basic". That's why they are usually towards the back end of textbooks teaching Java. – Phil Freihofner Jul 11 '19 at 06:56

1 Answers1

0

Declare a volatile boolean. Why volatile? Because it needs to update across threads.

private volatile boolean playing;

Include the boolean in the while clause.

while(playing && nBytesRead != -1)

Make the boolean accessible from outside the playback thread.

public void setPlaying(boolean) {
    this.playing = playing;
}

When you want to turn off the sound, call setPlaying(false). Don't forget to make the boolean true before the sound is started.

The only drawback here is that the sound may end with a click, since it will be instant. Adding a fade involves setting up and invoking a javax.sound.sampled.Control object (I've had dubious luck with these), or fiddling with the PCM data itself.

At least with a SourceDataLine, we have access to the bytes (in your abData array). The data can be assembled into PCM according to your audio format, then multiplied by a fader value that goes from 1 to 0 over the course of something like 64 frames, dialing the PCM values down to 0 gradually, and then taking these new PCM values and converting them back to bytes and writing that. Yes, a lot of trouble just to get rid of a click. But worth it.

Phil Freihofner
  • 7,645
  • 1
  • 20
  • 41