summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Thompson <dthompson2@worcester.edu>2014-12-07 20:12:07 -0500
committerDavid Thompson <dthompson2@worcester.edu>2014-12-07 20:12:07 -0500
commitb41a57d0542c4a3941a97514130070d931aab956 (patch)
treed5f5c5b8561bd64f146a59d8472fd105d7649ce4
parent95fa10b75d11b8b2e0db11301bd1d061d29bacea (diff)
doc: Begin rewriting manual.
* doc/Makefile.am (guile_TEXINFOS): Delete. (sly_TEXINFOS): New variable. * doc/sly.texi: Rewrite. * doc/api/signals.texi: New file.
-rw-r--r--doc/Makefile.am23
-rw-r--r--doc/api/signals.texi214
-rw-r--r--doc/sly.texi142
3 files changed, 340 insertions, 39 deletions
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 9c2d95e..b26a64e 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -2,23 +2,6 @@ AUTOMAKE_OPTIONS = gnu
info_TEXINFOS = sly.texi
-guile_TEXINFOS = audio.texi \
- fdl.texi \
- game.texi \
- graphics.texi \
- graphics/animation.texi \
- graphics/color.texi \
- graphics/font.texi \
- graphics/sprite.texi \
- graphics/texture.texi \
- graphics/tileset.texi \
- sly.texi \
- introduction.texi \
- math.texi \
- math/math.texi \
- math/rect.texi \
- math/vector2.texi \
- scripting.texi \
- scripting/actions.texi \
- scripting/agenda.texi \
- scripting/coroutine.texi
+sly_TEXINFOS = \
+ fdl.texi \
+ api/signals.texi
diff --git a/doc/api/signals.texi b/doc/api/signals.texi
new file mode 100644
index 0000000..a4e2c01
--- /dev/null
+++ b/doc/api/signals.texi
@@ -0,0 +1,214 @@
+@node Signals
+@section Signals
+
+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
diff --git a/doc/sly.texi b/doc/sly.texi
index 3898e5d..e70274a 100644
--- a/doc/sly.texi
+++ b/doc/sly.texi
@@ -4,9 +4,7 @@
@settitle Sly
@c %**end of header
@copying
-Sly is a 2D game development framework for GNU Guile.
-
-Copyright @copyright{} 2013 David Thompson
+Copyright @copyright{} 2013, 2014 David Thompson @email{davet@@gnu.org}
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -28,8 +26,8 @@ The document was typeset with
@titlepage
@title Sly 0.1
-@subtitle Sly is a 2D game development framework for GNU Guile
-@author David Thompson <dthompson@@member.fsf.org>
+@subtitle Using the Sly game engine
+@author David Thompson
@page
@vskip 0pt plus 1filll
@insertcopying
@@ -47,24 +45,128 @@ The document was typeset with
@c Generate the nodes for this menu with `C-c C-u C-m'.
@menu
-* Introduction::
-* Games and Scenes::
-* Graphics::
-* Audio::
-* Scripting::
-* Math::
-* Copying This Manual::
+* Introduction:: About Sly.
+* Installation:: Installing Sly.
+* Getting Started:: Writing your first Sly program.
+* API Reference:: Sly programming interface.
+* Contributing:: Help improve Sly!
+* Copying This Manual:: The license of this manual.
* Index::
@end menu
@c Update all node entries with `C-c C-u C-n'.
@c Insert new nodes with `C-c C-c n'.
-@include introduction.texi
-@include game.texi
-@include graphics.texi
-@include audio.texi
-@include scripting.texi
-@include math.texi
+
+@node Introduction
+@chapter Introduction
+
+Sly is a 2D/3D game engine written in the GNU Guile dialect of the
+Scheme programming language. With the help of Guile, Sly provides all
+of the essential building blocks for making video games, such as:
+window management, input even handling, rendering, linear algebra, and
+powerful scripting capabilities. Sly differentiates itself from
+traditional game engines by providing a dynamic live coding
+environment, functional reactive programming, and a declarative scene
+graph.
+
+Live coding is the practice of improvised interactive programming.
+Sly provides a suitable environment for live coding by leveraging
+Emacs, Geiser, and Guile's cooperative REPL server. With these tools,
+programmers may evaluate arbitrary code and see the effects of their
+modifications in real time. This tight feedback loop allows for
+faster prototyping, greater productivity, and most importantly, more
+fun.
+
+Functional reactive programming (FRP) is a technique used to model
+time-varying values with pure functions. A pure function is a
+function that produces no side-effects, such as calling 'set!' on a
+variable or writing to the contents of an array. Sly encapsulates
+time-varying values in ``signals'', a high-level data structure for
+controlling the flow of events. Unlike imperative event callbacks,
+signals can easily be composed to form new signals. By modeling game
+state with pure functions and immutable data, a game can be seen as a
+function of time, in the mathematical sense. Constructing a game this
+way allows for deterministic behavior that is easier to reason about
+than the accumulation of side-effects seen in traditional game
+engines.
+
+A scene graph is a data structure for positioning renderable objects
+relative to one another. Child nodes inherit the transformations
+applied to their parent, making it easy to move a large amount of
+objects around as a group rather than individually. Sly's implements
+a declarative scene graph API, which means that the programmer
+describes @emph{what} to render, rather than @emph{how} to render it.
+
+These three major components form a powerful, high-level environment
+for building video games.
+
+@node Installation
+@chapter Installation
+
+Sly is available for download from its website at
+@url{sly.dthompson.us}. This section describes the software
+requirements of Sly, as well as how to install it.
+
+The build procedure for Sly is the same as for GNU software packages,
+and is not covered here. Please see the files @file{README.org} and
+@file{INSTALL.org} for additional details.
+
+@menu
+* Requirements:: Software needed to build and run Sly.
+* Examples:: Run example programs.
+@end menu
+
+@node Requirements
+@section Requirements
+
+Sly depends on the following packages:
+
+@itemize
+@item @url{https://gnu.org/software/guile, GNU Guile}, version 2.0.11 or later;
+@item @url{https://gnu.org/software/guile-opengl, GNU guile-opengl}, version 0.1 or later.
+@item @url{https://gnu.org/software/guile-sdl, GNU guile-sdl}, version 0.5.0 or later;
+@item @url{https://gnu.org/software/gsl, GNU Scientific Library}, version 1.16 or later;
+@item @url{http://freeimage.sourceforge.net/, FreeImage}, version 3 or later
+@end itemize
+
+@node Examples
+@section Examples
+
+To test your Sly installation, try running some of the included
+example programs. Examples can be found in the
+@file{share/sly/examples} directory, relative to the installation
+prefix.
+
+To run an example, invoke Guile with the relevant file, such as:
+@code{guile simple.scm}. If successful, a window with a sprite in the
+center will open.
+
+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 Getting Started
+@chapter Getting Started
+
+@node API Reference
+@chapter API Reference
+
+@menu
+* Signals:: Functional reactive programming.
+@end menu
+
+@include api/signals.texi
+
+@node Contributing
+@chapter Contributing
+
+This project is a cooperative effort, and we need your help to make it
+grow! Please get in touch with us on @code{#sly} on the Freenode IRC
+network. We welcome ideas, bug reports, patches, and anything that
+may be helpful to the project.
+
+The git source code repository can be found on Gitorious at
+@url{https://gitorious.org/sly/sly}.
@node Copying This Manual
@appendix Copying This Manual
@@ -81,7 +183,9 @@ The document was typeset with
@node Index
@unnumbered Index
-@printindex cp
+@syncodeindex tp fn
+@syncodeindex vr fn
+@printindex fn
@bye