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.Batch;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.math.Vector2;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import io.github.lonamiwebs.klooni.Klooni;
import io.github.lonamiwebs.klooni.serializer.BinSerializable;
// Represents a single cell, with a position, size and color.
// Instances will use the cell texture provided by the currently used skin.
public class Cell implements BinSerializable {
//region Members
// Negative index indicates that the cell is empty
private int colorIndex;
private Vector2 pos;
private float size;
// No need to store the vanish color as a color index since
// this is something quick and shouldn't really affect the UX
private Color vanishColor;
private float vanishSize;
private float vanishElapsed;
private float vanishLifetime;
//endregion
//region Constructor
Cell(float x, float y, float cellSize) {
pos = new Vector2(x, y);
size = cellSize;
colorIndex = -1;
vanishElapsed = Float.POSITIVE_INFINITY;
}
//endregion
//region Package local methods
// Sets the cell to be non-empty and of the specified color index
void set(int ci) {
colorIndex = ci;
}
void draw(SpriteBatch batch) {
// Always query the color to the theme, because it might have changed
draw(Klooni.theme.getCellColor(colorIndex), batch, pos.x, pos.y, size);
// Draw the previous vanishing cell
if (vanishElapsed <= vanishLifetime) {
vanishElapsed += Gdx.graphics.getDeltaTime();
// 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, pos.x + centerOffset, pos.y + centerOffset, vanishSize);
}
}
// Vanish from indicates the point which caused the vanishing to happen,
// in this case, a piece was put. The closer it was put, the faster
// this piece will vanish. This immediately marks the piece as empty.
void vanish(Vector2 vanishFrom) {
if (isEmpty()) // We cannot vanish twice
return;
vanishSize = size;
vanishColor = Klooni.theme.getCellColor(colorIndex).cpy();
vanishLifetime = 1f;
colorIndex = -1;
// The vanish distance is this measure (distance² + size³ * 20% size)
// because it seems good enough. The more the distance, the more the
// delay, but we decrease the delay depending on the cell size too or
// it would be way too high
Vector2 center = new Vector2(pos.x + size * 0.5f, pos.y + 0.5f);
float vanishDist = Vector2.dst2(
vanishFrom.x, vanishFrom.y, center.x, center.y) / (size * size * size * size * 0.2f);
// Negative time = delay, + 0.4*lifetime because elastic interpolation has that delay
vanishElapsed = vanishLifetime * 0.4f - vanishDist;
}
boolean isEmpty() {
return colorIndex < 0;
}
//endregion
//region Static methods
// Default texture (don't call overloaded version to avoid overhead)
public static void draw(final Color color, final Batch batch,
final float x, final float y, final float size) {
batch.setColor(color);
batch.draw(Klooni.theme.cellTexture, x, y, size, size);
}
// Custom texture
public static void draw(final Texture texture, final Color color, final Batch batch,
final float x, final float y, final float size) {
batch.setColor(color);
batch.draw(texture, x, y, size, size);
}
//endregion
//region Serialization
@Override
public void write(DataOutputStream out) throws IOException {
// Only the color index is saved
out.writeInt(colorIndex);
}
@Override
public void read(DataInputStream in) throws IOException {
colorIndex = in.readInt();
}
//endregion
}