package moc.em.mygdxgame;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
public class Player implements Serializable {
/**
* The "Serializable" interface is a class that lets you "read" or "write"
* the object on to the disk, The TextureRegion is to show a certain area inside a sprite sheet
* Some of the objects which was initialized in this class is not serializable, so we can only save certain data
*
*/
private static final long serialVersionUID = 1L;
private String file;
private Vector2 position;
private static final int column = 4;
private static final int row = 4;
private transient Animation animation;
private transient Texture texture;
private transient TextureRegion[] frame;
private static final String saveFile = "player.dat";
private float stateTime;
private transient TextureRegion currentFrame;
private Rectangle bounds;
public Player(String file, Vector2 position){
this.file = file;
this.position = new Vector2(position);
texture = new Texture(Gdx.files.internal(file));
TextureRegion[][] tr = TextureRegion.split(texture, texture.getWidth()/column, texture.getHeight()/row);
frame = new TextureRegion[column * row];
int index = 0;
for(int i = 0; i < row; i++){
for(int j = 0; j < column; j++){
frame[index++] = tr[i][j]; // did not know you can have the index do that inside an array "index++"
}
}
animation = new Animation(1,frame);
stateTime = 0f;
currentFrame = animation.getKeyFrame(0);
bounds = new Rectangle(position.x, position.y, currentFrame.getRegionWidth(), currentFrame.getRegionHeight());
}
@SuppressWarnings("unused")
private static byte[] serialize(Object obj) throws IOException {//This method converts an object to a byte array
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutputStream o = new ObjectOutputStream(b);
o.writeObject(obj);
o.flush();
return b.toByteArray();
}
public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {//This converts byte array to an object
ByteArrayInputStream b = new ByteArrayInputStream(bytes);
ObjectInputStream o = new ObjectInputStream(b);
return o.readObject();
}
public static void savePlayer(Player player) throws IOException {
FileHandle fh = Gdx.files.local(saveFile); //relative path
OutputStream out = null;
try {
fh.writeBytes(serialize(player), false); //It is a byte array :)
}catch(Exception e){
System.out.println(e.toString());
}finally{
if(out != null) {
try{
out.close();
} catch (Exception ex){}
}
}
System.out.println("Saving Player");
}
public static Player loadPlayer() throws IOException, ClassNotFoundException {
Player player = null;
FileHandle fh = Gdx.files.local("player.dat");
player = (Player) deserialize(fh.readBytes()); // Its an object again :)
return player;
}
public void update(){
bounds.set(position.x, position.y, currentFrame.getRegionWidth(), currentFrame.getRegionHeight());
if(stateTime < 4){
stateTime += Gdx.graphics.getDeltaTime();
} else {
stateTime = 0;
}
if(Gdx.input.isKeyPressed(Keys.W)){
position.y += 1f;
currentFrame = animation.getKeyFrame(12 + stateTime);
} else if(Gdx.input.isKeyPressed(Keys.A)){
position.x -= 1f;
currentFrame = animation.getKeyFrame(4 + stateTime);
} else if(Gdx.input.isKeyPressed(Keys.S)){
position.y -= 1f;
currentFrame = animation.getKeyFrame(0 + stateTime);
} else if(Gdx.input.isKeyPressed(Keys.D)){
position.x += 1f;
currentFrame = animation.getKeyFrame(8 + stateTime);
}
}
public void draw(SpriteBatch sb){
sb.draw(currentFrame, position.x, position.y);
}
public String getPlayerImage(){
return file;
}
public Texture getTexture(){
return texture;
}
public Vector2 getPosition(){
return position;
}
public void changePlayer(String file){
this.file = file;
}
public Animation getAnimation() {
return animation;
}
public void setAnimation(Animation animation) {
this.animation = animation;
}
public TextureRegion[] getFrame() {
return frame;
}
public void setFrame(TextureRegion[] frame) {
this.frame = frame;
}
public TextureRegion getCurrentFrame() {
return currentFrame;
}
public void setCurrentFrame(TextureRegion currentFrame) {
this.currentFrame = currentFrame;
}
public float getStateTime() {
return stateTime;
}
public void setStateTime(float stateTime) {
this.stateTime = stateTime;
}
public String getFile() {
return file;
}
public void setFile(String file) {
this.file = file;
}
public Rectangle getBounds() {
return bounds;
}
public void setBounds(Rectangle bounds) {
this.bounds = bounds;
}
}
So I have three classes which are not serialize. Which are the: TextureRegion, Texture, and Animation class. I am trying to find a way to save the entire player class. I cannot use transient, because There is a render method in another class which always calls the update method. I would get a nullpointer from “bounds.set(position.x, position.y, currentFrame.getRegionWidth(), currentFrame.getRegionHeight());” If I use transient.