diff --git a/app/src/main/java/com/example/boidelov3/games/game89/Game89GameActivity.java b/app/src/main/java/com/example/boidelov3/games/game89/Game89GameActivity.java index a18fa31..451c38b 100644 --- a/app/src/main/java/com/example/boidelov3/games/game89/Game89GameActivity.java +++ b/app/src/main/java/com/example/boidelov3/games/game89/Game89GameActivity.java @@ -51,6 +51,9 @@ public class Game89GameActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_game89_game); + + // Garder l'écran allumé pendant la partie + getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); // Get intent data ArrayList playerNames = getIntent().getStringArrayListExtra("PLAYERS"); @@ -155,6 +158,9 @@ public class Game89GameActivity extends AppCompatActivity { challengeTitleTextView.setText(currentChallenge.getTitle()); challengeDescriptionTextView.setText(currentChallenge.getDescription()); + // Alerte sonore : le timer est terminé, un défi arrive + com.example.boidelov3.utils.SoundManager.getInstance(this).playChallenge(); + // Vibrate to alert players try { android.os.Vibrator vibrator = (android.os.Vibrator) getSystemService(android.content.Context.VIBRATOR_SERVICE); @@ -274,7 +280,7 @@ public class Game89GameActivity extends AppCompatActivity { int count = seekBar.getProgress() + 1; // 1-8 players.get(playerIndex).addGorgees(count); Toast.makeText(this, - players.get(playerIndex).getName() + " boit " + count + " gorgée(s)!", + players.get(playerIndex).getName() + " boit " + count + " gorgée" + (count > 1 ? "s" : "") + " !", Toast.LENGTH_SHORT).show(); }); @@ -288,10 +294,12 @@ public class Game89GameActivity extends AppCompatActivity { StringBuilder stats = new StringBuilder(); for (Game89Player player : players) { + int total = player.getTotalGorgees(); stats.append(player.getName()) .append(": ") - .append(player.getTotalGorgees()) - .append(" gorgée(s)\n\n"); + .append(total) + .append(total > 1 ? " gorgées" : " gorgée") + .append("\n\n"); } builder.setMessage(stats.toString()); diff --git a/app/src/main/java/com/example/boidelov3/games/game89/Game89Player.java b/app/src/main/java/com/example/boidelov3/games/game89/Game89Player.java index 324c5f6..c7c58eb 100644 --- a/app/src/main/java/com/example/boidelov3/games/game89/Game89Player.java +++ b/app/src/main/java/com/example/boidelov3/games/game89/Game89Player.java @@ -29,6 +29,6 @@ public class Game89Player { @Override public String toString() { - return name + " (" + totalGorgees + " gorgées)"; + return name + " (" + totalGorgees + (totalGorgees > 1 ? " gorgées)" : " gorgée)"); } } diff --git a/app/src/main/java/com/example/boidelov3/utils/SoundGenerator.java b/app/src/main/java/com/example/boidelov3/utils/SoundGenerator.java index dd56507..a637b08 100644 --- a/app/src/main/java/com/example/boidelov3/utils/SoundGenerator.java +++ b/app/src/main/java/com/example/boidelov3/utils/SoundGenerator.java @@ -115,6 +115,68 @@ public class SoundGenerator { }).start(); } + /** + * Carillon convivial - annonce la fin d'un timer (nouveau défi) + * Notes sinusoïdales do-mi-sol avec décroissance douce, timbre de cloche + */ + public synchronized void playChallenge() { + if (isMuted || toneGenerator == null) return; + new Thread(() -> { + android.media.AudioTrack track = null; + try { + final int sampleRate = 44100; + final double[] frequencies = {523.25, 659.25, 783.99}; // Do5, Mi5, Sol5 + final double noteDuration = 0.45; // durée de résonance d'une note (s) + final double noteSpacing = 0.15; // décalage entre les notes (s) + int totalSamples = (int) ((noteSpacing * 2 + noteDuration) * sampleRate); + + short[] pcm = new short[totalSamples]; + for (int n = 0; n < frequencies.length; n++) { + double freq = frequencies[n]; + int start = (int) (noteSpacing * n * sampleRate); + int length = (int) (noteDuration * sampleRate); + for (int i = 0; i < length && start + i < totalSamples; i++) { + double t = (double) i / sampleRate; + // Attaque rapide + décroissance exponentielle = timbre de cloche + double envelope = Math.min(1.0, t / 0.01) * Math.exp(-t * 5.5); + // Légère harmonique pour enrichir le timbre + double sample = 0.75 * Math.sin(2 * Math.PI * freq * t) + + 0.25 * Math.sin(2 * Math.PI * freq * 2.0 * t); + double value = pcm[start + i] / 32768.0 + sample * envelope * 0.55; + pcm[start + i] = (short) (Math.max(-1.0, Math.min(1.0, value)) * Short.MAX_VALUE); + } + } + + track = new android.media.AudioTrack.Builder() + .setAudioAttributes(new android.media.AudioAttributes.Builder() + .setUsage(android.media.AudioAttributes.USAGE_MEDIA) + .setContentType(android.media.AudioAttributes.CONTENT_TYPE_MUSIC) + .build()) + .setAudioFormat(new android.media.AudioFormat.Builder() + .setEncoding(android.media.AudioFormat.ENCODING_PCM_16BIT) + .setSampleRate(sampleRate) + .setChannelMask(android.media.AudioFormat.CHANNEL_OUT_MONO) + .build()) + .setTransferMode(android.media.AudioTrack.MODE_STREAM) + .setBufferSizeInBytes(sampleRate) + .build(); + track.play(); + track.write(pcm, 0, totalSamples); + Thread.sleep((long) ((noteSpacing * 2 + noteDuration + 0.15) * 1000)); + } catch (Exception e) { + Log.e("SoundGenerator", "Erreur lors de la lecture du carillon", e); + } finally { + if (track != null) { + try { + track.stop(); + } catch (Exception ignored) { + } + track.release(); + } + } + }).start(); + } + /** * Activer/Désactiver le son */ diff --git a/app/src/main/java/com/example/boidelov3/utils/SoundManager.java b/app/src/main/java/com/example/boidelov3/utils/SoundManager.java index 9431fea..92fc0ac 100644 --- a/app/src/main/java/com/example/boidelov3/utils/SoundManager.java +++ b/app/src/main/java/com/example/boidelov3/utils/SoundManager.java @@ -64,6 +64,15 @@ public class SoundManager { soundGenerator.playFin(); } } + /** + * Joue un carillon convivial (fin de timer / nouveau défi) + */ + public void playChallenge() { + if (soundGenerator != null) { + soundGenerator.playChallenge(); + } + } + /** * Active ou désactive le son