Fix score counting and use a custom Scorer class
This commit is contained in:
parent
ec19c31fd6
commit
7888ac23b4
8 changed files with 201 additions and 21 deletions
90
android/assets/font/geosans-light.fnt
Normal file
90
android/assets/font/geosans-light.fnt
Normal 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
|
BIN
android/assets/font/geosans-light.png
Normal file
BIN
android/assets/font/geosans-light.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.2 KiB |
BIN
android/assets/ui/cup.png
Normal file
BIN
android/assets/ui/cup.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4 KiB |
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
73
core/src/io/github/lonamiwebs/klooni/game/Scorer.java
Normal file
73
core/src/io/github/lonamiwebs/klooni/game/Scorer.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue