doc: Rename "Blending and Depth Testing" section to just "Blending".
[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)} module, lies
12 an event loop. This loop, or ``kernel'', is responsible for ensuring
13 that the game is updated at the desired interval, rendering the
14 current state of the game world, and handling errors if they occur.
15 The kernel implements what is known as a ``fixed timestep'' game loop,
16 meaning that the game simulation will be advanced by a fixed interval
17 of time and will never vary from frame to frame, unlike some other
18 styles of game loops. The appropriately named @code{run-game} and
19 @code{abort-game} procedures are the entry and exit points to the
20 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 sdl)} module:
83 @code{run-game/sdl}.
85 @deffn {Procedure} run-game/sdl [#:window-title "Chickadee!"] @
86 [#:window-width 640] [#:window-height 480] @
87 [#:window-fullscreen? @code{#f}] [#:update-hz 60] @
88 [#:load] [#:update] [#:draw] [#:quit] @
89 [#:key-press] [#:key-release] [#:text-input] @
90 [#:mouse-press] [#:mouse-release] [#:mouse-move] @
91 [#:controller-add] [#:controller-remove] [#:controller-press] @
92 [#:controller-release] [#:controller-move] [#:error]
94 Run the Chickadee game loop using the SDL engine.
96 A new graphical window will be opened with @var{window-width} x
97 @var{window-height} as its dimensions, @var{window-title} as its
98 title, and in fullscreen mode if @var{window-fullscreen?} is
99 @code{#t}.
101 @itemize
102 @item
103 @var{load}: Called with zero arguments when the game window has opened
104 but before the game loop has started. Can be used to perform
105 initialization that requires an open window and OpenGL context such as
106 loading textures.
108 @item
109 @var{update}: Called @var{update-hz} times per second with one
110 argument: The amount of time to advance the game simulation.
112 @item
113 @var{draw}: Called each time a frame should be rendered with a single
114 argument known as the @code{alpha} value. See the documentation for
115 @code{run-game} for an explanation of this value.
117 @item
118 @var{quit}: Called with zero arguments when the user tries to close
119 the game window. The default behavior is to exit the game.
121 @item
122 @var{key-press}: Called with four arguments when a key is pressed on
123 the keyboard:
125 @enumerate
126 @item
127 @var{key}: The symbolic name of the ``virtual'' key that was pressed.
128 For example: @code{backspace}. It's called a virtual key because the
129 operating system may map a physical keyboard key to another key
130 entirely, such as how the author likes to bind the ``caps lock'' key
131 to mean ``control''.
133 @item
134 @var{scancode}: The symbolic name of the physical key that was
135 pressed.
137 @item
138 @var{modifiers}: A list of the symbolic names of modifier keys that
139 were being held down when the key was pressed. Possible values
140 include @code{ctrl}, @code{alt}, and @code{shift}.
142 @item
143 @var{repeat?}: @code{#t} if this is a repeated press of the same key.
145 @end enumerate
147 @item
148 @var{key-release}: Called with three arguments when a key is released
149 on the keyboard:
151 @enumerate
152 @item
153 @var{key}: The symbolic name of the ``virtual'' key that was released.
155 @item
156 @var{scancode}: The symbolic name of the physical key that was
157 released.
159 @item
160 @var{modifiers}: A list of the symbolic names of modifier keys that
161 were being held down when the key was released.
163 @end enumerate
165 @item
166 @var{text-input}: Called with a single argument, a string of text,
167 when printable text is typed on the keyboard.
169 @item
170 @var{mouse-press}: Called with four arguments when a mouse button is
171 pressed:
172 @enumerate
174 @item
175 @var{button}: The symbolic name of the button that was pressed, such
176 as @code{left}, @code{middle}, or @code{right}.
178 @item
179 @var{clicks}: The number of times the button has been clicked in a row.
181 @item
182 @var{x}: The x coordinate of the mouse cursor.
184 @item
185 @var{y}: The y coordinate of the mouse cursor.
187 @end enumerate
189 @item
190 @var{mouse-release}: Called with three arguments when a mouse button
191 is released:
193 @enumerate
195 @item
196 @var{button}: The symbolic name of the button that was released.
198 @item
199 @var{x}: The x coordinate of the mouse cursor.
201 @item
202 @var{y}: The y coordinate of the mouse cursor.
204 @end enumerate
206 @item
207 @var{mouse-move}: Called with five arguments when the mouse is moved:
209 @enumerate
211 @item
212 @var{x}: The x coordinate of the mouse cursor.
214 @item
215 @var{y}: The y coordinate of the mouse cursor.
217 @item
218 @var{dx}: The amount the mouse has moved along the x axis since the
219 last mouse move event.
221 @item
222 @var{dy}: The amount the mouse has moved along the y axis since the
223 last mouse move event.
225 @item
226 @var{buttons}: A list of the buttons that were pressed down when the
227 mouse was moved.
229 @end enumerate
231 @item
232 @var{controller-add}: Called with a single argument, an SDL game
233 controller object, when a game controller is connected.
235 @item
236 @var{controller-remove}: Called with a single argument, an SDL game
237 controller object, when a game controller is disconnected.
239 @item
240 @var{controller-press}: Called with two arguments when a button on a
241 game controller is pressed:
243 @enumerate
245 @item
246 @var{controller}: The controller that triggered the event.
248 @item
249 @var{button}: The symbolic name of the button that was pressed.
250 Possible buttons are:
252 @itemize
253 @item
254 @code{a}
255 @item
256 @code{b}
257 @item
258 @code{x}
259 @item
260 @code{y}
261 @item
262 @code{back}
263 @item
264 @code{guide}
265 @item
266 @code{start}
267 @item
268 @code{left-stick}
269 @item
270 @code{right-stick}
271 @item
272 @code{left-shoulder}
273 @item
274 @code{right-shoulder}
275 @item
276 @code{dpad-up}
277 @item
278 @code{dpad-down}
279 @item
280 @code{dpad-left}
281 @item
282 @code{dpad-right}
284 @end itemize
286 @end enumerate
288 @item
289 @var{controller-release}: Called with two arguments when a button on a
290 game controller is released:
292 @enumerate
294 @item
295 @var{controller}: The controller that triggered the event.
297 @item
298 @var{button}: The symbolic name of the button that was released.
300 @end enumerate
302 @item
303 @var{controller-move}: Called with three arguments when an analog
304 stick or trigger on a game controller is moved:
306 @enumerate
308 @item
309 @var{controller}: The controller that triggered the event.
311 @item
312 @var{axis}: The symbolic name of the axis that was moved. Possible
313 values are:
315 @itemize
316 @item
317 @code{left-x}
318 @item
319 @code{left-y}
320 @item
321 @code{right-x}
322 @item
323 @code{right-y}
324 @item
325 @code{trigger-left}
326 @item
327 @code{trigger-right}
328 @end itemize
330 @end enumerate
332 @item
333 @var{error}: Called with three arguments when an error occurs:
335 @enumerate
337 @item
338 @var{stack}: The call stack at the point of error.
340 @item
341 @var{key}: The exception key.
343 @item
344 @var{args}: The arguments thrown with the exception.
346 @end enumerate
348 The default behavior is to re-throw the error.
350 @end itemize
352 @end deffn
354 @node Math
355 @section Math
357 Chickadee contains data types and procedures for performing the most
358 common computations in video game simulations such as linear algebra
359 with vectors and matrices and axis-aligned bounding box collision
360 detection.
362 @menu
363 * Basics:: Commonly used, miscellaneous things.
364 * Vectors:: Euclidean vectors.
365 * Rectangles:: Axis-aligned bounding boxes.
366 * Grid:: Spatial partitioning for bounding boxes.
367 * Matrices:: Transformation matrices.
368 * Quaternions:: Rotations about an arbitrary axis.
369 * Easings:: Easing functions for interesting animations.
370 * Bezier Curves:: Cubic Bezier curves and paths in 2D space.
371 * Path Finding:: Generic A* path finding.
372 @end menu
374 @node Basics
375 @subsection Basics
377 @defvar pi
378 An essential constant for all trigonometry. @code{@U{03C0}} is the ratio
379 of a circle's circumferences to its diameter. Since @code{@U{03C0}} is an
380 irrational number, the @var{pi} in Chickadee is a mere floating point
381 approximation that is ``good enough.''
382 @end defvar
384 @defvar pi/2
385 Half of @var{pi}.
386 @end defvar
388 @deffn {Procedure} cotan @var{z}
389 Return the cotangent of @var{z}.
390 @end deffn
392 @node Vectors
393 @subsection Vectors
395 Unlike Scheme's vector data type, which is a sequence of arbitrary
396 Scheme objects, Chickadee's @code{(chickadee math vector)} module
397 provides vectors in the linear algebra sense: Sequences of numbers
398 specialized for particular coordinate spaces. As of now, Chickadee
399 provides 2D and 3D vectors, with 4D vector support coming in a future
400 release.
402 Here's a quick example of adding two vectors:
404 @example
405 (define v (vec2+ (vec2 1 2) (vec2 3 4)))
406 @end example
408 Since vectors are used so frequently, the reader macro @code{#v} is
409 used to cut down on typing:
411 @example
412 (define v (vec2+ #v(1 2) #v(3 4)))
413 @end example
415 @subsubsection A Note About Performance
417 A lot of time has been spent making Chickadee's vector operations
418 perform relatively efficiently in critical code paths where excessive
419 garbage generation will cause major performance issues. The general
420 rule is that procedures ending with @code{!} perform an in-place
421 modification of one of the arguments in order to avoid allocating a
422 new vector. These procedures are also inlined by Guile's compiler in
423 order to take advantage of optimizations relating to floating point
424 math operations. The downside is that since these are not pure
425 functions, they do not compose well and create more verbose code.
427 @subsubsection 2D Vectors
429 @deffn {Procedure} vec2 @var{x} @var{y}
430 Return a new 2D vector with coordinates (@var{x}, @var{y}).
431 @end deffn
433 @deffn {Procedure} vec2/polar @var{r} @var{theta}
434 Return a new 2D vector containing the Cartesian representation of the
435 polar coordinate (@var{r}, @var{theta}). The angle @var{theta} is
436 measured in radians.
437 @end deffn
439 @deffn {Procedure} vec2? @var{obj}
440 Return @code{#t} if @var{obj} is a 2D vector.
441 @end deffn
443 @deffn {Procedure} vec2-x @var{v}
444 Return the X coordinate of the 2D vector @var{v}.
445 @end deffn
447 @deffn {Procedure} vec2-y @var{v}
448 Return the Y coordinate of the 2D vector @var{v}.
449 @end deffn
451 @deffn {Procedure} vec2-copy @var{v}
452 Return a fresh copy of the 2D vector @var{v}.
453 @end deffn
455 @deffn {Procedure} vec2-magnitude @var{v}
456 Return the magnitude of the 2D vector @var{v}.
457 @end deffn
459 @deffn {Procedure} vec2-dot-product @var{v1} @var{v2}
460 Return the dot product of the 2D vectors @var{v1} and @var{v2}.
461 @end deffn
463 @deffn {Procedure} vec2-normalize @var{v}
464 Return the normalized form of the 2D vector @var{v}.
465 @end deffn
467 @deffn {Procedure} vec2+ @var{v} @var{x}
468 Add @var{x}, either a 2D vector or a scalar (i.e. a real number), to
469 the 2D vector @var{v} and return a new vector containing the sum.
470 @end deffn
472 @deffn {Procedure} vec2- @var{v} @var{x}
473 Subtract @var{x}, either a 2D vector or a scalar, from the 2D vector
474 @var{v} and return a new vector containing the difference.
475 @end deffn
477 @deffn {Procedure} vec2* @var{v} @var{x}
478 Multiply the 2D vector @var{v} by @var{x}, a 2D vector or a scalar,
479 and return a new vector containing the product.
480 @end deffn
482 @deffn {Procedure} set-vec2-x! @var{v} @var{x}
483 Set the X coordinate of the 2D vector @var{v} to @var{x}.
484 @end deffn
486 @deffn {Procedure} set-vec2-y! @var{v} @var{y}
487 Set the Y coordinate of the 2D vector @var{v} to @var{y}.
488 @end deffn
490 @deffn {Procedure} vec2-copy! @var{source} @var{target}
491 Copy the 2D vector @var{source} into the 2D vector @var{target}.
492 @end deffn
494 @deffn {Procedure} vec2-add! @var{v} @var{x}
495 Perform an in-place modification of the 2D vector @var{v} by adding
496 @var{x}, a 2D vector or a scalar.
497 @end deffn
499 @deffn {Procedure} vec2-sub! @var{v} @var{x}
500 Perform an in-place modification of the 2D vector @var{v} by
501 subtracting @var{x}, a 2D vector or a scalar.
502 @end deffn
504 @deffn {Procedure} vec2-mult! @var{v} @var{x}
505 Perform an in-place modification of the 2D vector @var{v} by
506 multiplying it by @var{x}, a 2D vector or a scalar.
507 @end deffn
509 @subsubsection 3D Vectors
511 @deffn {Procedure} vec3 @var{x} @var{y}
512 Return a new 2D vector with coordinates (@var{x}, @var{y}).
513 @end deffn
515 @deffn {Procedure} vec3? @var{obj}
516 Return @code{#t} if @var{obj} is a 3D vector.
517 @end deffn
519 @deffn {Procedure} vec3-x @var{v}
520 Return the X coordinate of the 3D vector @var{v}.
521 @end deffn
523 @deffn {Procedure} vec3-y @var{v}
524 Return the Y coordinate of the 3D vector @var{v}.
525 @end deffn
527 @deffn {Procedure} vec3-z @var{v}
528 Return the Z coordinate of the 3D vector @var{v}.
529 @end deffn
531 @deffn {Procedure} vec3-copy @var{v}
532 Return a fresh copy of the 3D vector @var{v}.
533 @end deffn
535 @deffn {Procedure} vec3-magnitude @var{v}
536 Return the magnitude of the 3D vector @var{v}.
537 @end deffn
539 @deffn {Procedure} vec3-dot-product @var{v1} @var{v2}
540 Return the dot product of the 3D vectors @var{v1} and @var{v2}.
541 @end deffn
543 @deffn {Procedure} vec3-normalize @var{v}
544 Return the normalized form of the 3D vector @var{v}.
545 @end deffn
547 @deffn {Procedure} vec3+ @var{v} @var{x}
548 Add @var{x}, either a 3D vector or a scalar (i.e. a real number), to
549 the 3D vector @var{v} and return a new vector containing the sum.
550 @end deffn
552 @deffn {Procedure} vec3- @var{v} @var{x}
553 Subtract @var{x}, either a 3D vector or a scalar, from the 3D vector
554 @var{v} and return a new vector containing the difference.
555 @end deffn
557 @deffn {Procedure} vec3* @var{v} @var{x}
558 Multiply the 3D vector @var{v} by @var{x}, a 3D vector or a scalar,
559 and return a new vector containing the product.
560 @end deffn
562 @deffn {Procedure} set-vec3-x! @var{v} @var{x}
563 Set the X coordinate of the 3D vector @var{v} to @var{x}.
564 @end deffn
566 @deffn {Procedure} set-vec3-y! @var{v} @var{y}
567 Set the Y coordinate of the 3D vector @var{v} to @var{y}.
568 @end deffn
570 @deffn {Procedure} set-vec3-z! @var{v} @var{z}
571 Set the Z coordinate of the 3D vector @var{v} to @var{z}.
572 @end deffn
574 @deffn {Procedure} vec3-copy! @var{source} @var{target}
575 Copy the 3D vector @var{source} into the 3D vector @var{target}.
576 @end deffn
578 @deffn {Procedure} vec3-add! @var{v} @var{x}
579 Perform an in-place modification of the 3D vector @var{v} by adding
580 @var{x}, a 3D vector or a scalar.
581 @end deffn
583 @deffn {Procedure} vec3-sub! @var{v} @var{x}
584 Perform an in-place modification of the 3D vector @var{v} by
585 subtracting @var{x}, a 3D vector or a scalar.
586 @end deffn
588 @deffn {Procedure} vec3-mult! @var{v} @var{x}
589 Perform an in-place modification of the 3D vector @var{v} by
590 multiplying it by @var{x}, a 3D vector or a scalar.
591 @end deffn
593 @node Rectangles
594 @subsection Rectangles
596 The @code{(chickadee math rect)} module provides an API for
597 manipulating axis-aligned bounding boxes (AABBs). AABBs are often
598 used for collision detection in games. Common use-cases are defining
599 ``hitboxes'' in platformers or using them for the ``broad phase'' of a
600 collision detection algorithm that uses a more complex (and thus
601 slower) method of determining the actual collisions.
603 Like some of the other math modules, there exists a collection of
604 functions that do in-place modification of rectangles for use in
605 performance critical code paths.
607 @deffn {Procedure} make-rect @var{x} @var{y} @var{width} @var{height}
608 Create a new rectangle that is @var{width} by @var{height} in size and
609 whose bottom-left corner is located at (@var{x}, @var{y}).
610 @end deffn
612 @deffn {Procedure} rect? @var{obj}
613 Return @code{#t} if @var{obj} is a rectangle.
614 @end deffn
616 @deffn {Procedure} rect-within? @var{rect1} @var{rect2}
617 Return @code{#t} if @var{rect2} is completely within @var{rect1}.
618 @end deffn
620 @deffn {Procedure} rect-intersects? @var{rect1} @var{rect2}
621 Return @code{#t} if @var{rect2} overlaps @var{rect1}.
622 @end deffn
624 @deffn {Procedure} rect-contains? @var{rect} @var{x} @var{y}
625 Return @code{#t} if the coordinates (@var{x}, @var{y}) are within
626 @var{rect}.
627 @end deffn
629 @deffn {Procedure} rect-contains-vec2? @var{rect} @var{v}
630 Return @code{#t} if the 2D vector @var{v} is within the bounds of
631 @var{rect}.
632 @end deffn
634 @deffn {Procedure} rect-x @var{rect}
635 Return the X coordinate of the lower-left corner of @var{rect}.
636 @end deffn
638 @deffn {Procedure} rect-y @var{rect}
639 Return the Y coordinate of the lower-left corner of @var{rect}.
640 @end deffn
642 @deffn {Procedure} rect-left @var{rect}
643 Return the left-most X coordinate of @var{rect}.
644 @end deffn
646 @deffn {Procedure} rect-right @var{rect}
647 Return the right-most X coordinate of @var{rect}.
648 @end deffn
650 @deffn {Procedure} rect-bottom @var{rect}
651 Return the bottom-most Y coordinate of @var{rect}.
652 @end deffn
654 @deffn {Procedure} rect-top @var{rect}
655 Return the top-most Y coordinate of @var{rect}.
656 @end deffn
658 @deffn {Procedure} rect-center-x @var{rect}
659 Return the X coordinate of the center of @var{rect}.
660 @end deffn
662 @deffn {Procedure} rect-center-y @var{rect}
663 Return the Y coordinate of the center of @var{rect}.
664 @end deffn
666 @deffn {Procedure} rect-width @var{rect}
667 Return the width of @var{rect}.
668 @end deffn
670 @deffn {Procedure} rect-height @var{rect}
671 Return the height of @var{rect}.
672 @end deffn
674 @deffn {Procedure} rect-area @var{rect}
675 Return the surface area covered by @var{rect}.
676 @end deffn
678 @deffn {Procedure} rect-clamp-x @var{rect} @var{x}
679 Restrict @var{x} to the portion of the X axis covered by @var{rect}.
680 @end deffn
682 @deffn {Procedure} rect-clamp-y @var{rect} @var{y}
683 Restrict @var{y} to the portion of the Y axis covered by @var{rect}.
684 @end deffn
686 @deffn {Procedure} rect-clamp @var{rect1} @var{rect2}
687 Return a new rect that adjusts the location of @var{rect1} so that it
688 is completely within @var{rect2}. An exception is thrown in the case
689 that @var{rect1} cannot fit completely within @var{rect2}.
690 @end deffn
692 @deffn {Procedure} rect-move @var{rect} @var{x} @var{y}
693 Return a new rectangle based on @var{rect} but moved to the
694 coordinates (@var{x}, @var{y}).
695 @end deffn
697 @deffn {Procedure} rect-move-vec2 @var{rect} @var{v}
698 Return a new rectangle based on @var{rect} but moved to the
699 coordinates in the 2D vector @var{v}.
700 @end deffn
702 @deffn {Procedure} rect-move-by @var{rect} @var{x} @var{y}
703 Return a new rectangle based on @var{rect} but moved by (@var{x},
704 @var{y}) units relative to its current location.
705 @end deffn
707 @deffn {Procedure} rect-move-by-vec2 @var{rect} @var{v}
708 Return a new rectangle based on @var{rect} but moved by the 2D vector
709 @var{v} relative to its current location.
710 @end deffn
712 @deffn {Procedure} rect-inflate @var{rect} @var{width} @var{height}
713 Return a new rectangle based on @var{rect}, but expanded by
714 @var{width} units on the X axis and @var{height} units on the Y axis,
715 while keeping the rectangle centered on the same point.
716 @end deffn
718 @deffn {Procedure} rect-union @var{rect1} @var{rect2}
719 Return a new rectangle that completely covers the area of @var{rect1}
720 and @var{rect2}.
721 @end deffn
723 @deffn {Procedure} rect-clip @var{rect1} @var{rect2}
724 Return a new rectangle that is the overlapping region of @var{rect1}
725 and @var{rect2}. If the two rectangles do not overlap, a rectangle of
726 0 width and 0 height is returned.
727 @end deffn
729 @deffn {Procedure} set-rect-x! @var{rect} @var{x}
730 Set the left X coordinate of @var{rect} to @var{x}.
731 @end deffn
733 @deffn {Procedure} set-rect-y! @var{rect} @var{y}
734 Set the bottom Y coordinate of @var{rect} to @var{y}.
735 @end deffn
737 @deffn {Procedure} set-rect-width! @var{rect} @var{width}
738 Set the width of @var{rect} to @var{width}.
739 @end deffn
741 @deffn {Procedure} set-rect-height! @var{rect} @var{height}
742 Set the height of @var{rect} to @var{height}.
743 @end deffn
745 @deffn {Procedure} rect-move! @var{rect} @var{x} @var{y}
746 Move @var{rect} to (@var{x}, @var{y}) in-place.
747 @end deffn
749 @deffn {Procedure} rect-move-vec2! @var{rect} @var{v}
750 Move @var{rect} to the 2D vector @var{v} in-place.
751 @end deffn
753 @deffn {Procedure} rect-move-by! @var{rect} @var{x} @var{y}
754 Move @var{rect} by (@var{x}, @var{y}) in-place.
755 @end deffn
757 @deffn {Procedure} rect-move-by-vec2! @var{rect} @var{v}
758 Move @var{rect} by the 2D vector @var{v} in-place.
759 @end deffn
761 @deffn {Procedure} rect-inflate! @var{rect} @var{width} @var{height}
762 Expand @var{rect} by @var{width} and @var{height} in-place.
763 @end deffn
765 @deffn {Procedure} rect-union! @var{rect1} @var{rect2}
766 Modify @var{rect1} in-place to completely cover the area of both
767 @var{rect1} and @var{rect2}.
768 @end deffn
770 @deffn {Procedure} rect-clip! @var{rect1} @var{rect2}
771 Modify @var{rect1} in-place to be the overlapping region of
772 @var{rect1} and @var{rect2}.
773 @end deffn
775 @deffn {Procedure} rect-clamp! @var{rect1} @var{rect2}
776 Adjust the location of @var{rect1} in-place so that its bounds are
777 completely within @var{rect2}. An exception is thrown in the case
778 that @var{rect1} cannot fit completely within @var{rect2}.
779 @end deffn
781 @deffn {Procedure} vec2-clamp-to-rect! @var{v} @var{rect}
782 Restrict the coordinates of the 2D vector @var{v} so that they are
783 within the bounds of @var{rect}. @var{v} is modified in-place.
784 @end deffn
786 @node Grid
787 @subsection Grid
789 The @code{(chickadee math grid)} module provides a simple spatial
790 partitioning system for axis-aligned bounding boxes
791 (@pxref{Rectangles}) in 2D space. The grid divides the world into
792 tiles and keeps track of which rectangles occupy which tiles. When
793 there are lots of moving objects in the game world that need collision
794 detection, the grid greatly speeds up the process. Instead of
795 checking collisions of each object against every other object (an
796 O(n^2) operation), the grid quickly narrows down which objects could
797 possibly be colliding and only performs collision testing against a
798 small set of objects.
800 In addition to checking for collisions, the grid also handles the
801 resolution of collisions. Exactly how each collision is resolved is
802 user-defined. A player bumping into a wall may slide against it. An
803 enemy colliding with a projectile shot by the player may get pushed
804 back in the opposite direction. Two players colliding may not need
805 resolution at all and will just pass through each other. The way this
806 works is that each time an object (A) is moved within the grid, the
807 grid looks for an object (B) that may possibly be colliding with A. A
808 user-defined procedure known as a ``filter'' is then called with both
809 A and B. If the filter returns @code{#f}, it means that even if A and
810 B are colliding, no collision resolution is needed. In this case the
811 grid won't waste time checking if they really do collide because it
812 doesn't matter. If A and B are collidable, then the filter returns a
813 procedure that implements the resolution technique. The grid will
814 then perform a collision test. If A and B are colliding, the resolver
815 procedure is called. It's the resolvers job to adjust the objects
816 such that they are no longer colliding. The grid module comes with a
817 very simple resolution procedure, @code{slide}, that adjusts object A
818 by the smallest amount so that it no longer overlaps with B. By using
819 this filtering technique, a game can resolve collisions between
820 different objects in different ways.
822 @deffn {Procedure} make-grid [@var{cell-size} 64]
823 Return a new grid partitioned into @var{cell-size} tiles.
824 @end deffn
826 @deffn {Procedure} grid? @var{obj}
827 Return @code{#t} if @var{obj} is a grid.
828 @end deffn
830 @deffn {Procedure} cell? @var{obj}
831 Return @code{#t} if @var{obj} is a grid cell.
832 @end deffn
834 @deffn {Procedure} cell-count @var{cell}
835 Return the number of items in @var{cell}.
836 @end deffn
838 @deffn {Procedure} grid-cell-size @var{grid}
839 Return the cell size of @var{grid}.
840 @end deffn
842 @deffn {Procedure} grid-cell-count @var{grid}
843 Return the number of cells currently in @var{grid}.
844 @end deffn
846 @deffn {Procedure} grid-item-count @var{grid}
847 Return the number of items in @var{grid}.
848 @end deffn
850 @deffn {Procedure} grid-add @var{grid} @var{item} @var{x} @var{y} @
851 @var{width} @var{height}
853 Add @var{item} to @var{grid} represented by the axis-aligned bounding
854 box whose lower-left corner is at (@var{x}, @var{y}) and is
855 @var{width} x @var{height} in size.
856 @end deffn
858 @deffn {Procedure} grid-remove @var{grid} @var{item}
859 Return @var{item} from @var{grid}.
860 @end deffn
862 @deffn {Procedure} grid-clear @var{grid}
863 Remove all items from @var{grid}.
864 @end deffn
866 @deffn {Procedure} grid-move @var{grid} @var{item} @var{position} @var{filter}
867 Attempt to move @var{item} in @var{grid} to @var{position} (a 2D
868 vector) and check for collisions. For each collision, @var{filter}
869 will be called with two arguments: @var{item} and the item it collided
870 with. If a collision occurs, @var{position} may be modified to
871 resolve the colliding objects.
872 @end deffn
874 @deffn {Procedure} for-each-cell @var{proc} @var{grid} [@var{rect}]
875 Call @var{proc} with each cell in @var{grid} that intersects
876 @var{rect}, or every cell if @var{rect} is @code{#f}.
877 @end deffn
879 @deffn {Procedure} for-each-item @var{proc} @var{grid}
880 Call @var{proc} for each item in @var{grid}.
881 @end deffn
883 @deffn {Procedure} slide @var{item} @var{item-rect} @
884 @var{other} @var{other-rect} @var{goal}
886 Resolve the collision that occurs between @var{item} and @var{other}
887 when moving @var{item-rect} to @var{goal} by sliding @var{item-rect}
888 the minimum amount needed to make it no longer overlap
889 @var{other-rect}.
890 @end deffn
892 @node Matrices
893 @subsection Matrices
895 The @code{(chickadee math matrix)} module provides an interface for
896 working with the most common type of matrices in game development: 4x4
897 transformation matrices.
899 @subsubsection Another Note About Performance
901 Much like the vector API, the matrix API is commonly used in
902 performance critical code paths. In order to reduce the amount of
903 garbage generated and improve matrix multiplication performance, there
904 are many procedures that perform in-place modifications of matrix
905 objects.
907 @subsubsection Matrix Operations
909 @deffn {Procedure} make-matrix4 @var{aa} @var{ab} @var{ac} @var{ad} @
910 @var{ba} @var{bb} @var{bc} @var{bd} @
911 @var{ca} @var{cb} @var{cc} @var{cd} @
912 @var{da} @var{db} @var{dc} @var{dd}
914 Return a new 4x4 matrix initialized with the given 16 values in
915 column-major format.
916 @end deffn
918 @deffn {Procedure} make-null-matrix4
919 Return a new 4x4 matrix with all values initialized to 0.
920 @end deffn
922 @deffn {Procedure} make-identity-matrix4
923 Return a new 4x4 identity matrix. Any matrix multiplied by the
924 identity matrix yields the original matrix. This procedure is
925 equivalent to the following code:
927 @example
928 (make-matrix4 1 0 0 0
929 0 1 0 0
930 0 0 1 0
931 0 0 0 1)
932 @end example
934 @end deffn
936 @deffn {Procedure} matrix4? @var{obj}
937 Return @code{#t} if @var{obj} is a 4x4 matrix.
938 @end deffn
940 @deffn {Procedure} matrix4* . @var{matrices}
941 Return a new 4x4 matrix containing the product of multiplying all of
942 the given @var{matrices}.
944 Note: Remember that matrix multiplication is @strong{not} commutative!
945 @end deffn
947 @deffn {Procedure} orthographic-projection @var{left} @var{right} @
948 @var{top} @var{bottom} @
949 @var{near} @var{far}
951 Return a new 4x4 matrix that represents an orthographic (2D)
952 projection for the horizontal clipping plane @var{top} and
953 @var{bottom}, the vertical clipping plane @var{top} and @var{bottom},
954 and the depth clipping plane @var{near} and @var{far}.
955 @end deffn
957 @deffn {Procedure} perspective-projection @var{fov} @
958 @var{aspect-ratio} @
959 @var{near} @var{far}
961 Return a new 4x4 matrix that represents a perspective (3D) projection
962 with a field of vision of @var{fov} radians, an aspect ratio of
963 @var{aspect-ratio}, and a depth clipping plane defined by @var{near}
964 and @var{far}.
965 @end deffn
967 @deffn {Procedure} matrix4-translate @var{x}
968 Return a new 4x4 matrix that represents a translation by @var{x}, a 2D
969 vector, a 3D vector, or a rectangle (in which case the bottom-left
970 corner of the rectangle is used).
971 @end deffn
973 @deffn {Procedure} matrix4-scale @var{s}
974 Return a new 4x4 matrix that represents a scaling along the X, Y, and
975 Z axes by the scaling factor @var{s}, a real number.
976 @end deffn
978 @deffn {Procedure} matrix4-rotate @var{q}
979 Return a new 4x4 matrix that represents a rotation about an arbitrary
980 axis defined by the quaternion @var{q}.
981 @end deffn
983 @deffn {Procedure} matrix4-rotate-z @var{theta}
984 Return a new 4x4 matrix that represents a rotation about the Z axis by
985 @var{theta} radians.
986 @end deffn
988 @deffn {Procedure} matrix4-identity! @var{matrix}
989 Modify @var{matrix} in-place to contain the identity matrix.
990 @end deffn
992 @deffn {Procedure} matrix4-mult! @var{dest} @var{a} @var{b}
993 Multiply the 4x4 matrix @var{a} by the 4x4 matrix @var{b} and store
994 the result in the 4x4 matrix @var{dest}.
995 @end deffn
997 @deffn {Procedure} matrix4-translate! @var{matrix} @var{x}
998 Modify @var{matrix} in-place to contain a translation by @var{x}, a 2D
999 vector, a 3D vector, or a rectangle (in which case the bottom-left
1000 corner of the rectangle is used).
1001 @end deffn
1003 @deffn {Procedure} matrix4-scale! @var{matrix} @var{s}
1004 Modify @var{matrix} in-place to contain a scaling along the X, Y, and
1005 Z axes by the scaling factor @var{s}, a real number.
1006 @end deffn
1008 @deffn {Procedure} matrix4-rotate! @var{matrix} @var{q}
1009 Modify @var{matrix} in-place to contain a rotation about an arbitrary
1010 axis defined by the quaternion @var{q}.
1011 @end deffn
1013 @deffn {Procedure} matrix4-rotate-z! @var{matrix} @var{theta}
1014 Modify @var{matrix} in-place to contain a rotation about the Z axis by
1015 @var{theta} radians.
1016 @end deffn
1018 @deffn {Procedure} matrix4-2d-transform! @var{matrix} [#:origin] @
1019 [#:position] [#:rotation] @
1020 [#:scale] [#:skew]
1022 Modify @var{matrix} in-place to contain the transformation described
1023 by @var{position}, a 2D vector or rectangle, @var{rotation}, a scalar
1024 representing a rotation about the Z axis, @var{scale}, a 2D vector,
1025 and @var{skew}, a 2D vector. The transformation happens with respect
1026 to @var{origin}, a 2D vector. If an argument is not provided, that
1027 particular transformation will not be included in the result.
1028 @end deffn
1030 @deffn {Procedure} transform! @var{matrix} @var{v}
1031 Modify the 2D vector @var{v} in-place by multiplying it by the 4x4
1032 matrix @var{matrix}.
1033 @end deffn
1035 @node Quaternions
1036 @subsection Quaternions
1038 In game development, the quaternion is most often used to represent
1039 rotations. Why not use a matrix for that, you may ask. Unlike
1040 matrices, quaternions can be interpolated (animated) and produce a
1041 meaningful result. When interpolating two quaternions, there is a
1042 smooth transition from one rotation to another, whereas interpolating
1043 two matrices would yield garbage.
1045 @deffn {Procedure} quaternion @var{x} @var{y} @var{z} @var{w}
1046 Return a new quaternion with values @var{x}, @var{y}, @var{z}, and
1047 @var{w}.
1048 @end deffn
1050 @deffn {Procedure} quaternion? @var{obj}
1051 Return @code{#t} if @var{obj} is a quaternion.
1052 @end deffn
1054 @deffn {Procedure} quaternion-w @var{q}
1055 Return the W component of the quaternion @var{q}.
1056 @end deffn
1058 @deffn {Procedure} quaternion-x @var{q}
1059 Return the X component of the quaternion @var{q}.
1060 @end deffn
1062 @deffn {Procedure} quaternion-y @var{q}
1063 Return the Y component of the quaternion @var{q}.
1064 @end deffn
1066 @deffn {Procedure} quaternion-z @var{q}
1067 Return the Z component of the quaternion @var{q}.
1068 @end deffn
1070 @deffn {Procedure} make-identity-quaternion
1071 Return the identity quaternion.
1072 @end deffn
1074 @node Easings
1075 @subsection Easings
1077 Easing functions are essential for animation. Each easing function
1078 provides a different path to go from an initial value to a final
1079 value. These functions make an excellent companion to the
1080 @code{tween} procedure (@pxref{Tweening}). Experiment with them to
1081 figure out which function makes an animation look the best.
1083 Pro tip: @code{smoothstep} provides nice results most of the time and
1084 creates smoother animation than using @code{linear}.
1086 @deffn {Procedure} linear @var{t}
1087 @end deffn
1089 @deffn {Procedure} smoothstep @var{t}
1090 @end deffn
1092 @deffn {Procedure} ease-in-quad @var{t}
1093 @end deffn
1095 @deffn {Procedure} ease-out-quad @var{t}
1096 @end deffn
1098 @deffn {Procedure} ease-in-out-quad @var{t}
1099 @end deffn
1101 @deffn {Procedure} ease-in-cubic @var{t}
1102 @end deffn
1104 @deffn {Procedure} ease-out-cubic @var{t}
1105 @end deffn
1107 @deffn {Procedure} ease-in-out-cubic @var{t}
1108 @end deffn
1110 @deffn {Procedure} ease-in-quart @var{t}
1111 @end deffn
1113 @deffn {Procedure} ease-out-quart @var{t}
1114 @end deffn
1116 @deffn {Procedure} ease-in-out-quart @var{t}
1117 @end deffn
1119 @deffn {Procedure} ease-in-quint @var{t}
1120 @end deffn
1122 @deffn {Procedure} ease-out-quint @var{t}
1123 @end deffn
1125 @deffn {Procedure} ease-in-out-quint @var{t}
1126 @end deffn
1128 @deffn {Procedure} ease-in-sine @var{t}
1129 @end deffn
1131 @deffn {Procedure} ease-out-sine @var{t}
1132 @end deffn
1134 @deffn {Procedure} ease-in-out-sine @var{t}
1135 @end deffn
1137 @node Bezier Curves
1138 @subsection Bezier Curves
1140 The @code{(chickadee math bezier)} module provides an API for
1141 describing cubic Bezier curves in 2D space. These curves are notably
1142 used in font description, vector graphics programs, and when it comes
1143 to games: path building. With Bezier curves, it's somewhat easy to
1144 create a smooth looking path for an enemy to move along, for example.
1145 Bezier curves become particularly interesting when they are chained
1146 together to form a Bezier ``path'', where the end point of one curve
1147 becomes the starting point of the next.
1149 Currently, the rendering of Bezier curves is rather crude and provided
1150 mostly for visualizing and debugging curves that would be unseen in
1151 the final game. See @xref{Lines and Shapes} for more information.
1153 @deffn {Procedure} make-bezier-curve @var{p0} @var{p1} @var{p2} @var{p3}
1154 Return a new Bezier curve object whose starting point is @var{p0},
1155 ending point is @var{p3}, and control points are @var{p1} and
1156 @var{p2}. All points are 2D vectors.
1157 @end deffn
1159 @deffn {Procedure} bezier-curve? @var{obj}
1160 Return @code{#t} if @var{obj} is a Bezier curve.
1161 @end deffn
1163 @deffn {Procedure} bezier-curve-p0 @var{bezier}
1164 Return the starting point of @var{bezier}.
1165 @end deffn
1167 @deffn {Procedure} bezier-curve-p1 @var{bezier}
1168 Return the first control point of @var{bezier}.
1169 @end deffn
1171 @deffn {Procedure} bezier-curve-p2 @var{bezier}
1172 Return the second control point of @var{bezier}.
1173 @end deffn
1175 @deffn {Procedure} bezier-curve-p3 @var{bezier}
1176 Return the end point of @var{bezier}.
1177 @end deffn
1179 @deffn {Procedure} bezier-path . @var{control-points}
1180 Return a list of connected bezier curves defined by
1181 @var{control-points}. The first curve is defined by the first 4
1182 arguments and every additional curve thereafter requires 3 additional
1183 arguments.
1184 @end deffn
1186 @deffn {Procedure} bezier-curve-point-at @var{bezier} @var{t}
1187 Return the coordinates for @var{bezier} at @var{t} (a value in the
1188 range [0, 1] representing how far from the start of the curve to
1189 check) as a 2D vector.
1190 @end deffn
1192 @deffn {Procedure} bezier-curve-point-at! @var{dest} @var{bezier} @var{t}
1193 Modify the 2D vector @var{dest} in-place to contain the coordinates
1194 for @var{bezier} at @var{t}.
1195 @end deffn
1197 @node Path Finding
1198 @subsection Path Finding
1200 Most game worlds have maps. Often, these games have a need to move
1201 non-player characters around in an unscripted fashion. For example,
1202 in a real-time strategy game, the player may command one of their
1203 units to attack something in the enemy base. To do so, the unit must
1204 calculate the shortest route to get there. It wouldn't be a very fun
1205 game if units didn't know how to transport themselves efficiently.
1206 This is where path finding algorithms come in handy. The
1207 @code{(chickadee math path-finding)} module provides a generic
1208 implementation of the popular A* path finding algorithm. Just add a
1209 map implementation!
1211 The example below defines a very simple town map and finds the
1212 quickest way to get from the town common to the school.
1214 @example
1215 (define world-map
1216 '((town-common . (town-hall library))
1217 (town-hall . (town-common school))
1218 (library . (town-common cafe))
1219 (school . (town-hall cafe))
1220 (cafe . (library school))))
1221 (define (neighbors building)
1222 (assq-ref town-map building))
1223 (define (cost a b) 1)
1224 (define (distance a b) 1)
1225 (define pf (make-path-finder))
1226 (a* pf 'town-common 'school neighbors cost distance)
1227 @end example
1229 In this case, the @code{a*} procedure will return the list
1230 @code{(town-common town-hall school)}, which is indeed the shortest
1231 route. (The other possible route is @code{(town-common library cafe
1232 school)}.)
1234 The @code{a*} procedure does not know anything about about any kind of
1235 map and therefore must be told how to look up neighboring nodes, which
1236 is what the @code{neighbors} procedure in the example does. To
1237 simulate different types of terrain, a cost procedure is used. In
1238 this example, it is just as easy to move between any two nodes because
1239 @code{cost} always returns 1. In a real game, perhaps moving from
1240 from a field to a rocky hill would cost a lot more than moving from
1241 one field to another. Finally, a heuristic is used to calculate an
1242 approximate distance between two nodes on the map. In this simple
1243 association list based graph it is tough to calculate a distance
1244 between nodes, so the @code{distance} procedure isn't helpful and
1245 always returns 1. In a real game with a tile-based map, for example,
1246 the heuristic could be a quick Manhattan distance calculation based on
1247 the coordinates of the two map tiles. Choose an appropriate heuristic
1248 for optimal path finding!
1250 @deffn {Procedure} make-path-finder
1251 Return a new path finder object.
1252 @end deffn
1254 @deffn {Procedure} path-finder? @var{obj}
1255 Return @code{#t} if @var{obj} is a path finder.
1256 @end deffn
1258 @deffn {Procedure} a* @var{path-finder} @var{start} @var{goal} @
1259 @var{neighbors} @var{cost} @var{distance}
1261 Return a list of nodes forming a path from @var{start} to @var{goal}
1262 using @var{path-finder} to hold state. @var{neighbors} is a procedure
1263 that accepts a node and returns a list of nodes that neighbor it.
1264 @var{cost} is a procedure that accepts two neighboring nodes and
1265 returns the cost of moving from the first to the second as a real
1266 number. @var{distance} is a procedure that accepts two nodes and
1267 returns an approximate distance between them.
1268 @end deffn
1270 @node Graphics
1271 @section Graphics
1273 Chickadee aims to make hardware-accelerated graphics rendering as
1274 simple and efficient as possible by providing high-level APIs that
1275 interact with the low-level OpenGL API under the hood. Anyone that
1276 has worked with OpenGL directly knows that it has a steep learning
1277 curve and a lot of effort is needed to render even a single triangle.
1278 The Chickadee rendering engine attempts to make it easy to do common
1279 tasks like rendering a sprite while also providing all of the building
1280 blocks to implement additional rendering techniques.
1282 @menu
1283 * Textures:: 2D images.
1284 * Sprites:: Draw 2D images.
1285 * Tile Maps:: Draw 2D tile maps.
1286 * Lines and Shapes:: Draw line segments and polygons.
1287 * Fonts:: Drawing text.
1288 * Particles:: Pretty little flying pieces!
1289 * Blending:: Control how pixels are combined.
1290 * Framebuffers:: Render to texture.
1291 * Viewports:: Restrict rendering to a particular area.
1292 * Rendering Engine:: Rendering state management.
1293 * GPU Buffers:: Send data to the GPU.
1294 * Shaders:: Create custom GPU programs.
1295 @end menu
1297 @node Textures
1298 @subsection Textures
1300 @deffn {Procedure} load-image @var{file} [#:min-filter nearest] @
1301 [#:mag-filter nearest] [#:wrap-s repeat] [#:wrap-t repeat]
1303 Load the image data from @var{file} and return a new texture object.
1305 @var{min-filter} and @var{mag-filter} describe the method that should
1306 be used for minification and magnification when rendering,
1307 respectively. Possible values are @code{nearest} and @code{linear}.
1309 @var{wrap-s} and @var{wrap-t} describe how to interpret texture
1310 coordinates that are greater than @code{1.0}. Possible values are
1311 @code{repeat}, @code{clamp}, @code{clamp-to-border}, and
1312 @code{clamp-to-edge}.
1314 @end deffn
1316 @node Sprites
1317 @subsection Sprites
1319 For those who are new to this game, a sprite is a 2D rectangular
1320 bitmap that is rendered to the screen. For 2D games, sprites are the
1321 most essential graphical abstraction. They are used for drawing maps,
1322 players, NPCs, items, particles, text, etc. In Chickadee, bitmaps are
1323 stored in textures (@pxref{Textures}) and can be used to draw sprites
1324 via the @code{draw-sprite} procedure.
1326 @deffn {Procedure} draw-sprite @var{texture} @var{position} @
1327 [#:origin] [#:scale] [#:rotation] [#:blend-mode alpha] @
1328 [#:rect] [#:shader]
1330 Draw @var{texture} at @var{position}.
1332 Optionally, other transformations may be applied to the sprite.
1333 @var{rotation} specifies the angle to rotate the sprite, in radians.
1334 @var{scale} specifies the scaling factor as a 2D vector. All
1335 transformations are applied relative to @var{origin}, a 2D vector,
1336 which defaults to the lower-left corner.
1338 Alpha blending is used by default but the blending method can be
1339 changed by specifying @var{blend-mode}.
1341 The area drawn to is as big as the texture, by default. To draw to an
1342 arbitrary section of the screen, specify @var{rect}.
1344 Finally, advanced users may specify @var{shader} to change the way the
1345 sprite is rendered entirely.
1346 @end deffn
1348 It's not uncommon to need to draw hundreds or thousands of sprites
1349 each frame. However, GPUs (graphics processing units) are tricky
1350 beasts that prefer to be sent few, large chunks of data to render
1351 rather than many, small chunks. Using @code{draw-sprite} on its own
1352 will involve at least one GPU call @emph{per sprite}, which will
1353 quickly lead to poor performance. To deal with this, a technique
1354 known as ``sprite batching'' can be used. Instead of drawing each
1355 sprite immediately, the sprite batch will build up a large of buffer
1356 of sprites to draw and defer rendering until the last possible moment.
1357 Batching isn't a panacea, though. Batching only works if the sprites
1358 being drawn share as much in common as possible. Every time you draw
1359 a sprite with a different texture or blend mode, the batch will be
1360 sent off to the GPU. Therefore, batching is most useful if you
1361 minimize such changes. A good strategy for reducing texture changes
1362 is to stuff many bitmaps into a single image file and create a
1363 ``texture atlas'' (@pxref{Textures}) to access the sub-images within.
1365 Taking advantage of sprite batching in Chickadee is easy, just wrap
1366 the code that is calling @code{draw-sprite} a lot in the
1367 @code{with-batched-sprites} form.
1369 @deffn {Syntax} with-batched-sprites @var{body} @dots{}
1370 Use batched rendering for all @code{draw-sprite} calls within
1371 @var{body}.
1372 @end deffn
1374 With a basic sprite abstraction in place, it's possible to build other
1375 abstractions on top of it. One such example is the ``nine patch''. A
1376 nine patch is a sprite that can be rendered at various sizes without
1377 becoming distorted. This is achieved by dividing up the sprite into
1378 nine regions:
1380 @itemize
1381 @item
1382 the center, which can be scaled horizontally and vertically
1383 @item
1384 the four corners, which can never be scaled
1385 @item
1386 the left and right sides, which can be scaled vertically
1387 @item
1388 the top and bottom sides, which can be scaled horizontally
1389 @end itemize
1391 The one caveat is that the bitmap regions must be designed in such a
1392 way so that they are not distorted when stretched along the affected
1393 axes. For example, that means that the top and bottom sides could
1394 have varying colored pixels vertically, but not horizontally.
1396 The most common application of this technique is for graphical user
1397 interface widgets like buttons and dialog boxes. By using a nine
1398 patch, they can be rendered at any size without unappealing scaling
1399 artifacts.
1401 @deffn {Procedure} draw-nine-patch @var{texture} @var{rect} @
1402 [#:margin 0] [#:top-margin margin] [#:bottom-margin margin] @
1403 [#:left-margin margin] [#:right-margin margin] @
1404 [#:origin] [#:scale] [#:rotation] [#:blend-mode alpha] @
1405 [#:shader]
1407 Draw a nine patch sprite. A nine patch sprite renders @var{texture}
1408 as a @var{width} x @var{height} rectangle whose stretchable areas are
1409 defined by the given margin measurements @var{top-margin},
1410 @var{bottom-margin}, @var{left-margin}, and @var{right-margin}. The
1411 @var{margin} argument may be used to configure all four margins at
1412 once.
1414 Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
1415 the other arguments.
1416 @end deffn
1418 @node Tile Maps
1419 @subsection Tile Maps
1421 A tile map is a scene created by composing lots of small sprites,
1422 called ``tiles'', into a larger image. One program for editing such
1423 maps is called @url{,Tiled}. Chickadee has native
1424 support for loading and rendering Tiled maps in the @code{(chickadee
1425 render tiled)} module.
1427 @deffn {Procedure} load-tile-map @var{file-name}
1428 Load the Tiled formatted map in @var{file-name} and return a new tile
1429 map object.
1430 @end deffn
1432 @deffn {Procedure} draw-tile-map @var{tile-map} [#:layers] [#:region] @
1433 [#:origin] [#:position] [#:scale] [#:rotation]
1435 Draw the layers of @var{tile-map}. By default, all layers are drawn.
1436 To draw a subset of the available layers, pass a list of layer ids
1437 using the @var{layers} keyword argument.
1439 Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
1440 the other arguments.
1441 @end deffn
1443 @node Lines and Shapes
1444 @subsection Lines and Shapes
1446 Sprites are fun, but sometimes simple, untextured lines and polygons
1447 are desired. That's where the @code{(chickadee render shapes)} module
1448 comes in!
1450 @deffn {Procedure} draw-line @var{start} @var{end} @
1451 [#:thickness 0.5] [#:feather 1.0] [#:cap round] [#:color] @
1452 [#:shader]
1454 Draw a line segment from @var{start} to @var{end}. The line will be
1455 @var{thickness} pixels thick with an antialiased border @var{feather}
1456 pixels wide. The line will be colored @var{color}. @var{cap}
1457 specifies the type of end cap that should be used to terminate the
1458 lines, either @code{none}, @code{butt}, @code{square}, @code{round},
1459 @code{triangle-in}, or @code{triangle-out}. Advanced users may use
1460 the @var{shader} argument to override the built-in line segment
1461 shader.
1462 @end deffn
1464 @deffn {Procedure} draw-bezier-curve @var{bezier} [#:segments 32] @
1465 [#:control-points?] [#:tangents?] @
1466 [#:control-point-size 8] @
1467 [#:control-point-color yellow] @
1468 [#:tangent-color yellow] @
1469 [#:thickness 0.5] [#:feather 1.0] @
1470 [#:matrix]
1472 Draw the curve defined by @var{bezier} using a resolution of N
1473 @var{segments}. When @var{control-points?} is @code{#t}, the control
1474 points are rendered as squares of size @var{control-point-size} pixels
1475 and a color of @var{control-point-color}. When @var{tangents?} is
1476 @code{#t}, the tangent lines from terminal point to control point are
1477 rendered using the color @var{tangent-color}.
1479 All line segments rendered use @code{draw-line}, and thus the
1480 arguments @var{thickness} and @var{feather} have the same effect as in
1481 that procedure.
1483 A custom @var{matrix} may be passed for applications that require more
1484 control over the final output.
1485 @end deffn
1487 @deffn {Procedure} draw-bezier-path @var{path} [#:segments 32] @
1488 [#:control-points?] [#:tangents?] @
1489 [#:control-point-size 8] @
1490 [#:control-point-color yellow] @
1491 [#:tangent-color yellow] @
1492 [#:thickness 0.5] [#:feather 1.0] @
1493 [#:matrix]
1495 Render @var{path}, a list of bezier curves. See the documentation for
1496 @code{draw-bezier-curve} for an explanation of all the keyword
1497 arguments.
1498 @end deffn
1500 @node Fonts
1501 @subsection Fonts
1503 Unlike the traditional TrueType font format that many are accustomed
1504 to, Chickadee loads and renders bitmap fonts in the
1505 @url{,
1506 Angel Code format}. But why use this seemingly obscure format? It's
1507 easy to find TTFs but not easy to find FNTs (the canonical file
1508 extension used for Angel Code fonts) and bitmap fonts don't scale
1509 well. The reason is efficiency.
1511 If all of the glyphs of a font are pre-rendered and packed into an
1512 image file then it becomes possible to use a texture atlas
1513 (@pxref{Textures}) and a sprite batch (@pxref{Sprites}) when
1514 rendering, which is a more efficient way to render fonts than using,
1515 say, @url{, SDL_ttf} or other
1516 solutions that involve using the FreeType library directly.
1518 Now what about scaling? In libraries that use TTF fonts, one must
1519 choose the size that the glyphs will be rasterized at up front. To
1520 use @code{n} sizes of the same font, one must load @code{n} variants
1521 of that font. If the size of the text is dynamic, some kind of
1522 texture scaling algorithm must be used and the text will inevitably
1523 look blurry. At first glance, using bitmap fonts seem to have an even
1524 worse issue. Instead of just loading the same font @code{n} times at
1525 different sizes, one would need to generate @code{n} image files for
1526 each font size needed. This is where the ``signed distance field''
1527 rendering technique comes in. Introduced by
1528 @url{,
1529 Valve} in 2007, signed distance field fonts can be efficiently stored
1530 in a bitmap and be rendered at arbitrary scale factors with good
1531 results.
1533 While Chickadee does not yet offer a tool for converting TTF fonts
1534 into FNT fonts, tools such as
1535 @url{, Hiero} may be used
1536 in the meantime.
1538 The following procedures can be found in the @code{(chickadee render
1539 font)} module.
1541 @deffn {Procedure} load-font @var{file}
1542 Load the Angel Code formatted XML document in @var{file} and return a
1543 new font object.
1544 @end deffn
1546 @deffn {Procedure} font? @var{obj}
1547 Return @code{#t} if @var{obj} is a font object.
1548 @end deffn
1550 @deffn {Procedure} font-face @var{font}
1551 Return the name of @var{font}.
1552 @end deffn
1554 @deffn {Procedure} font-line-height @var{font}
1555 Return the line height of @var{font}.
1556 @end deffn
1558 @deffn {Procedure} font-line-height @var{font}
1559 Return the line height of @var{font}.
1560 @end deffn
1562 @deffn {Procedure} font-bold? @var{font}
1563 Return @code{#t} if @var{font} is a bold font.
1564 @end deffn
1566 @deffn {Procedure} font-italic? @var{font}
1567 Return @code{#t} if @var{font} is an italicized font.
1568 @end deffn
1570 @deffn {Procedure} draw-text @var{font} @var{text} @var{position}
1571 [#:origin] [#:scale] [#:rotation] [#:blend-mode]
1572 [#:start 0] [#:end @code{(string-length text)}]
1574 Draw the string @var{text} with the first character starting at
1575 @var{position} using @var{font}.
1577 @example
1578 (draw-text font "Hello, world!" (vec2 128.0 128.0))
1579 @end example
1581 To render a substring of @var{text}, use the @var{start} and @var{end}
1582 arguments.
1584 Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
1585 the other arguments.
1586 @end deffn
1588 @node Particles
1589 @subsection Particles
1591 Effects like smoke, fire, sparks, etc. are often achieved by animating
1592 lots of little, short-lived sprites known as ``particles''. In fact,
1593 all of these effects, and more, can be accomplished by turning a few
1594 configuration knobs in a ``particle system''. A particle system takes
1595 care of managing the many miniscule moving morsels so the developer
1596 can quickly produce an effect and move on with their life. The
1597 @code{(chickadee render particles)} module provides an API for
1598 manipulating particle systems.
1600 Below is an example of a very simple particle system that utilizes
1601 nearly all of the default configuration settings:
1603 @example
1604 (use-modules (chickadee render particles))
1605 (define texture (load-image "particle.png"))
1606 (define particles (make-particles 2000 #:texture texture))
1607 @end example
1609 In order to put particles into a particle system, a particle
1610 ``emitter'' is needed. Emitters know where to spawn new particles,
1611 how many of them to spawn, and for how long they should do it.
1613 Below is an example of an emitter that spawns 16 particles per frame
1614 at the coordinates @code{(320, 240)}:
1616 @example
1617 (use-modules (chickadee math vector))
1618 (define emitter (make-particle-emitter (vec2 320.0 240.0) 16))
1619 (add-particle-emitter particles emitter)
1620 @end example
1622 To see all of the tweakable knobs and switches, read on!
1624 @deffn {Procedure} make-particles @var{capacity} [#:blend-mode @code{alpha}] @
1625 [#:color white] [#:end-color transparent] [#:texture] @
1626 [#:animation-rows 1] [#:animation-columns 1] [#:width] [#:height] @
1627 [#:speed-range (vec2 0.1 1.0)] [#:acceleration-range (vec2 0.0 0.1)] @
1628 [#:direction-range (vec2 0 (* 2 pi))] [#:lifetime 30] [#:sort]
1630 Return a new particle system that may contain up to @var{capacity}
1631 particles. Achieving the desired particle effect involves tweaking
1632 the following keyword arguments as needed:
1634 - @var{blend-mode}: Pixel blending mode. @code{alpha} by default.
1635 (@pxref{Blending} for more about blend modes).
1637 - @var{start-color}: The tint color of the particle at the beginning of its
1638 life. White by default.
1640 - @var{end-color}: The tint color of the particle at the end of of its
1641 life. Completely transparent by default for a fade-out effect. The
1642 color in the middle of a particle's life will be an interpolation of
1643 @var{start-color} and @var{end-color}.
1645 - @var{texture}: The texture applied to the particles. The texture
1646 may be subdivided into many animation frames.
1648 - @var{animation-rows}: How many animation frame rows there are in the
1649 texture. Default is 1.
1651 - @var{animation-columns}: How many animation frame columns there are
1652 in the texture. Default is 1.
1654 - @var{width}: The width of each particle. By default, the width of
1655 an animation frame (in pixels) is used.
1657 - @var{height}: The height of each particle. By default, the height
1658 of an animation frame (in pixels) is used.
1660 - @var{speed-range}: A 2D vector containing the min and max particle
1661 speed. Each particle will have a speed chosen at random from this
1662 range. By default, speed ranges from 0.1 to 1.0.
1664 - @var{acceleration-range}: A 2D vector containing the min and max
1665 particle acceleration. Each particle will have an acceleration chosen
1666 at random from this range. By default, acceleration ranges from 0.0
1667 to 0.1.
1669 - @var{direction-range}: A 2D vector containing the min and max
1670 particle direction as an angle in radians. Each particle will have a
1671 direction chosen at random from this range. By default, the range
1672 covers all possible angles.
1674 - @var{lifetime}: How long each particle lives, measured in
1675 updates. 30 by default.
1677 - @var{sort}: @code{youngest} if youngest particle should be drawn
1678 last or @code{oldest} for the reverse. By default, no sorting is
1679 applied at all.
1680 @end deffn
1682 @deffn {Procedure} particles? @var{obj}
1683 Return @code{#t} if @var{obj} is a particle system.
1684 @end deffn
1686 @deffn {Procedure} update-particles @var{particles}
1687 Advance the simulation of @var{particles}.
1688 @end deffn
1690 @deffn {Procedure} draw-particles @var{particles}
1691 Render @var{particles}.
1692 @end deffn
1694 @deffn {Procedure} draw-particles* @var{particles} @var{matrix}
1695 Render @var{particles} with @var{matrix} applied.
1696 @end deffn
1698 @deffn {Procedure} make-particle-emitter @var{spawn-area} @
1699 @var{rate} [@var{duration}]
1701 Return a new particle emitter that spawns @var{rate} particles per
1702 frame within @var{spawn-area} (a rectangle or 2D vector) for
1703 @var{duration} frames. If @var{duration} is not specified, the
1704 emitter will spawn particles indefinitely.
1705 @end deffn
1707 @deffn {Procedure} particle-emitter? @var{obj}
1708 Return @code{#t} if @var{obj} is a particle emitter.
1709 @end deffn
1711 @deffn {Procedure} particle-emitter-spawn-area @var{emitter}
1712 Return the spawn area for @var{emitter}.
1713 @end deffn
1715 @deffn {Procedure} particle-emitter-rate @var{emitter}
1716 Return the number of particles that @var{emitter} will spawn per
1717 frame.
1718 @end deffn
1720 @deffn {Procedure} particle-emitter-life @var{emitter}
1721 Return the number of frames remaining in @var{emitter}'s lifespan.
1722 @end deffn
1724 @deffn {Procedure} particle-emitter-done? @var{emitter}
1725 Return @code{#t} if @var{emitter} has finished spawning particlces.
1726 @end deffn
1728 @deffn {Procedure} add-particle-emitter @var{particles} @var{emitter}
1729 Add @var{emitter} to @var{particles}.
1730 @end deffn
1732 @deffn {Procedure} remove-particle-emitter @var{particles} @var{emitter}
1733 Remove @var{emitter} to @var{particles}
1734 @end deffn
1736 @node Blending
1737 @subsection Blending
1739 Rendering a scene often involves drawing layers of objects that
1740 overlap each other. Blending determines how two overlapping pixels
1741 are combined in the final image that is rendered to the screen.
1742 Chickadee provides the following blend modes:
1744 @itemize
1746 @item @code{replace}
1747 Use the latest color, ignoring all others.
1749 @item @code{alpha}
1750 Blend pixels according to the values of their alpha channels. This is
1751 the most commonly used blend mode and thus is Chickadee's default
1752 mode.
1754 @item @code{add}
1755 Add all pixel color values together. The more colors blended
1756 together, the more white the final color becomes.
1758 @item @code{subtract}
1759 Subtract all pixel color values. The more colors blended together,
1760 the more black the final color becomes.
1762 @item @code{multiply}
1764 @item @code{darken}
1766 @item @code{lighten}
1768 @item @code{screen}
1770 @end itemize
1772 @node Framebuffers
1773 @subsection Framebuffers
1775 A framebuffer is a chunk of memory that the GPU can render things
1776 onto. By default, the framebuffer that is used for rendering is the
1777 one belonging to the game window, but custom framebuffers can be used
1778 as well. A common use-case for custom framebuffers is applying
1779 post-processing effects: The entire scene is rendered to a
1780 framebuffer, and then the contents of that framebuffer are applied to
1781 a post-processing shader and rendered to the game window. The
1782 post-processing shader could do any number of things: scaling,
1783 antialiasing, motion blur, etc.
1785 @deffn {Procedure} make-framebuffer @var{width} @var{height} [#:min-filter 'linear] [#:mag-filter 'linear] [#:wrap-s 'repeat] [#:wrap-t 'repeat]
1787 Create a new framebuffer that is @var{width} pixels wide and @var{height} pixels high.
1789 @var{min-filter} and @var{mag-filter} determine the scaling algorithm
1790 applied to the framebuffer when rendering. By default, linear scaling
1791 is used in both cases. To perform no smoothing at all, use
1792 @code{nearest} for simple nearest neighbor scaling. This is typically
1793 the best choice for pixel art games.
1794 @end deffn
1796 @deffn {Procedure} framebuffer? @var{obj}
1797 Return @code{#t} if @var{obj} is a framebuffer.
1798 @end deffn
1800 @deffn {Procedure} framebuffer-texture @var{fb}
1801 Return the texture backing the framebuffer @var{fb}.
1802 @end deffn
1804 @deffn {Procedure} framebuffer-viewport @var{fb}
1805 Return the default viewport (@pxref{Viewports}) used by the
1806 framebuffer @var{fb}.
1807 @end deffn
1809 @deffn {Procedure} null-framebuffer
1810 The default framebuffer.
1811 @end deffn
1813 @node Viewports
1814 @subsection Viewports
1816 A viewport represents a subset of the screen (or framebuffer). When
1817 rendering a frame, the resulting image will only appear within that
1818 viewport. These aren't often needed, and Chickadee's default viewport
1819 occupies the entire screen, but there are certain situations where
1820 they are useful. For example, a split-screen multiplayer game may
1821 render to two different viewports, each occupying a different half of
1822 the screen. For information about how to set the current viewport,
1823 see @code{with-viewport} in @ref{Rendering Engine}.
1825 The @code{(chickadee render viewport)} module provides the following
1826 API:
1828 @deffn {Procedure} make-viewport @var{x} @var{y} @var{width} @var{height} @
1829 [#:clear-color] [#:clear-flags]
1831 Create a viewport that covers an area of the window starting from
1832 coordinates (@var{x}, @var{y}) and spanning @var{width} @code{x}
1833 @var{height} pixels. Fill the viewport with @var{clear-color} when
1834 clearing the screen. Clear the buffers denoted by the list of symbols
1835 in @var{clear-flags}.
1837 Possible values for @var{clear-flags} are @var{color-buffer},
1838 @var{depth-buffer}, @var{accum-buffer}, and @var{stencil-buffer}.
1839 @end deffn
1841 @deffn {Procedure} viewport? @var{obj}
1842 Return @code{#t} if @var{obj} is a viewport.
1843 @end deffn
1845 @deffn {Procedure} viewport-x @var{viewport}
1846 Return the left edge of @var{viewport}.
1847 @end deffn
1849 @deffn {Procedure} viewport-y @var{viewport}
1850 Return the bottom edge of @var{viewport}.
1851 @end deffn
1853 @deffn {Procedure} viewport-width @var{viewport}
1854 Return the width of @var{viewport}.
1855 @end deffn
1857 @deffn {Procedure} viewport-height @var{viewport}
1858 Return the height of @var{viewport}.
1859 @end deffn
1861 @deffn {Procedure} viewport-clear-color @var{viewport}
1862 Return the clear color for @var{viewport}.
1863 @end deffn
1865 @deffn {Procedure} viewport-clear-flags @var{viewport}
1866 Return the list of clear flags for @var{viewport}.
1867 @end deffn
1869 @node Rendering Engine
1870 @subsection Rendering Engine
1872 Chickadee defines rendering using a metaphor familiar to Scheme
1873 programmers: procedure application. A shader (@pxref{Shaders}) is
1874 like a procedure for the GPU to apply. Shaders are passed arguments:
1875 A vertex array containing the geometry to render (@pxref{GPU Buffers})
1876 and zero or more keyword arguments that the shader understands.
1877 Similar to how Scheme has @code{apply} for calling procedures,
1878 Chickadee provides @code{gpu-apply} for calling shaders.
1880 Additionally, there is some dynamic state that effects how
1881 @code{gpu-apply} will behave. Things like the current viewport,
1882 framebuffer, and blend mode are stored as dynamic state because it
1883 would be tedious to have to have to specify them each time
1884 @code{gpu-apply} is called.
1886 The following procedures and syntax can be found in the
1887 @code{(chickadee render)} module.
1889 @deffn {Syntax} gpu-apply @var{shader} @var{vertex-array} @
1890 [#:uniform-key @var{uniform-value} ...]
1891 @deffnx {Syntax} gpu-apply* @var{shader} @var{vertex-array} @
1892 @var{count} [#:uniform-key @var{uniform-value} ...]
1894 Render @var{vertex-array} using @var{shader} with the uniform values
1895 specified in the following keyword arguments.
1897 While @code{gpu-apply} will draw every vertex in @var{vertex-array},
1898 @code{gpu-apply*} will only draw @var{count} vertices.
1899 @end deffn
1901 @deffn {Syntax} gpu-apply/instanced @var{shader} @var{vertex-array} @
1902 @var{n} [#:uniform-key @var{uniform-value} ...]
1903 @deffnx {Syntax} gpu-apply/instanced @var{shader} @var{vertex-array} @
1904 @var{count} @var{n} [#:uniform-key @var{uniform-value} ...]
1906 Render @var{vertex-array} @var{n} times using @var{shader} with the
1907 uniform values specified in the following keyword arguments.
1909 Instanced rendering is very beneficial for rendering the same object
1910 many times with only small differences for each one. For example, the
1911 particle effects described in @ref{Particles} use instanced rendering.
1913 While @code{gpu-apply/instanced} will draw every vertex in
1914 @var{vertex-array}, @code{gpu-apply*} will only draw @var{count}
1915 vertices.
1916 @end deffn
1918 @deffn {Procedure} current-viewport
1919 Return the currently bound viewport (@pxref{Viewports}).
1920 @end deffn
1922 @deffn {Procedure} current-framebuffer
1923 Return the currently bound framebuffer (@pxref{Framebuffers}).
1924 @end deffn
1926 @deffn {Procedure} current-blend-mode
1927 Return the currently bound blend mode (@pxref{Blending}).
1928 @end deffn
1930 @deffn {Procedure} current-depth-test
1931 Return @code{#t} if depth testing is currently enabled (@pxref{Blending}).
1932 @end deffn
1934 @deffn {Procedure} current-texture
1935 Return the currently bound texture (@pxref{Textures}).
1936 @end deffn
1938 @deffn {Procedure} current-projection
1939 Return the currently bound projection matrix (@pxref{Matrices}).
1940 @end deffn
1942 @deffn {Syntax} with-viewport @var{viewport} @var{body} ...
1943 Evaluate @var{body} with the current viewport bound to @var{viewport} (@pxref{Viewports}).
1944 @end deffn
1946 @deffn {Syntax} with-framebuffer @var{framebuffer} @var{body} ...
1947 Evaluate @var{body} with the current framebuffer bound to
1948 @var{framebuffer} (@pxref{Framebuffers}).
1949 @end deffn
1951 @deffn {Syntax} with-blend-mode @var{blend-mode} @var{body} ...
1952 Evaluate @var{body} with the current blend mode bound to
1953 @var{blend-mode} (@pxref{Blending}).
1954 @end deffn
1956 @deffn {Syntax} with-depth-test @var{depth-test?} @var{body} ...
1957 Evaluate @var{body} with the depth-test disabled if @var{depth-test?}
1958 is @code{#f}, or enabled otherwise (@pxref{Blending}).
1959 @end deffn
1961 @deffn {Syntax} with-texture @var{texture} @var{body} ...
1962 Evaluate @var{body} with the current texture bound to @var{texture}
1963 (@pxref{Textures}).
1964 @end deffn
1966 @deffn {Syntax} with-projection @var{projection} @var{body} ...
1967 Evaluate @var{body} with the current projection matrix bound to
1968 @var{projection} (@pxref{Matrices}).
1969 @end deffn
1971 @node GPU Buffers
1972 @subsection GPU Buffers
1974 Alright, let's brush aside all of those pretty high level abstractions
1975 and discuss what is going on under the hood. The GPU exists as a
1976 discrete piece of hardware separate from the CPU. In order to make it
1977 draw things, we must ship lots of data out of our memory space and
1978 into the GPU. The @code{(chickadee render buffer}) module provides an
1979 API for manipulating GPU buffers.
1981 In OpenGL terminology, a chunk of data allocated on the GPU is a
1982 ``vertex buffer object'' or VBO. For example, here is a bytevector
1983 that could be transformed into a GPU buffer that packs together vertex
1984 position and texture coordinates:
1986 @example
1987 (use-modules (chickadee render buffer) (srfi srfi-4))
1988 (define data
1989 (f32vector -8.0 -8.0 ; 2D vertex
1990 0.0 0.0 ; 2D texture coordinate
1991 8.0 -8.0 ; 2D vertex
1992 1.0 0.0 ; 2D texture coordinate
1993 8.0 8.0 ; 2D vertex
1994 1.0 1.0 ; 2D texture coordinate
1995 -8.0 8.0 ; 2d vertex
1996 0.0 1.0)) ; 2D texture coordinate
1997 @end example
1999 This data represents a textured 16x16 square centered on the
2000 origin. To send this data to the GPU, the @code{make-buffer} procedure
2001 is needed:
2003 @example
2004 (define buffer (make-buffer data #:stride 16)
2005 @end example
2007 The @code{#:stride} keyword argument indicates how many bytes make up
2008 each element of the buffer. In this case, there are 4 floats per
2009 element: 2 for the vertex, and 2 for the texture coordinate. A 32-bit
2010 float is 4 bytes in length, so the buffer's stride is 16.
2012 Within a VBO, one or more ``attributes'', as OpenGL calls them, may be
2013 present. Attributes are subregions within the buffer that have a
2014 particular data type. In this case, there are two attributes packed
2015 into the buffer. To provided a typed view into a buffer, the
2016 @code{make-typed-buffer} is needed:
2018 @example
2019 (define vertices
2020 (make-typed-buffer #:buffer buffer
2021 #:type 'vec2
2022 #:component-type 'float
2023 #:length 4))
2024 (define texcoords
2025 (make-typed-buffer #:buffer buffer
2026 #:type 'vec2
2027 #:component-type 'float
2028 #:length 4
2029 #:offset 8))
2030 @end example
2032 To render a square, the GPU needs to draw two triangles, which means
2033 we need 6 vertices in total. However, the above buffer only contains
2034 data for 4 vertices. This is becase there are only 4 unique vertices
2035 for a square, but 2 of them must be repeated for each triangle. To
2036 work with deduplicated vertex data, an ``index buffer'' must be
2037 created.
2039 @example
2040 (define index-buffer
2041 (make-buffer (u32vector 0 3 2 0 2 1)
2042 #:target 'index)
2043 (define indices
2044 (make-typed-buffer #:type 'scalar
2045 #:component-type 'unsigned-int
2046 #:buffer index-buffer))
2047 @end example
2049 Note the use of the @code{#:target} keyword argument. It is required
2050 because the GPU treats index data in a special way and must be told
2051 which data is index data.
2053 Now that the typed buffers representing each attribute have been
2054 created, all that's left is to bind them all together in a ``vertex
2055 array object'', or VAO. Vertex arrays associate each typed buffer
2056 with an attribute index on the GPU. The indices that are chosen must
2057 correspond with the indices that the shader (@pxref{Shaders}) expects
2058 for each attribute.
2060 @example
2061 (define vertex-array
2062 (make-vertex-array #:indices indices
2063 #:attributes `((0 . ,vertices)
2064 (1 . ,texcoords))))
2065 @end example
2067 With the vertex array created, the GPU is now fully aware of how to
2068 interpret the data that it has been given in the original buffer.
2069 Actually rendering this square is left as an exercise to the reader.
2070 See the @ref{Shaders} section and the @code{gpu-apply} procedure in
2071 @ref{Rendering Engine} the remaining pieces of a successful draw call.
2072 Additionally, consider reading the source code for sprites, shapes, or
2073 particles to see GPU buffers in action.
2075 Without further ado, the API reference:
2077 @deffn {Procedure} make-buffer @var{data} [#:name "anonymous"] @
2078 [#:length] [#:offset 0] [#:stride 0] [#:target @code{vertex}] @
2079 [#:usage @code{static}]
2081 Upload @var{data}, a bytevector, to the GPU. By default, the entire
2082 bytevector is uploaded. A subset of the data may be uploaded by
2083 specifying the @var{offset}, the index of the first byte to be
2084 uploaded, and @var{length}, the number of bytes to upload.
2086 If @var{data} is @code{#f}, allocate @var{length} bytes of fresh GPU
2087 memory instead.
2089 @var{target} and @var{usage} are hints that tell the GPU how the
2090 buffer is intended to be used.
2092 @var{target} may be:
2094 @itemize
2095 @item @code{vertex}
2096 Vertex attribute data.
2098 @item @code{index}
2099 Index buffer data.
2101 @end itemize
2103 @var{usage} may be:
2105 @itemize
2106 @item @code{static}
2107 The buffer data will not be modified after creation.
2109 @item @code{stream}
2110 The buffer data will be modified frequently.
2112 @end itemize
2114 @var{name} is simply an arbitrary string for debugging purposes that
2115 is never sent to the GPU.
2116 @end deffn
2118 @deffn {Procedure} buffer? @var{obj}
2119 Return @code{#t} if @var{obj} is a GPU buffer.
2120 @end deffn
2122 @deffn {Procedure} index-buffer? @var{buffer}
2123 Return @code{#t} if @var{buffer} is an index buffer.
2124 @end deffn
2126 @defvar null-buffer
2127 Represents the absence of a buffer.
2128 @end defvar
2130 @deffn {Procedure} buffer-name @var{buffer}
2131 Return the name of @var{buffer}.
2132 @end deffn
2134 @deffn {Procedure} buffer-length @var{buffer}
2135 Return the length of @var{buffer}.
2136 @end deffn
2138 @deffn {Procedure} buffer-stride @var{buffer}
2139 Return the amount of space, in bytes, between each element in
2140 @var{buffer}.
2141 @end deffn
2143 @deffn {Procedure} buffer-target @var{buffer}
2144 Return the the intended usage of @var{buffer}, either @code{vertex} or
2145 @code{index}.
2146 @end deffn
2148 @deffn {Procedure} buffer-usage @var{buffer}
2149 Return the intended usage of @var{buffer}, either @code{static} for
2150 buffer data that will not change once sent to the GPU, or
2151 @code{stream} for buffer data that will be frequently updated from the
2152 client-side.
2153 @end deffn
2155 @deffn {Procedure} buffer-data @var{buffer}
2156 Return a bytevector containing all the data within @var{buffer}. If
2157 @var{buffer} has not been mapped (see @code{with-mapped-buffer}) then
2158 this procedure will return @code{#f}.
2159 @end deffn
2161 @deffn {Syntax} with-mapped-buffer @var{buffer} @var{body} @dots{}
2162 Evaluate @var{body} in the context of @var{buffer} having its data
2163 synced from GPU memory to RAM. In this context, @code{buffer-data}
2164 will return a bytevector of all the data stored in @var{buffer}. When
2165 program execution exits this form, the data (including any
2166 modifications) is synced back to the GPU.
2168 This form is useful for streaming buffers that need to update their
2169 contents dynamically, such as a sprite batch.
2170 @end deffn
2172 @deffn {Procedure} make-typed-buffer #:buffer #:type @
2173 #:component-type #:length [#:offset 0] [#:divisor] @
2174 [#:name "anonymous"]
2176 Return a new typed buffer view for @var{buffer} starting at byte index
2177 @var{offset} of @var{length} elements, where each element is of
2178 @var{type} and composed of @var{component-type} values.
2180 Valid values for @var{type} are:
2182 @itemize
2183 @item @code{scalar}
2184 single number
2186 @item @code{vec2}
2187 2D vector
2189 @item @code{vec3}
2190 3D vector
2192 @item @code{vec4}
2193 4D vector
2195 @item @code{mat2}
2196 2x2 matrix
2198 @item @code{mat3}
2199 3x3 matrix
2201 @item @code{mat4}
2202 4x4 matrix
2203 @end itemize
2205 Valid values for @var{component-type} are:
2207 @itemize
2209 @item @code{byte}
2210 @item @code{unsigned-byte}
2211 @item @code{short}
2212 @item @code{unsigned-short}
2213 @item @code{int}
2214 @item @code{unsigned-int}
2215 @item @code{float}
2216 @item @code{double}
2218 @end itemize
2220 @var{divisor} is only needed for instanced rendering applications (see
2221 @code{gpu-apply/instanced} in @ref{Rendering Engine}) and represents
2222 how many instances each vertex element applies to. A divisor of 0
2223 means that a single element is used for every instance and is used for
2224 the data being instanced. A divisor of 1 means that each element is
2225 used for 1 instance. A divisor of 2 means that each element is used
2226 for 2 instances, and so on.
2227 @end deffn
2229 @deffn {Procedure} typed-buffer? @var{obj}
2230 Return @code{#t} if @var{obj} is a typed buffer.
2231 @end deffn
2233 @deffn {Procedure} typed-buffer->buffer @var{typed-buffer}
2234 Return the buffer that @var{typed-buffer} is using.
2235 @end deffn
2237 @deffn {Procedure} typed-buffer-name @var{typed-buffer}
2238 Return the name of @var{typed-buffer}.
2239 @end deffn
2241 @deffn {Procedure} typed-buffer-offset @var{typed-buffer}
2242 Return the byte offset of @var{typed-buffer}.
2243 @end deffn
2245 @deffn {Procedure} typed-buffer-type @var{typed-buffer}
2246 Return the data type of @var{typed-buffer}.
2247 @end deffn
2249 @deffn {Procedure} typed-buffer-component-type @var{typed-buffer}
2250 Return the component data type of @var{typed-buffer}
2251 @end deffn
2253 @deffn {Procedure} typed-buffer-divisor @var{typed-buffer}
2254 Return the instance divisor for @var{typed-buffer}.
2255 @end deffn
2257 @deffn {Syntax} with-mapped-typed-buffer @var{typed-buffer} @var{body} @dots{}
2259 Evaluate @var{body} in the context of @var{typed-buffer} having its
2260 data synced from GPU memory to RAM. See @code{with-mapped-buffer} for
2261 more information.
2262 @end deffn
2264 @deffn {Procedure} make-vertex-array #:indices #:attributes @
2265 [#:mode @code{triangles}]
2267 Return a new vertex array using the index data within the typed buffer
2268 @var{indices} and the vertex attribute data within @var{attributes}.
2270 @var{attributes} is an alist mapping shader attribute indices to typed
2271 buffers containing vertex data:
2273 @example
2274 `((1 . ,typed-buffer-a)
2275 (2 . ,typed-buffer-b)
2276 ...)
2277 @end example
2279 By default, the vertex array is interpreted as containing a series of
2280 triangles. If another primtive type is desired, the @var{mode}
2281 keyword argument may be overridden. The following values are
2282 supported:
2284 @itemize
2285 @item @code{points}
2286 @item @code{lines}
2287 @item @code{line-loop}
2288 @item @code{line-strip}
2289 @item @code{triangles}
2290 @item @code{triangle-strip}
2291 @item @code{triangle-fan}
2292 @end itemize
2294 @end deffn
2296 @defvar null-vertex-array
2297 Represents the absence of a vertex array.
2298 @end defvar
2300 @deffn {Procedure} vertex-array? @var{obj}
2301 Return @code{#t} if @var{obj} is a vertex array.
2302 @end deffn
2304 @deffn {Procedure} vertex-array-indices @var{vertex-array}
2305 Return the typed buffer containing index data for @var{vertex-array}.
2306 @end deffn
2308 @deffn {Procedure} vertex-array-attributes @var{vertex-array}
2309 Return the attribute index -> typed buffer mapping of vertex attribute
2310 data for @var{vertex-array}.
2311 @end deffn
2313 @deffn {Procedure} vertex-array-mode @var{vertex-array}
2314 Return the primitive rendering mode for @var{vertex-array}.
2315 @end deffn
2317 @node Shaders
2318 @subsection Shaders
2320 Shaders are programs that the GPU can evaluate that allow the
2321 programmer to completely customized the final output of a GPU draw
2322 call. The @code{(chickadee render shader)} module provides an API for
2323 building custom shaders.
2325 Shaders are written in the OpenGL Shading Language, or GLSL for short.
2326 Chickadee aspires to provide a domain specific language for writing
2327 shaders in Scheme, but we are not there yet.
2329 Shader programs consist of two components: A vertex shader and a
2330 fragment shader. A vertex shader receives vertex data (position
2331 coordinates, texture coordinates, normals, etc.) and transforms them
2332 as desired, whereas a fragment shader controls the color of each
2333 pixel.
2335 Sample vertex shader:
2337 @example
2338 @verbatim
2339 #version 130
2341 in vec2 position;
2342 in vec2 tex;
2343 out vec2 fragTex;
2344 uniform mat4 mvp;
2346 void main(void) {
2347 fragTex = tex;
2348 gl_Position = mvp * vec4(position.xy, 0.0, 1.0);
2349 }
2350 @end verbatim
2351 @end example
2353 Sample fragment shader:
2355 @example
2356 @verbatim
2357 #version 130
2359 in vec2 fragTex;
2360 uniform sampler2D colorTexture;
2362 void main (void) {
2363 gl_FragColor = texture2D(colorTexture, fragTex);
2364 }
2365 @end verbatim
2366 @end example
2368 This manual will not cover GLSL features and syntax as there is lots
2369 of information already available about this topic.
2371 One way to think about rendering with shaders, and the metaphor
2372 Chickadee uses, is to think about it as a function call: The shader is
2373 a function, and it is applied to some ``attributes'' (positional
2374 arguments), and some ``uniforms'' (keyword arguments).
2376 @example
2377 (define my-shader (load-shader "vert.glsl" "frag.glsl"))
2378 (define vertices (make-vertex-array ...))
2379 (gpu-apply my-shader vertices #:color red)
2380 @end example
2382 @xref{Rendering Engine} for more details about the @code{gpu-apply}
2383 procedure.
2385 Shaders are incredibly powerful tools, and there's more information
2386 about them than we could ever fit into this manual, so we highly
2387 recommend searching the web for more information and examples. What
2388 we can say, though, is how to use our API:
2390 @deffn {Procedure} strings->shader @var{vertex-source} @var{fragment-source}
2391 Compile @var{vertex-source}, the GLSL code for the vertex shader, and
2392 @var{fragment-source}, the GLSL code for the fragment shader, into a
2393 GPU shader program.
2394 @end deffn
2396 @deffn {Procedure} load-shader @var{vertex-source-file} @
2397 @var{fragment-source-file}
2399 Compile the GLSL source code within @var{vertex-source-file} and
2400 @var{fragment-source-file} into a GPU shader program.
2401 @end deffn
2403 @deffn {Procedure} make-shader @var{vertex-port} @var{fragment-port}
2404 Read GLSL source from @var{vertex-port} and @var{fragment-port} and
2405 compile them into a GPU shader program.
2406 @end deffn
2408 @deffn {Procedure} shader? @var{obj}
2409 Return @code{#t} if @var{obj} is a shader.
2410 @end deffn
2412 @defvar null-shader
2413 Represents the absence shader program.
2414 @end defvar
2416 @deffn {Procedure} shader-uniform @var{shader} @var{name}
2417 Return the metadata for the uniform @var{name} in @var{shader}.
2418 @end deffn
2420 @deffn {Procedure} shader-uniforms @var{shader}
2421 Return a hash table of uniforms for @var{shader}.
2422 @end deffn
2424 @deffn {Procedure} shader-attributes @var{shader}
2425 Return a hash table of attributes for @var{shader}.
2426 @end deffn
2428 @deffn {Procedure} uniform? @var{obj}
2429 Return @code{#t} if @var{obj} is a uniform.
2430 @end deffn
2432 @deffn {Procedure} uniform-name @var{uniform}
2433 Return the variable name of @var{uniform}.
2434 @end deffn
2436 @deffn {Procedure} uniform-type @var{uniform}
2437 Return the data type of @var{uniform}.
2438 @end deffn
2440 @deffn {Procedure} uniform-value @var{uniform}
2441 Return the current value of @var{uniform}.
2442 @end deffn
2444 @deffn {Procedure} uniform-default-value @var{uniform}
2445 Return the default value of @var{uniform}.
2446 @end deffn
2448 @deffn {Procedure} attribute? @var{obj}
2449 Return @code{#t} if @var{obj} is an attribute.
2450 @end deffn
2452 @deffn {Procedure} attribute-name @var{attribute}
2453 Return the variable name of @var{attribute}.
2454 @end deffn
2456 @deffn {Procedure} attribute-location @var{attribute}
2457 Return the binding location of @var{attribute}.
2458 @end deffn
2460 @deffn {Procedure} attribute-type @var{attribute}
2461 Return the data type of @var{attribute}.
2462 @end deffn
2464 @node Scripting
2465 @section Scripting
2467 Game logic is a web of asynchronous events that are carefully
2468 coordinated to bring the game world to life. In order to make an
2469 enemy follow and attack the player, or move an NPC back and forth in
2470 front of the item shop, or do both at the same time, a scripting
2471 system is a necessity. Chickadee comes with an asynchronous
2472 programming system in the @code{(chickadee scripting)} module.
2473 Lightweight, cooperative threads known as ``scripts'' allow the
2474 programmer to write asynchronous code as if it were synchronous, and
2475 allow many such ``threads'' to run concurrently.
2477 But before we dig deeper into scripts, let's discuss the simple act
2478 of scheduling tasks.
2480 @menu
2481 * Agendas:: Scheduling tasks.
2482 * Scripts:: Cooperative multitasking.
2483 * Tweening:: Animations.
2484 * Channels:: Publish data to listeners.
2485 @end menu
2487 @node Agendas
2488 @subsection Agendas
2490 To schedule a task to be performed later, an ``agenda'' is used.
2491 There is a default, global agenda that is ready to be used, or
2492 additional agendas may be created for different purposes. The
2493 following example prints the text ``hello'' when the agenda has
2494 advanced to time unit 10.
2496 @example
2497 (at 10 (display "hello\n"))
2498 @end example
2500 Most of the time it is more convenient to schedule tasks relative to
2501 the current time. This is where @code{after} comes in handy:
2503 @example
2504 (after 10 (display "hello\n"))
2505 @end example
2507 Time units in the agenda are in no way connected to real time. It's
2508 up to the programmer to decide what agenda time means. A simple and
2509 effective approach is to map each call of the update hook
2510 (@pxref{Kernel}) to 1 unit of agenda time, like so:
2512 @example
2513 (add-hook! update-hook (lambda (dt) (update-agenda 1)))
2514 @end example
2516 It is important to call @code{update-agenda} periodically, otherwise
2517 no tasks will ever be run!
2519 In addition to using the global agenda, it is useful to have multiple
2520 agendas for different purposes. For example, the game world can use a
2521 different agenda than the user interface, so that pausing the game is
2522 a simple matter of not updating the world's agenda while continuing to
2523 update the user interface's agenda. The current agenda is dynamically
2524 scoped and can be changed using the @code{with-agenda} special form:
2526 @example
2527 (define game-world-agenda (make-agenda))
2529 (with-agenda game-world-agenda
2530 (at 60 (spawn-goblin))
2531 (at 120 (spawn-goblin))
2532 (at 240 (spawn-goblin-king)))
2533 @end example
2535 @deffn {Procedure} make-agenda
2536 Return a new task scheduler.
2537 @end deffn
2539 @deffn {Procedure} agenda? @var{obj}
2540 Return @code{#t} if @var{obj} is an agenda.
2541 @end deffn
2543 @deffn {Procedure} current-agenda
2544 @deffnx {Procedure} current-agenda @var{agenda}
2545 When called with no arguments, return the current agenda. When called
2546 with one argument, set the current agenda to @var{agenda}.
2547 @end deffn
2549 @deffn {Syntax} with-agenda @var{agenda} @var{body} @dots{}
2550 Evaluate @var{body} with the current agenda set to @var{agenda}.
2551 @end deffn
2553 @deffn {Procedure} agenda-time
2554 Return the current agenda time.
2555 @end deffn
2557 @deffn {Procedure} update-agenda @var{dt}
2558 Advance the current agenda by @var{dt}.
2559 @end deffn
2561 @deffn {Procedure} schedule-at @var{time} @var{thunk}
2562 Schedule @var{thunk}, a procedure of zero arguments, to be run at
2563 @var{time}.
2564 @end deffn
2566 @deffn {Procedure} schedule-after @var{delay} @var{thunk}
2567 Schedule @var{thunk}, a procedure of zero arguments, to be run after
2568 @var{delay}.
2569 @end deffn
2571 @deffn {Procedure} schedule-every @var{interval} @var{thunk} [@var{n}]
2572 Schedule @var{thunk}, a procedure of zero arguments, to be run every
2573 @var{interval} amount of time. Repeat this @var{n} times, or
2574 indefinitely if not specified.
2575 @end deffn
2577 @deffn {Syntax} at @var{time} @var{body} @dots{}
2578 Schedule @var{body} to be evaluated at @var{time}.
2579 @end deffn
2581 @deffn {Syntax} after @var{delay} @var{body} @dots{}
2582 Schedule @var{body} to be evaluated after @var{delay}.
2583 @end deffn
2585 @deffn {Syntax} every @var{interval} @var{body} @dots{}
2586 @deffnx {Syntax} every (@var{interval} @var{n}) @var{body} @dots{}
2587 Schedule @var{body} to be evaluated every @var{interval} amount of
2588 time. Repeat this @var{n} times, or indefinitely if not specified.
2589 @end deffn
2591 @node Scripts
2592 @subsection Scripts
2594 Now that we can schedule tasks, let's take things to the next level.
2595 It sure would be great if we could make procedures that described a
2596 series of actions that happened over time, especially if we could do
2597 so without contorting our code into a nest of callback procedures.
2598 This is where scripts come in. With scripts we can write code in a
2599 linear way, in a manner that appears to be synchronous, but with the
2600 ability to suspend periodically in order to let other scripts have a
2601 turn and prevent blocking the game loop. Building on top of the
2602 scheduling that agendas provide, here is a script that models a child
2603 trying to get their mother's attention:
2605 @example
2606 (script
2607 (while #t
2608 (display "mom!")
2609 (newline)
2610 (sleep 60))) ; where 60 = 1 second of real time
2611 @end example
2613 This code runs in an endless loop, but the @code{sleep} procedure
2614 suspends the script and schedules it to be run later by the agenda.
2615 So, after each iteration of the loop, control is returned back to the
2616 game loop and the program is not stuck spinning in a loop that will
2617 never exit. Pretty neat, eh?
2619 Scripts can suspend to any capable handler, not just the agenda.
2620 The @code{yield} procedure will suspend the current script and pass
2621 its ``continuation'' to a handler procedure. This handler procedure
2622 could do anything. Perhaps the handler stashes the continuation
2623 somewhere where it will be resumed when the user presses a specific
2624 key on the keyboard, or maybe it will be resumed when the player picks
2625 up an item off of the dungeon floor; the sky is the limit.
2627 Sometimes it is necessary to abruptly terminate a script after it has
2628 been started. For example, when an enemy is defeated their AI routine
2629 needs to be shut down. When a script is spawned, a handle to that
2630 script is returned that can be used to cancel it when desired.
2632 @example
2633 (define script (script (while #t (display "hey\n") (sleep 60))))
2634 ;; sometime later
2635 (cancel-script script)
2636 @end example
2638 @deffn {Procedure} spawn-script @var{thunk}
2639 Apply @var{thunk} as a script and return a handle to it.
2640 @end deffn
2642 @deffn {Syntax} script @var{body} @dots{}
2643 Evaluate @var{body} as a script and return a handle to it.
2644 @end deffn
2646 @deffn {Procedure} script? @var{obj}
2647 Return @code{#t} if @var{obj} is a script handle.
2648 @end deffn
2650 @deffn {Procedure} script-cancelled? @var{obj}
2651 Return @code{#t} if @var{obj} has been cancelled.
2652 @end deffn
2654 @deffn {Procedure} script-running? @var{obj}
2655 Return @code{#t} if @var{obj} has not yet terminated or been
2656 cancelled.
2657 @end deffn
2659 @deffn {Procedure} script-complete? @var{obj}
2660 Return @code{#t} if @var{obj} has terminated.
2661 @end deffn
2663 @deffn {Procedure} cancel-script @var{co}
2664 Prevent further execution of the script @var{co}.
2665 @end deffn
2667 @deffn {Procedure} yield @var{handler}
2668 Suspend the current script and pass its continuation to the
2669 procedure @var{handler}.
2670 @end deffn
2672 @deffn {Procedure} sleep @var{duration}
2673 Wait @var{duration} before resuming the current script.
2674 @end deffn
2676 @deffn {Syntax} forever @var{body} @dots{}
2677 Evaluate @var{body} in an endless loop.
2678 @end deffn
2680 @node Tweening
2681 @subsection Tweening
2683 Tweening is the process of transitioning something from an initial
2684 state to a final state over a pre-determined period of time. In other
2685 words, tweening is a way to create animation. The @code{tween}
2686 procedure can be used within any script like so:
2688 @example
2689 (define x 0)
2690 (script
2691 ;; 0 to 100 in 60 ticks of the agenda.
2692 (tween 60 0 100 (lambda (y) (set! x y))))
2693 @end example
2695 @deffn {Procedure} tween @var{duration} @var{start} @var{end} @var{proc} [#:step 1 #:ease @code{smoothstep} #:interpolate @code{lerp}]
2696 Transition a value from @var{start} to @var{end} over @var{duration},
2697 sending each succesive value to @var{proc}. @var{step} controls the
2698 amount of time between each update of the animation.
2700 To control how the animation goes from the initial to final state, an
2701 ``easing'' procedure may be specified. By default, the
2702 @code{smoothstep} easing is used, which is a more pleasing default
2703 than a simplistic linear function. @xref{Easings} for a complete list
2704 of available easing procedures.
2706 The @var{interpolate} procedure computes the values in between
2707 @var{start} and @var{end}. By default, linear interpolation (``lerp''
2708 for short) is used.
2709 @end deffn
2711 @node Channels
2712 @subsection Channels
2714 Channels are a tool for communicating amongst different scripts. One
2715 script can write a value to the channel and another can read from it.
2716 Reading or writing to a channel suspends that script until there is
2717 someone on the other end of the line to complete the transaction.
2719 Here's a simplistic example:
2721 @example
2722 (define c (make-channel))
2724 (script
2725 (forever
2726 (let ((item (channel-get c)))
2727 (pk 'got item))))
2729 (script
2730 (channel-put c 'sword)
2731 (channel-put c 'shield)
2732 (channel-put c 'potion))
2733 @end example
2735 @deffn {Procedure} make-channel
2736 Return a new channel
2737 @end deffn
2739 @deffn {Procedure} channel? @var{obj}
2740 Return @code{#t} if @var{obj} is a channel.
2741 @end deffn
2743 @deffn {Procedure} channel-get @var{channel}
2744 Retrieve a value from @var{channel}. The current script suspends
2745 until a value is available.
2746 @end deffn
2748 @deffn {Procedure} channel-put @var{channel} @var{data}
2749 Send @var{data} to @var{channel}. The current script suspends until
2750 another script is available to retrieve the value.
2751 @end deffn
2753 A low-level API also exists for using channels outside of a script via
2754 callback procedures:
2756 @deffn {Procedure} channel-get! @var{channel} @var{proc}
2757 Asynchronously retrieve a value from @var{channel} and call @var{proc}
2758 with that value.
2759 @end deffn
2761 @deffn {Procedure} channel-put! @var{channel} @var{data} [@var{thunk}]
2762 Asynchronously send @var{data} to @var{channel} and call @var{thunk}
2763 after it has been received.
2764 @end deffn