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