diff --git a/core/src/dev/lonami/klooni/game/BaseScorer.java b/core/src/dev/lonami/klooni/game/BaseScorer.java index 759d600..a5cbefe 100644 --- a/core/src/dev/lonami/klooni/game/BaseScorer.java +++ b/core/src/dev/lonami/klooni/game/BaseScorer.java @@ -35,6 +35,7 @@ public abstract class BaseScorer implements BinSerializable { //region Members int currentScore; + int lastScore; final Label currentScoreLabel; final Label highScoreLabel; @@ -86,8 +87,13 @@ public abstract class BaseScorer implements BinSerializable { //region Public methods + public void undo() { + currentScore = lastScore; + } + // Adds the score a given piece would give public void addPieceScore(final int areaPut) { + lastScore = currentScore; currentScore += areaPut; } diff --git a/core/src/dev/lonami/klooni/game/Board.java b/core/src/dev/lonami/klooni/game/Board.java index 2e6da90..f249e9a 100644 --- a/core/src/dev/lonami/klooni/game/Board.java +++ b/core/src/dev/lonami/klooni/game/Board.java @@ -40,6 +40,7 @@ public class Board implements BinSerializable { public final int cellCount; public float cellSize; private Cell[][] cells; + private Cell[][] lastCells; private final Array effects = new Array(); // Particle effects once they vanish public final Vector2 pos = new Vector2(); @@ -70,9 +71,19 @@ public class Board implements BinSerializable { private void createCells() { cells = new Cell[this.cellCount][this.cellCount]; + lastCells = new Cell[this.cellCount][this.cellCount]; for (int i = 0; i < this.cellCount; ++i) { for (int j = 0; j < this.cellCount; ++j) { cells[i][j] = new Cell(j * cellSize, i * cellSize, cellSize); + lastCells[i][j] = new Cell(cells[i][j]); + } + } + } + + private void CopyToLastCells() { + for(int y = 0; y < cells.length; y += 1) { + for(int x = 0; x < cells[0].length; x += 1) { + lastCells[y][x] = new Cell(cells[y][x]); } } } @@ -110,6 +121,7 @@ public class Board implements BinSerializable { return false; lastPutPiecePos.set(piece.calculateGravityCenter()); + CopyToLastCells(); for (int i = 0; i < piece.cellRows; ++i) for (int j = 0; j < piece.cellCols; ++j) if (piece.filled(i, j)) @@ -122,6 +134,16 @@ public class Board implements BinSerializable { //region Public methods + public void undo() { + if(lastCells != null) { + for(int y = 0; y < cells.length; y += 1) { + for(int x = 0; x < cells[0].length; x += 1) { + cells[y][x] = new Cell(lastCells[y][x]); + } + } + } + } + public void draw(final Batch batch) { batch.setTransformMatrix(batch.getTransformMatrix().translate(pos.x, pos.y, 0)); diff --git a/core/src/dev/lonami/klooni/game/Cell.java b/core/src/dev/lonami/klooni/game/Cell.java index 1767e88..38c0e27 100644 --- a/core/src/dev/lonami/klooni/game/Cell.java +++ b/core/src/dev/lonami/klooni/game/Cell.java @@ -52,6 +52,12 @@ public class Cell implements BinSerializable { colorIndex = -1; } + Cell(Cell c) { + pos = new Vector2(c.pos.x, c.pos.y); + size = c.size; + colorIndex = c.colorIndex; + } + //endregion //region Package local methods diff --git a/core/src/dev/lonami/klooni/game/PieceHolder.java b/core/src/dev/lonami/klooni/game/PieceHolder.java index d7c5701..eb24efb 100644 --- a/core/src/dev/lonami/klooni/game/PieceHolder.java +++ b/core/src/dev/lonami/klooni/game/PieceHolder.java @@ -41,6 +41,7 @@ public class PieceHolder implements BinSerializable { final Rectangle area; private final Piece[] pieces; + private Piece lastPiece = null; private final Sound pieceDropSound; private final Sound invalidPieceDropSound; @@ -51,6 +52,7 @@ public class PieceHolder implements BinSerializable { // Currently held piece index (picked by the user) private int heldPiece; + private int lastHeldPiece; public boolean enabled; // Needed after a piece is dropped, so it can go back @@ -110,6 +112,7 @@ public class PieceHolder implements BinSerializable { // Takes a new set of pieces. Should be called when there are no more piece left private void takeMore() { + lastPiece = null; // NO UNDO! for (int i = 0; i < count; ++i) pieces[i] = Piece.random(); updatePiecesStartLocation(); @@ -155,6 +158,17 @@ public class PieceHolder implements BinSerializable { //region Public methods + public boolean undo() { + if(lastPiece != null) { + pieces[lastHeldPiece] = lastPiece; + lastPiece = null; + return true; + } + else { + return false; + } + } + // Picks the piece below the finger/mouse, returning true if any was picked public boolean pickPiece() { Vector2 mouse = new Vector2( @@ -211,6 +225,8 @@ public class PieceHolder implements BinSerializable { float pitch = 1.104f - pieces[heldPiece].calculateArea() * 0.04f; pieceDropSound.play(1, pitch, 0); } + lastPiece = pieces[heldPiece]; + lastHeldPiece = heldPiece; result = new DropResult(calculateHeldPieceArea(), calculateHeldPieceCenter()); pieces[heldPiece] = null; diff --git a/core/src/dev/lonami/klooni/screens/GameScreen.java b/core/src/dev/lonami/klooni/screens/GameScreen.java index ddc0b8d..8e952a3 100644 --- a/core/src/dev/lonami/klooni/screens/GameScreen.java +++ b/core/src/dev/lonami/klooni/screens/GameScreen.java @@ -25,6 +25,7 @@ import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.math.Vector2; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -111,7 +112,7 @@ class GameScreen implements Screen, InputProcessor, BinSerializable { board = new Board(layout, BOARD_SIZE); holder = new PieceHolder(layout, board, HOLDER_PIECE_COUNT, board.cellSize); - pauseMenu = new PauseMenuStage(layout, game, scorer, gameMode); + pauseMenu = new PauseMenuStage(layout, game, scorer, gameMode, board, holder); bonusParticleHandler = new BonusParticleHandler(game); gameOverSound = Gdx.audio.newSound(Gdx.files.internal("sound/game_over.mp3")); diff --git a/core/src/dev/lonami/klooni/screens/PauseMenuStage.java b/core/src/dev/lonami/klooni/screens/PauseMenuStage.java index 8c8e5e8..b568055 100644 --- a/core/src/dev/lonami/klooni/screens/PauseMenuStage.java +++ b/core/src/dev/lonami/klooni/screens/PauseMenuStage.java @@ -35,7 +35,9 @@ import dev.lonami.klooni.Klooni; import dev.lonami.klooni.actors.Band; import dev.lonami.klooni.actors.SoftButton; import dev.lonami.klooni.game.BaseScorer; +import dev.lonami.klooni.game.Board; import dev.lonami.klooni.game.GameLayout; +import dev.lonami.klooni.game.PieceHolder; // The pause stage is not a whole screen but rather a menu // which can be overlaid on top of another screen @@ -55,12 +57,14 @@ class PauseMenuStage extends Stage { private final SoftButton playButton; private final SoftButton customButton; // Customize & "Shut down" + //endregion + //region Constructor // We need the score to save the maximum score if a new record was beaten - PauseMenuStage(final GameLayout layout, final Klooni game, final BaseScorer scorer, final int gameMode) { + PauseMenuStage(final GameLayout layout, final Klooni game, final BaseScorer scorer, final int gameMode, final Board board, final PieceHolder holder) { this.game = game; this.scorer = scorer; @@ -108,6 +112,30 @@ class PauseMenuStage extends Stage { playButton = new SoftButton(2, "play_texture"); table.add(playButton).space(16); playButton.addListener(playChangeListener); + + // UNDO :)))))) + if(gameMode == 0) // this is kinda bad but meh for now, 0 is normal game, so no undo in the time thingy! + { + SoftButton undoButton = new SoftButton(3, "back_texture"); + undoButton.setPosition( + (Gdx.graphics.getWidth() - undoButton.getWidth())* 0.5f, + Gdx.graphics.getHeight() * 0.25f + ); + addActor(undoButton); + ChangeListener undoChangeListener = new ChangeListener() { + @Override + public void changed(ChangeEvent event, Actor actor) { + boolean undo = holder.undo(); + if(undo) { + scorer.undo(); + board.undo(); + } + hide(); + } + }; + undoButton.addListener(undoChangeListener); + } + } //endregion