doc.txt

Allegro Graphics Library

_Allegro Graphics_ Library
===============

By Jon Rafkind (jon at rafkind dot com)

Keywords: _graphics_

Introduction
============

This library is a set of bindings to the Allegro graphics library.
Allegro is typically thought of as a game library, implementing all the
useful features a game is composed of: graphics, sound, and keyboard/mouse input.
For more on Allegro, see the following websites:
http://alleg.sf.net
http://www.allegro.cc/manual/

For immediate gratification see the examples chapter at the end.

Each "feature" is split into its own module:
Graphics:
   (require (planet "image.ss" ("kazzmir" "allegro.plt" 1 0)))

Keyboard:
   (require (planet "keyboard.ss" ("kazzmir" "allegro.plt" 1 0)))

Mouse:
   (require (planet "mouse.ss" ("kazzmir" "allegro.plt" 1 0)))

Sound:
   (require (planet "sound.ss" ("kazzmir" "allegro.plt" 1 0)))

Utilities:
   (require (planet "util.ss" ("kazzmir" "allegro.plt" 1 0)))

Most of these modules export common function names so its usually best to
import them with a prefix, i.e:

   (require (prefix keyboard- (planet "keyboard.ss" ("kazzmir" "allegro.plt" 1
   0))))

Using any of the Allegro subsystems require that Allegro be set up properly.
The utilities module is just for that purpose.

On Linux, Allegro is built from source so there will be a considerable delay
when installing the Allegro planet archive.

_Utilies_
=========

> (easy-init width height depth [mode]) -> void

Set up the Allegro system. This function creates a graphics context, installs
the keyboard, the mouse, and sound.

  width - Width of the graphics window
  height - Height of the graphics window
  depth - Bits per pixel, otherwise known as color depth
  mode - Optional argument that defines whether to use fullscreen or windowed.
  The default is windowed mode.

  Typical width/height pairs are:
  320 240
  640 480
  800 600
  1024 768
  1280 960

  Typical color depths are:
  8
  15
  16
  24
  32

  Possible modes are:
  'TEXT - Destroys the graphics window if it exists
  'AUTO - Let Allegro choose the proper graphics mode
  'FULLSCREEN - Fullscreen mode
  'WINDOWED - Windowed mode
  'SAFE - Allegro will choose a graphics mode. This mode may ignore the
  width, height and color depths but will almost always set some graphics
  mode.

  A typical use of this function is:
  (easy-init 640 480 16)

> (easy-exit) -> void

Shuts down the Allegro system. Call this method at the end of your program.

> (game-loop logic-func draw-func delay) -> void

This method implements the de-facto game loop. In short the logic-func will
update the environment after `delay' amount of time has passed. After the
logic-func is run, the draw-func is run which will display the environment
onto the graphics context.

  logic-func :: (lambda () body)
  If logic-func returns #f, game-loop will exit.

  draw-func :: (lambda (buffer) body)
  buffer is an image, as defined in image.ss, and is used as a double buffer
  to make drawing graphics look smooth. Buffer is not the screen, but rather a
  section of memory that you are free to do as you wish with. The game-loop
  will copy buffer to the screen immediately following this function.

  delay :: int
  Amount of time to wait in between logic updates. If there is enough time,
  sleep will be called so that cpu cycles are not wasted. You can play with
  this number until you feel comfortable or you can use frames-per-second to
  calculate a reasonable time.

> (frames-per-second frames) -> int

Calculate an amount of time to delay between logic cycles in game-loop. This
function does exactly what it sounds like: (frames-per-second 30) will run 30
logic/draw cycles per second.

_Graphics_
==========

> (screen) -> image

Predefined image that represents the graphics context currently open. All the
functions defined below also have a corresponding -screen function which
operates directly on this variable. For example:

(line (screen) 5 5 10 10 (color 64 0 0)) ;; Draws on the screen
(line-screen 5 5 10 10 (color 64 0 0)) ;; Does the same thing

(copy (screen) my-image) ;; Copy a buffer onto the screen
(copy-screen my-image) ;; Same thing

> (create width height) -> image

Create a graphics buffer in memory with the dimensions provided.
  width - Width of buffer. Should be > 0
  height - Height of buffer. Should be > 0

If there is not enough available memory width/height #f will be returned.

> (create-from-file filename) -> image

Load `filename' and copy it into a graphics buffer. This buffer is safe to
draw on. Allegro will guess at the filetype and can be one of the following:
  .bmp
  .pcx
  .lbm
  .tga

Extensions to support .jpg and .png exist for Allegro and will be added to
this module at some point.

> (color red green blue) -> int

Creates a color that can be used with all Allegro functions. The
representation of the color will vary depending on the current color depth.
  0 <= red <= 255
  0 <= green <= 255
  0 <= blue <= 255

In all truecolor modes( 15, 16, 24, 32 ) the following hold:
(color 0 0 0) = black
(color 255 255 255) = white
(color 255 0 255) = magic pink, the masking color

> (line image x1 y1 x2 y2 color) -> void

Draw a line from x1,y1 to x2,y2 on image using `color'

> (circle image x y radius color) -> void

Draw a hollow circle onto image at x,y with radius

> (circle-fill image x y radius color) -> void

Draw a filled circle onto image at x,y with radius

> (rectangle image x1 y1 x2 y2 color) -> void

Draw a hollow rectangle onto image from x1, y1 to x2, y2. x1,y1 should be the
opposite corner from x2,y2 but there is no restriction on which pair of points
is which corner.

> (rectangle-fill image x1 y1 x2 y2 color) -> void

Like rectangle but filled

> (putpixel image x y color) -> void

Draw a single pixel onto image at x,y

> (getpixel image x y) -> color :: int

Read a pixel from an image. The value returned can be used in all situations
that (color) can be used.

(putpixel image 5 5 (color 64 0 0))
(eq? (color 64 0 0) (getpixel image 5 5))

Would be #t

> (print image x y color background-color message) -> void

Print some text onto image starting at x, y. color is the foreground color
while background-color is for the background. If background-color is -1 the
message will be printed without obscuring the background its printed on.

> (clear image [color]) -> void

Set every pixel in the image to a color. color defaults to black, (color 0 0
0).

> (copy image1 image2 [x y])

Copy image2 onto image1. x,y specify the upper left corner of image1 to copy
to and both default to 0.

_Keyboard_
==========

> (keypressed? key) -> boolean

Returns true if the key is being pressed on the keyboard. Available keys are:
    'A 'B 'C 'D 'E 'F 'G 'H 'I 'J 'K
    'L 'M 'N 'O 'P 'Q 'R 'S 'T 'U
    'V 'W 'X 'Y 'Z '0 '1 '2 '3 '4
    '5 '6 '7 '8 '9 'PAD-0 'PAD-1 'PAD-2
    'PAD-3 'PAD-4 'PAD-5 'PAD-6 'PAD-7 'PAD-8
    'PAD-9 'F1 'F2 'F3 'F4 'F5 'F6 'F7
    'F8 'F9 'F10 'F11 'F12 'ESC 'TILDE
    'MINUS 'EQUALS 'BACKSPACE 'TAB 'OPENBRACE
    'CLOSEBRACE 'ENTER 'COLON 'QUOTE 'BACKSLASH
    'BACKSLASH2 'COMMA 'STOP 'SLASH 'SPACE 'INSERT
    'DEL 'HOME 'END 'PGUP 'PGDN 'LEFT 'RIGHT
    'UP 'DOWN 'SLASH_PAD 'ASTERISK 'MINUS_PAD
    'PLUS_PAD 'DEL_PAD 'ENTER_PAD 'PRTSCR 'PAUSE
    'ABNT_C1 'YEN 'KANA 'CONVERT 'NOCONVERT 'AT
    'CIRCUMFLEX 'COLON2 'KANJI
    'EQUALS_PAD  ;; MacOS X
    'BACKQUOTE  ;; MacOS X
    'SEMICOLON  ;; MacOS X
    'COMMAND  ;; MacOS X
    'UNKNOWN1
    'UNKNOWN2
    'UNKNOWN3
    'UNKNOWN4
    'UNKNOWN5
    'UNKNOWN6
    'UNKNOWN7
    'UNKNOWN8
    'MODIFIERS
    'LSHIFT
    'RSHIFT
    'LCONTROL
    'RCONTROL
    'ALT
    'ALTGR
    'LWIN
    'RWIN
    'MENU
    'SCRLOCK
    'NUMLOCK
    'CAPSLOCK

_Mouse_
=======

> (left-click?) -> boolean

Returns #t if the left button on the mouse was clicked, false otherwise.

> (right-click?) -> boolean

Returns #t if the right button on the mouse was clicked, false otherwise.

> (x) -> int

Returns the current x position of the mouse on the graphics context.

> (y) -> int

Returns the current y position of the mouse on the graphics context.

> (get-mickeys) -> (values x y)

Returns pair of values, x/y, that represent how far the mouse has just moved.

_Sound_
=======

> (load-sound filename) -> sound

Create a sound object from a filename. Available extensions for filenames are
  .wav
  .voc

> (play-sound sound [volume] [pan] [frequency]) -> void

Plays a sound.
  sound - sound object
  volume - 0 <= volume <= 255
  pan - 0 <= pan <= 255. Pan determines which speaker the sound will come out
  of. 0 is left, 255 is right. 128 is in the middle.
  frequency - What speed to play the sound at. 1000 is normal, less is slower,
  and more is faster.

> (play-sound-looped sound [volume] [pan] [frequency]) -> void

Exactly like play-sound except the sound will play forever.

_Examples_
==========

Some examples that demonstrate some of what Allegro can do are in the
examples.ss module. Use them like so:

(require (planet "examples.ss" ("kazzmir" "allegro.plt" 1 0)))
(exblend-run) ;; Shows Allegros ability to blend images
(exflame-run) ;; Real-time fire.
(exhello-run) ;; Prints hello world
(piano-run) ;; Plays sounds when you hover over a key with the mouse
(wormhole-run) ;; Pseudo-3d illusion of flying through a colored wormhole
(xquest-run) ;; A game wherein you have to move the disk with your mouse and
collect the diamond like things. Left click to shoot.

_Step by step_
==============

The following is a short tutorial on using Allegro. At each step I will add
some code and explain what it does.

1. Set up Allegro and quit. Pretty self explanatory.

;; this require will be used throughout
(require (planet "util.ss" ("kazzmir" "allegro.plt" 1 0)))
(require (planet "keyboard.ss" ("kazzmir" "allegro.plt" 1 0)))
(require (prefix image- (planet "image.ss" ("kazzmir" "allegro.plt" 1 0))))
(require (prefix mouse- (planet "mouse.ss" ("kazzmir" "allegro.plt" 1 0))))

(define (run)
  (easy-init 640 480 16) ;; set up Allegro. Use 640x480 for window demensions
  and 16 bits per pixel
  (easy-exit)) ;; Just quit Allegro

2. Print hello world to the screen and quit when ESC is pressed.

(define (run)
  (easy-init 640 480 16)
  (game-loop
     (lambda ()
        (keypressed? 'ESC))
     (lambda (buffer)
        (image-print buffer 50 50 (image-color 255 255 255) -1 "Hello world"))
     (frames-per-second 30))
  (easy-exit))

3. Print hello world wherever the mouse is.

(define (run)
  (easy-init 640 480 16)
  (game-loop
     (lambda ()
        (keypressed? 'ESC))
     (lambda (buffer)
        (let ((x (mouse-x))
	      (y (mouse-y)))
	 (image-print buffer x y (image-color 255 255 255) -1 "Hello world")))
     (frames-per-second 30))
  (easy-exit))

4. Load a bitmap and show it where the mouse is.

(define (run)
  (easy-init 640 480 16)
  (let ((my-image (image-load "myimage.bmp")))
    (game-loop
      (lambda ()
        (keypressed? 'ESC))
      (lambda (buffer)
        (let ((x (mouse-x))
	      (y (mouse-y)))
	 (image-copy buffer my-image x y)))
     (frames-per-second 30))
  (easy-exit))