-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
[anchor=general_java_development]General Java Development[/anchor]
[anchor=how_do_i_load_resources]Q: How do I load images/sounds/textures/configs from the classpath?[/anchor]
Use the getResource() method to return a URL that can be opened later, or getResourceAsStream() to open the resource directly as an InputStream. There are several different objects where this method can be used, and which you should use depends on many subtle aspects of java classloading, but for 99% of cases there are two approaches, depending on whether you want an absolute or relative resource path:
// APPROACH 1: To load from the root of jars in your classpath
Thread.currentThread().getContextClassLoader().getResourceAsStream("images/backgrounds/sky.jpg");
// APPROACH 2: To load resources relative to the package of this class (the class of 'this')
// e.g. if your class is org.stuff.Game, this will look for /org/stuff/config/settings.xml
getClass().getResourceAsStream("config/settings.xml");
Notice that neither path uses a leading “/”, such as “/config/settings.xml”. Using a leading slash in the first example simply won’t work much of the time, while it will cause the second example to behave similarly to the first (searching from the root). Finally, there are environments such as OSGi where neither of these approaches is correct, so the best advice is to use a utility class to hide all this behind, so you can change it out if and when you need to.
[anchor=how_do_i_access_home_directory]Q: How do I access the user’s home directory[/anchor]
On the surface, it’s pretty simple: [icode]System.getProperty(“user.home”)[/icode]. Except it does completely the wrong thing on Windows, so you can fall back on using System.getEnv() and reading the USERPROFILE variable on Windows or HOME on Unix. You don’t usually even have to detect the OS if you just look for those variables and bypass the problematic user.home property altogether.
The real problem is, what are you actually trying to do? If you’re trying to read or save settings, then read on to see just how deep the rabbit hole goes: First off, seriously consider using the Preferences API for application settings – it takes care of all this stuff for you. If that’s not an option for whatever reason, then your problem becomes figuring out the appropriate directory to use. Most users don’t really mind all that much when you drop folders into their home directory, and a lot of applications do so, whether Unix or Windows, but if you really want to be a proper citizen, that’s where things get really hairy.
[*]Windows: The environment variable you’re looking is APPDATA for application prefs, but LOCALAPPDATA for stuff you don’t want synchronized on roaming profiles. Throw a directory under there and it’s good enough for government work … but the frightening whole story can be seen in this SO thread.
[*]Linux and other Unixoids: You think preferences live in $HOME? The freedesktop.org people have different news for you with the XDG Base Directory Spec. It not only splits app data into “config” and “data” dirs ($XDG_CONFIG_HOME and $XDG_DATA_HOME) but adds to the “fun” by adding path search environment variables for each! Short story: use a hidden folder in $HOME, or use the Preferences API.
[*]OSX: TODO – I’m going to need someone to fill this in.
[/li]
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
[anchor=game_development]Game Development[/anchor]
[anchor=how_do_i_sync_framerate]Q: How do run I my game at a constant framerate?[/anchor]
It’s not anything special: after every frame you draw, simply call a method that measures the time between now and the last frame you drew, and pause for however long it takes to make up the difference. How you do this pause can be as simple as a single Thread.sleep or as complex as multiple sleeps and yields, depending on how precise you need to be. Obviously you can only slow down your game this way to reach the desired framerate. If you need constant-rate motion in your game, you will still need to adjust for the actual time each frame is taking, not just the ideal frame rate.
As with any utility, it’s best to use an existing utility class that accounts for things like timer inaccuracy on different platforms and adapt it to your needs. Some implementations of this:
[*] Sync class in LWJGL 2.8.4 and up
Further reading:
[] http://www.java-gaming.org/topics/is-a-busy-wait-thead-yield-a-good-idea/26103/msg/227461/view.html
[] http://www.java-gaming.org/topics/solving-stuttering-with-fixed-timesteps-once-and-for-all/24975/view.html