Heli sissejuhatus¶
Sound ja Music klassid¶
LibGDX pakub kahte erinevat klassi helide esitamiseks: Sound ja Music. Nende erinevuse mõistmine on oluline, et valida õige klass vastavalt vajadusele.
Sound¶
Sound klass on mõeldud lühikeste heliefektide jaoks, nagu tulistamine, hüppamine või muu sarnane lühike heli. Sound laetakse täielikult mällu, mis tähendab, et seda saab kiiresti ja korduvalt mängida ilma viivituseta. Seetõttu sobib Sound hästi kõikide lühikeste heliefektide jaoks mängus.
Kiire esitus
Sobib lühikestele efektidele
Saab mängida korraga mitut korda (nt kiire tulistamine)
Music¶
Music klass on mõeldud pikemate helifailide jaoks, nagu taustamuusika.
Music ei laeta täielikult mällu korraga, vaid voogedastab (stream) faili kettalt, mis tähendab, et see kulutab vähem RAM-i, kuid ei sobi kiireks korduvaks esituseks.
Sobib pikkadele helidele (taustamuusika, ambient)
Toetab tsüklis mängimist (
setLooping(true))
Toetatud heliformaadid¶
LibGDX toetab kolme peamist heliformaati: WAV, MP3 ja OGG. Tuleb arvestada, et mõned formaadid ei pruugi kõikidel platvormidel korrektselt töötada, mistõttu võib olla vaja erinevaid formaate proovida.
WAV – lossless formaat, kõrgeim helikvaliteet, failid on suured. Laadib kiiresti, kuna dekompresseerimist pole vaja. Sobib hästi lühikestele heliefektidele (
Soundklass).MP3 – kompresseeritud formaat, väiksemad failid. Sobib taustamuusikale, kui failimaht on oluline.
OGG (Ogg Vorbis) – avatud ja kompresseeritud formaat, hea kvaliteedi ja failimahu suhe. Laialdaselt soovitatav LibGDX projektides, eriti kui WAV ja MP3 probleeme tekitavad. Paljud arendajad on leidnud, et OGG toimib kõige stabiilsemalt.
Soovitus: kui WAV või MP3 ei tööta oodatult, proovi OGG formaati. Helifaile saab konvertida näiteks tasuta tarkvaraga Audacity.
Heli haldav klass¶
Audio lisamiseks oma mängu tuleks luua eraldi klass AudioManager, kuhu koondatakse kõik heliga seotud meetodid. Selle kasutamine on hea mitmel põhjusel:
Koondab kõik heliga seotud funktsioonid (laadimine, esitamine, peatamine) ühte kohta
Heliloogika kapseldamine parendab koodi loetavust ja hooldatavust.
Soodustab koodi korduvkasutatavust
Mängu keerukuse kasvades saab hõlpsasti meetodeid juurde lisada.
AudioManager näide¶
Allpool on AudioManager klass koos konstruktori, initsialiseerimise ja vabastamise meetoditega. AssetManager on siin jagatud üle kogu mängu (üks eksemplar), mis aitab vältida sama vara korduvat laadimist.
public class AudioManager {
private AssetManager assetManager;
private Music backgroundMusic;
private Sound soundEffect;
private float musicVolume = 0.8f; // Vaikimisi volüüm 80%
private float soundVolume = 1.0f;
// Konstruktor – võtab jagatud AssetManageri parameetrina
// (üks AssetManager kogu mängu jaoks, ei loo uut)
public AudioManager(AssetManager assetManager) {
this.assetManager = assetManager;
}
// Laeb kõik vajalikud helivarad AssetManageriga
public void loadAssets() {
// Music pikemate helide jaoks (taustamuusika)
assetManager.load("audio/background.ogg", Music.class);
// Sound lühikeste efektide jaoks
assetManager.load("audio/shoot.wav", Sound.class);
// Ootab kuni kõik varad on laetud
assetManager.finishLoading();
backgroundMusic = assetManager.get("audio/background.ogg", Music.class);
soundEffect = assetManager.get("audio/shoot.wav", Sound.class);
}
// Mängib taustamuusikat tsüklis
public void playBackgroundMusic() {
backgroundMusic.setLooping(true);
backgroundMusic.setVolume(musicVolume);
backgroundMusic.play();
}
// Peatab taustamuusika (saab hiljem jätkata)
public void pauseBackgroundMusic() {
backgroundMusic.pause();
}
// Mängib lühikest heliefekti
public void playSoundEffect() {
soundEffect.play(soundVolume);
}
// Muudab muusika volüümi (0.0 - 1.0)
public void setMusicVolume(float volume) {
this.musicVolume = volume;
if (backgroundMusic != null) {
backgroundMusic.setVolume(volume);
}
}
// Kutsu välja mängu sulgemisel
public void dispose() {
// AssetManager vabastab kõik laetud varad
assetManager.unload("audio/background.ogg");
assetManager.unload("audio/shoot.wav");
}
}
Helide järjestikune mängimine¶
Mõnikord on vaja mängida mitu heli üksteise järel (dialoogid, sammud või animatsiooniga seotud helid). Seda saab teha heli lõpetamise kuulaja (completion listener) abil.
public class AudioManager {
private Sound[] stepSounds; // Sammude helide massiiv
private int currentStepIndex = 0;
// Laeb mitu sammu heli
public void loadStepSounds() {
assetManager.load("audio/step1.wav", Sound.class);
assetManager.load("audio/step2.wav", Sound.class);
assetManager.load("audio/step3.wav", Sound.class);
assetManager.finishLoading();
stepSounds = new Sound[] {
assetManager.get("audio/step1.wav", Sound.class),
assetManager.get("audio/step2.wav", Sound.class),
assetManager.get("audio/step3.wav", Sound.class)
};
}
// Mängib sammude helisid tsükliliselt
public void playNextStep() {
// Mängib järgmise heli massiivist
stepSounds[currentStepIndex].play(soundVolume);
// Liigub järgmise heli juurde (tsükkel)
currentStepIndex = (currentStepIndex + 1) % stepSounds.length;
}
// Alternatiiv: kasuta Music klassi onCompletionListener
// järjestikku mängimiseks (nt dialoog)
public void playSequence(Music first, Music second) {
first.setOnCompletionListener(music -> {
// Esimene heli lõppes – mängi teist
second.play();
});
first.play();
}
}
Mängu integreerimine¶
AudioManager integreeritakse mängu läbi jagatud AssetManageri. See luuakse mängu peaklassis ja antakse edasi kõigile ekraanidele – nii välditakse sama vara korduvat laadimist.
public class MyGame extends Game {
public AssetManager assetManager;
public AudioManager audioManager;
@Override
public void create() {
assetManager = new AssetManager();
audioManager = new AudioManager(assetManager);
audioManager.loadAssets();
setScreen(new GameScreen(this));
}
@Override
public void dispose() {
audioManager.dispose();
assetManager.dispose();
}
}
public class GameScreen implements Screen {
private AudioManager audioManager;
public GameScreen(MyGame game) {
// Saab AudioManageri peamängult
this.audioManager = game.audioManager;
}
@Override
public void show() {
// Ekraan ilmub – käivita muusika
audioManager.playBackgroundMusic();
}
@Override
public void hide() {
// Ekraan peidetakse – peata muusika
audioManager.pauseBackgroundMusic();
}
}
Volüüm¶
Volüümi muutmist saab implementeerida LibGDX poolt pakutud Slider klassiga. Slider võtab konstruktoris minimaalsed ja maksimaalsed väärtused, sammusuurus määrab kui palju volüüm korraga muutub.
public class VolumeSlider extends Slider {
private AudioManager audioManager;
// Parameetrid:
// min, max – volüümi vahemik (0.0 kuni 1.0)
// stepSize – muutuse suurus ühe sammu kohta (nt 0.1)
// vertical – kas liugur on vertikaalne (false = horisontaalne)
// skin – LibGDX Skin liuguri visuaalse stiili jaoks
public VolumeSlider(float min, float max, float stepSize,
boolean vertical, Skin skin,
AudioManager audioManager) {
super(min, max, stepSize, vertical, skin);
this.audioManager = audioManager;
// Kuulaja käivitub iga kord, kui kasutaja liugurit liigutab
addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
float volume = getValue(); // 0.0 – 1.0
audioManager.setMusicVolume(volume);
}
});
}
}
Nüüd saab liuguri lisada oma helisätetega ekraanile:
public class AudioScreen implements Screen {
private Stage stage;
private Skin skin;
private AudioManager audioManager;
public AudioScreen(MyGame game) {
this.audioManager = game.audioManager;
stage = new Stage();
skin = new Skin(Gdx.files.internal("ui/uiskin.json"));
// Loo volüümi liugur: min=0, max=1, samm=0.1, horisontaalne
VolumeSlider volumeSlider = new VolumeSlider(
0f, 1f, 0.1f, false, skin, audioManager
);
// Aseta liugur ekraani keskele
volumeSlider.setPosition(
Gdx.graphics.getWidth() / 2f - 100,
Gdx.graphics.getHeight() / 2f
);
volumeSlider.setWidth(200);
stage.addActor(volumeSlider);
}
@Override
public void render(float delta) {
stage.act(delta);
stage.draw();
}
@Override
public void dispose() {
stage.dispose();
skin.dispose();
}
}