Inspiration:
I really like trains, and so I thought I could try to make a basic train simulator in Processing. I wanted the user to control a subway train between two stations, have to navigate a red signal, and stop and the next station without overshooting the platform. I also wanted the background to be populated with other NPC trains.
Process:
I started by trying to build the background for the simulator, which would simply be a top-down view of the tracks and tunnel. I made a platform, two rails for the tracks, and made a class for trains. I tried to add a .png image for the tracks, but for some reason, it wouldn’t load in. I never got an error message, I simply couldn’t see the image. As a place-holder, I added some rectangles for the rails. You can’t control the train yet, but the goal is to be able to.
Final Work:
Challenges:
I had a lot of challenges so far. For some reason, the rectangle of the subway train stays on the screen without disappearing. As mentioned above, I can’t load the tracks .png file, and finally I haven’t yet added user control over the train.
Code:
Train[] trains; int platformDepth; int platformLength; int railWidth; int railSpacing; int sleeperWidth; int sleeperLength; int sleeperSpacing; PFont stationFont; PImage img; void setup(){ size(1280,640); background(255); stationFont = createFont("Courier New", 30); img = loadImage("subwayTracks.png"); platformDepth = 100; platformLength = 800; railWidth = 2; railSpacing = 28; sleeperWidth = 5; sleeperLength = 30; sleeperSpacing = 15; trains = new Train[3]; for (int i=0; i<trains.length; i++) { trains[i] = new Train(0, height-platformDepth-10-railSpacing, (10)); } } void draw(){ //platform stroke(0); fill(255, 200, 100); rect(width/2-platformLength/2, height-platformDepth, platformLength, platformDepth); //rails noStroke(); fill(0); rect(0, (height-platformDepth) - 10, width, railWidth); rect(0, (height-platformDepth) - 10 - railSpacing, width, railWidth); noStroke(); fill(0); // for (int i=0; i>0; i++){ // rect(i, height-platformDepth - sleeperLength, sleeperWidth, sleeperLength); // } for (int i=0; i<trains.length; i++) { trains[i].runTrain(); textFont(stationFont); textAlign(CENTER); text("23rd St. Station", width/2, height-platformDepth+50); image(img, (height-platformDepth) - 10, width/2); } }
class Train{ float posX, posY; float trainWidth, trainLength; color trainColor; float wheelWidth, wheelHeight; float speed; Train(float _posX_, float _posY_, float _speed){ posX = _posX_; posY = _posY_; trainWidth = 40; trainLength = trainWidth*1; trainColor = color(126,127,128); speed = _speed; } void runTrain(){ trainBody(); driveTrain(); } void constructTrain(float _posX_, float _posY_){ } void trainBody(){ fill(trainColor); noStroke(); rect(posX, posY, trainLength, trainWidth, 7); //trailing carriages //fill(trainColor); rect(posX-trainLength-10, posY, trainLength, trainWidth, 7); rect(posX-(trainLength*2)-10, posY, trainLength, trainWidth, 7); } void driveTrain(){ posX += speed; if (posX > width+trainWidth/2) { posX = -trainWidth/2; } } }