I wrote some code and then had an epiphany. A minor one but one that made me realize I had approached something in the wrong way. It was not much code and can be reused with the new idea.
First, the requirement is that the train move in a realistic manner. It needs to have the wheels or bogie of a car sit on the track and have a fixed linear distance between the bogies. That seems simple but it’s easier to move things on the track network using the track distance and not the linear distance. the difference is that the linear distance will be the cord of an arc. I can’t easily simulate couplers that pivot at the ends of the cars because establishing the location of the bogies on one car based on that type of coupler on a previous car is complicated and possibly impossible without a loop or some sort of expensive equation. I’ll use track distance between bogies of adjacent cars as a means of establishing coupler distance between cars.
With the above requirements, I came to a few conclusions and an implementation design.
The train object contains a linked list of train units or cars. The locomotive is a unit in this context. There is one unit, likely to be the locomotive, that is the main or key unit. It is the one unit that is known to the train object. To move the train in a realistic manner, I will simply start with one of the bogies of the key unit and figure out the proper location of each bogie for each unit before, including, and after, the key unit. This was not really the most important issue but deciding to generate the location of the entire train for each time step in the game was the important part. It needs to be done because moving bogies along the track the same distance for each bogie violates the rile that the two bogies on a unit remain the same linear distance apart.
The next issue is that the train could be straddling any number of turnouts or switches. I decided to keep things more game-like and not have turnouts maintain a direction state. When a train reaches a turnout, it can take the desired path without any predetermined turnout direction. This is a game and not a simulation so this is fine. Plus, making the player manage turnouts is the kind of micromanagement that is not appropriate for this sort of game. The problem in turnouts is that the train needs to pick a direction quickly and easily. To accommodate the quick part, I will maintain a list of turnouts that are under the train. This list will also hold information about what direction the train is currently taking for each turnout. Each time I position the bogies of all of the units, I’ll simply keep track of which turnouts are not in the list and decide the route selection at that point for that turnout. The selection of the route is then stored in the list so that it can be found quickly for subsequent iterations where the train is still over that turnout.
I may also need to store turnout route selection information in the list for turnouts that are ahead of the train’s current position. This way, I can look ahead to see what stops or speed limits are ahead and adjust train acceleration to stop in time. I want to figure out the route once for each turnout so storing them ahead of the train makes sense. They would only get stored ahead as far as the train needs to track them for the purpose of stopping or slowing.
That’s it. It’s really quite simple as long as the positioning of the bogies doesn’t take more than a few microseconds.
The linear distance stuff will require intersecting circles and lines and finding best matches. The idea will be to first find the track distance to a bogie position and store that point. Then the code will intersect circles representing a track segment and the bogie-to-bogie distance. The intersection that is closest to the track distance point will get used. Circles are likely to have zero or two intersections in these situations and I need to pick which of the two is closest to the track distance point to avoid cars getting flipped backwards if the wrong point were to be picked in an arbitrary manner. I’ll try a few methods of picking the best point to see what is dependable and requires the least number of tests.
The key unit bogie can be on either side of the one main bogie that is used to start the process. Fortunately, the key unit is used for train direction management and the direction information can be used to figure out a track distance point for that second bogie before the linear distance is used for the actual positioning.
When I write this stuff done, it sure seems like there would be an easier way to do all of this. I doubt it can be made simpler as long as linear distances are needed.
One of the interesting benefits of the earlier mentioned route finding is that I can work with a random route without some units or some bogies taking one route through a turnout while others of the same train take a different route. The turnout direction is picked once when the train reaches it and is discarded once the train has passed it.
Now I need pictures of some of these concepts and to explain why linear distance is important.
I want to maintain a list of waypoints, the internal name for any track geometry change location including turnout locations, instead of just the turnout choices for waypoints that are under the train. this would allow the track network to be modified under the train without the train seeing a new turnout and taking it mid-train. Since a modification could actually add a waypoint and split a segment in two to do it, this can’t be accomplished easily. Things will be left “broke” and when the game play is running, code will get written to keep the game from modifying the network under the train. only once a train has passed can the imaginary work crews lay track and make a new turnout.