diff --git a/android/assets/sound/game_over.mp3 b/android/assets/sound/game_over.mp3 new file mode 100644 index 0000000..2c9d86d Binary files /dev/null and b/android/assets/sound/game_over.mp3 differ diff --git a/android/assets/sound/invalid_drop.mp3 b/android/assets/sound/invalid_drop.mp3 new file mode 100644 index 0000000..b7d84ad Binary files /dev/null and b/android/assets/sound/invalid_drop.mp3 differ diff --git a/android/assets/sound/piece_drop.mp3 b/android/assets/sound/piece_drop.mp3 new file mode 100644 index 0000000..55d3864 Binary files /dev/null and b/android/assets/sound/piece_drop.mp3 differ diff --git a/android/assets/sound/strip_clear.mp3 b/android/assets/sound/strip_clear.mp3 new file mode 100644 index 0000000..fe7b137 Binary files /dev/null and b/android/assets/sound/strip_clear.mp3 differ diff --git a/android/assets/sound/take_pieces.mp3 b/android/assets/sound/take_pieces.mp3 new file mode 100644 index 0000000..966d06c Binary files /dev/null and b/android/assets/sound/take_pieces.mp3 differ diff --git a/core/src/io/github/lonamiwebs/klooni/Klooni.java b/core/src/io/github/lonamiwebs/klooni/Klooni.java index 07667a2..9b36467 100644 --- a/core/src/io/github/lonamiwebs/klooni/Klooni.java +++ b/core/src/io/github/lonamiwebs/klooni/Klooni.java @@ -2,6 +2,7 @@ package io.github.lonamiwebs.klooni; import com.badlogic.gdx.Game; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Preferences; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.NinePatch; import com.badlogic.gdx.scenes.scene2d.ui.Skin; @@ -14,6 +15,8 @@ public class Klooni extends Game { @Override public void create() { + prefs = Gdx.app.getPreferences("io.github.lonamiwebs.klooni.game"); + // TODO Better way to have this skin somewhere // Gotta create that darn .jsonā€¦! skin = new Skin(Gdx.files.internal("skin/uiskin.json")); @@ -46,4 +49,22 @@ public class Klooni extends Game { super.dispose(); skin.dispose(); } + + //region Settings + + private static Preferences prefs; + + public static int getMaxScore() { + return prefs.getInteger("maxScore", 0); + } + + public static void setMaxScore(int score) { + prefs.putInteger("maxScore", score).flush(); + } + + public static boolean soundsEnabled() { + return !prefs.getBoolean("muteSound", false); + } + + //endregion } diff --git a/core/src/io/github/lonamiwebs/klooni/game/Board.java b/core/src/io/github/lonamiwebs/klooni/game/Board.java index d2d728c..96a1b2a 100644 --- a/core/src/io/github/lonamiwebs/klooni/game/Board.java +++ b/core/src/io/github/lonamiwebs/klooni/game/Board.java @@ -1,12 +1,15 @@ package io.github.lonamiwebs.klooni.game; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.NinePatch; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; +import io.github.lonamiwebs.klooni.Klooni; + public class Board { Cell[][] cells; @@ -18,6 +21,7 @@ public class Board { final Vector2 pos; public NinePatch cellPatch; + private final Sound stripClearSound; public Board(final GameLayout layout, int cellCount) { this.cellCount = cellCount; @@ -25,6 +29,8 @@ public class Board { cellPatch = new NinePatch( new Texture(Gdx.files.internal("ui/cells/basic.png")), 4, 4, 4, 4); + stripClearSound = Gdx.audio.newSound(Gdx.files.internal("sound/strip_clear.mp3")); + lastPutPiecePos = new Vector2(); pos = new Vector2(); layout.update(this); @@ -120,6 +126,8 @@ public class Board { clearCount++; } if (clearCount > 0) { + float pan = 0; + // Do clear those rows and columns for (int i = 0; i < cellCount; i++) { if (clearedRows[i]) { @@ -130,11 +138,19 @@ public class Board { } for (int j = 0; j < cellCount; j++) { if (clearedCols[j]) { + pan += 2f * (j - cellCount / 2) / (float)cellCount; for (int i = 0; i < cellCount; i++) { cells[i][j].vanish(lastPutPiecePos); } } } + + if (Klooni.soundsEnabled()) { + long id = stripClearSound.play(); + pan = MathUtils.clamp(pan, -1, 1); + stripClearSound.setPitch(id, MathUtils.random(0.8f, 1.2f)); + stripClearSound.setPan(id, pan, MathUtils.random(0.7f, 1f)); + } } return clearCount; diff --git a/core/src/io/github/lonamiwebs/klooni/game/PieceHolder.java b/core/src/io/github/lonamiwebs/klooni/game/PieceHolder.java index 8121591..144d95b 100644 --- a/core/src/io/github/lonamiwebs/klooni/game/PieceHolder.java +++ b/core/src/io/github/lonamiwebs/klooni/game/PieceHolder.java @@ -1,18 +1,26 @@ package io.github.lonamiwebs.klooni.game; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.graphics.g2d.NinePatch; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.Interpolation; +import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; +import io.github.lonamiwebs.klooni.Klooni; + public class PieceHolder { private final Piece[] pieces; private final Rectangle[] originalPositions; // Needed after a piece is dropped + private final Sound pieceDropSound; + private final Sound invalidPieceDropSound; + private final Sound takePiecesSound; + private final int count; private int heldPiece; @@ -31,6 +39,10 @@ public class PieceHolder { pieces = new Piece[count]; originalPositions = new Rectangle[count]; + pieceDropSound = Gdx.audio.newSound(Gdx.files.internal("sound/piece_drop.mp3")); + invalidPieceDropSound = Gdx.audio.newSound(Gdx.files.internal("sound/invalid_drop.mp3")); + takePiecesSound = Gdx.audio.newSound(Gdx.files.internal("sound/take_pieces.mp3")); + heldPiece = -1; this.pickedCellSize = pickedCellSize; @@ -64,6 +76,13 @@ public class PieceHolder { originalPositions[i] = new Rectangle( pieces[i].pos.x, pieces[i].pos.y, pieces[i].cellSize, pieces[i].cellSize); + + // Now that we have the original positions, reset the size so it animates and grows + pieces[i].cellSize = 0f; + } + if (Klooni.soundsEnabled()) { + // Random pitch so it's not always the same sound + takePiecesSound.setPitch(takePiecesSound.play(), MathUtils.random(0.8f, 1.2f)); } } @@ -114,8 +133,18 @@ public class PieceHolder { public int dropPiece(Board board) { if (heldPiece > -1) { boolean put = board.putScreenPiece(pieces[heldPiece]); - if (put) + if (put) { + if (Klooni.soundsEnabled()) { + // The larger the piece size, the smaller the pitch + // Considering 10 cells to be the largest, 1.1 highest pitch, 0.7 lowest + float pitch = 1.104f - pieces[heldPiece].calculateArea() * 0.04f; + pieceDropSound.setPitch(pieceDropSound.play(), pitch); + } pieces[heldPiece] = null; + } else { + if (Klooni.soundsEnabled()) + invalidPieceDropSound.play(); + } heldPiece = -1; if (handFinished()) diff --git a/core/src/io/github/lonamiwebs/klooni/game/Scorer.java b/core/src/io/github/lonamiwebs/klooni/game/Scorer.java index 4c7e3b5..d6e8e78 100644 --- a/core/src/io/github/lonamiwebs/klooni/game/Scorer.java +++ b/core/src/io/github/lonamiwebs/klooni/game/Scorer.java @@ -1,7 +1,6 @@ package io.github.lonamiwebs.klooni.game; import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.Preferences; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; @@ -12,9 +11,10 @@ import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.utils.Align; +import io.github.lonamiwebs.klooni.Klooni; + public class Scorer { - private final Preferences prefs; private int currentScore, maxScore; private boolean newRecord; @@ -28,10 +28,8 @@ public class Scorer { final Rectangle cupArea; public Scorer(GameLayout layout, int boardSize) { - prefs = Gdx.app.getPreferences("io.github.lonamiwebs.klooni.game"); - currentScore = 0; - maxScore = prefs.getInteger("maxScore", 0); + maxScore = Klooni.getMaxScore(); this.boardSize = boardSize; cupTexture = new Texture(Gdx.files.internal("ui/cup.png")); @@ -69,8 +67,7 @@ public class Scorer { public void saveScore() { if (newRecord) { - prefs.putInteger("maxScore", currentScore); - prefs.flush(); + Klooni.setMaxScore(currentScore); } } diff --git a/core/src/io/github/lonamiwebs/klooni/screens/GameScreen.java b/core/src/io/github/lonamiwebs/klooni/screens/GameScreen.java index f30b651..298d80a 100644 --- a/core/src/io/github/lonamiwebs/klooni/screens/GameScreen.java +++ b/core/src/io/github/lonamiwebs/klooni/screens/GameScreen.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.InputProcessor; import com.badlogic.gdx.Screen; +import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.g2d.SpriteBatch; @@ -21,6 +22,7 @@ public class GameScreen implements Screen, InputProcessor { private PieceHolder holder; private final GameLayout layout; + private final Sound gameOverSound; private SpriteBatch batch; @@ -35,6 +37,8 @@ public class GameScreen implements Screen, InputProcessor { board = new Board(layout, 10); holder = new PieceHolder(layout, 3, board.cellSize); pauseMenu = new PauseMenuStage(layout, game, scorer); + + gameOverSound = Gdx.audio.newSound(Gdx.files.internal("sound/game_over.mp3")); } private boolean isGameOver() { @@ -139,6 +143,8 @@ public class GameScreen implements Screen, InputProcessor { // After the piece was put, check if it's game over if (isGameOver()) { pauseMenu.show(true); + if (Klooni.soundsEnabled()) + gameOverSound.play(); } } return true;