notworking: Idk

This commit is contained in:
Jakub Žitník 2025-03-28 08:17:13 +01:00
parent 433dbf6f96
commit a8e80c405d
Signed by: jzitnik
GPG Key ID: C577A802A6AF4EF3
34 changed files with 120 additions and 45 deletions

View File

@ -15,6 +15,7 @@ import cz.jzitnik.game.annotations.AutoTransient;
import cz.jzitnik.game.annotations.WalkSound; import cz.jzitnik.game.annotations.WalkSound;
import cz.jzitnik.game.annotations.BreaksByPlace; import cz.jzitnik.game.annotations.BreaksByPlace;
import cz.jzitnik.game.annotations.MineSound; import cz.jzitnik.game.annotations.MineSound;
import cz.jzitnik.game.annotations.MiningSound;
import cz.jzitnik.game.annotations.PlaceSound; import cz.jzitnik.game.annotations.PlaceSound;
import cz.jzitnik.game.blocks.Chest; import cz.jzitnik.game.blocks.Chest;
import cz.jzitnik.game.blocks.Furnace; import cz.jzitnik.game.blocks.Furnace;
@ -199,9 +200,19 @@ public class Game extends AutoTransientSupport {
double hardness = world[y][x].stream().filter(block -> !block.getBlockId().equals("air")).toList().getFirst() double hardness = world[y][x].stream().filter(block -> !block.getBlockId().equals("air")).toList().getFirst()
.calculateHardness(inventory); .calculateHardness(inventory);
var blocks = world[y][x];
this.mining = true; this.mining = true;
new Thread(() -> { new Thread(() -> {
for (Block block : blocks) {
if (block.getClass().isAnnotationPresent(MiningSound.class)) {
new Thread(() -> {
gameStates.dependencies.sound.playSound(configuration,
block.getClass().getAnnotation(MiningSound.class).value());
}).start();
}
}
try { try {
Thread.sleep((long) (hardness * 166)); Thread.sleep((long) (hardness * 166));
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -209,7 +220,14 @@ public class Game extends AutoTransientSupport {
} }
breakingBlock.setSpriteState(Breaking.BreakingState.SECOND); breakingBlock.setSpriteState(Breaking.BreakingState.SECOND);
screenRenderer.render(this); screenRenderer.render(this);
for (Block block : blocks) {
if (block.getClass().isAnnotationPresent(MiningSound.class)) {
new Thread(() -> {
gameStates.dependencies.sound.playSound(configuration,
block.getClass().getAnnotation(MiningSound.class).value());
}).start();
}
}
try { try {
Thread.sleep((long) (hardness * 166)); Thread.sleep((long) (hardness * 166));
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -217,7 +235,14 @@ public class Game extends AutoTransientSupport {
} }
breakingBlock.setSpriteState(Breaking.BreakingState.THIRD); breakingBlock.setSpriteState(Breaking.BreakingState.THIRD);
screenRenderer.render(this); screenRenderer.render(this);
for (Block block : blocks) {
if (block.getClass().isAnnotationPresent(MiningSound.class)) {
new Thread(() -> {
gameStates.dependencies.sound.playSound(configuration,
block.getClass().getAnnotation(MiningSound.class).value());
}).start();
}
}
try { try {
Thread.sleep((long) (hardness * 166)); Thread.sleep((long) (hardness * 166));
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -282,7 +307,6 @@ public class Game extends AutoTransientSupport {
gameStates.dependencies.eventHandlerProvider.handleMine(screenRenderer, this, x, y); gameStates.dependencies.eventHandlerProvider.handleMine(screenRenderer, this, x, y);
for (Block block : blocksCopy) { for (Block block : blocksCopy) {
if (block.getClass().isAnnotationPresent(MineSound.class)) { if (block.getClass().isAnnotationPresent(MineSound.class)) {
var key = block.getClass().getAnnotation(MineSound.class).value(); var key = block.getClass().getAnnotation(MineSound.class).value();
@ -478,10 +502,10 @@ public class Game extends AutoTransientSupport {
new Thread(() -> { new Thread(() -> {
try { try {
Thread.sleep(500); Thread.sleep(500);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
player.getPlayerBlock1().setSpriteState(SteveState.FIRST); player.getPlayerBlock1().setSpriteState(SteveState.FIRST);
player.getPlayerBlock2().setSpriteState(SteveState.SECOND); player.getPlayerBlock2().setSpriteState(SteveState.SECOND);
@ -490,7 +514,7 @@ public class Game extends AutoTransientSupport {
} }
private void playMovePlayerSound(int x, int y) { private void playMovePlayerSound(int x, int y) {
var blocks = world[y+1][x]; var blocks = world[y + 1][x];
for (Block block : blocks) { for (Block block : blocks) {
if (block.getClass().isAnnotationPresent(WalkSound.class)) { if (block.getClass().isAnnotationPresent(WalkSound.class)) {

View File

@ -6,10 +6,12 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import cz.jzitnik.game.core.sound.SoundKey; import cz.jzitnik.game.core.sound.SoundKey;
import cz.jzitnik.game.core.sound.SoundType;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@RequireAnnotation(BlockRegistry.class) @RequireAnnotation(BlockRegistry.class)
@SoundTypeSet(SoundType.BLOCK)
public @interface MineSound { public @interface MineSound {
SoundKey value(); SoundKey value();
} }

View File

@ -0,0 +1,17 @@
package cz.jzitnik.game.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import cz.jzitnik.game.core.sound.SoundKey;
import cz.jzitnik.game.core.sound.SoundType;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@RequireAnnotation(BlockRegistry.class)
@SoundTypeSet(SoundType.MINING)
public @interface MiningSound {
SoundKey value();
}

View File

@ -6,10 +6,12 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import cz.jzitnik.game.core.sound.SoundKey; import cz.jzitnik.game.core.sound.SoundKey;
import cz.jzitnik.game.core.sound.SoundType;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@RequireAnnotation(BlockRegistry.class) @RequireAnnotation(BlockRegistry.class)
@SoundTypeSet(SoundType.BLOCK)
public @interface PlaceSound { public @interface PlaceSound {
SoundKey value(); SoundKey value();
} }

View File

@ -5,7 +5,6 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import cz.jzitnik.game.core.sound.SoundKey; import cz.jzitnik.game.core.sound.SoundKey;
import cz.jzitnik.game.core.sound.SoundType;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
@ -13,6 +12,5 @@ import java.lang.annotation.ElementType;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface SoundRegistry { public @interface SoundRegistry {
SoundKey key(); SoundKey key();
SoundType type();
String[] resourceLocation(); String[] resourceLocation();
} }

View File

@ -0,0 +1,15 @@
package cz.jzitnik.game.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import cz.jzitnik.game.core.sound.SoundType;
import java.lang.annotation.ElementType;
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SoundTypeSet {
SoundType value();
}

View File

@ -6,10 +6,12 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import cz.jzitnik.game.core.sound.SoundKey; import cz.jzitnik.game.core.sound.SoundKey;
import cz.jzitnik.game.core.sound.SoundType;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@RequireAnnotation(BlockRegistry.class) @RequireAnnotation(BlockRegistry.class)
@SoundTypeSet(SoundType.WALKING)
public @interface WalkSound { public @interface WalkSound {
SoundKey value(); SoundKey value();
} }

View File

@ -11,6 +11,7 @@ import javax.sound.sampled.UnsupportedAudioFileException;
import org.reflections.Reflections; import org.reflections.Reflections;
import cz.jzitnik.game.annotations.SoundRegistry; import cz.jzitnik.game.annotations.SoundRegistry;
import cz.jzitnik.game.annotations.SoundTypeSet;
import cz.jzitnik.game.config.Configuration; import cz.jzitnik.game.config.Configuration;
import cz.jzitnik.tui.SoundPlayer; import cz.jzitnik.tui.SoundPlayer;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -38,20 +39,23 @@ public class Sound {
public void playSound(Configuration configuration, SoundKey soundKey) { public void playSound(Configuration configuration, SoundKey soundKey) {
var volume = configuration.getSoundVolume(); var volume = configuration.getSoundVolume();
var annotation = map.get(soundKey); var annotation = map.get(soundKey);
var resources = annotation.resourceLocation(); var resources = annotation.resourceLocation();
var resource = resources[random.nextInt(resources.length)]; var resource = resources[random.nextInt(resources.length)];
var typeVolue = annotation.type().getVolume(); var typeVolume = annotation.getClass().isAnnotationPresent(SoundTypeSet.class)
? annotation.getClass().getAnnotation(SoundTypeSet.class).value().getVolume()
int totalVolume = (int) ((volume + typeVolue) * 100) / 200; : 0;
log.debug("Type volume: {}", typeVolume);
log.debug("Config volume: {}", volume);
new Thread(() -> { new Thread(() -> {
try { try {
SoundPlayer.playSound(resource); SoundPlayer.playSound(resource, typeVolume, volume);
} catch (LineUnavailableException | IOException | UnsupportedAudioFileException | InterruptedException e) { } catch (LineUnavailableException | IOException | UnsupportedAudioFileException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -4,7 +4,9 @@ import lombok.Getter;
@Getter @Getter
public enum SoundType { public enum SoundType {
BLOCK(100); BLOCK(0),
WALKING(100),
MINING(100);
// TODO: Volume is not currently used but will be probably used in future to better normalize the sound volume // TODO: Volume is not currently used but will be probably used in future to better normalize the sound volume
private final int volume; private final int volume;

View File

@ -2,13 +2,12 @@ package cz.jzitnik.game.core.sound.registry;
import cz.jzitnik.game.annotations.SoundRegistry; import cz.jzitnik.game.annotations.SoundRegistry;
import cz.jzitnik.game.core.sound.SoundKey; import cz.jzitnik.game.core.sound.SoundKey;
import cz.jzitnik.game.core.sound.SoundType;
@SoundRegistry(key = SoundKey.GRASS, resourceLocation = { @SoundRegistry(key = SoundKey.GRASS, resourceLocation = {
"grass/grass1.ogg", "grass/grass1.ogg",
"grass/grass2.ogg", "grass/grass2.ogg",
"grass/grass3.ogg", "grass/grass3.ogg",
"grass/grass4.ogg" "grass/grass4.ogg"
}, type = SoundType.BLOCK) })
public class GrassSound { public class GrassSound {
} }

View File

@ -2,7 +2,6 @@ package cz.jzitnik.game.core.sound.registry;
import cz.jzitnik.game.annotations.SoundRegistry; import cz.jzitnik.game.annotations.SoundRegistry;
import cz.jzitnik.game.core.sound.SoundKey; import cz.jzitnik.game.core.sound.SoundKey;
import cz.jzitnik.game.core.sound.SoundType;
@SoundRegistry(key = SoundKey.GRASS_WALKING, resourceLocation = { @SoundRegistry(key = SoundKey.GRASS_WALKING, resourceLocation = {
"grass/walk1.ogg", "grass/walk1.ogg",
@ -11,6 +10,6 @@ import cz.jzitnik.game.core.sound.SoundType;
"grass/walk4.ogg", "grass/walk4.ogg",
"grass/walk5.ogg", "grass/walk5.ogg",
"grass/walk6.ogg", "grass/walk6.ogg",
}, type = SoundType.BLOCK) })
public class GrassWalkingSound { public class GrassWalkingSound {
} }

View File

@ -2,13 +2,12 @@ package cz.jzitnik.game.core.sound.registry;
import cz.jzitnik.game.annotations.SoundRegistry; import cz.jzitnik.game.annotations.SoundRegistry;
import cz.jzitnik.game.core.sound.SoundKey; import cz.jzitnik.game.core.sound.SoundKey;
import cz.jzitnik.game.core.sound.SoundType;
@SoundRegistry(key = SoundKey.GRAVEL, resourceLocation = { @SoundRegistry(key = SoundKey.GRAVEL, resourceLocation = {
"gravel/gravel1.wav", "gravel/gravel1.ogg",
"gravel/gravel2.wav", "gravel/gravel2.ogg",
"gravel/gravel3.wav", "gravel/gravel3.ogg",
"gravel/gravel4.wav" "gravel/gravel4.ogg"
}, type = SoundType.BLOCK) })
public class GravelSound { public class GravelSound {
} }

View File

@ -2,13 +2,12 @@ package cz.jzitnik.game.core.sound.registry;
import cz.jzitnik.game.annotations.SoundRegistry; import cz.jzitnik.game.annotations.SoundRegistry;
import cz.jzitnik.game.core.sound.SoundKey; import cz.jzitnik.game.core.sound.SoundKey;
import cz.jzitnik.game.core.sound.SoundType;
@SoundRegistry(key = SoundKey.GRAVEL_WALKING, resourceLocation = { @SoundRegistry(key = SoundKey.GRAVEL_WALKING, resourceLocation = {
"gravel/step1.wav", "gravel/step1.ogg",
"gravel/step2.wav", "gravel/step2.ogg",
"gravel/step3.wav", "gravel/step3.ogg",
"gravel/step4.wav", "gravel/step4.ogg",
}, type = SoundType.BLOCK) })
public class GravelWalkingSound { public class GravelWalkingSound {
} }

View File

@ -2,10 +2,9 @@ package cz.jzitnik.game.core.sound.registry;
import cz.jzitnik.game.annotations.SoundRegistry; import cz.jzitnik.game.annotations.SoundRegistry;
import cz.jzitnik.game.core.sound.SoundKey; import cz.jzitnik.game.core.sound.SoundKey;
import cz.jzitnik.game.core.sound.SoundType;
@SoundRegistry(key = SoundKey.WOOD, resourceLocation = { @SoundRegistry(key = SoundKey.WOOD, resourceLocation = {
"wood/wood1.ogg", "wood/wood1.ogg",
}, type = SoundType.BLOCK) })
public class WoodSound { public class WoodSound {
} }

View File

@ -3,6 +3,7 @@ package cz.jzitnik.game.entities.items.registry.blocks.blocks;
import cz.jzitnik.game.SpriteLoader; import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.BlockRegistry; import cz.jzitnik.game.annotations.BlockRegistry;
import cz.jzitnik.game.annotations.MineSound; import cz.jzitnik.game.annotations.MineSound;
import cz.jzitnik.game.annotations.MiningSound;
import cz.jzitnik.game.annotations.PlaceSound; import cz.jzitnik.game.annotations.PlaceSound;
import cz.jzitnik.game.annotations.ResetDataOnMine; import cz.jzitnik.game.annotations.ResetDataOnMine;
import cz.jzitnik.game.annotations.WalkSound; import cz.jzitnik.game.annotations.WalkSound;
@ -16,6 +17,7 @@ import java.util.ArrayList;
@PlaceSound(SoundKey.GRAVEL) @PlaceSound(SoundKey.GRAVEL)
@MineSound(SoundKey.GRAVEL) @MineSound(SoundKey.GRAVEL)
@WalkSound(SoundKey.GRAVEL_WALKING) @WalkSound(SoundKey.GRAVEL_WALKING)
@MiningSound(SoundKey.GRAVEL_WALKING)
@ResetDataOnMine @ResetDataOnMine
@BlockRegistry("dirt") @BlockRegistry("dirt")
public class DirtBlock extends Block { public class DirtBlock extends Block {

View File

@ -3,6 +3,7 @@ package cz.jzitnik.game.entities.items.registry.blocks.blocks;
import cz.jzitnik.game.SpriteLoader; import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.BlockRegistry; import cz.jzitnik.game.annotations.BlockRegistry;
import cz.jzitnik.game.annotations.MineSound; import cz.jzitnik.game.annotations.MineSound;
import cz.jzitnik.game.annotations.MiningSound;
import cz.jzitnik.game.annotations.PlaceSound; import cz.jzitnik.game.annotations.PlaceSound;
import cz.jzitnik.game.annotations.ResetDataOnMine; import cz.jzitnik.game.annotations.ResetDataOnMine;
import cz.jzitnik.game.annotations.WalkSound; import cz.jzitnik.game.annotations.WalkSound;
@ -16,6 +17,7 @@ import java.util.ArrayList;
@MineSound(SoundKey.GRASS) @MineSound(SoundKey.GRASS)
@PlaceSound(SoundKey.GRASS) @PlaceSound(SoundKey.GRASS)
@WalkSound(SoundKey.GRASS_WALKING) @WalkSound(SoundKey.GRASS_WALKING)
@MiningSound(SoundKey.GRASS_WALKING)
@ResetDataOnMine @ResetDataOnMine
@BlockRegistry(value = "grass", drops = "dirt") @BlockRegistry(value = "grass", drops = "dirt")
public class GrassBlock extends Block { public class GrassBlock extends Block {

View File

@ -4,6 +4,7 @@ import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.game.annotations.BlockRegistry; import cz.jzitnik.game.annotations.BlockRegistry;
import cz.jzitnik.game.annotations.FallingBlock; import cz.jzitnik.game.annotations.FallingBlock;
import cz.jzitnik.game.annotations.MineSound; import cz.jzitnik.game.annotations.MineSound;
import cz.jzitnik.game.annotations.MiningSound;
import cz.jzitnik.game.annotations.PlaceSound; import cz.jzitnik.game.annotations.PlaceSound;
import cz.jzitnik.game.annotations.WalkSound; import cz.jzitnik.game.annotations.WalkSound;
import cz.jzitnik.game.core.sound.SoundKey; import cz.jzitnik.game.core.sound.SoundKey;
@ -15,6 +16,7 @@ import java.util.ArrayList;
@PlaceSound(SoundKey.GRAVEL) @PlaceSound(SoundKey.GRAVEL)
@MineSound(SoundKey.GRAVEL) @MineSound(SoundKey.GRAVEL)
@WalkSound(SoundKey.GRAVEL_WALKING) @WalkSound(SoundKey.GRAVEL_WALKING)
@MiningSound(SoundKey.GRAVEL_WALKING)
@FallingBlock @FallingBlock
@BlockRegistry("gravel") @BlockRegistry("gravel")
public class GravelBlock extends Block { public class GravelBlock extends Block {

View File

@ -7,19 +7,17 @@ import java.io.IOException;
@Slf4j @Slf4j
public class SoundPlayer { public class SoundPlayer {
public static void playSound(String filePath) public static void playSound(String filePath, int backendVolume, int masterVolume)
throws LineUnavailableException, IOException, UnsupportedAudioFileException, InterruptedException { throws LineUnavailableException, IOException, UnsupportedAudioFileException {
if (!filePath.endsWith(".ogg")) { if (!filePath.endsWith(".ogg") || masterVolume == 0) {
return; return; // No sound if master volume is 0
} }
log.info("Loading resource: {}", "sounds/" + filePath); log.info("Loading resource: {}", "sounds/" + filePath);
var file = SoundPlayer.class.getClassLoader().getResourceAsStream("sounds/" + filePath); var file = SoundPlayer.class.getClassLoader().getResourceAsStream("sounds/" + filePath);
AudioInputStream audioStream = AudioSystem.getAudioInputStream(file); AudioInputStream audioStream = AudioSystem.getAudioInputStream(file);
AudioFormat baseFormat = audioStream.getFormat(); AudioFormat baseFormat = audioStream.getFormat();
// Convert the audio format to PCM_SIGNED
AudioFormat targetFormat = new AudioFormat( AudioFormat targetFormat = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED, AudioFormat.Encoding.PCM_SIGNED,
baseFormat.getSampleRate(), baseFormat.getSampleRate(),
@ -30,10 +28,9 @@ public class SoundPlayer {
false false
); );
// Apply the format change to the stream
AudioInputStream dataIn = AudioSystem.getAudioInputStream(targetFormat, audioStream); AudioInputStream dataIn = AudioSystem.getAudioInputStream(targetFormat, audioStream);
byte[] buffer = new byte[8192]; // Larger buffer to reduce read/write operations byte[] buffer = new byte[8192];
DataLine.Info info = new DataLine.Info(SourceDataLine.class, targetFormat); DataLine.Info info = new DataLine.Info(SourceDataLine.class, targetFormat);
try (SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info)) { try (SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info)) {
@ -41,18 +38,29 @@ public class SoundPlayer {
line.open(targetFormat); line.open(targetFormat);
line.start(); line.start();
float finalVolume = (backendVolume / 100.0f) * (masterVolume / 100.0f);
log.info("Applying volume: {} (backend: {}, master: {})", finalVolume, backendVolume, masterVolume);
int bytesRead; int bytesRead;
while ((bytesRead = dataIn.read(buffer, 0, buffer.length)) != -1) { while ((bytesRead = dataIn.read(buffer, 0, buffer.length)) != -1) {
applyVolume(buffer, bytesRead, finalVolume);
line.write(buffer, 0, bytesRead); line.write(buffer, 0, bytesRead);
} }
// Ensure the line is fully flushed before stopping
line.drain(); line.drain();
} }
} }
// Close streams after use
dataIn.close(); dataIn.close();
audioStream.close(); audioStream.close();
} }
private static void applyVolume(byte[] buffer, int bytesRead, float volume) {
for (int i = 0; i < bytesRead; i += 2) { // 16-bit PCM samples are 2 bytes each
int sample = (buffer[i] & 0xFF) | (buffer[i + 1] << 8);
sample = (int) (sample * volume);
buffer[i] = (byte) (sample & 0xFF);
buffer[i + 1] = (byte) ((sample >> 8) & 0xFF);
}
}
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.