# Module `occade` - A library for programming simple arcade games in occam-pi

A library for programming simple arcade games in occam-pi.

This library provides facilities for occam programmers similar to those available on microcomputers of the early 1980s: a fixed playfield that's displayed in the background (see `occade.load.playfield`), a number of moving sprites on top of it with collision detection (see `occade.start.sprite`), and event-based input (see `occade.start.input`). Unlike 1980s micros, you've got a 24-bit display and potentially thousands of sprites to play with.

Image files referenced below must either be in BMP format, or in any format supported by the `rasterio` module (e.g. PNG). Any areas coloured `OCCADE.TRANSPARENT.COLOUR` will appear transparent. Note, however, that collision detection is currently done simply by using the bounding boxes of the sprites -- so don't leave big borders around your images unless you want them to be really easy to hit!

Font image files, used for text rendering, must contain a 16x16 rectangular grid of characters. The font size will be computed automatically from the image size.

There are some keypresses that all Occade programs will recognise regardless of whether you've written any input code:

- Alt-Return: toggles full-screen mode on platforms that support it.
- Alt-Backspace: cause the program to `STOP` immediately.

To use this library:

    #INCLUDE "occade.module"

## Index

- Channel type `OCCADE` - Channel bundle for communicating with Occade
- Record `OCCADE.COLLISION` - Reports of collisions between sprites
  - Variable `id` - ID of the other sprite
  - Variable `w`, `h` - Width and height of the other sprite
  - Variable `x`, `y` - Position of the other sprite
- Channel type `OCCADE.INPUT` - Channel bundle for carrying input events
  - Variable `events!` - Input events
  - Variable `req?` - Commands to the event filter
  - Variable `resp!` - Responses from the event filter
- Protocol `OCCADE.INPUT.REQ` - Commands that can be sent to the event filter
  - Tag `enable` - Pick the types of events you're interested in
  - Tag `quit` - Close this event filter
- Protocol `OCCADE.INPUT.RESP` - Responses from the event filter
- Record `OCCADE.PARAMS` - Startup parameters for Occade
  - Variable `depth` - Pixel depth in bits
  - Variable `width`, `height` - Screen width and height in pixels
- Channel type `OCCADE.SPRITE` - Channel bundle for controlling sprites
  - Variable `collisions!` - Reports of collisions with other sprites
  - Variable `req?` - Commands to the sprite
  - Variable `resp!` - Responses from the sprite
- Protocol `OCCADE.SPRITE.REQ` - Commands that can be sent to the sprite
  - Tag `collisions` - Enable or disable collision reports
  - Tag `get.position` - Get the position of the sprite
  - Tag `get.size` - Get the size of the sprite
  - Tag `load.image` - Set the sprite's image from a file
  - Tag `load.raster` - Set the sprite's image from a raster
  - Tag `load.text` - Set the sprite's image by rendering text
  - Tag `move` - Set the sprite's position
  - Tag `quit` - Make the sprite exit
  - Tag `visible` - Show or hide the sprite
- Protocol `OCCADE.SPRITE.RESP` - Responses from the sprite
  - Tag `get.position` - The position of the sprite
  - Tag `get.size` - The size of the sprite
  - Tag `return.raster` - Returning a used raster
- Constant `OCCADE.TRANSPARENT.COLOUR` - The colour in images that is considered transparent when drawing
- Group `PRI` - Process priorities * Priority for buffer processes
  - Constant `PRI.DISPLAY` - Priority for display server
  - Constant `PRI.INPUT` - Priority for input filters
  - Constant `PRI.SPRITES` - Priority for sprite servers
  - Constant `PRI.USER` - Priority for user processes
- Process `occade.append.int` - Append a number to a string
- Process `occade.append.string` - Append a string to a string
- Function `occade.clamp.int` - Limit an integer to a particular range
- Constant `occade.default.params` - Default parameters for Occade
- Process `occade.delay` - Wait for a period of time
- Process `occade.draw.playfield` - Draw a raster image onto the playfield at the given position
- Process `occade.finish.input` - Make an input filter quit, and consume any remaining input events
- Process `occade.finish.sprite` - Make a sprite quit, and consume any remaining collision reports
- Process `occade.load.playfield` - Load an image onto the playfield at the given position
- Process `occade.random` - Generate a random integer
- Process `occade.start` - Start up the display and return a handle for communicating with it
- Process `occade.start.input` - Start up a new input filter and return its control interface
- Process `occade.start.sprite` - Start up a new sprite and return its control interface
- Process `occade.write` - Write a string to stderr
- Process `occade.write.int` - Write an integer to stderr

## Declarations

### `occade.occ`:34Group `PRI`

``

Process priorities * Priority for buffer processes.

### `occade.occ`:38Constant `PRI.DISPLAY`

`VAL INT PRI.DISPLAY`

Priority for display server.

### `occade.occ`:40Constant `PRI.SPRITES`

`VAL INT PRI.SPRITES`

Priority for sprite servers.

### `occade.occ`:42Constant `PRI.INPUT`

`VAL INT PRI.INPUT`

Priority for input filters.

### `occade.occ`:44Constant `PRI.USER`

`VAL INT PRI.USER`

Priority for user processes.

### `occade.occ`:52Process `occade.write`

`PROC occade.write (VAL []BYTE s)`

Write a string to stderr. This uses direct filelib calls rather than the TLP channel interface, so it can be used anywhere in your code, which may be useful for debugging.

#### Parameters:

`VAL []BYTE` | `s` | String to print

### `occade.occ`:65Process `occade.write.int`

`PROC occade.write.int (VAL INT n)`

Write an integer to stderr. See `occade.write`.

#### Parameters:

`VAL INT` | `n` | Integer to print

### `occade.occ`:122Function `occade.clamp.int`

`INT FUNCTION occade.clamp.int (VAL INT in, left, width)`

Limit an integer to a particular range. For example, if you call this with `left = 3` and `width = 3`, then the output value will be in the range `3 .. 5`. You can use this with a sprite's coordinates to limit it to a particular part of the screen.

#### Parameters:

`VAL INT` | `in` | Input value
`VAL INT` | `left` | The lowest value in the range
`VAL INT` | `width` | The width of the range

### `occade.occ`:159Process `occade.append.string`

`PROC occade.append.string (MOBILE []BYTE out, VAL []BYTE in)`

Append a string to a string.

#### Parameters:

`MOBILE []BYTE` | `out` | String to append to.
`VAL []BYTE` | `in` | String that will be appended to `out`.

### `occade.occ`:173Process `occade.append.int`

`PROC occade.append.int (MOBILE []BYTE out, VAL INT n)`

Append a number to a string.

#### Parameters:

`MOBILE []BYTE` | `out` | String to which the decimal representation of `n` will be appended.
`VAL INT` | `n` | Integer to format.

### `occade.occ`:838Process `occade.start`

`PROC occade.start (RESULT SHARED OCCADE! handle, VAL OCCADE.PARAMS params, VAL []BYTE app.name)`

Start up the display and return a handle for communicating with it. This must be the first call your program makes into the library.

#### Parameters:

`RESULT SHARED OCCADE!` | `handle` | Occade handle, returned for other library PROCs to use
`VAL OCCADE.PARAMS` | `params` | Display parameters (see `OCCADE.PARAMS`)
`VAL []BYTE` | `app.name` | The application name

### `occade.occ`:855Process `occade.load.playfield`

`PROC occade.load.playfield (SHARED OCCADE! handle, VAL []BYTE name, VAL INT x, y)`

Load an image onto the playfield at the given position. This is intended for static background images; if you want things to overlap or move around, use sprites instead.

#### Parameters:

`SHARED OCCADE!` | `handle` | Occade handle
`VAL []BYTE` | `name` | Image filename
`VAL INT` | `x`, `y` | Top left corner coordinates

### `occade.occ`:866Process `occade.draw.playfield`

`PROC occade.draw.playfield (SHARED OCCADE! handle, RASTER raster, VAL INT x, y)`

Draw a raster image onto the playfield at the given position.

#### Parameters:

`SHARED OCCADE!` | `handle` | Occade handle
`RASTER` | `raster` | Raster image
`VAL INT` | `x`, `y` | Top left corner coordinates

### `occade.occ`:1004Process `occade.start.sprite`

`PROC occade.start.sprite (SHARED OCCADE! handle, RESULT OCCADE.SPRITE! control, VAL INT id)`

Start up a new sprite and return its control interface. Sprites are graphical objects that can move around and change appearance; you should use them for any moving or changing graphical elements.

Sprites can report collisions with other sprites. So that you know which sprites have run into each other, you must give your sprites ID numbers if you want them to partiticipate in collision detection. For example, if you give your player's missile sprites the ID number 5, then you know that whenever an enemy collides with ID 5 it's been hit by a missile. (You can give more than one sprite the same ID.)

If you've got a sprite where you don't care about collisions -- for example, one that's displaying the number of lives the player has left -- then pass `-1` as the ID and Occade won't bother doing collision detection on it.

Sprites are invisible with no image loaded by default; you must set up your sprite and make it visible before you can see it on the screen.

#### Parameters:

`SHARED OCCADE!` | `handle` | Occade handle
`RESULT OCCADE.SPRITE!` | `control` | Control interface for the sprite
`VAL INT` | `id` | ID number for the sprite. If this is negative, the sprite won't participate in collision detection.

### `occade.occ`:1015Process `occade.finish.sprite`

`PROC occade.finish.sprite (OCCADE.SPRITE! sprite)`

Make a sprite quit, and consume any remaining collision reports.

### `occade.occ`:1109Process `occade.start.input`

`PROC occade.start.input (SHARED OCCADE! handle, RESULT OCCADE.INPUT! control)`

Start up a new input filter and return its control interface. Input filters look at all the events coming in to the program and pick out the ones you've told them you're interested in. You can have multiple input filters listening for the same or different events; for example, in a two-player game you might want to have an input filter for each player.

Filters don't report any events by default; you must enable the types of event you're interested in.

#### Parameters:

`SHARED OCCADE!` | `handle` | Occade handle
`RESULT OCCADE.INPUT!` | `control` | Control interface for the filter

### `occade.occ`:1119Process `occade.finish.input`

`PROC occade.finish.input (OCCADE.INPUT! input)`

Make an input filter quit, and consume any remaining input events.

### `occade.occ`:1140Process `occade.random`

`PROC occade.random (SHARED OCCADE! handle, VAL INT max, RESULT INT n)`

Generate a random integer.

#### Parameters:

`SHARED OCCADE!` | `handle` | Occade handle
`VAL INT` | `max` | Limit
`RESULT INT` | `n` | Number generated, in the range `0` to `max - 1`.

### `occade.occ`:1151Process `occade.delay`

`PROC occade.delay (VAL INT time)`

Wait for a period of time.

#### Parameters:

`VAL INT` | `time` | The delay in microseconds

### `occade.inc`:59Constant `OCCADE.TRANSPARENT.COLOUR`

`VAL [3]BYTE OCCADE.TRANSPARENT.COLOUR`

The colour in images that is considered transparent when drawing. RGB `#EE66EE`, which is a sort of pinkish purple.

### `occade.inc`:66Record `OCCADE.PARAMS`

`DATA TYPE OCCADE.PARAMS`

Startup parameters for Occade. You should initialise this from `occade.default.params` and then just change the fields you want.

### `occade.inc`:68Variable `width`, `height`

`INT`

Screen width and height in pixels.

### `occade.inc`:69Variable `depth`

`INT`

Pixel depth in bits.

### `occade.inc`:73Constant `occade.default.params`

`VAL OCCADE.PARAMS occade.default.params`

Default parameters for Occade.

### `occade.inc`:100Record `OCCADE.COLLISION`

`DATA TYPE OCCADE.COLLISION`

Reports of collisions between sprites.

### `occade.inc`:102Variable `id`

`INT`

ID of the other sprite

### `occade.inc`:103Variable `x`, `y`

`INT`

Position of the other sprite

### `occade.inc`:104Variable `w`, `h`

`INT`

Width and height of the other sprite

### `occade.inc`:108Protocol `OCCADE.SPRITE.REQ`

`PROTOCOL OCCADE.SPRITE.REQ`

Commands that can be sent to the sprite.

### `occade.inc`:112Tag `load.image`

`load.image; MOBILE []BYTE`

Set the sprite's image from a file.

#### Parameters:

`MOBILE []BYTE` | `name` | Image filename

### `occade.inc`:115Tag `load.raster`

`load.raster; RASTER`

Set the sprite's image from a raster. Returns `return.raster`.

#### Parameters:

`RASTER` | `raster` | Raster image

### `occade.inc`:119Tag `load.text`

`load.text; MOBILE []BYTE; MOBILE []BYTE`

Set the sprite's image by rendering text.

#### Parameters:

`MOBILE []BYTE` | `text` | String to render
`MOBILE []BYTE` | `font` | Font image filename

### `occade.inc`:125Tag `move`

`move; INT; INT; BOOL`

Set the sprite's position.

#### Parameters:

`INT` | `x`, `y` | Coordinates
`BOOL` | `centre` | Whether to centre the sprite on these coordinates. If this is `FALSE`, the coordinates are the top left corner of the sprite; if `TRUE`, they are the centre of the sprite.

### `occade.inc`:127Tag `visible`

`visible; BOOL`

Show or hide the sprite.

### `occade.inc`:129Tag `collisions`

`collisions; BOOL`

Enable or disable collision reports.

### `occade.inc`:131Tag `get.size`

`get.size`

Get the size of the sprite. Returns `get.size`.

### `occade.inc`:133Tag `get.position`

`get.position`

Get the position of the sprite. Returns `get.position`.

### `occade.inc`:137Tag `quit`

`quit`

Make the sprite exit. Use `occade.finish.input` rather than sending this by hand, since that'll mop up any remaining collision reports too.

### `occade.inc`:141Protocol `OCCADE.SPRITE.RESP`

`PROTOCOL OCCADE.SPRITE.RESP`

Responses from the sprite.

### `occade.inc`:144Tag `return.raster`

`return.raster; RASTER`

Returning a used raster.

### `occade.inc`:147Tag `get.size`

`get.size; INT; INT`

The size of the sprite.

#### Parameters:

`INT` | `w`, `h` | Width and height in pixels

### `occade.inc`:151Tag `get.position`

`get.position; INT; INT; BOOL`

The position of the sprite.

#### Parameters:

`INT` | `x`, `y` | Coordinates
`BOOL` | `centre` | Whether the sprite is centred on those coordinates

### `occade.inc`:155Channel type `OCCADE.SPRITE`

`CHAN TYPE OCCADE.SPRITE`

Channel bundle for controlling sprites.

### `occade.inc`:158Variable `req?`

`CHAN OCCADE.SPRITE.REQ`

Commands to the sprite.

### `occade.inc`:160Variable `resp!`

`CHAN OCCADE.SPRITE.RESP`

Responses from the sprite.

### `occade.inc`:177Variable `collisions!`

`CHAN OCCADE.COLLISION`

Reports of collisions with other sprites. You'll only get messages on this channel if you've enabled them by sending the `collisions; TRUE` command first.

Messages can arrive at any time; you must be prepared to handle them interleaved with communications on other channels, and you must be prepared to handle some collisions arriving after you disable collisions or tell the sprite to exit. (See `occade.finish.input`.)

This channel comes from a limited-capacity overwriting buffer, so you will lose events (rather than deadlocking the system) if you persist in ignoring it.

Each sprite will only be told about each collision once -- once two objects are in contact with each other, no more collision reports will be sent about that pair of objects until they move apart again.

### `occade.inc`:183Protocol `OCCADE.INPUT.REQ`

`PROTOCOL OCCADE.INPUT.REQ`

Commands that can be sent to the event filter

### `occade.inc`:187Tag `enable`

`enable; INT`

Pick the types of events you're interested in. This should be the bitwise OR of values from `RASTER.ET`.

### `occade.inc`:191Tag `quit`

`quit`

Close this event filter. Use `occade.finish.input` rather than sending this by hand, since that'll mop up any remaining input events too.

### `occade.inc`:195Protocol `OCCADE.INPUT.RESP`

`PROTOCOL OCCADE.INPUT.RESP`

Responses from the event filter.

### `occade.inc`:200Channel type `OCCADE.INPUT`

`CHAN TYPE OCCADE.INPUT`

Channel bundle for carrying input events.

### `occade.inc`:203Variable `req?`

`CHAN OCCADE.INPUT.REQ`

Commands to the event filter.

### `occade.inc`:205Variable `resp!`

`CHAN OCCADE.INPUT.RESP`

Responses from the event filter.

### `occade.inc`:210Variable `events!`

`CHAN RASTER.EVENT`

Input events. You won't receive any events until you turn some on using the `enable; N` command. Once you've done that, events can arrive at any time.

### `occade.inc`:292Channel type `OCCADE`

`CHAN TYPE OCCADE`

Channel bundle for communicating with Occade. You shouldn't use the channels inside this in your own code; you can treat the shared client end of this as an opaque "handle" for Occade PROCs to use.