Sections of a PuzzleScript file

A puzzlescript file is divided into the following sections.

Objects

Here's where your in-game objects are all declared. The simplest way is to give something a name and a color.

OBJECTS
=======      
Player P
Blue
If you do this, the player will be a blue square.

You can specify a sprite as a 5x5 grid as follows:

Player P
PINK YELLOW #000000    
.222.
.000.
22122
.222.
.2.2.

Which gives you this wee fella:

Object Names

The first line is the name of the object, and aliases too if you like. So the extra P on the line is another name for the Player object (and you can have as many aliases as you like). This is convenient for creating single characters needed for putting objects into a level, but you can get the same result in the Legend section if you prefer.

Colors

The second line is a list of colors. The available color names are as follows, but the exact shade of color is set according to the palette setting in the prelude.

  • black
  • white
  • lightgray/grey
  • gray/grey
  • darkgray/grey
  • red
  • darkred
  • lightred
  • brown
  • darkbrown
  • lightbrown
  • orange
  • yellow
  • green
  • darkgreen
  • lightgreen
  • blue
  • lightblue
  • darkblue
  • purple
  • pink
  • transparent

See this Color Chart for a display of the colors in the default palette. You can change the palette if you like.

Or you can use hex codes if you prefer.

The Grid

The third and following lines are rows of numeric digits making up the sprite grid (or they can be omitted, and then you just get a square). The dots represent transparency, and the numbers 0..9 index the colors in the second line, for as many colors as there are.

If ten colors really aren't enough, or perhaps you have an automated tool doing subtle shades, then you can use letters for up to another 26 colors. The letter 'a' or 'A' is color index 10, and so on.

In the simple case each line is sprite_size in length and there are sprite_size of them. This defaults to 5x5, but you can set it set to a different value in the prelude.

The sprite grid can be smaller or larger, and does not have to be square. It will be rendered with the bottom left-hand corner aligned with the tile. If it is larger, it will overflow and hide tiles above and to the right. You can use control this, see CollisionLayers.

Transforms

Following the sprite grid are one or more lines of object transforms. The transforms are executed in order, left to right, and modify the sprite grid as they do so. These are the things you can do.

copy:crate
The sprite grid is replaced by one taken from another object, in this case the crate object. Note:
  • If the object does not exist, the default square is used instead.
  • the copy: transform can be written on the first line, for compatibility. This usage is deprecated.
  • flip:right
    Mirrors the grid vertically, left <-> right. As expected, down mirrors the grid horizontally, up <-> down.

    The shorthands - and | do the same, horizontal and vertical.

    shift:down:3
    Shifts the pixels of the grid down 3, in a circular fashion. Pixels falling off the bottom reappear at the top. You can use negative numbers too.
    rot:up:right
    Rotates the grid so that what was up is now right. In this case, that would be a 90 degree rotation.
    translate:right:5
    Moves the grid across 5 pixels to the right. You can use negative numbers too.

    In each case of an absolute direction you can use the relative directions > < ^ v instead. This becomes important when used in conjunction with tags.

    Text Sprites PuzzleScript Next

    Instead of a sprite matrix, you can create an object that displays as a string of text. You can see it working in 333. Use it like this.

    s; purple; text: S
    t; orange; text: tea for two
    3; pink; text: 3
    4; pink; text: 4
    number8 scale: 0.5; green; text: 8
    

    These are the things you can do.

    text: tea for two
    The string of characters is trimmed and centred to fit in the cell. Text objects use the custom font, or Monospace fallback, rather than the built-in font.
    scale: 0.8
    The text is scaled, relative to 1.0.

    Canvas Sprites PuzzleScript Next

    For advanced users, a canvas sprite lets you draw just about anything. A canvas sprite consists of a sequence of instructions expressed as JSON, which can be vector drawing, text or symbols, shading and so on. You can see it working in Wriggle.

    A canvas sprite is defined by adding canvas:w,h to the first line after any objects and aliases. The width and height are optional, and default to 1. Here is an example of an object that is a grey blob.

    // this is a grey blob
    blob b canvas:2,1
    {"beginPath":[]}{"fillStyle":"#C0C0C0"}
    {"arc":[1.5,0.5,0.4,0,6.28]}
    {"fill":[]}
    

    This should be followed by lines of JSON objects, each with one name and one value. The name should be one of the CanvasRenderingContext2D properties or functions. If the name is a function it is invoked with the value, which is a (possibly empty) array containing the function arguments. Otherwise it is a property, and the value is assigned to that property.

    Alternatively the name may be !include in which case the argument is the name of another canvas object, and the JSON for that object is included.
    // this canvas object includes another
    {"!include":"man"}
    {"beginPath":[]}
    {"fillStyle":"white"}
    {"arc":[0.5,0.5,0.1,0,7]}
    {"fill":[]}
    

    Objects are scaled so that a size of 1.0 is one cell (or as defined by w and h). Angles are in radians.

    The object transforms copy:, translate, rot: and flip: behave as expected, with distances defined in sprite pixels. The shift: transform is not implemented.

    The test program is test/test_min_canvas.

    Notes.

    1. The canvas API uses named colours which are quite different from any of the PS pixel colours (eg "red" is not the same red). If you really need them to be the same, use hex format colours (e.g. #FFA500) which should always match.

    2. Canvas size units are grid cells and drawing instructions have their origin at top-left. So canvas:2,3 allows a sprite to be 6 grid cells, and {"rect":[0.01,0.01,1.98,1.98]} will draw a rectange just less than 2x2, relative to the top left corner. However, like pixel sprites the drawing is aligned with the bottom left corner, so that over-sized sprites extend up and right.

    3. All transforms use the sprite_size as the unit of measure, so translate:right:1 means 1 pixel to the right. Use a larger sprite_size to achieve more fine-grained positioning.

    4. Canvas sprites rotate around the centre of their canvas and are not realigned on the grid, while pixel sprites are realigned on the grid after rotation, anchored to the bottom-left corner. Use square canvas and sprite to minimise alignment issues.

    5. Watch out for applying transforms to copy: objects that already have transforms applied. Likewise, applying multiple transforms to a single canvas sprite may not yield the same expected result as the same list applied to a pixel sprite. Probably best to define a collection of transform-free base sprites and only apply transforms on the copies, but if in doubt, try it!

    6. All objects must be included in a collision layer, even partially-defined objects you only "!include" into later objects. Since these are never displayed, you can add all your include-only objects to the first (Background) layer.

    7. The Level Editor sprite pick-list currently displays canvas sprites without their transforms, so it can be hard to pick the right one. If you give sprites meaningful names and hover over a sprite to check its name before you click on it, this should help.

    8. JSON syntax error detection and reporting is very limited. If you see a magenta square, your JSON is badly formed, but often there is nothing to see except it doesn't work. Ask for help or look for existing examples.