Where to place game logic

I mean, where place things like updating positions of objects, making simple/complex decisions etc.

I could place it in update loop (directly or via controlls), but then it would both depend on frame rate and influence it too. And if I want to make it multiplayer, it would go out of synch, as soon as someone would start to turn (his position would differ on two machines with different fps)

So I’m thinking about different thread, and from this thread update controlls of game objects, so They would visualy move smooth, even if rules of game would be applied in lower frequency.

So “Rules” thread would have to take care of logical time and graphics thread would have to use some estimate of this logical time to animate thinkgs between logical steps. This would allow changing speed of game (either because user wants it, or because processing of one step takes longer than current duration of step).

In rule step, AI would react based on their current behavoir (no thinking ahead). From behavoir it would decide what action it want to make and would send to graphics thread update of its controller to show it doing such action.

And if something needs to make decision that takes longer, it would create and send decision making task to some thread pool and as soon as its done, it would change its behavoir.

Is there something fundamentaly wrong with this?

Is it alreay implemented (if I understand correctly, jBullet physics is something like this, but I’d like to have rules based game, not physics based game (If I want something to do a maneuver, I make it do it, not try to find setting of forces, resistances etc. that would in the end produce that maneuver).

To be more precise, I’m currently thinking about unrealistic (for example ships do accelerate, but have maximal speed) 2D space game.

You should place most everything in the update loop to avoid logic problems. You can multithread in that loop too. Think like “i do my update and then at the end I start the parallel task that I check for next time I am updated again”.

The general way in jME3 to compartmentalize code is by using AppStates and Controls which are basically callbacks to the update loop. AppStates are for the application scope (managing entities, user interface etc) and Controls are for Spatial scope (managing spatial animation, collision detection etc.). Since all registered AppStates and Controls are retrievable via their class ( getContol(MyControlType.class).doStuff() ) this also allows you to access any of those AppStates or Controls via the application or spatial variable, without passing around references to the classes.

1 Like

Then everything in game rules must be formulated to work with nonuniform time delta (tpf)?

Thats reason why I think about puting logic in separate thread (et least “model logic”). (But presentation logic i definitely intend to put in main loop somewhere (controlls, appstates, whatever)

Or does I understand something wrong?

You can also use any kind of other timer but you are bound to the update loop when you actually want to modify the scenegraph so completely detaching your logic from it is probably not a good idea.

My idea is, that i will update controlls of nodes and that update itself will be in enqueue call, so I will not change it in the middle of use. If it takes effect one frame sooner or later does not matter, because it “ticks” with different speed, so object will never change what they do graphicaly when they change logicaly.

Yeah you can do that of course, but in this case I suggest that you “encapsulate” all calls to the actual scenegraph in objects that you use on the other thread. So if you have your entities or AI system running there they should never ever call spatial.getLocalTranslation() or something but instead rely on some other data that is updated somewhere or use a class to access this data from the scenegraph that takes care of the threading.

Still, linking the whole thing into the update loop is probably still a good idea as it allows for better control over the graphics side compared to the “loose” threading method using a queue, especially when its not only one separate thread.