summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Thompson <dthompson2@worcester.edu>2014-12-13 13:31:57 -0500
committerDavid Thompson <dthompson2@worcester.edu>2014-12-13 13:31:57 -0500
commitcd56361421ff460768fbe4e9eaf1080a5507c5c3 (patch)
tree29789f97ede43cfbee8180626c1f297b740a501a
parentedd5b8a2b52744cbe696cd9555757bbed00817b1 (diff)
docs: Add half-written manual.
* doc/game.texi: Delete. * doc/api/init.texi: New file. * doc/api/input.texi: Likewise. * doc/api/math.texi: Likewise. * doc/api/rendering.texi: Likewise. * doc/api/time.texi: Likewise. * doc/api/utils.texi: Likewise. * doc/sly.texi: Add API reference. * doc/Makefile.am (sly_TEXINFOS): Add new files.
-rw-r--r--doc/Makefile.am7
-rw-r--r--doc/api/init.texi13
-rw-r--r--doc/api/input.texi21
-rw-r--r--doc/api/math.texi672
-rw-r--r--doc/api/rendering.texi48
-rw-r--r--doc/api/time.texi362
-rw-r--r--doc/api/utils.texi29
-rw-r--r--doc/game.texi118
-rw-r--r--doc/sly.texi34
9 files changed, 1183 insertions, 121 deletions
diff --git a/doc/Makefile.am b/doc/Makefile.am
index b26a64e..d2b6d5f 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -4,4 +4,9 @@ info_TEXINFOS = sly.texi
sly_TEXINFOS = \
fdl.texi \
- api/signals.texi
+ api/init.texi \
+ api/math.texi \
+ api/time.texi \
+ api/input.texi \
+ api/rendering.texi \
+ api/utils.texi
diff --git a/doc/api/init.texi b/doc/api/init.texi
new file mode 100644
index 0000000..0d46dae
--- /dev/null
+++ b/doc/api/init.texi
@@ -0,0 +1,13 @@
+@node Booting
+@section Booting
+
+@menu
+* Window Creation:: Opening a window.
+* The Game Loop:: The core of the engine.
+@end menu
+
+@node Window Creation
+@subsection Window Creation
+
+@node The Game Loop
+@subsection The Game Loop
diff --git a/doc/api/input.texi b/doc/api/input.texi
new file mode 100644
index 0000000..ad83b1e
--- /dev/null
+++ b/doc/api/input.texi
@@ -0,0 +1,21 @@
+@node Input
+@section Input
+
+Sly can handle user input from a keyboard, mouse, or joystick. The
+input modules expose signals that represent various input
+events (@pxref{Signals}).
+
+@menu
+* Keyboard:: Clack clack.
+* Mouse:: Exercise the rodent.
+* Joystick:: Wee!
+@end menu
+
+@node Keyboard
+@subsection Keyboard
+
+@node Mouse
+@subsection Mouse
+
+@node Joystick
+@subsection Joystick
diff --git a/doc/api/math.texi b/doc/api/math.texi
new file mode 100644
index 0000000..8102e04
--- /dev/null
+++ b/doc/api/math.texi
@@ -0,0 +1,672 @@
+@node Math
+@section Math
+
+Modeling a virtual world requires a good dose of linear algebra,
+trigonometry, and calculus. Sly comes with modules for 2D/3D/4D
+vector math, trigonometry, axis-aligned bounding boxes, quaternions,
+4x4 transformation matrices, and interpolation.
+
+@menu
+* Vectors:: 2D/3D/4D vectors.
+* Rectangles:: Axis-aligned bounding boxes.
+* Transforms:: 4x4 transformation matrices.
+* Tweens:: Interpolation between two values.
+* Quaternions:: Representing rotations.
+* Miscellaneous:: Other useful variables and procedures.
+@end menu
+
+@node Vectors
+@subsection Vectors
+
+@example
+(use-modules (sly math vector))
+@end example
+
+Not to be confused with Guile's vector data structure, Sly provides
+dedicated data types for 2D, 3D, and 4D vectors in the mathematical
+sense. Vector procedures are polymorphic, and will work with any
+dimensionality that the operation supports. In some cases, such as
+@code{v+}, @code{v-}, and @code{v*}, scalar values may be passed as
+well.
+
+The @code{<vector2>}, @code{<vector3>}, and @code{<vector4>} type
+descriptors have been exposed for use with Guile's @code{(ice-9
+match)} pattern matching module.
+
+@defvr {Record Type} <vector2>
+2D vector data type with fields @code{x} and @code{y}, in that order.
+@end defvr
+
+@defvr {Record Type} <vector3>
+3D vector data type with fields @code{x}, @code{y}, and @code{z}, in
+that order.
+@end defvr
+
+@defvr {Record Type} <vector4>
+4D vector data type with fields @code{x}, @code{y}, @code{z} and
+@code{w}, in that order.
+@end defvr
+
+@deffn {Scheme Syntax} vector2 @var{x} @var{y}
+Create a new 2D vector with coordinates (@var{x}, @var{y}).
+@end deffn
+
+@deffn {Scheme Syntax} vector3 @var{x} @var{y} @var{z}
+Create a new 3D vector with coordinates (@var{x}, @var{y}, @var{z}).
+@end deffn
+
+@deffn {Scheme Syntax} vector4 @var{x} @var{y} @var{z} @var{w}
+Create a new 4D vector with coordinates (@var{x}, @var{y}, @var{z},
+@var{w}).
+@end deffn
+
+@deffn {Scheme Syntax} vector2? @var{v}
+Return @code{#t} if @code{v} is a 2D vector.
+@end deffn
+
+@deffn {Scheme Syntax} vector3? @var{v}
+Return @code{#t} if @code{v} is a 3D vector.
+@end deffn
+
+@deffn {Scheme Syntax} vector4? @var{v}
+Return @code{#t} if @code{v} is a 4D vector.
+@end deffn
+
+@deffn {Scheme Procedure} vx @var{v}
+Return the x coordinate of the 2D, 3D, or 4D vector @var{v}.
+@end deffn
+
+@deffn {Scheme Procedure} vy @var{v}
+Return the y coordinate of the 2D, 3D, or 4D vector @var{v}.
+@end deffn
+
+@deffn {Scheme Procedure} vz @var{v}
+Return the z coordinate of the 3D or 4D vector @var{v}.
+@end deffn
+
+@deffn {Scheme Procedure} vw @var{v}
+Return the w coordinate of the 4D vector @var{v}.
+@end deffn
+
+@deffn {Scheme Procedure} vmap @var{proc} @var{v}
+Return a new vector that is the result of applying @var{proc} to each
+element of the 2D, 3D, or 4D vector @var{v}.
+@end deffn
+
+@deffn {Scheme Procedure} v+ . @var{vectors}
+Return the sum of all @var{vectors}. @var{vectors} may contain scalar
+values, but it may not contain vectors of mixed dimensions.
+@end deffn
+
+@deffn {Scheme Procedure} v- . @var{vectors}
+Return the difference of all @var{vectors}. @var{vectors} may contain scalar
+values, but it may not contain vectors of mixed dimensions.
+@end deffn
+
+@deffn {Scheme Procedure} v* . @var{vectors}
+Return the product of all @var{vectors}. @var{vectors} may contain
+scalar values, but it may not contain vectors of mixed dimensions.
+@end deffn
+
+@deffn {Scheme Procedure} vdot @var{v1} @var{v2}
+Return the dot product of @var{v1} and @var{v2}. Both vectors must be
+of the same dimensionality.
+@end deffn
+
+@deffn {Scheme Procedure} vcross @var{v1} @var{v2}
+Return the cross product of the 3D vectors @var{v1} and @var{v2}.
+@end deffn
+
+@deffn {Scheme Procedure} magnitude @var{v}
+Return the magnitude of the vector @var{v}.
+@end deffn
+
+@deffn {Scheme Procedure} normalize @var{v}
+Return the normalized form of the vector @var{v}.
+@end deffn
+
+@deffn {Scheme Procedure} vlerp @var{v1} @var{v2} @var{alpha}
+Return the linear interpolation of @var{v1} and @var{v2} by the scalar
+@var{alpha}. @var{alpha} is expected to be in the range [0, 1].
+@end deffn
+
+@node Rectangles
+@subsection Rectangles
+
+@example
+(use-modules (sly math rect))
+@end example
+
+Rects are 2D axis-aligned bounding boxes. They are useful for
+defining rectangular regions, such as the hitbox of a game entity, or
+the viewport of a camera. Because rects are axis-aligned, they
+provide a cheap means to perform simple collision detection.
+
+The @code{<rect>} type descriptor has been exposed for use with
+Guile's @code{(ice-9 match)} pattern matching module.
+
+@defvr {Scheme Variable} <rect>
+Rectangle data type with fields @code{x}, @code{y}, @code{width},
+@code{height}, in that order.
+@end defvr
+
+@deffn {Scheme Procedure} make-rect @var{x} @var{y} @var{width} @var{height}
+Create a new rectangle with position (@var{x}, @var{y}), and
+dimensions (@var{width}, @var{height}).
+@end deffn
+
+@defvr {Scheme Variable} null-rect
+Rectangle with @code{x}, @code{y}, @code{width}, and @code{height} of 0.
+@end defvr
+
+@deffn {Scheme Macro} rect? @var{obj}
+Return @code{#t} if @var{obj} is a rectangle.
+@end deffn
+
+@deffn {Scheme Macro} rect-x @var{rect}
+Return the x coordinate of @var{rect}.
+@end deffn
+
+@deffn {Scheme Macro} rect-y @var{rect}
+Return the x coordinate of @var{rect}.
+@end deffn
+
+@deffn {Scheme Macro} rect-width @var{rect}
+Return the width of @var{rect}.
+@end deffn
+
+@deffn {Scheme Macro} rect-height @var{rect}
+Return the height of @var{rect}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-left @var{rect}
+Return the left-hand x coordinate of @var{rect}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-right @var{rect}
+Return the right-hand x coordinate of @var{rect}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-top @var{rect}
+Return the top y coordinate of @var{rect}
+@end deffn
+
+@deffn {Scheme Procedure} rect-bottom @var{rect}
+Return the bottom y coordinate of @var{rect}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-top-left @var{rect}
+Return the top-left corner of @var{rect}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-top-right @var{rect}
+Return the top-right corner of @var{rect}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-bottom-left @var{rect}
+@deffnx {Scheme Procedure} rect-position @var{rect}
+Return the bottom-left corner of @var{rect}
+@end deffn
+
+@deffn {Scheme Procedure} rect-bottom-right @var{rect}
+Return the bottom-right corner of @var{rect}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-center-x @var{rect}
+Return the center x coordinate of @var{rect}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-center-y @var{rect}
+Return the center y coordinate of @var{rect}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-center @var{rect}
+Return the center of @var{rect}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-half-width @var{rect}
+Return the half width of @var{rect}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-half-height @var{rect}
+Return the half height of @var{rect}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-size @var{rect}
+Return the size of @var{rect}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-move @var{rect} @var{v}
+@deffnx {Scheme Procedure} rect-move @var{rect} @var{x} @var{y}
+Create a new rectangle by moving @var{rect} by the given 2D vector
+offset @var{v}, or the coordinates @var{x} and @var{y}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-inflate @var{rect} @var{size}
+@deffnx {Scheme Procedure} rect-inflate @var{rect} @var{width} @var{height}
+Create a new rectangle by growing @var{rect} by the 2D vector
+@var{size} (or @var{width} and @var{height}) without changing the
+center point.
+@end deffn
+
+@deffn {Scheme Procedure} rect-union @var{rect1} @var{rect2}
+Create a new rectangle that covers the area of both @var{rect1} and
+@var{rect2}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-clip @var{rect1} @var{rect2}
+Create a new rectangle that is the overlapping region of @var{rect1}
+and @var{rect2}. If the rects do not overlap, a rect of size 0 is
+returned.
+@end deffn
+
+@deffn {Scheme Procedure} rect-clamp @var{rect} @var{v}
+Return a new 2D vector by constraining @var{v} to the bounds of
+@var{rect}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-within? @var{rect1} @var{rect2}
+Return @code{#t} if @var{rect2} is completely within @var{rect1}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-intersects? @var{rect1} @var{rect2}
+Return @code{#t} if @var{rect2} overlaps @var{rect1}.
+@end deffn
+
+@deffn {Scheme Procedure} rect-contains? @var{rect} @var{v}
+@deffnx {Scheme Procedure} rect-contains? @var{rect} @var{x} @var{y}
+Return @code{#t} if the 2D vector @var{v} (or the coordinates @var{x}
+and @var{y}) is within @var{rect}.
+@end deffn
+
+@node Transforms
+@subsection Transforms
+
+@example
+(use-modules (sly math transform))
+@end example
+
+Transforms are 4x4 transformation matrices. Matrices are the
+fundamental structure for modeling affine transformations such as
+translation, rotation, and scaling. Complex transformations are
+created by composing many simpler ones with the @code{transform*}
+procedure.
+
+It's a good idea to use transforms in a functional manner by treating
+them as immutable. This is made easy because almost every procedure
+in this module returns a new transform rather than mutating an
+existing one. However, in some cases it is necessary to use mutable
+transforms via @code{transform*!} for performance reasons.
+
+@deffn {Scheme Procedure} make-transform @var{aa} @var{ab} @var{ac} @var{ad} @var{ba} @var{bb} @var{bc} @var{bd} @var{ca} @var{cb} @var{cc} @var{cd} @var{da} @var{db} @var{dc} @var{dd}
+Create a new transform initialized with the given 16 values in
+column-major format.
+@end deffn
+
+@defvr {Scheme Variable} null-transform
+A transform composed entirely of zeroes.
+@end defvr
+
+@defvr {Scheme Variable} identity-transform
+The multiplicative identity transform.
+@end defvr
+
+@deffn {Scheme Macro} transform? @var{obj}
+Return @code{#t} if @var{obj} is a transform.
+@end deffn
+
+@deffn {Scheme Macro} transform-matrix @var{transform}
+Return the underlying 4x4 floating point array for @var{transform}.
+@end deffn
+
+@deffn {Scheme Procedure} transpose @var{transform}
+Return a transform that is the transpose of @var{transform}.
+@end deffn
+
+@deffn {Scheme Procedure} transform-vector2 @var{transform} @var{v}
+Apply @var{transform} to the 2D vector @var{v}.
+@end deffn
+
+@deffn {Scheme Procedure} transform-position @var{transform}
+Return a 3D vector containing the positional data stored in
+@var{transform}.
+@end deffn
+
+@deffn {Scheme Procedure} transform+ . @var{transforms}
+Return the sum of @var{transforms}. Return @code{null-transform} if
+called without any arguments.
+@end deffn
+
+@deffn {Scheme Procedure} transform* . @var{transforms}
+Return the product of @var{transforms}. Return identity-transform if
+called without any arguments.
+@end deffn
+
+@deffn {Scheme Procedure} transform*! @var{dest} @var{a} @var{b}
+Multiply @var{a} and @var{b}, storing the result in @var{dest}.
+@end deffn
+
+@deffn {Scheme Procedure} translate @var{v}
+Create a new transform that translates by the 2D or 3D vector @var{v}.
+@end deffn
+
+@deffn {Scheme Procedure} scale @var{v}
+@deffnx {Scheme Procedure} scale @var{scalar}
+Create a new transform that scales by the 2D or 3D vector @var{v}, or
+by @var{scalar} to scale evenly in all dimensions.
+@end deffn
+
+@deffn {Scheme Procedure} rotate-x @var{angle}
+Create a new transform that rotates the x axis by @var{angle} radians.
+@end deffn
+
+@deffn {Scheme Procedure} rotate-y @var{angle}
+Create a new transform that rotates the y axis by @var{angle} radians.
+@end deffn
+
+@deffn {Scheme Procedure} rotate-z @var{angle}
+Create a new transform that rotates the z axis by @var{angle} radians.
+@end deffn
+
+@deffn {Scheme Procedure} rotate @var{q}
+Convert the quaternion @var{q} into a rotation transform.
+@xref{Quaternions} for more information.
+@end deffn
+
+One of the most common composite transformations is a translation
+multiplied by a scale multiplied by a rotation. The
+@code{build-transform} procedure is a convenience procedure for this
+case.
+
+@deffn {Scheme Procedure} build-transform @var{[#:position=(vector3 0 0 0)] [#:scale=1] [#:rotation=null-quaternion]}
+Build a transform by multiplying the following transforms:
+
+@itemize
+@item translation by @var{position}
+@item rotation by @var{rotation}
+@item scaling by @var{scale}
+@end itemize
+
+@end deffn
+
+The procedures below are useful for creating projection and view
+matrices for cameras. @xref{Cameras} for more details.
+
+@deffn {Scheme Procedure} orthographic-projection left right top bottom near far
+Create a new transform that represents an orthographic projection for
+the vertical clipping plane @var{left} and @var{right}, the horizontal
+clipping plane @var{top} and @var{bottom}, and the depth clipping
+plane @var{near} and @var{far}.
+@end deffn
+
+@deffn {Scheme Procedure} perspective-projection @var{field-of-vision} @var{aspect-ratio} @var{near} @var{far}
+Create a new transform that represents a perspective projection with a
+@var{field-of-vision} in degrees, the desired @var{aspect-ratio}, and
+the depth clipping plane @var{near} and @var{far}.
+@end deffn
+
+@deffn {Scheme Procedure} look-at @var{eye} @var{center} [@var{up=(vector3 0 1 0)}]
+Create a view transform that looks from 3D vector @var{eye} at the 3D
+vector @var{center}, with the 3D vector @var{up} indicating which
+direction points up.
+@end deffn
+
+@node Tweens
+@subsection Tweens
+
+@example
+(use-modules (sly math tween))
+@end example
+
+Tweening is the process of interpolating between two key values to
+create the illusion of smooth animation. There are many different
+ways to alter the rate of change, or ``ease'', one value to another.
+
+When tween functions are combined with @ref{Signals}, the result is
+animation!
+
+@menu
+* Easings:: Easing procedures.
+* Tweening:: The tween procedure.
+@end menu
+
+@node Easings
+@subsubsection Easings
+
+Easing procedures specify the rate of change of a value @var{alpha}
+over time. Easings may be composed to form complex animation.
+
+The following procedures are used to control repitition by clamping
+@var{alpha} to the range [0, 1] in different ways.
+
+@deffn {Scnheme Procedure} ease-loop @var{alpha}
+When @var{alpha} reaches 1, start over from 0.
+@end deffn
+
+@deffn {Scheme Procedure} ease-reflect @var{alpha}
+When @var{alpha} reaches 1, work backwards to 0. When @var{alpha}
+reaches 0, work forwards to 1.
+@end deffn
+
+The following easing functions control the rate of change of an
+animation:
+
+@c TODO: Add graphs like on <http://easings.net>.
+@deffn {Scheme Procedure} ease-linear @var{alpha}
+@end deffn
+
+@deffn {Scheme Procedure} ease-in-sine @var{alpha}
+@end deffn
+
+@deffn {Scheme Procedure} ease-out-sine @var{alpha}
+@end deffn
+
+@deffn {Scheme Procedure} ease-in-out-sine @var{alpha}
+@end deffn
+
+@deffn {Scheme Procedure} ease-in-quad @var{alpha}
+@end deffn
+
+@deffn {Scheme Procedure} ease-out-quad @var{alpha}
+@end deffn
+
+@deffn {Scheme Procedure} ease-in-out-quad @var{alpha}
+@end deffn
+
+@node Tweening
+@subsubsection Tweening
+
+The @code{tween} procedure creates new procedures to be used for
+animation. For example, the code below creates a tween procedure that
+linearly interpolates (0, 0) to (10, 10) over the course of ten ticks.
+
+@example
+(define t (tween vlerp ease-linear (vector2 0 0) (vector2 10 0) 10))
+
+(t 5) ;; => (vector2 5 5)
+@end example
+
+@deffn {Scheme Procedure} tween @var{interpolator} @var{ease} @var{start} @var{end} @var{duration}
+Return a procedure that interpolates from @var{start} to @var{end} in
+@var{duration} ticks. The value returned for a given time is
+determined by applying @var{ease} with the time ratio to acquire an
+@var{alpha} value, and then applying @var{interpolator} with
+@var{start}, @var{end}, and @var{alpha}. @var{alpha} is a rational
+number in the range [0, 1].
+@end deffn
+
+@node Quaternions
+@subsection Quaternions
+
+@example
+(use-modules (sly math quaternion))
+@end example
+
+Quaternions are used to express rotations about an arbitrary axis in a
+way that avoids ``gimbal lock'' and allows for useful interpolation,
+unlike matrices or Euler angles.
+
+Quaternions can be used in rotation transformations
+(@pxref{Transforms}), as well as converted to and from @ref{Vectors}.
+
+@defvr {Record Type} <quaternion>
+Data type with 4 fields: @code{w}, @code{x}, @code{y}, @code{z}, in
+that order. This type descriptor has been exposed for destructuring
+via Guile's @code{(ice-9 match)} module.
+@end defvr
+
+@deffn {Scheme Procedure} make-quaternion @var{v} @var{theta}
+@deffnx {Scheme Procedure} make-quaternion @var{w} @var{x} @var{y} @var{z}
+Create a new quaternion from an axis angle (a 3D vector @var{v} plus
+an angle @var{theta}) or from individual coordinates @var{w}, @var{x},
+@var{y}, and @var{z}.
+@end deffn
+
+@deffn {Scheme Procedure} quaternion @var{v} @var{theta}
+@deffnx {Scheme Procedure} quaternion @var{w} @var{x} @var{y} @var{z}
+Alternate spelling of @code{make-quaternion}.
+@end deffn
+
+@deffn {Scheme Macro} quaternion? @var{obj}
+Return @code{#t} if @var{obj} is a quaternion.
+@end deffn
+
+@deffn {Scheme Macro} quaternion-w @var{q}
+Return the w coordinate of the quaternion @var{q}.
+@end deffn
+
+@deffn {Scheme Macro} quaternion-x @var{q}
+Return the x coordinate of the quaternion @var{q}.
+@end deffn
+
+@deffn {Scheme Macro} quaternion-y @var{q}
+Return the y coordinate of the quaternion @var{q}.
+@end deffn
+
+@deffn {Scheme Macro} quaternion-z @var{q}
+Return the z coordinate of the quaternion @var{q}.
+@end deffn
+
+@defvr {Scheme Variable} identity-quaternion
+The multiplicative identity quaternion.
+@end defvr
+
+@defvr {Scheme Variable} null-quaternion
+A quaternion with all fields set to zero.
+@end defvr
+
+@deffn {Scheme Procedure} quaternion* . @var{quaternions}
+Return the product of all @var{quaternions}. Return
+@code{identity-quaternion} if called without arguments.
+@end deffn
+
+@deffn {Scheme Procedure} quaternion-slerp @var{q1} @var{q2} @var{delta}
+Perform a spherical linear interpolation of the quaternions @var{q1}
+and @var{q2} and blending factor @var{delta}.
+@end deffn
+
+@deffn {Scheme Procedure} quaternion-magnitude @var{q}
+Return the magnitude of the quaternion @var{q}.
+@end deffn
+
+@deffn {Scheme Procedure} quaternion-normalize @var{q}
+Return the normalized form of the quaternion @var{q}.
+@end deffn
+
+@deffn {Scheme Procedure} vector->quaternion @var{v}
+Convert the 4D vector @var{v} to a quaternion.
+@end deffn
+
+@deffn {Scheme Procedure} quaternion->vector @var{q}
+Convert the quaternion @var{q} to a 4D vector.
+@end deffn
+
+@node Miscellaneous
+@subsection Miscellaneous
+
+@example
+(use-modules (sly math))
+@end example
+
+A grab bag of commonly used math functions and constants.
+
+@defvr {Scheme Variable} pi
+An approximation of \pi, the ratio of a circle's circumference to its
+diameter.
+@end defvr
+
+@defvr {Scheme Variable} 2pi
+@math{2\pi}
+@end defvr
+
+@defvr {Scheme Variable} pi/2
+@math{\pi/2}
+@end defvr
+
+@deffn {Scheme Procedure} degrees->radians @var{angle}
+Convert @var{angle} from degrees to radians.
+@end deffn
+
+@deffn {Scheme Procedure} radians->degrees @var{angle}
+Convert @var{angle} from radians to degrees.
+@end deffn
+
+@deffn {Scheme Procedure} sin-degrees @var{angle}
+Return the sine of @var{angle}, where @var{angle} is measured in
+degrees.
+@end deffn
+
+@deffn {Scheme Procedure} cos-degrees @var{angle}
+Return the cosine of @var{angle}, where @var{angle} is measured in
+degrees.
+@end deffn
+
+@deffn {Scheme Procedure} tan-degrees @var{angle}
+Return the tangent of @var{angle}, where @var{angle} is measured in
+degrees.
+@end deffn
+
+@deffn {Scheme Procedure} atan-degrees @var{y} @var{x}
+Return the arctangent of @var{y} and @var{x}, where @var{y} and
+@var{x} are measured in degrees.
+@end deffn
+
+@deffn {Scheme Procedure} cotan @var{z}
+Return the cotangent of @var{z}.
+@end deffn
+
+@deffn {Scheme Procedure} clamp @var{min} @var{max} @var{x}
+Restrict @var{x} to the range [@var{min}, @var{max}], assuming that
+@var{min} is actually less than @var{max}.
+@end deffn
+
+@deffn {Scheme Procedure} linear-scale @var{min} @var{max} @var{a} @var{b} @var{n}
+Map @var{n} in the range [@var{min}, @var{max}] to the range [@var{a}, @var{b}].
+@end deffn
+
+@deffn {Scheme Procedure} half @var{x}
+Return @math{@var{x} / 2}.
+@end deffn
+
+@deffn {Scheme Procedure} square @var{x}
+Return @math{@var{x}^2}.
+@end deffn
+
+@deffn {Scheme Procedure} make-lerp @var{+} @var{*}
+Return a new procedure that accepts three arguments: @var{start},
+@var{end}, and @var{alpha}. The returned procedure uses the
+procedures @var{+} and @var{*} to linearly interpolate a value between
+@var{start} and @var{end}. @var{alpha} should always be in the range
+[0, 1].
+@end deffn
+
+@deffn {Scheme Procedure} lerp @var{start} @var{end} @var{alpha}
+Return the linear interpolation between the numbers @var{start} and
+@var{end} with scalar factor @var{alpha}.
+@end deffn
+
+@deffn {Scheme Procedure} modulo* @var{x} @var{y}
+Return the remainder of @math{@var{x} / @var{y}}. Works like regular
+@code{modulo}, except that @var{x} and @var{y} may be rational numbers
+or inexact numbers.
+@end deffn
diff --git a/doc/api/rendering.texi b/doc/api/rendering.texi
new file mode 100644
index 0000000..364d09c
--- /dev/null
+++ b/doc/api/rendering.texi
@@ -0,0 +1,48 @@
+@node Rendering
+@section Rendering
+
+@menu
+* Scene Graph:: Declarative rendering.
+* Sprites:: 2D textured rectangles.
+* Textures:: Pixel arrays.
+* Fonts:: Font loading and text rendering.
+* Shapes:: Primitive 2D/3D shapes.
+* Cameras:: Defining a viewpoint.
+* Colors:: Pretty colors.
+* Framebuffers:: Offscreen rendering.
+@end menu
+
+@node Scene Graph
+@subsection Scene Graph
+
+@menu
+* Models:: Renderable objects.
+* Groups:: Transformation hierarchy.
+@end menu
+
+@node Models
+@subsubsection Models
+
+@node Groups
+@subsubsection Groups
+
+@node Sprites
+@subsection Sprites
+
+@node Textures
+@subsection Textures
+
+@node Fonts
+@subsection Fonts
+
+@node Shapes
+@subsection Shapes
+
+@node Cameras
+@subsection Cameras
+
+@node Colors
+@subsection Colors
+
+@node Framebuffers
+@subsection Framebuffers
diff --git a/doc/api/time.texi b/doc/api/time.texi
new file mode 100644
index 0000000..cc637f2
--- /dev/null
+++ b/doc/api/time.texi
@@ -0,0 +1,362 @@
+@node Time
+@section Time
+
+In the context of Sly, time is not the seconds that are passing in the
+real world, but the virtual clock that is ticking within the game
+loop. This manual refers to a ``tick'' as the smallest unit of time.
+There are a user-defined amount of ticks in a real world second, but
+by default it is 60.
+
+Sly includes several useful modules for working with time. Coroutines
+are procedures that can be paused and resumed, agendas are procedure
+schedulers, and signals built atop both agendas and coroutines to
+provide a high-level functional reactive programming API.
+
+For most use-cases, the signal module should be used exclusively, but
+the agenda and coroutine modules are useful for building new
+high-level abstractions.
+
+@menu
+* Signals:: Functional reactive programming.
+* Coroutines:: Cooperative multi-tasking.
+* Agendas:: Deferred procedure scheduling.
+@end menu
+
+@node Signals
+@subsection Signals
+
+@example
+(use-modules (sly signal))
+@end example
+
+Game state is a function of time. The player's score, the current
+stage, an enemy's hit points, etc. all change in response to events
+that happen at discrete points in time. Typically, this means that a
+number of callback procedures are registered to respond to events
+which mutate the relevant data structures. However, this approach,
+while simple and effective, comes at the price of readability,
+reproducibility, and expression. Instead of explicitly mutating data
+and entering ``callback hell'', Sly abstracts and formalizes the
+process using a functional reactive programming style.
+
+In Sly, time-varying values are called ``signals'', and they are
+defined in a declarative and functional manner. Rather than
+describing the process of mutation procedurally, one describes the
+relationships between signals instead. The result is a ``signal
+graph'', a directed acyclic graph of event responses.
+
+@example
+(define-signal position
+ (signal-fold v+ (vector2 320 240)
+ (signal-map (lambda (v) (v* v 4))
+ (signal-sample 1 key-arrows))))
+@end example
+
+This signal describes a relationship between the arrow keys on the
+keyboard and the position of the player. @code{signal-sample} is used
+to trigger a signal update upon every game tick that provides the
+current state of the arrow keys. @code{key-arrows} is a 2D vector
+that maps to the current state of the arrow keys, allowing for 8
+directional movement. This vector is then scaled 4x to make the
+player move faster. Finally, the scaled vector is added to the
+previous player position via @code{signal-fold}. The player's
+position is at (320, 240) initially. As you can see, there are no
+callbacks and explicit mutation needed, and the position seems to
+magically change with the passage of time.
+
+@deffn {Scheme Procedure} signal? @var{obj}
+Return @code{#t} if @var{obj} is a signal.
+@end deffn
+
+@deffn {Scheme Procedure} make-signal @var{value}
+Wrap @var{value} in a signal.
+@end deffn
+
+@deffn {Scheme Syntax} define-signal @var{name} @var{value}
+Create a top-level signal variable called @var{name}. If the variable
+already exists and refers to a signal then its outputs will be spliced
+into the new signal. If the given value is not a signal then it will
+be put into one via @code{make-signal}.
+
+@code{define-signal} is particularly useful when working at the REPL.
+A top-level signal variable defined by @code{define-signal} can be
+redefined at runtime, and the signals that depended on the old signal
+will continue to work with the new signal.
+@end deffn
+
+@deffn {Scheme Procedure} signal-ref @var{signal}
+Return the value stored within @var{signal}.
+@end deffn
+
+@deffn {Scheme Procedure} signal-ref-maybe object
+Return the value stored within @var{object} if @var{object} is a
+signal. Otherwise, return @var{object}.
+@end deffn
+
+@deffn {Scheme Syntax} signal-let ((@var{var} @var{signal}) @dots{}) @var{body} @dots{}
+Evaluate @var{body} in the context of the local bindings defined by
+the two-element lists @code{((var signal) @dots{})}.
+@code{signal-let} works like regular @code{let}, except that it
+derefences @var{signal} before binding to @var{var}.
+@end deffn
+
+@deffn {Scheme Syntax} signal-let* ((@var{var} @var{signal}) @dots{}) @var{body} @dots{}
+Similar to @code{signal-let}, but the variable bindings are performed
+sequentially. This means that all initialization expressions are
+allowed to use the variables defined to the their left in the binding
+list.
+@end deffn
+
+@deffn {Scheme Procedure} signal-set! signal-box value
+Change the contents of @var{signal} to @var{value}. This procedure
+should almost never be used, except to bootstrap a root node of a
+signal graph.
+@end deffn
+
+@deffn {Scheme Procedure} hook->signal @var{hook} @var{init} @var{proc}
+Create a new signal whose initial value is @var{init} and whose future
+values are calculated by applying @var{proc} to the arguments passed
+when @var{hook} is run.
+@end deffn
+
+@deffn {Scheme Procedure} signal-merge @var{signal1} @var{signal2} . @var{rest}
+Create a new signal whose value is the that of the most recently
+updated signal in @var{signal1}, @var{signal2}, etc. The initial
+value is that of @var{signal1}.
+@end deffn
+
+@deffn {Scheme Procedure} signal-zip . @var{signals}
+Create a new signal whose value is a list of the values stored in
+@var{signals}.
+@end deffn
+
+@deffn {Scheme Procedure} signal-map @var{proc} @var{signal} . @var{rest}
+Create a new signal that applies @var{proc} to the values of
+@var{SIGNAL}. More than one input signal may be specified, in which
+case @var{proc} must accept as many arguments as there are input
+signals.
+@end deffn
+
+@deffn {Scheme Procedure} signal-sample-on @var{value-signal} @var{sample-signal}
+Create a new signal that takes on the value of @var{value-signal}
+whenever @var{sample-signal} receives a new value.
+@end deffn
+
+@deffn {Scheme Procedure} signal-negate @var{signal}
+Create a new signal whose value is the negation of @var{signal} by
+applying @code{not} to each value received.
+@end deffn
+
+@deffn {Scheme Procedure} signal-fold @var{proc} @var{init} @var{signal} . @var{rest}
+Create a new signal that applies @var{proc} with the value received
+from @var{signal} and the past value of itself, starting with
+@var{init}. Like @code{signal-map}, more than one input signal may be
+given.
+@end deffn
+
+@deffn {Scheme Procedure} signal-filter @var{predicate} @var{default} @var{signal}
+Create a new signal that takes on the value received from @var{signal}
+when it satisfies the procedure @var{predicate}. The value of the
+signal is @var{default} in the case that the predicate is never
+satisfied.
+@end deffn
+
+@deffn {Scheme Procedure} signal-drop @var{predicate} @var{default} @var{signal}
+Create a new signal that takes on the value received from @var{signal}
+when it does @emph{not} satisfy the procedure @var{predicate}. The
+value of the signal is @var{default} in the case that the predicate is
+never satisfied.
+@end deffn
+
+@deffn {Scheme Procedure} signal-drop-repeats @var{signal} [@var{equal?}]
+Create a new signal that drops the value received from @var{signal}
+when it is equivalent to the current value. By default, @code{equal?}
+is used for testing equivalence.
+@end deffn
+
+@deffn {Scheme Procedure} signal-switch @var{predicate} @var{on} @var{off}
+Create a new signal whose value is that of the signal @var{on} when
+the signal @var{predicate} is true, or the value of the signal
+@var{off} otherwise.
+@end deffn
+
+@deffn {Scheme Procedure} signal-constant @var{constant} @var{signal}
+Create a new signal whose value is always @var{constant} no matter the
+value received from @var{signal}.
+@end deffn
+
+@deffn {Scheme Procedure} signal-count @var{signal} [@var{start}] [@var{step}]
+Create a new signal that increments a counter by @var{step} when a
+value from @var{signal} is received, starting from @var{start}. By
+default, @var{start} is 0 and @var{step} is 1.
+@end deffn
+
+@deffn {Scheme Procedure} signal-tap @var{proc} @var{signal}
+Create a new signal that applies @var{proc} for side-effects when a
+value from @var{signal} is received. The value of the new signal will
+always be the value of @var{signal}. This signal is a convenient way
+to sneak in a procedure that with a side-effect into a signal graph.
+Such a signal might write text to a file, or play a sound.
+@end deffn
+
+@deffn {Scheme Procedure} signal-timestamp @var{signal}
+Create a new signal whose value is a pair, the car of which is the
+time that the value of @var{signal} was received and the cdr of which
+is the received value.
+@end deffn
+
+@deffn {Scheme Procedure} signal-time @var{signal}
+Create a new signal whose value is the time that the value of
+@var{signal} was received.
+@end deffn
+
+@deffn {Scheme Procedure} signal-sample @var{step} @var{signal}
+Create a new signal that takes on the value of @var{signal} every
+@var{step} ticks.
+@end deffn
+
+@deffn {Scheme Procedure} signal-every @var{step}
+Create a new signal that emits @var{step} every @var{step} ticks.
+@end deffn
+
+@deffn {Scheme Procedure} signal-since @var{step} @var{signal}
+Create a new signal that emits the time since @var{signal} was updated
+ever @var{step} ticks.
+@end deffn
+
+@deffn {Scheme Procedure} signal-delay @var{delay} @var{signal}
+Create a new signal that delays propagation of @var{signal} by
+@var{delay} ticks..
+@end deffn
+
+@deffn {Scheme Procedure} signal-throttle delay signal
+Create a new signal that propagates @var{signal} at most once every
+@var{delay} ticks.
+@end deffn
+
+@deffn {Scheme Syntax} signal-generator @var{body} @dots{}
+Create a new signal whose value is the most recently yielded value of
+the coroutine defined by @var{body}. A special @code{yield} syntax is
+available within @var{body} to specify which values are passed to the
+signal.
+@end deffn
+
+@node Coroutines
+@subsection Coroutines
+
+@example
+(use-modules (sly coroutine))
+@end example
+
+Coroutines are the building block for cooperative multitasking. When
+used with agendas, they are a powerful mechanism for writing
+algorithms that span multiple clock ticks in a straightforward, linear
+fashion. Sly's coroutines are built on top of Guile's delimited
+continuations, called prompts.
+
+To run a procedure as a coroutine, use the @code{call-with-coroutine}
+procedure. Once inside the coroutine prompt, the @code{yield}
+procedure can be used to pause the procedure and pass its continuation
+to a callback procedure. The callback may call the continuation at
+its convenience, resuming the original procedure.
+
+Coroutines are particularly useful in conjunction with @ref{Agendas}.
+
+@deffn {Scheme Procedure} call-with-coroutine @var{thunk}
+Apply @var{thunk} within a coroutine prompt.
+@end deffn
+
+@deffn {Scheme Syntax} coroutine @var{body} @dots{}
+Evaluate @var{body} within a coroutine prompt.
+@end deffn
+
+@deffn {Scheme Syntax} colambda @var{args} @var{body} @dots{}
+Syntacic sugar for a @code{lambda} expression whose @var{body} is run
+within a coroutine prompt.
+@end deffn
+
+@deffn {Scheme Syntax} codefine (@var{name} @var{formals} @dots{}) @var{body} @dots{}
+Syntacic sugar for defining a procedure called @var{name} with formal
+arguments @var{formals} whose @var{body} is run within a coroutine
+prompt.
+@end deffn
+
+@deffn {Scheme Syntax} codefine* (@var{name} @var{formals} @dots{}) @var{body} @dots{}
+Syntacic sugar for defining a procedure called @var{name} with
+optional and keyword arguments @var{formals} whose @var{body} is run
+within a coroutine prompt.
+@end deffn
+
+@deffn {Scheme Procedure} yield @var{callback}
+Yield continuation to the procedure @var{callback}.
+@end deffn
+
+@node Agendas
+@subsection Agendas
+
+@example
+(use-modules (sly agenda))
+@end example
+
+Agendas are used to schedule procedures to be called at distinct
+points in time. One agenda, stored in the @code{current-agenda}
+parameter, is active at any given time. A global agenda is initially
+bound and is sufficient for most needs. When a separate scheduler is
+required (@pxref{REPL} for one such case), the parameter can be
+rebound using @code{parameterize} or @code{with-agenda} form.
+
+@deffn {Scheme Procedure} make-agenda
+Create a new, empty agenda.
+@end deffn
+
+@deffn {Scheme Syntax} agenda? @var{obj}
+Return @code{#t} if @var{obj} is an agenda.
+@end deffn
+
+@defvr {Scheme Variable} current-agenda
+A parameter containing the current, dynamically scoped agenda object.
+@end defvr
+
+@deffn {Scheme Procedure} agenda-time
+Return the time of the current agenda.
+@end deffn
+
+@deffn {Scheme Syntax} with-agenda @var{agenda} @var{body} @dots{}
+Evaluate @var{body} with @code{current-agenda} bound to @var{agenda}.
+@end deffn
+
+@deffn {Scheme Procedure} agenda-tick!
+Increment time by 1 for the current agenda and run scheduled
+procedures.
+@end deffn
+
+@deffn {Scheme Procedure} agenda-clear!
+Remove all scheduled procedures from the current agenda.
+@end deffn
+
+@deffn {Scheme Procedure} schedule @var{thunk} [@var{delay}]
+Schedule @var{thunk} to be applied after @var{delay} ticks of the
+current agenda. The default @var{delay} is one tick.
+@end deffn
+
+@deffn {Scheme Procedure} schedule-interval @var{thunk} @var{interval}
+Schedule @var{thunk} to be applied every @var{interval} ticks of the
+current agenda, forever.
+@end deffn
+
+@deffn {Scheme Procedure} schedule-each @var{thunk}
+Schedule @var{thunk} to be applied upon every tick of the current
+agenda, forever.
+@end deffn
+
+@ref{Coroutines} become particularly useful for game programming when
+combined with the agenda. For example, a computer controller opponent
+could periodically pause its AI algorithm to give the rest of the game
+world a chance to do some processing. By using the @code{wait}
+procedure, algorithms that span multiple ticks of game time can be
+written in a straightforward, natural way.
+
+@deffn {Scheme Procedure} wait @var{delay}
+Abort the current coroutine prompt and schedule the continuation to be
+run after @var{delay} ticks of the current agenda.
+@end deffn
diff --git a/doc/api/utils.texi b/doc/api/utils.texi
new file mode 100644
index 0000000..e75dd47
--- /dev/null
+++ b/doc/api/utils.texi
@@ -0,0 +1,29 @@
+@node Utilities
+@section Utilities
+
+@menu
+* REPL:: REPL server integrated with game loop.
+* Live Reloading:: Automatically reload game assets.
+* Miscellaneous-Utilities:: Generally useful things.
+@end menu
+
+@node REPL
+@subsection REPL
+
+@example
+(use-modules (sly utils repl))
+@end example
+
+@node Live Reloading
+@subsection Live Reloading
+
+@example
+(use-modules (sly utils live-reload))
+@end example
+
+@node Miscellaneous-Utilities
+@subsection Miscellaneous
+
+@example
+(use-modules (sly utils))
+@end example
diff --git a/doc/game.texi b/doc/game.texi
deleted file mode 100644
index 28cddf5..0000000
--- a/doc/game.texi
+++ /dev/null
@@ -1,118 +0,0 @@
-@node Games and Scenes
-@chapter Games and Scenes
-
-In Sly, games are defined declaratively. Game objects define
-things such as the title and screen resolution. Games are composed of
-many scenes, which encapsulate a particular aspect of the
-game. Examples would be a main menu, a world map, or a battle screen.
-
-@menu
-* Games::
-* Scenes::
-@end menu
-
-@node Games
-@section Games
-
-@anchor{2d game make-game}@defun make-game [#:title] [#:resolution] [#:fullscreen] [#:first-scene]
-Return a new game. All game properties have some reasonable default
-value.
-
-@end defun
-
-@anchor{2d game define-game}@defspec define-game name kwargs ...
-Syntactic sugar over define and make-game.
-
-@end defspec
-
-@anchor{2d game game?}@defspec game?
-@end defspec
-
-@anchor{2d game game-first-scene}@defspec game-first-scene
-@end defspec
-
-@anchor{2d game game-fullscreen?}@defspec game-fullscreen?
-@end defspec
-
-@anchor{2d game game-resolution}@defspec game-resolution
-@end defspec
-
-@anchor{2d game game-title}@defspec game-title
-@end defspec
-
-@anchor{2d game run-game}@defun run-game game
-Open a window and start the game loop for GAME.
-
-@end defun
-
-@node Scenes
-@section Scenes
-
-@anchor{2d game make-scene}@defun make-scene [#:title] [#:events] [#:update] [#:draw] [#:state]
-Return a new scene. TITLE is a human readable name for the scene.
-EVENTS is an alist of event handlers. UPDATE is a procedure that
-updates the scene. DRAW is a procedure that renders the scene. STATE
-is an object that encapsulates the scene state.
-
-@end defun
-
-@anchor{2d game define-scene}@defspec define-scene name kwargs ...
-Syntactic sugar over define and make-scene. Return a procedure that
-creates a new scene.
-
-@end defspec
-
-@anchor{2d game scene?}@defspec scene?
-@end defspec
-
-@anchor{2d game scene-draw-proc}@defspec scene-draw-proc
-@end defspec
-
-@anchor{2d game scene-observer}@defspec scene-observer
-@end defspec
-
-@anchor{2d game scene-state}@defspec scene-state
-@end defspec
-
-@anchor{2d game scene-title}@defspec scene-title
-@end defspec
-
-@anchor{2d game scene-update-proc}@defspec scene-update-proc
-@end defspec
-
-@anchor{2d game current-fps}@defun current-fps
-Return the current FPS value.
-
-@end defun
-
-@anchor{2d game default-scene-events}@defun default-scene-events
-@end defun
-
-@anchor{2d game draw-scene}@defun draw-scene scene
-Draw SCENE.
-
-@end defun
-
-@anchor{2d game pop-scene}@defun pop-scene
-Exit the current scene and resume the previous scene. If there is no
-previous scene, the game loop will terminate.
-
-@end defun
-
-@anchor{2d game push-scene}@defun push-scene scene
-Pause the current scene and start SCENE upon next game tick.
-
-@end defun
-
-@anchor{2d game replace-scene}@defun replace-scene scene
-@end defun
-
-@anchor{2d game scene-trigger}@defun scene-trigger scene event-type . args
-Trigger an event on the scene observer.
-
-@end defun
-
-@anchor{2d game update-scene}@defun update-scene scene
-Update SCENE.
-
-@end defun
diff --git a/doc/sly.texi b/doc/sly.texi
index e70274a..8eaeb71 100644
--- a/doc/sly.texi
+++ b/doc/sly.texi
@@ -114,6 +114,7 @@ and is not covered here. Please see the files @file{README.org} and
@menu
* Requirements:: Software needed to build and run Sly.
* Examples:: Run example programs.
+* Development Environment:: The ideal development environment.
@end menu
@node Requirements
@@ -145,17 +146,46 @@ A more complex example can further test your installation and show off
what Sly can do. Try running the ``2048'' example in
@file{share/sly/examples/2048} with @code{guile 2048.scm}.
+@node Development Environment
+@section Development Environment
+
+The ideal tools to use for developing Sly applications are:
+
+@itemize
+@item @url{https://gnu.org/software/emacs, GNU Emacs}, version 24 or later
+@item @url{http://mumble.net/~campbell/emacs/paredit/, Paredit}, version 23 or later
+@item @url{http://nongnu.org/geiser/, Geiser}, version 0.6 or later;
+@end itemize
+
+See their respective home pages for installation and usage instructions.
+
@node Getting Started
@chapter Getting Started
+@c @menu
+@c * Open a window
+@c * Draw a sprite
+@c * Respond to user input
+@c @end menu
+
@node API Reference
@chapter API Reference
@menu
-* Signals:: Functional reactive programming.
+* Booting:: Opening a window and running the game loop.
+* Math:: Vectors, quaternions, matrices, etc.
+* Time:: Tick-tock.
+* Input:: Keyboard, mouse, and joystick input.
+* Rendering:: Drawing to the screen.
+* Utilities:: Miscellaneous conveniences.
@end menu
-@include api/signals.texi
+@include api/init.texi
+@include api/math.texi
+@include api/time.texi
+@include api/input.texi
+@include api/rendering.texi
+@include api/utils.texi
@node Contributing
@chapter Contributing