Fix score counting and use a custom Scorer class

This commit is contained in:
Lonami Exo 2017-01-27 11:19:53 +01:00
parent ec19c31fd6
commit 7888ac23b4
8 changed files with 201 additions and 21 deletions

View file

@ -0,0 +1,90 @@
info face="GeosansLight" size=64 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=1,1,1,1 spacing=-2,-2
common lineHeight=77 base=58 scaleW=512 scaleH=512 pages=1 packed=0
page id=0 file="geosans-light.png"
chars count=12
char id=10 x=0 y=0 width=0 height=0 xoffset=0 yoffset=0 xadvance=0 page=0 chnl=0
char id=32 x=0 y=0 width=0 height=0 xoffset=-1 yoffset=57 xadvance=16 page=0 chnl=0
char id=48 x=0 y=0 width=36 height=51 xoffset=0 yoffset=9 xadvance=35 page=0 chnl=0
char id=49 x=297 y=0 width=13 height=48 xoffset=10 yoffset=11 xadvance=35 page=0 chnl=0
char id=50 x=94 y=0 width=31 height=49 xoffset=2 yoffset=10 xadvance=35 page=0 chnl=0
char id=51 x=36 y=0 width=29 height=50 xoffset=3 yoffset=10 xadvance=35 page=0 chnl=0
char id=52 x=125 y=0 width=34 height=49 xoffset=1 yoffset=10 xadvance=35 page=0 chnl=0
char id=53 x=159 y=0 width=34 height=49 xoffset=0 yoffset=11 xadvance=35 page=0 chnl=0
char id=54 x=193 y=0 width=34 height=49 xoffset=1 yoffset=11 xadvance=35 page=0 chnl=0
char id=55 x=227 y=0 width=36 height=49 xoffset=0 yoffset=11 xadvance=35 page=0 chnl=0
char id=56 x=65 y=0 width=29 height=50 xoffset=3 yoffset=10 xadvance=35 page=0 chnl=0
char id=57 x=263 y=0 width=34 height=49 xoffset=1 yoffset=11 xadvance=35 page=0 chnl=0
kernings count=73
kerning first=49 second=48 amount=-7
kerning first=48 second=49 amount=-11
kerning first=56 second=52 amount=-2
kerning first=57 second=53 amount=-3
kerning first=55 second=57 amount=-4
kerning first=57 second=50 amount=-2
kerning first=48 second=52 amount=-4
kerning first=51 second=49 amount=-12
kerning first=57 second=56 amount=-3
kerning first=56 second=50 amount=-4
kerning first=54 second=49 amount=-13
kerning first=55 second=51 amount=-6
kerning first=48 second=55 amount=-3
kerning first=54 second=50 amount=-6
kerning first=52 second=51 amount=-4
kerning first=52 second=50 amount=-3
kerning first=51 second=50 amount=-4
kerning first=50 second=50 amount=-2
kerning first=57 second=49 amount=-11
kerning first=54 second=52 amount=-4
kerning first=55 second=50 amount=-6
kerning first=49 second=56 amount=-10
kerning first=57 second=52 amount=-6
kerning first=50 second=54 amount=-3
kerning first=51 second=53 amount=-4
kerning first=49 second=49 amount=-17
kerning first=57 second=51 amount=-2
kerning first=55 second=56 amount=-4
kerning first=50 second=55 amount=-3
kerning first=55 second=48 amount=-3
kerning first=56 second=53 amount=-4
kerning first=53 second=55 amount=-2
kerning first=52 second=57 amount=-4
kerning first=51 second=52 amount=-3
kerning first=50 second=53 amount=-4
kerning first=49 second=55 amount=-9
kerning first=53 second=50 amount=-7
kerning first=55 second=52 amount=-20
kerning first=55 second=49 amount=-9
kerning first=53 second=52 amount=-2
kerning first=54 second=51 amount=-2
kerning first=49 second=54 amount=-8
kerning first=50 second=56 amount=-2
kerning first=53 second=53 amount=-3
kerning first=51 second=51 amount=-4
kerning first=48 second=51 amount=-2
kerning first=51 second=57 amount=-3
kerning first=49 second=52 amount=-11
kerning first=52 second=55 amount=-4
kerning first=50 second=49 amount=-12
kerning first=49 second=57 amount=-8
kerning first=54 second=57 amount=-4
kerning first=56 second=55 amount=-3
kerning first=51 second=55 amount=-4
kerning first=56 second=56 amount=-4
kerning first=56 second=51 amount=-3
kerning first=49 second=50 amount=-11
kerning first=55 second=53 amount=-8
kerning first=49 second=51 amount=-12
kerning first=53 second=49 amount=-10
kerning first=48 second=50 amount=-2
kerning first=52 second=49 amount=-10
kerning first=53 second=57 amount=-3
kerning first=50 second=52 amount=-13
kerning first=53 second=51 amount=-3
kerning first=56 second=49 amount=-12
kerning first=49 second=53 amount=-9
kerning first=55 second=54 amount=-9
kerning first=57 second=55 amount=-3
kerning first=54 second=55 amount=-3
kerning first=56 second=57 amount=-4
kerning first=51 second=56 amount=-1
kerning first=50 second=51 amount=-4

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
android/assets/ui/cup.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

View file

@ -39,6 +39,8 @@ class Cell {
} }
// TODO Use vanish with a pretty animation instead .setEmpty() // TODO Use vanish with a pretty animation instead .setEmpty()
// It would be AWESOME if the delay from vanishing (bounce -> big -> small -> gone)
// was delayed by how far this cell is from the cleared piece, I mean cool!!
public void vanish() { public void vanish() {
empty = true; empty = true;
} }

View file

@ -2,6 +2,7 @@ package io.github.lonamiwebs.klooni.game;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Rectangle;
// Helper class to calculate the size of each element // Helper class to calculate the size of each element
// //
@ -10,7 +11,7 @@ import com.badlogic.gdx.Gdx;
public class GameLayout { public class GameLayout {
// Widths // Widths
private float screenWidth, marginWidth; private float screenWidth, marginWidth, availableWidth;
// Heights // Heights
private float screenHeight, logoHeight, scoreHeight, boardHeight, pieceHolderHeight; private float screenHeight, logoHeight, scoreHeight, boardHeight, pieceHolderHeight;
@ -25,6 +26,7 @@ public class GameLayout {
// Widths // Widths
marginWidth = screenWidth * 0.05f; marginWidth = screenWidth * 0.05f;
availableWidth = screenWidth - marginWidth * 2f;
// Heights // Heights
logoHeight = screenHeight * 0.10f; logoHeight = screenHeight * 0.10f;
@ -34,19 +36,37 @@ public class GameLayout {
} }
// Note that we're now using Y-up coordinates // Note that we're now using Y-up coordinates
void update(Scorer 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.currentScoreLabel.setBounds(
area.x, area.y,
area.width * 0.5f - cupSize * 0.5f, area.height);
scorer.maxScoreLabel.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
float availableWidth = screenWidth - marginWidth * 2f;
float boardSize = Math.min(availableWidth, boardHeight); float boardSize = Math.min(availableWidth, boardHeight);
board.cellSize = boardSize / board.cellCount; board.cellSize = boardSize / board.cellCount;
// Now that we know the board size, we can center the board on the screen // Now that we know the board size, we can center the board on the screen
board.pos.set(screenWidth * 0.5f - boardSize * 0.5f, pieceHolderHeight); board.pos.set(
screenWidth * 0.5f - boardSize * 0.5f, pieceHolderHeight);
} }
void update(PieceHolder holder) { void update(PieceHolder holder) {
float availableWidth = screenWidth - marginWidth * 2f;
holder.area.set( holder.area.set(
marginWidth, 0f, marginWidth, 0f,
availableWidth, pieceHolderHeight); availableWidth, pieceHolderHeight);

View file

@ -87,17 +87,17 @@ public class PieceHolder {
} }
public boolean dropPiece(Board board) { public boolean dropPiece(Board board) {
boolean put = false;
if (heldPiece > -1) { if (heldPiece > -1) {
if (board.putScreenPiece(pieces[heldPiece])) { if (board.putScreenPiece(pieces[heldPiece])) {
pieces[heldPiece] = null; pieces[heldPiece] = null;
put = true;
} }
heldPiece = -1; heldPiece = -1;
if (handFinished()) if (handFinished())
takeMore(); takeMore();
return true;
} }
return false; return put;
} }
public void update(float cellSizeOnBoard) { public void update(float cellSizeOnBoard) {

View file

@ -0,0 +1,73 @@
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.BitmapFont;
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.scenes.scene2d.ui.Label;
import com.badlogic.gdx.utils.Align;
public class Scorer {
private int currentScore;
private float shownScore; // To interpolate between shown score -> real score
private final int boardSize;
final Label currentScoreLabel;
final Label maxScoreLabel;
final Texture cupTexture;
final Rectangle cupArea;
public Scorer(GameLayout layout, int boardSize) {
currentScore = 0;
this.boardSize = boardSize;
cupTexture = new Texture(Gdx.files.internal("ui/cup.png"));
cupArea = new Rectangle();
Label.LabelStyle scoreStyle = new Label.LabelStyle();
scoreStyle.font = new BitmapFont(Gdx.files.internal("font/geosans-light.fnt"));
currentScoreLabel = new Label("0", scoreStyle);
currentScoreLabel.setAlignment(Align.right);
maxScoreLabel = new Label("0", scoreStyle);
layout.update(this);
}
public void addPieceScore(int areaPut) {
currentScore += areaPut;
}
public void addBoardScore(int stripsCleared) {
currentScore += calculateClearScore(stripsCleared);
}
int calculateClearScore(int stripsCleared) {
// 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)
if (stripsCleared < 1) return 0;
if (stripsCleared == 1) return boardSize;
else return boardSize * stripsCleared + calculateClearScore(stripsCleared - 1);
}
public void draw(SpriteBatch batch) {
int roundShown = MathUtils.round(shownScore);
if (roundShown != currentScore) {
shownScore = Interpolation.linear.apply(shownScore, currentScore, 0.1f);
currentScoreLabel.setText(Integer.toString(MathUtils.round(shownScore)));
}
batch.setColor(Color.WHITE);
batch.draw(cupTexture, cupArea.x, cupArea.y, cupArea.width, cupArea.height);
currentScoreLabel.draw(batch, 1f);
maxScoreLabel.draw(batch, 1f);
}
}

View file

@ -13,10 +13,13 @@ 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;
import io.github.lonamiwebs.klooni.game.PieceHolder; import io.github.lonamiwebs.klooni.game.PieceHolder;
import io.github.lonamiwebs.klooni.game.Scorer;
public class GameScreen implements Screen, InputProcessor { public class GameScreen implements Screen, InputProcessor {
private Klooni game; private Klooni game;
private Scorer scorer;
private Board board; private Board board;
private PieceHolder holder; private PieceHolder holder;
@ -35,6 +38,7 @@ public class GameScreen implements Screen, InputProcessor {
layout = new GameLayout(); layout = new GameLayout();
scorer = new Scorer(layout, 10);
board = new Board(layout, 10); board = new Board(layout, 10);
holder = new PieceHolder(layout, 3); holder = new PieceHolder(layout, 3);
@ -44,16 +48,6 @@ public class GameScreen implements Screen, InputProcessor {
} }
} }
int calculateClearScore(int cleared) {
// 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)
if (cleared < 1) return 0;
if (cleared == 1) return board.cellCount;
else return board.cellCount * cleared + calculateClearScore(cleared - 1);
}
boolean isGameOver() { boolean isGameOver() {
for (Piece piece : holder.getAvailablePieces()) { for (Piece piece : holder.getAvailablePieces()) {
if (board.canPutPiece(piece)) { if (board.canPutPiece(piece)) {
@ -76,8 +70,9 @@ public class GameScreen implements Screen, InputProcessor {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin(); batch.begin();
board.draw(batch);
scorer.draw(batch);
board.draw(batch);
holder.update(board.cellSize); holder.update(board.cellSize);
holder.draw(batch, board.cellPatch); holder.draw(batch, board.cellPatch);
@ -137,13 +132,13 @@ public class GameScreen implements Screen, InputProcessor {
public boolean touchUp(int screenX, int screenY, int pointer, int button) { public boolean touchUp(int screenX, int screenY, int pointer, int button) {
int area = holder.calculateHeldPieceArea(); int area = holder.calculateHeldPieceArea();
if (holder.dropPiece(board)) { if (holder.dropPiece(board)) {
int cleared = board.clearComplete(); scorer.addPieceScore(area);
score += area + calculateClearScore(cleared); scorer.addBoardScore(board.clearComplete());
// After the piece was put, check if it's game over
if (isGameOver()) { if (isGameOver()) {
clearColor.set(0.4f, 0.1f, 0.1f, 1f); clearColor.set(0.4f, 0.1f, 0.1f, 1f);
} }
return true; return true;
} else { } else {
return false; return false;