Halcyon Racer is actually quite simple from an organizational point of view. The number of main game classes is small; take a look at the class diagram. Below you will find a brief explanation of each class and an overview of which classes the game itself relies upon. Feel free to download the source code and take a look. The code is full of remarks and comments about what each function, class, etc is doing.
CGameEngine intercepts all the messages it needs through MFC. Then, it distributes the needed messages throughout the object hierarchy (when needed) to affect the running game. This is done by using member functions set up in CEnvironment. CEnvironment than decides from those messages, what to send to CUserCar, CEnemyCar (each enemy car actually, there are multiple ones), and to the CTrack. CGameEngine also handles all of the introduction screens (the spinning car at the beginning and the menu, etc) and all sound playing.
CCar is where everything about driving takes place. All the cars move, speed up, slow down, skid, run into walls, etc. according to this class. Physics are implemented here that take care of momentum and collision detection as well. Since all cars (the user car and all enemy cars) inherit from this class, all cars drive following the same rules. CUserCar inherits from this and adds a method to get user input and translate that into movements of the car. It also prints out feedback information to the user. CEnemyCar, conversely, adds artificial intelligence methods instead of user input.