Roller Coaster Simulation

[Home]   [Puzzles & Projects]    [Delphi Techniques]   [Math topics]   [Library]   [Utilities]



Search WWW


As of October, 2016, Embarcadero is offering a free release of Delphi (Delphi 10.1 Berlin Starter Edition ).     There are a few restrictions, but it is a welcome step toward making more programmers aware of the joys of Delphi.  They do say "Offer may be withdrawn at any time", so don't delay if you want to check it out.  Please use the feedback link to let me know if the link stops working.


Support DFF - Shop

 If you shop at Amazon anyway,  consider using this link. We receive a few cents from each purchase.   Thanks.


Support DFF - Donate

 If you benefit from the website,  in terms of knowledge, entertainment value, or something otherwise useful, consider making a donation via PayPal  to help defray the costs.  (No PayPal account necessary to donate via credit card.)  Transaction is secure.


Feedback:  Send an e-mail with your comments about this program (or anything else).

Search only




Problem Description


Here's another in the Physics simulation series - a roller coaster this time.  The program allows users to -  

Load and save track designs
Modify a track or create new tracks with  hills and loops 
Specify cart and cart train properties
Set simulation parameters, gravity, time scaling, track start point, etc.  
Run the coaster and observe position, velocity, acceleration and g-levels.  Can optionally pause and enter step mode at any point in the run 

If you are not into reading about how it was done,  click here to skip to  the download section at the bottom of this page.

Background & Techniques

This is an advanced program, 2500 or so lines of code.  A complete description would take a book, so here we'll just write enough here to orient any adventurous Delphi programmers that want to improve the program.   I've spent 6 weeks of spare time and this is the 4th version so I'm ready to move on.  The number of ways to screw up a program increases with program size in the same way as the number of possible  handshakes in a group of people - exponentially.   So I'm sure there are a few bugs left for y'all.  

Here are the main design considerations and a few of the techniques used.   

Program Structure  

RCoaster4 has three units: U_RCoaster4 is the main form which runs the user interface fields in the tab sheet controls at the bottom of the screen.   U_Coaster contains the TCoaster class defining the track and coaster stuff running the coaster  image in the top half of the screen.  U_Splines is a unit which contains the B-Splines class used to define  track curves..  

The TCoaster class  is a  TPaintBox descendent containing  properties and methods for the virtual world cart and track, and the information to display the coaster on the screen.   I call it a "pseudo" component.   It has the features of a component but doesn't require installation and takes its visual characteristics (location, size, and parent) from information passed at create time.  This avoids the hassle of installing a component which will probably only be used in a single  program, but still gives full graphics capability.   


Scaling operations maintain external views in real world units and, for efficiency,  keep internal values in pixel based units.  A number of properties in TCoaster exist to support  automatic conversion as required.   

Scaling has been the biggest headache in developing this program.  I think that this is at least partly due to cumulative differences introduced by approximating the continuous track with a set of  line segments.   Run characteristics, especially the extremes, can be affected by  the screen resolution or number of line segments chosen.  Also, the program tries to maintain the height to width ratio across screen resolutions.  To do this we keep track of max and min x & y coordinates in virtual world coordinates and as % of image are width and height -  a total of 8 numbers.  These are saved and restored in coaster files.     


Here's a fairly standard way to efficiently move an object, the cart train in this case,  across an image.  This is usually called sprite movement.   The idea is to build images off screen so that we can update the on screen image with a single Copyrect operation.  This avoids the flicker that would occur if we  erased and the redrew the cart in separate operations.  

At startup make a bitmap copy of the background (without the cart), call it SaveBG.
Also at startup, define a bitmap large enough to contain the entire image, call it ImageCopy and copy the background there also.   This is the off screen image that will be updated with cart images.
At each time step, if it not the first time, erase the previous cart image in ImageCopy by moving the piece of the background image corresponding to the previous cart image (saved in Saverect)  from SaveBG to ImageCopy.  Copy  Saverect to another rectangle structure, Prevrect, since we're about to make a new Saverect with the new cart location and we'll need both rectangles before we're done. . 
Define a rectangle large enough to include the new cart image, save the new dimensions in Saverect, and draw the cart in ImageCopy.
Finally define a 3rd rectangle structure large enough to cover the old (Prevrect)  and new (Saverect) cart images, Moverect, and use it to copy from ImageCopy to the on-screen image.  

Cart physics

Between the initial "onchain" portion of the ride at the beginning and the "braking" portion at the end, gravity rules!  When off the track the cart behaves exactly like the bouncing ball program (without the bounce).   When on the track, the constant force due to gravity acts straight down.  This resolves itself into two parts - one acting parallel to the current track directions trying to speed up or slow down the cart, and one acting at right angles to the first part and which holds the cart on the track.  Most discussions of coaster physics speak in terms of maintenance of total energy - potential energy at the top of hills (mass*gravity*height) is converted to kinetic energy at the bottoms (1/2*mass*velocity2).   This is true but doesn't account for friction effects or centripetal forces through dips and through loops.  These complicate things considerably.   

Rolling friction always acts to in the oppose the direction of cart travel.  The force applied is proportional to cart mass and velocity.   Loops need to be elongated (clothoid shape) to allow carts to move through tighter radii as they slow down at the tops of loops.   This shape allows rider to remain conscious throughout the entire loop.   Circular loops require such high entry velocities that G forces would cause black outs - typically above 5 G's or so if applied for several seconds.         

StepTime is the key procedure which recalculates forces and and moves the cart by one timestep, typically .05 seconds to produce a fairly smooth illusion of motion.     It just takes previous cart parameters (acceleration, velocity, angle, location) and assumes that we moved a distance corresponding to one timestep.  We then call the GetNextPosition procedure which check the array of track points to determine which line segment we're on and how for from the end of the segment.  A record is returned with lots of information about the current track location, including angle and an estimate of the current turning radius.  Radius is important to determine G forces.

Starting/Stopping the Cart

The chainpoint is set to release the cart at the first point when the coaster track dips below the horizon.  From the beginning of the track to chainpoint, the coaster in moved at a constant velocity as specified in VZero, an initial velocity field.    Uniform braking is applied from the next-to-last control point to the end of track by reducing velocity by  a fraction, "1/(estimated time steps remaining)",  at each time step. 

Track Design -B-Splines and "Control Points"

Unit U_Splines is a modified version of a freeware Delphi B-Spline component written by M. v. Engeland.  I modified the code to convert it from a component to a unit  and added procedures to load and save the spline "control points" that define the track.    A B-spline curve is a set of piecewise (cubic in this case) polynomial segments that pass close to a set of control points. 

Left click on the coaster image invokes designmode.  This mode allows click and drag rearrangement of control points.  A popup menu, invoked by right clicking on the coaster, or a control point, allows new control points to be added or deleted. 

Loading/Saving Coasters

Procedures LoadFromStream and SaveToStream load and save coaster information.  One  problem with streams is maintaining compatibility if stream structure is changed during development.   A "version"  feature here maintains compatibility with previously saved coasters by inserting a 4 character version string with format "Vx.x" at the beginning of saved streams.  SaveToStream will always save the current new version number, and all of the current save fields.  LoadFromStream will check the version number and adjust reading as necessary to  read or set defaults for fields.

Lots more to tell, but that's enough for starters.  Have fun!

Addendum: November 15, 2002 - RCoaster4 has been replaced by RCoaster5 which fixes a few problems and has some minor improvements.

Debug display now shows  g force and distance traveled in the detailed data list
Add Control Point processing does a better job of inserting new control points where the user intended.
Scaling in the Simulation Parameters tab now works to adjust the location  of the displayed coaster track.    A new edit field allows the displayed track size to be scaled up or down.  
Virtual world track size on the Track Properties tab now works better.  This allows the track height and width to be adjusted in units of feet, meters or whatever.  Displayed values will reflect the changes, but the coaster image will not change significantly (unless the aspect ratio box is cleared).    

Addendum August 15, 2003:  RCoaster6 has been posted.  It introduces "Templates" ,  circles or straight lines that can be placed and resized on the screen when in Design Mode.   The idea is to allow students to build tracks with specific characteristics to check  against their calculated values.  (Or perhaps to check my coding, I'm not sure that the university that requested the feature has tested it thoroughly yet.)   Right click the screen while in design mode to show a pop-up menu that will allow you to define or delete a template.  Click the center of a circle template to select it for dragging to a new location.  Click the circumference to select the circle for resizing.   For lines, click either end to select that end for moving.  In all cases click unselects the template.   You will also see an option on the popup menu to lock/unlock  the templates.  This is to avoid accidentally picking up a templates when working with track control points.   Templates will be saved and restored with coasters.  

 If you have problems using the feature,  find bugs, or think up enhancements (idealized clothoid template?), use the feedback link to let me know.    


Running/Exploring the Program 

Suggestions for Further Explorations

 Add "Strip chart" type graphic display of acceleration, velocity, g-force as function of x-coordinate.
Make a more realistic, or user selectable, bmp for background image
Rate coasters for "safety" and "thrill factor" based on max/min g-force, acceleration, etc.  Should consider time at higher G levels
 Add units (ft, meters, etc.) to displays
 Continuous play wave files - currently has a sound break when looping a sound or changing files
Draw "support structure" under coaster to make image more realistic.
Define a "coaster box" that the user could resize to control the size and location of the coaster image within the paintbox area. (Implemented 11/15/02 in RCoaster5)  


Created: December 13, 2001

Modified: February 18, 2016


  [Feedback]   [Newsletters (subscribe/view)] [About me]
Copyright 2000-2016, Gary Darby    All rights reserved.