java - Java:使用AudioClips或Clips一次播放multibleSounds

标签 java eclipse audio javasound

我想有一个“单独的类(class)” ****来发出声音,我想请那个类(class)播放声音,但是如果有更好的方法,请告诉我。

故事(可以跳过):

首先,我使用AudioClips,这些音频存储在最终需要播放声音的静态静态文件中。对于诸如背景音乐之类的单个东西来说,这是完美的,但是如果我想一次使用声音不止一次,例如我拍摄的炮塔,它们有时会播放完美的声音,有时会重新播放或完全取消。
然后,在阅读了一些帖子之后,我切换到Clips,并且在使用了一个教程之后,有人通过doin Clips找到了解决方案。

声音等级:

package Game.main;

import java.net.URL;

import javax.sound.sampled.AudioInputStream;

import javax.sound.sampled.AudioSystem;

import javax.sound.sampled.Clip;

import javax.sound.sampled.DataLine;

import javax.sound.sampled.Mixer;

public class Sound {
    public static final Sound backgroundMusic4 = new Sound("/backgroundMusic4.wav");
    public static final Sound blockDestroy = new Sound("/blockDestroy.wav");
    public static final Sound bulletHit = new Sound("/bulletHit.wav");
    public static final Sound button = new Sound("/button.wav");
    public static final Sound camera = new Sound("/camera.wav");
    public static final Sound teleporter = new Sound("/teleporter.wav");
    public static final Sound turretShot = new Sound("/turretShot.wav");
    public static final Sound walking = new Sound("/walking.wav");

    public static Clip clip;

    public Sound(String fileLocation){
        Mixer.Info[] mixInfos = AudioSystem.getMixerInfo();

        Mixer mixer = AudioSystem.getMixer(mixInfos[0]);

        DataLine.Info dataInfo = new DataLine.Info(Clip.class, null);

        try{
            clip =(Clip) mixer.getLine(dataInfo);
        }catch(Exception e){
            e.printStackTrace();
        }

        try{
            URL soundURL = getClass().getResource(fileLocation);
            AudioInputStream audioStream = AudioSystem.getAudioInputStream(soundURL);
            clip.open(audioStream);
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public void play(){
        clip.loop(clip.LOOP_CONTINUOUSLY);
    }

    public void playOnce(){
        clip.start();
    }

    public void stop(){
        clip.stop();
    }
}

炮塔类(例如)[仅最后一个方法“shoot()”很重要]:
package Game.main.IngameObjects;

import java.applet.AudioClip;
import java.awt.Graphics;
import java.awt.Rectangle;

import Game.main.Controller;
import Game.main.Game;
import Game.main.GameObject;
import Game.main.Sound;
import Game.main.Textures;
import Game.main.classes.EntityC;

public class Turret extends GameObject implements EntityC{

    private boolean activated;
    private String direction;
    private Game game;
    private Textures tex;
    private Camera activationCam;
    private Controller c;

    private long lastShot=0;

    public Turret (double x, double y, Textures tex, Game game, Controller c, String direction){
        super(x,y);
        this.game=game;
        this.tex=tex;
        this.c=c;
        if(!direction.equalsIgnoreCase("up") && !direction.equalsIgnoreCase("down") && !direction.equalsIgnoreCase("left") && !direction.equalsIgnoreCase("right")){
            System.err.println("ERROR 1: Wrong Direction in Constructor in Class \"java.Game.main.IngameObjects.Camera\"");
            System.exit(1);
        }else{
            this.direction=direction;
        }
    }

    public Turret (double x, double y, Textures tex, Game game, Controller c , Camera cam, String direction){
        super(x,y);
        this.game=game;
        this.tex=tex;
        this.c=c;
        if(!direction.equalsIgnoreCase("up") && !direction.equalsIgnoreCase("down") && !direction.equalsIgnoreCase("left") && !direction.equalsIgnoreCase("right")){
            System.err.println("ERROR 1: Wrong Direction in Constructor in Class \"java.Game.main.IngameObjects.Camera\"");
            System.exit(1);
        }else{
            this.direction=direction;
        }
        this.activationCam=cam;
    }

    public void tick() {
        if(activationCam==null){
            shoot();
        }else if(activationCam.getActivated()){
            shoot();
        }
    }

    public void render(Graphics g) {
        if(activated){
            if(direction.equalsIgnoreCase("up")){
                g.drawImage(tex.turretActi.get(0), (int)x, (int)y, null);
            }else if(direction.equalsIgnoreCase("down")){
                g.drawImage(tex.turretActi.get(1), (int)x, (int)y, null);
            }else if(direction.equalsIgnoreCase("left")){
                g.drawImage(tex.turretActi.get(2), (int)x, (int)y, null);
            }else if(direction.equalsIgnoreCase("right")){
                g.drawImage(tex.turretActi.get(3), (int)x, (int)y, null);
            }
        }else{
            if(direction.equalsIgnoreCase("up")){
                g.drawImage(tex.turretDeac.get(0), (int)x, (int)y, null);
            }else if(direction.equalsIgnoreCase("down")){
                g.drawImage(tex.turretDeac.get(1), (int)x, (int)y, null);
            }else if(direction.equalsIgnoreCase("left")){
                g.drawImage(tex.turretDeac.get(2), (int)x, (int)y, null);
            }else if(direction.equalsIgnoreCase("right")){
                g.drawImage(tex.turretDeac.get(3), (int)x, (int)y, null);
            }
        }
    }

    public Rectangle getBounds() {
        return new Rectangle((int)x, (int)y, 32, 32);
    }

    public double getX() {
        return x;
    }

    public double getY() {
        return y;
    }

    public void activate() {
        activated=true;
    }

    public void deactivate() {
        activated=false;
    }

    public boolean getActivated() {
        return activated;
    }

    public void setX(double x) {
        this.x=x;
    }

    public void setY(double y) {
        this.y=y;
    }

    public void shoot(){
        if(System.currentTimeMillis() - lastShot >= 1000){
            Sound.turretShot.playOnce();
            lastShot = System.currentTimeMillis();
            c.addEntity(new Bullet(x,y,game,tex,c,direction));
        }
    }
}

现在我有一个问题,炮塔只发射一次,声音播放然后消失(示例视频:https://youtu.be/q8TR2nR8hUI)。我试图给每个对象自己的声音剪辑,但是这非常浪费,上一次它使我的刻度和fps每5秒减少到1个。

这就是为什么我想寻求解决方案或一些有益的想法和代码。

我用红字和字节数组和dataStreamOutput,或者我可以克隆剪辑,但我不能任其工作。

很抱歉我的英语不好,我是德国人,所以请忽略任何错误(除非您看不懂)

最佳答案

没有为同时播放设置Java剪辑。充其量是经常这样做的,您可以将正在播放的Clip重置为开始并重新启动(即在完成之前中断它)。下一步的逻辑选择是实例化Clip的多个副本(如VGR在注释中所建议),并编写一层代码来管理这些实例。

有几个库允许同时播放剪辑等效项。 TinySound可通过github公开获得。 java-gaming.org上的开发人员对此有一个主要话题。那里的几个成员已经成功使用了这个库。

我一直在开发自己的声音库,其中包括并发播放剪辑等效文件。不过,我还没有公开消息。但是,如果您希望探索编写自己的代码来执行此操作,那么很高兴在此处或在java-gaming.org上的线程上进行回复。基本计划是将数据存储在一个数组中(可以是字节,也可以是PCM法线等),并通过设置为从该数据文件读取的SourceDataLine(SDL)进行播放。还可以选择通过一条SDL输出线运行其中的几个(在输出之前将它们混合在一起),或者给每个分配自己的SDL。设置所有这些工作有点麻烦,因此许多人都希望找到一个库。

关于java - Java:使用AudioClips或Clips一次播放multibleSounds,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40052579/

相关文章:

java - 使用 ScheduledExecutorService 方法定期运行一批任务

java - Proguard 找不到引用的类 com.google.ads.internal.state.AdState

java - 获取异常原因、类型转换为正确类型的正确方法签名是什么?

android - 条形码扫描仪 - Cordova 插件

flash - Flash CS4 + AS3,SoundChannel.position不正确

java - 插入循环时数组中的值

来自特定文件的 Eclipse 任务

c++ - Eclipse CDT C++ - [Main] 程序未指定

objective-c - 为DSP目的在C++中处理音频数据

python - 如何通过 BeagleBone 上的 GPIO 引脚生成声音信号