Trackballs - Scripting Language

# The Scripting Language

In the `.scm` files of a level the designer can use a powerful scripting language to decide which objects should exist in the game and, optionally, even customize how they should behave. Using these features it is possible to create very different kind of games.

The scripting language chosen for this is called Guile and is a language developed by GNU to be used for customizing applications. The language is a version of Scheme and on a first appearance seems to constructed by lots of incredibly silly parenthesis (LISP).

The easiest way to get started with the language is by copying an existing .scm file and customize it for your new map. We start by taking a look at, for instance, `con1.scm`.

`

    ;;; steep - by Russel Valentine

    (set-track-name "Steep")
    (set-author "Russell Valentine")

    (start-time 120)
    (set-start-position 253.5 253.5)
    (add-goal 230 228 #f "con2")

    (add-flag 248 220 100 1 0.1)
    (add-flag 247 220 100 1 0.1)
    (add-flag 246 220 150 1 0.1)

    (add-modpill 254.5 217.5 *mod-jump* 20 0)

`
In this script file we see first a comment, this is any line which starts with a ';' and is ignored by the program.

Following this is a number of function calls which use some of the built-in functions in trackballs to setup the settings for this level and to create objects. The first of these function calls are the "set-track-name" function. As you can see all function calls must be encapsulated by parenthesis (that's how scheme knows they are functions and not variables or values) and this first function expects one argument. In this example it is given the argument "Steep" which is the name of the level. Similarly the function "set-author" is used to tell trackballs whom has created this level. These two pieces of information is used in the beginning of the level to give proper credit to you, the author!

Some other inter sting functions you see here is the one to decide how much time the player has to complete the level, start-time, expressed as seconds, and where he starts. The later function, set-start-position, expects the x and y position for where the player starts and the easiest way to decide which coordinate to use is to look at the coordinates of a cell in the map editor. Note that this function expects a floating point number, so it is possible to very precisely decide exactly where in the cell to start.

The next function, add-goal, expresses where the goal for this level is placed and expects x/y coordinates again and a true or false value if the goal should be horizontal or vertical (use #f or #t) and finally the file name of the next level to go to.

The remaining functions, add-flag and add-modpill, are used to create some objects in the game. In this case flags which gives points and a modpill which makes the player capable of jumping further. See the API Reference for more information about these and other functions.

Apart from a number of built-in function trackballs also includes a large number of built-in variables. These variables are typically used as constant values to be passed to functions. One example was the variable `*mod-jump*` which declared which kind of bonus pill was created in the example above.

### Programming in Scheme

If you want to do more fancy setup in you levels, perhaps selecting starting time and position depending on the difficulty settings or other customizations, you need to know a little bit of scheme programming. If you want to learn how to use scheme properly i would recommend reading a tutorial on using scheme. Otherwise, you can probably just learn as you go by examining examples.

### Creating your own variables and functions

Apart from using the predefined functions and variables in trackballs you can create your own. This is good since it allows you to simplify the code for doing complex repetitive things. For instance, if you want to create an opponent ball with a customized colour you can do so by doing:

    (define erik (new-mr-black 241.5 245.5))
    (set-primary-color erik 1.0 1.0 0.0)

This would create an opponent "erik" which is yellow. If you want to create lots of eriks, you can create a function which does this:

    (define new-erik (x y)
      (set-primary-color (new-mr-black x y)
      1.0 1.0 0.0))

and use this function repeatedly.

    (new-erik 100.0 100.0)
    (new-erik 200.0 100.0)
    (new-erik 200.0 200.0)

Another more useful way of using functions is to have them as "hooks" which get called by the game when different events occur. There exists a number of different functions with which you can create a hook which calls one of your functions when something happens in the game. Depending on on which event you have your function called your function may need different number of arguments. For instance, if we want to create a modpill when an opponent "mr-black" gets killed we can do this by first creating a function to be called:

    (define my-modpill-function (subject object)
      (add-modpill (get-position-x subject)
                   (get-position-y subject)
                   *mod-extra-life* 30 -1))

This function accepts one argument, subject, which is the mr-black that got killed and another argument which is ignored. It then gets the position where he got killed and creates a new "extra life" modpill at that position. In order to use this function when different opponents gets killed we need to tell Trackballs to use it:

    (define erik (new-mr-black 241.5 245.5))
    (set-primary-color erik 1.0 1.0 0.0)
    (on-event *death* erik my-modpill-function)

Congratulations, you now know the basic steps on how to completely customize the game. By using your own functions and hooks which plug in to different parts of the game (like when objects get killed, or the player is close to a switch, or whatever) you can accomplish almost anything. Well... at least that's the general idea. Go ahead now and read the API Reference to see which functions, variables and hooks are available to you and take a look at the Examples to get you started. If you have any great ideas for extra hooks or functions that are needed in the game please post a request at the issue tracker and we'll see what we can do.