/Rose

A programming language for animated turtle graphics

Primary LanguageC++

Rose - a programming language for temporal turtle graphics


INTRODUCTION

A Rose program produces an animation drawn by a number of "turtles"
moving around on a canvas. Each turtle has the following state:

- Position (x and y)
- Direction
- Pen size
- Color index, called "tint"
- Random number generator state.

Unless specific otherwise, all numeric values in Rose are 16.16 bits
fixed-point values.

The position and direction are available as global variables x, y and dir.


SYNTAX

Rose is whitespace-agnostic: line breaks can be inserted or omitted anywhere
between tokens.

Comments start with # and extend to the end of the line.

Just for the fun of it, and because I enjoy using a thesaurus, all keywords
in Rose have four letters.

A Rose program starts with an optional size directive, specifying the width
and height (respectively) in pixels:

- size <expression> <expression>

If the size is not specified, the resolution will be 352x280 (full overscan).

Next is an optional layer configuration, specifying the number of layers and
the number of colors in each layer (respectively):

- form <expression> <expression>

The tints are distributed over the layers, so if, for instance, there are 4
colors per layer, tints 0-3 are in the first (backmost) layer, tints 4-7 are
in the next layer and so on.

If no layer configuration is specified, there is 1 layer with 4 colors.

After this comes the color script, which has the syntax:

- plan <event>*

where <event> is one of:

- wait <expression>
  Wait a number of frames. The expression cannot contain variables.
- <tint>:<color>
  Set the given tint (integer) to the given color (three-digit hex value).

The first tint in each layer except the first is transparent, showing the
layers behind it. Thus, the colors for these tints are ignored.

The rest of the program is a sequence of procedures. A procedure has the
syntax:

- proc <name> <param>* <statement>*

where <name> and <param> are identifiers, and <statement> is one of:

- move <expression>
  Move forward a number of pixels.
- jump <expression> <expression>
  Jump to a pixel coordinate position.
- turn <expression>
  Turn a number of 256-on-a-circle degrees clockwise.
- face <expression>
  Turn to a number of 256-on-a-circle degrees clockwise from horizontal right.
- size <expression>
  Set pen radius in pixels (rounded to nearest integer-and-a-half).
- tint <expression>
  Set the current tint (rounded down to an integer).
- draw
  Draw a circular dot at the current position.
- plot
  Draw a square dot at the current position.
- wait <expression>
  Wait a number of frames.
- fork <procedure> <expression>*
  Branch off a new turtle with a copy of this turtle's state, running the
  given procedure with the given arguments. The old turtle continues executing
  the rest of the current procedure in parallel.
- temp <variable> = <expression>
  Assign a value to a local variable.
- seed <expression>
  Seed the random number generator.
- when <expression> <statement>* done
  Run the block of statements if the expression evaluates to non-zero.
- when <expression> <statement>* else <statement>* done
  Run the first block of statements if the expression evaluates to non-zero,
  or the second block of statements otherwise.
- defy
  Suppress all warnings for the current source line.

An <expression> is one of:

- <digit>+[.<digit>+]
  Constant value.
- $<hexdigit>+
  Constant value in hexadecimal. The value is used directly as the
  32-bit fixed-point representation, i.e. the last four digits are
  implicitly fractional.
- <name>
  Procedure or value of parameter, temporary variable or global variable.
- <expression> op <expression>
  Operation, where op is one of (*, /, +, -, ==, !=, <, <=, >, >=, &, |).
  Operator semantics and precedence are as in C, except * and / which do
  fixed-point adjustment to match fixed-point multiplication and division.
- ~ <expression>
  Negate value. Used instead of - to enable airy, delimiter-sparse syntax.
- sine ( <expression> )
  Computes the sine of 2pi * argument.
- rand
  Produces a random number between 0 and 1.
- <expression> ? <expression> : <expression>
  If the first expression evaulates to non-zero, evaluate the second
  expression, otherwise evaluate the third expression.
- ( <expression> )
  For grouping.

Procedures can be assigned to temporaries and passed as arguments to
procedures. The procedure part of a fork statement can refer directly to
a procedure or to a parameter or local variable containing a procedure.

And just to mention it one more time, because this could be a common
pitfall: Remember to use ~ and not - for negation, including for
writing negative numbers!


THE VISUALIZER

Run the visualizer with these arguments:

rose <filename> [<scale>] [<framerate> [<music>]]

where <filename> is the name of a file containing a Rose program,
<scale> is a scale factor for the visualizer window (with an 'x' in
front, i.e. 'x3' for a scaling factor of 3), <framerate> is the frame
rate in frames per second (default 50) and <music> is a 16-bit stereo
WAV file containing the music to play to the animation.

The total number of frames for the animation will be inferred from
the length of the music, or set to 10000 if no music is specified.

The visualizer will continuously monitor the file and reload it whenever
its modification time changes.

Keyboard shortcuts:
- SPACE: start/stop animation.
- RIGHT/LEFT: Step one frame forward/backward.
- PGDOWN/PGUP: Step 50 frames forward/backward.
- BACKSPACE: Go back to frame animation was last started.
- HOME: Go to first frame.
- TAB: Toggle statistics overlay.
- ESCAPE: Quit the visualizer.

Clicking or holding the left mouse button sets the time proportionally to
the mouse X position within the window, up to the total number of frames.