0

假设我有一个主要的 GameLoop

在这个循环中,我有我的游戏更新

我正在处理我的事件以进行每次迭代的 Sprite 碰撞测试

如果碰撞为真,播放音频文件

这是问题发生的地方

音频剪辑将在游戏冻结时快速播放

或者

它会像我想要的那样延迟播放,但除了音频剪辑之外,整个游戏都会停止。

我只是在寻找一些关于线程基本的技巧。据我所知,这将是处理此问题的最佳方法,但我似乎无法使其正常运行。

注意我会在主类上扩展线程,但已经扩展了 Canvas,需要。

    public Main()
    {

        boolean running = true;

        while(running)
        {

            // check for collision (returns boolean)
            // if true proceed to execute Entity.doLogic()
            // this then activates the AudioClip class' .playAudioClip(this, path)
            // the audio Clip is then played and once it's done it'll return
            // returns and instantly goes back to playing again
            // meanwhile the loop Freezes up on me.

        }

    }

这是实际的 Sound.class

public class Sounds
{

    public void startSound()
    {
        String path = "path";
        playAudioClip(game, path);
    }

    public void playAudioClip(String path)
    {
        try
        {
            Clip clip = AudioSystem.getClip();
            clip.open(AudioSystem.getAudioInputStream(new File(path)));
            clip.start();
        }
        catch(Exception e)
        {
            System.out.println("Problem loading audio file");
        }
        try{Thread.sleep(500);}catch(Exception ex){System.out.println("Problem with Sleep");};
    }
}

我已经尝试过以下相同的情况(通过 s.start() 和 s.run() 调用它没有区别)使用 .start() 会在线程中抛出错误,将重新创建真正的快速并共享)

public class Sounds extends Thread
{
    @Override
    public void run()
    {
        String path = "path";
        playAudioClip(game, path);
    }

    public void playAudioClip(String path)
    {
        try
        {
            Clip clip = AudioSystem.getClip();
            clip.open(AudioSystem.getAudioInputStream(new File(path)));
            clip.start();
        }
        catch(Exception e)
        {
            System.out.println("Problem loading audio file");
        }
        try{Thread.sleep(500);}catch(Exception ex){System.out.println("Problem with Sleep");};
    }
}

抛出控制台“java.lang.IllegalThreadStateException”调用 start() 仅在此对象内部定义 run()

在此处输入图像描述 注意自我。不要那样做。

以错误的方式进行多线程主要示例 243 max 线程在任何时候都在那里

4

1 回答 1

0

start()a 的方法Clip执行时,声音会通过一个为此目的而创建的守护线程播放。您无需创建 aThread也无需包含该Thread.sleep()命令。只要您的程序正在运行,声音就会执行。如果您的程序在声音仍在播放时停止,因为它在一个守护进程上,声音不会结束,但会随着程序一起停止。

我的猜测是您的代码来自一个示例程序,该示例程序的唯一任务是播放声音。一个更好的演示示例将展示如何Clip在更大的程序的上下文中管理 a。

这是一个可以尝试的课程。我省略了Exception处理。我使用URL它是因为即使程序已编译成 jar,它也可以让人们获得资源。在文件结构方面,代码假定声音文件位于相对于您的Sounds类位置的子文件夹中。

public class Sounds
{
    private Clip clip;

    public Sounds(String soundFileName)
    {
        URL url = this.class.getResource("audio/" + soundFileName);
        AudioInputStream ais = AudioSystem.getAudioInputStream(url);
        DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
        clip = (Clip) AudioSystem.getLine(info);
        clip.open(ais);
    }

    public void playAudioClip()
    {
        clip.setFramePosition(0);
        clip.start();
    } 
}

Clip课程专为记忆中的声音而设计。如果您不想将声音文件保存在内存中,则应该使用SourceDataLine,因为它会更快地启动,并且一次只在内存中保存一个缓冲区的数据,而不是整个文件。

因此,我们创建Clip一个实例变量,并在实例化过程中加载和打开它。

该命令clip.setFramePosition(0)在那里,因此无论何时您调用Clip,它都会从文件的开头开始播放。有了这个,你可以随时打电话和玩Clip。最坏的情况,如果你调用它时它正在播放,声音会跳回到开头重新开始。

于 2020-08-22T07:01:23.047 回答