Documentation

GeekTrains.com developer's technical documentation, writen by Quintus Hegie for computer geeks and train enthousiasts. With this documentation you'll be able to develop new levels and create new game objects (locomotives and/or wagons). If you're a web developer and you have a question about 3D progamming and/or BabylonJs, please contact me on Forum.BabylonJS.com (until December 8th 2018: HTML5GameDevs). If you're a game player instead of a developer, then you can find the manual here.

Please note: The game specific soure code is protected with legal copyright! You may not use this code to create your own train or similar game, but you can use some components and logic for any other type of game. The code may be changed at any time without any notification, rendering any custom additions maybe no longer compatible with the latest version.

3D Engine

Scene Optimization

In comparison with regular train simulator games with large worlds that are partly visible, my game is about model trains where the whole play world fits into a single room so to say. The player thus generally has a good camera view over the whole level (room). Therefore most meshes are visible and need to be rendered most of the time. This creates a challenge for keeping a constant and high framerate, because only a little fraction of the meshes will be out of view most of the time. That is why I use some specific scene optimization techniques for this train game.

Texture Quality

To main save on memory use (for low end devices) and network bandwidth (slow connections) and server traffic (costs), the textures used in the game come in several qualities. We set the quality mainly by choosing the resolution or pixel dimensions (width and height) of the texture. Depending on the type of texture contents, we choose for a JPEG (photo/realistic) or PNG (drawing/cartoonistic) compression technique and file format. The GPU generaly won't care which format we use, and often has enough RAM, but if the player has a low end device with no GPU then we want to reduce the load on CPU and normal memory.

Texture Qualities
Quality Setting Maximum pixel side dimension Average compressed file size
Low64-128 pixels10-25KB
Medium256-512 pixels50-250KB
High1024-2048 pixels500KB-2MB

Some gameobjects use non-square textures (e.g. a rectangular texture for sphere materials). For these textures the maximum pixel dimension to take is that of the longest side (width or height). So a low quality rectangular texture for use on a sphere mesh may be 128×64 pixels.

For sprite atlas textures, the dimension of a single sprite may not exceed the specified limits. So a low quality sprite atlas which holds 4 square sprites, may be at most (4×128)×(1×128), or (1×128)×(4×128) or (2×128)×(2×128) pixels in size.

Level of Detail (LOD)

A level mainly consists of a terrain or playing ground, that is visible in full or in large part. Next in line of frequently visible meshes are the train tracks. The train tracks may be observed from very close by (when camera is set to train drivers view mode) as well as from a large distance (when camera is set to level map view). A technique to speed up rendering when using various distances to view the same mesh is to apply Level of Detail (LOD).

Level of Detail (LOD) on a Rail
Levels of Detail on a Rail: left the full mesh (rendered when viewed from close-by), right the simplified mesh (rendered when viewed from a distance)

Game Engine

General logic

Config file

The game consists of many different game object types, which each have their own unique capabilities. To keep the game logic as simple as possible, I chose to use a config or settings file to set up a specific game object type.

This config file contains the properties to set for the different game objects. This way it would be easier for me to tweak the game settings in order to get the best gaming experience. The specific game object's type config will be loaded in the GameObject definition from the settings file.

Game Objects

Hierarchy

Locomotives

A locomotive is equiped with a motorblock and is controllable by a player.

Locomotive Game Object properties
Locomotive Game Object: accessors of attached objects

Wagons

A wagon is not motorized and needs to be pushed/pulled by a locomotive.

Wagon Game Object properties
Wagon Game Object: accessors of attached objects

Trains

A train is a logical unit that consists of one or more vehicles (array). Because this is a train game, the vehicles in a train are typically rail vehicle game objects like wagons and locomotives. A train has at most 1 master, that is the unit that controls or moves the train (often the 1st locomotive).

Train Game Object properties
Train Game Object: accessors of attached objects and constraints

A train vehicle sequence imposes a new (additional) constraint on its vehicles. Where a wagon and/or locomotive is already rail track bound by its wheels, a train also is bound to the condition that the vehicles are attached to each other. The separate vehicles together form a whole 1 train.

The constraint added is that the distance between each coupling is limited by a min and max hook 'rope'. This is of course a simplification of the physical constraint for real world model trains (as hooks aren't ropes but rigid bodies), but it gives enough effect of a train composition because the vehicles are bound to the rail track anyway. As rail tracks won't make sudden abrupt 90-degree angles, but only slow smooth curves, the 'rope' constraint will give nice enough visual impression of inter-wagon connection.

Train Line System

While cars loosely follow road waypoints, trains drive strictly on railroad tracks. These railroad tracks are laid out within a TrainLineSystem. So the TrainLineSystem contains all pieces there are to the complete railway within the level.

A line, a curve and a path
A (straight) line, a curve and a path

In its simplest form, the TrainLineSystem is a collection of connected paths. The paths approximate smooth curves by concatenating small pieces of straight lines together.

Train Line

Each segment within the TrainLineSystem is called a TrainLine. The segment actually contains the 3D track mesh.

The segments are connected to each other via points (railroad switches / turnouts) or connectors.

A TrainLine is composed of track pieces
A TrainLine is composed of track pieces

Laying railroad track

Railroad track is layed very similar to the construction of a toy model railroad layout: consecutively by connected each train piece to the next. Railroad track is then layed using track piece chains. The order of the track laying must respect the natural driving direction. The following track pieces are available:

A starting track (for example a buffer stop) can be given a starting position and rotation. Any next connected track will be layed in the specified direction.

The slope parameter is expressed as a fraction. So when slope = 0.01 then the slope is 1 centimeter rise per 100 centimenter flat distance. Regardless of the slope the length is always measured in flat distance (does not take into account the equal or longer length of the slope distance). This makes connecting track pieces with slopes more easily in a 3D-world, as the distance is always measured on the 2D-surface plane.

Turnouts

Turnouts are logical units and don't have a track size (length) themselves, so you must connect straight or curved tracks yourself. All turnouts must have an unique id each so the track layer knows which tracks to connect where to it in what direction. Based on the entry and exit-points, tracks are connected to the turnouts. For example, the leftturnout has connecting points start, left and straight.

Power connectors

Power connectors are logical units and don't have a track size (length) themselves. You cannot start or end track with a powerconnector; it must be placed within a track segment. If a team is specified, the powerconnector becomes a possible starting location for any player in that team. If a player is specified, the powerconnector becomes the starting position for that player locomotive.

Trigger magnets

Trigger magnets are logical units and don't have a track size (length) themselves. You cannot start or end track with a triggermagnet; it must be placed within a track segment. If a group is specified, the triggermagnet will trigger any logic tied to that group. For example, you can open or close a bridge, a gated level crossing, change a signal, etc.

Crane

A crane is equiped with a hook and one or more controllable joints. The controllable joints allow for steering and operation of the crane.

Crane Structure Game Object properties
Crane Structure Game Object: accessors of attached objects

The joints can be restricted so that movement or rotation is limited to a certain distance or angle for example by setting the min and max properties.

Places & Zones

In the game, places and areas of interest and interaction are marked by the logical Place and Zone GameObjects. Both a Place and a Zone have a position and a rotation, but only a Zone has a scaling attribute.

The usage of places and areas enables interaction in the level for moveable GameObjects. For example for a Vehicle (including locomotives and wagons) and a Creature (including figures), but also for Item (such as goods). Both a Place and a Zone trigger an action on moveable GameObjects entering and/or leaving the marked location or area.

A difference between a Place and a Zone is that an occupant bounding box need not fit in a Place, but must fit as a whole in a Zone.

Places

A Place has no shape because it only marks a location. The rotation may indicate at which direction the occupant must occupy the place.

We defined a special set of Places that mark some standard location automatically. The special Places are:

Zones

A Zone has either a box or sphere shape to describe the size of the area. The shape also determines the colission detection to use for GameObject models entering and exiting the area.

The default size of the Zone is Babylon.Vector3.One().

Use the GameObject parenting system to attach a Zone to a (often static) GameObject such as a Structure.

We defined a special set of Zones that accomplish some standard task automatically. These types of Zones also show visible markers, so their presense and usage is more clear to the Player. The special Zones are:

Level setup

Before a new Level can be added to the list of playable levels, a level setup file is needed. The Level GameStateObject creates the playfield (scene) for your trains based on this level config file in JavaScript. So the level setup file is parsed when the Level has been chosen by the user to be loaded/played.

3rd Party Railway layout tools

The game by default uses the G-scale track gauge format of approximately 45mm (1¾ inch).

Due to the nature of this garden toy trains game, also larger 'big toy' / 'home garden' / 'fun parc' scales might be eligable to be played. For example 3½, 5, 7¼, 7½, 10¼, 12¼ and 15 inch. (In the code, the level scenery will be scaled down such that the track becomes G-scale gauge again.)

You can design your railroad track layout using 3rd party tools from vendors like:

Using some simple logic, the designed track plan can be converted to the GeekTrains system. E.g. by approximating the length of straight track parts and the radius of curved track parts.

Level config file (JavaScript)

level variable

First set the general properties of the level:

Property: level
PropertyMeaningExample
iLevel number (higher level number means more complex level to complete)1
nameUnique internal level name'geektrainsdemo1'
titleA friendly title for this level, shown to player'GeekTrains Demo Level #1'
descriptionA longer description for this level, shown to player'A demo level of GeekTrains consisting of a basic circle railway track layout.'
authorName of the level author/creator'Conduqtor Q'
locationGeographical location of the level, for example a place name and a country name (especially used for outdoor track layouts)'Rotterdam, The Netherlands'
urlAn optional URL to a webpage containing more information on the level for background reading at another time'http://geektrains.com/geektrainsdemo1/about'

world_config variable

Second, construct the empty world (that will later contain the model train tracks). It can have the following optional properties: (When you omit some properties, they will fall back to a default setting.)

background

The background to use (rendered behind the skybox, if a skybox is present).

color
The BABYLON.Color3 (or BABYLON.Color4) background color. For example BABYLON.Color3.Blue() (which is the default fallback color by the way).
url
URL to the background file, for example 'background.jpg'. If no URL is set, the background color will be visible.
sky

The sky (rendered before background). Defaults to no sky (thus show background).

fog

To enable a fog effect.

color
A BABYLON.Color3 color to use for as fog. Defaults to the generic clearColor.
mode
A BABYLON.Scene.FOGMODE mode to use for as fog. Defaults to BABYLON.Scene.FOGMODE_NONE.
snow
Adds a snowy cloud to the level. Optionally can make a hail storm.
rain
Adds a rain cloud to the level. Optionally can make a thunder storm.
url
URL to the skybox JPEG file, without the file extension and dot. Will load the 6 face textures by adding a postfix per face to the URL (_nx, _ny, _nz, _px, _py, _pz). For example 'sunny'.
surface

The surface plane (prevents objects from falling into an infinite abyss).

diffuseColor (same as: mainColor for grids)
Sets the diffuse BABYLON.Color3 for the surface (if no texture is specified).
emissiveColor (same as: lineColor for grids)
Sets the emissive BABYLON.Color3 for the surface (if no texture is specified).
texture
Name of the texture within the texture library to use for the surface, for example 'dirt'. If no texture name is set, falls back to a diffuseColor material.
type
The type of surface, typically named after the Mesh to create. Choose from 'box', 'cylinder', 'disc', 'plane', 'tiledground'.
Property: world_config
PropertyMeaningExample
terrainTextures for the terrain. 
heightmapOptional. Set it to give the terrain a heightmap. 
groundSets the size of the playground (where the train track is put upon). 
sun

Optional. Configures the lighting for the scene.

You can set the type of lighting with type. Choose from: HemisphericLight (great for debugging), PointLight (great for indoor scenes), DirectionalLight (great for outdoor scenes) and SpotLight (great for mini-scenes). The scene will always be lit with at least a HemisphericLight.

You can optionally set the time with time. It can set the scene's lighting to a fixed time in day (midnight, night, dusk, morning, day, noon, afternoon, evening, dawn, night), or simulate a day/night schedule with setting clock (24 hours pass in 6 minutes, starts at day).

 
waterOptional. Adds a full-scale water to the level. 

Third, place the railway tracks:

track_line_layout (more info soon)

Fourth, add all other objects to complete the scene:

Finally, decide upon the mission objectives to complete the level:

objectives