Implemented read/write of saved characters, currently a Tester.java file tests the ability to save and read saved characters, and the Application has a rudimentary GUI interface to choose to load a specific save file and see information about that character.

This commit is contained in:
Josh Ashton
2022-11-29 17:50:28 -07:00
parent 67624b18b5
commit 4d5fd7c952
38 changed files with 498 additions and 170 deletions
+58
View File
@@ -1,2 +1,60 @@
# Application
CSIS 1410 - Group Project
CURRENT TODO ITEMS:
**************** CONTENT ****************
- All PHB classes should be included.
**************** GUI ********************
- Finish GUI panels
PANELS:
- Race
Upload custom profile picture button.
- Description (needs positioning)
- Spells & Equipment
- Preview
- Load Character/View character
- Save as PDF / Print
DESCRIPTIONS:
- Class action scene pictures.
- Ability Scores description text.
- Class descriptions.
- Race descriptions.
*************** FILES ******************
NOTE: user.dir = /home/joshuaashton/Development/misc/dndApp/src
user.home = /home/joshuaashton
NOTE: user.dir is changed to exe directory by application launch4j. This creates an exe file from .jar.
see Inno Setup Compiler to package .exe and the JRE into a singular installer.
- Upload custom profile picture.
- Character sheet from selections.
- Load existing characters to edit.
- Save new characters.
- File directory based upon OS used.
- Export to PDF.
- Print
************** FINAL TOUCHES **********
- Generate a random character.
- Character levels.
- Spells.
- Dice roller.
+1 -2
View File
@@ -2,9 +2,8 @@ public class App {
public static void main(String[] args) {
FileManager data = new FileManager();
GUImanager gui = new GUImanager();
GUImanager gui = new GUImanager(data.isReturninguser());
gui.setVisible(true);
}
+13
View File
@@ -13,8 +13,17 @@ public class BasicNavPanel extends JPanel implements AppTheme {
super(new GridLayout(1, 2, 30, 0));
this.backButton = backButton;
if(continueButton == null) {
this.continueButton = null;
} else {
this.continueButton = continueButton;
}
this.continueRequirement = continueRequirement;
createNavPanel();
@@ -56,8 +65,12 @@ public class BasicNavPanel extends JPanel implements AppTheme {
if (continueRequirement == 0) {
if(continueButton != null) {
add(continueButton);
}
} else {
DefaultButton requiredStepsNeeds = new DefaultButton(Integer.toString(continueRequirement) + " Points Left");
+76 -59
View File
@@ -6,97 +6,113 @@ public class CharacterSheet implements Serializable {
private int heightFeet;
private int heightInch;
private int weight;
private String eye;
private String hair;
private String eyeColor;
private String hairColor;
private Race race;
private ClassTemplate chClass;
private String[] spells;
private String[] equipment;
private String alignment;
private String background;
private CharacterStats stats;
/**
* @param name
* @param age
* @param heightFeet
* @param heightInch
* @param weight
* @param eye
* @param hair
/*
* TODO: Need to add the following variables:
*
* - CharacterClass x1 var
* - ChosenSpells xN vars
* - Equipment xN vars
* - Description x3 vars
*
* TOTAL: Minimum 12, + N spells and N equipment
*
*/
public CharacterSheet(String name, int age,
int heightFeet, int heightInch,
int weight, String eye, String hair,
Race race, CharacterStats stats) {
public CharacterSheet(
String name,
int age,
int heightFeet,
int heightInch,
int weight,
String eyeColor,
String hairColor,
Race race,
ClassTemplate chClass,
String alignment,
String background,
CharacterStats stats
) {
this.name = name;
this.age = age;
this.heightFeet = heightFeet;
this.heightInch = heightInch;
this.weight = weight;
this.eye = eye;
this.hair = hair;
this.eyeColor = eyeColor;
this.hairColor = hairColor;
this.race = race;
this.chClass = chClass;
this.alignment = alignment;
this.background = background;
this.stats = stats;
}
/**
* Default constructor
*/
public CharacterSheet() {
this.name = "null";
this.age = 0;
this.heightFeet = 0;
this.heightInch = 0;
this.weight = 0;
this.eye = "null";
this.hair = "null";
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the age
*/
public int getAge() {
return age;
}
/**
* @return the heightFeet
*/
public int getHeightFeet() {
return heightFeet;
}
/**
* @return the heightInch
*/
public int getHeightInch() {
return heightInch;
}
/**
* @return the weigth
*/
public int getWeight() {
return weight;
}
/**
* @return the eye
*/
public String getEye() {
return eye;
public String getEyeColor() {
return eyeColor;
}
/**
* @return the hair
*/
public String getHair() {
return hair;
public String getHairColor() {
return hairColor;
}
public Race getRace() {
return race;
}
public ClassTemplate getCharacterClass() {
return chClass;
}
public CharacterStats getStats() {
@@ -107,10 +123,11 @@ public class CharacterSheet implements Serializable {
@Override
public String toString() {
return "name: " + name + " | age: " + age + " | height: "
+ heightFeet + "\'" + heightInch + "\" | weight: "
+ weight + " | eye: " + eye + " | hair: " + hair
+ " | race: " + race.toString() + " | stats: " + stats.toString();
String output = "Character name: " + name + "\nAge: " + age + "\nHeight: " + heightFeet + "\'" + heightInch + "\"" + "\nWeight: " + weight + "\nEye Color: " + eyeColor + "\nHair Color: " + hairColor + "\nRace: " + race.toString() + "\nClass: " + chClass.toString() + "\nStats: " + stats.toString();
return output;
}
}
+3 -1
View File
@@ -1,4 +1,6 @@
public class CharacterStats {
import java.io.Serializable;
public class CharacterStats implements Serializable {
private Stats[] stats;
+3 -1
View File
@@ -1,4 +1,6 @@
public class Charisma extends Stats {
import java.io.Serializable;
public class Charisma extends Stats implements Serializable {
private int abilityScore;
private int abilityScoreModifier;
+3 -1
View File
@@ -1,4 +1,6 @@
public class Constitution extends Stats {
import java.io.Serializable;
public class Constitution extends Stats implements Serializable {
private int abilityScore;
private int abilityScoreModifier;
-12
View File
@@ -1,12 +0,0 @@
import java.awt.*;
public interface CustomTheme {
public Color background = null;
public Color foreground = null;
Color getBackground();
Color getForeground();
}
+3 -1
View File
@@ -1,4 +1,6 @@
public class Dexterity extends Stats {
import java.io.Serializable;
public class Dexterity extends Stats implements Serializable {
private int abilityScore;
private int abilityScoreModifier;
+20 -10
View File
@@ -1,4 +1,6 @@
public class Elf implements Race {
import java.io.Serializable;
public class Elf implements Race, Serializable {
private final int speed = 30;
private final int maxAge = 750;
private String[] traits;
@@ -14,57 +16,65 @@ public class Elf implements Race {
@Override
public String getRace() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
@Override
public int maxAge() {
// TODO Auto-generated method stub
return maxAge;
}
@Override
public int getSpeed() {
// TODO Auto-generated method stub
return speed;
}
@Override
public String[] getTraits() {
// TODO Auto-generated method stub
return traits;
}
@Override
public String[] getSkills() {
// TODO Auto-generated method stub
return skills;
}
@Override
public String[] getLanguages() {
// TODO Auto-generated method stub
return languages;
}
@Override
public String[] getProficiencies() {
// TODO Auto-generated method stub
return proficiencies;
}
@Override
public int[] getASI() {
// TODO Auto-generated method stub
return new int[]{1, 1};
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
}
+11 -2
View File
@@ -1,4 +1,6 @@
public class Fighter implements ClassTemplate {
import java.io.Serializable;
public class Fighter implements ClassTemplate, Serializable {
private int HP;
@@ -7,7 +9,7 @@ public class Fighter implements ClassTemplate {
// TODO: This should be the type of die.
private int hitDie;
public Fighter(Stats[] stats, int level) {
public Fighter() {
}
@@ -85,4 +87,11 @@ public class Fighter implements ClassTemplate {
return null;
}
@Override
public String toString() {
return this.getClass().getSimpleName();
}
}
+109 -61
View File
@@ -1,63 +1,128 @@
import java.awt.*;
import java.io.*;
import java.util.*;
public class FileManager {
private File[] savedCharacters;
private String filepath;
private boolean returningUser;
private ArrayList<File> saveFiles;
private ArrayList<CharacterSheet> saves;
public FileManager() {
findSavedCharacters();
filepath = System.getProperty("user.dir");
loadFonts();
saveFiles = new ArrayList<>();
setSaveFiles();
loadFont();
}
private void loadFonts() {
public String getOSFilepath() {
return filepath;
}
public boolean isReturningUser() {
return returningUser;
}
public CharacterSheet readSavedCharacter(int index) {
return readCharacter(saveFiles.get(index));
}
public void saveCharacter(CharacterSheet completedCharacter) {
writeCharacter(completedCharacter);
}
public ArrayList<CharacterSheet> getSaves() {
return saves;
}
// TODO: Need to implement.
public void deleteCharacter() {
}
private void loadFont() {
try {
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, new File("SanSalvi.ttf")));
} catch (IOException | FontFormatException e) {
//Handle exception
System.out.println("Error finding font.");
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, new File(filepath + "/.resources/SanSalvi.ttf")));
} catch(IOException | FontFormatException e) {
System.out.println("Filepath of font not found: " + filepath + "/.resources/SanSalvi.ttf does not exist.");
}
}
public boolean isReturninguser() {
private void setSaveFiles() {
if (savedCharacters == null) {
File[] tmp = new File(filepath + "/.savedSheets/").listFiles();
return false;
if(tmp != null) {
for(int i = 0; i < tmp.length; i++) {
saveFiles.add(tmp[i]);
}
return savedCharacters.length > 0;
returningUser = true;
} else {
returningUser = false;
}
public CharacterSheet readCharacter(int index) {
saves = new ArrayList<>();
for(File file : saveFiles) {
saves.add(readCharacter(file));
}
}
private CharacterSheet readCharacter(File file) {
CharacterSheet sheet = null;
System.out.println("filepath: " + file.getPath());
try {
FileInputStream fileIn = new FileInputStream("/dndBuilder/" + savedCharacters[index].getPath() + ".dnd");
FileInputStream fileIn = new FileInputStream(file.getPath());
ObjectInputStream in = new ObjectInputStream(fileIn);
sheet = (CharacterSheet) in.readObject();
in.close();
fileIn.close();
} catch (IOException i) {
} catch (IOException | ClassNotFoundException e) {
i.printStackTrace();
} catch (ClassNotFoundException c) {
System.out.println("Saved characters not found");
c.printStackTrace();
System.out.println("No saved characters were found");
}
@@ -65,51 +130,34 @@ public class FileManager {
}
public void saveCharacter(CharacterSheet completedCharacter) {
private void writeCharacter(CharacterSheet sheet) {
try {
try(
FileOutputStream fileOut =
new FileOutputStream("/dndBuilder/" + completedCharacter.getName().hashCode() + ".dnd");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(completedCharacter);
out.close();
fileOut.close();
FileOutputStream fileOut = new FileOutputStream(filepath + "/.savedSheets/" + sheet.getName() + ".dnd");
} catch (IOException i) {
ObjectOutputStream objOut = new ObjectOutputStream(fileOut);
i.printStackTrace();
) {
System.out.println("Inside saving char method.");
objOut.writeObject(sheet);
setSaveFiles();
System.out.println("Object written to file.");
} catch (IOException e) {
System.out.println("ERROR: ");
e.printStackTrace();
System.out.println("\nERROR: Unable to write character sheet object to \n" + filepath + "/.savedSheets");
}
findSavedCharacters();
}
public void deleteCharacter(int index) {
File[] tmp = new File[savedCharacters.length - 1];
for (int i = 0; i < savedCharacters.length; i++) {
if (i != index) {
tmp[i] = savedCharacters[i];
}
}
savedCharacters = tmp;
findSavedCharacters();
}
private void findSavedCharacters() {
savedCharacters = new File("/dndBuilder").listFiles();
}
}
+81 -11
View File
@@ -1,8 +1,13 @@
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class GUImanager extends JFrame {
private FileManager fileManager;
private ArrayList<CharacterSheet> saves;
private ArrayList<DefaultButton> savesButtons;
private static JPanel[] panels;
private int lastPanel;
private int currentPanel;
@@ -25,24 +30,23 @@ public class GUImanager extends JFrame {
private String[] backgroundDescriptions;
private int[] selectedStats;
public GUImanager(boolean returningUser) {
public GUImanager() {
super("D&D Character Builder");
fileManager = new FileManager();
frameSetup();
setupPanelInfo();
this.panels = new JPanel[]{
new MainMenuPanel(createNewCharacterButton(), createRandomCharacterButton(), createLoadButton()),
new BasicPanel(createNavPanel(), raceOptions, raceDescriptions, "Step 1: Choose Your Race"), // To choose Race.
new BasicPanel(createNavPanel(), classOptions, classDescriptions, "Step 2: Choose Your Class"), // To choose Class.
new ChooseAbilityScoresPanel(createNavPanel(1), statOptions, statDescriptions, selectedStats, "Step 3: Choose Your Ability Scores"),
new DescriptionPanel(createNavPanel(), characteristics, alignmentOptions, alignmentDescriptions, backgroundOptions, backgroundDescriptions, "Step 4: Describe your character")
new DescriptionPanel(createNavPanel(), characteristics, alignmentOptions, alignmentDescriptions, backgroundOptions, backgroundDescriptions, "Step 4: Describe your character"),
new LoadCharacterPanel(createBackPanel(), loadableCharacters()),
new ViewCharacterPanel(createBackPanel(), new CharacterSheet("Josh", 21, 5, 8, 180, "Brown", "Dark Brown", new Elf(), new Fighter(), "Neutral", "Nomad", new CharacterStats(9, 15, 12, 10, 13, 10)))
};
/*
this.currentPanel = 0;
this.lastPanel = currentPanel - 1;
this.nextPanel = currentPanel + 1;*/
if (returningUser) {
if (fileManager.isReturningUser()) {
this.currentPanel = 0;
@@ -52,6 +56,9 @@ public class GUImanager extends JFrame {
}
this.lastPanel = currentPanel - 1;
this.nextPanel = currentPanel + 1;
add(panels[currentPanel]);
}
@@ -62,7 +69,7 @@ public class GUImanager extends JFrame {
setLayout(new BorderLayout());
setPreferredSize(new Dimension(750, 550));
setSize(getPreferredSize());
// setResizable(false);
setResizable(false);
setLocationRelativeTo(null);
try {
@@ -260,6 +267,12 @@ public class GUImanager extends JFrame {
}
private BasicNavPanel createBackPanel() {
return new BasicNavPanel(createBackButton(), null, 0);
}
private DefaultButton createBackButton() {
DefaultButton button = new DefaultButton("Back");
@@ -305,6 +318,19 @@ public class GUImanager extends JFrame {
DefaultButton button = createContinueButton();
button.setText("Create New Character");
button.addActionListener(
e -> {
lastPanel = currentPanel;
currentPanel = 1;
nextPanel = 2;
clearAndReset();
}
);
return button;
}
@@ -361,8 +387,51 @@ public class GUImanager extends JFrame {
e -> {
lastPanel = currentPanel;
currentPanel = 3;
nextPanel = currentPanel + 1;
currentPanel = 5;
clearAndReset();
}
);
return button;
}
private ArrayList<DefaultButton> loadableCharacters() {
System.out.println("Loading characters...");
saves = fileManager.getSaves();
savesButtons = new ArrayList<>();
for(int i = 0; i < saves.size(); i++) {
savesButtons.add(createLoadNCharacterButton(i));
}
for(int i = 0; i < saves.size(); i++) {
System.out.println(saves.get(i).toString());
}
return savesButtons;
}
private DefaultButton createLoadNCharacterButton(int index) {
DefaultButton button = new DefaultButton(saves.get(index).getName());
button.addActionListener(
e -> {
lastPanel = currentPanel;
panels[5] = new ViewCharacterPanel(createBackPanel(), saves.get(index));
currentPanel = 5;
clearAndReset();
}
@@ -392,4 +461,5 @@ public class GUImanager extends JFrame {
}
}
+42
View File
@@ -11,6 +11,23 @@ public class ImageInfoPanel extends InfoPanel implements AppTheme {
private JLabel[][] portraits;
private int lastIndex;
//private JLabel[] savesPortraits;
//private int numSaveCharacters;
// TODO: Need to implement
/*
public ImageInfoPanel(int panelIndex, int numSaveCharacters) {
super(panelIndex);
this.numSaveCharacters = numSaveCharacters;
this.characterName = characterName;
createSavesPortraits();
}
*/
public ImageInfoPanel(String[] categoryHolder, String[] holderDescriptions, Rectangle[] bounds, int panelIndex) {
super(categoryHolder, holderDescriptions, bounds, panelIndex);
@@ -43,6 +60,31 @@ public class ImageInfoPanel extends InfoPanel implements AppTheme {
}
// TODO: Need to create a separate class/refactor ImageInfoPanel to be multi-purpose.
/*
private void createSavesPortraits() {
File imagesDir;
imagesDir = new File("Img/.savesPortraits").listFiles();
savesPortraits = new JLabel[imagesDir.length);
int index = 0;
for(File file : imagesDir) {
savesPortraits[index] = image(file);
savesPortraits[index].setOpaque(true);
savesPortraits[index].setBackground(lightBrown);
savesPortraits[index].setBounds(bounds[3]);
index++;
}
}
*/
private void createPortraits() {
String category = "";
+3 -1
View File
@@ -1,4 +1,6 @@
public class Intelligence extends Stats {
import java.io.Serializable;
public class Intelligence extends Stats implements Serializable {
private int abilityScore;
private int abilityScoreModifier;
+63 -1
View File
@@ -1,2 +1,64 @@
public class LoadCharacterPanel {
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class LoadCharacterPanel extends JPanel implements AppTheme {
private ArrayList<DefaultButton> savedCharacters;
public LoadCharacterPanel(JPanel nav, ArrayList<DefaultButton> savedCharacters) {
super();
panelSetup();
this.savedCharacters = savedCharacters;
createMasterPanel();
add(nav, BorderLayout.SOUTH);
}
private void panelSetup() {
setBackground(lightBrown);
setLayout(new BorderLayout(0, 0));
}
private void createMasterPanel() {
JLabel title = new JLabel("Load a Character");
title.setHorizontalAlignment(SwingConstants.CENTER);
title.setFont(headerFont);
title.setForeground(darkestBrown);
JPanel panel = new JPanel();
panel.setOpaque(false);
panel.setLayout(null);
//panel.add(buttonPanel());
// TODO: Need to implement.
//panel.add(portraitPanel());
add(buttonPanel(), BorderLayout.NORTH);
}
private JPanel buttonPanel() {
JPanel panel = new JPanel(new GridLayout(savedCharacters.size(), 1, 0, 0));
panel.setOpaque(false);
panel.setBackground(lightBrown);
for(int i = 0; i < savedCharacters.size(); i++) {
panel.add(savedCharacters.get(i));
}
return panel;
}
}
-2
View File
@@ -1,2 +0,0 @@
public class PreviewCharacterSheet {
}
+3 -1
View File
@@ -1,4 +1,6 @@
public class Strength extends Stats {
import java.io.Serializable;
public class Strength extends Stats implements Serializable {
private int abilityScore;
private int abilityScoreModifier;
+3 -1
View File
@@ -1,4 +1,6 @@
public class Wisdom extends Stats {
import java.io.Serializable;
public class Wisdom extends Stats implements Serializable {
private int abilityScore;
private int abilityScoreModifier;
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.