Skip to content

feature: add mute and umute button, and functionality to mute during rounds #43

Merged
merged 2 commits into from
Apr 10, 2026
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
public class AudioSystem extends EntitySystem {
private static AudioSystem instance;
private AudioPlayer audioPlayer;
private boolean muted = false;

private AudioSystem() {}

Expand Down Expand Up @@ -42,9 +43,14 @@ public void stop(Entity round) {
}

public void setMuted(boolean muted) {
this.muted = muted;
if (audioPlayer != null) audioPlayer.setMuted(muted);
}

public boolean isMuted() {
return muted;
}

public void dispose() {
if (audioPlayer != null) audioPlayer.dispose();
}
Expand Down
84 changes: 83 additions & 1 deletion core/src/main/java/group07/beatbattle/view/GameRoundView.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import group07.beatbattle.BeatBattle;
import group07.beatbattle.controller.RoundController;
import group07.beatbattle.ecs.Engine;
import group07.beatbattle.ecs.systems.AudioSystem;
import group07.beatbattle.i18n.Strings;
import group07.beatbattle.model.Question;

Expand Down Expand Up @@ -53,11 +54,16 @@ public class GameRoundView extends ScreenAdapter {
private boolean revealed = false;
private float resultDelay = RESULT_DISPLAY_DELAY;

private boolean muted = false;
private TextButton muteButton;

private Texture defaultTex;
private Texture selectedTex;
private Texture disabledTex;
private Texture correctTex;
private Texture wrongTex;
private Texture iconSoundTex;
private Texture iconMuteTex;
private Texture logoTexture;

public GameRoundView(BeatBattle game, RoundController controller) {
Expand All @@ -72,6 +78,8 @@ public GameRoundView(BeatBattle game, RoundController controller) {
disabledTex = solidTexture(COLOR_DISABLED);
correctTex = solidTexture(COLOR_CORRECT);
wrongTex = solidTexture(COLOR_WRONG);
iconSoundTex = createSpeakerTexture(false);
iconMuteTex = createSpeakerTexture(true);

logoTexture = new Texture(Gdx.files.internal("logo.png"));
Image bgLogo = new Image(logoTexture);
Expand Down Expand Up @@ -101,9 +109,22 @@ public void changed(ChangeEvent event, Actor actor) {
timerLabel = new Label(String.valueOf((int) Math.ceil(controller.getTotalTime())), timerStyle());
timerLabel.setAlignment(Align.center);

muted = AudioSystem.getInstance().isMuted();
muteButton = makeButton("", muted ? iconMuteTex : iconSoundTex);
muteButton.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
muted = !muted;
AudioSystem.getInstance().setMuted(muted);
Texture tex = muted ? iconMuteTex : iconSoundTex;
muteButton.getStyle().up = new TextureRegionDrawable(new TextureRegion(tex));
muteButton.getStyle().down = new TextureRegionDrawable(new TextureRegion(tex));
}
});

topBar.add(leaveButton).width(120f).height(100f).padLeft(40f);
topBar.add(timerLabel).expandX().center().padTop(60f);
topBar.add().width(120f).padRight(40f); // Spacer
topBar.add(muteButton).width(120f).height(100f).padRight(40f);

root.add(topBar).fillX().row();

Expand Down Expand Up @@ -197,6 +218,8 @@ public void dispose() {
disabledTex.dispose();
correctTex.dispose();
wrongTex.dispose();
iconSoundTex.dispose();
iconMuteTex.dispose();
logoTexture.dispose();
}

Expand Down Expand Up @@ -232,6 +255,65 @@ private Label.LabelStyle timerStyle() {
return style;
}

private Texture createSpeakerTexture(boolean muted) {
int S = 128;
Pixmap pm = new Pixmap(S, S, Pixmap.Format.RGBA8888);

// Background
pm.setColor(muted ? new Color(0.45f, 0.15f, 0.15f, 1f) : new Color(0.23f, 0.23f, 0.34f, 1f));
pm.fill();

pm.setColor(Color.WHITE);

// Speaker body (rectangle)
pm.fillRectangle(18, 46, 20, 36);

// Speaker horn (trapezoid): narrow at x=38, wide at x=70
// top diagonal: (38,46) -> (70,18); bottom diagonal: (38,82) -> (70,110)
for (int y = 18; y <= 110; y++) {
int leftX;
if (y <= 46) {
leftX = Math.round(70 - 32f * (y - 18) / 28f);
} else if (y <= 82) {
leftX = 38;
} else {
leftX = Math.round(38 + 32f * (y - 82) / 28f);
}
if (leftX <= 70) pm.drawLine(leftX, y, 70, y);
}

if (!muted) {
// Sound arcs (two concentric arcs opening to the right)
int cx = 58, cy = 64;
for (int r = 14; r <= 18; r++) {
for (int angle = -55; angle <= 55; angle++) {
double rad = Math.toRadians(angle);
int x = cx + (int) (r * Math.cos(rad));
int y = cy + (int) (r * Math.sin(rad));
if (x >= 0 && x < S && y >= 0 && y < S) pm.drawPixel(x, y);
}
}
for (int r = 26; r <= 30; r++) {
for (int angle = -65; angle <= 65; angle++) {
double rad = Math.toRadians(angle);
int x = cx + (int) (r * Math.cos(rad));
int y = cy + (int) (r * Math.sin(rad));
if (x >= 0 && x < S && y >= 0 && y < S) pm.drawPixel(x, y);
}
}
} else {
// Mute slash line (top-right to bottom-left through speaker area)
pm.setColor(new Color(1f, 0.6f, 0.6f, 1f));
for (int t = -3; t <= 3; t++) {
pm.drawLine(92 + t, 20, 20 + t, 108);
}
}

Texture tex = new Texture(pm);
pm.dispose();
return tex;
}

private Texture solidTexture(Color color) {
Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
pixmap.setColor(color);
Expand Down
Loading