John Cletheroe's
Trainz Hintz - TRS2004 Scenario Creation Tutorial


TRS2004 Scenario Creation Tutorial - An Introduction To Programming For TRS2004 Scenario Creation

Introduction

This page is intended for someone with general computer literacy but only very limited knowledge of computer programming, who wants to learn how to write scenarios for TRS2004. It won't make you a professional programmer in five minutes but I hope it may help with learning about scenario creation.

Computer Programming Languages

There are numerous computer programming languages. They differ in their fundamental conception, and in their details. In almost all languages a series of instructions are written by the programmer, then obeyed by the computer when the program is run.

The programming language used to write TRS2004 scenarios goes by two names, GameScript and TrainzScript.

GameScript/TrainzScript is based on the "C" language, with many additional features that are required to control all aspects of Trainz. It is to some extent an object-oriented version of "C".

Text Editors And Integrated Development Environments

Most modern programming languages are designed to create programs that run in Windows and therefore involve 2D graphical objects. Therefore it makes sense for these languages to combine a text editor with a 2D graphical object editor, and include facilities for testing and debugging programs. This is called an Integrated Development Environment (IDE). A good example of such a programming language is Visual BASIC.

GameScript/TrainzScript does not have an Integrated Development Environment. Instead, programs are written using a text editor program such as Notepad (or any of its superior alternatives). GameScript/TrainzScript programs can only be run in Trainz.

Interpreters And Compilers

Some programming languages require a program's instructions to be converted into machine code before they can be run. This is called compilation and is performed by a program called a compiler that is supplied as part of the language's package. Most versions of "C" require compilation.

Some programming languages do not require compilation. Instead, programs are converted into machine as they are run. Such languages are called interpreters. Most traditional (pre-Windows) versions of BASIC are interpreters.

Compiled languages tend to run their programs faster than interpreters. On the other hand, debugging a program in an interpreter is much easier and faster than with a compiler.

Although GameScript/TrainzScript has a compiler, it can be ignored because Trainz has a built-in interpreter for the language, or perhaps it compiles when loading a scenario which has the same effect.

Therefore, if you are reading a book on "C" with the aim of it helping you to learn GameScript/TrainzScript, totally ignore the sections referring to the compilation process.

Planning

It is vital to plan what a program will do before starting to write it. Minor changes and enhancements can be made as the program is written and debugged, but the fundamental structure needs to be correct from the beginning.

Accuracy And Consistency

Computer programming needs 100% accuracy. The smallest typing, spelling or punctuation mistake will usually cause a program to fail. It is also vital to be 100% consistent with spelling, including the use of upper and lower case.

Patience

Computer programming is usually extremely frustrating. There is a need for enormous patience and persistence. Programs often need to be edited and tested hundreds of times before they perform correctly. This makes it all the more satisfying when a program is finally completed.

Statements

Each instruction in a program is called a statement. This is rather inappropriate name but it is very much an established standard.

The word "instruction" is usually reserved to mean a machine code instruction.

The word "command" is usually reserved to mean a textual instruction to a traditional operating system such as MS-DOS.

In GameScript/TrainzScript, as in "C", most statements must be terminated with a semi-colon (;). Learning when to include a semi-colon and when not to is one of the more frustrating aspects of "C".

Program Format

In all programming languages, including GameScript/TrainzScript, it is very highly recommended to write one statement per line.

In all programming languages, including GameScript/TrainzScript, it is very highly recommended to indent statements which lie within a FOR loop or a WHILE loop, or which are conditional on an IF/THEN statement. (These concepts are explained later in this document.)

In all programming languages, including GameScript/TrainzScript, it is very highly recommended to add meaningful comments such as headings for each part of the program, and explanations of any unusual techniques used or tricky sections. Bear in mind that you may have to debug a program months or years after writing it. In GameScript/TrainzScript, a comment is prefixed by two forward slashes (//) and runs to the end of the line.

Input and Output

If you are reading a book on "C" with the aim of it helping you to learn GameScript/TrainzScript, totally ignore the sections referring to input and output (for example, printf). This is because Trainz and GameScript/TrainzScript use totally different techniques for these operations to those of most programming languages.

User input to scenarios in GameScript/TrainzScript is possible within a mini-browser window but as this is a fairly advanced topic it is best ignored here.

Output of text to the user from a scenario can be to the scenario objective panel, or to the radio text box. It is also possible to output to a mini-browser window but that is considerably more complicated.

To output to the scenario objective panel, use the Interface.SetObjective function. Rather confusingly, this function doesn't set an objective, it merely displays some text.

To output to the radio text box, use the Interface.Print function. To make the radio text box visible from within a scenario, use the Interface.SetMessageWindowVisible function.

These functions are documented in the API. The API (Application Programming Interface) is an exceedingly useful document supplied and installed with TRS2004. It can be found here:
C:\Program Files\Auran\TRS2004\Scripts\docs\index.chm

Variables

A variable is a place where something can be stored by a program.

In early programming languages, the only things which could be stored were numbers, and the names of the places where they could be stored were pre-defined by the language, typically the twenty-six letters of the alphabet.

For example: A = 6 puts the number 6 into the variable called A, or if you prefer, sets the value of A to 6.

For example: C = A + B looks up what numbers had previously been stored in variables A and B, adds them together, and puts the result into variable C.

In all cases, putting a value into a variable replaces its previous value. For example A = A + 1 would add one to the current value of A. Although this is nonsense in maths, it is perfectly legitimate in programming. The value of the expression on the righthand side of the equals sign is calculated, and then stored in the variable specified on the lefthand side of the equals sign.

Modern programming languages differ from the above relatively simple concepts in several very important respects.

Firstly, the names of variables are chosen by the programmer, but limited by some rules. In GameScript/TrainzScript most words and combinations of words can be used. In all languages, including GameScript/TrainzScript, it is not allowed to put spaces or most other punctuation characters in the names of variables. Either capitalise the first letter of each word (for example AltonaSignal) or use an underline character instead of a space (for example Altona_Signal). It is highly recommended to use meaningful variable names, to assist in understanding a program. Bear in mind that you may have to debug a program months or years after writing it.

Secondly, different types of variables can be used. These include different types of numbers (integers and floating point numbers), strings (sections of text), Boolean variables (which are either true or false) and sometimes additional types.

Thirdly, in GameScript/TrainzScript, as in "C", each new variable must be declared before it can be used. This is done by prefixing its name with its type, for example int a would declare an integer variable called a. The declaration can be combined with giving the variable a value, for example int a = 6 would both declare a as an integer variable and give it a value of 6. Each variable must only be declared once (subject to the next paragraph).

Fourthly, variables are only defined in the area in which they are declared and lower. Therefore the same variable name could be used in different parts of the program, require separate declarations, and have different values. This is both useful (to avoid variable name clashes) and also potentially exceedingly confusing. This concept is called variable scoping.

Fifthly, many modern languages can handle objects, which can be thought of as variables that have two or more separate values.

Arrays

When a set of related values need to be stored or processed, it often makes sense to give them one general name and a numerical sequence number to distinguish between them. This is done by using an array with a subscript.

In GameScript/TrainzScript the subscript is put inside square brackets after the name of the array. For example A[5] and A[6] refer to two different elements within the A array. The subscript can be a numerical variable or a numerical expression.

In GameScript/TrainzScript, array subscripts start at zero.

As an example, in GameScript/TrainzScript it is often very useful to handle the set of rolling stock vehicles in a train as an array.

Expressions

An expression is anything which the program can calculate and make use of. Examples of numerical expressions are 6, 6 + 7, A + 6 (assuming A is a numerical variable), and A + B.

Expressions can also involve strings and other types of variables.

GameScript/TrainzScript, like "C", allows a wide variety of complicated multiple operations to be specified by writing two arithmetical operators next to each other, for example ++. If you are happy using these then do so. For those who find the idea nothing but a useless confusion, it can be ignored.

Functions

Functions have long since replaced the concept of subroutines in computer programming.

Functions operate in programming languages in much the same way as they do in maths. They have arguments (also called parameters) and they return results. The arguments are specified in round brackets, and separated from each other with commas.

GameScript/TrainzScript, like most programming languages, has a number of built-in functions to perform mathematical operations, for example Math.Sqrt will return the square root of a number, and Math.Rand will return a pseudo-random number.

GameScript/TrainzScript also has a vast number of built-in functions to set and get the properties of objects in Trainz. These functions are documented in the API. It is very important that each of the arguments used in a function is of the correct type (numeric, string, Boolean, an object of the correct kind, etc).

GameScript/TrainzScript, like most programming languages, also allows the programmer to create their own functions. While this concept can be very powerful, it can also easily lead to a complicated hierarchy of functions which is very difficult to maintain and almost impossible for any other programmer to understand.

FOR And WHILE Loops

When a set of statements need to be performed repeatedly, it is always best to obey them within a loop rather than write them more than once in the program. In GameScript/TrainzScript, as in most programming languages, there are two main types of loops.

If the program will know how many times to execute the loop before the loop starts, use a FOR loop. If the program won't know this, use a WHILE loop. In neither case need the programmer know how many times to execute the loop.

With a FOR loop, a control variable is given an initial value, an end condition, and an increment statement which specifies how much it should be incremented or decremented each time the loop is obeyed. These three items are placed inside round brackets and separated from each other with semi-colons. The statements within the loop are surrounded by curly brackets. For example, the following program segment will display the numbers 1 to 10 in the radio text box:

int i;	// declare i as an integer variable
Interface.SetMessageWindowVisible(true);	// make the radio text box visible
for ( i = 1; i <= 10; i = i + 1 )
	{
	Interface.Print( i );	// output to the radio text box
	}
<= means "less than or equal to".

It is very highly recommended to indent the statements inside the loop.

With a WHILE loop, all that is required is the condition under which the loop will continue to be executed, for example:

bool finished = false;		// define finished as a Boolean variable and set its value to false
while ( finished == false )
	{
	// many statements can go here
	}
When testing for equality, two equals signs are needed (==). When setting a value, only one equals sign is needed (=).

IF/THEN Statements

Sometimes one or more statements only need to be obeyed if a certain condition is met. This is done with an IF/THEN statement, although in GameScript/TrainzScript there is no "THEN". For example:
Interface.SetMessageWindowVisible(true);	// make the radio text box visible
if ( a > 6 )
	{
	Interface.Print( "a is greater than six" );		// output to the radio text box
	}

Objects

This is an attempt at a practical explanation of objects as they are used in GameScript/TrainzScript. Object-oriented programming purists may well object to such a simplistic description.

An object is a variable which has multiple associated values, called properties. For example, in Trainz a rolling stock vehicle is a type of object which has mass, length, velocity and other properties. In Visual BASIC a text box has properties including its left and top (which define its position), width and height, and text.

Whereas in Visual BASIC the properties of objects can be referenced directly (for example TextBox1.Text = "Hi there" sets the Text property of the TextBox1 object), in GameScript/TrainzScript in most cases built-in functions must be used. Get.... functions retrieve properties, Set.... functions set properties. These numerous functions are documented in the API.

A class is a set of related functions, in most cases all the functions which get and set the properties of a specific type of object.

The theory of object-oriented programming, including topics such as inheritance, encapsulation and polymorphism, can be ignored except by very advanced GameScript/TrainzScript programmers.


Index
Overall Site Home Page
About this personal web site JohnCletheroe

EMail me

Most recently modified 16-Apr-10