|
| 1 | +package audio; |
1 | 2 |
|
| 3 | +import java.io.IOException; |
| 4 | +import java.net.URL; |
| 5 | +import java.util.Random; |
| 6 | +import javax.sound.sampled.*; |
| 7 | + |
| 8 | +public class AudioPlayer { |
| 9 | + |
| 10 | + // Các chỉ số cho các bài nhạc |
| 11 | + public static int MENU_1 = 0; |
| 12 | + public static int LEVEL_1 = 1; |
| 13 | + public static int LEVEL_2 = 2; |
| 14 | + |
| 15 | + // Các chỉ số cho các hiệu ứng âm thanh |
| 16 | + public static int DIE = 0; //Chết |
| 17 | + public static int JUMP = 1;// Nhảy |
| 18 | + public static int GAMEOVER = 2;// Kết thúc trò chơi |
| 19 | + public static int LVL_COMPLETED = 3;// hoàn thành level |
| 20 | + public static int ATTACK_ONE = 4;// Kĩ năng đánh 1 |
| 21 | + public static int ATTACK_TWO = 5;// Kĩ năng đánh 2 |
| 22 | + public static int ATTACK_THREE = 6;// Kĩ năng đánh 3 |
| 23 | + |
| 24 | + private Clip[] songs, effects; // Mảng chứa các bài nhạc và hiệu ứng âm thanh |
| 25 | + private int currentSongId; // ID bài nhạc đang phát |
| 26 | + private float volume = 0.5f; // Mức âm lượng mặc định |
| 27 | + private boolean songMute, effectMute; // Trạng thái tắt tiếng của nhạc và hiệu ứng |
| 28 | + private Random rand = new Random(); // Để phát hiệu ứng âm thanh ngẫu nhiên |
| 29 | + |
| 30 | + // Constructor: Khởi tạo AudioPlayer và bắt đầu phát nhạc menu |
| 31 | + public AudioPlayer() { |
| 32 | + loadSongs(); // Nạp các bài nhạc |
| 33 | + loadEffects(); // Nạp các hiệu ứng âm thanh |
| 34 | + playSong(MENU_1); // Phát nhạc menu |
| 35 | + } |
| 36 | + |
| 37 | + // Nạp các file âm thanh cho nhạc nền từ thư mục /audio/ |
| 38 | + private void loadSongs() { |
| 39 | + String[] names = { "menu", "level1", "level2" }; // Tên các file nhạc |
| 40 | + songs = new Clip[names.length]; // Tạo mảng chứa các bài nhạc |
| 41 | + for (int i = 0; i < songs.length; i++) |
| 42 | + songs[i] = getClip(names[i]); // Lấy từng bài nhạc từ file |
| 43 | + } |
| 44 | + |
| 45 | + // Nạp các file âm thanh cho hiệu ứng từ thư mục /audio/ |
| 46 | + private void loadEffects() { |
| 47 | + String[] effectNames = { "die", "jump", "gameover", "lvlcompleted", "attack1", "attack2", "attack3" }; // Tên các file hiệu ứng |
| 48 | + effects = new Clip[effectNames.length]; // Tạo mảng chứa hiệu ứng âm thanh |
| 49 | + for (int i = 0; i < effects.length; i++) |
| 50 | + effects[i] = getClip(effectNames[i]); // Lấy từng hiệu ứng từ file |
| 51 | + |
| 52 | + updateEffectsVolume(); // Cập nhật âm lượng cho hiệu ứng âm thanh |
| 53 | + } |
| 54 | + |
| 55 | + // Lấy file âm thanh từ đường dẫn và tạo đối tượng Clip |
| 56 | + private Clip getClip(String name) { |
| 57 | + URL url = getClass().getResource("/audio/" + name + ".wav"); // Đường dẫn tới file âm thanh |
| 58 | + AudioInputStream audio; |
| 59 | + |
| 60 | + try { |
| 61 | + audio = AudioSystem.getAudioInputStream(url); // Lấy dữ liệu âm thanh từ file |
| 62 | + Clip c = AudioSystem.getClip(); // Tạo đối tượng Clip |
| 63 | + c.open(audio); // Mở file âm thanh |
| 64 | + return c; // Trả về đối tượng Clip |
| 65 | + |
| 66 | + } catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) { |
| 67 | + e.printStackTrace(); // Bắt và in lỗi nếu có |
| 68 | + } |
| 69 | + |
| 70 | + return null; // Trả về null nếu xảy ra lỗi |
| 71 | + } |
| 72 | + |
| 73 | + // Đặt âm lượng mới cho cả nhạc nền và hiệu ứng âm thanh |
| 74 | + public void setVolume(float volume) { |
| 75 | + this.volume = volume; |
| 76 | + updateSongVolume(); // Cập nhật âm lượng của nhạc |
| 77 | + updateEffectsVolume(); // Cập nhật âm lượng của hiệu ứng |
| 78 | + } |
| 79 | + |
| 80 | + // Dừng phát nhạc hiện tại |
| 81 | + public void stopSong() { |
| 82 | + if (songs[currentSongId].isActive()) |
| 83 | + songs[currentSongId].stop(); // Dừng bài nhạc nếu nó đang phát |
| 84 | + } |
| 85 | + |
| 86 | + // Đặt nhạc nền theo cấp độ (level) trò chơi |
| 87 | + public void setLevelSong(int lvlIndex) { |
| 88 | + if (lvlIndex % 2 == 0) |
| 89 | + playSong(LEVEL_1); // Phát nhạc của level 1 nếu chỉ số là chẵn |
| 90 | + else |
| 91 | + playSong(LEVEL_2); // Phát nhạc của level 2 nếu chỉ số là lẻ |
| 92 | + } |
| 93 | + |
| 94 | + // Khi hoàn thành màn chơi, dừng nhạc và phát hiệu ứng hoàn thành |
| 95 | + public void lvlCompleted() { |
| 96 | + stopSong(); |
| 97 | + playEffect(LVL_COMPLETED); // Phát hiệu ứng âm thanh hoàn thành level |
| 98 | + } |
| 99 | + |
| 100 | + // Phát hiệu ứng âm thanh tấn công ngẫu nhiên |
| 101 | + public void playAttackSound() { |
| 102 | + int start = 4; // Các hiệu ứng tấn công bắt đầu từ chỉ số 4 |
| 103 | + start += rand.nextInt(3); // Chọn ngẫu nhiên giữa các hiệu ứng tấn công |
| 104 | + playEffect(start); // Phát hiệu ứng tấn công |
| 105 | + } |
| 106 | + |
| 107 | + // Phát hiệu ứng âm thanh |
| 108 | + public void playEffect(int effect) { |
| 109 | + if (effects[effect].getMicrosecondPosition() > 0) |
| 110 | + effects[effect].setMicrosecondPosition(0); // Reset thời gian nếu hiệu ứng đã phát |
| 111 | + effects[effect].start(); // Bắt đầu phát hiệu ứng |
| 112 | + } |
| 113 | + |
| 114 | + // Phát nhạc nền |
| 115 | + public void playSong(int song) { |
| 116 | + stopSong(); |
| 117 | + // Dừng bài nhạc hiện tại |
| 118 | + |
| 119 | + currentSongId = song; // Cập nhật ID bài nhạc mới |
| 120 | + updateSongVolume(); // Cập nhật âm lượng |
| 121 | + songs[currentSongId].setMicrosecondPosition(0); // Đặt lại vị trí phát nhạc |
| 122 | + songs[currentSongId].loop(Clip.LOOP_CONTINUOUSLY); // Phát nhạc liên tục |
| 123 | + } |
| 124 | + |
| 125 | + // Chuyển đổi trạng thái tắt/bật tiếng của nhạc nền |
| 126 | + public void toggleSongMute() { |
| 127 | + this.songMute = !songMute; |
| 128 | + for (Clip c : songs) { |
| 129 | + BooleanControl booleanControl = (BooleanControl) c.getControl(BooleanControl.Type.MUTE); |
| 130 | + booleanControl.setValue(songMute); // Tắt hoặc bật tiếng cho nhạc |
| 131 | + } |
| 132 | + } |
| 133 | + |
| 134 | + // Chuyển đổi trạng thái tắt/bật tiếng của hiệu ứng âm thanh |
| 135 | + public void toggleEffectMute() { |
| 136 | + this.effectMute = !effectMute; |
| 137 | + for (Clip c : effects) { |
| 138 | + BooleanControl booleanControl = (BooleanControl) c.getControl(BooleanControl.Type.MUTE); |
| 139 | + booleanControl.setValue(effectMute); // Tắt hoặc bật tiếng cho hiệu ứng |
| 140 | + } |
| 141 | + if (!effectMute) |
| 142 | + playEffect(JUMP); // Nếu bật lại tiếng, phát hiệu ứng nhảy |
| 143 | + } |
| 144 | + |
| 145 | + // Cập nhật âm lượng cho nhạc nền |
| 146 | + private void updateSongVolume() { |
| 147 | + FloatControl gainControl = (FloatControl) songs[currentSongId].getControl(FloatControl.Type.MASTER_GAIN); |
| 148 | + float range = gainControl.getMaximum() - gainControl.getMinimum(); // Tính khoảng điều chỉnh âm lượng |
| 149 | + float gain = (range * volume) + gainControl.getMinimum(); // Tính giá trị âm lượng mới |
| 150 | + gainControl.setValue(gain); // Đặt âm lượng mới cho nhạc nền |
| 151 | + } |
| 152 | + |
| 153 | + // Cập nhật âm lượng cho hiệu ứng âm thanh |
| 154 | + private void updateEffectsVolume() { |
| 155 | + for (Clip c : effects) { |
| 156 | + FloatControl gainControl = (FloatControl) c.getControl(FloatControl.Type.MASTER_GAIN); |
| 157 | + float range = gainControl.getMaximum() - gainControl.getMinimum(); // Tính khoảng điều chỉnh âm lượng |
| 158 | + float gain = (range * volume) + gainControl.getMinimum(); // Tính giá trị âm lượng mới |
| 159 | + gainControl.setValue(gain); // Đặt âm lượng mới cho hiệu ứng âm thanh |
| 160 | + } |
| 161 | + } |
| 162 | +} |
0 commit comments