I’m a long time Java (amongst other languages) developer who has mostly dealt in backend webservices and want to develop a game as a hobby project. After looking at countless frameworks and tools I settled on Jmonkey for various reasons (using Java which I’m comfortable with and running both the SDK and the game on Linux, which is what I use - not to mention some of the most comprehensible and digestible tutorial material around!).
I’ve gone through the tutorials and am starting to put the pieces together to build a simple game level but I’ve run into some issues when trying to define my application logic. Generally, when I do Java, I think in terms of interfaces and class hierarchies to build up my logic. However, I notice that it’s easiest to work in what amounts to the global application scope - to have access to the scene graph, the physics space and so on. I end up passing the rootnode or the physics space around quite a bit or finding myself with an ever-growing Main class. So my question is this: how do you guys structure your stuff?
Here’s an example, and some of the solutions I’ve thought of so far - but none of them make me very happy:
I want to define “shot” objects which the player spawns by clicking the mouse. There should be multiple types of shots, which differ based on a few factors - range, rate of fire, damage, size (for collision detection) and material. Naturally I defined an abstract Shot class and then for testing created a child class to use. The class has a RigidBodyControl field, a Geometry field, a Material and a bunch of other fields specific to my application. To define the range I basically gave it a TTL and in the update loop I iterate through the shots (stored in a CopyOnWriteArrayList, held in the Main class), check if any shots are passed their TTL and destroy them if so. If not, they get a counter incremented (which is used against the TTL check). Basically the shots can last for 120 or however many passes of the update loop before they are removed from physics space and detached from my shotNode (in turn part of the rootNode), as well as cut from the array list. They should be marked for GC at this point - those should have been the only refs to the objects.
So this was working OK - I realize it’s probably not the most efficient or elegant solution but it worked and didn’t cause any noticeable CPU chugging (the TTL is aggressive enough that even if the player spams shots the old ones get GC’d fast enough to keep the overall number of them low).
Then I hit the wall with collision. I want to use the physics space to detect the collisions of shots so I started implementing a PhysicsCollisionListener. It detects collisions of shots with stuff like the walls and other obstacles great. The problem I’ve got with this is while I can get a shot’s RigidBodyControl from the listener, I can’t get my Shot object back. It makes sense of course - but I’m not sure how people deal with this.
Here are some idea’s I’ve considered:
Extend the RigidBodyControl class altogether and make that new extended class my Shot class. Basically store all my shot-specific fields and methods in there, and keep all the old stuff. When the listener returns it to me, I’ll indeed have the object I want in hand. This will work, but I don’t like it because I feel like I’d want to do this with other stuff too and would have to constantly figure out what the right thing to extend was.
Extend the rigid body control class but only a little - just to add some kind of “shot id” property to it. Somewhere in global app space I’ll have to keep track of these IDs and be able to grab any of the associated objects for that unique ID (the app specific logic class, the spatial, the control etc). This could work but seems like a lot of book keeping and I know from experience that messing with unique IDs is error prone.
So any thoughts on the subject for how to structure this type of stuff would be absolutely great! Thanks for reading and apologies for the length!