Added directional sound.
This commit is contained in:
parent
3b9519cbca
commit
b8311cd0b5
|
@ -80,7 +80,7 @@ public class Client {
|
||||||
team.setScore(t.getScore());
|
team.setScore(t.getScore());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.soundManager.play(update.getSoundsToPlay());
|
this.soundManager.play(update.getSoundsToPlay(), myPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWorld(World world) {
|
public void setWorld(World world) {
|
||||||
|
|
|
@ -1,32 +1,56 @@
|
||||||
package nl.andrewlalis.aos_client;
|
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.Sound;
|
||||||
|
import nl.andrewlalis.aos_core.net.data.SoundType;
|
||||||
|
|
||||||
import javax.sound.sampled.*;
|
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.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class SoundManager {
|
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, List<Clip>> soundData = new HashMap<>();
|
||||||
private final Map<String, Integer> clipIndexes = 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) {
|
public void play(List<Sound> sounds) {
|
||||||
for (Sound sound : sounds) {
|
for (Sound sound : sounds) {
|
||||||
this.play(sound);
|
this.play(sound, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void play(Sound sound) {
|
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) {
|
if (clip == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clip.setFramePosition(0);
|
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();
|
clip.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +60,19 @@ public class SoundManager {
|
||||||
gainControl.setValue(20f * (float) Math.log10(volume));
|
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);
|
var clips = this.soundData.get(sound);
|
||||||
if (clips == null) {
|
if (clips == null) {
|
||||||
InputStream is = Client.class.getResourceAsStream("/nl/andrewlalis/aos_client/sound/" + sound);
|
InputStream is = Client.class.getResourceAsStream("/nl/andrewlalis/aos_client/sound/" + sound);
|
||||||
|
@ -48,8 +84,8 @@ public class SoundManager {
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
is.transferTo(bos);
|
is.transferTo(bos);
|
||||||
byte[] data = bos.toByteArray();
|
byte[] data = bos.toByteArray();
|
||||||
clips = new ArrayList<>(CLIP_COUNT);
|
clips = new ArrayList<>(soundType.getClipBufferCount());
|
||||||
for (int i = 0; i < CLIP_COUNT; i++) {
|
for (int i = 0; i < soundType.getClipBufferCount(); i++) {
|
||||||
var ais = AudioSystem.getAudioInputStream(new ByteArrayInputStream(data));
|
var ais = AudioSystem.getAudioInputStream(new ByteArrayInputStream(data));
|
||||||
var clip = AudioSystem.getClip();
|
var clip = AudioSystem.getClip();
|
||||||
clip.open(ais);
|
clip.open(ais);
|
||||||
|
@ -64,7 +100,7 @@ public class SoundManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int index = this.clipIndexes.get(sound);
|
int index = this.clipIndexes.get(sound);
|
||||||
if (index >= CLIP_COUNT) {
|
if (index >= soundType.getClipBufferCount()) {
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
Clip clip = clips.get(index);
|
Clip clip = clips.get(index);
|
||||||
|
|
|
@ -9,6 +9,9 @@ import java.util.concurrent.ThreadLocalRandom;
|
||||||
public record Vec2(float x, float y) implements Serializable {
|
public record Vec2(float x, float y) implements Serializable {
|
||||||
public static final Vec2 ZERO = new Vec2(0, 0);
|
public static final Vec2 ZERO = new Vec2(0, 0);
|
||||||
public static final Vec2 UP = new Vec2(0, -1);
|
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() {
|
public float mag() {
|
||||||
|
|
|
@ -8,24 +8,26 @@ import java.util.Map;
|
||||||
* efficient transmission to clients.
|
* efficient transmission to clients.
|
||||||
*/
|
*/
|
||||||
public enum SoundType {
|
public enum SoundType {
|
||||||
SHOT_SMG(0, "ak47shot1.wav"),
|
SHOT_SMG(0, "ak47shot1.wav", 25),
|
||||||
SHOT_RIFLE(1, "m1garand-shot1.wav"),
|
SHOT_RIFLE(1, "m1garand-shot1.wav", 25),
|
||||||
SHOT_SHOTGUN(2, "shotgun-shot1.wav"),
|
SHOT_SHOTGUN(2, "shotgun-shot1.wav", 25),
|
||||||
RELOAD(3, "reload.wav"),
|
RELOAD(3, "reload.wav", 10),
|
||||||
CHAT(4, "chat.wav"),
|
CHAT(4, "chat.wav", 5),
|
||||||
DEATH(5, "death.wav"),
|
DEATH(5, "death.wav", 5),
|
||||||
BULLET_IMPACT_1(6, "bullet_impact_1.wav"),
|
BULLET_IMPACT_1(6, "bullet_impact_1.wav", 10),
|
||||||
BULLET_IMPACT_2(7, "bullet_impact_2.wav"),
|
BULLET_IMPACT_2(7, "bullet_impact_2.wav", 10),
|
||||||
BULLET_IMPACT_3(8, "bullet_impact_3.wav"),
|
BULLET_IMPACT_3(8, "bullet_impact_3.wav", 10),
|
||||||
BULLET_IMPACT_4(9, "bullet_impact_4.wav"),
|
BULLET_IMPACT_4(9, "bullet_impact_4.wav", 10),
|
||||||
BULLET_IMPACT_5(10, "bullet_impact_5.wav");
|
BULLET_IMPACT_5(10, "bullet_impact_5.wav", 10);
|
||||||
|
|
||||||
private final byte code;
|
private final byte code;
|
||||||
private final String soundName;
|
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.code = (byte) code;
|
||||||
this.soundName = soundName;
|
this.soundName = soundName;
|
||||||
|
this.clipBufferCount = clipBufferCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte getCode() {
|
public byte getCode() {
|
||||||
|
@ -36,6 +38,10 @@ public enum SoundType {
|
||||||
return soundName;
|
return soundName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getClipBufferCount() {
|
||||||
|
return clipBufferCount;
|
||||||
|
}
|
||||||
|
|
||||||
private static final Map<Byte, SoundType> typeIndex = new HashMap<>();
|
private static final Map<Byte, SoundType> typeIndex = new HashMap<>();
|
||||||
static {
|
static {
|
||||||
for (var val : values()) {
|
for (var val : values()) {
|
||||||
|
|
|
@ -60,6 +60,18 @@ gun-settings:
|
||||||
bullet-speed: 90
|
bullet-speed: 90
|
||||||
base-damage: 40
|
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
|
- name: M1 Garand
|
||||||
category: RIFLE
|
category: RIFLE
|
||||||
color: "#452d06"
|
color: "#452d06"
|
||||||
|
|
Loading…
Reference in New Issue