Rihpsalis / GhostGame

0 stars 0 forks source link

Resource/image loading #8

Closed armin-reichert closed 1 year ago

armin-reichert commented 1 year ago

Resources should be loaded via URLs or streams that you create with Class.getResource()or Class.getResouceAsStream(). As I already explained in Reddit, consider providing a Utility class e.g. ResourceLoaderthat creates URLs from paths relative to your resource root folder (src/main/resources if following Maven conventions) and that provides methods for loading images, fonts, audio clips etc. accordingly. Then in your code your just can write something like

Image image = ResourceLoader.image("relative/path/inside/src/main/resources/to/image.png")
Rihpsalis commented 1 year ago

how would you write such a ResourceLoader class

armin-reichert commented 1 year ago

With a text editor ;-)

No, it is really simple, something like this:

public class ResourceLoader {
       /* The path under your src/main/resources folder where you store your images... */
      private static final String ROOT = "/";

    /**
     * @param relativePath relative path (without leading slash) starting from resource root directory
     * @return full path to resource including path to resource root directory
     */
    private static String toFullPath(String relativePath) {
        return ROOT + relativePath;
    }

    /**
     * @param relPath relative path (without leading slash) starting from resource root directory
     * @return URL of resource addressed by this path. Never returns <code>null</code>!
     */
    public static URL urlFromRelPath(String relPath) {
        return url(toFullPath(relPath));
    }

    /**
     * @param fullPath full path to resource including path to resource root directory
     * @return URL of resource addressed by this path. Never returns <code>null</code>!
     */
    public static URL url(String fullPath) {
        Objects.requireNonNull(fullPath);
        var url = ResourceLoader.class.getResource(fullPath);
        if (url == null) {
            throw new MissingResourceException("Missing resource, path=" + fullPath, "", fullPath);
        }
        return url;
    }

    /**
     * @param relPath relative path (without leading slash) starting from resource root directory
     * @return image loaded from resource addressed by this path.
     */
    public static Image image(String relPath) {
        var url = urlFromRelPath(relPath);
        return new Image(url.toExternalForm());
    }
}
Rihpsalis commented 1 year ago

Why would I use a ResourceLoader instead of what I´ve been doing?

armin-reichert commented 1 year ago

Wenn deine Anwendung später mal in ein jar-File oder ähnlichem gepackt ist, dann lädt man Ressourcen wie Bilder, Fonts, Sounds etc. nicht mehr vom Filesystem sondern mittels Class.getResource oder Class.getResourceAsStream. Und wenn man alle Methoden, um solche Ressourcen zu laden, in einer Klasse sammelt, dann hat man halt sowas wie oben beschrieben.

Rihpsalis commented 1 year ago

ok aber wenn ich wie bisher meine Texturen auch skalieren will geht das mit water = new Image(new File("main/resources/terrain/floor/Water.png").toString(), terrainSize, terrainSize, false, false); nicht mehr da ich dann new File nicht benutzen kann. Hast du da eine Idee?

armin-reichert commented 1 year ago

Nein, da verstehst Du was falsch.

Das Image erwartet als ersten Parameter ja einen URL (Uniform Resource Locator) und den bekommt Du ja gerade per Class.getResource().

Du verwendest also nicht new Image(new File("path").toString(), ...) sondern

var url = getClass().getResource("/pfad/zum/bild/bildname.png"); // Pfad unterhalb von src/main/resources
var image = new Image(url.toString(), ...);

Das funktioniert sowohl, wenn das Bild vom Fileystem geladen wird, als auch, wenn das Bild mit den Klassen in einem jar-File liegt.

Rihpsalis commented 1 year ago

Ich muss allerdings bei var image = new Image() einen new File erstellen weil ich ansonsten die geladene Textur nicht skalieren kann und dieser benötigt eine URI oder einen pathname. Irgendwelche Ideen das zu beheben (also die Textur anders zu skalieren oder den ResourceLoader URIs "generieren" zu lassen). Das ist mein Fehler for (int i = 0; i < 4; i++) { URL url = getClass().getResource("/player/MovingRight_" + i + ".png"); movingImagesR[i] = new Image(new File(), playerSize, playerSize, false, false); }

     Candidates for new File() are:  
     File(String pathname, int prefixLength) 
     File(String child, File parent)   
     File(String pathname)   
     File(String parent, String child)   
     File(File parent, String child)   
     File(URI uri)
armin-reichert commented 1 year ago

Vergiss einfach File(). Das Image erwartet als ersten Parameter ja kein File oder einen Filenamen, sondern einen URL. Und den liefert doch gerade getClass().getResource().

Rihpsalis commented 1 year ago

aber wie skaliere ich im folgenden mein Image?

armin-reichert commented 1 year ago

Na genau wie vorher, nur dass der erste Parameter von new Image() nicht new File(...).toString() sondern getClass().getResource(...).toString() ist.

Rihpsalis commented 1 year ago

Ich hatte wohl einen knick in der Optik. Jetzt habe ich gesehen wie du meinst. Vielen Dank

armin-reichert commented 1 year ago

Prima. Freut mich.