App Screenshot

Yamanote Line

This console app is a train simulator that evolved from a beginner exercise in c++ object-oriented programming (here's a car, it has a speed, you can brake or accelerate, it travels distance etc.).

The main life lesson was that unless some parameters are passed in by reference, the train will not move. The rest is a fair amount of horribly nested conditional logic that was good exercise for me at the time.

Yamanote line is a circle line in central Tokyo. You start from Shinagawa station and can pick a direction (keys 1 or 2). The physics is based on plain linear acceleration formulars (no friction or air resistance etc.) as you might remember from high school or getting your driver's license. The distances between stations and the arrival and departure schedules are also loosely modeled after reality as the internet knows it, that is with considerable imprecision.

Press w to accelerate, s to brake, x to quit. You score points if you arrive in time. The game is over when you complete a circle.

The a key turns the autopilot (ATC) on or off. Designing that was just so much fun. The train, having traveled a certain distance already (distTraveled) needs to be at the next station in time (targetDist and timeLeft), just in time, not too early and not too late.

You need to know up to what speed the train has to accelerate (or slow down) and keep moving a while before you start braking in order to stop at the next platform in perfect harmony with the schedule.

The velocity where distAcc (how far you travel until you reach that speed), distBrake (how much displacement happens before you grind to a halt) and distMax (where you just keep going at that speed for the time you got left excluding accelerating and braking) are equal to the current distance to the next station.

Now, physics relates velocity to time and displacement to time, you could solve the train problem as a quadratic formula, but then you typically get one useless negative result and the useful number suffers from terrible rounding errors because of chip architecture when taking the square root.

So instead, brute force it is: speed is meter per second, just try a range of velocities until you find the right one:

for (i = 0; i <= 25; i = i + 0.0001)
     maxSpeed = i;
     distAcc = ((maxSpeed*maxSpeed) - ((m_speed / 3.6)*(m_speed / 3.6))) / (2 * accRate);
     if (distAcc < 0) {
         distAcc = 0;
     distMax = maxSpeed*(timeLeft - ((maxSpeed - (m_speed / 3.6)) / accRate) - (maxSpeed / brakeRate));
     distBrake = (maxSpeed*maxSpeed) / (2 * brakeRate);
     if (distAcc + distMax + distBrake >= targetDist)
         targetSet = true;

What you get is the speed you should be having and you will brake or accelerate accordingly. If from your current time and position you cannot make it in time anymore, you leave the loop having tested 25 m/s (that is about the highest speed of the trains they use). In that case you just accelerate and keep going until distBrake is equal to targetDist.

I end up running this for statement once in each game loop to dynamically fix the velocity, because the mysterious ways of the console cause weird time gaps that I could not manage otherwise (every attempt to flatten them out just created other new weird gaps).

App Screenshot
Download the Game 

Take a look at the whole messy Code

Copyright © 2016-2024