Skip to main content
GameDev.net gamedev.net
🔒 Locked

How to make a train turn correctly

Started by serioso Jan 20, 2010 at 5:55 AM 3 replies 1.2k views
Original Post
serioso
serioso
Hello, I have what is probably a very simple conceptual question, but I'm having some trouble thinking it through. I'm learning OpenGL (using C++) and I'm working on a simple application where the user gets to control a train. (At this point, I don't have tracks for the train, so it's really more like a bus with several jointed segments). Suppose you have a train with 4 cars: And suppose it's moving forward at some speed and the user wants to turn it to the left. I'm a little confused how to go about making the last three cars follow the first one correctly -- in other words, the train shouldn't "fall apart", and also, each car should always face the right direction. At the moment, I have a class for the whole train (Train), and a class for each car (Car). For each Car, I'm keeping track of the current position, the previous position in the last frame, the current direction, the previous direction, and I'm also keeping pointers to the car ahead and the car behind:

float pos_x, pos_y;              // Current position
float prev_pos_x, prev_pos_y;    // Position during last frame
float dir_x, dir_y;              // Current direction
float prev_dir_x, prev_dir_y;    // Direction during last frame
Car *ahead, *behind;             // Pointers to the car ahead and the car behind
For the Train, I'm keeping track of the first car, the speed, and I also have booleans for whether the train is currently accelerating, decelerating, turning left, and turning right:

Car *first;         // The leading car in the train
float speed;        // Speed of the whole train
bool is_accelerating, is_decelerating;  // Whether the user is pressing up or down
bool is_turning_left, is_turning_right; // Whether the user is pressing left or right
I'm probably going to have to have something for how fast the train is allowed to turn depending on its speed. Not yet sure what else. Suppose we also have the following constants:

const float length = 3.2f;
const float joint_offset = 1.5f;
And just for clarity, the "joint" is what I call the part where two adjacent cars are attached. The cars should pivot about these points. Anyways, here's what I'm wondering about: 1. How do I correctly update each car's direction per frame? Am I supposed to interpolate between the direction of the current car and the direction of the car ahead? Should I subtract the car ahead's position from its previous position to obtain a delta_pos vector and add that vector to the current car's direction vector to obtain the new direction? 2. How do I correctly update each car's position per frame? Obviously, this should (eventually) depend on the speed of the train. Should I just use pos and prev_pos from the car ahead? I apologize if this is a simple question -- it certainly doesn't seem that way to me, but then again, I am kind of a beginner and I've never really coded something like this before. (I'm also kind of sleep deprived.) I hope someone can help me understand the intuition behind this problem. Thanks in advance.
OldProgie2
OldProgie2
I've done something similar previously.

The way I treated it is that the trains followed a splined path. I could work out a position based on the distance along this path.
Once you can do this, you can work out the distance along the track for the front and rear bogies of each carriage then use these to points to get the position and orientation of the whole unit. The front bogie of the following carriage will be a set distance behind the first on the track.

Buckeye
Buckeye
OldProgie2 has a good suggestion. You'll have to choose where and how you want the car's direction to change.

When the car in front changes it's direction, the "joint" will swing off-centerline. This picture is somewhat exaggerated, perhaps, but illustrates the problem.



A method: when the first car (the locomotive?) changes direction, setup 2 variables:
- the new direction vector (red line to the right)
- the point at which the change of direction is to take place. (green cross) Perhaps set at the center position of the loco at the moment the "change" command is given.

Forget about fixing the joints together. Maintain a constant distance between car centers or maintain a constant speed. Each car continues along it's current direction, either a constant distance between car centers or at a constant speed, until it reaches the "change of direction" point. It then changes to the new direction.

Maintaining a constant speed is probably easier, as maintaining some distance would involve a bit more triginometry. As OldProgie2 suggested, you could also calculate the distance along a spline to fancy it up a bit.

If the change angle isn't too great, the dis-joint between cars won't look too bad. That's a problem with real RR couplers, by the way, and they must be built to swing off-centerline. In addition, the radius of track curves are restricted to minimize the problem.
Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly. You don't forget how to play when you grow old; you grow old when you forget how to play.
ItsDan
ItsDan
Perhaps part of your conceptualization difficulties are coming from the fact that a train and a 'segmented bus' would behave differently in regards to steering. The track information (possibly a spline as previously mentioned) would help determine where the center of the car should be.
-----------------------------------------------“The best, most affordable way to save the most lives and improve overall health is to increase the number of trained local, primary healthcare workers.”Learn how you can help at www.ghets.org
Nazdreg
Nazdreg
As ItsDan pointed out, a train and its cars move differently to a segmented bus.
One solution could be to have a class for the track, and instead of the train calculating its position, it sends the distance along the track it wants to move to to the track it is currently on, and the track would send back the coordinates for the center of the train, and the bearing it would be. This would be the same for the cars as well, except they would each have a distance_from_train variable which they would subtract the train's distance_along_track variable by before querying the track. How the track calculates the coordinates and angle depends on how you implement the track, whether it is made up of a series of straight lines, or a series of geometric shapes.
"REAL programmers use a magnetised needle and a steady hand"xkcd.com/378

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.