77f6ae030c112fd2390eeda1c66d7f24837106b1
[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)} module, lies
12 an event loop. This loop, or ``kernel'', is responsible for ensuring
13 that the game is updated at the desired interval, rendering the
14 current state of the game world, and handling errors if they occur.
15 The kernel implements what is known as a ``fixed timestep'' game loop,
16 meaning that the game simulation will be advanced by a fixed interval
17 of time and will never vary from frame to frame, unlike some other
18 styles of game loops. The appropriately named @code{run-game} and
19 @code{abort-game} procedures are the entry and exit points to the
20 Chickadee game loop kernel.
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 sdl)} module:
83 @code{run-game/sdl}.
84
85 @deffn {Procedure} run-game/sdl [#:window-title "Chickadee!"] @
86 [#:window-width 640] [#:window-height 480] @
87 [#:window-fullscreen? @code{#f}] [#:update-hz 60] @
88 [#:load] [#:update] [#:draw] [#:quit] @
89 [#:key-press] [#:key-release] [#:text-input] @
90 [#:mouse-press] [#:mouse-release] [#:mouse-move] @
91 [#:controller-add] [#:controller-remove] [#:controller-press] @
92 [#:controller-release] [#:controller-move] [#:error]
93
94 Run the Chickadee game loop using the SDL engine.
95
96 A new graphical window will be opened with @var{window-width} x
97 @var{window-height} as its dimensions, @var{window-title} as its
98 title, and in fullscreen mode if @var{window-fullscreen?} is
99 @code{#t}.
100
101 @itemize
102 @item
103 @var{load}: Called with zero arguments when the game window has opened
104 but before the game loop has started. Can be used to perform
105 initialization that requires an open window and OpenGL context such as
106 loading textures.
107
108 @item
109 @var{update}: Called @var{update-hz} times per second with one
110 argument: The amount of time to advance the game simulation.
111
112 @item
113 @var{draw}: Called each time a frame should be rendered with a single
114 argument known as the @code{alpha} value. See the documentation for
115 @code{run-game} for an explanation of this value.
116
117 @item
118 @var{quit}: Called with zero arguments when the user tries to close
119 the game window. The default behavior is to exit the game.
120
121 @item
122 @var{key-press}: Called with four arguments when a key is pressed on
123 the keyboard:
124
125 @enumerate
126 @item
127 @var{key}: The symbolic name of the ``virtual'' key that was pressed.
128 For example: @code{backspace}. It's called a virtual key because the
129 operating system may map a physical keyboard key to another key
130 entirely, such as how the author likes to bind the ``caps lock'' key
131 to mean ``control''.
132
133 @item
134 @var{scancode}: The symbolic name of the physical key that was
135 pressed.
136
137 @item
138 @var{modifiers}: A list of the symbolic names of modifier keys that
139 were being held down when the key was pressed. Possible values
140 include @code{ctrl}, @code{alt}, and @code{shift}.
141
142 @item
143 @var{repeat?}: @code{#t} if this is a repeated press of the same key.
144
145 @end enumerate
146
147 @item
148 @var{key-release}: Called with three arguments when a key is released
149 on the keyboard:
150
151 @enumerate
152 @item
153 @var{key}: The symbolic name of the ``virtual'' key that was released.
154
155 @item
156 @var{scancode}: The symbolic name of the physical key that was
157 released.
158
159 @item
160 @var{modifiers}: A list of the symbolic names of modifier keys that
161 were being held down when the key was released.
162
163 @end enumerate
164
165 @item
166 @var{text-input}: Called with a single argument, a string of text,
167 when printable text is typed on the keyboard.
168
169 @item
170 @var{mouse-press}: Called with four arguments when a mouse button is
171 pressed:
172 @enumerate
173
174 @item
175 @var{button}: The symbolic name of the button that was pressed, such
176 as @code{left}, @code{middle}, or @code{right}.
177
178 @item
179 @var{clicks}: The number of times the button has been clicked in a row.
180
181 @item
182 @var{x}: The x coordinate of the mouse cursor.
183
184 @item
185 @var{y}: The y coordinate of the mouse cursor.
186
187 @end enumerate
188
189 @item
190 @var{mouse-release}: Called with three arguments when a mouse button
191 is released:
192
193 @enumerate
194
195 @item
196 @var{button}: The symbolic name of the button that was released.
197
198 @item
199 @var{x}: The x coordinate of the mouse cursor.
200
201 @item
202 @var{y}: The y coordinate of the mouse cursor.
203
204 @end enumerate
205
206 @item
207 @var{mouse-move}: Called with five arguments when the mouse is moved:
208
209 @enumerate
210
211 @item
212 @var{x}: The x coordinate of the mouse cursor.
213
214 @item
215 @var{y}: The y coordinate of the mouse cursor.
216
217 @item
218 @var{dx}: The amount the mouse has moved along the x axis since the
219 last mouse move event.
220
221 @item
222 @var{dy}: The amount the mouse has moved along the y axis since the
223 last mouse move event.
224
225 @item
226 @var{buttons}: A list of the buttons that were pressed down when the
227 mouse was moved.
228
229 @end enumerate
230
231 @item
232 @var{controller-add}: Called with a single argument, an SDL game
233 controller object, when a game controller is connected.
234
235 @item
236 @var{controller-remove}: Called with a single argument, an SDL game
237 controller object, when a game controller is disconnected.
238
239 @item
240 @var{controller-press}: Called with two arguments when a button on a
241 game controller is pressed:
242
243 @enumerate
244
245 @item
246 @var{controller}: The controller that triggered the event.
247
248 @item
249 @var{button}: The symbolic name of the button that was pressed.
250 Possible buttons are:
251
252 @itemize
253 @item
254 @code{a}
255 @item
256 @code{b}
257 @item
258 @code{x}
259 @item
260 @code{y}
261 @item
262 @code{back}
263 @item
264 @code{guide}
265 @item
266 @code{start}
267 @item
268 @code{left-stick}
269 @item
270 @code{right-stick}
271 @item
272 @code{left-shoulder}
273 @item
274 @code{right-shoulder}
275 @item
276 @code{dpad-up}
277 @item
278 @code{dpad-down}
279 @item
280 @code{dpad-left}
281 @item
282 @code{dpad-right}
283
284 @end itemize
285
286 @end enumerate
287
288 @item
289 @var{controller-release}: Called with two arguments when a button on a
290 game controller is released:
291
292 @enumerate
293
294 @item
295 @var{controller}: The controller that triggered the event.
296
297 @item
298 @var{button}: The symbolic name of the button that was released.
299
300 @end enumerate
301
302 @item
303 @var{controller-move}: Called with three arguments when an analog
304 stick or trigger on a game controller is moved:
305
306 @enumerate
307
308 @item
309 @var{controller}: The controller that triggered the event.
310
311 @item
312 @var{axis}: The symbolic name of the axis that was moved. Possible
313 values are:
314
315 @itemize
316 @item
317 @code{left-x}
318 @item
319 @code{left-y}
320 @item
321 @code{right-x}
322 @item
323 @code{right-y}
324 @item
325 @code{trigger-left}
326 @item
327 @code{trigger-right}
328 @end itemize
329
330 @end enumerate
331
332 @item
333 @var{error}: Called with three arguments when an error occurs:
334
335 @enumerate
336
337 @item
338 @var{stack}: The call stack at the point of error.
339
340 @item
341 @var{key}: The exception key.
342
343 @item
344 @var{args}: The arguments thrown with the exception.
345
346 @end enumerate
347
348 The default behavior is to re-throw the error.
349
350 @end itemize
351
352 @end deffn
353
354 @node Math
355 @section Math
356
357 Chickadee contains data types and procedures for performing the most
358 common computations in video game simulations such as linear algebra
359 with vectors and matrices and axis-aligned bounding box collision
360 detection.
361
362 @menu
363 * Basics:: Commonly used, miscellaneous things.
364 * Vectors:: Euclidean vectors.
365 * Rectangles:: Axis-aligned bounding boxes.
366 * Grid:: Spatial partitioning for bounding boxes.
367 * Matrices:: Transformation matrices.
368 * Quaternions:: Rotations about an arbitrary axis.
369 * Easings:: Easing functions for interesting animations.
370 * Bezier Curves:: Cubic Bezier curves and paths in 2D space.
371 * Path Finding:: Generic A* path finding.
372 @end menu
373
374 @node Basics
375 @subsection Basics
376
377 @defvar pi
378 An essential constant for all trigonometry. @code{@U{03C0}} is the ratio
379 of a circle's circumferences to its diameter. Since @code{@U{03C0}} is an
380 irrational number, the @var{pi} in Chickadee is a mere floating point
381 approximation that is ``good enough.''
382 @end defvar
383
384 @defvar pi/2
385 Half of @var{pi}.
386 @end defvar
387
388 @deffn {Procedure} cotan @var{z}
389 Return the cotangent of @var{z}.
390 @end deffn
391
392 @node Vectors
393 @subsection Vectors
394
395 Unlike Scheme's vector data type, which is a sequence of arbitrary
396 Scheme objects, Chickadee's @code{(chickadee math vector)} module
397 provides vectors in the linear algebra sense: Sequences of numbers
398 specialized for particular coordinate spaces. As of now, Chickadee
399 provides 2D and 3D vectors, with 4D vector support coming in a future
400 release.
401
402 Here's a quick example of adding two vectors:
403
404 @example
405 (define v (vec2+ (vec2 1 2) (vec2 3 4)))
406 @end example
407
408 Since vectors are used so frequently, the reader macro @code{#v} is
409 used to cut down on typing:
410
411 @example
412 (define v (vec2+ #v(1 2) #v(3 4)))
413 @end example
414
415 @subsubsection A Note About Performance
416
417 A lot of time has been spent making Chickadee's vector operations
418 perform relatively efficiently in critical code paths where excessive
419 garbage generation will cause major performance issues. The general
420 rule is that procedures ending with @code{!} perform an in-place
421 modification of one of the arguments in order to avoid allocating a
422 new vector. These procedures are also inlined by Guile's compiler in
423 order to take advantage of optimizations relating to floating point
424 math operations. The downside is that since these are not pure
425 functions, they do not compose well and create more verbose code.
426
427 @subsubsection 2D Vectors
428
429 @deffn {Procedure} vec2 @var{x} @var{y}
430 Return a new 2D vector with coordinates (@var{x}, @var{y}).
431 @end deffn
432
433 @deffn {Procedure} vec2/polar @var{r} @var{theta}
434 Return a new 2D vector containing the Cartesian representation of the
435 polar coordinate (@var{r}, @var{theta}). The angle @var{theta} is
436 measured in radians.
437 @end deffn
438
439 @deffn {Procedure} vec2? @var{obj}
440 Return @code{#t} if @var{obj} is a 2D vector.
441 @end deffn
442
443 @deffn {Procedure} vec2-x @var{v}
444 Return the X coordinate of the 2D vector @var{v}.
445 @end deffn
446
447 @deffn {Procedure} vec2-y @var{v}
448 Return the Y coordinate of the 2D vector @var{v}.
449 @end deffn
450
451 @deffn {Procedure} vec2-copy @var{v}
452 Return a fresh copy of the 2D vector @var{v}.
453 @end deffn
454
455 @deffn {Procedure} vec2-magnitude @var{v}
456 Return the magnitude of the 2D vector @var{v}.
457 @end deffn
458
459 @deffn {Procedure} vec2-dot-product @var{v1} @var{v2}
460 Return the dot product of the 2D vectors @var{v1} and @var{v2}.
461 @end deffn
462
463 @deffn {Procedure} vec2-normalize @var{v}
464 Return the normalized form of the 2D vector @var{v}.
465 @end deffn
466
467 @deffn {Procedure} vec2+ @var{v} @var{x}
468 Add @var{x}, either a 2D vector or a scalar (i.e. a real number), to
469 the 2D vector @var{v} and return a new vector containing the sum.
470 @end deffn
471
472 @deffn {Procedure} vec2- @var{v} @var{x}
473 Subtract @var{x}, either a 2D vector or a scalar, from the 2D vector
474 @var{v} and return a new vector containing the difference.
475 @end deffn
476
477 @deffn {Procedure} vec2* @var{v} @var{x}
478 Multiply the 2D vector @var{v} by @var{x}, a 2D vector or a scalar,
479 and return a new vector containing the product.
480 @end deffn
481
482 @deffn {Procedure} set-vec2-x! @var{v} @var{x}
483 Set the X coordinate of the 2D vector @var{v} to @var{x}.
484 @end deffn
485
486 @deffn {Procedure} set-vec2-y! @var{v} @var{y}
487 Set the Y coordinate of the 2D vector @var{v} to @var{y}.
488 @end deffn
489
490 @deffn {Procedure} set-vec2! @var{v} @var{x} @var{y}
491 Set the X and Y coordinates of the 2D vector @var{v} to @var{x} and
492 @var{y}, respectively.
493 @end deffn
494
495 @deffn {Procedure} vec2-copy! @var{source} @var{target}
496 Copy the 2D vector @var{source} into the 2D vector @var{target}.
497 @end deffn
498
499 @deffn {Procedure} vec2-add! @var{v} @var{x}
500 Perform an in-place modification of the 2D vector @var{v} by adding
501 @var{x}, a 2D vector or a scalar.
502 @end deffn
503
504 @deffn {Procedure} vec2-sub! @var{v} @var{x}
505 Perform an in-place modification of the 2D vector @var{v} by
506 subtracting @var{x}, a 2D vector or a scalar.
507 @end deffn
508
509 @deffn {Procedure} vec2-mult! @var{v} @var{x}
510 Perform an in-place modification of the 2D vector @var{v} by
511 multiplying it by @var{x}, a 2D vector or a scalar.
512 @end deffn
513
514 @subsubsection 3D Vectors
515
516 @deffn {Procedure} vec3 @var{x} @var{y}
517 Return a new 2D vector with coordinates (@var{x}, @var{y}).
518 @end deffn
519
520 @deffn {Procedure} vec3? @var{obj}
521 Return @code{#t} if @var{obj} is a 3D vector.
522 @end deffn
523
524 @deffn {Procedure} vec3-x @var{v}
525 Return the X coordinate of the 3D vector @var{v}.
526 @end deffn
527
528 @deffn {Procedure} vec3-y @var{v}
529 Return the Y coordinate of the 3D vector @var{v}.
530 @end deffn
531
532 @deffn {Procedure} vec3-z @var{v}
533 Return the Z coordinate of the 3D vector @var{v}.
534 @end deffn
535
536 @deffn {Procedure} vec3-copy @var{v}
537 Return a fresh copy of the 3D vector @var{v}.
538 @end deffn
539
540 @deffn {Procedure} vec3-magnitude @var{v}
541 Return the magnitude of the 3D vector @var{v}.
542 @end deffn
543
544 @deffn {Procedure} vec3-dot-product @var{v1} @var{v2}
545 Return the dot product of the 3D vectors @var{v1} and @var{v2}.
546 @end deffn
547
548 @deffn {Procedure} vec3-normalize @var{v}
549 Return the normalized form of the 3D vector @var{v}.
550 @end deffn
551
552 @deffn {Procedure} vec3+ @var{v} @var{x}
553 Add @var{x}, either a 3D vector or a scalar (i.e. a real number), to
554 the 3D vector @var{v} and return a new vector containing the sum.
555 @end deffn
556
557 @deffn {Procedure} vec3- @var{v} @var{x}
558 Subtract @var{x}, either a 3D vector or a scalar, from the 3D vector
559 @var{v} and return a new vector containing the difference.
560 @end deffn
561
562 @deffn {Procedure} vec3* @var{v} @var{x}
563 Multiply the 3D vector @var{v} by @var{x}, a 3D vector or a scalar,
564 and return a new vector containing the product.
565 @end deffn
566
567 @deffn {Procedure} set-vec3-x! @var{v} @var{x}
568 Set the X coordinate of the 3D vector @var{v} to @var{x}.
569 @end deffn
570
571 @deffn {Procedure} set-vec3-y! @var{v} @var{y}
572 Set the Y coordinate of the 3D vector @var{v} to @var{y}.
573 @end deffn
574
575 @deffn {Procedure} set-vec3-z! @var{v} @var{z}
576 Set the Z coordinate of the 3D vector @var{v} to @var{z}.
577 @end deffn
578
579 @deffn {Procedure} set-vec3! @var{v} @var{x} @var{y} @var{z}
580 Set the X, Y, and Z coordinates of the 3D vector @var{v} to @var{x},
581 @var{y}, and @var{z}, respectively.
582 @end deffn
583
584 @deffn {Procedure} vec3-copy! @var{source} @var{target}
585 Copy the 3D vector @var{source} into the 3D vector @var{target}.
586 @end deffn
587
588 @deffn {Procedure} vec3-add! @var{v} @var{x}
589 Perform an in-place modification of the 3D vector @var{v} by adding
590 @var{x}, a 3D vector or a scalar.
591 @end deffn
592
593 @deffn {Procedure} vec3-sub! @var{v} @var{x}
594 Perform an in-place modification of the 3D vector @var{v} by
595 subtracting @var{x}, a 3D vector or a scalar.
596 @end deffn
597
598 @deffn {Procedure} vec3-mult! @var{v} @var{x}
599 Perform an in-place modification of the 3D vector @var{v} by
600 multiplying it by @var{x}, a 3D vector or a scalar.
601 @end deffn
602
603 @node Rectangles
604 @subsection Rectangles
605
606 The @code{(chickadee math rect)} module provides an API for
607 manipulating axis-aligned bounding boxes (AABBs). AABBs are often
608 used for collision detection in games. Common use-cases are defining
609 ``hitboxes'' in platformers or using them for the ``broad phase'' of a
610 collision detection algorithm that uses a more complex (and thus
611 slower) method of determining the actual collisions.
612
613 Like some of the other math modules, there exists a collection of
614 functions that do in-place modification of rectangles for use in
615 performance critical code paths.
616
617 @deffn {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 @node Sprites
1327 @subsection Sprites
1328
1329 For those who are new to this game, a sprite is a 2D rectangular
1330 bitmap that is rendered to the screen. For 2D games, sprites are the
1331 most essential graphical abstraction. They are used for drawing maps,
1332 players, NPCs, items, particles, text, etc. In Chickadee, bitmaps are
1333 stored in textures (@pxref{Textures}) and can be used to draw sprites
1334 via the @code{draw-sprite} procedure.
1335
1336 @deffn {Procedure} draw-sprite @var{texture} @var{position} @
1337 [#:origin] [#:scale] [#:rotation] [#:blend-mode alpha] @
1338 [#:rect] [#:shader]
1339
1340 Draw @var{texture} at @var{position}.
1341
1342 Optionally, other transformations may be applied to the sprite.
1343 @var{rotation} specifies the angle to rotate the sprite, in radians.
1344 @var{scale} specifies the scaling factor as a 2D vector. All
1345 transformations are applied relative to @var{origin}, a 2D vector,
1346 which defaults to the lower-left corner.
1347
1348 Alpha blending is used by default but the blending method can be
1349 changed by specifying @var{blend-mode}.
1350
1351 The area drawn to is as big as the texture, by default. To draw to an
1352 arbitrary section of the screen, specify @var{rect}.
1353
1354 Finally, advanced users may specify @var{shader} to change the way the
1355 sprite is rendered entirely.
1356 @end deffn
1357
1358 It's not uncommon to need to draw hundreds or thousands of sprites
1359 each frame. However, GPUs (graphics processing units) are tricky
1360 beasts that prefer to be sent few, large chunks of data to render
1361 rather than many, small chunks. Using @code{draw-sprite} on its own
1362 will involve at least one GPU call @emph{per sprite}, which will
1363 quickly lead to poor performance. To deal with this, a technique
1364 known as ``sprite batching'' can be used. Instead of drawing each
1365 sprite immediately, the sprite batch will build up a large of buffer
1366 of sprites to draw and defer rendering until the last possible moment.
1367 Batching isn't a panacea, though. Batching only works if the sprites
1368 being drawn share as much in common as possible. Every time you draw
1369 a sprite with a different texture or blend mode, the batch will be
1370 sent off to the GPU. Therefore, batching is most useful if you
1371 minimize such changes. A good strategy for reducing texture changes
1372 is to stuff many bitmaps into a single image file and create a
1373 ``texture atlas'' (@pxref{Textures}) to access the sub-images within.
1374
1375 Taking advantage of sprite batching in Chickadee is easy, just wrap
1376 the code that is calling @code{draw-sprite} a lot in the
1377 @code{with-batched-sprites} form.
1378
1379 @deffn {Syntax} with-batched-sprites @var{body} @dots{}
1380 Use batched rendering for all @code{draw-sprite} calls within
1381 @var{body}.
1382 @end deffn
1383
1384 With a basic sprite abstraction in place, it's possible to build other
1385 abstractions on top of it. One such example is the ``nine patch''. A
1386 nine patch is a sprite that can be rendered at various sizes without
1387 becoming distorted. This is achieved by dividing up the sprite into
1388 nine regions:
1389
1390 @itemize
1391 @item
1392 the center, which can be scaled horizontally and vertically
1393 @item
1394 the four corners, which can never be scaled
1395 @item
1396 the left and right sides, which can be scaled vertically
1397 @item
1398 the top and bottom sides, which can be scaled horizontally
1399 @end itemize
1400
1401 The one caveat is that the bitmap regions must be designed in such a
1402 way so that they are not distorted when stretched along the affected
1403 axes. For example, that means that the top and bottom sides could
1404 have varying colored pixels vertically, but not horizontally.
1405
1406 The most common application of this technique is for graphical user
1407 interface widgets like buttons and dialog boxes. By using a nine
1408 patch, they can be rendered at any size without unappealing scaling
1409 artifacts.
1410
1411 @deffn {Procedure} draw-nine-patch @var{texture} @var{rect} @
1412 [#:margin 0] [#:top-margin margin] [#:bottom-margin margin] @
1413 [#:left-margin margin] [#:right-margin margin] @
1414 [#:origin] [#:scale] [#:rotation] [#:blend-mode alpha] @
1415 [#:shader]
1416
1417 Draw a nine patch sprite. A nine patch sprite renders @var{texture}
1418 as a @var{width} x @var{height} rectangle whose stretchable areas are
1419 defined by the given margin measurements @var{top-margin},
1420 @var{bottom-margin}, @var{left-margin}, and @var{right-margin}. The
1421 @var{margin} argument may be used to configure all four margins at
1422 once.
1423
1424 Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
1425 the other arguments.
1426 @end deffn
1427
1428 @node Tile Maps
1429 @subsection Tile Maps
1430
1431 A tile map is a scene created by composing lots of small sprites,
1432 called ``tiles'', into a larger image. One program for editing such
1433 maps is called @url{http://mapeditor.org,Tiled}. Chickadee has native
1434 support for loading and rendering Tiled maps in the @code{(chickadee
1435 render tiled)} module.
1436
1437 @deffn {Procedure} load-tile-map @var{file-name}
1438 Load the Tiled formatted map in @var{file-name} and return a new tile
1439 map object.
1440 @end deffn
1441
1442 @deffn {Procedure} draw-tile-map @var{tile-map} [#:layers] [#:region] @
1443 [#:origin] [#:position] [#:scale] [#:rotation]
1444
1445 Draw the layers of @var{tile-map}. By default, all layers are drawn.
1446 To draw a subset of the available layers, pass a list of layer ids
1447 using the @var{layers} keyword argument.
1448
1449 Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
1450 the other arguments.
1451 @end deffn
1452
1453 @node Lines and Shapes
1454 @subsection Lines and Shapes
1455
1456 Sprites are fun, but sometimes simple, untextured lines and polygons
1457 are desired. That's where the @code{(chickadee render shapes)} module
1458 comes in!
1459
1460 @deffn {Procedure} draw-line @var{start} @var{end} @
1461 [#:thickness 0.5] [#:feather 1.0] [#:cap round] [#:color] @
1462 [#:shader]
1463
1464 Draw a line segment from @var{start} to @var{end}. The line will be
1465 @var{thickness} pixels thick with an antialiased border @var{feather}
1466 pixels wide. The line will be colored @var{color}. @var{cap}
1467 specifies the type of end cap that should be used to terminate the
1468 lines, either @code{none}, @code{butt}, @code{square}, @code{round},
1469 @code{triangle-in}, or @code{triangle-out}. Advanced users may use
1470 the @var{shader} argument to override the built-in line segment
1471 shader.
1472 @end deffn
1473
1474 @deffn {Procedure} draw-bezier-curve @var{bezier} [#:segments 32] @
1475 [#:control-points?] [#:tangents?] @
1476 [#:control-point-size 8] @
1477 [#:control-point-color yellow] @
1478 [#:tangent-color yellow] @
1479 [#:thickness 0.5] [#:feather 1.0] @
1480 [#:matrix]
1481
1482 Draw the curve defined by @var{bezier} using a resolution of N
1483 @var{segments}. When @var{control-points?} is @code{#t}, the control
1484 points are rendered as squares of size @var{control-point-size} pixels
1485 and a color of @var{control-point-color}. When @var{tangents?} is
1486 @code{#t}, the tangent lines from terminal point to control point are
1487 rendered using the color @var{tangent-color}.
1488
1489 All line segments rendered use @code{draw-line}, and thus the
1490 arguments @var{thickness} and @var{feather} have the same effect as in
1491 that procedure.
1492
1493 A custom @var{matrix} may be passed for applications that require more
1494 control over the final output.
1495 @end deffn
1496
1497 @deffn {Procedure} draw-bezier-path @var{path} [#:segments 32] @
1498 [#:control-points?] [#:tangents?] @
1499 [#:control-point-size 8] @
1500 [#:control-point-color yellow] @
1501 [#:tangent-color yellow] @
1502 [#:thickness 0.5] [#:feather 1.0] @
1503 [#:matrix]
1504
1505 Render @var{path}, a list of bezier curves. See the documentation for
1506 @code{draw-bezier-curve} for an explanation of all the keyword
1507 arguments.
1508 @end deffn
1509
1510 @node Fonts
1511 @subsection Fonts
1512
1513 Unlike the traditional TrueType font format that many are accustomed
1514 to, Chickadee loads and renders bitmap fonts in the
1515 @url{http://www.angelcode.com/products/bmfont/doc/file_format.html,
1516 Angel Code format}. But why use this seemingly obscure format? It's
1517 easy to find TTFs but not easy to find FNTs (the canonical file
1518 extension used for Angel Code fonts) and bitmap fonts don't scale
1519 well. The reason is efficiency.
1520
1521 If all of the glyphs of a font are pre-rendered and packed into an
1522 image file then it becomes possible to use a texture atlas
1523 (@pxref{Textures}) and a sprite batch (@pxref{Sprites}) when
1524 rendering, which is a more efficient way to render fonts than using,
1525 say, @url{https://www.libsdl.org/projects/SDL_ttf/, SDL_ttf} or other
1526 solutions that involve using the FreeType library directly.
1527
1528 Now what about scaling? In libraries that use TTF fonts, one must
1529 choose the size that the glyphs will be rasterized at up front. To
1530 use @code{n} sizes of the same font, one must load @code{n} variants
1531 of that font. If the size of the text is dynamic, some kind of
1532 texture scaling algorithm must be used and the text will inevitably
1533 look blurry. At first glance, using bitmap fonts seem to have an even
1534 worse issue. Instead of just loading the same font @code{n} times at
1535 different sizes, one would need to generate @code{n} image files for
1536 each font size needed. This is where the ``signed distance field''
1537 rendering technique comes in. Introduced by
1538 @url{http://www.valvesoftware.com/.../2007/SIGGRAPH2007_AlphaTestedMagnification.pdf,
1539 Valve} in 2007, signed distance field fonts can be efficiently stored
1540 in a bitmap and be rendered at arbitrary scale factors with good
1541 results.
1542
1543 While Chickadee does not yet offer a tool for converting TTF fonts
1544 into FNT fonts, tools such as
1545 @url{https://github.com/libgdx/libgdx/wiki/Hiero, Hiero} may be used
1546 in the meantime.
1547
1548 The following procedures can be found in the @code{(chickadee render
1549 font)} module.
1550
1551 @deffn {Procedure} load-font @var{file}
1552 Load the Angel Code formatted XML document in @var{file} and return a
1553 new font object.
1554 @end deffn
1555
1556 @deffn {Procedure} font? @var{obj}
1557 Return @code{#t} if @var{obj} is a font object.
1558 @end deffn
1559
1560 @deffn {Procedure} font-face @var{font}
1561 Return the name of @var{font}.
1562 @end deffn
1563
1564 @deffn {Procedure} font-line-height @var{font}
1565 Return the line height of @var{font}.
1566 @end deffn
1567
1568 @deffn {Procedure} font-line-height @var{font}
1569 Return the line height of @var{font}.
1570 @end deffn
1571
1572 @deffn {Procedure} font-bold? @var{font}
1573 Return @code{#t} if @var{font} is a bold font.
1574 @end deffn
1575
1576 @deffn {Procedure} font-italic? @var{font}
1577 Return @code{#t} if @var{font} is an italicized font.
1578 @end deffn
1579
1580 @deffn {Procedure} draw-text @var{font} @var{text} @var{position}
1581 [#:origin] [#:scale] [#:rotation] [#:blend-mode]
1582 [#:start 0] [#:end @code{(string-length text)}]
1583
1584 Draw the string @var{text} with the first character starting at
1585 @var{position} using @var{font}.
1586
1587 @example
1588 (draw-text font "Hello, world!" (vec2 128.0 128.0))
1589 @end example
1590
1591 To render a substring of @var{text}, use the @var{start} and @var{end}
1592 arguments.
1593
1594 Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
1595 the other arguments.
1596 @end deffn
1597
1598 @node Particles
1599 @subsection Particles
1600
1601 Effects like smoke, fire, sparks, etc. are often achieved by animating
1602 lots of little, short-lived sprites known as ``particles''. In fact,
1603 all of these effects, and more, can be accomplished by turning a few
1604 configuration knobs in a ``particle system''. A particle system takes
1605 care of managing the many miniscule moving morsels so the developer
1606 can quickly produce an effect and move on with their life. The
1607 @code{(chickadee render particles)} module provides an API for
1608 manipulating particle systems.
1609
1610 Below is an example of a very simple particle system that utilizes
1611 nearly all of the default configuration settings:
1612
1613 @example
1614 (use-modules (chickadee render particles))
1615 (define texture (load-image "particle.png"))
1616 (define particles (make-particles 2000 #:texture texture))
1617 @end example
1618
1619 In order to put particles into a particle system, a particle
1620 ``emitter'' is needed. Emitters know where to spawn new particles,
1621 how many of them to spawn, and for how long they should do it.
1622
1623 Below is an example of an emitter that spawns 16 particles per frame
1624 at the coordinates @code{(320, 240)}:
1625
1626 @example
1627 (use-modules (chickadee math vector))
1628 (define emitter (make-particle-emitter (vec2 320.0 240.0) 16))
1629 (add-particle-emitter particles emitter)
1630 @end example
1631
1632 To see all of the tweakable knobs and switches, read on!
1633
1634 @deffn {Procedure} make-particles @var{capacity} [#:blend-mode @code{alpha}] @
1635 [#:color white] [#:end-color transparent] [#:texture] @
1636 [#:animation-rows 1] [#:animation-columns 1] [#:width] [#:height] @
1637 [#:speed-range (vec2 0.1 1.0)] [#:acceleration-range (vec2 0.0 0.1)] @
1638 [#:direction-range (vec2 0 (* 2 pi))] [#:lifetime 30] [#:sort]
1639
1640 Return a new particle system that may contain up to @var{capacity}
1641 particles. Achieving the desired particle effect involves tweaking
1642 the following keyword arguments as needed:
1643
1644 - @var{blend-mode}: Pixel blending mode. @code{alpha} by default.
1645 (@pxref{Blending} for more about blend modes).
1646
1647 - @var{start-color}: The tint color of the particle at the beginning of its
1648 life. White by default.
1649
1650 - @var{end-color}: The tint color of the particle at the end of of its
1651 life. Completely transparent by default for a fade-out effect. The
1652 color in the middle of a particle's life will be an interpolation of
1653 @var{start-color} and @var{end-color}.
1654
1655 - @var{texture}: The texture applied to the particles. The texture
1656 may be subdivided into many animation frames.
1657
1658 - @var{animation-rows}: How many animation frame rows there are in the
1659 texture. Default is 1.
1660
1661 - @var{animation-columns}: How many animation frame columns there are
1662 in the texture. Default is 1.
1663
1664 - @var{width}: The width of each particle. By default, the width of
1665 an animation frame (in pixels) is used.
1666
1667 - @var{height}: The height of each particle. By default, the height
1668 of an animation frame (in pixels) is used.
1669
1670 - @var{speed-range}: A 2D vector containing the min and max particle
1671 speed. Each particle will have a speed chosen at random from this
1672 range. By default, speed ranges from 0.1 to 1.0.
1673
1674 - @var{acceleration-range}: A 2D vector containing the min and max
1675 particle acceleration. Each particle will have an acceleration chosen
1676 at random from this range. By default, acceleration ranges from 0.0
1677 to 0.1.
1678
1679 - @var{direction-range}: A 2D vector containing the min and max
1680 particle direction as an angle in radians. Each particle will have a
1681 direction chosen at random from this range. By default, the range
1682 covers all possible angles.
1683
1684 - @var{lifetime}: How long each particle lives, measured in
1685 updates. 30 by default.
1686
1687 - @var{sort}: @code{youngest} if youngest particle should be drawn
1688 last or @code{oldest} for the reverse. By default, no sorting is
1689 applied at all.
1690 @end deffn
1691
1692 @deffn {Procedure} particles? @var{obj}
1693 Return @code{#t} if @var{obj} is a particle system.
1694 @end deffn
1695
1696 @deffn {Procedure} update-particles @var{particles}
1697 Advance the simulation of @var{particles}.
1698 @end deffn
1699
1700 @deffn {Procedure} draw-particles @var{particles}
1701 Render @var{particles}.
1702 @end deffn
1703
1704 @deffn {Procedure} draw-particles* @var{particles} @var{matrix}
1705 Render @var{particles} with @var{matrix} applied.
1706 @end deffn
1707
1708 @deffn {Procedure} make-particle-emitter @var{spawn-area} @
1709 @var{rate} [@var{duration}]
1710
1711 Return a new particle emitter that spawns @var{rate} particles per
1712 frame within @var{spawn-area} (a rectangle or 2D vector) for
1713 @var{duration} frames. If @var{duration} is not specified, the
1714 emitter will spawn particles indefinitely.
1715 @end deffn
1716
1717 @deffn {Procedure} particle-emitter? @var{obj}
1718 Return @code{#t} if @var{obj} is a particle emitter.
1719 @end deffn
1720
1721 @deffn {Procedure} particle-emitter-spawn-area @var{emitter}
1722 Return the spawn area for @var{emitter}.
1723 @end deffn
1724
1725 @deffn {Procedure} particle-emitter-rate @var{emitter}
1726 Return the number of particles that @var{emitter} will spawn per
1727 frame.
1728 @end deffn
1729
1730 @deffn {Procedure} particle-emitter-life @var{emitter}
1731 Return the number of frames remaining in @var{emitter}'s lifespan.
1732 @end deffn
1733
1734 @deffn {Procedure} particle-emitter-done? @var{emitter}
1735 Return @code{#t} if @var{emitter} has finished spawning particlces.
1736 @end deffn
1737
1738 @deffn {Procedure} add-particle-emitter @var{particles} @var{emitter}
1739 Add @var{emitter} to @var{particles}.
1740 @end deffn
1741
1742 @deffn {Procedure} remove-particle-emitter @var{particles} @var{emitter}
1743 Remove @var{emitter} to @var{particles}
1744 @end deffn
1745
1746 @node Blending
1747 @subsection Blending
1748
1749 Rendering a scene often involves drawing layers of objects that
1750 overlap each other. Blending determines how two overlapping pixels
1751 are combined in the final image that is rendered to the screen.
1752 Chickadee provides the following blend modes:
1753
1754 @itemize
1755
1756 @item @code{replace}
1757 Use the latest color, ignoring all others.
1758
1759 @item @code{alpha}
1760 Blend pixels according to the values of their alpha channels. This is
1761 the most commonly used blend mode and thus is Chickadee's default
1762 mode.
1763
1764 @item @code{add}
1765 Add all pixel color values together. The more colors blended
1766 together, the more white the final color becomes.
1767
1768 @item @code{subtract}
1769 Subtract all pixel color values. The more colors blended together,
1770 the more black the final color becomes.
1771
1772 @item @code{multiply}
1773
1774 @item @code{darken}
1775
1776 @item @code{lighten}
1777
1778 @item @code{screen}
1779
1780 @end itemize
1781
1782 @node Framebuffers
1783 @subsection Framebuffers
1784
1785 A framebuffer is a chunk of memory that the GPU can render things
1786 onto. By default, the framebuffer that is used for rendering is the
1787 one belonging to the game window, but custom framebuffers can be used
1788 as well. A common use-case for custom framebuffers is applying
1789 post-processing effects: The entire scene is rendered to a
1790 framebuffer, and then the contents of that framebuffer are applied to
1791 a post-processing shader and rendered to the game window. The
1792 post-processing shader could do any number of things: scaling,
1793 antialiasing, motion blur, etc.
1794
1795 @deffn {Procedure} make-framebuffer @var{width} @var{height} [#:min-filter 'linear] [#:mag-filter 'linear] [#:wrap-s 'repeat] [#:wrap-t 'repeat]
1796
1797 Create a new framebuffer that is @var{width} pixels wide and @var{height} pixels high.
1798
1799 @var{min-filter} and @var{mag-filter} determine the scaling algorithm
1800 applied to the framebuffer when rendering. By default, linear scaling
1801 is used in both cases. To perform no smoothing at all, use
1802 @code{nearest} for simple nearest neighbor scaling. This is typically
1803 the best choice for pixel art games.
1804 @end deffn
1805
1806 @deffn {Procedure} framebuffer? @var{obj}
1807 Return @code{#t} if @var{obj} is a framebuffer.
1808 @end deffn
1809
1810 @deffn {Procedure} framebuffer-texture @var{fb}
1811 Return the texture backing the framebuffer @var{fb}.
1812 @end deffn
1813
1814 @deffn {Procedure} framebuffer-viewport @var{fb}
1815 Return the default viewport (@pxref{Viewports}) used by the
1816 framebuffer @var{fb}.
1817 @end deffn
1818
1819 @deffn {Procedure} null-framebuffer
1820 The default framebuffer.
1821 @end deffn
1822
1823 @node Viewports
1824 @subsection Viewports
1825
1826 A viewport represents a subset of the screen (or framebuffer). When
1827 rendering a frame, the resulting image will only appear within that
1828 viewport. These aren't often needed, and Chickadee's default viewport
1829 occupies the entire screen, but there are certain situations where
1830 they are useful. For example, a split-screen multiplayer game may
1831 render to two different viewports, each occupying a different half of
1832 the screen. For information about how to set the current viewport,
1833 see @code{with-viewport} in @ref{Rendering Engine}.
1834
1835 The @code{(chickadee render viewport)} module provides the following
1836 API:
1837
1838 @deffn {Procedure} make-viewport @var{x} @var{y} @var{width} @var{height} @
1839 [#:clear-color] [#:clear-flags]
1840
1841 Create a viewport that covers an area of the window starting from
1842 coordinates (@var{x}, @var{y}) and spanning @var{width} @code{x}
1843 @var{height} pixels. Fill the viewport with @var{clear-color} when
1844 clearing the screen. Clear the buffers denoted by the list of symbols
1845 in @var{clear-flags}.
1846
1847 Possible values for @var{clear-flags} are @var{color-buffer},
1848 @var{depth-buffer}, @var{accum-buffer}, and @var{stencil-buffer}.
1849 @end deffn
1850
1851 @deffn {Procedure} viewport? @var{obj}
1852 Return @code{#t} if @var{obj} is a viewport.
1853 @end deffn
1854
1855 @deffn {Procedure} viewport-x @var{viewport}
1856 Return the left edge of @var{viewport}.
1857 @end deffn
1858
1859 @deffn {Procedure} viewport-y @var{viewport}
1860 Return the bottom edge of @var{viewport}.
1861 @end deffn
1862
1863 @deffn {Procedure} viewport-width @var{viewport}
1864 Return the width of @var{viewport}.
1865 @end deffn
1866
1867 @deffn {Procedure} viewport-height @var{viewport}
1868 Return the height of @var{viewport}.
1869 @end deffn
1870
1871 @deffn {Procedure} viewport-clear-color @var{viewport}
1872 Return the clear color for @var{viewport}.
1873 @end deffn
1874
1875 @deffn {Procedure} viewport-clear-flags @var{viewport}
1876 Return the list of clear flags for @var{viewport}.
1877 @end deffn
1878
1879 @node Rendering Engine
1880 @subsection Rendering Engine
1881
1882 Chickadee defines rendering using a metaphor familiar to Scheme
1883 programmers: procedure application. A shader (@pxref{Shaders}) is
1884 like a procedure for the GPU to apply. Shaders are passed arguments:
1885 A vertex array containing the geometry to render (@pxref{Buffers}) and
1886 zero or more keyword arguments that the shader understands. Similar
1887 to how Scheme has @code{apply} for calling procedures, Chickadee
1888 provides @code{gpu-apply} for calling shaders.
1889
1890 Additionally, there is some dynamic state that effects how
1891 @code{gpu-apply} will behave. Things like the current viewport,
1892 framebuffer, and blend mode are stored as dynamic state because it
1893 would be tedious to have to have to specify them each time
1894 @code{gpu-apply} is called.
1895
1896 The following procedures and syntax can be found in the
1897 @code{(chickadee render)} module.
1898
1899 @deffn {Syntax} gpu-apply @var{shader} @var{vertex-array} @
1900 [#:uniform-key @var{uniform-value} ...]
1901 @deffnx {Syntax} gpu-apply* @var{shader} @var{vertex-array} @
1902 @var{count} [#:uniform-key @var{uniform-value} ...]
1903
1904 Render @var{vertex-array} using @var{shader} with the uniform values
1905 specified in the following keyword arguments.
1906
1907 While @code{gpu-apply} will draw every vertex in @var{vertex-array},
1908 @code{gpu-apply*} will only draw @var{count} vertices.
1909 @end deffn
1910
1911 @deffn {Syntax} gpu-apply/instanced @var{shader} @var{vertex-array} @
1912 @var{n} [#:uniform-key @var{uniform-value} ...]
1913 @deffnx {Syntax} gpu-apply/instanced @var{shader} @var{vertex-array} @
1914 @var{count} @var{n} [#:uniform-key @var{uniform-value} ...]
1915
1916 Render @var{vertex-array} @var{n} times using @var{shader} with the
1917 uniform values specified in the following keyword arguments.
1918
1919 Instanced rendering is very beneficial for rendering the same object
1920 many times with only small differences for each one. For example, the
1921 particle effects described in @ref{Particles} use instanced rendering.
1922
1923 While @code{gpu-apply/instanced} will draw every vertex in
1924 @var{vertex-array}, @code{gpu-apply*} will only draw @var{count}
1925 vertices.
1926 @end deffn
1927
1928 @deffn {Procedure} current-viewport
1929 Return the currently bound viewport (@pxref{Viewports}).
1930 @end deffn
1931
1932 @deffn {Procedure} current-framebuffer
1933 Return the currently bound framebuffer (@pxref{Framebuffers}).
1934 @end deffn
1935
1936 @deffn {Procedure} current-blend-mode
1937 Return the currently bound blend mode (@pxref{Blending}).
1938 @end deffn
1939
1940 @deffn {Procedure} current-depth-test
1941 Return @code{#t} if depth testing is currently enabled (@pxref{Blending}).
1942 @end deffn
1943
1944 @deffn {Procedure} current-texture
1945 Return the currently bound texture (@pxref{Textures}).
1946 @end deffn
1947
1948 @deffn {Procedure} current-projection
1949 Return the currently bound projection matrix (@pxref{Matrices}).
1950 @end deffn
1951
1952 @deffn {Syntax} with-viewport @var{viewport} @var{body} ...
1953 Evaluate @var{body} with the current viewport bound to @var{viewport} (@pxref{Viewports}).
1954 @end deffn
1955
1956 @deffn {Syntax} with-framebuffer @var{framebuffer} @var{body} ...
1957 Evaluate @var{body} with the current framebuffer bound to
1958 @var{framebuffer} (@pxref{Framebuffers}).
1959 @end deffn
1960
1961 @deffn {Syntax} with-blend-mode @var{blend-mode} @var{body} ...
1962 Evaluate @var{body} with the current blend mode bound to
1963 @var{blend-mode} (@pxref{Blending}).
1964 @end deffn
1965
1966 @deffn {Syntax} with-depth-test @var{depth-test?} @var{body} ...
1967 Evaluate @var{body} with the depth-test disabled if @var{depth-test?}
1968 is @code{#f}, or enabled otherwise (@pxref{Blending}).
1969 @end deffn
1970
1971 @deffn {Syntax} with-texture @var{texture} @var{body} ...
1972 Evaluate @var{body} with the current texture bound to @var{texture}
1973 (@pxref{Textures}).
1974 @end deffn
1975
1976 @deffn {Syntax} with-projection @var{projection} @var{body} ...
1977 Evaluate @var{body} with the current projection matrix bound to
1978 @var{projection} (@pxref{Matrices}).
1979 @end deffn
1980
1981 @node Buffers
1982 @subsection Buffers
1983
1984 Alright, let's brush aside all of those pretty high level abstractions
1985 and discuss what is going on under the hood. The GPU exists as a
1986 discrete piece of hardware separate from the CPU. In order to make it
1987 draw things, we must ship lots of data out of our memory space and
1988 into the GPU. The @code{(chickadee render buffer}) module provides an
1989 API for manipulating GPU buffers.
1990
1991 In OpenGL terminology, a chunk of data allocated on the GPU is a
1992 ``vertex buffer object'' or VBO. For example, here is a bytevector
1993 that could be transformed into a GPU buffer that packs together vertex
1994 position and texture coordinates:
1995
1996 @example
1997 (use-modules (chickadee render buffer) (srfi srfi-4))
1998 (define data
1999 (f32vector -8.0 -8.0 ; 2D vertex
2000 0.0 0.0 ; 2D texture coordinate
2001 8.0 -8.0 ; 2D vertex
2002 1.0 0.0 ; 2D texture coordinate
2003 8.0 8.0 ; 2D vertex
2004 1.0 1.0 ; 2D texture coordinate
2005 -8.0 8.0 ; 2D vertex
2006 0.0 1.0)) ; 2D texture coordinate
2007 @end example
2008
2009 This data represents a textured 16x16 square centered on the
2010 origin. To send this data to the GPU, the @code{make-buffer} procedure
2011 is needed:
2012
2013 @example
2014 (define buffer (make-buffer data #:stride 16))
2015 @end example
2016
2017 The @code{#:stride} keyword argument indicates how many bytes make up
2018 each element of the buffer. In this case, there are 4 floats per
2019 element: 2 for the vertex, and 2 for the texture coordinate. A 32-bit
2020 float is 4 bytes in length, so the buffer's stride is 16.
2021
2022 Within a VBO, one or more ``attributes'', as OpenGL calls them, may be
2023 present. Attributes are subregions within the buffer that have a
2024 particular data type. In this case, there are two attributes packed
2025 into the buffer. To provided a typed view into a buffer, the
2026 @code{make-typed-buffer} procedure is needed:
2027
2028 @example
2029 (define vertices
2030 (make-typed-buffer #:buffer buffer
2031 #:type 'vec2
2032 #:component-type 'float
2033 #:length 4))
2034 (define texcoords
2035 (make-typed-buffer #:buffer buffer
2036 #:type 'vec2
2037 #:component-type 'float
2038 #:length 4
2039 #:offset 8))
2040 @end example
2041
2042 To render a square, the GPU needs to draw two triangles, which means
2043 we need 6 vertices in total. However, the above buffer only contains
2044 data for 4 vertices. This is becase there are only 4 unique vertices
2045 for a square, but 2 of them must be repeated for each triangle. To
2046 work with deduplicated vertex data, an ``index buffer'' must be
2047 created.
2048
2049 @example
2050 (define index-buffer
2051 (make-buffer (u32vector 0 3 2 0 2 1)
2052 #:target 'index)
2053 (define indices
2054 (make-typed-buffer #:type 'scalar
2055 #:component-type 'unsigned-int
2056 #:buffer index-buffer))
2057 @end example
2058
2059 Note the use of the @code{#:target} keyword argument. It is required
2060 because the GPU treats index data in a special way and must be told
2061 which data is index data.
2062
2063 Now that the typed buffers representing each attribute have been
2064 created, all that's left is to bind them all together in a ``vertex
2065 array object'', or VAO. Vertex arrays associate each typed buffer
2066 with an attribute index on the GPU. The indices that are chosen must
2067 correspond with the indices that the shader (@pxref{Shaders}) expects
2068 for each attribute.
2069
2070 @example
2071 (define vertex-array
2072 (make-vertex-array #:indices indices
2073 #:attributes `((0 . ,vertices)
2074 (1 . ,texcoords))))
2075 @end example
2076
2077 With the vertex array created, the GPU is now fully aware of how to
2078 interpret the data that it has been given in the original buffer.
2079 Actually rendering this square is left as an exercise to the reader.
2080 See the @ref{Shaders} section and the @code{gpu-apply} procedure in
2081 @ref{Rendering Engine} for the remaining pieces of a successful draw
2082 call. Additionally, consider reading the source code for sprites,
2083 shapes, or particles to see GPU buffers in action.
2084
2085 Without further ado, the API reference:
2086
2087 @deffn {Procedure} make-buffer @var{data} [#:name "anonymous"] @
2088 [#:length] [#:offset 0] [#:stride 0] [#:target @code{vertex}] @
2089 [#:usage @code{static}]
2090
2091 Upload @var{data}, a bytevector, to the GPU. By default, the entire
2092 bytevector is uploaded. A subset of the data may be uploaded by
2093 specifying the @var{offset}, the index of the first byte to be
2094 uploaded, and @var{length}, the number of bytes to upload.
2095
2096 If @var{data} is @code{#f}, allocate @var{length} bytes of fresh GPU
2097 memory instead.
2098
2099 @var{target} and @var{usage} are hints that tell the GPU how the
2100 buffer is intended to be used.
2101
2102 @var{target} may be:
2103
2104 @itemize
2105 @item @code{vertex}
2106 Vertex attribute data.
2107
2108 @item @code{index}
2109 Index buffer data.
2110
2111 @end itemize
2112
2113 @var{usage} may be:
2114
2115 @itemize
2116 @item @code{static}
2117 The buffer data will not be modified after creation.
2118
2119 @item @code{stream}
2120 The buffer data will be modified frequently.
2121
2122 @end itemize
2123
2124 @var{name} is simply an arbitrary string for debugging purposes that
2125 is never sent to the GPU.
2126 @end deffn
2127
2128 @deffn {Procedure} buffer? @var{obj}
2129 Return @code{#t} if @var{obj} is a GPU buffer.
2130 @end deffn
2131
2132 @deffn {Procedure} index-buffer? @var{buffer}
2133 Return @code{#t} if @var{buffer} is an index buffer.
2134 @end deffn
2135
2136 @defvar null-buffer
2137 Represents the absence of a buffer.
2138 @end defvar
2139
2140 @deffn {Procedure} buffer-name @var{buffer}
2141 Return the name of @var{buffer}.
2142 @end deffn
2143
2144 @deffn {Procedure} buffer-length @var{buffer}
2145 Return the length of @var{buffer}.
2146 @end deffn
2147
2148 @deffn {Procedure} buffer-stride @var{buffer}
2149 Return the amount of space, in bytes, between each element in
2150 @var{buffer}.
2151 @end deffn
2152
2153 @deffn {Procedure} buffer-target @var{buffer}
2154 Return the the intended usage of @var{buffer}, either @code{vertex} or
2155 @code{index}.
2156 @end deffn
2157
2158 @deffn {Procedure} buffer-usage @var{buffer}
2159 Return the intended usage of @var{buffer}, either @code{static} for
2160 buffer data that will not change once sent to the GPU, or
2161 @code{stream} for buffer data that will be frequently updated from the
2162 client-side.
2163 @end deffn
2164
2165 @deffn {Procedure} buffer-data @var{buffer}
2166 Return a bytevector containing all the data within @var{buffer}. If
2167 @var{buffer} has not been mapped (see @code{with-mapped-buffer}) then
2168 this procedure will return @code{#f}.
2169 @end deffn
2170
2171 @deffn {Syntax} with-mapped-buffer @var{buffer} @var{body} @dots{}
2172 Evaluate @var{body} in the context of @var{buffer} having its data
2173 synced from GPU memory to RAM. In this context, @code{buffer-data}
2174 will return a bytevector of all the data stored in @var{buffer}. When
2175 program execution exits this form, the data (including any
2176 modifications) is synced back to the GPU.
2177
2178 This form is useful for streaming buffers that need to update their
2179 contents dynamically, such as a sprite batch.
2180 @end deffn
2181
2182 @deffn {Procedure} make-typed-buffer #:buffer #:type @
2183 #:component-type #:length [#:offset 0] [#:divisor] @
2184 [#:name "anonymous"]
2185
2186 Return a new typed buffer view for @var{buffer} starting at byte index
2187 @var{offset} of @var{length} elements, where each element is of
2188 @var{type} and composed of @var{component-type} values.
2189
2190 Valid values for @var{type} are:
2191
2192 @itemize
2193 @item @code{scalar}
2194 single number
2195
2196 @item @code{vec2}
2197 2D vector
2198
2199 @item @code{vec3}
2200 3D vector
2201
2202 @item @code{vec4}
2203 4D vector
2204
2205 @item @code{mat2}
2206 2x2 matrix
2207
2208 @item @code{mat3}
2209 3x3 matrix
2210
2211 @item @code{mat4}
2212 4x4 matrix
2213 @end itemize
2214
2215 Valid values for @var{component-type} are:
2216
2217 @itemize
2218
2219 @item @code{byte}
2220 @item @code{unsigned-byte}
2221 @item @code{short}
2222 @item @code{unsigned-short}
2223 @item @code{int}
2224 @item @code{unsigned-int}
2225 @item @code{float}
2226 @item @code{double}
2227
2228 @end itemize
2229
2230 @var{divisor} is only needed for instanced rendering applications (see
2231 @code{gpu-apply/instanced} in @ref{Rendering Engine}) and represents
2232 how many instances each vertex element applies to. A divisor of 0
2233 means that a single element is used for every instance and is used for
2234 the data being instanced. A divisor of 1 means that each element is
2235 used for 1 instance. A divisor of 2 means that each element is used
2236 for 2 instances, and so on.
2237 @end deffn
2238
2239 @deffn {Procedure} typed-buffer? @var{obj}
2240 Return @code{#t} if @var{obj} is a typed buffer.
2241 @end deffn
2242
2243 @deffn {Procedure} typed-buffer->buffer @var{typed-buffer}
2244 Return the buffer that @var{typed-buffer} is using.
2245 @end deffn
2246
2247 @deffn {Procedure} typed-buffer-name @var{typed-buffer}
2248 Return the name of @var{typed-buffer}.
2249 @end deffn
2250
2251 @deffn {Procedure} typed-buffer-offset @var{typed-buffer}
2252 Return the byte offset of @var{typed-buffer}.
2253 @end deffn
2254
2255 @deffn {Procedure} typed-buffer-type @var{typed-buffer}
2256 Return the data type of @var{typed-buffer}.
2257 @end deffn
2258
2259 @deffn {Procedure} typed-buffer-component-type @var{typed-buffer}
2260 Return the component data type of @var{typed-buffer}
2261 @end deffn
2262
2263 @deffn {Procedure} typed-buffer-divisor @var{typed-buffer}
2264 Return the instance divisor for @var{typed-buffer}.
2265 @end deffn
2266
2267 @deffn {Syntax} with-mapped-typed-buffer @var{typed-buffer} @var{body} @dots{}
2268
2269 Evaluate @var{body} in the context of @var{typed-buffer} having its
2270 data synced from GPU memory to RAM. See @code{with-mapped-buffer} for
2271 more information.
2272 @end deffn
2273
2274 @deffn {Procedure} make-vertex-array #:indices #:attributes @
2275 [#:mode @code{triangles}]
2276
2277 Return a new vertex array using the index data within the typed buffer
2278 @var{indices} and the vertex attribute data within @var{attributes}.
2279
2280 @var{attributes} is an alist mapping shader attribute indices to typed
2281 buffers containing vertex data:
2282
2283 @example
2284 `((1 . ,typed-buffer-a)
2285 (2 . ,typed-buffer-b)
2286 ...)
2287 @end example
2288
2289 By default, the vertex array is interpreted as containing a series of
2290 triangles. If another primtive type is desired, the @var{mode}
2291 keyword argument may be overridden. The following values are
2292 supported:
2293
2294 @itemize
2295 @item @code{points}
2296 @item @code{lines}
2297 @item @code{line-loop}
2298 @item @code{line-strip}
2299 @item @code{triangles}
2300 @item @code{triangle-strip}
2301 @item @code{triangle-fan}
2302 @end itemize
2303
2304 @end deffn
2305
2306 @defvar null-vertex-array
2307 Represents the absence of a vertex array.
2308 @end defvar
2309
2310 @deffn {Procedure} vertex-array? @var{obj}
2311 Return @code{#t} if @var{obj} is a vertex array.
2312 @end deffn
2313
2314 @deffn {Procedure} vertex-array-indices @var{vertex-array}
2315 Return the typed buffer containing index data for @var{vertex-array}.
2316 @end deffn
2317
2318 @deffn {Procedure} vertex-array-attributes @var{vertex-array}
2319 Return the attribute index -> typed buffer mapping of vertex attribute
2320 data for @var{vertex-array}.
2321 @end deffn
2322
2323 @deffn {Procedure} vertex-array-mode @var{vertex-array}
2324 Return the primitive rendering mode for @var{vertex-array}.
2325 @end deffn
2326
2327 @node Shaders
2328 @subsection Shaders
2329
2330 Shaders are programs that the GPU can evaluate that allow the
2331 programmer to completely customized the final output of a GPU draw
2332 call. The @code{(chickadee render shader)} module provides an API for
2333 building custom shaders.
2334
2335 Shaders are written in the OpenGL Shading Language, or GLSL for short.
2336 Chickadee aspires to provide a domain specific language for writing
2337 shaders in Scheme, but we are not there yet.
2338
2339 Shader programs consist of two components: A vertex shader and a
2340 fragment shader. A vertex shader receives vertex data (position
2341 coordinates, texture coordinates, normals, etc.) and transforms them
2342 as desired, whereas a fragment shader controls the color of each
2343 pixel.
2344
2345 Sample vertex shader:
2346
2347 @example
2348 @verbatim
2349 #version 130
2350
2351 in vec2 position;
2352 in vec2 tex;
2353 out vec2 fragTex;
2354 uniform mat4 mvp;
2355
2356 void main(void) {
2357 fragTex = tex;
2358 gl_Position = mvp * vec4(position.xy, 0.0, 1.0);
2359 }
2360 @end verbatim
2361 @end example
2362
2363 Sample fragment shader:
2364
2365 @example
2366 @verbatim
2367 #version 130
2368
2369 in vec2 fragTex;
2370 uniform sampler2D colorTexture;
2371
2372 void main (void) {
2373 gl_FragColor = texture2D(colorTexture, fragTex);
2374 }
2375 @end verbatim
2376 @end example
2377
2378 This manual will not cover GLSL features and syntax as there is lots
2379 of information already available about this topic.
2380
2381 One way to think about rendering with shaders, and the metaphor
2382 Chickadee uses, is to think about it as a function call: The shader is
2383 a function, and it is applied to some ``attributes'' (positional
2384 arguments), and some ``uniforms'' (keyword arguments).
2385
2386 @example
2387 (define my-shader (load-shader "vert.glsl" "frag.glsl"))
2388 (define vertices (make-vertex-array ...))
2389 (gpu-apply my-shader vertices #:color red)
2390 @end example
2391
2392 @xref{Rendering Engine} for more details about the @code{gpu-apply}
2393 procedure.
2394
2395 Shaders are incredibly powerful tools, and there's more information
2396 about them than we could ever fit into this manual, so we highly
2397 recommend searching the web for more information and examples. What
2398 we can say, though, is how to use our API:
2399
2400 @deffn {Procedure} strings->shader @var{vertex-source} @var{fragment-source}
2401 Compile @var{vertex-source}, the GLSL code for the vertex shader, and
2402 @var{fragment-source}, the GLSL code for the fragment shader, into a
2403 GPU shader program.
2404 @end deffn
2405
2406 @deffn {Procedure} load-shader @var{vertex-source-file} @
2407 @var{fragment-source-file}
2408
2409 Compile the GLSL source code within @var{vertex-source-file} and
2410 @var{fragment-source-file} into a GPU shader program.
2411 @end deffn
2412
2413 @deffn {Procedure} make-shader @var{vertex-port} @var{fragment-port}
2414 Read GLSL source from @var{vertex-port} and @var{fragment-port} and
2415 compile them into a GPU shader program.
2416 @end deffn
2417
2418 @deffn {Procedure} shader? @var{obj}
2419 Return @code{#t} if @var{obj} is a shader.
2420 @end deffn
2421
2422 @defvar null-shader
2423 Represents the absence shader program.
2424 @end defvar
2425
2426 @deffn {Procedure} shader-uniform @var{shader} @var{name}
2427 Return the metadata for the uniform @var{name} in @var{shader}.
2428 @end deffn
2429
2430 @deffn {Procedure} shader-uniforms @var{shader}
2431 Return a hash table of uniforms for @var{shader}.
2432 @end deffn
2433
2434 @deffn {Procedure} shader-attributes @var{shader}
2435 Return a hash table of attributes for @var{shader}.
2436 @end deffn
2437
2438 @deffn {Procedure} uniform? @var{obj}
2439 Return @code{#t} if @var{obj} is a uniform.
2440 @end deffn
2441
2442 @deffn {Procedure} uniform-name @var{uniform}
2443 Return the variable name of @var{uniform}.
2444 @end deffn
2445
2446 @deffn {Procedure} uniform-type @var{uniform}
2447 Return the data type of @var{uniform}.
2448 @end deffn
2449
2450 @deffn {Procedure} uniform-value @var{uniform}
2451 Return the current value of @var{uniform}.
2452 @end deffn
2453
2454 @deffn {Procedure} uniform-default-value @var{uniform}
2455 Return the default value of @var{uniform}.
2456 @end deffn
2457
2458 @deffn {Procedure} attribute? @var{obj}
2459 Return @code{#t} if @var{obj} is an attribute.
2460 @end deffn
2461
2462 @deffn {Procedure} attribute-name @var{attribute}
2463 Return the variable name of @var{attribute}.
2464 @end deffn
2465
2466 @deffn {Procedure} attribute-location @var{attribute}
2467 Return the binding location of @var{attribute}.
2468 @end deffn
2469
2470 @deffn {Procedure} attribute-type @var{attribute}
2471 Return the data type of @var{attribute}.
2472 @end deffn
2473
2474 @node Scripting
2475 @section Scripting
2476
2477 Game logic is a web of asynchronous events that are carefully
2478 coordinated to bring the game world to life. In order to make an
2479 enemy follow and attack the player, or move an NPC back and forth in
2480 front of the item shop, or do both at the same time, a scripting
2481 system is a necessity. Chickadee comes with an asynchronous
2482 programming system in the @code{(chickadee scripting)} module.
2483 Lightweight, cooperative threads known as ``scripts'' allow the
2484 programmer to write asynchronous code as if it were synchronous, and
2485 allow many such ``threads'' to run concurrently.
2486
2487 But before we dig deeper into scripts, let's discuss the simple act
2488 of scheduling tasks.
2489
2490 @menu
2491 * Agendas:: Scheduling tasks.
2492 * Scripts:: Cooperative multitasking.
2493 * Tweening:: Animations.
2494 * Channels:: Publish data to listeners.
2495 @end menu
2496
2497 @node Agendas
2498 @subsection Agendas
2499
2500 To schedule a task to be performed later, an ``agenda'' is used.
2501 There is a default, global agenda that is ready to be used, or
2502 additional agendas may be created for different purposes. The
2503 following example prints the text ``hello'' when the agenda has
2504 advanced to time unit 10.
2505
2506 @example
2507 (at 10 (display "hello\n"))
2508 @end example
2509
2510 Most of the time it is more convenient to schedule tasks relative to
2511 the current time. This is where @code{after} comes in handy:
2512
2513 @example
2514 (after 10 (display "hello\n"))
2515 @end example
2516
2517 Time units in the agenda are in no way connected to real time. It's
2518 up to the programmer to decide what agenda time means. A simple and
2519 effective approach is to map each call of the update hook
2520 (@pxref{Kernel}) to 1 unit of agenda time, like so:
2521
2522 @example
2523 (add-hook! update-hook (lambda (dt) (update-agenda 1)))
2524 @end example
2525
2526 It is important to call @code{update-agenda} periodically, otherwise
2527 no tasks will ever be run!
2528
2529 In addition to using the global agenda, it is useful to have multiple
2530 agendas for different purposes. For example, the game world can use a
2531 different agenda than the user interface, so that pausing the game is
2532 a simple matter of not updating the world's agenda while continuing to
2533 update the user interface's agenda. The current agenda is dynamically
2534 scoped and can be changed using the @code{with-agenda} special form:
2535
2536 @example
2537 (define game-world-agenda (make-agenda))
2538
2539 (with-agenda game-world-agenda
2540 (at 60 (spawn-goblin))
2541 (at 120 (spawn-goblin))
2542 (at 240 (spawn-goblin-king)))
2543 @end example
2544
2545 @deffn {Procedure} make-agenda
2546 Return a new task scheduler.
2547 @end deffn
2548
2549 @deffn {Procedure} agenda? @var{obj}
2550 Return @code{#t} if @var{obj} is an agenda.
2551 @end deffn
2552
2553 @deffn {Procedure} current-agenda
2554 @deffnx {Procedure} current-agenda @var{agenda}
2555 When called with no arguments, return the current agenda. When called
2556 with one argument, set the current agenda to @var{agenda}.
2557 @end deffn
2558
2559 @deffn {Syntax} with-agenda @var{agenda} @var{body} @dots{}
2560 Evaluate @var{body} with the current agenda set to @var{agenda}.
2561 @end deffn
2562
2563 @deffn {Procedure} agenda-time
2564 Return the current agenda time.
2565 @end deffn
2566
2567 @deffn {Procedure} update-agenda @var{dt}
2568 Advance the current agenda by @var{dt}.
2569 @end deffn
2570
2571 @deffn {Procedure} schedule-at @var{time} @var{thunk}
2572 Schedule @var{thunk}, a procedure of zero arguments, to be run at
2573 @var{time}.
2574 @end deffn
2575
2576 @deffn {Procedure} schedule-after @var{delay} @var{thunk}
2577 Schedule @var{thunk}, a procedure of zero arguments, to be run after
2578 @var{delay}.
2579 @end deffn
2580
2581 @deffn {Procedure} schedule-every @var{interval} @var{thunk} [@var{n}]
2582 Schedule @var{thunk}, a procedure of zero arguments, to be run every
2583 @var{interval} amount of time. Repeat this @var{n} times, or
2584 indefinitely if not specified.
2585 @end deffn
2586
2587 @deffn {Syntax} at @var{time} @var{body} @dots{}
2588 Schedule @var{body} to be evaluated at @var{time}.
2589 @end deffn
2590
2591 @deffn {Syntax} after @var{delay} @var{body} @dots{}
2592 Schedule @var{body} to be evaluated after @var{delay}.
2593 @end deffn
2594
2595 @deffn {Syntax} every @var{interval} @var{body} @dots{}
2596 @deffnx {Syntax} every (@var{interval} @var{n}) @var{body} @dots{}
2597 Schedule @var{body} to be evaluated every @var{interval} amount of
2598 time. Repeat this @var{n} times, or indefinitely if not specified.
2599 @end deffn
2600
2601 @node Scripts
2602 @subsection Scripts
2603
2604 Now that we can schedule tasks, let's take things to the next level.
2605 It sure would be great if we could make procedures that described a
2606 series of actions that happened over time, especially if we could do
2607 so without contorting our code into a nest of callback procedures.
2608 This is where scripts come in. With scripts we can write code in a
2609 linear way, in a manner that appears to be synchronous, but with the
2610 ability to suspend periodically in order to let other scripts have a
2611 turn and prevent blocking the game loop. Building on top of the
2612 scheduling that agendas provide, here is a script that models a child
2613 trying to get their mother's attention:
2614
2615 @example
2616 (script
2617 (while #t
2618 (display "mom!")
2619 (newline)
2620 (sleep 60))) ; where 60 = 1 second of real time
2621 @end example
2622
2623 This code runs in an endless loop, but the @code{sleep} procedure
2624 suspends the script and schedules it to be run later by the agenda.
2625 So, after each iteration of the loop, control is returned back to the
2626 game loop and the program is not stuck spinning in a loop that will
2627 never exit. Pretty neat, eh?
2628
2629 Scripts can suspend to any capable handler, not just the agenda.
2630 The @code{yield} procedure will suspend the current script and pass
2631 its ``continuation'' to a handler procedure. This handler procedure
2632 could do anything. Perhaps the handler stashes the continuation
2633 somewhere where it will be resumed when the user presses a specific
2634 key on the keyboard, or maybe it will be resumed when the player picks
2635 up an item off of the dungeon floor; the sky is the limit.
2636
2637 Sometimes it is necessary to abruptly terminate a script after it has
2638 been started. For example, when an enemy is defeated their AI routine
2639 needs to be shut down. When a script is spawned, a handle to that
2640 script is returned that can be used to cancel it when desired.
2641
2642 @example
2643 (define script (script (while #t (display "hey\n") (sleep 60))))
2644 ;; sometime later
2645 (cancel-script script)
2646 @end example
2647
2648 @deffn {Procedure} spawn-script @var{thunk}
2649 Apply @var{thunk} as a script and return a handle to it.
2650 @end deffn
2651
2652 @deffn {Syntax} script @var{body} @dots{}
2653 Evaluate @var{body} as a script and return a handle to it.
2654 @end deffn
2655
2656 @deffn {Procedure} script? @var{obj}
2657 Return @code{#t} if @var{obj} is a script handle.
2658 @end deffn
2659
2660 @deffn {Procedure} script-cancelled? @var{obj}
2661 Return @code{#t} if @var{obj} has been cancelled.
2662 @end deffn
2663
2664 @deffn {Procedure} script-running? @var{obj}
2665 Return @code{#t} if @var{obj} has not yet terminated or been
2666 cancelled.
2667 @end deffn
2668
2669 @deffn {Procedure} script-complete? @var{obj}
2670 Return @code{#t} if @var{obj} has terminated.
2671 @end deffn
2672
2673 @deffn {Procedure} cancel-script @var{co}
2674 Prevent further execution of the script @var{co}.
2675 @end deffn
2676
2677 @deffn {Procedure} yield @var{handler}
2678 Suspend the current script and pass its continuation to the
2679 procedure @var{handler}.
2680 @end deffn
2681
2682 @deffn {Procedure} sleep @var{duration}
2683 Wait @var{duration} before resuming the current script.
2684 @end deffn
2685
2686 @deffn {Syntax} forever @var{body} @dots{}
2687 Evaluate @var{body} in an endless loop.
2688 @end deffn
2689
2690 @node Tweening
2691 @subsection Tweening
2692
2693 Tweening is the process of transitioning something from an initial
2694 state to a final state over a pre-determined period of time. In other
2695 words, tweening is a way to create animation. The @code{tween}
2696 procedure can be used within any script like so:
2697
2698 @example
2699 (define x 0)
2700 (script
2701 ;; 0 to 100 in 60 ticks of the agenda.
2702 (tween 60 0 100 (lambda (y) (set! x y))))
2703 @end example
2704
2705 @deffn {Procedure} tween @var{duration} @var{start} @var{end} @var{proc} [#:step 1 #:ease @code{smoothstep} #:interpolate @code{lerp}]
2706 Transition a value from @var{start} to @var{end} over @var{duration},
2707 sending each succesive value to @var{proc}. @var{step} controls the
2708 amount of time between each update of the animation.
2709
2710 To control how the animation goes from the initial to final state, an
2711 ``easing'' procedure may be specified. By default, the
2712 @code{smoothstep} easing is used, which is a more pleasing default
2713 than a simplistic linear function. @xref{Easings} for a complete list
2714 of available easing procedures.
2715
2716 The @var{interpolate} procedure computes the values in between
2717 @var{start} and @var{end}. By default, linear interpolation (``lerp''
2718 for short) is used.
2719 @end deffn
2720
2721 @node Channels
2722 @subsection Channels
2723
2724 Channels are a tool for communicating amongst different scripts. One
2725 script can write a value to the channel and another can read from it.
2726 Reading or writing to a channel suspends that script until there is
2727 someone on the other end of the line to complete the transaction.
2728
2729 Here's a simplistic example:
2730
2731 @example
2732 (define c (make-channel))
2733
2734 (script
2735 (forever
2736 (let ((item (channel-get c)))
2737 (pk 'got item))))
2738
2739 (script
2740 (channel-put c 'sword)
2741 (channel-put c 'shield)
2742 (channel-put c 'potion))
2743 @end example
2744
2745 @deffn {Procedure} make-channel
2746 Return a new channel
2747 @end deffn
2748
2749 @deffn {Procedure} channel? @var{obj}
2750 Return @code{#t} if @var{obj} is a channel.
2751 @end deffn
2752
2753 @deffn {Procedure} channel-get @var{channel}
2754 Retrieve a value from @var{channel}. The current script suspends
2755 until a value is available.
2756 @end deffn
2757
2758 @deffn {Procedure} channel-put @var{channel} @var{data}
2759 Send @var{data} to @var{channel}. The current script suspends until
2760 another script is available to retrieve the value.
2761 @end deffn
2762
2763 A low-level API also exists for using channels outside of a script via
2764 callback procedures:
2765
2766 @deffn {Procedure} channel-get! @var{channel} @var{proc}
2767 Asynchronously retrieve a value from @var{channel} and call @var{proc}
2768 with that value.
2769 @end deffn
2770
2771 @deffn {Procedure} channel-put! @var{channel} @var{data} [@var{thunk}]
2772 Asynchronously send @var{data} to @var{channel} and call @var{thunk}
2773 after it has been received.
2774 @end deffn