So I want to develop a small game engine. This has the main engine classes like a Vector and Actor for the user to use. Since I only need the engine once, I want to make the games use the same engine, and to avoid having all games in the same jar, I intend to have them in separate folders, one with the engine, and then folders for each game. The engine should then be able to load the eg. Player class from the other folder and utilize it.
I thought one solution could be compiling the game folder at runtime. But then the problem would be that the files depend on each other and on compiled classes already loaded in the JVM. For this approach:
So as an example, we have three classes: An Actor from the engine, a Player extending the engines actor class written by the user, and a third class, the item, written by the user, spawned in Player, but again needs the Player to be compiled, meaning they can't be compiled one after the other.
To my understanding, the Actor will already be compiled in the JVM when we run the program. Now we know a folder with all the classes to compile, where the Player depends on the compiled class in the JVM and the uncompiled class in the folder, which depends on the Player.
Now I want to compile the Player class, whereby we must also compile the Item, and then instantiate the Player so we can move around and spawn items.
Here a basic example of what I mean:
// already compiled in eg. executing jar file
class MainStuff
{
public static void main(String args[])
{
String FolderOfUncompiledClasses = "Some/folder/to/src/";
Class<?>[] CompiledClasses = CompileFolderContents(FolderOfUncompiledClasses);
// iterating through compiled classes
for (Class<?> C : CompiledClasses)
{
// if we have an Actor class, we create a new instance
if (C.isAssignableFrom(Actor.class))
{
try
{
C.getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException | SecurityException e)
{
e.printStackTrace();
}
}
}
}
// should compile all the files and returns the classes of the compiled java files
private static Class<?>[] CompileFolderContents(String Folder)
{
File[] JavaFiles = new File(Folder).listFiles();
Class<?>[] CompiledClasses = new Class<?>[JavaFiles.length];
for (int i = 0; i < JavaFiles.length; i++)
{
Class<?> CompiledClass = DoCompilationStuff(JavaFiles[i]);
CompiledClasses[i] = CompiledClass;
}
return CompiledClasses;
}
// this should effectively compile the class which it can both use non compiled
// java files in the folder and already compiled classes
private static Class<?> DoCompilationStuff(File ToCompile)
{
return null;
}
}
// already compiled in eg. executing jar file
class Actor
{
int X, Y;
}
In a folder somewhere on the drive:
// not compiled
class Player extends Actor
{
public Player()
{
// uses other non compiled class
new Item();
}
}
// not compiled
class Item
{
// Also uses Actor so we can't compile them in series
public Item(Player P)
{
}
}
I've tried using the javac command but I can't get it to work with an entire folder structure somehow.
I hope I explained it in a logical way and if this approach doesn't make sense. This was just an idea, if you have a better approach I would be very happy to hear it.
Thank you very much!
If you really have to use javac
keep the classes in the same package and directory. This will simplify the build process, instead of having to use -cp
argument to specify the class-path existing across multiple different directories.
I'd recommend that instead of compiling manually you should setup a project using a build system e.g. Gradle. If you look at Building Java Applications Gradle docs it should take around 10 minutes and you should have everything you need: build, tests and packaging.