Add an abstract base scorer (reuse code)
This commit is contained in:
parent
47301864eb
commit
bf0fa208f5
9 changed files with 181 additions and 162 deletions
|
@ -91,6 +91,10 @@ public class Klooni extends Game {
|
||||||
return prefs.getInteger("maxScore", 0);
|
return prefs.getInteger("maxScore", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getMaxTimeScore() {
|
||||||
|
return prefs.getInteger("maxTimeScore", 0);
|
||||||
|
}
|
||||||
|
|
||||||
public static void setMaxScore(int score) {
|
public static void setMaxScore(int score) {
|
||||||
prefs.putInteger("maxScore", score).flush();
|
prefs.putInteger("maxScore", score).flush();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,15 +11,15 @@ import com.badlogic.gdx.scenes.scene2d.ui.Label;
|
||||||
import com.badlogic.gdx.utils.Align;
|
import com.badlogic.gdx.utils.Align;
|
||||||
|
|
||||||
import io.github.lonamiwebs.klooni.Klooni;
|
import io.github.lonamiwebs.klooni.Klooni;
|
||||||
|
import io.github.lonamiwebs.klooni.game.BaseScorer;
|
||||||
import io.github.lonamiwebs.klooni.game.GameLayout;
|
import io.github.lonamiwebs.klooni.game.GameLayout;
|
||||||
import io.github.lonamiwebs.klooni.game.Scorer;
|
|
||||||
|
|
||||||
// Horizontal band, used to show the score on the pause menu
|
// Horizontal band, used to show the score on the pause menu
|
||||||
public class Band extends Actor {
|
public class Band extends Actor {
|
||||||
|
|
||||||
//region Members
|
//region Members
|
||||||
|
|
||||||
private final Scorer scorer;
|
private final BaseScorer scorer;
|
||||||
private final Texture bandTexture;
|
private final Texture bandTexture;
|
||||||
|
|
||||||
public final Rectangle scoreBounds;
|
public final Rectangle scoreBounds;
|
||||||
|
@ -32,7 +32,7 @@ public class Band extends Actor {
|
||||||
|
|
||||||
//region Constructor
|
//region Constructor
|
||||||
|
|
||||||
public Band(final Klooni game, final GameLayout layout, final Scorer scorer, final Color bandColor) {
|
public Band(final Klooni game, final GameLayout layout, final BaseScorer scorer, final Color bandColor) {
|
||||||
this.scorer = scorer;
|
this.scorer = scorer;
|
||||||
|
|
||||||
// A 1x1 pixel map will be enough since the band texture will then be expanded
|
// A 1x1 pixel map will be enough since the band texture will then be expanded
|
||||||
|
|
97
core/src/io/github/lonamiwebs/klooni/game/BaseScorer.java
Normal file
97
core/src/io/github/lonamiwebs/klooni/game/BaseScorer.java
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
package io.github.lonamiwebs.klooni.game;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.graphics.Color;
|
||||||
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
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 abstract class BaseScorer {
|
||||||
|
|
||||||
|
//region Members
|
||||||
|
|
||||||
|
final Label leftLabel;
|
||||||
|
final Label highScoreLabel;
|
||||||
|
|
||||||
|
final Texture cupTexture;
|
||||||
|
final Rectangle cupArea;
|
||||||
|
|
||||||
|
private final Color cupColor;
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Constructor
|
||||||
|
|
||||||
|
// The board size is required when calculating the score
|
||||||
|
BaseScorer(final Klooni game, GameLayout layout, int highScore) {
|
||||||
|
cupTexture = new Texture(Gdx.files.internal("ui/cup.png"));
|
||||||
|
cupColor = Klooni.theme.currentScore.cpy();
|
||||||
|
cupArea = new Rectangle();
|
||||||
|
|
||||||
|
Label.LabelStyle labelStyle = new Label.LabelStyle();
|
||||||
|
labelStyle.font = game.skin.getFont("font");
|
||||||
|
|
||||||
|
leftLabel = new Label("0", labelStyle);
|
||||||
|
leftLabel.setColor(Klooni.theme.currentScore);
|
||||||
|
leftLabel.setAlignment(Align.right);
|
||||||
|
|
||||||
|
highScoreLabel = new Label(Integer.toString(highScore), labelStyle);
|
||||||
|
highScoreLabel.setColor(Klooni.theme.highScore);
|
||||||
|
|
||||||
|
layout.update(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Private methods
|
||||||
|
|
||||||
|
protected abstract void addScore(int score);
|
||||||
|
|
||||||
|
// The original game seems to work as follows:
|
||||||
|
// If < 1 were cleared, score = 0
|
||||||
|
// If = 1 was cleared, score = cells cleared
|
||||||
|
// If > 1 were cleared, score = cells cleared + score(cleared - 1)
|
||||||
|
private int calculateClearScore(int stripsCleared, int boardSize) {
|
||||||
|
if (stripsCleared < 1) return 0;
|
||||||
|
if (stripsCleared == 1) return boardSize;
|
||||||
|
else return boardSize * stripsCleared + calculateClearScore(stripsCleared - 1, boardSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Public methods
|
||||||
|
|
||||||
|
// Adds the score a given piece would give
|
||||||
|
public final void addPieceScore(int areaPut) {
|
||||||
|
addScore(areaPut);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds the score given by the board, this is, the count of cleared strips
|
||||||
|
public final void addBoardScore(int stripsCleared, int boardSize) {
|
||||||
|
addScore(calculateClearScore(stripsCleared, boardSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract public boolean isGameOver();
|
||||||
|
|
||||||
|
abstract public int getCurrentScore();
|
||||||
|
|
||||||
|
abstract public void saveScore();
|
||||||
|
|
||||||
|
abstract protected boolean isNewRecord();
|
||||||
|
|
||||||
|
public void draw(SpriteBatch batch) {
|
||||||
|
// If we beat a new record, the cup color will linear interpolate to the high score color
|
||||||
|
cupColor.lerp(isNewRecord() ? Klooni.theme.highScore : Klooni.theme.currentScore, 0.05f);
|
||||||
|
batch.setColor(cupColor);
|
||||||
|
batch.draw(cupTexture, cupArea.x, cupArea.y, cupArea.width, cupArea.height);
|
||||||
|
|
||||||
|
leftLabel.draw(batch, 1f);
|
||||||
|
highScoreLabel.draw(batch, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
}
|
|
@ -56,7 +56,7 @@ public class GameLayout {
|
||||||
// coordinates. Since these objects are not actors and we cannot
|
// coordinates. Since these objects are not actors and we cannot
|
||||||
// add them to a table (and would probably be harder), this approach
|
// add them to a table (and would probably be harder), this approach
|
||||||
// was used. Note that all these are using Y-up coordinates.
|
// was used. Note that all these are using Y-up coordinates.
|
||||||
void update(Scorer scorer) {
|
void update(BaseScorer scorer) {
|
||||||
float cupSize = Math.min(scoreHeight, scorer.cupTexture.getHeight());
|
float cupSize = Math.min(scoreHeight, scorer.cupTexture.getHeight());
|
||||||
final Rectangle area = new Rectangle(
|
final Rectangle area = new Rectangle(
|
||||||
marginWidth, pieceHolderHeight + boardHeight,
|
marginWidth, pieceHolderHeight + boardHeight,
|
||||||
|
@ -66,7 +66,7 @@ public class GameLayout {
|
||||||
area.x + area.width * 0.5f - cupSize * 0.5f, area.y,
|
area.x + area.width * 0.5f - cupSize * 0.5f, area.y,
|
||||||
cupSize, cupSize);
|
cupSize, cupSize);
|
||||||
|
|
||||||
scorer.currentScoreLabel.setBounds(
|
scorer.leftLabel.setBounds(
|
||||||
area.x, area.y,
|
area.x, area.y,
|
||||||
area.width * 0.5f - cupSize * 0.5f, area.height);
|
area.width * 0.5f - cupSize * 0.5f, area.height);
|
||||||
|
|
||||||
|
@ -75,25 +75,6 @@ public class GameLayout {
|
||||||
area.width * 0.5f - cupSize * 0.5f, area.height);
|
area.width * 0.5f - cupSize * 0.5f, area.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(TimeScorer scorer) {
|
|
||||||
float cupSize = Math.min(scoreHeight, scorer.cupTexture.getHeight());
|
|
||||||
final Rectangle area = new Rectangle(
|
|
||||||
marginWidth, pieceHolderHeight + boardHeight,
|
|
||||||
availableWidth, scoreHeight);
|
|
||||||
|
|
||||||
scorer.cupArea.set(
|
|
||||||
area.x + area.width * 0.5f - cupSize * 0.5f, area.y,
|
|
||||||
cupSize, cupSize);
|
|
||||||
|
|
||||||
scorer.timeLeftLabel.setBounds(
|
|
||||||
area.x, area.y,
|
|
||||||
area.width * 0.5f - cupSize * 0.5f, area.height);
|
|
||||||
|
|
||||||
scorer.highTimeLabel.setBounds(
|
|
||||||
area.x + area.width * 0.5f + cupSize * 0.5f, area.y,
|
|
||||||
area.width * 0.5f - cupSize * 0.5f, area.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void update(Board board) {
|
void update(Board board) {
|
||||||
// We can't leave our area, so pick the minimum between available
|
// We can't leave our area, so pick the minimum between available
|
||||||
// height and width to determine an appropriated cell size
|
// height and width to determine an appropriated cell size
|
||||||
|
|
|
@ -1,34 +1,20 @@
|
||||||
package io.github.lonamiwebs.klooni.game;
|
package io.github.lonamiwebs.klooni.game;
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
|
||||||
import com.badlogic.gdx.graphics.Color;
|
|
||||||
import com.badlogic.gdx.graphics.Texture;
|
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
import com.badlogic.gdx.math.Interpolation;
|
import com.badlogic.gdx.math.Interpolation;
|
||||||
import com.badlogic.gdx.math.MathUtils;
|
import com.badlogic.gdx.math.MathUtils;
|
||||||
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;
|
import io.github.lonamiwebs.klooni.Klooni;
|
||||||
|
|
||||||
// Used to keep track of the current and maximum
|
// Used to keep track of the current and maximum
|
||||||
// score, and to also display it on the screen.
|
// score, and to also display it on the screen.
|
||||||
// The maximum score is NOT saved automatically.
|
// The maximum score is NOT saved automatically.
|
||||||
public class Scorer {
|
public class Scorer extends BaseScorer {
|
||||||
|
|
||||||
//region Members
|
//region Members
|
||||||
|
|
||||||
private int currentScore, maxScore;
|
private int currentScore, maxScore;
|
||||||
|
|
||||||
final Label currentScoreLabel;
|
|
||||||
final Label highScoreLabel;
|
|
||||||
|
|
||||||
final Texture cupTexture;
|
|
||||||
final Rectangle cupArea;
|
|
||||||
|
|
||||||
private final Color cupColor;
|
|
||||||
|
|
||||||
// If the currentScore beat the maxScore, then we have a new record
|
// If the currentScore beat the maxScore, then we have a new record
|
||||||
private boolean newRecord;
|
private boolean newRecord;
|
||||||
|
|
||||||
|
@ -41,59 +27,26 @@ public class Scorer {
|
||||||
|
|
||||||
// The board size is required when calculating the score
|
// The board size is required when calculating the score
|
||||||
public Scorer(final Klooni game, GameLayout layout) {
|
public Scorer(final Klooni game, GameLayout layout) {
|
||||||
|
super(game, layout, Klooni.getMaxScore());
|
||||||
|
|
||||||
currentScore = 0;
|
currentScore = 0;
|
||||||
maxScore = Klooni.getMaxScore();
|
maxScore = Klooni.getMaxScore();
|
||||||
|
|
||||||
cupTexture = new Texture(Gdx.files.internal("ui/cup.png"));
|
|
||||||
cupColor = Klooni.theme.currentScore.cpy();
|
|
||||||
cupArea = new Rectangle();
|
|
||||||
|
|
||||||
Label.LabelStyle labelStyle = new Label.LabelStyle();
|
|
||||||
labelStyle.font = game.skin.getFont("font");
|
|
||||||
|
|
||||||
currentScoreLabel = new Label("0", labelStyle);
|
|
||||||
currentScoreLabel.setColor(Klooni.theme.currentScore);
|
|
||||||
currentScoreLabel.setAlignment(Align.right);
|
|
||||||
|
|
||||||
highScoreLabel = new Label(Integer.toString(maxScore), labelStyle);
|
|
||||||
highScoreLabel.setColor(Klooni.theme.highScore);
|
|
||||||
|
|
||||||
layout.update(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
//region Private methods
|
//region Private methods
|
||||||
|
|
||||||
private void addScore(int score) {
|
@Override
|
||||||
|
protected void addScore(int score) {
|
||||||
currentScore += score;
|
currentScore += score;
|
||||||
newRecord = currentScore > maxScore;
|
newRecord = currentScore > maxScore;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The original game seems to work as follows:
|
|
||||||
// If < 1 were cleared, score = 0
|
|
||||||
// If = 1 was cleared, score = cells cleared
|
|
||||||
// If > 1 were cleared, score = cells cleared + score(cleared - 1)
|
|
||||||
private int calculateClearScore(int stripsCleared, int boardSize) {
|
|
||||||
if (stripsCleared < 1) return 0;
|
|
||||||
if (stripsCleared == 1) return boardSize;
|
|
||||||
else return boardSize * stripsCleared + calculateClearScore(stripsCleared - 1, boardSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
//region Public methods
|
//region Public methods
|
||||||
|
|
||||||
// Adds the score a given piece would give
|
|
||||||
public void addPieceScore(int areaPut) {
|
|
||||||
addScore(areaPut);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds the score given by the board, this is, the count of cleared strips
|
|
||||||
public void addBoardScore(int stripsCleared, int boardSize) {
|
|
||||||
addScore(calculateClearScore(stripsCleared, boardSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCurrentScore() {
|
public int getCurrentScore() {
|
||||||
return currentScore;
|
return currentScore;
|
||||||
}
|
}
|
||||||
|
@ -104,20 +57,23 @@ public class Scorer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isNewRecord() {
|
||||||
|
return newRecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGameOver() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void draw(SpriteBatch batch) {
|
public void draw(SpriteBatch batch) {
|
||||||
int roundShown = MathUtils.round(shownScore);
|
int roundShown = MathUtils.round(shownScore);
|
||||||
if (roundShown != currentScore) {
|
if (roundShown != currentScore) {
|
||||||
shownScore = Interpolation.linear.apply(shownScore, currentScore, 0.1f);
|
shownScore = Interpolation.linear.apply(shownScore, currentScore, 0.1f);
|
||||||
currentScoreLabel.setText(Integer.toString(MathUtils.round(shownScore)));
|
leftLabel.setText(Integer.toString(MathUtils.round(shownScore)));
|
||||||
}
|
}
|
||||||
|
super.draw(batch);
|
||||||
// If we beat a new record, the cup color will linear interpolate to the high score color
|
|
||||||
cupColor.lerp(newRecord ? Klooni.theme.highScore : Klooni.theme.currentScore, 0.05f);
|
|
||||||
batch.setColor(cupColor);
|
|
||||||
batch.draw(cupTexture, cupArea.x, cupArea.y, cupArea.width, cupArea.height);
|
|
||||||
|
|
||||||
currentScoreLabel.draw(batch, 1f);
|
|
||||||
highScoreLabel.draw(batch, 1f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
|
@ -1,38 +1,21 @@
|
||||||
package io.github.lonamiwebs.klooni.game;
|
package io.github.lonamiwebs.klooni.game;
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
|
||||||
import com.badlogic.gdx.graphics.Color;
|
|
||||||
import com.badlogic.gdx.graphics.Texture;
|
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
import com.badlogic.gdx.math.MathUtils;
|
import com.badlogic.gdx.math.MathUtils;
|
||||||
import com.badlogic.gdx.math.Rectangle;
|
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Label;
|
|
||||||
import com.badlogic.gdx.utils.Align;
|
|
||||||
import com.badlogic.gdx.utils.TimeUtils;
|
import com.badlogic.gdx.utils.TimeUtils;
|
||||||
|
|
||||||
import io.github.lonamiwebs.klooni.Klooni;
|
import io.github.lonamiwebs.klooni.Klooni;
|
||||||
|
|
||||||
public class TimeScorer {
|
public class TimeScorer extends BaseScorer {
|
||||||
|
|
||||||
//region Members
|
//region Members
|
||||||
|
|
||||||
private final long startTime;
|
private final long startTime;
|
||||||
|
|
||||||
// Maximum time alive, in seconds
|
|
||||||
private int maxTimeScore;
|
|
||||||
|
|
||||||
// Indicates where we would die in time. Score adds to this, so we take
|
// Indicates where we would die in time. Score adds to this, so we take
|
||||||
// longer to die. To get the "score" we simply calculate `deadTime - startTime`
|
// longer to die. To get the "score" we simply calculate `deadTime - startTime`
|
||||||
private long deadTime;
|
private long deadTime;
|
||||||
|
|
||||||
final Label timeLeftLabel;
|
|
||||||
final Label highTimeLabel;
|
|
||||||
|
|
||||||
final Texture cupTexture;
|
|
||||||
final Rectangle cupArea;
|
|
||||||
|
|
||||||
private final Color cupColor;
|
|
||||||
|
|
||||||
private static final long START_TIME = 20 * 1000000000L;
|
private static final long START_TIME = 20 * 1000000000L;
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
@ -41,40 +24,21 @@ public class TimeScorer {
|
||||||
|
|
||||||
// The board size is required when calculating the score
|
// The board size is required when calculating the score
|
||||||
public TimeScorer(final Klooni game, GameLayout layout) {
|
public TimeScorer(final Klooni game, GameLayout layout) {
|
||||||
|
super(game, layout, Klooni.getMaxTimeScore());
|
||||||
|
|
||||||
startTime = TimeUtils.nanoTime();
|
startTime = TimeUtils.nanoTime();
|
||||||
deadTime = startTime + START_TIME;
|
deadTime = startTime + START_TIME;
|
||||||
|
|
||||||
cupTexture = new Texture(Gdx.files.internal("ui/cup.png"));
|
|
||||||
cupColor = Klooni.theme.currentScore.cpy();
|
|
||||||
cupArea = new Rectangle();
|
|
||||||
|
|
||||||
Label.LabelStyle labelStyle = new Label.LabelStyle();
|
|
||||||
labelStyle.font = game.skin.getFont("font");
|
|
||||||
|
|
||||||
timeLeftLabel = new Label("0", labelStyle);
|
|
||||||
timeLeftLabel.setColor(Klooni.theme.currentScore);
|
|
||||||
timeLeftLabel.setAlignment(Align.right);
|
|
||||||
|
|
||||||
highTimeLabel = new Label(Integer.toString(nanosToSeconds(maxTimeScore)), labelStyle);
|
|
||||||
highTimeLabel.setColor(Klooni.theme.highScore);
|
|
||||||
|
|
||||||
layout.update(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
//region Private methods
|
//region Private methods
|
||||||
|
|
||||||
private void addScore(int score) {
|
@Override
|
||||||
|
protected void addScore(int score) {
|
||||||
deadTime += scoreToNanos(score);
|
deadTime += scoreToNanos(score);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int calculateClearScore(int stripsCleared, int boardSize) {
|
|
||||||
if (stripsCleared < 1) return 0;
|
|
||||||
if (stripsCleared == 1) return boardSize;
|
|
||||||
else return boardSize * stripsCleared + calculateClearScore(stripsCleared - 1, boardSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int nanosToSeconds(long nano) {
|
private int nanosToSeconds(long nano) {
|
||||||
return MathUtils.ceil((float)(nano * 1e-09));
|
return MathUtils.ceil((float)(nano * 1e-09));
|
||||||
}
|
}
|
||||||
|
@ -84,6 +48,7 @@ public class TimeScorer {
|
||||||
return (long)((score / 4.0) * 1e+09);
|
return (long)((score / 4.0) * 1e+09);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isGameOver() {
|
public boolean isGameOver() {
|
||||||
return TimeUtils.nanoTime() > deadTime;
|
return TimeUtils.nanoTime() > deadTime;
|
||||||
}
|
}
|
||||||
|
@ -92,27 +57,28 @@ public class TimeScorer {
|
||||||
|
|
||||||
//region Public methods
|
//region Public methods
|
||||||
|
|
||||||
// Adds the score a given piece would give
|
@Override
|
||||||
public void addPieceScore(int areaPut) {
|
public int getCurrentScore() {
|
||||||
addScore(areaPut);
|
return nanosToSeconds(deadTime - startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds the score given by the board, this is, the count of cleared strips
|
@Override
|
||||||
public void addBoardScore(int stripsCleared, int boardSize) {
|
public void saveScore() {
|
||||||
addScore(calculateClearScore(stripsCleared, boardSize));
|
// TODO Save high time score
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isNewRecord() {
|
||||||
|
// TODO Return true if it is a new record
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void draw(SpriteBatch batch) {
|
public void draw(SpriteBatch batch) {
|
||||||
int timeLeft = Math.max(nanosToSeconds(deadTime - TimeUtils.nanoTime()), 0);
|
int timeLeft = Math.max(nanosToSeconds(deadTime - TimeUtils.nanoTime()), 0);
|
||||||
timeLeftLabel.setText(Integer.toString(timeLeft));
|
leftLabel.setText(Integer.toString(timeLeft));
|
||||||
|
|
||||||
// If we beat a new record, the cup color will linear interpolate to the high score color
|
super.draw(batch);
|
||||||
//cupColor.lerp(newRecord ? Klooni.theme.highScore : Klooni.theme.currentScore, 0.05f);
|
|
||||||
batch.setColor(cupColor);
|
|
||||||
batch.draw(cupTexture, cupArea.x, cupArea.y, cupArea.width, cupArea.height);
|
|
||||||
|
|
||||||
timeLeftLabel.draw(batch, 1f);
|
|
||||||
highTimeLabel.draw(batch, 1f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
|
@ -9,6 +9,7 @@ import com.badlogic.gdx.graphics.GL20;
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||||
|
|
||||||
import io.github.lonamiwebs.klooni.Klooni;
|
import io.github.lonamiwebs.klooni.Klooni;
|
||||||
|
import io.github.lonamiwebs.klooni.game.BaseScorer;
|
||||||
import io.github.lonamiwebs.klooni.game.Board;
|
import io.github.lonamiwebs.klooni.game.Board;
|
||||||
import io.github.lonamiwebs.klooni.game.GameLayout;
|
import io.github.lonamiwebs.klooni.game.GameLayout;
|
||||||
import io.github.lonamiwebs.klooni.game.Piece;
|
import io.github.lonamiwebs.klooni.game.Piece;
|
||||||
|
@ -21,8 +22,7 @@ class GameScreen implements Screen, InputProcessor {
|
||||||
|
|
||||||
//region Members
|
//region Members
|
||||||
|
|
||||||
private final Scorer scorer;
|
private final BaseScorer scorerlol;
|
||||||
private final TimeScorer timeScorer;
|
|
||||||
|
|
||||||
private final Board board;
|
private final Board board;
|
||||||
private final PieceHolder holder;
|
private final PieceHolder holder;
|
||||||
|
@ -55,12 +55,20 @@ class GameScreen implements Screen, InputProcessor {
|
||||||
this.gameMode = gameMode;
|
this.gameMode = gameMode;
|
||||||
|
|
||||||
final GameLayout layout = new GameLayout();
|
final GameLayout layout = new GameLayout();
|
||||||
scorer = new Scorer(game, layout);
|
switch (gameMode) {
|
||||||
timeScorer = new TimeScorer(game, layout);
|
case GAME_MODE_SCORE:
|
||||||
|
scorerlol = new Scorer(game, layout);
|
||||||
|
break;
|
||||||
|
case GAME_MODE_TIME:
|
||||||
|
scorerlol = new TimeScorer(game, layout);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Unknown game mode given: "+gameMode);
|
||||||
|
}
|
||||||
|
|
||||||
board = new Board(layout, BOARD_SIZE);
|
board = new Board(layout, BOARD_SIZE);
|
||||||
holder = new PieceHolder(layout, HOLDER_PIECE_COUNT, board.cellSize);
|
holder = new PieceHolder(layout, HOLDER_PIECE_COUNT, board.cellSize);
|
||||||
pauseMenu = new PauseMenuStage(layout, game, scorer);
|
pauseMenu = new PauseMenuStage(layout, game, scorerlol);
|
||||||
|
|
||||||
gameOverSound = Gdx.audio.newSound(Gdx.files.internal("sound/game_over.mp3"));
|
gameOverSound = Gdx.audio.newSound(Gdx.files.internal("sound/game_over.mp3"));
|
||||||
}
|
}
|
||||||
|
@ -78,6 +86,12 @@ class GameScreen implements Screen, InputProcessor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void doGameOver() {
|
||||||
|
pauseMenu.show(true);
|
||||||
|
if (Klooni.soundsEnabled())
|
||||||
|
gameOverSound.play();
|
||||||
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
//region Screen
|
//region Screen
|
||||||
|
@ -95,17 +109,13 @@ class GameScreen implements Screen, InputProcessor {
|
||||||
Klooni.theme.glClearBackground();
|
Klooni.theme.glClearBackground();
|
||||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
// With the time mode, we always need to check whether it's game over or not
|
if (scorerlol.isGameOver() && !pauseMenu.isShown()) {
|
||||||
if (timeScorer.isGameOver() && !pauseMenu.isShown()) {
|
doGameOver();
|
||||||
pauseMenu.show(true);
|
|
||||||
if (Klooni.soundsEnabled())
|
|
||||||
gameOverSound.play();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.begin();
|
batch.begin();
|
||||||
|
|
||||||
//scorer.draw(batch);
|
scorerlol.draw(batch);
|
||||||
timeScorer.draw(batch);
|
|
||||||
board.draw(batch);
|
board.draw(batch);
|
||||||
holder.update();
|
holder.update();
|
||||||
holder.draw(batch);
|
holder.draw(batch);
|
||||||
|
@ -148,16 +158,12 @@ class GameScreen implements Screen, InputProcessor {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (action == PieceHolder.ON_BOARD_DROP) {
|
if (action == PieceHolder.ON_BOARD_DROP) {
|
||||||
//scorer.addPieceScore(area);
|
scorerlol.addPieceScore(area);
|
||||||
//scorer.addBoardScore(board.clearComplete(), board.cellCount);
|
scorerlol.addBoardScore(board.clearComplete(), board.cellCount);
|
||||||
timeScorer.addPieceScore(area);
|
|
||||||
timeScorer.addBoardScore(board.clearComplete(), board.cellCount);
|
|
||||||
|
|
||||||
// After the piece was put, check if it's game over
|
// After the piece was put, check if it's game over
|
||||||
if (isGameOver()) {
|
if (isGameOver()) {
|
||||||
pauseMenu.show(true);
|
doGameOver();
|
||||||
if (Klooni.soundsEnabled())
|
|
||||||
gameOverSound.play();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -66,6 +66,15 @@ public class MainMenuScreen extends InputListener implements Screen {
|
||||||
|
|
||||||
// Stats button (high scores)
|
// Stats button (high scores)
|
||||||
final SoftButton statsButton = new SoftButton(2, "stats_texture");
|
final SoftButton statsButton = new SoftButton(2, "stats_texture");
|
||||||
|
// TODO For testing purposes, open the time mode
|
||||||
|
statsButton.addListener(new ChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void changed(ChangeEvent event, Actor actor) {
|
||||||
|
MainMenuScreen.this.game.setScreen(
|
||||||
|
new GameScreen(MainMenuScreen.this.game, GameScreen.GAME_MODE_TIME));
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
table.add(statsButton).space(16);
|
table.add(statsButton).space(16);
|
||||||
|
|
||||||
// Palette button (buy colors)
|
// Palette button (buy colors)
|
||||||
|
|
|
@ -17,8 +17,8 @@ import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||||
import io.github.lonamiwebs.klooni.Klooni;
|
import io.github.lonamiwebs.klooni.Klooni;
|
||||||
import io.github.lonamiwebs.klooni.actors.Band;
|
import io.github.lonamiwebs.klooni.actors.Band;
|
||||||
import io.github.lonamiwebs.klooni.actors.SoftButton;
|
import io.github.lonamiwebs.klooni.actors.SoftButton;
|
||||||
|
import io.github.lonamiwebs.klooni.game.BaseScorer;
|
||||||
import io.github.lonamiwebs.klooni.game.GameLayout;
|
import io.github.lonamiwebs.klooni.game.GameLayout;
|
||||||
import io.github.lonamiwebs.klooni.game.Scorer;
|
|
||||||
|
|
||||||
// The pause stage is not a whole screen but rather a menu
|
// The pause stage is not a whole screen but rather a menu
|
||||||
// which can be overlaid on top of another screen
|
// which can be overlaid on top of another screen
|
||||||
|
@ -33,14 +33,14 @@ class PauseMenuStage extends Stage {
|
||||||
private final ShapeRenderer shapeRenderer;
|
private final ShapeRenderer shapeRenderer;
|
||||||
|
|
||||||
private final Band band;
|
private final Band band;
|
||||||
private final Scorer scorer;
|
private final BaseScorer scorer;
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
//region Constructor
|
//region Constructor
|
||||||
|
|
||||||
// We need the score to save the maximum score if a new record was beaten
|
// We need the score to save the maximum score if a new record was beaten
|
||||||
PauseMenuStage(final GameLayout layout, final Klooni game, final Scorer scorer) {
|
PauseMenuStage(final GameLayout layout, final Klooni game, final BaseScorer scorer) {
|
||||||
this.scorer = scorer;
|
this.scorer = scorer;
|
||||||
|
|
||||||
shapeRenderer = new ShapeRenderer(20); // 20 vertex seems to be enough for a rectangle
|
shapeRenderer = new ShapeRenderer(20); // 20 vertex seems to be enough for a rectangle
|
||||||
|
|
Loading…
Reference in a new issue