Skip to content

Instantly share code, notes, and snippets.

@EudyContreras
Last active April 8, 2020 22:50
Show Gist options
  • Save EudyContreras/a3ad63067e7e16ed7cf580eb992b4a60 to your computer and use it in GitHub Desktop.
Save EudyContreras/a3ad63067e7e16ed7cf580eb992b4a60 to your computer and use it in GitHub Desktop.
JavaFX Game Saving and Loading Utility
/*
* JavaFX Game Save and Load utility
*
* The author of this software "Eudy Contreras" grants you ("Licensee")
* a non-exclusive, royalty free, license to use,modify and redistribute this
* software in source and binary code form.
*
* Please be aware that this software is simply part of a personal test
* and may in fact be unstable. The software in its current state is not
* considered a finished product and has plenty of room for improvement and
* changes due to the range of different approaches which can be used to
* achieved the desired result of the software.
*
*/
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.imageio.ImageIO;
import javafx.concurrent.Task;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image;
/**
*
* @author Eudy Contreras
*
* This program saves a game state or settings of a game. The save and stores the data to a predefined destination.
* The program allows the user to save and retrieve the saved data which can than be processed and implemented to the
* current game!
*
*/
public enum SaveAndLoadUtility {
INSTANCE; //To call the save function SaveAndLoadUtility.INSTANCE.createSaveSlot();
private final String DIRECTORY_NAME = "Game Save Data"+ File.separator;
/**
* Directory where the game files are located!
*/
private final String PATH_ROOT = "." + File.separator + DIRECTORY_NAME ;
/**
* Desktop !
*/
@SuppressWarnings("unused")
private final String PATH_ROOT_ALT = System.getProperty("user.home") + "/Desktop" + File.separator + DIRECTORY_NAME;
private final String SAVE_FILE = "gameData.saveSlot";
private final String IMAGE_TYPE = "png";
private final String SAVE_FILE_PATH = PATH_ROOT + SAVE_FILE;
private SaveSlot savedData;
/**
* Can be called in order to create a save game
*/
public void createSaveSlot() {
BufferedImage image = SwingFXUtils.fromFXImage(GameSettings.profilePic, null);
SaveSlot saveData = new SaveSlot(GameSettings.profileName,ImageToByte(image),GameSettings.score,GameSettings.level,GameSettings.gameVolume,GameSettings.resolutionX,GameSettings.resolutionY);
saveGame(saveData);
}
/**
* Method which when called will attempt to save a SaveSlot
* to a specified directory.
* @param saveData
*/
private void saveGame(SaveSlot saveData) {
Task<Void> task = new Task<Void>() {
@Override
public Void call() throws Exception {
File root = new File(PATH_ROOT);
File file = new File(SAVE_FILE_PATH);
file.delete();
logState("Saving file...");
try {
root.mkdirs();
FileOutputStream fileOut = new FileOutputStream(SAVE_FILE_PATH);
BufferedOutputStream bufferedStream = new BufferedOutputStream(fileOut);
ObjectOutputStream outputStream = new ObjectOutputStream(bufferedStream);
outputStream.writeObject(saveData);
outputStream.close();
fileOut.close();
logState("File saved.");
} catch (IOException e) {
logState("Failed to save, I/O exception");
e.printStackTrace();
}
return null;
}
};
Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
}
/**
* Method which when called attempts to retrieve the saved data
* from a specified directory
*/
public void loadGame() {
Task<Void> task = new Task<Void>() {
@Override
public Void call() throws Exception {
File root = new File(PATH_ROOT);
File file = new File(SAVE_FILE_PATH);
if (root.exists() && file.exists()) {
try {
logState("Loading file");
FileInputStream fileIn = new FileInputStream(SAVE_FILE_PATH);
ObjectInputStream inputStream = new ObjectInputStream(fileIn);
savedData = (SaveSlot) inputStream.readObject();
processSavedData(savedData);
inputStream.close();
fileIn.close();
logState("File loaded");
} catch (IOException | ClassNotFoundException e) {
logState("Failed to load! " + e.getLocalizedMessage());
}
} else {
logState("Nothing to load.");
}
return null;
}
};
Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
}
private void processSavedData(SaveSlot savedData){
GameSettings.profilePic = byteToImage(savedData.getProfilePic());
GameSettings.profileName = savedData.getProfileName();
GameSettings.score = savedData.getScore();
GameSettings.level = savedData.getLevel();
GameSettings.gameVolume = savedData.getGameVolume();
GameSettings.resolutionX = savedData.getResolutionX();
GameSettings.resolutionY = savedData.getResolutionY();
}
private String logState(String log){
System.out.println("Game Saver: " + log);
return log;
}
/**
* Method which converts a buffered image to byte array
* @param image: image to be converted
* @return: byte array of the image
* @throws IOException
*/
private final byte[] ImageToByte(BufferedImage image) {
ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
byte[] imageInByte = null;
try {
if (image != null) {
ImageIO.write(image, IMAGE_TYPE, byteOutput);
imageInByte = byteOutput.toByteArray();
byteOutput.flush();
byteOutput.close();
}
} catch (IOException | IllegalArgumentException e) {
e.printStackTrace();
}
try {
return imageInByte;
} finally {
byteOutput.reset();
}
}
/**
* Method which converts a byte array to an Image
* @param data: byte array to be converted.
* @return: image of the byte array
*/
private final Image byteToImage(byte[] data) {
BufferedImage newImage = null;
Image image = null;
try {
InputStream inputStream = new ByteArrayInputStream(data);
newImage = ImageIO.read(inputStream);
inputStream.close();
image = SwingFXUtils.toFXImage(newImage, null);
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
import java.io.Serializable;
public class SaveSlot implements Serializable{
private static final long serialVersionUID = 1L;
private byte[] profilePic;
private int score;
private int level;
private double gameVolume;
private double resolutionX;
private double resolutionY;
private String profileName;
public SaveSlot(String profileName, byte[] profilePic, int score, int level, double gameVolume, double resolutionX, double resolutionY) {
super();
this.profileName = profileName;
this.profilePic = profilePic;
this.score = score;
this.level = level;
this.gameVolume = gameVolume;
this.resolutionX = resolutionX;
this.resolutionY = resolutionY;
}
public SaveSlot(String profileName, int score, int level, double gameVolume, double resolutionX, double resolutionY) {
new SaveSlot(profileName,null,score,level,gameVolume, resolutionX, resolutionY);
}
public int getScore() {return score;}
public int getLevel() {return level;}
public String getProfileName() {return profileName;}
public byte[] getProfilePic() {return profilePic;}
public double getGameVolume() {return gameVolume;}
public double getResolutionX() {return resolutionX;}
public double getResolutionY() {return resolutionY;}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
import javafx.scene.image.Image;
public class GameSettings {
public static String profileName = "player name";
public static Image profilePic = new Image("playerImage.png");
public static int score = 100;
public static int level = 1;
public static double gameVolume = 1;
public static double resolutionX = 1920;
public static double resolutionY = 1080;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment