doc: Remove unnecessary @var markup in argument lists.
[chickadee.git] / doc / api.texi
1 @menu
2 * Kernel:: The fundamental components.
3 * Math:: Linear algebra, spatial partitioning, and more.
4 * Graphics:: Eye candy.
5 * Scripting:: Bringing the game world to life.
6 @end menu
8 @node Kernel
9 @section Kernel
11 At the very core of Chickadee, in the @code{(chickadee game-loop)}
12 module, lies an event loop. This loop, or ``kernel'', is responsible
13 for ensuring that the game is updated at the desired interval,
14 rendering the current state of the game world, and handling errors if
15 they occur. The kernel implements what is known as a ``fixed
16 timestep'' game loop, meaning that the game simulation will be
17 advanced by a fixed interval of time and will never vary from frame to
18 frame, unlike some other styles of game loops. The appropriately
19 named @code{run-game*} and @code{abort-game} procedures are the entry
20 and exit points to the Chickadee game loop kernel.
22 On its own, the kernel does not do very much at all. In order to
23 actually respond to input events, update game state, or render output,
24 the programmer must provide an engine. But don’t worry, you don’t
25 have to start from scratch! Chickadee comes with a simple engine that
26 uses SDL to create a graphical window and handle input devices, and
27 OpenGL to handle rendering. This default engine is enough for most
28 users to get started writing games quickly. More advanced users may
29 want to write a custom engine that uses a different I/O system.
30 Perhaps you are writing a text adventure or roguelike that reads from
31 and writes to a terminal instead of a graphical window. The game loop
32 kernel makes no assumptions.
34 @deffn {Procedure} run-game [#:update] [#:render] [#:time] [#:error] @
35 [#:update-hz 60]
37 Start the game loop. This procedure will not return until
38 @code{abort-game} is called.
40 The core game loop is generic and requires four additional procedures
41 to operate:
43 @itemize
44 @item
45 @var{update}: Called @var{update-hz} times per second to advance the
46 game simulation. This procedure is called with a single argument: The
47 amount of time that has passed since the last update, in milliseconds.
48 @item
49 @var{render}: Called each iteration of the loop to render the game to
50 the desired output device. This procedure is called with a single
51 argument: A value in the range [0, 1] which represents how much time
52 has past since the last game state update relative to the upcoming
53 game state update, as a percentage. Because the game state is updated
54 independent of rendering, it is often the case that rendering is
55 occuring between two updates. If the game is rendered as it was
56 during the last update, a strange side-effect will occur that makes
57 animation appear rough or ``choppy''. To counter this, the
58 @var{alpha} value can be used to perfrom a linear interpolation of a
59 moving object between its current position and its previous position.
60 This odd trick has the pleasing result of making the animation look
61 smooth again, but requires keeping track of previous state.
62 @item
63 @var{time}: Called to get the current time in milliseconds. This
64 procedure is called with no arguments.
65 @item
66 @var{error}: Called when an error from the @var{update} or
67 @var{render} procedures reaches the game loop. This procedure is
68 called with three arguments: The call stack, the error key, and the
69 error arguments. If no error handler is provided, the default
70 behavior is to simply re-throw the error.
71 @end itemize
73 @end deffn
75 @deffn {Procedure} abort-game
76 Stop the currently running Chickadee game loop.
77 @end deffn
79 Since most users will want to write 2D/3D games with hardware
80 accelerated graphics rendering, controlled via keyboard, mouse, or
81 game controller, Chickadee comes with an easy to use engine just for
82 this purpose in the @code{(chickadee)} module: @code{run-game}.
84 @deffn {Procedure} run-game [#:window-title "Chickadee!"] @
85 [#:window-width 640] [#:window-height 480] @
86 [#:window-fullscreen? @code{#f}] [#:update-hz 60] @
87 [#:load] [#:update] [#:draw] [#:quit] @
88 [#:key-press] [#:key-release] [#:text-input] @
89 [#:mouse-press] [#:mouse-release] [#:mouse-move] @
90 [#:controller-add] [#:controller-remove] [#:controller-press] @
91 [#:controller-release] [#:controller-move] [#:error]
93 Run the Chickadee game loop using the SDL engine in OpenGL mode.
95 A new graphical window will be opened with @var{window-width} x
96 @var{window-height} as its dimensions, @var{window-title} as its
97 title, and in fullscreen mode if @var{window-fullscreen?} is
98 @code{#t}.
100 @itemize
101 @item
102 @var{load}: Called with zero arguments when the game window has opened
103 but before the game loop has started. Can be used to perform
104 initialization that requires an open window and OpenGL context such as
105 loading textures.
107 @item
108 @var{update}: Called @var{update-hz} times per second with one
109 argument: The amount of time to advance the game simulation.
111 @item
112 @var{draw}: Called each time a frame should be rendered with a single
113 argument known as the @code{alpha} value. See the documentation for
114 @code{run-game} for an explanation of this value.
116 @item
117 @var{quit}: Called with zero arguments when the user tries to close
118 the game window. The default behavior is to exit the game.
120 @item
121 @var{key-press}: Called with four arguments when a key is pressed on
122 the keyboard:
124 @enumerate
125 @item
126 @var{key}: The symbolic name of the ``virtual'' key that was pressed.
127 For example: @code{backspace}. It's called a virtual key because the
128 operating system may map a physical keyboard key to another key
129 entirely, such as how the author likes to bind the ``caps lock'' key
130 to mean ``control''.
132 @item
133 @var{scancode}: The symbolic name of the physical key that was
134 pressed.
136 @item
137 @var{modifiers}: A list of the symbolic names of modifier keys that
138 were being held down when the key was pressed. Possible values
139 include @code{ctrl}, @code{alt}, and @code{shift}.
141 @item
142 @var{repeat?}: @code{#t} if this is a repeated press of the same key.
144 @end enumerate
146 @item
147 @var{key-release}: Called with three arguments when a key is released
148 on the keyboard:
150 @enumerate
151 @item
152 @var{key}: The symbolic name of the ``virtual'' key that was released.
154 @item
155 @var{scancode}: The symbolic name of the physical key that was
156 released.
158 @item
159 @var{modifiers}: A list of the symbolic names of modifier keys that
160 were being held down when the key was released.
162 @end enumerate
164 @item
165 @var{text-input}: Called with a single argument, a string of text,
166 when printable text is typed on the keyboard.
168 @item
169 @var{mouse-press}: Called with four arguments when a mouse button is
170 pressed:
171 @enumerate
173 @item
174 @var{button}: The symbolic name of the button that was pressed, such
175 as @code{left}, @code{middle}, or @code{right}.
177 @item
178 @var{clicks}: The number of times the button has been clicked in a row.
180 @item
181 @var{x}: The x coordinate of the mouse cursor.
183 @item
184 @var{y}: The y coordinate of the mouse cursor.
186 @end enumerate
188 @item
189 @var{mouse-release}: Called with three arguments when a mouse button
190 is released:
192 @enumerate
194 @item
195 @var{button}: The symbolic name of the button that was released.
197 @item
198 @var{x}: The x coordinate of the mouse cursor.
200 @item
201 @var{y}: The y coordinate of the mouse cursor.
203 @end enumerate
205 @item
206 @var{mouse-move}: Called with five arguments when the mouse is moved:
208 @enumerate
210 @item
211 @var{x}: The x coordinate of the mouse cursor.
213 @item
214 @var{y}: The y coordinate of the mouse cursor.
216 @item
217 @var{dx}: The amount the mouse has moved along the x axis since the
218 last mouse move event.
220 @item
221 @var{dy}: The amount the mouse has moved along the y axis since the
222 last mouse move event.
224 @item
225 @var{buttons}: A list of the buttons that were pressed down when the
226 mouse was moved.
228 @end enumerate
230 @item
231 @var{controller-add}: Called with a single argument, an SDL game
232 controller object, when a game controller is connected.
234 @item
235 @var{controller-remove}: Called with a single argument, an SDL game
236 controller object, when a game controller is disconnected.
238 @item
239 @var{controller-press}: Called with two arguments when a button on a
240 game controller is pressed:
242 @enumerate
244 @item
245 @var{controller}: The controller that triggered the event.
247 @item
248 @var{button}: The symbolic name of the button that was pressed.
249 Possible buttons are:
251 @itemize
252 @item
253 @code{a}
254 @item
255 @code{b}
256 @item
257 @code{x}
258 @item
259 @code{y}
260 @item
261 @code{back}
262 @item
263 @code{guide}
264 @item
265 @code{start}
266 @item
267 @code{left-stick}
268 @item
269 @code{right-stick}
270 @item
271 @code{left-shoulder}
272 @item
273 @code{right-shoulder}
274 @item
275 @code{dpad-up}
276 @item
277 @code{dpad-down}
278 @item
279 @code{dpad-left}
280 @item
281 @code{dpad-right}
283 @end itemize
285 @end enumerate
287 @item
288 @var{controller-release}: Called with two arguments when a button on a
289 game controller is released:
291 @enumerate
293 @item
294 @var{controller}: The controller that triggered the event.
296 @item
297 @var{button}: The symbolic name of the button that was released.
299 @end enumerate
301 @item
302 @var{controller-move}: Called with three arguments when an analog
303 stick or trigger on a game controller is moved:
305 @enumerate
307 @item
308 @var{controller}: The controller that triggered the event.
310 @item
311 @var{axis}: The symbolic name of the axis that was moved. Possible
312 values are:
314 @itemize
315 @item
316 @code{left-x}
317 @item
318 @code{left-y}
319 @item
320 @code{right-x}
321 @item
322 @code{right-y}
323 @item
324 @code{trigger-left}
325 @item
326 @code{trigger-right}
327 @end itemize
329 @end enumerate
331 @item
332 @var{error}: Called with three arguments when an error occurs:
334 @enumerate
336 @item
337 @var{stack}: The call stack at the point of error.
339 @item
340 @var{key}: The exception key.
342 @item
343 @var{args}: The arguments thrown with the exception.
345 @end enumerate
347 The default behavior is to re-throw the error.
349 @end itemize
351 @end deffn
353 @node Math
354 @section Math
356 Chickadee contains data types and procedures for performing the most
357 common computations in video game simulations such as linear algebra
358 with vectors and matrices and axis-aligned bounding box collision
359 detection.
361 @menu
362 * Basics:: Commonly used, miscellaneous things.
363 * Vectors:: Euclidean vectors.
364 * Rectangles:: Axis-aligned bounding boxes.
365 * Grid:: Spatial partitioning for bounding boxes.
366 * Matrices:: Transformation matrices.
367 * Quaternions:: Rotations about an arbitrary axis.
368 * Easings:: Easing functions for interesting animations.
369 * Bezier Curves:: Cubic Bezier curves and paths in 2D space.
370 * Path Finding:: Generic A* path finding.
371 @end menu
373 @node Basics
374 @subsection Basics
376 @defvar pi
377 An essential constant for all trigonometry. Pi is the ratio of a
378 circle's circumferences to its diameter. Since pi is an irrational
379 number, the @var{pi} in Chickadee is a mere floating point
380 approximation that is ``good enough.''
381 @end defvar
383 @defvar pi/2
384 Half of @var{pi}.
385 @end defvar
387 @deffn {Procedure} cotan z
388 Return the cotangent of @var{z}.
389 @end deffn
391 @node Vectors
392 @subsection Vectors
394 Unlike Scheme's vector data type, which is a sequence of arbitrary
395 Scheme objects, Chickadee's @code{(chickadee math vector)} module
396 provides vectors in the linear algebra sense: Sequences of numbers
397 specialized for particular coordinate spaces. As of now, Chickadee
398 provides 2D and 3D vectors, with 4D vector support coming in a future
399 release.
401 Here's a quick example of adding two vectors:
403 @example
404 (define v (vec2+ (vec2 1 2) (vec2 3 4)))
405 @end example
407 Since vectors are used so frequently, the reader macro @code{#v} is
408 used to cut down on typing:
410 @example
411 (define v (vec2+ #v(1 2) #v(3 4)))
412 @end example
414 @subsubsection A Note About Performance
416 A lot of time has been spent making Chickadee's vector operations
417 perform relatively efficiently in critical code paths where excessive
418 garbage generation will cause major performance issues. The general
419 rule is that procedures ending with @code{!} perform an in-place
420 modification of one of the arguments in order to avoid allocating a
421 new vector. These procedures are also inlined by Guile's compiler in
422 order to take advantage of optimizations relating to floating point
423 math operations. The downside is that since these are not pure
424 functions, they do not compose well and create more verbose code.
426 @subsubsection 2D Vectors
428 @deffn {Procedure} vec2 x y
429 Return a new 2D vector with coordinates (@var{x}, @var{y}).
430 @end deffn
432 @deffn {Procedure} vec2/polar r theta
433 Return a new 2D vector containing the Cartesian representation of the
434 polar coordinate (@var{r}, @var{theta}). The angle @var{theta} is
435 measured in radians.
436 @end deffn
438 @deffn {Procedure} vec2? obj
439 Return @code{#t} if @var{obj} is a 2D vector.
440 @end deffn
442 @deffn {Procedure} vec2-x v
443 Return the X coordinate of the 2D vector @var{v}.
444 @end deffn
446 @deffn {Procedure} vec2-y v
447 Return the Y coordinate of the 2D vector @var{v}.
448 @end deffn
450 @deffn {Procedure} vec2-copy v
451 Return a fresh copy of the 2D vector @var{v}.
452 @end deffn
454 @deffn {Procedure} vec2-magnitude v
455 Return the magnitude of the 2D vector @var{v}.
456 @end deffn
458 @deffn {Procedure} vec2-dot-product v1 v2
459 Return the dot product of the 2D vectors @var{v1} and @var{v2}.
460 @end deffn
462 @deffn {Procedure} vec2-normalize v
463 Return the normalized form of the 2D vector @var{v}.
464 @end deffn
466 @deffn {Procedure} vec2+ v x
467 Add @var{x}, either a 2D vector or a scalar (i.e. a real number), to
468 the 2D vector @var{v} and return a new vector containing the sum.
469 @end deffn
471 @deffn {Procedure} vec2- v x
472 Subtract @var{x}, either a 2D vector or a scalar, from the 2D vector
473 @var{v} and return a new vector containing the difference.
474 @end deffn
476 @deffn {Procedure} vec2* v x
477 Multiply the 2D vector @var{v} by @var{x}, a 2D vector or a scalar,
478 and return a new vector containing the product.
479 @end deffn
481 @deffn {Procedure} set-vec2-x! v x
482 Set the X coordinate of the 2D vector @var{v} to @var{x}.
483 @end deffn
485 @deffn {Procedure} set-vec2-y! v y
486 Set the Y coordinate of the 2D vector @var{v} to @var{y}.
487 @end deffn
489 @deffn {Procedure} set-vec2! v x y
490 Set the X and Y coordinates of the 2D vector @var{v} to @var{x} and
491 @var{y}, respectively.
492 @end deffn
494 @deffn {Procedure} vec2-copy! source target
495 Copy the 2D vector @var{source} into the 2D vector @var{target}.
496 @end deffn
498 @deffn {Procedure} vec2-add! v x
499 Perform an in-place modification of the 2D vector @var{v} by adding
500 @var{x}, a 2D vector or a scalar.
501 @end deffn
503 @deffn {Procedure} vec2-sub! v x
504 Perform an in-place modification of the 2D vector @var{v} by
505 subtracting @var{x}, a 2D vector or a scalar.
506 @end deffn
508 @deffn {Procedure} vec2-mult! v x
509 Perform an in-place modification of the 2D vector @var{v} by
510 multiplying it by @var{x}, a 2D vector or a scalar.
511 @end deffn
513 @subsubsection 3D Vectors
515 @deffn {Procedure} vec3 x y
516 Return a new 2D vector with coordinates (@var{x}, @var{y}).
517 @end deffn
519 @deffn {Procedure} vec3? obj
520 Return @code{#t} if @var{obj} is a 3D vector.
521 @end deffn
523 @deffn {Procedure} vec3-x v
524 Return the X coordinate of the 3D vector @var{v}.
525 @end deffn
527 @deffn {Procedure} vec3-y v
528 Return the Y coordinate of the 3D vector @var{v}.
529 @end deffn
531 @deffn {Procedure} vec3-z v
532 Return the Z coordinate of the 3D vector @var{v}.
533 @end deffn
535 @deffn {Procedure} vec3-copy v
536 Return a fresh copy of the 3D vector @var{v}.
537 @end deffn
539 @deffn {Procedure} vec3-magnitude v
540 Return the magnitude of the 3D vector @var{v}.
541 @end deffn
543 @deffn {Procedure} vec3-dot-product v1 v2
544 Return the dot product of the 3D vectors @var{v1} and @var{v2}.
545 @end deffn
547 @deffn {Procedure} vec3-normalize v
548 Return the normalized form of the 3D vector @var{v}.
549 @end deffn
551 @deffn {Procedure} vec3+ v x
552 Add @var{x}, either a 3D vector or a scalar (i.e. a real number), to
553 the 3D vector @var{v} and return a new vector containing the sum.
554 @end deffn
556 @deffn {Procedure} vec3- v x
557 Subtract @var{x}, either a 3D vector or a scalar, from the 3D vector
558 @var{v} and return a new vector containing the difference.
559 @end deffn
561 @deffn {Procedure} vec3* v x
562 Multiply the 3D vector @var{v} by @var{x}, a 3D vector or a scalar,
563 and return a new vector containing the product.
564 @end deffn
566 @deffn {Procedure} set-vec3-x! v x
567 Set the X coordinate of the 3D vector @var{v} to @var{x}.
568 @end deffn
570 @deffn {Procedure} set-vec3-y! v y
571 Set the Y coordinate of the 3D vector @var{v} to @var{y}.
572 @end deffn
574 @deffn {Procedure} set-vec3-z! v z
575 Set the Z coordinate of the 3D vector @var{v} to @var{z}.
576 @end deffn
578 @deffn {Procedure} set-vec3! v x y z
579 Set the X, Y, and Z coordinates of the 3D vector @var{v} to @var{x},
580 @var{y}, and @var{z}, respectively.
581 @end deffn
583 @deffn {Procedure} vec3-copy! source target
584 Copy the 3D vector @var{source} into the 3D vector @var{target}.
585 @end deffn
587 @deffn {Procedure} vec3-add! v x
588 Perform an in-place modification of the 3D vector @var{v} by adding
589 @var{x}, a 3D vector or a scalar.
590 @end deffn
592 @deffn {Procedure} vec3-sub! v x
593 Perform an in-place modification of the 3D vector @var{v} by
594 subtracting @var{x}, a 3D vector or a scalar.
595 @end deffn
597 @deffn {Procedure} vec3-mult! v x
598 Perform an in-place modification of the 3D vector @var{v} by
599 multiplying it by @var{x}, a 3D vector or a scalar.
600 @end deffn
602 @node Rectangles
603 @subsection Rectangles
605 The @code{(chickadee math rect)} module provides an API for
606 manipulating axis-aligned bounding boxes (AABBs). AABBs are often
607 used for collision detection in games. Common use-cases are defining
608 ``hitboxes'' in platformers or using them for the ``broad phase'' of a
609 collision detection algorithm that uses a more complex (and thus
610 slower) method of determining the actual collisions.
612 Like some of the other math modules, there exists a collection of
613 functions that do in-place modification of rectangles for use in
614 performance critical code paths.
616 @deffn {Procedure} rect x y width height
617 @deffnx {Procedure} make-rect @var{x} @var{y} @var{width} @var{height}
618 Create a new rectangle that is @var{width} by @var{height} in size and
619 whose bottom-left corner is located at (@var{x}, @var{y}).
620 @end deffn
622 @deffn {Procedure} rect? obj
623 Return @code{#t} if @var{obj} is a rectangle.
624 @end deffn
626 @deffn {Procedure} rect-within? rect1 rect2
627 Return @code{#t} if @var{rect2} is completely within @var{rect1}.
628 @end deffn
630 @deffn {Procedure} rect-intersects? rect1 rect2
631 Return @code{#t} if @var{rect2} overlaps @var{rect1}.
632 @end deffn
634 @deffn {Procedure} rect-contains? rect x y
635 Return @code{#t} if the coordinates (@var{x}, @var{y}) are within
636 @var{rect}.
637 @end deffn
639 @deffn {Procedure} rect-contains-vec2? rect v
640 Return @code{#t} if the 2D vector @var{v} is within the bounds of
641 @var{rect}.
642 @end deffn
644 @deffn {Procedure} rect-x rect
645 Return the X coordinate of the lower-left corner of @var{rect}.
646 @end deffn
648 @deffn {Procedure} rect-y rect
649 Return the Y coordinate of the lower-left corner of @var{rect}.
650 @end deffn
652 @deffn {Procedure} rect-left rect
653 Return the left-most X coordinate of @var{rect}.
654 @end deffn
656 @deffn {Procedure} rect-right rect
657 Return the right-most X coordinate of @var{rect}.
658 @end deffn
660 @deffn {Procedure} rect-bottom rect
661 Return the bottom-most Y coordinate of @var{rect}.
662 @end deffn
664 @deffn {Procedure} rect-top rect
665 Return the top-most Y coordinate of @var{rect}.
666 @end deffn
668 @deffn {Procedure} rect-center-x rect
669 Return the X coordinate of the center of @var{rect}.
670 @end deffn
672 @deffn {Procedure} rect-center-y rect
673 Return the Y coordinate of the center of @var{rect}.
674 @end deffn
676 @deffn {Procedure} rect-width rect
677 Return the width of @var{rect}.
678 @end deffn
680 @deffn {Procedure} rect-height rect
681 Return the height of @var{rect}.
682 @end deffn
684 @deffn {Procedure} rect-area rect
685 Return the surface area covered by @var{rect}.
686 @end deffn
688 @deffn {Procedure} rect-clamp-x rect x
689 Restrict @var{x} to the portion of the X axis covered by @var{rect}.
690 @end deffn
692 @deffn {Procedure} rect-clamp-y rect y
693 Restrict @var{y} to the portion of the Y axis covered by @var{rect}.
694 @end deffn
696 @deffn {Procedure} rect-clamp rect1 rect2
697 Return a new rect that adjusts the location of @var{rect1} so that it
698 is completely within @var{rect2}. An exception is thrown in the case
699 that @var{rect1} cannot fit completely within @var{rect2}.
700 @end deffn
702 @deffn {Procedure} rect-move rect x y
703 Return a new rectangle based on @var{rect} but moved to the
704 coordinates (@var{x}, @var{y}).
705 @end deffn
707 @deffn {Procedure} rect-move-vec2 rect v
708 Return a new rectangle based on @var{rect} but moved to the
709 coordinates in the 2D vector @var{v}.
710 @end deffn
712 @deffn {Procedure} rect-move-by rect x y
713 Return a new rectangle based on @var{rect} but moved by (@var{x},
714 @var{y}) units relative to its current location.
715 @end deffn
717 @deffn {Procedure} rect-move-by-vec2 rect v
718 Return a new rectangle based on @var{rect} but moved by the 2D vector
719 @var{v} relative to its current location.
720 @end deffn
722 @deffn {Procedure} rect-inflate rect width height
723 Return a new rectangle based on @var{rect}, but expanded by
724 @var{width} units on the X axis and @var{height} units on the Y axis,
725 while keeping the rectangle centered on the same point.
726 @end deffn
728 @deffn {Procedure} rect-union rect1 rect2
729 Return a new rectangle that completely covers the area of @var{rect1}
730 and @var{rect2}.
731 @end deffn
733 @deffn {Procedure} rect-clip rect1 rect2
734 Return a new rectangle that is the overlapping region of @var{rect1}
735 and @var{rect2}. If the two rectangles do not overlap, a rectangle of
736 0 width and 0 height is returned.
737 @end deffn
739 @deffn {Procedure} set-rect-x! rect x
740 Set the left X coordinate of @var{rect} to @var{x}.
741 @end deffn
743 @deffn {Procedure} set-rect-y! rect y
744 Set the bottom Y coordinate of @var{rect} to @var{y}.
745 @end deffn
747 @deffn {Procedure} set-rect-width! rect width
748 Set the width of @var{rect} to @var{width}.
749 @end deffn
751 @deffn {Procedure} set-rect-height! rect height
752 Set the height of @var{rect} to @var{height}.
753 @end deffn
755 @deffn {Procedure} rect-move! rect x y
756 Move @var{rect} to (@var{x}, @var{y}) in-place.
757 @end deffn
759 @deffn {Procedure} rect-move-vec2! rect v
760 Move @var{rect} to the 2D vector @var{v} in-place.
761 @end deffn
763 @deffn {Procedure} rect-move-by! rect x y
764 Move @var{rect} by (@var{x}, @var{y}) in-place.
765 @end deffn
767 @deffn {Procedure} rect-move-by-vec2! rect v
768 Move @var{rect} by the 2D vector @var{v} in-place.
769 @end deffn
771 @deffn {Procedure} rect-inflate! rect width height
772 Expand @var{rect} by @var{width} and @var{height} in-place.
773 @end deffn
775 @deffn {Procedure} rect-union! rect1 rect2
776 Modify @var{rect1} in-place to completely cover the area of both
777 @var{rect1} and @var{rect2}.
778 @end deffn
780 @deffn {Procedure} rect-clip! rect1 rect2
781 Modify @var{rect1} in-place to be the overlapping region of
782 @var{rect1} and @var{rect2}.
783 @end deffn
785 @deffn {Procedure} rect-clamp! rect1 rect2
786 Adjust the location of @var{rect1} in-place so that its bounds are
787 completely within @var{rect2}. An exception is thrown in the case
788 that @var{rect1} cannot fit completely within @var{rect2}.
789 @end deffn
791 @deffn {Procedure} vec2-clamp-to-rect! v rect
792 Restrict the coordinates of the 2D vector @var{v} so that they are
793 within the bounds of @var{rect}. @var{v} is modified in-place.
794 @end deffn
796 @node Grid
797 @subsection Grid
799 The @code{(chickadee math grid)} module provides a simple spatial
800 partitioning system for axis-aligned bounding boxes
801 (@pxref{Rectangles}) in 2D space. The grid divides the world into
802 tiles and keeps track of which rectangles occupy which tiles. When
803 there are lots of moving objects in the game world that need collision
804 detection, the grid greatly speeds up the process. Instead of
805 checking collisions of each object against every other object (an
806 O(n^2) operation), the grid quickly narrows down which objects could
807 possibly be colliding and only performs collision testing against a
808 small set of objects.
810 In addition to checking for collisions, the grid also handles the
811 resolution of collisions. Exactly how each collision is resolved is
812 user-defined. A player bumping into a wall may slide against it. An
813 enemy colliding with a projectile shot by the player may get pushed
814 back in the opposite direction. Two players colliding may not need
815 resolution at all and will just pass through each other. The way this
816 works is that each time an object (A) is moved within the grid, the
817 grid looks for an object (B) that may possibly be colliding with A. A
818 user-defined procedure known as a ``filter'' is then called with both
819 A and B. If the filter returns @code{#f}, it means that even if A and
820 B are colliding, no collision resolution is needed. In this case the
821 grid won't waste time checking if they really do collide because it
822 doesn't matter. If A and B are collidable, then the filter returns a
823 procedure that implements the resolution technique. The grid will
824 then perform a collision test. If A and B are colliding, the resolver
825 procedure is called. It's the resolvers job to adjust the objects
826 such that they are no longer colliding. The grid module comes with a
827 very simple resolution procedure, @code{slide}, that adjusts object A
828 by the smallest amount so that it no longer overlaps with B. By using
829 this filtering technique, a game can resolve collisions between
830 different objects in different ways.
832 @deffn {Procedure} make-grid [cell-size 64]
833 Return a new grid partitioned into @var{cell-size} tiles.
834 @end deffn
836 @deffn {Procedure} grid? obj
837 Return @code{#t} if @var{obj} is a grid.
838 @end deffn
840 @deffn {Procedure} cell? obj
841 Return @code{#t} if @var{obj} is a grid cell.
842 @end deffn
844 @deffn {Procedure} cell-count cell
845 Return the number of items in @var{cell}.
846 @end deffn
848 @deffn {Procedure} grid-cell-size grid
849 Return the cell size of @var{grid}.
850 @end deffn
852 @deffn {Procedure} grid-cell-count grid
853 Return the number of cells currently in @var{grid}.
854 @end deffn
856 @deffn {Procedure} grid-item-count grid
857 Return the number of items in @var{grid}.
858 @end deffn
860 @deffn {Procedure} grid-add grid item x y @
861 width height
863 Add @var{item} to @var{grid} represented by the axis-aligned bounding
864 box whose lower-left corner is at (@var{x}, @var{y}) and is
865 @var{width} x @var{height} in size.
866 @end deffn
868 @deffn {Procedure} grid-remove grid item
869 Return @var{item} from @var{grid}.
870 @end deffn
872 @deffn {Procedure} grid-clear grid
873 Remove all items from @var{grid}.
874 @end deffn
876 @deffn {Procedure} grid-move grid item position filter
877 Attempt to move @var{item} in @var{grid} to @var{position} (a 2D
878 vector) and check for collisions. For each collision, @var{filter}
879 will be called with two arguments: @var{item} and the item it collided
880 with. If a collision occurs, @var{position} may be modified to
881 resolve the colliding objects.
882 @end deffn
884 @deffn {Procedure} for-each-cell proc grid [rect]
885 Call @var{proc} with each cell in @var{grid} that intersects
886 @var{rect}, or every cell if @var{rect} is @code{#f}.
887 @end deffn
889 @deffn {Procedure} for-each-item proc grid
890 Call @var{proc} for each item in @var{grid}.
891 @end deffn
893 @deffn {Procedure} slide item item-rect other other-rect goal
895 Resolve the collision that occurs between @var{item} and @var{other}
896 when moving @var{item-rect} to @var{goal} by sliding @var{item-rect}
897 the minimum amount needed to make it no longer overlap
898 @var{other-rect}.
899 @end deffn
901 @node Matrices
902 @subsection Matrices
904 The @code{(chickadee math matrix)} module provides an interface for
905 working with the most common type of matrices in game development: 4x4
906 transformation matrices.
908 @subsubsection Another Note About Performance
910 Much like the vector API, the matrix API is commonly used in
911 performance critical code paths. In order to reduce the amount of
912 garbage generated and improve matrix multiplication performance, there
913 are many procedures that perform in-place modifications of matrix
914 objects.
916 @subsubsection Matrix Operations
918 @deffn {Procedure} make-matrix4 aa ab ac ad @
919 ba bb bc bd @
920 ca cb cc cd @
921 da db dc dd
923 Return a new 4x4 matrix initialized with the given 16 values in
924 column-major format.
925 @end deffn
927 @deffn {Procedure} make-null-matrix4
928 Return a new 4x4 matrix with all values initialized to 0.
929 @end deffn
931 @deffn {Procedure} make-identity-matrix4
932 Return a new 4x4 identity matrix. Any matrix multiplied by the
933 identity matrix yields the original matrix. This procedure is
934 equivalent to the following code:
936 @example
937 (make-matrix4 1 0 0 0
938 0 1 0 0
939 0 0 1 0
940 0 0 0 1)
941 @end example
943 @end deffn
945 @deffn {Procedure} matrix4? obj
946 Return @code{#t} if @var{obj} is a 4x4 matrix.
947 @end deffn
949 @deffn {Procedure} matrix4* . matrices
950 Return a new 4x4 matrix containing the product of multiplying all of
951 the given @var{matrices}.
953 Note: Remember that matrix multiplication is @strong{not} commutative!
954 @end deffn
956 @deffn {Procedure} orthographic-projection left right top bottom near far
958 Return a new 4x4 matrix that represents an orthographic (2D)
959 projection for the horizontal clipping plane @var{top} and
960 @var{bottom}, the vertical clipping plane @var{top} and @var{bottom},
961 and the depth clipping plane @var{near} and @var{far}.
962 @end deffn
964 @deffn {Procedure} perspective-projection fov aspect-ratio near far
966 Return a new 4x4 matrix that represents a perspective (3D) projection
967 with a field of vision of @var{fov} radians, an aspect ratio of
968 @var{aspect-ratio}, and a depth clipping plane defined by @var{near}
969 and @var{far}.
970 @end deffn
972 @deffn {Procedure} matrix4-translate x
973 Return a new 4x4 matrix that represents a translation by @var{x}, a 2D
974 vector, a 3D vector, or a rectangle (in which case the bottom-left
975 corner of the rectangle is used).
976 @end deffn
978 @deffn {Procedure} matrix4-scale s
979 Return a new 4x4 matrix that represents a scaling along the X, Y, and
980 Z axes by the scaling factor @var{s}, a real number.
981 @end deffn
983 @deffn {Procedure} matrix4-rotate q
984 Return a new 4x4 matrix that represents a rotation about an arbitrary
985 axis defined by the quaternion @var{q}.
986 @end deffn
988 @deffn {Procedure} matrix4-rotate-z theta
989 Return a new 4x4 matrix that represents a rotation about the Z axis by
990 @var{theta} radians.
991 @end deffn
993 @deffn {Procedure} matrix4-identity! matrix
994 Modify @var{matrix} in-place to contain the identity matrix.
995 @end deffn
997 @deffn {Procedure} matrix4-mult! dest a b
998 Multiply the 4x4 matrix @var{a} by the 4x4 matrix @var{b} and store
999 the result in the 4x4 matrix @var{dest}.
1000 @end deffn
1002 @deffn {Procedure} matrix4-translate! matrix x
1003 Modify @var{matrix} in-place to contain a translation by @var{x}, a 2D
1004 vector, a 3D vector, or a rectangle (in which case the bottom-left
1005 corner of the rectangle is used).
1006 @end deffn
1008 @deffn {Procedure} matrix4-scale! matrix s
1009 Modify @var{matrix} in-place to contain a scaling along the X, Y, and
1010 Z axes by the scaling factor @var{s}, a real number.
1011 @end deffn
1013 @deffn {Procedure} matrix4-rotate! matrix q
1014 Modify @var{matrix} in-place to contain a rotation about an arbitrary
1015 axis defined by the quaternion @var{q}.
1016 @end deffn
1018 @deffn {Procedure} matrix4-rotate-z! matrix theta
1019 Modify @var{matrix} in-place to contain a rotation about the Z axis by
1020 @var{theta} radians.
1021 @end deffn
1023 @deffn {Procedure} matrix4-2d-transform! matrix [#:origin] @
1024 [#:position] [#:rotation] @
1025 [#:scale] [#:skew]
1027 Modify @var{matrix} in-place to contain the transformation described
1028 by @var{position}, a 2D vector or rectangle, @var{rotation}, a scalar
1029 representing a rotation about the Z axis, @var{scale}, a 2D vector,
1030 and @var{skew}, a 2D vector. The transformation happens with respect
1031 to @var{origin}, a 2D vector. If an argument is not provided, that
1032 particular transformation will not be included in the result.
1033 @end deffn
1035 @deffn {Procedure} transform! matrix v
1036 Modify the 2D vector @var{v} in-place by multiplying it by the 4x4
1037 matrix @var{matrix}.
1038 @end deffn
1040 @node Quaternions
1041 @subsection Quaternions
1043 In game development, the quaternion is most often used to represent
1044 rotations. Why not use a matrix for that, you may ask. Unlike
1045 matrices, quaternions can be interpolated (animated) and produce a
1046 meaningful result. When interpolating two quaternions, there is a
1047 smooth transition from one rotation to another, whereas interpolating
1048 two matrices would yield garbage.
1050 @deffn {Procedure} quaternion x y z w
1051 Return a new quaternion with values @var{x}, @var{y}, @var{z}, and
1052 @var{w}.
1053 @end deffn
1055 @deffn {Procedure} quaternion? obj
1056 Return @code{#t} if @var{obj} is a quaternion.
1057 @end deffn
1059 @deffn {Procedure} quaternion-w q
1060 Return the W component of the quaternion @var{q}.
1061 @end deffn
1063 @deffn {Procedure} quaternion-x q
1064 Return the X component of the quaternion @var{q}.
1065 @end deffn
1067 @deffn {Procedure} quaternion-y q
1068 Return the Y component of the quaternion @var{q}.
1069 @end deffn
1071 @deffn {Procedure} quaternion-z q
1072 Return the Z component of the quaternion @var{q}.
1073 @end deffn
1075 @deffn {Procedure} make-identity-quaternion
1076 Return the identity quaternion.
1077 @end deffn
1079 @node Easings
1080 @subsection Easings
1082 Easing functions are essential for animation. Each easing function
1083 provides a different path to go from an initial value to a final
1084 value. These functions make an excellent companion to the
1085 @code{tween} procedure (@pxref{Tweening}). Experiment with them to
1086 figure out which function makes an animation look the best.
1088 Pro tip: @code{smoothstep} provides nice results most of the time and
1089 creates smoother animation than using @code{linear}.
1091 @deffn {Procedure} linear t
1092 @end deffn
1094 @deffn {Procedure} smoothstep t
1095 @end deffn
1097 @deffn {Procedure} ease-in-quad t
1098 @end deffn
1100 @deffn {Procedure} ease-out-quad t
1101 @end deffn
1103 @deffn {Procedure} ease-in-out-quad t
1104 @end deffn
1106 @deffn {Procedure} ease-in-cubic t
1107 @end deffn
1109 @deffn {Procedure} ease-out-cubic t
1110 @end deffn
1112 @deffn {Procedure} ease-in-out-cubic t
1113 @end deffn
1115 @deffn {Procedure} ease-in-quart t
1116 @end deffn
1118 @deffn {Procedure} ease-out-quart t
1119 @end deffn
1121 @deffn {Procedure} ease-in-out-quart t
1122 @end deffn
1124 @deffn {Procedure} ease-in-quint t
1125 @end deffn
1127 @deffn {Procedure} ease-out-quint t
1128 @end deffn
1130 @deffn {Procedure} ease-in-out-quint t
1131 @end deffn
1133 @deffn {Procedure} ease-in-sine t
1134 @end deffn
1136 @deffn {Procedure} ease-out-sine t
1137 @end deffn
1139 @deffn {Procedure} ease-in-out-sine t
1140 @end deffn
1142 @node Bezier Curves
1143 @subsection Bezier Curves
1145 The @code{(chickadee math bezier)} module provides an API for
1146 describing cubic Bezier curves in 2D space. These curves are notably
1147 used in font description, vector graphics programs, and when it comes
1148 to games: path building. With Bezier curves, it's somewhat easy to
1149 create a smooth looking path for an enemy to move along, for example.
1150 Bezier curves become particularly interesting when they are chained
1151 together to form a Bezier ``path'', where the end point of one curve
1152 becomes the starting point of the next.
1154 Currently, the rendering of Bezier curves is rather crude and provided
1155 mostly for visualizing and debugging curves that would be unseen in
1156 the final game. See @xref{Lines and Shapes} for more information.
1158 @deffn {Procedure} make-bezier-curve p0 p1 p2 p3
1159 Return a new Bezier curve object whose starting point is @var{p0},
1160 ending point is @var{p3}, and control points are @var{p1} and
1161 @var{p2}. All points are 2D vectors.
1162 @end deffn
1164 @deffn {Procedure} bezier-curve? obj
1165 Return @code{#t} if @var{obj} is a Bezier curve.
1166 @end deffn
1168 @deffn {Procedure} bezier-curve-p0 bezier
1169 Return the starting point of @var{bezier}.
1170 @end deffn
1172 @deffn {Procedure} bezier-curve-p1 bezier
1173 Return the first control point of @var{bezier}.
1174 @end deffn
1176 @deffn {Procedure} bezier-curve-p2 bezier
1177 Return the second control point of @var{bezier}.
1178 @end deffn
1180 @deffn {Procedure} bezier-curve-p3 bezier
1181 Return the end point of @var{bezier}.
1182 @end deffn
1184 @deffn {Procedure} bezier-path . control-points
1185 Return a list of connected bezier curves defined by
1186 @var{control-points}. The first curve is defined by the first 4
1187 arguments and every additional curve thereafter requires 3 additional
1188 arguments.
1189 @end deffn
1191 @deffn {Procedure} bezier-curve-point-at bezier t
1192 Return the coordinates for @var{bezier} at @var{t} (a value in the
1193 range [0, 1] representing how far from the start of the curve to
1194 check) as a 2D vector.
1195 @end deffn
1197 @deffn {Procedure} bezier-curve-point-at! dest bezier t
1198 Modify the 2D vector @var{dest} in-place to contain the coordinates
1199 for @var{bezier} at @var{t}.
1200 @end deffn
1202 @node Path Finding
1203 @subsection Path Finding
1205 Most game worlds have maps. Often, these games have a need to move
1206 non-player characters around in an unscripted fashion. For example,
1207 in a real-time strategy game, the player may command one of their
1208 units to attack something in the enemy base. To do so, the unit must
1209 calculate the shortest route to get there. It wouldn't be a very fun
1210 game if units didn't know how to transport themselves efficiently.
1211 This is where path finding algorithms come in handy. The
1212 @code{(chickadee math path-finding)} module provides a generic
1213 implementation of the popular A* path finding algorithm. Just add a
1214 map implementation!
1216 The example below defines a very simple town map and finds the
1217 quickest way to get from the town common to the school.
1219 @example
1220 (define world-map
1221 '((town-common . (town-hall library))
1222 (town-hall . (town-common school))
1223 (library . (town-common cafe))
1224 (school . (town-hall cafe))
1225 (cafe . (library school))))
1226 (define (neighbors building)
1227 (assq-ref town-map building))
1228 (define (cost a b) 1)
1229 (define (distance a b) 1)
1230 (define pf (make-path-finder))
1231 (a* pf 'town-common 'school neighbors cost distance)
1232 @end example
1234 In this case, the @code{a*} procedure will return the list
1235 @code{(town-common town-hall school)}, which is indeed the shortest
1236 route. (The other possible route is @code{(town-common library cafe
1237 school)}.)
1239 The @code{a*} procedure does not know anything about about any kind of
1240 map and therefore must be told how to look up neighboring nodes, which
1241 is what the @code{neighbors} procedure in the example does. To
1242 simulate different types of terrain, a cost procedure is used. In
1243 this example, it is just as easy to move between any two nodes because
1244 @code{cost} always returns 1. In a real game, perhaps moving from
1245 from a field to a rocky hill would cost a lot more than moving from
1246 one field to another. Finally, a heuristic is used to calculate an
1247 approximate distance between two nodes on the map. In this simple
1248 association list based graph it is tough to calculate a distance
1249 between nodes, so the @code{distance} procedure isn't helpful and
1250 always returns 1. In a real game with a tile-based map, for example,
1251 the heuristic could be a quick Manhattan distance calculation based on
1252 the coordinates of the two map tiles. Choose an appropriate heuristic
1253 for optimal path finding!
1255 @deffn {Procedure} make-path-finder
1256 Return a new path finder object.
1257 @end deffn
1259 @deffn {Procedure} path-finder? obj
1260 Return @code{#t} if @var{obj} is a path finder.
1261 @end deffn
1263 @deffn {Procedure} a* path-finder start goal neighbors cost distance
1265 Return a list of nodes forming a path from @var{start} to @var{goal}
1266 using @var{path-finder} to hold state. @var{neighbors} is a procedure
1267 that accepts a node and returns a list of nodes that neighbor it.
1268 @var{cost} is a procedure that accepts two neighboring nodes and
1269 returns the cost of moving from the first to the second as a real
1270 number. @var{distance} is a procedure that accepts two nodes and
1271 returns an approximate distance between them.
1272 @end deffn
1274 @node Graphics
1275 @section Graphics
1277 Chickadee aims to make hardware-accelerated graphics rendering as
1278 simple and efficient as possible by providing high-level APIs that
1279 interact with the low-level OpenGL API under the hood. Anyone that
1280 has worked with OpenGL directly knows that it has a steep learning
1281 curve and a lot of effort is needed to render even a single triangle.
1282 The Chickadee rendering engine attempts to make it easy to do common
1283 tasks like rendering a sprite while also providing all of the building
1284 blocks to implement additional rendering techniques.
1286 @menu
1287 * Textures:: 2D images.
1288 * Sprites:: Draw 2D images.
1289 * Tile Maps:: Draw 2D tile maps.
1290 * Lines and Shapes:: Draw line segments and polygons.
1291 * Fonts:: Drawing text.
1292 * Particles:: Pretty little flying pieces!
1293 * Blending:: Control how pixels are combined.
1294 * Framebuffers:: Render to texture.
1295 * Viewports:: Restrict rendering to a particular area.
1296 * Rendering Engine:: Rendering state management.
1297 * Buffers:: Send data to the GPU.
1298 * Shaders:: Create custom GPU programs.
1299 @end menu
1301 @node Textures
1302 @subsection Textures
1304 @deffn {Procedure} load-image file [#:min-filter nearest] @
1305 [#:mag-filter nearest] [#:wrap-s repeat] [#:wrap-t repeat]
1307 Load the image data from @var{file} and return a new texture object.
1309 @var{min-filter} and @var{mag-filter} describe the method that should
1310 be used for minification and magnification when rendering,
1311 respectively. Possible values are @code{nearest} and @code{linear}.
1313 @var{wrap-s} and @var{wrap-t} describe how to interpret texture
1314 coordinates that are greater than @code{1.0}. Possible values are
1315 @code{repeat}, @code{clamp}, @code{clamp-to-border}, and
1316 @code{clamp-to-edge}.
1318 @end deffn
1320 @deffn {Procedure} texture? obj
1321 Return @code{#t} if @var{obj} is a texture.
1322 @end deffn
1324 @deffn {Procedure} texture-region? obj
1325 Return @code{#t} if @var{obj} is a texture region.
1326 @end deffn
1328 @deffn {Procedure} texture-parent texture
1329 If @var{texture} is a texture region, return the full texture that it
1330 is based upon. Otherwise, return @code{#f}.
1331 @end deffn
1333 @deffn {Procedure} texture-min-filter texture
1334 Return the minification filter for @var{texture}, either
1335 @code{nearest} or @code{linear}.
1336 @end deffn
1338 @deffn {Procedure} texture-mag-filter texture
1339 Return the magnification filter for @var{texture}, either
1340 @code{nearest} or @code{linear}.
1341 @end deffn
1343 @deffn {Procedure} texture-wrap-s texture
1344 Return the method used for wrapping texture coordinates along the X
1345 axis for @var{texture}.
1347 Possible wrapping methods:
1348 @itemize
1349 @item @code{repeat}
1350 @item @code{clamp}
1351 @item @code{clamp-to-border}
1352 @item @code{clamp-to-edge}
1353 @end itemize
1355 @end deffn
1357 @deffn {Procedure} texture-wrap-t texture
1358 Return the method used for wrapping texture coordinates along the Y
1359 axis for @var{texture}.
1360 @end deffn
1362 @deffn {Procedure} texture-width texture
1363 Return the width of @var{texture} in pixels.
1364 @end deffn
1366 @deffn {Procedure} texture-height texture
1367 Return the height of @var{texture} in pixels.
1368 @end deffn
1370 It is common practice to combine multiple bitmap images into a single
1371 texture, known as a ``tile atlas'' or ``tile set'', because it is more
1372 efficient to render many regions of a large texture than it is to
1373 render a bunch of small textures. Chickadee provides a tile atlas
1374 data type for collecting texture regions into a single vector.
1376 @deffn {Procedure} split-texture texture tile-width tile-height @
1377 [#:margin 0] [#:spacing 0]
1379 Return a new texture atlas that splits @var{texture} into a grid of
1380 @var{tile-width} by @var{tile-height} rectangles. Optionally, each
1381 tile may have @var{spacing} pixels of horizontal and vertical space
1382 between surrounding tiles and the entire image may have @var{margin}
1383 pixels of empty space around its border.
1385 This type of texture atlas layout is very common for 2D tile maps.
1386 @xref{Tile Maps} for more information.
1387 @end deffn
1389 @deffn {Procedure} texture-atlas? obj
1390 Return @code{#t} if @var{obj} is a texture atlas.
1391 @end deffn
1393 @deffn {Procedure} texture-atlas-texture atlas
1394 Return the texture that all texture regions in @var{atlas} have been created from.
1395 @end deffn
1397 @deffn {Procedure} texture-atlas-ref atlas index
1398 Return the texture region in @var{atlas} at @var{index}.
1399 @end deffn
1401 @node Sprites
1402 @subsection Sprites
1404 For those who are new to this game, a sprite is a 2D rectangular
1405 bitmap that is rendered to the screen. For 2D games, sprites are the
1406 most essential graphical abstraction. They are used for drawing maps,
1407 players, NPCs, items, particles, text, etc. In Chickadee, bitmaps are
1408 stored in textures (@pxref{Textures}) and can be used to draw sprites
1409 via the @code{draw-sprite} procedure.
1411 @deffn {Procedure} draw-sprite texture position @
1412 [#:tint white] [#:origin] [#:scale] [#:rotation] [#:blend-mode alpha] @
1413 [#:rect]
1415 Draw @var{texture} at @var{position}.
1417 Optionally, other transformations may be applied to the sprite.
1418 @var{rotation} specifies the angle to rotate the sprite, in radians.
1419 @var{scale} specifies the scaling factor as a 2D vector. All
1420 transformations are applied relative to @var{origin}, a 2D vector,
1421 which defaults to the lower-left corner.
1423 @var{tint} specifies the color to multiply against all the sprite's
1424 pixels. By default white is used, which does no tinting at all.
1426 Alpha blending is used by default but the blending method can be
1427 changed by specifying @var{blend-mode}.
1429 The area drawn to is as big as the texture, by default. To draw to an
1430 arbitrary section of the screen, specify @var{rect}.
1431 @end deffn
1433 It's not uncommon to need to draw hundreds or thousands of sprites
1434 each frame. However, GPUs (graphics processing units) are tricky
1435 beasts that prefer to be sent few, large chunks of data to render
1436 rather than many, small chunks. Using @code{draw-sprite} on its own
1437 will involve at least one GPU call @emph{per sprite}. This is fine
1438 for rendering a few dozen sprites, but will become a serious
1439 bottleneck when rendering hundreds or thousands of sprites. To deal
1440 with this, a technique known as ``sprite batching'' is used. Instead
1441 of drawing each sprite immediately, the sprite batch will build up a
1442 large of buffer of sprites to draw and send them to the GPU all at
1443 once. There is one caveat, however. Batching only works if the
1444 sprites being drawn share a common texture. A good strategy for
1445 reducing the number of different textures is to stuff many bitmaps
1446 into a single image file and create a ``texture atlas''
1447 (@pxref{Textures}) to access the sub-images within.
1449 @deffn {Procedure} make-sprite-batch texture [#:capacity 256]
1450 Create a new sprite batch for @var{texture} with initial space for
1451 @var{capacity} sprites. Sprite batches automatically resize when they
1452 are full to accomodate as many sprites as necessary.
1453 @end deffn
1455 @deffn {Procedure} sprite-batch? obj
1456 Return @code{#t} if @var{obj} is a sprite batch.
1457 @end deffn
1459 @deffn {Procedure} sprite-batch-texture batch
1460 Return the texture for @var{batch}.
1461 @end deffn
1463 @deffn {Procedure} set-sprite-batch-texture! batch texture
1464 Set texture for @var{batch} to @var{texture}.
1465 @end deffn
1467 @deffn {Procedure} sprite-batch-add! batch position @
1468 [#:origin] [#:scale] [:rotation] @
1469 [#:tint @code{white}] [#:texture-region]
1471 Add sprite located at @var{position} to @var{batch}.
1473 To render a subsection of the batch's texture, a texture object whose
1474 parent is the batch texture may be specified as @var{texture-region}.
1476 See @code{draw-sprite} for information about the other arguments.
1477 @end deffn
1479 @deffn {Procedure} sprite-batch-clear! batch
1480 Reset size of @var{batch} to 0.
1481 @end deffn
1483 @deffn {Procedure} draw-sprite-batch batch [#:blend-mode @code{alpha}]
1484 Render @var{batch} using @var{blend-mode}. Alpha blending is used by
1485 default.
1486 @end deffn
1488 With a basic sprite abstraction in place, it's possible to build other
1489 abstractions on top of it. One such example is the ``nine patch''. A
1490 nine patch is a sprite that can be rendered at various sizes without
1491 becoming distorted. This is achieved by dividing up the sprite into
1492 nine regions:
1494 @itemize
1495 @item
1496 the center, which can be scaled horizontally and vertically
1497 @item
1498 the four corners, which can never be scaled
1499 @item
1500 the left and right sides, which can be scaled vertically
1501 @item
1502 the top and bottom sides, which can be scaled horizontally
1503 @end itemize
1505 The one caveat is that the bitmap regions must be designed in such a
1506 way so that they are not distorted when stretched along the affected
1507 axes. For example, that means that the top and bottom sides could
1508 have varying colored pixels vertically, but not horizontally.
1510 The most common application of this technique is for graphical user
1511 interface widgets like buttons and dialog boxes. By using a nine
1512 patch, they can be rendered at any size without unappealing scaling
1513 artifacts.
1515 @deffn {Procedure} draw-nine-patch texture rect @
1516 [#:margin 0] [#:top-margin margin] [#:bottom-margin margin] @
1517 [#:left-margin margin] [#:right-margin margin] @
1518 [#:origin] [#:scale] [#:rotation] [#:blend-mode alpha] @
1519 [#:tint white]
1521 Draw a nine patch sprite. A nine patch sprite renders @var{texture}
1522 as a @var{width} x @var{height} rectangle whose stretchable areas are
1523 defined by the given margin measurements @var{top-margin},
1524 @var{bottom-margin}, @var{left-margin}, and @var{right-margin}. The
1525 @var{margin} argument may be used to configure all four margins at
1526 once.
1528 Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
1529 the other arguments.
1530 @end deffn
1532 @node Tile Maps
1533 @subsection Tile Maps
1535 A tile map is a scene created by composing lots of small sprites,
1536 called ``tiles'', into a larger image. One program for editing such
1537 maps is called @url{,Tiled}. Chickadee has native
1538 support for loading and rendering Tiled maps in the @code{(chickadee
1539 render tiled)} module.
1541 @deffn {Procedure} load-tile-map file-name
1542 Load the Tiled formatted map in @var{file-name} and return a new tile
1543 map object.
1544 @end deffn
1546 @deffn {Procedure} draw-tile-map tile-map [#:layers] [#:region] @
1547 [#:origin] [#:position] [#:scale] [#:rotation]
1549 Draw the layers of @var{tile-map}. By default, all layers are drawn.
1550 To draw a subset of the available layers, pass a list of layer ids
1551 using the @var{layers} keyword argument.
1553 Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
1554 the other arguments.
1555 @end deffn
1557 @node Lines and Shapes
1558 @subsection Lines and Shapes
1560 Sprites are fun, but sometimes simple, untextured lines and polygons
1561 are desired. That's where the @code{(chickadee render shapes)} module
1562 comes in!
1564 @deffn {Procedure} draw-line start end @
1565 [#:thickness 0.5] [#:feather 1.0] [#:cap round] [#:color] @
1566 [#:shader]
1568 Draw a line segment from @var{start} to @var{end}. The line will be
1569 @var{thickness} pixels thick with an antialiased border @var{feather}
1570 pixels wide. The line will be colored @var{color}. @var{cap}
1571 specifies the type of end cap that should be used to terminate the
1572 lines, either @code{none}, @code{butt}, @code{square}, @code{round},
1573 @code{triangle-in}, or @code{triangle-out}. Advanced users may use
1574 the @var{shader} argument to override the built-in line segment
1575 shader.
1576 @end deffn
1578 @deffn {Procedure} draw-bezier-curve bezier [#:segments 32] @
1579 [#:control-points?] [#:tangents?] @
1580 [#:control-point-size 8] @
1581 [#:control-point-color yellow] @
1582 [#:tangent-color yellow] @
1583 [#:thickness 0.5] [#:feather 1.0] @
1584 [#:matrix]
1586 Draw the curve defined by @var{bezier} using a resolution of N
1587 @var{segments}. When @var{control-points?} is @code{#t}, the control
1588 points are rendered as squares of size @var{control-point-size} pixels
1589 and a color of @var{control-point-color}. When @var{tangents?} is
1590 @code{#t}, the tangent lines from terminal point to control point are
1591 rendered using the color @var{tangent-color}.
1593 All line segments rendered use @code{draw-line}, and thus the
1594 arguments @var{thickness} and @var{feather} have the same effect as in
1595 that procedure.
1597 A custom @var{matrix} may be passed for applications that require more
1598 control over the final output.
1599 @end deffn
1601 @deffn {Procedure} draw-bezier-path path [#:segments 32] @
1602 [#:control-points?] [#:tangents?] @
1603 [#:control-point-size 8] @
1604 [#:control-point-color yellow] @
1605 [#:tangent-color yellow] @
1606 [#:thickness 0.5] [#:feather 1.0] @
1607 [#:matrix]
1609 Render @var{path}, a list of bezier curves. See the documentation for
1610 @code{draw-bezier-curve} for an explanation of all the keyword
1611 arguments.
1612 @end deffn
1614 @node Fonts
1615 @subsection Fonts
1617 Printing text to the screen is quite easy:
1619 @example
1620 (draw-text "Hello, world" (vec2 100.0 100.0))
1621 @end example
1623 Chickadee loads and renders bitmap fonts in the
1624 @url{,
1625 Angel Code format}. A default font named ``Good Neighbors'' is
1626 built-in to Chickadee and is used for all text rendering operations
1627 where a font is not specified, as is the case in the above example.
1629 The following procedures can be found in the @code{(chickadee render
1630 font)} module:
1632 @deffn {Procedure} load-font file
1633 Load the Angel Code font (in either XML or FNT format) in @var{file}
1634 and return a new font object.
1635 @end deffn
1637 @deffn {Procedure} font? obj
1638 Return @code{#t} if @var{obj} is a font object.
1639 @end deffn
1641 @deffn {Procedure} font-face font
1642 Return the name of @var{font}.
1643 @end deffn
1645 @deffn {Procedure} font-line-height font
1646 Return the line height of @var{font}.
1647 @end deffn
1649 @deffn {Procedure} font-line-height font
1650 Return the line height of @var{font}.
1651 @end deffn
1653 @deffn {Procedure} font-bold? font
1654 Return @code{#t} if @var{font} is a bold font.
1655 @end deffn
1657 @deffn {Procedure} font-italic? font
1658 Return @code{#t} if @var{font} is an italicized font.
1659 @end deffn
1661 @deffn {Procedure} draw-text text position
1662 [#:font] [#:origin] [#:scale] [#:rotation] [#:blend-mode]
1663 [#:start 0] [#:end @code{(string-length text)}]
1665 Draw the string @var{text} with the first character starting at
1666 @var{position} using @var{font}. If @var{font} is not specified, a
1667 built-in font is used.
1669 @example
1670 (draw-text font "Hello, world!" (vec2 128.0 128.0))
1671 @end example
1673 To render a substring of @var{text}, use the @var{start} and @var{end}
1674 arguments.
1676 Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
1677 the other arguments.
1678 @end deffn
1680 @node Particles
1681 @subsection Particles
1683 Effects like smoke, fire, sparks, etc. are often achieved by animating
1684 lots of little, short-lived sprites known as ``particles''. In fact,
1685 all of these effects, and more, can be accomplished by turning a few
1686 configuration knobs in a ``particle system''. A particle system takes
1687 care of managing the many miniscule moving morsels so the developer
1688 can quickly produce an effect and move on with their life. The
1689 @code{(chickadee render particles)} module provides an API for
1690 manipulating particle systems.
1692 Below is an example of a very simple particle system that utilizes
1693 nearly all of the default configuration settings:
1695 @example
1696 (use-modules (chickadee render particles))
1697 (define texture (load-image "particle.png"))
1698 (define particles (make-particles 2000 #:texture texture))
1699 @end example
1701 In order to put particles into a particle system, a particle
1702 ``emitter'' is needed. Emitters know where to spawn new particles,
1703 how many of them to spawn, and for how long they should do it.
1705 Below is an example of an emitter that spawns 16 particles per frame
1706 at the coordinates @code{(320, 240)}:
1708 @example
1709 (use-modules (chickadee math vector))
1710 (define emitter (make-particle-emitter (vec2 320.0 240.0) 16))
1711 (add-particle-emitter particles emitter)
1712 @end example
1714 To see all of the tweakable knobs and switches, read on!
1716 @deffn {Procedure} make-particles capacity [#:blend-mode @code{alpha}] @
1717 [#:color white] [#:end-color transparent] [#:texture] @
1718 [#:animation-rows 1] [#:animation-columns 1] [#:width] [#:height] @
1719 [#:speed-range (vec2 0.1 1.0)] [#:acceleration-range (vec2 0.0 0.1)] @
1720 [#:direction-range (vec2 0 (* 2 pi))] [#:lifetime 30] [#:sort]
1722 Return a new particle system that may contain up to @var{capacity}
1723 particles. Achieving the desired particle effect involves tweaking
1724 the following keyword arguments as needed:
1726 - @var{blend-mode}: Pixel blending mode. @code{alpha} by default.
1727 (@pxref{Blending} for more about blend modes).
1729 - @var{start-color}: The tint color of the particle at the beginning of its
1730 life. White by default.
1732 - @var{end-color}: The tint color of the particle at the end of of its
1733 life. Completely transparent by default for a fade-out effect. The
1734 color in the middle of a particle's life will be an interpolation of
1735 @var{start-color} and @var{end-color}.
1737 - @var{texture}: The texture applied to the particles. The texture
1738 may be subdivided into many animation frames.
1740 - @var{animation-rows}: How many animation frame rows there are in the
1741 texture. Default is 1.
1743 - @var{animation-columns}: How many animation frame columns there are
1744 in the texture. Default is 1.
1746 - @var{width}: The width of each particle. By default, the width of
1747 an animation frame (in pixels) is used.
1749 - @var{height}: The height of each particle. By default, the height
1750 of an animation frame (in pixels) is used.
1752 - @var{speed-range}: A 2D vector containing the min and max particle
1753 speed. Each particle will have a speed chosen at random from this
1754 range. By default, speed ranges from 0.1 to 1.0.
1756 - @var{acceleration-range}: A 2D vector containing the min and max
1757 particle acceleration. Each particle will have an acceleration chosen
1758 at random from this range. By default, acceleration ranges from 0.0
1759 to 0.1.
1761 - @var{direction-range}: A 2D vector containing the min and max
1762 particle direction as an angle in radians. Each particle will have a
1763 direction chosen at random from this range. By default, the range
1764 covers all possible angles.
1766 - @var{lifetime}: How long each particle lives, measured in
1767 updates. 30 by default.
1769 - @var{sort}: @code{youngest} if youngest particle should be drawn
1770 last or @code{oldest} for the reverse. By default, no sorting is
1771 applied at all.
1772 @end deffn
1774 @deffn {Procedure} particles? obj
1775 Return @code{#t} if @var{obj} is a particle system.
1776 @end deffn
1778 @deffn {Procedure} update-particles particles
1779 Advance the simulation of @var{particles}.
1780 @end deffn
1782 @deffn {Procedure} draw-particles particles
1783 Render @var{particles}.
1784 @end deffn
1786 @deffn {Procedure} draw-particles* particles matrix
1787 Render @var{particles} with @var{matrix} applied.
1788 @end deffn
1790 @deffn {Procedure} make-particle-emitter spawn-area rate [duration]
1792 Return a new particle emitter that spawns @var{rate} particles per
1793 frame within @var{spawn-area} (a rectangle or 2D vector) for
1794 @var{duration} frames. If @var{duration} is not specified, the
1795 emitter will spawn particles indefinitely.
1796 @end deffn
1798 @deffn {Procedure} particle-emitter? obj
1799 Return @code{#t} if @var{obj} is a particle emitter.
1800 @end deffn
1802 @deffn {Procedure} particle-emitter-spawn-area emitter
1803 Return the spawn area for @var{emitter}.
1804 @end deffn
1806 @deffn {Procedure} particle-emitter-rate emitter
1807 Return the number of particles that @var{emitter} will spawn per
1808 frame.
1809 @end deffn
1811 @deffn {Procedure} particle-emitter-life emitter
1812 Return the number of frames remaining in @var{emitter}'s lifespan.
1813 @end deffn
1815 @deffn {Procedure} particle-emitter-done? emitter
1816 Return @code{#t} if @var{emitter} has finished spawning particlces.
1817 @end deffn
1819 @deffn {Procedure} add-particle-emitter particles emitter
1820 Add @var{emitter} to @var{particles}.
1821 @end deffn
1823 @deffn {Procedure} remove-particle-emitter particles emitter
1824 Remove @var{emitter} to @var{particles}
1825 @end deffn
1827 @node Blending
1828 @subsection Blending
1830 Rendering a scene often involves drawing layers of objects that
1831 overlap each other. Blending determines how two overlapping pixels
1832 are combined in the final image that is rendered to the screen.
1833 Chickadee provides the following blend modes:
1835 @itemize
1837 @item @code{replace}
1838 Use the latest color, ignoring all others.
1840 @item @code{alpha}
1841 Blend pixels according to the values of their alpha channels. This is
1842 the most commonly used blend mode and thus is Chickadee's default
1843 mode.
1845 @item @code{add}
1846 Add all pixel color values together. The more colors blended
1847 together, the more white the final color becomes.
1849 @item @code{subtract}
1850 Subtract all pixel color values. The more colors blended together,
1851 the more black the final color becomes.
1853 @item @code{multiply}
1855 @item @code{darken}
1857 @item @code{lighten}
1859 @item @code{screen}
1861 @end itemize
1863 @node Framebuffers
1864 @subsection Framebuffers
1866 A framebuffer is a chunk of memory that the GPU can render things
1867 onto. By default, the framebuffer that is used for rendering is the
1868 one belonging to the game window, but custom framebuffers can be used
1869 as well. A common use-case for custom framebuffers is applying
1870 post-processing effects: The entire scene is rendered to a
1871 framebuffer, and then the contents of that framebuffer are applied to
1872 a post-processing shader and rendered to the game window. The
1873 post-processing shader could do any number of things: scaling,
1874 antialiasing, motion blur, etc.
1876 @deffn {Procedure} make-framebuffer width height @
1877 [#:min-filter @code{linear}] @
1878 [#:mag-filter @code{linear}] @
1879 [#:wrap-s @code{repeat}] @
1880 [#:wrap-t @code{repeat}]
1882 Create a new framebuffer that is @var{width} pixels wide and @var{height} pixels high.
1884 @var{min-filter} and @var{mag-filter} determine the scaling algorithm
1885 applied to the framebuffer when rendering. By default, linear scaling
1886 is used in both cases. To perform no smoothing at all, use
1887 @code{nearest} for simple nearest neighbor scaling. This is typically
1888 the best choice for pixel art games.
1889 @end deffn
1891 @deffn {Procedure} framebuffer? obj
1892 Return @code{#t} if @var{obj} is a framebuffer.
1893 @end deffn
1895 @deffn {Procedure} framebuffer-texture fb
1896 Return the texture backing the framebuffer @var{fb}.
1897 @end deffn
1899 @deffn {Procedure} framebuffer-viewport fb
1900 Return the default viewport (@pxref{Viewports}) used by the
1901 framebuffer @var{fb}.
1902 @end deffn
1904 @deffn {Procedure} null-framebuffer
1905 The default framebuffer.
1906 @end deffn
1908 @node Viewports
1909 @subsection Viewports
1911 A viewport represents a subset of the screen (or framebuffer). When
1912 rendering a frame, the resulting image will only appear within that
1913 viewport. These aren't often needed, and Chickadee's default viewport
1914 occupies the entire screen, but there are certain situations where
1915 they are useful. For example, a split-screen multiplayer game may
1916 render to two different viewports, each occupying a different half of
1917 the screen. For information about how to set the current viewport,
1918 see @code{with-viewport} in @ref{Rendering Engine}.
1920 The @code{(chickadee render viewport)} module provides the following
1921 API:
1923 @deffn {Procedure} make-viewport x y width height @
1924 [#:clear-color] [#:clear-flags]
1926 Create a viewport that covers an area of the window starting from
1927 coordinates (@var{x}, @var{y}) and spanning @var{width} @code{x}
1928 @var{height} pixels. Fill the viewport with @var{clear-color} when
1929 clearing the screen. Clear the buffers denoted by the list of symbols
1930 in @var{clear-flags}.
1932 Possible values for @var{clear-flags} are @var{color-buffer},
1933 @var{depth-buffer}, @var{accum-buffer}, and @var{stencil-buffer}.
1934 @end deffn
1936 @deffn {Procedure} viewport? obj
1937 Return @code{#t} if @var{obj} is a viewport.
1938 @end deffn
1940 @deffn {Procedure} viewport-x viewport
1941 Return the left edge of @var{viewport}.
1942 @end deffn
1944 @deffn {Procedure} viewport-y viewport
1945 Return the bottom edge of @var{viewport}.
1946 @end deffn
1948 @deffn {Procedure} viewport-width viewport
1949 Return the width of @var{viewport}.
1950 @end deffn
1952 @deffn {Procedure} viewport-height viewport
1953 Return the height of @var{viewport}.
1954 @end deffn
1956 @deffn {Procedure} viewport-clear-color viewport
1957 Return the clear color for @var{viewport}.
1958 @end deffn
1960 @deffn {Procedure} viewport-clear-flags viewport
1961 Return the list of clear flags for @var{viewport}.
1962 @end deffn
1964 @node Rendering Engine
1965 @subsection Rendering Engine
1967 Chickadee defines rendering using a metaphor familiar to Scheme
1968 programmers: procedure application. A shader (@pxref{Shaders}) is
1969 like a procedure for the GPU to apply. Shaders are passed arguments:
1970 A vertex array containing the geometry to render (@pxref{Buffers}) and
1971 zero or more keyword arguments that the shader understands. Similar
1972 to how Scheme has @code{apply} for calling procedures, Chickadee
1973 provides @code{gpu-apply} for calling shaders.
1975 Additionally, there is some dynamic state that effects how
1976 @code{gpu-apply} will behave. Things like the current viewport,
1977 framebuffer, and blend mode are stored as dynamic state because it
1978 would be tedious to have to have to specify them each time
1979 @code{gpu-apply} is called.
1981 The following procedures and syntax can be found in the
1982 @code{(chickadee render)} module.
1984 @deffn {Syntax} gpu-apply shader vertex-array @
1985 [#:uniform-key uniform-value @dots{}]
1986 @deffnx {Syntax} gpu-apply* shader vertex-array count @
1987 [#:uniform-key uniform-value @dots{}]
1989 Render @var{vertex-array} using @var{shader} with the uniform values
1990 specified in the following keyword arguments.
1992 While @code{gpu-apply} will draw every vertex in @var{vertex-array},
1993 @code{gpu-apply*} will only draw @var{count} vertices.
1994 @end deffn
1996 @deffn {Syntax} gpu-apply/instanced shader vertex-array @
1997 n [#:uniform-key uniform-value @dots{}]
1998 @deffnx {Syntax} gpu-apply/instanced shader vertex-array @
1999 count n [#:uniform-key uniform-value @dots{}]
2001 Render @var{vertex-array} @var{n} times using @var{shader} with the
2002 uniform values specified in the following keyword arguments.
2004 Instanced rendering is very beneficial for rendering the same object
2005 many times with only small differences for each one. For example, the
2006 particle effects described in @ref{Particles} use instanced rendering.
2008 While @code{gpu-apply/instanced} will draw every vertex in
2009 @var{vertex-array}, @code{gpu-apply*} will only draw @var{count}
2010 vertices.
2011 @end deffn
2013 @deffn {Procedure} current-viewport
2014 Return the currently bound viewport (@pxref{Viewports}).
2015 @end deffn
2017 @deffn {Procedure} current-framebuffer
2018 Return the currently bound framebuffer (@pxref{Framebuffers}).
2019 @end deffn
2021 @deffn {Procedure} current-blend-mode
2022 Return the currently bound blend mode (@pxref{Blending}).
2023 @end deffn
2025 @deffn {Procedure} current-depth-test
2026 Return @code{#t} if depth testing is currently enabled (@pxref{Blending}).
2027 @end deffn
2029 @deffn {Procedure} current-texture
2030 Return the currently bound texture (@pxref{Textures}).
2031 @end deffn
2033 @deffn {Procedure} current-projection
2034 Return the currently bound projection matrix (@pxref{Matrices}).
2035 @end deffn
2037 @deffn {Syntax} with-viewport viewport body @dots{}
2038 Evaluate @var{body} with the current viewport bound to @var{viewport} (@pxref{Viewports}).
2039 @end deffn
2041 @deffn {Syntax} with-framebuffer framebuffer body @dots{}
2042 Evaluate @var{body} with the current framebuffer bound to
2043 @var{framebuffer} (@pxref{Framebuffers}).
2044 @end deffn
2046 @deffn {Syntax} with-blend-mode blend-mode body @dots{}
2047 Evaluate @var{body} with the current blend mode bound to
2048 @var{blend-mode} (@pxref{Blending}).
2049 @end deffn
2051 @deffn {Syntax} with-depth-test depth-test? body @dots{}
2052 Evaluate @var{body} with the depth-test disabled if @var{depth-test?}
2053 is @code{#f}, or enabled otherwise (@pxref{Blending}).
2054 @end deffn
2056 @deffn {Syntax} with-texture texture body @dots{}
2057 Evaluate @var{body} with the current texture bound to @var{texture}
2058 (@pxref{Textures}).
2059 @end deffn
2061 @deffn {Syntax} with-projection projection body @dots{}
2062 Evaluate @var{body} with the current projection matrix bound to
2063 @var{projection} (@pxref{Matrices}).
2064 @end deffn
2066 @node Buffers
2067 @subsection Buffers
2069 Alright, let's brush aside all of those pretty high level abstractions
2070 and discuss what is going on under the hood. The GPU exists as a
2071 discrete piece of hardware separate from the CPU. In order to make it
2072 draw things, we must ship lots of data out of our memory space and
2073 into the GPU. The @code{(chickadee render buffer}) module provides an
2074 API for manipulating GPU buffers.
2076 In OpenGL terminology, a chunk of data allocated on the GPU is a
2077 ``vertex buffer object'' or VBO. For example, here is a bytevector
2078 that could be transformed into a GPU buffer that packs together vertex
2079 position and texture coordinates:
2081 @example
2082 (use-modules (chickadee render buffer) (srfi srfi-4))
2083 (define data
2084 (f32vector -8.0 -8.0 ; 2D vertex
2085 0.0 0.0 ; 2D texture coordinate
2086 8.0 -8.0 ; 2D vertex
2087 1.0 0.0 ; 2D texture coordinate
2088 8.0 8.0 ; 2D vertex
2089 1.0 1.0 ; 2D texture coordinate
2090 -8.0 8.0 ; 2D vertex
2091 0.0 1.0)) ; 2D texture coordinate
2092 @end example
2094 This data represents a textured 16x16 square centered on the
2095 origin. To send this data to the GPU, the @code{make-buffer} procedure
2096 is needed:
2098 @example
2099 (define buffer (make-buffer data #:stride 16))
2100 @end example
2102 The @code{#:stride} keyword argument indicates how many bytes make up
2103 each element of the buffer. In this case, there are 4 floats per
2104 element: 2 for the vertex, and 2 for the texture coordinate. A 32-bit
2105 float is 4 bytes in length, so the buffer's stride is 16.
2107 Within a VBO, one or more ``attributes'', as OpenGL calls them, may be
2108 present. Attributes are subregions within the buffer that have a
2109 particular data type. In this case, there are two attributes packed
2110 into the buffer. To provided a typed view into a buffer, the
2111 @code{make-buffer-view} procedure is needed:
2113 @example
2114 (define vertices
2115 (make-buffer-view #:buffer buffer
2116 #:type 'vec2
2117 #:component-type 'float
2118 #:length 4))
2119 (define texcoords
2120 (make-buffer-view #:buffer buffer
2121 #:type 'vec2
2122 #:component-type 'float
2123 #:length 4
2124 #:offset 8))
2125 @end example
2127 To render a square, the GPU needs to draw two triangles, which means
2128 we need 6 vertices in total. However, the above buffer only contains
2129 data for 4 vertices. This is becase there are only 4 unique vertices
2130 for a square, but 2 of them must be repeated for each triangle. To
2131 work with deduplicated vertex data, an ``index buffer'' must be
2132 created.
2134 @example
2135 (define index-buffer
2136 (make-buffer (u32vector 0 3 2 0 2 1)
2137 #:target 'index)
2138 (define indices
2139 (make-buffer-view #:type 'scalar
2140 #:component-type 'unsigned-int
2141 #:buffer index-buffer))
2142 @end example
2144 Note the use of the @code{#:target} keyword argument. It is required
2145 because the GPU treats index data in a special way and must be told
2146 which data is index data.
2148 Now that the buffer views representing each attribute have been
2149 created, all that's left is to bind them all together in a ``vertex
2150 array object'', or VAO. Vertex arrays associate each buffer view
2151 with an attribute index on the GPU. The indices that are chosen must
2152 correspond with the indices that the shader (@pxref{Shaders}) expects
2153 for each attribute.
2155 @example
2156 (define vertex-array
2157 (make-vertex-array #:indices indices
2158 #:attributes `((0 . ,vertices)
2159 (1 . ,texcoords))))
2160 @end example
2162 With the vertex array created, the GPU is now fully aware of how to
2163 interpret the data that it has been given in the original buffer.
2164 Actually rendering this square is left as an exercise to the reader.
2165 See the @ref{Shaders} section and the @code{gpu-apply} procedure in
2166 @ref{Rendering Engine} for the remaining pieces of a successful draw
2167 call. Additionally, consider reading the source code for sprites,
2168 shapes, or particles to see GPU buffers in action.
2170 Without further ado, the API reference:
2172 @deffn {Procedure} make-buffer data [#:name "anonymous"] @
2173 [#:length] [#:offset 0] [#:stride 0] [#:target @code{vertex}] @
2174 [#:usage @code{static}]
2176 Upload @var{data}, a bytevector, to the GPU. By default, the entire
2177 bytevector is uploaded. A subset of the data may be uploaded by
2178 specifying the @var{offset}, the index of the first byte to be
2179 uploaded, and @var{length}, the number of bytes to upload.
2181 If @var{data} is @code{#f}, allocate @var{length} bytes of fresh GPU
2182 memory instead.
2184 @var{target} and @var{usage} are hints that tell the GPU how the
2185 buffer is intended to be used.
2187 @var{target} may be:
2189 @itemize
2190 @item @code{vertex}
2191 Vertex attribute data.
2193 @item @code{index}
2194 Index buffer data.
2196 @end itemize
2198 @var{usage} may be:
2200 @itemize
2201 @item @code{static}
2202 The buffer data will not be modified after creation.
2204 @item @code{stream}
2205 The buffer data will be modified frequently.
2207 @end itemize
2209 @var{name} is simply an arbitrary string for debugging purposes that
2210 is never sent to the GPU.
2211 @end deffn
2213 @deffn {Procedure} buffer? obj
2214 Return @code{#t} if @var{obj} is a GPU buffer.
2215 @end deffn
2217 @deffn {Procedure} index-buffer? buffer
2218 Return @code{#t} if @var{buffer} is an index buffer.
2219 @end deffn
2221 @defvar null-buffer
2222 Represents the absence of a buffer.
2223 @end defvar
2225 @deffn {Procedure} buffer-name buffer
2226 Return the name of @var{buffer}.
2227 @end deffn
2229 @deffn {Procedure} buffer-length buffer
2230 Return the length of @var{buffer}.
2231 @end deffn
2233 @deffn {Procedure} buffer-stride buffer
2234 Return the amount of space, in bytes, between each element in
2235 @var{buffer}.
2236 @end deffn
2238 @deffn {Procedure} buffer-target buffer
2239 Return the the intended usage of @var{buffer}, either @code{vertex} or
2240 @code{index}.
2241 @end deffn
2243 @deffn {Procedure} buffer-usage buffer
2244 Return the intended usage of @var{buffer}, either @code{static} for
2245 buffer data that will not change once sent to the GPU, or
2246 @code{stream} for buffer data that will be frequently updated from the
2247 client-side.
2248 @end deffn
2250 @deffn {Procedure} buffer-data buffer
2251 Return a bytevector containing all the data within @var{buffer}. If
2252 @var{buffer} has not been mapped (see @code{with-mapped-buffer}) then
2253 this procedure will return @code{#f}.
2254 @end deffn
2256 @deffn {Syntax} with-mapped-buffer buffer body @dots{}
2257 Evaluate @var{body} in the context of @var{buffer} having its data
2258 synced from GPU memory to RAM. In this context, @code{buffer-data}
2259 will return a bytevector of all the data stored in @var{buffer}. When
2260 program execution exits this form, the data (including any
2261 modifications) is synced back to the GPU.
2263 This form is useful for streaming buffers that need to update their
2264 contents dynamically, such as a sprite batch.
2265 @end deffn
2267 @deffn {Procedure} make-buffer-view #:buffer #:type @
2268 #:component-type #:length [#:offset @code{0}] [#:divisor @code{1}] @
2269 [#:name @code{"anonymous"}]
2271 Return a new buffer view for @var{buffer} starting at byte index
2272 @var{offset} of @var{length} elements, where each element is of
2273 @var{type} and composed of @var{component-type} values.
2275 Valid values for @var{type} are:
2277 @itemize
2278 @item @code{scalar}
2279 single number
2281 @item @code{vec2}
2282 2D vector
2284 @item @code{vec3}
2285 3D vector
2287 @item @code{vec4}
2288 4D vector
2290 @item @code{mat2}
2291 2x2 matrix
2293 @item @code{mat3}
2294 3x3 matrix
2296 @item @code{mat4}
2297 4x4 matrix
2298 @end itemize
2300 Valid values for @var{component-type} are:
2302 @itemize
2304 @item @code{byte}
2305 @item @code{unsigned-byte}
2306 @item @code{short}
2307 @item @code{unsigned-short}
2308 @item @code{int}
2309 @item @code{unsigned-int}
2310 @item @code{float}
2311 @item @code{double}
2313 @end itemize
2315 @var{divisor} is only needed for instanced rendering applications (see
2316 @code{gpu-apply/instanced} in @ref{Rendering Engine}) and represents
2317 how many instances each vertex element applies to. A divisor of 0
2318 means that a single element is used for every instance and is used for
2319 the data being instanced. A divisor of 1 means that each element is
2320 used for 1 instance. A divisor of 2 means that each element is used
2321 for 2 instances, and so on.
2322 @end deffn
2324 @deffn {Procedure} buffer-view? obj
2325 Return @code{#t} if @var{obj} is a buffer view.
2326 @end deffn
2328 @deffn {Procedure} buffer-view->buffer buffer-view
2329 Return the buffer that @var{buffer-view} is using.
2330 @end deffn
2332 @deffn {Procedure} buffer-view-name buffer-view
2333 Return the name of @var{buffer-view}.
2334 @end deffn
2336 @deffn {Procedure} buffer-view-offset buffer-view
2337 Return the byte offset of @var{buffer-view}.
2338 @end deffn
2340 @deffn {Procedure} buffer-view-type buffer-view
2341 Return the data type of @var{buffer-view}.
2342 @end deffn
2344 @deffn {Procedure} buffer-view-component-type buffer-view
2345 Return the component data type of @var{buffer-view}
2346 @end deffn
2348 @deffn {Procedure} buffer-view-divisor buffer-view
2349 Return the instance divisor for @var{buffer-view}.
2350 @end deffn
2352 @deffn {Syntax} with-mapped-buffer-view buffer-view body @dots{}
2354 Evaluate @var{body} in the context of @var{buffer-view} having its
2355 data synced from GPU memory to RAM. See @code{with-mapped-buffer} for
2356 more information.
2357 @end deffn
2359 @deffn {Procedure} make-vertex-array #:indices #:attributes @
2360 [#:mode @code{triangles}]
2362 Return a new vertex array using the index data within the buffer view
2363 @var{indices} and the vertex attribute data within @var{attributes}.
2365 @var{attributes} is an alist mapping shader attribute indices to typed
2366 buffers containing vertex data:
2368 @example
2369 `((1 . ,buffer-view-a)
2370 (2 . ,buffer-view-b)
2371 @dots{})
2372 @end example
2374 By default, the vertex array is interpreted as containing a series of
2375 triangles. If another primtive type is desired, the @var{mode}
2376 keyword argument may be overridden. The following values are
2377 supported:
2379 @itemize
2380 @item @code{points}
2381 @item @code{lines}
2382 @item @code{line-loop}
2383 @item @code{line-strip}
2384 @item @code{triangles}
2385 @item @code{triangle-strip}
2386 @item @code{triangle-fan}
2387 @end itemize
2389 @end deffn
2391 @defvar null-vertex-array
2392 Represents the absence of a vertex array.
2393 @end defvar
2395 @deffn {Procedure} vertex-array? obj
2396 Return @code{#t} if @var{obj} is a vertex array.
2397 @end deffn
2399 @deffn {Procedure} vertex-array-indices vertex-array
2400 Return the buffer view containing index data for @var{vertex-array}.
2401 @end deffn
2403 @deffn {Procedure} vertex-array-attributes vertex-array
2404 Return the attribute index -> buffer view mapping of vertex attribute
2405 data for @var{vertex-array}.
2406 @end deffn
2408 @deffn {Procedure} vertex-array-mode vertex-array
2409 Return the primitive rendering mode for @var{vertex-array}.
2410 @end deffn
2412 @node Shaders
2413 @subsection Shaders
2415 Shaders are programs that the GPU can evaluate that allow the
2416 programmer to completely customized the final output of a GPU draw
2417 call. The @code{(chickadee render shader)} module provides an API for
2418 building custom shaders.
2420 Shaders are written in the OpenGL Shading Language, or GLSL for short.
2421 Chickadee aspires to provide a domain specific language for writing
2422 shaders in Scheme, but we are not there yet.
2424 Shader programs consist of two components: A vertex shader and a
2425 fragment shader. A vertex shader receives vertex data (position
2426 coordinates, texture coordinates, normals, etc.) and transforms them
2427 as desired, whereas a fragment shader controls the color of each
2428 pixel.
2430 Sample vertex shader:
2432 @example
2433 @verbatim
2434 #version 130
2436 in vec2 position;
2437 in vec2 tex;
2438 out vec2 fragTex;
2439 uniform mat4 mvp;
2441 void main(void) {
2442 fragTex = tex;
2443 gl_Position = mvp * vec4(position.xy, 0.0, 1.0);
2444 }
2445 @end verbatim
2446 @end example
2448 Sample fragment shader:
2450 @example
2451 @verbatim
2452 #version 130
2454 in vec2 fragTex;
2455 uniform sampler2D colorTexture;
2457 void main (void) {
2458 gl_FragColor = texture2D(colorTexture, fragTex);
2459 }
2460 @end verbatim
2461 @end example
2463 This manual will not cover GLSL features and syntax as there is lots
2464 of information already available about this topic.
2466 One way to think about rendering with shaders, and the metaphor
2467 Chickadee uses, is to think about it as a function call: The shader is
2468 a function, and it is applied to some ``attributes'' (positional
2469 arguments), and some ``uniforms'' (keyword arguments).
2471 @example
2472 (define my-shader (load-shader "vert.glsl" "frag.glsl"))
2473 (define vertices (make-vertex-array @dots{}))
2474 (gpu-apply my-shader vertices #:color red)
2475 @end example
2477 @xref{Rendering Engine} for more details about the @code{gpu-apply}
2478 procedure.
2480 Shaders are incredibly powerful tools, and there's more information
2481 about them than we could ever fit into this manual, so we highly
2482 recommend searching the web for more information and examples. What
2483 we can say, though, is how to use our API:
2485 @deffn {Procedure} strings->shader vertex-source fragment-source
2486 Compile @var{vertex-source}, the GLSL code for the vertex shader, and
2487 @var{fragment-source}, the GLSL code for the fragment shader, into a
2488 GPU shader program.
2489 @end deffn
2491 @deffn {Procedure} load-shader vertex-source-file fragment-source-file
2492 Compile the GLSL source code within @var{vertex-source-file} and
2493 @var{fragment-source-file} into a GPU shader program.
2494 @end deffn
2496 @deffn {Procedure} make-shader vertex-port fragment-port
2497 Read GLSL source from @var{vertex-port} and @var{fragment-port} and
2498 compile them into a GPU shader program.
2499 @end deffn
2501 @deffn {Procedure} shader? obj
2502 Return @code{#t} if @var{obj} is a shader.
2503 @end deffn
2505 @defvar null-shader
2506 Represents the absence shader program.
2507 @end defvar
2509 @deffn {Procedure} shader-uniform shader name
2510 Return the metadata for the uniform @var{name} in @var{shader}.
2511 @end deffn
2513 @deffn {Procedure} shader-uniforms shader
2514 Return a hash table of uniforms for @var{shader}.
2515 @end deffn
2517 @deffn {Procedure} shader-attributes shader
2518 Return a hash table of attributes for @var{shader}.
2519 @end deffn
2521 @deffn {Procedure} uniform? obj
2522 Return @code{#t} if @var{obj} is a uniform.
2523 @end deffn
2525 @deffn {Procedure} uniform-name uniform
2526 Return the variable name of @var{uniform}.
2527 @end deffn
2529 @deffn {Procedure} uniform-type uniform
2530 Return the data type of @var{uniform}.
2531 @end deffn
2533 @deffn {Procedure} uniform-value uniform
2534 Return the current value of @var{uniform}.
2535 @end deffn
2537 @deffn {Procedure} uniform-default-value uniform
2538 Return the default value of @var{uniform}.
2539 @end deffn
2541 @deffn {Procedure} attribute? obj
2542 Return @code{#t} if @var{obj} is an attribute.
2543 @end deffn
2545 @deffn {Procedure} attribute-name attribute
2546 Return the variable name of @var{attribute}.
2547 @end deffn
2549 @deffn {Procedure} attribute-location attribute
2550 Return the binding location of @var{attribute}.
2551 @end deffn
2553 @deffn {Procedure} attribute-type attribute
2554 Return the data type of @var{attribute}.
2555 @end deffn
2557 @node Scripting
2558 @section Scripting
2560 Game logic is a web of asynchronous events that are carefully
2561 coordinated to bring the game world to life. In order to make an
2562 enemy follow and attack the player, or move an NPC back and forth in
2563 front of the item shop, or do both at the same time, a scripting
2564 system is a necessity. Chickadee comes with an asynchronous
2565 programming system in the @code{(chickadee scripting)} module.
2566 Lightweight, cooperative threads known as ``scripts'' allow the
2567 programmer to write asynchronous code as if it were synchronous, and
2568 allow many such ``threads'' to run concurrently.
2570 But before we dig deeper into scripts, let's discuss the simple act
2571 of scheduling tasks.
2573 @menu
2574 * Agendas:: Scheduling tasks.
2575 * Scripts:: Cooperative multitasking.
2576 * Tweening:: Animations.
2577 * Channels:: Publish data to listeners.
2578 @end menu
2580 @node Agendas
2581 @subsection Agendas
2583 To schedule a task to be performed later, an ``agenda'' is used.
2584 There is a default, global agenda that is ready to be used, or
2585 additional agendas may be created for different purposes. The
2586 following example prints the text ``hello'' when the agenda has
2587 advanced to time unit 10.
2589 @example
2590 (at 10 (display "hello\n"))
2591 @end example
2593 Most of the time it is more convenient to schedule tasks relative to
2594 the current time. This is where @code{after} comes in handy:
2596 @example
2597 (after 10 (display "hello\n"))
2598 @end example
2600 Time units in the agenda are in no way connected to real time. It's
2601 up to the programmer to decide what agenda time means. A simple and
2602 effective approach is to map each call of the update procedure
2603 (@pxref{Kernel}) to 1 unit of agenda time, like so:
2605 @example
2606 (define (update dt)
2607 (update-agenda 1))
2608 @end example
2610 It is important to call @code{update-agenda} periodically, otherwise
2611 no tasks will ever be run!
2613 In addition to using the global agenda, it is useful to have multiple
2614 agendas for different purposes. For example, the game world can use a
2615 different agenda than the user interface, so that pausing the game is
2616 a simple matter of not updating the world's agenda while continuing to
2617 update the user interface's agenda. The current agenda is dynamically
2618 scoped and can be changed using the @code{with-agenda} special form:
2620 @example
2621 (define game-world-agenda (make-agenda))
2623 (with-agenda game-world-agenda
2624 (at 60 (spawn-goblin))
2625 (at 120 (spawn-goblin))
2626 (at 240 (spawn-goblin-king)))
2627 @end example
2629 @deffn {Procedure} make-agenda
2630 Return a new task scheduler.
2631 @end deffn
2633 @deffn {Procedure} agenda? obj
2634 Return @code{#t} if @var{obj} is an agenda.
2635 @end deffn
2637 @deffn {Procedure} current-agenda
2638 @deffnx {Procedure} current-agenda agenda
2639 When called with no arguments, return the current agenda. When called
2640 with one argument, set the current agenda to @var{agenda}.
2641 @end deffn
2643 @deffn {Syntax} with-agenda agenda body @dots{}
2644 Evaluate @var{body} with the current agenda set to @var{agenda}.
2645 @end deffn
2647 @deffn {Procedure} agenda-time
2648 Return the current agenda time.
2649 @end deffn
2651 @deffn {Procedure} update-agenda dt
2652 Advance the current agenda by @var{dt}.
2653 @end deffn
2655 @deffn {Procedure} schedule-at time thunk
2656 Schedule @var{thunk}, a procedure of zero arguments, to be run at
2657 @var{time}.
2658 @end deffn
2660 @deffn {Procedure} schedule-after delay thunk
2661 Schedule @var{thunk}, a procedure of zero arguments, to be run after
2662 @var{delay}.
2663 @end deffn
2665 @deffn {Procedure} schedule-every interval thunk [n]
2666 Schedule @var{thunk}, a procedure of zero arguments, to be run every
2667 @var{interval} amount of time. Repeat this @var{n} times, or
2668 indefinitely if not specified.
2669 @end deffn
2671 @deffn {Syntax} at time body @dots{}
2672 Schedule @var{body} to be evaluated at @var{time}.
2673 @end deffn
2675 @deffn {Syntax} after delay body @dots{}
2676 Schedule @var{body} to be evaluated after @var{delay}.
2677 @end deffn
2679 @deffn {Syntax} every interval body @dots{}
2680 @deffnx {Syntax} every (interval n) body @dots{}
2681 Schedule @var{body} to be evaluated every @var{interval} amount of
2682 time. Repeat this @var{n} times, or indefinitely if not specified.
2683 @end deffn
2685 @node Scripts
2686 @subsection Scripts
2688 Now that we can schedule tasks, let's take things to the next level.
2689 It sure would be great if we could make procedures that described a
2690 series of actions that happened over time, especially if we could do
2691 so without contorting our code into a nest of callback procedures.
2692 This is where scripts come in. With scripts we can write code in a
2693 linear way, in a manner that appears to be synchronous, but with the
2694 ability to suspend periodically in order to let other scripts have a
2695 turn and prevent blocking the game loop. Building on top of the
2696 scheduling that agendas provide, here is a script that models a child
2697 trying to get their mother's attention:
2699 @example
2700 (script
2701 (while #t
2702 (display "mom!")
2703 (newline)
2704 (sleep 60))) ; where 60 = 1 second of real time
2705 @end example
2707 This code runs in an endless loop, but the @code{sleep} procedure
2708 suspends the script and schedules it to be run later by the agenda.
2709 So, after each iteration of the loop, control is returned back to the
2710 game loop and the program is not stuck spinning in a loop that will
2711 never exit. Pretty neat, eh?
2713 Scripts can suspend to any capable handler, not just the agenda.
2714 The @code{yield} procedure will suspend the current script and pass
2715 its ``continuation'' to a handler procedure. This handler procedure
2716 could do anything. Perhaps the handler stashes the continuation
2717 somewhere where it will be resumed when the user presses a specific
2718 key on the keyboard, or maybe it will be resumed when the player picks
2719 up an item off of the dungeon floor; the sky is the limit.
2721 Sometimes it is necessary to abruptly terminate a script after it has
2722 been started. For example, when an enemy is defeated their AI routine
2723 needs to be shut down. When a script is spawned, a handle to that
2724 script is returned that can be used to cancel it when desired.
2726 @example
2727 (define script (script (while #t (display "hey\n") (sleep 60))))
2728 ;; sometime later
2729 (cancel-script script)
2730 @end example
2732 @deffn {Procedure} spawn-script thunk
2733 Apply @var{thunk} as a script and return a handle to it.
2734 @end deffn
2736 @deffn {Syntax} script body @dots{}
2737 Evaluate @var{body} as a script and return a handle to it.
2738 @end deffn
2740 @deffn {Procedure} script? obj
2741 Return @code{#t} if @var{obj} is a script handle.
2742 @end deffn
2744 @deffn {Procedure} script-cancelled? obj
2745 Return @code{#t} if @var{obj} has been cancelled.
2746 @end deffn
2748 @deffn {Procedure} script-running? obj
2749 Return @code{#t} if @var{obj} has not yet terminated or been
2750 cancelled.
2751 @end deffn
2753 @deffn {Procedure} script-complete? obj
2754 Return @code{#t} if @var{obj} has terminated.
2755 @end deffn
2757 @deffn {Procedure} cancel-script co
2758 Prevent further execution of the script @var{co}.
2759 @end deffn
2761 @deffn {Procedure} yield handler
2762 Suspend the current script and pass its continuation to the
2763 procedure @var{handler}.
2764 @end deffn
2766 @deffn {Procedure} sleep duration
2767 Wait @var{duration} before resuming the current script.
2768 @end deffn
2770 @deffn {Syntax} forever body @dots{}
2771 Evaluate @var{body} in an endless loop.
2772 @end deffn
2774 @node Tweening
2775 @subsection Tweening
2777 Tweening is the process of transitioning something from an initial
2778 state to a final state over a pre-determined period of time. In other
2779 words, tweening is a way to create animation. The @code{tween}
2780 procedure can be used within any script like so:
2782 @example
2783 (define x 0)
2784 (script
2785 ;; 0 to 100 in 60 ticks of the agenda.
2786 (tween 60 0 100 (lambda (y) (set! x y))))
2787 @end example
2789 @deffn {Procedure} tween duration start end proc @
2790 [#:step @code{1}] [#:ease @code{smoothstep}] @
2791 #:interpolate @code{lerp}]
2792 Transition a value from @var{start} to @var{end} over @var{duration},
2793 sending each succesive value to @var{proc}. @var{step} controls the
2794 amount of time between each update of the animation.
2796 To control how the animation goes from the initial to final state, an
2797 ``easing'' procedure may be specified. By default, the
2798 @code{smoothstep} easing is used, which is a more pleasing default
2799 than a simplistic linear function. @xref{Easings} for a complete list
2800 of available easing procedures.
2802 The @var{interpolate} procedure computes the values in between
2803 @var{start} and @var{end}. By default, linear interpolation (``lerp''
2804 for short) is used.
2805 @end deffn
2807 @node Channels
2808 @subsection Channels
2810 Channels are a tool for communicating amongst different scripts. One
2811 script can write a value to the channel and another can read from it.
2812 Reading or writing to a channel suspends that script until there is
2813 someone on the other end of the line to complete the transaction.
2815 Here's a simplistic example:
2817 @example
2818 (define c (make-channel))
2820 (script
2821 (forever
2822 (let ((item (channel-get c)))
2823 (pk 'got item))))
2825 (script
2826 (channel-put c 'sword)
2827 (channel-put c 'shield)
2828 (channel-put c 'potion))
2829 @end example
2831 @deffn {Procedure} make-channel
2832 Return a new channel
2833 @end deffn
2835 @deffn {Procedure} channel? obj
2836 Return @code{#t} if @var{obj} is a channel.
2837 @end deffn
2839 @deffn {Procedure} channel-get channel
2840 Retrieve a value from @var{channel}. The current script suspends
2841 until a value is available.
2842 @end deffn
2844 @deffn {Procedure} channel-put channel data
2845 Send @var{data} to @var{channel}. The current script suspends until
2846 another script is available to retrieve the value.
2847 @end deffn
2849 A low-level API also exists for using channels outside of a script via
2850 callback procedures:
2852 @deffn {Procedure} channel-get! channel proc
2853 Asynchronously retrieve a value from @var{channel} and call @var{proc}
2854 with that value.
2855 @end deffn
2857 @deffn {Procedure} channel-put! channel data [thunk]
2858 Asynchronously send @var{data} to @var{channel} and call @var{thunk}
2859 after it has been received.
2860 @end deffn