3
\$\begingroup\$

Suppose I have a Spacecraft object in 3D space, controllable by the player. I want it to update its own trajectory, so I give it a function for that (actually it might be inside a controller component associated with it). No problem until this point.

For this function I want to use a scientifically tested, accurate N-body simulation algorithm (like this). It's my field so I already know how to do that.

The challenge is how to make the game activate the function efficiently. This is what I've thought of so far:

  1. The algorithm can calculate a lot of time steps in a short time, so I could activate it in one loop, save the trajectory data, and go on for several game loops using that data. During this time the spacecraft's position is updated every loop, but the algorithm is sleeping.
  2. When the predefined number of loops has passed, or when the user gives a movement command, the algorithm is activated again, producing the new portion of the trajectory to use next.
  3. This might require double-buffering.

The question is: who should be responsible for activating the spacecraft's algorithm? Should I do that directly in the game loop, or perhaps create a "timer object" that keeps track of the number of loops and user input and calls the function when appropriate? Something else?

Note that the same thing would happen for all the other bodies orbiting in space. However the other bodies would simply have to follow predefined trajectories, no need for an algorithm. The timer object could take care of updating all the trajectories at the right times.

Also, if you think there is a totally different and better way to do this, please let me know.

Additional info: the game is in C++, and the graphics engine is Ogre3D.

EDIT: changed the part about the trajectories of the non-interactive bodies, because comments here made me realize that it was plain stupid.

\$\endgroup\$
2
  • \$\begingroup\$ For the other bodies, read trajectories from a file at load time, then never touch that file again. \$\endgroup\$
    – thedaian
    Commented Sep 9, 2011 at 13:27
  • \$\begingroup\$ @thedaian yeah, that would be the best thing, but a few calculations led me to think that the file might be several GB large. I can't keep it all in memory... \$\endgroup\$
    – IGRSR
    Commented Sep 9, 2011 at 14:13

1 Answer 1

2
\$\begingroup\$

This is a interesting software engineering problem.

First of all you need to identify what entities are involved (entities broadly speaking) and assign them responsibilities (-bility is better) and knowledge about the other entities (less is better).

Here I can see: your trajectory algorithm, the generic position updater, the user interface or user control subsystem.

Your algorithm does not need to know anything about user control subsystem or frame related updating stuff so it should be highly decoupled about the rest: it should keep the environment status and output the trajectory information and time validity by its own. You should implement it so you can run it without any game related component. This make your life easier in debugging and unit-testing phases.

Your algorithm needs a bridge to let its outputs be used for your ludic purposes. This kind of bridge should be implemented in a way so a different algorithm may be used with easy.

The interface side of the bridge (the side that will be used by the game) should give to its consumers a way observe the relevant environmental status (this prescinds the particular trajectory algorithm) and the user input while providing a query interface that can return a positional status, given a particular time coordinate.

The implementation side of the bridge should be aware of the trajectory algorithm: this encapsulates how you transform a positional query to a positional computation or a projection of your trajectory).

A possible implementation of the query functionality can be that the bridge uses the time coordinate along with the current computed trajectory to compute the position. If the trajectory is invalid than a new one is computed: a stored trajectory becomes invalid if used outside its time range of validity or if the environmental update methods detect an action by the user.

About the way the non-interactive objects trajectory are computed, keep in mind that probably everything is better than read through a file. Here we are talking about to trade-off disk usage, memory occupation and CPU allocation.

The answer to this trade-off is simple "compress": compressing basically means to store a fraction of the whole data and use CPU and RAM to transform compressed data into real and useful data.

In your case, the knowledge of the data is the key: you can start by identify the minimum data that is required to compute your trajectory; how you can translate it into a real(raster) path?

If the CPU usage for this is acceptable you are done, if not (as it should be reading your question) you need to look for where CPU intensive temporary data are computed.

This kind of data can be stored along with the basic trajectory parameters to speed up the trajectory reconstruction (memoization-like). You may preload these data if the ratio memory_usage/usage_frequency is good or avoid it and discard used data(hence re-read if re-needed).

In a nutshell: your custom specialized compression algorithm has to be tuned to achieve the better CPU/RAM/DISK trade-off.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for the helpful explanation. Regarding the compression of the orbital data, you're totally right. After @thedaian's and your comment I've done some thinking and found a way to do this easily, I think. \$\endgroup\$
    – IGRSR
    Commented Sep 11, 2011 at 8:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .