I am currently developing a simple 2D game that is like Minecraft in Eclipse Java. One of the features I am currently trying to debug is saving a generated 2D noise map into a source folder separate from the root folder called resources and then using that same file that was saved to generate the map that will be displayed when the game runs. The issue that I am having is that my program does not display the recently generated map that was saved, it will display the previous map (from other test runs).
The different times the program was able to display the recently generated map is when:
- I run the program, close it, hit refresh in Eclipse, then run the program again.
- Find the project file, go into the bin folder, and delete the previous generated map that Java compiled.
- Comment out the code that displays the map, run the program with the code that generates the map, then run the program again with the code that displays the map.
- Open the file that contains the map data in Eclipse, have it update, then run the program.
- Run the program many times until it decides to update.
I can confirm that the program successfully generates the map, and saves it with each run so I do not think there are any bugs in that sense. My assumption is that the program can save the map data to the resources source folder but for some reason is not available during run time? Which is weird because the program looks in the same place that the map data is stored to display to the player. If anyone can point me in the right direction or at least notice if I am doing something wrong it will be greatly appreciated.
Below are screenshots and code:
[Structure of Files][1]
Main construction where objects are called:
public GamePanel() {
this.setPreferredSize(new Dimension(screen_width,screen_height));
this.setBackground(Color.gray);
this.setDoubleBuffered(true);
key_handler = new KeyEvents();
this.addKeyListener(key_handler);
this.setFocusable(true);
player = new Player(this,key_handler);
//generate map and save map data
map_generator = new TileMap(this);
//load saved map data to be displayed
tile_manager = new TileManager(this);
}
Function of the map_generator object that saves map data:
void saveMap(String map) {
Path resource_path = Paths.get("resources","map_files");
String map_path = resource_path.toFile().getAbsolutePath() "\\" map;
try {
OutputStream map_stream = new FileOutputStream(map_path);
for (int r=0; r<map_height; r ) {
String map_row = "";
for (int c=0; c<map_width; c ) {
map_row = map_row map_array[r][c] " ";
}
byte[] bytes = map_row.getBytes();
map_stream.write(bytes);
if (r!=map_height-1)
map_stream.write(10);
}
map_stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Function of the tile_manager object that loads map data to be displayed to player
public void loadMap(String map) {
try {
InputStream map_stream = getClass().getResourceAsStream(map);
BufferedReader map_reader = new BufferedReader
(new InputStreamReader(map_stream));
int col = 0;
int row = 0;
while (col < game_panel.col_size && row < game_panel.row_size) {
String map_line = map_reader.readLine();
while (col < game_panel.col_size) {
String numbers[] = map_line.split(" ");
int num = Integer.parseInt(numbers[col]);
map_file[col][row] = num;
col ;
}
if (col == game_panel.col_size) {
col = 0;
row ;
}
}
map_reader.close();
} catch(IOException e) {
e.printStackTrace();
}
}
CodePudding user response:
I was able to successfully solve my problem, and now there are no issues with my program using the map data it generated and displaying it to the player while running. The solution was to use VGA's tip on using a known source (in my case Windows %APPDATA% folder) instead of having to read and write data into the programs files (specially considering that I would like to make this a jar file to be exported and played by others in the future).
The changes to the code are as follows: Top section of the saveMap function:
String working_directory = System.getenv("AppData") "\\" map;
//Path resource_path = Paths.get("resources","map_files");
//String map_path = resource_path.toFile().getAbsolutePath() "\\" map;
Top section of the loadMap function:
String working_directory = System.getenv("AppData") "\\" map;
try {
//InputStream map_stream = getClass().getResourceAsStream(map);
InputStream map_stream = new FileInputStream(working_directory);
The top line in both functions, System.getenv("AppData"), allows Java to get the path of the AppData folder which is marked as a environment variable in computers running recent versions of the Windows OS. The AppData folder, by default, is hidden and contains three folders; Local, LocalLow, and Roaming. When testing, the map data was saved in Roaming, I believe this is default, but I could be wrong.
While researching this I did find out that this method is fine, but can backfire in unique edge cases where a user is running an older version of the Windows OS/Computer or if they have manually changed the %APPDATA% environment variables in their system. In those cases it is recommended to use Windows Native API calls which will find the folder for you even if its not default. There is a stack overflow post giving details on how you can implement Native API calls through java on the link below: Is there a Java library to access the native Windows API?
Since I am making a game and planning to export it I would love to show how to do this as well, but that will be something to implement later down the road once the program has been fleshed out and polished. Thank you everyone for your help and tips!