Added directional sound.

This commit is contained in:
Andrew Lalis 2021-06-30 20:51:16 +02:00
parent 3b9519cbca
commit b8311cd0b5
5 changed files with 79 additions and 22 deletions

View File

@ -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) {

View File

@ -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);

View File

@ -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() {

View File

@ -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()) {

View File

@ -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"