Add binary serializer, make game classes serializable

This commit is contained in:
Lonami Exo 2017-02-09 19:04:03 +01:00
parent 6d2501b022
commit 67d74936d2
9 changed files with 222 additions and 22 deletions

View file

@ -9,8 +9,9 @@ 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.serializer.BinSerializable;
public abstract class BaseScorer { public abstract class BaseScorer implements BinSerializable {
//region Members //region Members

View file

@ -6,11 +6,16 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2; 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.Klooni;
import io.github.lonamiwebs.klooni.serializer.BinSerializable;
// Represents the on screen board, with all the put cells // Represents the on screen board, with all the put cells
// and functions to determine when it is game over given a PieceHolder // and functions to determine when it is game over given a PieceHolder
public class Board { public class Board implements BinSerializable {
//region Members //region Members
@ -185,4 +190,30 @@ public class Board {
} }
//endregion //endregion
//region Serialization
@Override
public void write(DataOutputStream out) throws IOException {
// Cell count, cells in row-major order
out.writeInt(cellCount);
for (int i = 0; i < cellCount; ++i)
for (int j = 0; j < cellCount; ++j)
cells[i][j].write(out);
}
@Override
public void read(DataInputStream in) throws IOException {
// If the saved cell count does not match the current cell count,
// then an IOException is thrown since the data saved was invalid
final int savedCellCount = in.readInt();
if (savedCellCount != cellCount)
throw new IOException("Invalid cellCount saved.");
for (int i = 0; i < cellCount; ++i)
for (int j = 0; j < cellCount; ++j)
cells[i][j].read(in);
}
//endregion
} }

View file

@ -7,11 +7,16 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.math.Vector2; 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.Klooni;
import io.github.lonamiwebs.klooni.serializer.BinSerializable;
// Represents a single cell, with a position, size and color. // Represents a single cell, with a position, size and color.
// Instances will use the cell texture provided by the currently used skin. // Instances will use the cell texture provided by the currently used skin.
public class Cell { public class Cell implements BinSerializable {
//region Members //region Members
@ -108,4 +113,19 @@ public class Cell {
} }
//endregion //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
} }

View file

@ -6,6 +6,10 @@ import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2; 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.Klooni;
// Represents a piece with an arbitrary shape, which // Represents a piece with an arbitrary shape, which
@ -88,22 +92,25 @@ public class Piece {
// Generates a random piece with always the same color for the generated shape // Generates a random piece with always the same color for the generated shape
static Piece random() { static Piece random() {
int color = MathUtils.random(8); // 9 pieces return fromIndex(MathUtils.random(8)); // 9 pieces, [08]
switch (color) { }
private static Piece fromIndex(int colorIndex) {
switch (colorIndex) {
// Squares // Squares
case 0: return new Piece(1, 1, false, color); case 0: return new Piece(1, 1, false, colorIndex);
case 1: return new Piece(2, 2, false, color); case 1: return new Piece(2, 2, false, colorIndex);
case 2: return new Piece(3, 3, false, color); case 2: return new Piece(3, 3, false, colorIndex);
// Lines // Lines
case 3: return new Piece(1, 2, MathUtils.randomBoolean(), color); case 3: return new Piece(1, 2, MathUtils.randomBoolean(), colorIndex);
case 4: return new Piece(1, 3, MathUtils.randomBoolean(), color); case 4: return new Piece(1, 3, MathUtils.randomBoolean(), colorIndex);
case 5: return new Piece(1, 4, MathUtils.randomBoolean(), color); case 5: return new Piece(1, 4, MathUtils.randomBoolean(), colorIndex);
case 6: return new Piece(1, 5, MathUtils.randomBoolean(), color); case 6: return new Piece(1, 5, MathUtils.randomBoolean(), colorIndex);
// L's // L's
case 7: return new Piece(2, MathUtils.random(3), color); case 7: return new Piece(2, MathUtils.random(3), colorIndex);
case 8: return new Piece(3, MathUtils.random(3), color); case 8: return new Piece(3, MathUtils.random(3), colorIndex);
} }
throw new RuntimeException("Random function is broken."); throw new RuntimeException("Random function is broken.");
} }
@ -161,4 +168,16 @@ public class Piece {
} }
//endregion //endregion
//region Serialization
void write(DataOutputStream out) throws IOException {
out.writeInt(colorIndex);
}
static Piece read(DataInputStream in) throws IOException {
return fromIndex(in.readInt());
}
//endregion
} }

View file

@ -9,11 +9,16 @@ import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import io.github.lonamiwebs.klooni.Klooni; import io.github.lonamiwebs.klooni.Klooni;
import io.github.lonamiwebs.klooni.serializer.BinSerializable;
// A holder of pieces that can be drawn on screen. // A holder of pieces that can be drawn on screen.
// Pieces can be picked up from it and dropped on a board. // Pieces can be picked up from it and dropped on a board.
public class PieceHolder { public class PieceHolder implements BinSerializable {
//region Members //region Members
@ -229,4 +234,34 @@ public class PieceHolder {
} }
//endregion //endregion
//region Serialization
@Override
public void write(DataOutputStream out) throws IOException {
// Piece count, false if piece == null, true + piece if piece != null
out.writeInt(count);
for (int i = 0; i < count; ++i) {
if (pieces[i] == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
pieces[i].write(out);
}
}
}
@Override
public void read(DataInputStream in) throws IOException {
// If the saved piece count does not match the current piece count,
// then an IOException is thrown since the data saved was invalid
final int savedPieceCount = in.readInt();
if (savedPieceCount != count)
throw new IOException("Invalid piece count saved.");
for (int i = 0; i < count; i++)
pieces[i] = in.readBoolean() ? Piece.read(in) : null;
}
//endregion
} }

View file

@ -4,16 +4,21 @@ 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 java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import io.github.lonamiwebs.klooni.Klooni; import io.github.lonamiwebs.klooni.Klooni;
import io.github.lonamiwebs.klooni.serializer.BinSerializable;
// 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 extends BaseScorer { public class Scorer extends BaseScorer implements BinSerializable {
//region Members //region Members
private int currentScore, maxScore; private int currentScore, highScore;
// To interpolate between shown score -> real score // To interpolate between shown score -> real score
private float shownScore; private float shownScore;
@ -27,7 +32,7 @@ public class Scorer extends BaseScorer {
super(game, layout, Klooni.getMaxScore()); super(game, layout, Klooni.getMaxScore());
currentScore = 0; currentScore = 0;
maxScore = Klooni.getMaxScore(); highScore = Klooni.getMaxScore();
} }
//endregion //endregion
@ -55,7 +60,7 @@ public class Scorer extends BaseScorer {
@Override @Override
protected boolean isNewRecord() { protected boolean isNewRecord() {
return currentScore > maxScore; return currentScore > highScore;
} }
@Override @Override
@ -73,4 +78,21 @@ public class Scorer extends BaseScorer {
} }
//endregion //endregion
//region Serialization
@Override
public void write(DataOutputStream out) throws IOException {
// currentScore, highScore
out.writeInt(currentScore);
out.writeInt(highScore);
}
@Override
public void read(DataInputStream in) throws IOException {
currentScore = in.readInt();
highScore = in.readInt();
}
//endregion
} }

View file

@ -4,14 +4,19 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.utils.TimeUtils; import com.badlogic.gdx.utils.TimeUtils;
import io.github.lonamiwebs.klooni.Klooni; import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class TimeScorer extends BaseScorer { import io.github.lonamiwebs.klooni.Klooni;
import io.github.lonamiwebs.klooni.serializer.BinSerializable;
public class TimeScorer extends BaseScorer implements BinSerializable {
//region Members //region Members
private long startTime; private long startTime;
private final int highScoreTime; private int highScoreTime;
// 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`
@ -113,4 +118,23 @@ public class TimeScorer extends BaseScorer {
} }
//endregion //endregion
//region Serialization
@Override
public void write(DataOutputStream out) throws IOException {
// startTime, highScoreTime, deadTime
out.writeLong(startTime);
out.writeInt(highScoreTime);
out.writeLong(deadTime);
}
@Override
public void read(DataInputStream in) throws IOException {
startTime = in.readLong();
highScoreTime = in.readInt();
deadTime = in.readLong();
}
//endregion
} }

View file

@ -0,0 +1,10 @@
package io.github.lonamiwebs.klooni.serializer;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public interface BinSerializable {
void write(final DataOutputStream out) throws IOException;
void read(final DataInputStream in) throws IOException;
}

View file

@ -0,0 +1,38 @@
package io.github.lonamiwebs.klooni.serializer;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class BinSerializer {
public static void serialize(final BinSerializable serializable, final OutputStream output)
throws IOException {
DataOutputStream out = new DataOutputStream(output);
try {
serializable.write(out);
} finally {
try {
out.close();
} catch (IOException ignored) { }
}
// todo uhm maybe make the classes serializable? like telethon, kinda, idk, bye.
/*
DataInputStream d = new DataInputStream(new FileInputStream("test.txt"));
DataOutputStream out = new DataOutputStream(new FileOutputStream("test1.txt"));
String count;
d.readFully();
while((count = d.readLine()) != null){
String u = count.toUpperCase();
System.out.println(u);
out.writeBytes(u + " ,");
}
d.close();
out.close();
*/
}
}