Simple Cart

[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.

Mensa Daily Puzzlers

For over 15 years Mensa Page-A-Day calendars have provided several puzzles a year for my programming pleasure.  Coding "solvers" is most fun, but many programs also allow user solving, convenient for "fill in the blanks" type.  Below are Amazon  links to the two most recent years.

Mensa 365 Puzzlers  Calendar 2017

Mensa 365 Puzzlers Calendar 2018

(Hint: If you can wait, current year calendars are usually on sale in January.)


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

Search only





Problem Description

Here's another physical world simulation  program that represents a simple gravity driven cart that knows how to accelerate under the influence of gravity and has some rolling friction that will cause it to coast to a stop eventually. 

Background & Techniques

This program is a test-bed for for a future Roller Coaster program.    The idea is to end up with a TCart object that behaves realistically as it rolls down a track at various angles (up and down),  with various levels of gravity, mass, friction.  

I'm still developing the code, but thought that this version contains enough interesting concepts to make it worth posting.   Let me assure you that, even though the cart behaves pretty well now, I've sent it flying many directions at many speeds while debugging the code.   Fun!

The Physics 

Like the Bouncing Ball program, we need to allow for gravity pulling down on a object.  Unlike  bouncing ball, the cart is constrained by the track so most of the force is probably spent just pushing against the track and only the leftover force is available to move the cart.    Let's use theta to represent the angle of the track to the horizon.   By convention we'll use  positive values for track descending to the right, and negative values for ascending to the right.   Then the force due to  gravity acting straight down is divided into two components:   one pushing at right angles against the track,  mass*gravity*cos(theta) and one acting parallel to the track and available to move the cart, mass*gravity*sin(theta).   There is some drag trying to keep the cart from accelerating, specifically rolling friction caused by friction in the wheels and axels and the slight deformation of the track as the wheels roll over it.     There is also drag due to the cart pushing the air out of the way as it  moves, we'll ignore that for now.    The opposing force due to rolling friction is proportional to the weight pushing against the track  and the coefficient of rolling friction (friction).  So opposing force = friction*mass*gravity*cos(theta).    The cart will be accelerated, according the Mr. Newton, by an amount directly proportional to the net force applied and inversely proportional to the mass, a=(aiding force-opposing force)/mass.  Note that as long as mass is not 0, it simply cancels out, i.e. things with more mass do get pulled to earth harder, but it takes more force to get heavy things moving.     

The TRamp class

TRamp  is pretty minimal - just enough to draw a few lines for a track.  I'm assuming that the final roller coaster track will be drawn with a bunch of short line segments.   The interesting routine is GetAngle,  called when the cart is to be moved.  It finds the line segment on the ramp representing the current cart position.   GetAngle scans forward or backward, depending on which direction the cart is moving until a segment is found encompassing the given Xval value.   Future loops in the track will cause multiple line segments  containing a particular Xval, so I take a StartAt parameter to begin the search.  When the segment is found, the Yval value corresponding to Xval  is found by interpolation and passed back to the caller.   

The TCart class

TCart has scaling properties Locscale and TimeScale which I haven't' worried about yet - the idea eventually is to make the user interface in real world units (feet & pounds, or meters & kilograms).   The Timescale property will allow the action to be speeded up - a thrilling ride that takes a minute in real time probably wouldn't look very thrilling  if it ran for a minute on the screen.  

Procedure Steptime does the move calculations, incrementing time by Timestep seconds each time it's called.     Xval is incremented by velocity*Timestep, then TRamp.GetAngle is called to get the track angle and YVal for this piece of track.  Acceleration for this angle is calculated as described above. The "opposing force" part is not quite straightforward - it's direction is determined by the direction of motion, independent of the ramp angle.   I ended up defining a "sign" function and multiplying the opposing force by sign(velocity) to make sure that it always acted to slow the cart.  

The DrawCart procedure also may be of interest to beginners.  It uses the routines from the Rotate Square program to define a rectangle  then rotate and translate it to its final location.     The wheels are imperfectly located on hills for two reasons - 1) the TCanvas.ellipse procedure used to draw them needs 4 corners of a square to define each circle and 2)  I was too lazy to write the code define, rotate, and translate each wheel's rectangle - seems like overkill somehow.    

DrawCart also uses a "sprite" technique to draw the cart.  The idea is to capture the piece of the background image where the cart will be drawn before drawing the cart.  When it's time to draw the cart again, we'll restore the background (erasing the old cart image), then capture a new piece of the background image for the new cart location.    The bitmap,  Savebg, is defined to hold the background image.  Saverect is a TRect record holding the coordinates of the area to be saved and restored. 

Running/Exploring the Program 

bulletBrowse source extract
bulletDownload source

Suggestions for Further Explorations

What if the track falls faster that the natural free-fall path of the cart?  Program needs to test and "fly the cart" off of the track if this design constraint is violated.
I would like to define linear and time scaling factors so that inputs can be in natural units with the  program handling the details of translating to pixels.  But still give user access to  natural unit readouts for x/y position, velocity, angle, and acceleration.  
Cart need to track successfully around loops (or not!).   Centripetal force?  
  [Feedback]   [Newsletters (subscribe/view)] [About me]
Copyright 2000-2018, Gary Darby    All rights reserved.