Add cool vanish effect to cleared strips

This commit is contained in:
Lonami Exo 2017-01-27 12:14:10 +01:00
parent 7888ac23b4
commit 65d3c8d1a0
3 changed files with 92 additions and 25 deletions

View file

@ -13,6 +13,8 @@ public class Board {
public final int cellCount; public final int cellCount;
public float cellSize; public float cellSize;
private final Vector2 lastPutPiecePos; // Used to animate cleared cells vanishing
final Vector2 pos; final Vector2 pos;
public NinePatch cellPatch; public NinePatch cellPatch;
@ -20,18 +22,21 @@ public class Board {
public Board(final GameLayout layout, int cellCount) { public Board(final GameLayout layout, int cellCount) {
this.cellCount = cellCount; this.cellCount = cellCount;
cells = 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();
}
}
cellPatch = new NinePatch( cellPatch = new NinePatch(
new Texture(Gdx.files.internal("ui/cells/basic.png")), 4, 4, 4, 4); new Texture(Gdx.files.internal("ui/cells/basic.png")), 4, 4, 4, 4);
lastPutPiecePos = new Vector2();
pos = new Vector2(); pos = new Vector2();
layout.update(this); layout.update(this);
// Cell size depends on the layout to be updated
cells = 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(
pos.x + j * cellSize, pos.y + i * cellSize, cellSize);
}
}
} }
private boolean inBounds(int x, int y) { private boolean inBounds(int x, int y) {
@ -119,14 +124,14 @@ public class Board {
for (int i = 0; i < cellCount; i++) { for (int i = 0; i < cellCount; i++) {
if (clearedRows[i]) { if (clearedRows[i]) {
for (int j = 0; j < cellCount; j++) { for (int j = 0; j < cellCount; j++) {
cells[i][j].setEmpty(); cells[i][j].vanish(lastPutPiecePos);
} }
} }
} }
for (int j = 0; j < cellCount; j++) { for (int j = 0; j < cellCount; j++) {
if (clearedCols[j]) { if (clearedCols[j]) {
for (int i = 0; i < cellCount; i++) { for (int i = 0; i < cellCount; i++) {
cells[i][j].setEmpty(); cells[i][j].vanish(lastPutPiecePos);
} }
} }
} }
@ -139,6 +144,7 @@ public class Board {
if (!canPutPiece(piece, x, y)) if (!canPutPiece(piece, x, y))
return false; return false;
lastPutPiecePos.set(piece.calculateGravityCenter());
for (int i = 0; i < piece.cellRows; i++) { for (int i = 0; i < piece.cellRows; i++) {
for (int j = 0; j < piece.cellCols; j++) { for (int j = 0; j < piece.cellCols; j++) {
if (piece.filled(i, j)) { if (piece.filled(i, j)) {
@ -153,8 +159,7 @@ public class Board {
public void draw(SpriteBatch batch) { public void draw(SpriteBatch batch) {
for (int i = 0; i < cellCount; i++) { for (int i = 0; i < cellCount; i++) {
for (int j = 0; j < cellCount; j++) { for (int j = 0; j < cellCount; j++) {
cells[i][j].draw(batch, cellPatch, cells[i][j].draw(batch, cellPatch);
pos.x + j * cellSize, pos.y + i * cellSize, cellSize);
} }
} }
} }

View file

@ -1,16 +1,33 @@
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.Color;
import com.badlogic.gdx.graphics.g2d.NinePatch; import com.badlogic.gdx.graphics.g2d.NinePatch;
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.Vector2;
class Cell { class Cell {
private boolean empty; private boolean empty;
private Color color; private Color color;
Cell() { Vector2 pos;
setEmpty(); float size;
private Color vanishColor;
private float vanishSize;
private float vanishElapsed;
private float vanishLifetime;
private static float vanishDelta = 0.1f;
Cell(float x, float y, float cellSize) {
pos = new Vector2(x, y);
size = cellSize;
empty = true;
color = Color.WHITE;
} }
void set(Color c) { void set(Color c) {
@ -18,18 +35,31 @@ class Cell {
color = c; color = c;
} }
void setEmpty() { void draw(SpriteBatch batch, NinePatch patch) {
empty = true; draw(color, batch, patch, pos.x, pos.y, size);
color = Color.WHITE;
} // Draw the previous vanishing cell
if (vanishSize > vanishDelta) {
void draw(SpriteBatch batch, NinePatch patch, float x, float y, float size) { vanishElapsed += Gdx.graphics.getDeltaTime();
draw(color, batch, patch, x, y, size);
// vanishElapsed might be < 0 (delay), so clamp to 0
float progress = Math.min(1f,
Math.max(vanishElapsed, 0f) / vanishLifetime);
vanishSize = Interpolation.elasticIn.apply(size, 0, progress);
float centerOffset = size * 0.5f - vanishSize * 0.5f;
draw(vanishColor, batch, patch, pos.x + centerOffset, pos.y + centerOffset, vanishSize);
if (progress == 1f) {
vanishSize = 0f; // Stop vanishing
}
}
} }
// TODO Use skin atlas
static void draw(Color color, SpriteBatch batch, NinePatch patch, static void draw(Color color, SpriteBatch batch, NinePatch patch,
float x, float y, float size) { float x, float y, float size) {
// TODO Use skin atlas
batch.setColor(color); batch.setColor(color);
patch.draw(batch, x, y, size, size); patch.draw(batch, x, y, size, size);
} }
@ -38,10 +68,26 @@ class Cell {
return empty; return empty;
} }
// TODO Use vanish with a pretty animation instead .setEmpty() // Vanish from indicates the point which caused the vanishing to happen,
// It would be AWESOME if the delay from vanishing (bounce -> big -> small -> gone) // in this case, a piece was put. The closer it was put, the faster
// was delayed by how far this cell is from the cleared piece, I mean cool!! // this piece will vanish.
public void vanish() { void vanish(Vector2 vanishFrom) {
empty = true; empty = true;
vanishSize = size;
vanishColor = color.cpy();
vanishLifetime = 1.5f;
// Square the size when calculating the vanish distance
// because it will be used as delay, and without squaring,
// the delay would be too large
Vector2 center = new Vector2(pos.x + size * 0.5f, pos.y + 0.5f);
float vanishDist = Vector2.dst(
vanishFrom.x, vanishFrom.y, center.x, center.y) / (size * size);
// Negative time indicates delay, + half lifetime because elastic has that delay
vanishElapsed = vanishLifetime * 0.5f - vanishDist;
color = Color.WHITE;
} }
} }

View file

@ -114,6 +114,22 @@ public class Piece {
return area; return area;
} }
Vector2 calculateGravityCenter() {
int filledCount = 0;
Vector2 result = new Vector2();
for (int i = 0; i < cellRows; i++) {
for (int j = 0; j < cellCols; j++) {
if (shape[i][j]) {
filledCount++;
result.add(
pos.x + j * cellSize - cellSize * 0.5f,
pos.y + i * cellSize - cellSize * 0.5f);
}
}
}
return result.scl(1f / filledCount);
}
void draw(SpriteBatch batch, NinePatch patch) { void draw(SpriteBatch batch, NinePatch patch) {
for (int i = 0; i < cellRows; i++) { for (int i = 0; i < cellRows; i++) {
for (int j = 0; j < cellCols; j++) { for (int j = 0; j < cellCols; j++) {