Added directional sound.
This commit is contained in:
parent
3b9519cbca
commit
b8311cd0b5
|
@ -80,7 +80,7 @@ public class Client {
|
|||
team.setScore(t.getScore());
|
||||
}
|
||||
}
|
||||
this.soundManager.play(update.getSoundsToPlay());
|
||||
this.soundManager.play(update.getSoundsToPlay(), myPlayer);
|
||||
}
|
||||
|
||||
public void setWorld(World world) {
|
||||
|
|
|
@ -1,32 +1,56 @@
|
|||
package nl.andrewlalis.aos_client;
|
||||
|
||||
import nl.andrewlalis.aos_core.geom.Vec2;
|
||||
import nl.andrewlalis.aos_core.model.Player;
|
||||
import nl.andrewlalis.aos_core.net.data.Sound;
|
||||
import nl.andrewlalis.aos_core.net.data.SoundType;
|
||||
|
||||
import javax.sound.sampled.*;
|
||||
import java.io.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class SoundManager {
|
||||
private static final int CLIP_COUNT = 10;
|
||||
private static final float HEARING_RANGE = 50.0f;
|
||||
private final Map<String, List<Clip>> soundData = new HashMap<>();
|
||||
private final Map<String, Integer> clipIndexes = new HashMap<>();
|
||||
|
||||
public void play(List<Sound> sounds, Player player) {
|
||||
for (Sound sound : sounds) {
|
||||
this.play(sound, player);
|
||||
}
|
||||
}
|
||||
public void play(List<Sound> sounds) {
|
||||
for (Sound sound : sounds) {
|
||||
this.play(sound);
|
||||
this.play(sound, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void play(Sound sound) {
|
||||
var clip = this.getClip(sound.getType().getSoundName());
|
||||
this.play(sound, null);
|
||||
}
|
||||
|
||||
public void play(Sound sound, Player player) {
|
||||
var clip = this.getClip(sound.getType());
|
||||
if (clip == null) {
|
||||
return;
|
||||
}
|
||||
clip.setFramePosition(0);
|
||||
setVolume(clip, sound.getVolume());
|
||||
float v = sound.getVolume();
|
||||
if (player != null && sound.getPosition() != null) {
|
||||
float dist = player.getPosition().dist(sound.getPosition());
|
||||
v *= (Math.max(HEARING_RANGE - dist, 0) / HEARING_RANGE);
|
||||
}
|
||||
if (v <= 0.0f) return;
|
||||
if (player != null && player.getTeam() != null && sound.getPosition() != null) {
|
||||
setPan(clip, player.getPosition(), sound.getPosition(), player.getTeam().getOrientation());
|
||||
}
|
||||
setVolume(clip, v);
|
||||
clip.start();
|
||||
}
|
||||
|
||||
|
@ -36,7 +60,19 @@ public class SoundManager {
|
|||
gainControl.setValue(20f * (float) Math.log10(volume));
|
||||
}
|
||||
|
||||
private Clip getClip(String sound) {
|
||||
private void setPan(Clip clip, Vec2 playerPos, Vec2 soundPos, Vec2 playerOrientation) {
|
||||
Vec2 soundDir = soundPos
|
||||
.sub(playerPos)
|
||||
.rotate(playerOrientation.perp().angle())
|
||||
.unit();
|
||||
float pan = Math.max(Math.min(soundDir.dot(Vec2.RIGHT), 1.0f), -1.0f);
|
||||
if (Float.isNaN(pan)) pan = 0f;
|
||||
FloatControl panControl = (FloatControl) clip.getControl(FloatControl.Type.PAN);
|
||||
panControl.setValue(pan);
|
||||
}
|
||||
|
||||
private Clip getClip(SoundType soundType) {
|
||||
String sound = soundType.getSoundName();
|
||||
var clips = this.soundData.get(sound);
|
||||
if (clips == null) {
|
||||
InputStream is = Client.class.getResourceAsStream("/nl/andrewlalis/aos_client/sound/" + sound);
|
||||
|
@ -48,8 +84,8 @@ public class SoundManager {
|
|||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
is.transferTo(bos);
|
||||
byte[] data = bos.toByteArray();
|
||||
clips = new ArrayList<>(CLIP_COUNT);
|
||||
for (int i = 0; i < CLIP_COUNT; i++) {
|
||||
clips = new ArrayList<>(soundType.getClipBufferCount());
|
||||
for (int i = 0; i < soundType.getClipBufferCount(); i++) {
|
||||
var ais = AudioSystem.getAudioInputStream(new ByteArrayInputStream(data));
|
||||
var clip = AudioSystem.getClip();
|
||||
clip.open(ais);
|
||||
|
@ -64,7 +100,7 @@ public class SoundManager {
|
|||
}
|
||||
}
|
||||
int index = this.clipIndexes.get(sound);
|
||||
if (index >= CLIP_COUNT) {
|
||||
if (index >= soundType.getClipBufferCount()) {
|
||||
index = 0;
|
||||
}
|
||||
Clip clip = clips.get(index);
|
||||
|
|
|
@ -9,6 +9,9 @@ import java.util.concurrent.ThreadLocalRandom;
|
|||
public record Vec2(float x, float y) implements Serializable {
|
||||
public static final Vec2 ZERO = new Vec2(0, 0);
|
||||
public static final Vec2 UP = new Vec2(0, -1);
|
||||
public static final Vec2 DOWN = new Vec2(0, 1);
|
||||
public static final Vec2 RIGHT = new Vec2(1, 0);
|
||||
public static final Vec2 LEFT = new Vec2(-1, 0);
|
||||
|
||||
|
||||
public float mag() {
|
||||
|
|
|
@ -8,24 +8,26 @@ import java.util.Map;
|
|||
* efficient transmission to clients.
|
||||
*/
|
||||
public enum SoundType {
|
||||
SHOT_SMG(0, "ak47shot1.wav"),
|
||||
SHOT_RIFLE(1, "m1garand-shot1.wav"),
|
||||
SHOT_SHOTGUN(2, "shotgun-shot1.wav"),
|
||||
RELOAD(3, "reload.wav"),
|
||||
CHAT(4, "chat.wav"),
|
||||
DEATH(5, "death.wav"),
|
||||
BULLET_IMPACT_1(6, "bullet_impact_1.wav"),
|
||||
BULLET_IMPACT_2(7, "bullet_impact_2.wav"),
|
||||
BULLET_IMPACT_3(8, "bullet_impact_3.wav"),
|
||||
BULLET_IMPACT_4(9, "bullet_impact_4.wav"),
|
||||
BULLET_IMPACT_5(10, "bullet_impact_5.wav");
|
||||
SHOT_SMG(0, "ak47shot1.wav", 25),
|
||||
SHOT_RIFLE(1, "m1garand-shot1.wav", 25),
|
||||
SHOT_SHOTGUN(2, "shotgun-shot1.wav", 25),
|
||||
RELOAD(3, "reload.wav", 10),
|
||||
CHAT(4, "chat.wav", 5),
|
||||
DEATH(5, "death.wav", 5),
|
||||
BULLET_IMPACT_1(6, "bullet_impact_1.wav", 10),
|
||||
BULLET_IMPACT_2(7, "bullet_impact_2.wav", 10),
|
||||
BULLET_IMPACT_3(8, "bullet_impact_3.wav", 10),
|
||||
BULLET_IMPACT_4(9, "bullet_impact_4.wav", 10),
|
||||
BULLET_IMPACT_5(10, "bullet_impact_5.wav", 10);
|
||||
|
||||
private final byte code;
|
||||
private final String soundName;
|
||||
private final int clipBufferCount;
|
||||
|
||||
SoundType(int code, String soundName) {
|
||||
SoundType(int code, String soundName, int clipBufferCount) {
|
||||
this.code = (byte) code;
|
||||
this.soundName = soundName;
|
||||
this.clipBufferCount = clipBufferCount;
|
||||
}
|
||||
|
||||
public byte getCode() {
|
||||
|
@ -36,6 +38,10 @@ public enum SoundType {
|
|||
return soundName;
|
||||
}
|
||||
|
||||
public int getClipBufferCount() {
|
||||
return clipBufferCount;
|
||||
}
|
||||
|
||||
private static final Map<Byte, SoundType> typeIndex = new HashMap<>();
|
||||
static {
|
||||
for (var val : values()) {
|
||||
|
|
|
@ -60,6 +60,18 @@ gun-settings:
|
|||
bullet-speed: 90
|
||||
base-damage: 40
|
||||
|
||||
- name: M-249
|
||||
category: SMG
|
||||
color: "#001942"
|
||||
max-clip-count: 3
|
||||
clip-size: 100
|
||||
bullets-per-round: 1
|
||||
accuracy: 0.08
|
||||
shot-cooldown-time: 0.03
|
||||
reload-time: 3.5
|
||||
bullet-speed: 80
|
||||
base-damage: 35
|
||||
|
||||
- name: M1 Garand
|
||||
category: RIFLE
|
||||
color: "#452d06"
|
||||
|
|
Loading…
Reference in New Issue