Application logic structuring/architecture questions

Hello everyone,

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:

  1. 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.

  2. 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!

I seem to have missed this article https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:custom_controls which appears to be the accepted approach, so while I’d still like to hear how people structure their applications, this “problem” is solved :slight_smile:

AppStates are another thing you might want to look into. In my games, my main class has almost nothing in it.

I have a few examples out but they are really entity system examples so I hesitate to point you in that direction as that might confuse the issue.

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

The 2 options that come to mind are:
1 - Make your Shot class a Control (not ideal if its just storing data, but is easy to access from a Spatial), and then can access it via (assuming it’s node A) [java]Shot shot = event.getNodeA().getControl(Shot.class)[/java]

Or

2 - Implement the Savable Interface on your Shot class, and save it as user data, then access it like:

[java]Shot shot = (Shot) event.NodeA().getUserData(“shot”)[/java]

@gabe said: Hello everyone,

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:

  1. 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.

  2. 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!

Ok, i think I have a cure for your confusion. But first welcome to the jungle.

I’m rather happy when I heard you say JME3 is a “framework” that worth to try. It also has game specific aspects as you and @pspeed mentions : Controls and AppStates. Beside of that, I think some of long term Java developer should get their self straight when come to game developing, because the real-time space is much more differ from the web space :stuck_out_tongue:

About extends functions via extends class, it’s one way amongs other solutions: EntitySystem (check Zay-ES) , via a Spatial’s Control, or Managers…

Managers are “book keeper” for “game objects” and “game data”, manage, contain and ecapsulate those information and provide API… [ Hold on for this concept for minute]

I saw your example (or kind of ) many times already. People always try to solve to much problems at once, which not aware of doing it easier when divide and conquer. Now ask your self?

    • How may data should that “game object” - a “shot” contain?
    • Is it suitable to be “modeled” as a “spatial” - thing that belong to world space and basiclly have positions, parent, nested children and controls [more]… which you already implemented and are welmanaged.
    • Is there a reason to “book keeping” all the nessesary information, for collision detect, for callback? Is there a need of your own Manager for this dection and triggering, event handling routines.

So 1)2)3) questions let you answer What?How?When you should model your “game objects” and “manager”. Corporate with the benefit of Controls and AppState you will get a better picture of what you should do.

For the Shot example, what I did is:

  • Making two singleton managers, which in turn are AppStates. EventManager handle ingame event, including collision events, TriggerManager manage Trigger including PhysicCollision.
  • Shot are spatial, they can be physical collision check or simple range check. When is out of simple range check, do not do collision check because it’s slow. Every single bullet can come with custom data like explosive, effect type, damage etc… It’s motion can also be handle by a control, (which can be shared!!)
  • When a Bullet hit an object, the TriggerManager get called by PhysicCollision, or in opposite, TriggerManager check and notice that PhysicCollision are triggered. -> It let it’s EventManager know to speard the news -> Maybe a “CombatSystem”-“PlayerManager” in form of another Manager somewhere have to news and decide who should be dead and who should be reward with points.

My points are:

  • devide and conquers,
  • use existed models if possible, expand the framework in wel-crafted areas and spots; into right directions such as Managers, Controls, AppStates
  • Concern about physics, 3d collision or even spatial checking in simplest form first, it can work in almost cases.
  • Should take a look at triggers and generic event system and may be generic game logic framework. [I’ve write an framework called Atom for this purpose]

More tips:

  1. First make it work,
  2. Make it reusable. As read the initial question, I see you are tracing this, and you came from web world, I guess you are familiar with framework.
  3. If performance come in concern, let take a close look at “bottle neck” in the “loop”. If there is book keeper, let’s the book keeper tracking and monitoring its attendants and inspect who delay the queue.

Happy coding.