0

I am using gradle for building 2D game project. I have set up gradle, but when I add images and txt files to resources folder I get FileNotFoundException: levels/level1_path.txt (No such file or directory).

I CAN NOT use GameEngine.class.getResource("levels/level1_path.txt").getFile() , because there are more than 100 pictures and icon in the game, it would be wrong. I need to find a way such that new File("levels/level1_path.txt") works.

My gradle :

plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

sourceSets {
    main {
        resources {
            srcDirs = ['src/main/resources']
        }
    }
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'

    // slick 2d
    compile files('/Users/faridganbarli/Downloads/slickLIB/lib/jinput.jar')
    compile files('/Users/faridganbarli/Downloads/slickLIB/lib/lwjgl.jar')
    compile files('/Users/faridganbarli/Downloads/slickLIB/lib/lwjgl_util.jar')
    compile files('/Users/faridganbarli/Downloads/slickLIB/lib/slick.jar')

}

My function :

private int[][] initLocations() throws FileNotFoundException{
        File file = new File("levels/level1_path.txt");
        Scanner sc = new Scanner(file);
        int[][] loc=new int[sc.nextInt()][2];
        for(int i=0; i<loc.length; i++){
            loc[i][0]=sc.nextInt();
            loc[i][1]=sc.nextInt();
        }
        return loc;
    }
smac89
  • 39,374
  • 15
  • 132
  • 179
  • Resources are **not** files. Don't use `File` to access resources. The correct API to use is `Class#getResource(String)` and other related methods; I'm not sure I understand your reasoning for not using that API. – Slaw Apr 19 '20 at 22:58

1 Answers1

1

Here is a way to do it:

I would create a Map for each type of resource, and this will be a mapping of the form: folder/with/resource.ext -> uri:///actual/path/to/folder/with/resource.ext where folder is a folder within your resources. In your case, folder could be something like levels.

Now in your code, create these structures and put them somewhere they cannot be modified

public static final Map<String, URI> IMAGE_RESOURCES = Collections.unmodifiableMap(loadAllResources("images"));
public static final Map<String, URI> PATH_RESOURCES = Collections.unmodifiableMap(loadAllResources("levels"));

Now we define a function that will load all resources from a given folder and have them all available for easy access.

private static Map<String, URI> loadAllResources(String folder) {
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    URL folderUrl = loader.getResource(folder);

    final Path root = Paths.get(folderUrl.toURI()).getParent();

    return Files.walk(Paths.get(folderUrl.toURI()))
                .filter(Files::isRegularFile)
                .collect(Collectors.toMap((p)-> root.relativize(p).toString(), Path::toUri));
}

Now assuming the following folder structure in your resources folder:

.
├── images
│   ├── foo.png
│   └── bear.png
└── levels
    └── level1_path.txt

You can load the file level1_path.txt by doing:

new File(PATH_RESOURCES.get("levels/level1_path.txt"));

References:

smac89
  • 39,374
  • 15
  • 132
  • 179