doc: Document the rectangle API.
[chickadee.git] / doc / api.texi
1 @menu
2 * Kernel:: The fundamental components.
3 * Math:: Linear algebra 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 * Matrices:: Transformation matrices.
367 * Quaternions:: Rotations about an arbitrary axis.
368 * Easings:: Easing functions for interesting animations.
369 @end menu
370
371 @node Basics
372 @subsection Basics
373
374 @defvar pi
375 An essential constant for all trigonometry. @code{@U{03C0}} is the ratio
376 of a circle's circumferences to its diameter. Since @code{@U{03C0}} is an
377 irrational number, the @var{pi} in Chickadee is a mere floating point
378 approximation that is ``good enough.''
379 @end defvar
380
381 @defvar pi/2
382 Half of @var{pi}.
383 @end defvar
384
385 @deffn {Procedure} cotan @var{z}
386 Return the cotangent of @var{z}.
387 @end deffn
388
389 @node Vectors
390 @subsection Vectors
391
392 Unlike Scheme's vector data type, which is a sequence of arbitrary
393 Scheme objects, Chickadee's @code{(chickadee math vector)} module
394 provides vectors in the linear algebra sense: Sequences of numbers
395 specialized for particular coordinate spaces. As of now, Chickadee
396 provides 2D and 3D vectors, with 4D vector support coming in a future
397 release.
398
399 Here's a quick example of adding two vectors:
400
401 @example
402 (define v (vec2+ (vec2 1 2) (vec2 3 4)))
403 @end example
404
405 Since vectors are used so frequently, the reader macro @code{#v} is
406 used to cut down on typing:
407
408 @example
409 (define v (vec2+ #v(1 2) #v(3 4)))
410 @end example
411
412 @subsubsection A Note About Performance
413
414 A lot of time has been spent making Chickadee's vector operations
415 perform relatively efficiently in critical code paths where excessive
416 garbage generation will cause major performance issues. The general
417 rule is that procedures ending with @code{!} perform an in-place
418 modification of one of the arguments in order to avoid allocating a
419 new vector. These procedures are also inlined by Guile's compiler in
420 order to take advantage of optimizations relating to floating point
421 math operations. The downside is that since these are not pure
422 functions, they do not compose well and create more verbose code.
423
424 @subsubsection 2D Vectors
425
426 @deffn {Procedure} vec2 @var{x} @var{y}
427 Return a new 2D vector with coordinates (@var{x}, @var{y}).
428 @end deffn
429
430 @deffn {Procedure} vec2/polar @var{r} @var{theta}
431 Return a new 2D vector containing the Cartesian representation of the
432 polar coordinate (@var{r}, @var{theta}). The angle @var{theta} is
433 measured in radians.
434 @end deffn
435
436 @deffn {Procedure} vec2? @var{obj}
437 Return @code{#t} if @var{obj} is a 2D vector.
438 @end deffn
439
440 @deffn {Procedure} vec2-x @var{v}
441 Return the X coordinate of the 2D vector @var{v}.
442 @end deffn
443
444 @deffn {Procedure} vec2-y @var{v}
445 Return the Y coordinate of the 2D vector @var{v}.
446 @end deffn
447
448 @deffn {Procedure} vec2-copy @var{v}
449 Return a fresh copy of the 2D vector @var{v}.
450 @end deffn
451
452 @deffn {Procedure} vec2-magnitude @var{v}
453 Return the magnitude of the 2D vector @var{v}.
454 @end deffn
455
456 @deffn {Procedure} vec2-dot-product @var{v1} @var{v2}
457 Return the dot product of the 2D vectors @var{v1} and @var{v2}.
458 @end deffn
459
460 @deffn {Procedure} vec2-normalize @var{v}
461 Return the normalized form of the 2D vector @var{v}.
462 @end deffn
463
464 @deffn {Procedure} vec2+ @var{v} @var{x}
465 Add @var{x}, either a 2D vector or a scalar (i.e. a real number), to
466 the 2D vector @var{v} and return a new vector containing the sum.
467 @end deffn
468
469 @deffn {Procedure} vec2- @var{v} @var{x}
470 Subtract @var{x}, either a 2D vector or a scalar, from the 2D vector
471 @var{v} and return a new vector containing the difference.
472 @end deffn
473
474 @deffn {Procedure} vec2* @var{v} @var{x}
475 Multiply the 2D vector @var{v} by @var{x}, a 2D vector or a scalar,
476 and return a new vector containing the product.
477 @end deffn
478
479 @deffn {Procedure} set-vec2-x! @var{v} @var{x}
480 Set the X coordinate of the 2D vector @var{v} to @var{x}.
481 @end deffn
482
483 @deffn {Procedure} set-vec2-y! @var{v} @var{y}
484 Set the Y coordinate of the 2D vector @var{v} to @var{y}.
485 @end deffn
486
487 @deffn {Procedure} vec2-copy! @var{source} @var{target}
488 Copy the 2D vector @var{source} into the 2D vector @var{target}.
489 @end deffn
490
491 @deffn {Procedure} vec2-add! @var{v} @var{x}
492 Perform an in-place modification of the 2D vector @var{v} by adding
493 @var{x}, a 2D vector or a scalar.
494 @end deffn
495
496 @deffn {Procedure} vec2-sub! @var{v} @var{x}
497 Perform an in-place modification of the 2D vector @var{v} by
498 subtracting @var{x}, a 2D vector or a scalar.
499 @end deffn
500
501 @deffn {Procedure} vec2-mult! @var{v} @var{x}
502 Perform an in-place modification of the 2D vector @var{v} by
503 multiplying it by @var{x}, a 2D vector or a scalar.
504 @end deffn
505
506 @subsubsection 3D Vectors
507
508 @deffn {Procedure} vec3 @var{x} @var{y}
509 Return a new 2D vector with coordinates (@var{x}, @var{y}).
510 @end deffn
511
512 @deffn {Procedure} vec3? @var{obj}
513 Return @code{#t} if @var{obj} is a 3D vector.
514 @end deffn
515
516 @deffn {Procedure} vec3-x @var{v}
517 Return the X coordinate of the 3D vector @var{v}.
518 @end deffn
519
520 @deffn {Procedure} vec3-y @var{v}
521 Return the Y coordinate of the 3D vector @var{v}.
522 @end deffn
523
524 @deffn {Procedure} vec3-z @var{v}
525 Return the Z coordinate of the 3D vector @var{v}.
526 @end deffn
527
528 @deffn {Procedure} vec3-copy @var{v}
529 Return a fresh copy of the 3D vector @var{v}.
530 @end deffn
531
532 @deffn {Procedure} vec3-magnitude @var{v}
533 Return the magnitude of the 3D vector @var{v}.
534 @end deffn
535
536 @deffn {Procedure} vec3-dot-product @var{v1} @var{v2}
537 Return the dot product of the 3D vectors @var{v1} and @var{v2}.
538 @end deffn
539
540 @deffn {Procedure} vec3-normalize @var{v}
541 Return the normalized form of the 3D vector @var{v}.
542 @end deffn
543
544 @deffn {Procedure} vec3+ @var{v} @var{x}
545 Add @var{x}, either a 3D vector or a scalar (i.e. a real number), to
546 the 3D vector @var{v} and return a new vector containing the sum.
547 @end deffn
548
549 @deffn {Procedure} vec3- @var{v} @var{x}
550 Subtract @var{x}, either a 3D vector or a scalar, from the 3D vector
551 @var{v} and return a new vector containing the difference.
552 @end deffn
553
554 @deffn {Procedure} vec3* @var{v} @var{x}
555 Multiply the 3D vector @var{v} by @var{x}, a 3D vector or a scalar,
556 and return a new vector containing the product.
557 @end deffn
558
559 @deffn {Procedure} set-vec3-x! @var{v} @var{x}
560 Set the X coordinate of the 3D vector @var{v} to @var{x}.
561 @end deffn
562
563 @deffn {Procedure} set-vec3-y! @var{v} @var{y}
564 Set the Y coordinate of the 3D vector @var{v} to @var{y}.
565 @end deffn
566
567 @deffn {Procedure} set-vec3-z! @var{v} @var{z}
568 Set the Z coordinate of the 3D vector @var{v} to @var{z}.
569 @end deffn
570
571 @deffn {Procedure} vec3-copy! @var{source} @var{target}
572 Copy the 3D vector @var{source} into the 3D vector @var{target}.
573 @end deffn
574
575 @deffn {Procedure} vec3-add! @var{v} @var{x}
576 Perform an in-place modification of the 3D vector @var{v} by adding
577 @var{x}, a 3D vector or a scalar.
578 @end deffn
579
580 @deffn {Procedure} vec3-sub! @var{v} @var{x}
581 Perform an in-place modification of the 3D vector @var{v} by
582 subtracting @var{x}, a 3D vector or a scalar.
583 @end deffn
584
585 @deffn {Procedure} vec3-mult! @var{v} @var{x}
586 Perform an in-place modification of the 3D vector @var{v} by
587 multiplying it by @var{x}, a 3D vector or a scalar.
588 @end deffn
589
590 @node Rectangles
591 @subsection Rectangles
592
593 The @code{(chickadee math rect)} module provides an API for
594 manipulating axis-aligned bounding boxes (AABBs). AABBs are often
595 used for collision detection in games. Common use-cases are defining
596 ``hitboxes'' in platformers or using them for the ``broad phase'' of a
597 collision detection algorithm that uses a more complex (and thus
598 slower) method of determining the actual collisions.
599
600 Like some of the other math modules, there exists a collection of
601 functions that do in-place modification of rectangles for use in
602 performance critical code paths.
603
604 @deffn {Procedure} make-rect @var{x} @var{y} @var{width} @var{height}
605 Create a new rectangle that is @var{width} by @var{height} in size and
606 whose bottom-left corner is located at (@var{x}, @var{y}).
607 @end deffn
608
609 @deffn {Procedure} rect? @var{obj}
610 Return @code{#t} if @var{obj} is a rectangle.
611 @end deffn
612
613 @deffn {Procedure} rect-within? @var{rect1} @var{rect2}
614 Return @code{#t} if @var{rect2} is completely within @var{rect1}.
615 @end deffn
616
617 @deffn {Procedure} rect-intersects? @var{rect1} @var{rect2}
618 Return @code{#t} if @var{rect2} overlaps @var{rect1}.
619 @end deffn
620
621 @deffn {Procedure} rect-contains? @var{rect} @var{x} @var{y}
622 Return @code{#t} if the coordinates (@var{x}, @var{y}) are within
623 @var{rect}.
624 @end deffn
625
626 @deffn {Procedure} rect-contains-vec2? @var{rect} @var{v}
627 Return @code{#t} if the 2D vector @var{v} is within the bounds of
628 @var{rect}.
629 @end deffn
630
631 @deffn {Procedure} rect-x @var{rect}
632 Return the X coordinate of the lower-left corner of @var{rect}.
633 @end deffn
634
635 @deffn {Procedure} rect-y @var{rect}
636 Return the Y coordinate of the lower-left corner of @var{rect}.
637 @end deffn
638
639 @deffn {Procedure} rect-left @var{rect}
640 Return the left-most X coordinate of @var{rect}.
641 @end deffn
642
643 @deffn {Procedure} rect-right @var{rect}
644 Return the right-most X coordinate of @var{rect}.
645 @end deffn
646
647 @deffn {Procedure} rect-bottom @var{rect}
648 Return the bottom-most Y coordinate of @var{rect}.
649 @end deffn
650
651 @deffn {Procedure} rect-top @var{rect}
652 Return the top-most Y coordinate of @var{rect}.
653 @end deffn
654
655 @deffn {Procedure} rect-center-x @var{rect}
656 Return the X coordinate of the center of @var{rect}.
657 @end deffn
658
659 @deffn {Procedure} rect-center-y @var{rect}
660 Return the Y coordinate of the center of @var{rect}.
661 @end deffn
662
663 @deffn {Procedure} rect-width @var{rect}
664 Return the width of @var{rect}.
665 @end deffn
666
667 @deffn {Procedure} rect-height @var{rect}
668 Return the height of @var{rect}.
669 @end deffn
670
671 @deffn {Procedure} rect-area @var{rect}
672 Return the surface area covered by @var{rect}.
673 @end deffn
674
675 @deffn {Procedure} rect-clamp-x @var{rect} @var{x}
676 Restrict @var{x} to the portion of the X axis covered by @var{rect}.
677 @end deffn
678
679 @deffn {Procedure} rect-clamp-y @var{rect} @var{y}
680 Restrict @var{y} to the portion of the Y axis covered by @var{rect}.
681 @end deffn
682
683 @deffn {Procedure} rect-clamp @var{rect1} @var{rect2}
684 Return a new rect that adjusts the location of @var{rect1} so that it
685 is completely within @var{rect2}. An exception is thrown in the case
686 that @var{rect1} cannot fit completely within @var{rect2}.
687 @end deffn
688
689 @deffn {Procedure} rect-move @var{rect} @var{x} @var{y}
690 Return a new rectangle based on @var{rect} but moved to the
691 coordinates (@var{x}, @var{y}).
692 @end deffn
693
694 @deffn {Procedure} rect-move-vec2 @var{rect} @var{v}
695 Return a new rectangle based on @var{rect} but moved to the
696 coordinates in the 2D vector @var{v}.
697 @end deffn
698
699 @deffn {Procedure} rect-move-by @var{rect} @var{x} @var{y}
700 Return a new rectangle based on @var{rect} but moved by (@var{x},
701 @var{y}) units relative to its current location.
702 @end deffn
703
704 @deffn {Procedure} rect-move-by-vec2 @var{rect} @var{v}
705 Return a new rectangle based on @var{rect} but moved by the 2D vector
706 @var{v} relative to its current location.
707 @end deffn
708
709 @deffn {Procedure} rect-inflate @var{rect} @var{width} @var{height}
710 Return a new rectangle based on @var{rect}, but expanded by
711 @var{width} units on the X axis and @var{height} units on the Y axis,
712 while keeping the rectangle centered on the same point.
713 @end deffn
714
715 @deffn {Procedure} rect-union @var{rect1} @var{rect2}
716 Return a new rectangle that completely covers the area of @var{rect1}
717 and @var{rect2}.
718 @end deffn
719
720 @deffn {Procedure} rect-clip @var{rect1} @var{rect2}
721 Return a new rectangle that is the overlapping region of @var{rect1}
722 and @var{rect2}. If the two rectangles do not overlap, a rectangle of
723 0 width and 0 height is returned.
724 @end deffn
725
726 @deffn {Procedure} set-rect-x! @var{rect} @var{x}
727 Set the left X coordinate of @var{rect} to @var{x}.
728 @end deffn
729
730 @deffn {Procedure} set-rect-y! @var{rect} @var{y}
731 Set the bottom Y coordinate of @var{rect} to @var{y}.
732 @end deffn
733
734 @deffn {Procedure} set-rect-width! @var{rect} @var{width}
735 Set the width of @var{rect} to @var{width}.
736 @end deffn
737
738 @deffn {Procedure} set-rect-height! @var{rect} @var{height}
739 Set the height of @var{rect} to @var{height}.
740 @end deffn
741
742 @deffn {Procedure} rect-move! @var{rect} @var{x} @var{y}
743 Move @var{rect} to (@var{x}, @var{y}) in-place.
744 @end deffn
745
746 @deffn {Procedure} rect-move-vec2! @var{rect} @var{v}
747 Move @var{rect} to the 2D vector @var{v} in-place.
748 @end deffn
749
750 @deffn {Procedure} rect-move-by! @var{rect} @var{x} @var{y}
751 Move @var{rect} by (@var{x}, @var{y}) in-place.
752 @end deffn
753
754 @deffn {Procedure} rect-move-by-vec2! @var{rect} @var{v}
755 Move @var{rect} by the 2D vector @var{v} in-place.
756 @end deffn
757
758 @deffn {Procedure} rect-inflate! @var{rect} @var{width} @var{height}
759 Expand @var{rect} by @var{width} and @var{height} in-place.
760 @end deffn
761
762 @deffn {Procedure} rect-union! @var{rect1} @var{rect2}
763 Modify @var{rect1} in-place to completely cover the area of both
764 @var{rect1} and @var{rect2}.
765 @end deffn
766
767 @deffn {Procedure} rect-clip! @var{rect1} @var{rect2}
768 Modify @var{rect1} in-place to be the overlapping region of
769 @var{rect1} and @var{rect2}.
770 @end deffn
771
772 @deffn {Procedure} rect-clamp! @var{rect1} @var{rect2}
773 Adjust the location of @var{rect1} in-place so that its bounds are
774 completely within @var{rect2}. An exception is thrown in the case
775 that @var{rect1} cannot fit completely within @var{rect2}.
776 @end deffn
777
778 @deffn {Procedure} vec2-clamp-to-rect! @var{v} @var{rect}
779 Restrict the coordinates of the 2D vector @var{v} so that they are
780 within the bounds of @var{rect}. @var{v} is modified in-place.
781 @end deffn
782
783 @node Matrices
784 @subsection Matrices
785
786 The @code{(chickadee math matrix)} module provides an interface for
787 working with the most common type of matrices in game development: 4x4
788 transformation matrices.
789
790 @subsubsection Another Note About Performance
791
792 Much like the vector API, the matrix API is commonly used in
793 performance critical code paths. In order to reduce the amount of
794 garbage generated and improve matrix multiplication performance, there
795 are many procedures that perform in-place modifications of matrix
796 objects.
797
798 @subsubsection Matrix Operations
799
800 @deffn {Procedure} make-matrix4 @var{aa} @var{ab} @var{ac} @var{ad} @
801 @var{ba} @var{bb} @var{bc} @var{bd} @
802 @var{ca} @var{cb} @var{cc} @var{cd} @
803 @var{da} @var{db} @var{dc} @var{dd}
804
805 Return a new 4x4 matrix initialized with the given 16 values in
806 column-major format.
807 @end deffn
808
809 @deffn {Procedure} make-null-matrix4
810 Return a new 4x4 matrix with all values initialized to 0.
811 @end deffn
812
813 @deffn {Procedure} make-identity-matrix4
814 Return a new 4x4 identity matrix. Any matrix multiplied by the
815 identity matrix yields the original matrix. This procedure is
816 equivalent to the following code:
817
818 @example
819 (make-matrix4 1 0 0 0
820 0 1 0 0
821 0 0 1 0
822 0 0 0 1)
823 @end example
824
825 @end deffn
826
827 @deffn {Procedure} matrix4? @var{obj}
828 Return @code{#t} if @var{obj} is a 4x4 matrix.
829 @end deffn
830
831 @deffn {Procedure} matrix4* . @var{matrices}
832 Return a new 4x4 matrix containing the product of multiplying all of
833 the given @var{matrices}.
834
835 Note: Remember that matrix multiplication is @strong{not} commutative!
836 @end deffn
837
838 @deffn {Procedure} orthographic-projection @var{left} @var{right} @
839 @var{top} @var{bottom} @
840 @var{near} @var{far}
841
842 Return a new 4x4 matrix that represents an orthographic (2D)
843 projection for the horizontal clipping plane @var{top} and
844 @var{bottom}, the vertical clipping plane @var{top} and @var{bottom},
845 and the depth clipping plane @var{near} and @var{far}.
846 @end deffn
847
848 @deffn {Procedure} perspective-projection @var{fov} @
849 @var{aspect-ratio} @
850 @var{near} @var{far}
851
852 Return a new 4x4 matrix that represents a perspective (3D) projection
853 with a field of vision of @var{fov} radians, an aspect ratio of
854 @var{aspect-ratio}, and a depth clipping plane defined by @var{near}
855 and @var{far}.
856 @end deffn
857
858 @deffn {Procedure} matrix4-translate @var{x}
859 Return a new 4x4 matrix that represents a translation by @var{x}, a 2D
860 vector, a 3D vector, or a rectangle (in which case the bottom-left
861 corner of the rectangle is used).
862 @end deffn
863
864 @deffn {Procedure} matrix4-scale @var{s}
865 Return a new 4x4 matrix that represents a scaling along the X, Y, and
866 Z axes by the scaling factor @var{s}, a real number.
867 @end deffn
868
869 @deffn {Procedure} matrix4-rotate @var{q}
870 Return a new 4x4 matrix that represents a rotation about an arbitrary
871 axis defined by the quaternion @var{q}.
872 @end deffn
873
874 @deffn {Procedure} matrix4-rotate-z @var{theta}
875 Return a new 4x4 matrix that represents a rotation about the Z axis by
876 @var{theta} radians.
877 @end deffn
878
879 @deffn {Procedure} matrix4-identity! @var{matrix}
880 Modify @var{matrix} in-place to contain the identity matrix.
881 @end deffn
882
883 @deffn {Procedure} matrix4-mult! @var{dest} @var{a} @var{b}
884 Multiply the 4x4 matrix @var{a} by the 4x4 matrix @var{b} and store
885 the result in the 4x4 matrix @var{dest}.
886 @end deffn
887
888 @deffn {Procedure} matrix4-translate! @var{matrix} @var{x}
889 Modify @var{matrix} in-place to contain a translation by @var{x}, a 2D
890 vector, a 3D vector, or a rectangle (in which case the bottom-left
891 corner of the rectangle is used).
892 @end deffn
893
894 @deffn {Procedure} matrix4-scale! @var{matrix} @var{s}
895 Modify @var{matrix} in-place to contain a scaling along the X, Y, and
896 Z axes by the scaling factor @var{s}, a real number.
897 @end deffn
898
899 @deffn {Procedure} matrix4-rotate! @var{matrix} @var{q}
900 Modify @var{matrix} in-place to contain a rotation about an arbitrary
901 axis defined by the quaternion @var{q}.
902 @end deffn
903
904 @deffn {Procedure} matrix4-rotate-z! @var{matrix} @var{theta}
905 Modify @var{matrix} in-place to contain a rotation about the Z axis by
906 @var{theta} radians.
907 @end deffn
908
909 @deffn {Procedure} matrix4-2d-transform! @var{matrix} [#:origin] @
910 [#:position] [#:rotation] @
911 [#:scale] [#:skew]
912
913 Modify @var{matrix} in-place to contain the transformation described
914 by @var{position}, a 2D vector or rectangle, @var{rotation}, a scalar
915 representing a rotation about the Z axis, @var{scale}, a 2D vector,
916 and @var{skew}, a 2D vector. The transformation happens with respect
917 to @var{origin}, a 2D vector. If an argument is not provided, that
918 particular transformation will not be included in the result.
919 @end deffn
920
921 @deffn {Procedure} transform! @var{matrix} @var{v}
922 Modify the 2D vector @var{v} in-place by multiplying it by the 4x4
923 matrix @var{matrix}.
924 @end deffn
925
926 @node Quaternions
927 @subsection Quaternions
928
929 In game development, the quaternion is most often used to represent
930 rotations. Why not use a matrix for that, you may ask. Unlike
931 matrices, quaternions can be interpolated (animated) and produce a
932 meaningful result. When interpolating two quaternions, there is a
933 smooth transition from one rotation to another, whereas interpolating
934 two matrices would yield garbage.
935
936 @deffn {Procedure} quaternion @var{x} @var{y} @var{z} @var{w}
937 Return a new quaternion with values @var{x}, @var{y}, @var{z}, and
938 @var{w}.
939 @end deffn
940
941 @deffn {Procedure} quaternion? @var{obj}
942 Return @code{#t} if @var{obj} is a quaternion.
943 @end deffn
944
945 @deffn {Procedure} quaternion-w @var{q}
946 Return the W component of the quaternion @var{q}.
947 @end deffn
948
949 @deffn {Procedure} quaternion-x @var{q}
950 Return the X component of the quaternion @var{q}.
951 @end deffn
952
953 @deffn {Procedure} quaternion-y @var{q}
954 Return the Y component of the quaternion @var{q}.
955 @end deffn
956
957 @deffn {Procedure} quaternion-z @var{q}
958 Return the Z component of the quaternion @var{q}.
959 @end deffn
960
961 @deffn {Procedure} make-identity-quaternion
962 Return the identity quaternion.
963 @end deffn
964
965 @node Easings
966 @subsection Easings
967
968 @deffn {Procedure} linear @var{t}
969 @end deffn
970
971 @deffn {Procedure} smoothstep @var{t}
972 @end deffn
973
974 @deffn {Procedure} ease-in-quad @var{t}
975 @end deffn
976
977 @deffn {Procedure} ease-out-quad @var{t}
978 @end deffn
979
980 @deffn {Procedure} ease-in-out-quad @var{t}
981 @end deffn
982
983 @deffn {Procedure} ease-in-cubic @var{t}
984 @end deffn
985
986 @deffn {Procedure} ease-out-cubic @var{t}
987 @end deffn
988
989 @deffn {Procedure} ease-in-out-cubic @var{t}
990 @end deffn
991
992 @deffn {Procedure} ease-in-quart @var{t}
993 @end deffn
994
995 @deffn {Procedure} ease-out-quart @var{t}
996 @end deffn
997
998 @deffn {Procedure} ease-in-out-quart @var{t}
999 @end deffn
1000
1001 @deffn {Procedure} ease-in-quint @var{t}
1002 @end deffn
1003
1004 @deffn {Procedure} ease-out-quint @var{t}
1005 @end deffn
1006
1007 @deffn {Procedure} ease-in-out-quint @var{t}
1008 @end deffn
1009
1010 @deffn {Procedure} ease-in-sine @var{t}
1011 @end deffn
1012
1013 @deffn {Procedure} ease-out-sine @var{t}
1014 @end deffn
1015
1016 @deffn {Procedure} ease-in-out-sine @var{t}
1017 @end deffn
1018
1019 @node Graphics
1020 @section Graphics
1021
1022 Chickadee aims to make hardware-accelerated graphics rendering as
1023 simple and efficient as possible by providing high-level APIs that
1024 interact with the low-level OpenGL API under the hood. Anyone that
1025 has worked with OpenGL directly knows that it has a steep learning
1026 curve and a lot of effort is needed to render even a single triangle.
1027 The Chickadee rendering engine attempts to make it easy to do common
1028 tasks like rendering a sprite while also providing all of the building
1029 blocks to implement additional rendering techniques.
1030
1031 @menu
1032 * Rendering Engine:: Rendering state management.
1033 * Textures:: 2D images.
1034 * Sprites:: Draw 2D images.
1035 * Tile Maps:: Draw 2D tile maps.
1036 * Lines and Shapes:: Draw line segments and polygons.
1037 * Fonts:: Drawing text.
1038 * Blending and Depth Testing:: Control how pixels are combined.
1039 * Vertex Arrays:: Create 2D/3D models.
1040 * Shaders:: Create custom GPU programs.
1041 * Framebuffers:: Render to texture.
1042 * Viewports:: Restrict rendering to
1043 @end menu
1044
1045 @node Rendering Engine
1046 @subsection Rendering Engine
1047
1048 Chickadee defines rendering using a metaphor familiar to Scheme
1049 programmers: procedure application. A shader (@pxref{Shaders}) is
1050 like a procedure for the GPU to apply. Shaders are passed arguments:
1051 A vertex array containing the geometry to render (@pxref{Vertex
1052 Arrays}) and zero or more keyword arguments that the shader
1053 understands. Similar to how Scheme has @code{apply} for calling
1054 procedures, Chickadee provides @code{gpu-apply} for calling shaders.
1055
1056 Additionally, there is some dynamic state that effects how
1057 @code{gpu-apply} will behave. Things like the current viewport,
1058 framebuffer, and blend mode are stored as dynamic state because it
1059 would be tedious to have to have to specify them each time
1060 @code{gpu-apply} is called.
1061
1062 The following procedures and syntax can be found in the
1063 @code{(chickadee render)} module.
1064
1065 @deffn {Syntax} gpu-apply @var{shader} @var{vertex-array} @
1066 [#:uniform-key @var{uniform-value} ...]
1067 @deffnx {Syntax} gpu-apply* @var{shader} @var{vertex-array} @
1068 @var{count} [#:uniform-key @var{uniform-value} ...]
1069
1070 Render @var{vertex-array} using @var{shader} with the uniform values
1071 specified in the following keyword arguments.
1072
1073 While @code{gpu-apply} will draw every vertex in @var{vertex-array},
1074 @code{gpu-apply*} will only draw @var{count} vertices.
1075
1076 @end deffn
1077
1078 @deffn {Procedure} current-viewport
1079 Return the currently bound viewport (@pxref{Viewports}).
1080 @end deffn
1081
1082 @deffn {Procedure} current-framebuffer
1083 Return the currently bound framebuffer (@pxref{Framebuffers}).
1084 @end deffn
1085
1086 @deffn {Procedure} current-blend-mode
1087 Return the currently bound blend mode (@pxref{Blending and Depth
1088 Testing}).
1089 @end deffn
1090
1091 @deffn {Procedure} current-depth-test
1092 Return @code{#t} if depth testing is currently enabled (@pxref{Blending and Depth Testing}).
1093 @end deffn
1094
1095 @deffn {Procedure} current-texture
1096 Return the currently bound texture (@pxref{Textures}).
1097 @end deffn
1098
1099 @deffn {Procedure} current-projection
1100 Return the currently bound projection matrix (@pxref{Matrices}).
1101 @end deffn
1102
1103 @deffn {Syntax} with-viewport @var{viewport} @var{body} ...
1104 Evaluate @var{body} with the current viewport bound to @var{viewport} (@pxref{Viewports}).
1105 @end deffn
1106
1107 @deffn {Syntax} with-framebuffer @var{framebuffer} @var{body} ...
1108 Evaluate @var{body} with the current framebuffer bound to
1109 @var{framebuffer} (@pxref{Framebuffers}).
1110 @end deffn
1111
1112 @deffn {Syntax} with-blend-mode @var{blend-mode} @var{body} ...
1113 Evaluate @var{body} with the current blend mode bound to
1114 @var{blend-mode} (@pxref{Blending and Depth Testing}).
1115 @end deffn
1116
1117 @deffn {Syntax} with-depth-test @var{depth-test?} @var{body} ...
1118 Evaluate @var{body} with the depth-test disabled if @var{depth-test?}
1119 is @code{#f}, or enabled otherwise (@pxref{Blending and Depth
1120 Testing}).
1121 @end deffn
1122
1123 @deffn {Syntax} with-texture @var{texture} @var{body} ...
1124 Evaluate @var{body} with the current texture bound to @var{texture}
1125 (@pxref{Textures}).
1126 @end deffn
1127
1128 @deffn {Syntax} with-projection @var{projection} @var{body} ...
1129 Evaluate @var{body} with the current projection matrix bound to
1130 @var{projection} (@pxref{Matrices}).
1131 @end deffn
1132
1133 @node Textures
1134 @subsection Textures
1135
1136 @deffn {Procedure} load-image @var{file} [#:min-filter nearest] @
1137 [#:mag-filter nearest] [#:wrap-s repeat] [#:wrap-t repeat]
1138
1139 Load the image data from @var{file} and return a new texture object.
1140
1141 @var{min-filter} and @var{mag-filter} describe the method that should
1142 be used for minification and magnification when rendering,
1143 respectively. Possible values are @code{nearest} and @code{linear}.
1144
1145 @var{wrap-s} and @var{wrap-t} describe how to interpret texture
1146 coordinates that are greater than @code{1.0}. Possible values are
1147 @code{repeat}, @code{clamp}, @code{clamp-to-border}, and
1148 @code{clamp-to-edge}.
1149
1150 @end deffn
1151
1152 @node Sprites
1153 @subsection Sprites
1154
1155 For those who are new to this game, a sprite is a 2D rectangular
1156 bitmap that is rendered to the screen. For 2D games, sprites are the
1157 most essential graphical abstraction. They are used for drawing maps,
1158 players, NPCs, items, particles, text, etc. In Chickadee, bitmaps are
1159 stored in textures (@pxref{Textures}) and can be used to draw sprites
1160 via the @code{draw-sprite} procedure.
1161
1162 @deffn {Procedure} draw-sprite @var{texture} @var{position} @
1163 [#:origin] [#:scale] [#:rotation] [#:blend-mode alpha] @
1164 [#:rect] [#:shader]
1165
1166 Draw @var{texture} at @var{position}.
1167
1168 Optionally, other transformations may be applied to the sprite.
1169 @var{rotation} specifies the angle to rotate the sprite, in radians.
1170 @var{scale} specifies the scaling factor as a 2D vector. All
1171 transformations are applied relative to @var{origin}, a 2D vector,
1172 which defaults to the lower-left corner.
1173
1174 Alpha blending is used by default but the blending method can be
1175 changed by specifying @var{blend-mode}.
1176
1177 The area drawn to is as big as the texture, by default. To draw to an
1178 arbitrary section of the screen, specify @var{rect}.
1179
1180 Finally, advanced users may specify @var{shader} to change the way the
1181 sprite is rendered entirely.
1182 @end deffn
1183
1184 It's not uncommon to need to draw hundreds or thousands of sprites
1185 each frame. However, GPUs (graphics processing units) are tricky
1186 beasts that prefer to be sent few, large chunks of data to render
1187 rather than many, small chunks. Using @code{draw-sprite} on its own
1188 will involve at least one GPU call @emph{per sprite}, which will
1189 quickly lead to poor performance. To deal with this, a technique
1190 known as ``sprite batching'' can be used. Instead of drawing each
1191 sprite immediately, the sprite batch will build up a large of buffer
1192 of sprites to draw and defer rendering until the last possible moment.
1193 Batching isn't a panacea, though. Batching only works if the sprites
1194 being drawn share as much in common as possible. Every time you draw
1195 a sprite with a different texture or blend mode, the batch will be
1196 sent off to the GPU. Therefore, batching is most useful if you
1197 minimize such changes. A good strategy for reducing texture changes
1198 is to stuff many bitmaps into a single image file and create a
1199 ``texture atlas'' (@pxref{Textures}) to access the sub-images within.
1200
1201 Taking advantage of sprite batching in Chickadee is easy, just wrap
1202 the code that is calling @code{draw-sprite} a lot in the
1203 @code{with-batched-sprites} form.
1204
1205 @deffn {Syntax} with-batched-sprites @var{body} @dots{}
1206 Use batched rendering for all @code{draw-sprite} calls within
1207 @var{body}.
1208 @end deffn
1209
1210 With a basic sprite abstraction in place, it's possible to build other
1211 abstractions on top of it. One such example is the ``nine patch''. A
1212 nine patch is a sprite that can be rendered at various sizes without
1213 becoming distorted. This is achieved by diving up the sprite into
1214 nine regions:
1215
1216 @itemize
1217 @item
1218 the center, which can be scaled horizontally and vertically
1219 @item
1220 the four corners, which can never be scaled
1221 @item
1222 the left and right sides, which can be scaled vertically
1223 @item
1224 the top and bottom sides, which can be scaled horizontally
1225 @end itemize
1226
1227 The one caveat is that the bitmap regions must be designed in such a
1228 way so that they are not distorted when stretched along the affected
1229 axes. For example, that means that the top and bottom sides could
1230 have varying colored pixels vertically, but not horizontally.
1231
1232 The most common application of this technique is for graphical user
1233 interface widgets like buttons and dialog boxes. By using a nine
1234 patch, they can be rendered at any size without unappealing scaling
1235 artifacts.
1236
1237 @deffn {Procedure} draw-nine-patch @var{texture} @var{rect} @
1238 [#:margin 0] [#:top-margin margin] [#:bottom-margin margin] @
1239 [#:left-margin margin] [#:right-margin margin] @
1240 [#:origin] [#:scale] [#:rotation] [#:blend-mode alpha] @
1241 [#:shader]
1242
1243 Draw a nine patch sprite. A nine patch sprite renders @var{texture}
1244 as a @var{width} x @var{height} rectangle whose stretchable areas are
1245 defined by the given margin measurements @var{top-margin},
1246 @var{bottom-margin}, @var{left-margin}, and @var{right-margin}. The
1247 @var{margin} argument may be used to configure all four margins at
1248 once.
1249
1250 Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
1251 the other arguments.
1252 @end deffn
1253
1254 @node Tile Maps
1255 @subsection Tile Maps
1256
1257 A tile map is a scene created by composing lots of small sprites,
1258 called ``tiles'', into a larger image. One program for editing such
1259 maps is called @url{http://mapeditor.org,Tiled}. Chickadee has native
1260 support for loading and rendering Tiled maps in the @code{(chickadee
1261 render tiled)} module.
1262
1263 @deffn {Procedure} load-tile-map @var{file-name}
1264 Load the Tiled formatted map in @var{file-name} and return a new tile
1265 map object.
1266 @end deffn
1267
1268 @deffn {Procedure} draw-tile-map @var{tile-map} [#:layers] [#:region] @
1269 [#:origin] [#:position] [#:scale] [#:rotation]
1270
1271 Draw the layers of @var{tile-map}. By default, all layers are drawn.
1272 To draw a subset of the available layers, pass a list of layer ids
1273 using the @var{layers} keyword argument.
1274
1275 Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
1276 the other arguments.
1277 @end deffn
1278
1279 @node Lines and Shapes
1280 @subsection Lines and Shapes
1281
1282 Sprites are fun, but sometimes simple, untextured lines and polygons
1283 are desired. That's where the @code{(chickadee render shapes)} module
1284 comes in!
1285
1286 @deffn {Procedure} draw-line @var{start} @var{end} @
1287 [#:thickness 0.5] [#:feather 1.0] [#:cap round] [#:color] @
1288 [#:shader]
1289
1290 Draw a line segment from @var{start} to @var{end}. The line will be
1291 @var{thickness} pixels thick with an antialiased border @var{feather}
1292 pixels wide. The line will be colored @var{color}. @var{cap}
1293 specifies the type of end cap that should be used to terminate the
1294 lines, either @code{none}, @code{butt}, @code{square}, @code{round},
1295 @code{triangle-in}, or @code{triangle-out}. Advanced users may use
1296 the @var{shader} argument to override the built-in line segment
1297 shader.
1298 @end deffn
1299
1300 @node Fonts
1301 @subsection Fonts
1302
1303 Unlike the traditional TrueType font format that many are accustomed
1304 to, Chickadee loads and renders bitmap fonts in the
1305 @url{http://www.angelcode.com/products/bmfont/doc/file_format.html,
1306 Angel Code format}. But why use this seemingly obscure format? It's
1307 easy to find TTFs but not easy to find FNTs (the canonical file
1308 extension used for Angel Code fonts) and bitmap fonts don't scale
1309 well. The reason is efficiency.
1310
1311 If all of the glyphs of a font are pre-rendered and packed into an
1312 image file then it becomes possible to use a texture atlas
1313 (@pxref{Textures}) and a sprite batch (@pxref{Sprites}) when
1314 rendering, which is a more efficient way to render fonts than using,
1315 say, @url{https://www.libsdl.org/projects/SDL_ttf/, SDL_ttf} or other
1316 solutions that involve using the FreeType library directly.
1317
1318 Now what about scaling? In libraries that use TTF fonts, one must
1319 choose the size that the glyphs will be rasterized at up front. To
1320 use @code{n} sizes of the same font, one must load @code{n} variants
1321 of that font. If the size of the text is dynamic, some kind of
1322 texture scaling algorithm must be used and the text will inevitably
1323 look blurry. At first glance, using bitmap fonts seem to have an even
1324 worse issue. Instead of just loading the same font @code{n} times at
1325 different sizes, one would need to generate @code{n} image files for
1326 each font size needed. This is where the ``signed distance field''
1327 rendering technique comes in. Introduced by
1328 @url{http://www.valvesoftware.com/.../2007/SIGGRAPH2007_AlphaTestedMagnification.pdf,
1329 Valve} in 2007, signed distance field fonts can be efficiently stored
1330 in a bitmap and be rendered at arbitrary scale factors with good
1331 results.
1332
1333 While Chickadee does not yet offer a tool for converting TTF fonts
1334 into FNT fonts, tools such as
1335 @url{https://github.com/libgdx/libgdx/wiki/Hiero, Hiero} may be used
1336 in the meantime.
1337
1338 The following procedures can be found in the @code{(chickadee render
1339 font)} module.
1340
1341 @deffn {Procedure} load-font @var{file}
1342 Load the Angel Code formatted XML document in @var{file} and return a
1343 new font object.
1344 @end deffn
1345
1346 @deffn {Procedure} font? @var{obj}
1347 Return @code{#t} if @var{obj} is a font object.
1348 @end deffn
1349
1350 @deffn {Procedure} font-face @var{font}
1351 Return the name of @var{font}.
1352 @end deffn
1353
1354 @deffn {Procedure} font-line-height @var{font}
1355 Return the line height of @var{font}.
1356 @end deffn
1357
1358 @deffn {Procedure} font-line-height @var{font}
1359 Return the line height of @var{font}.
1360 @end deffn
1361
1362 @deffn {Procedure} font-bold? @var{font}
1363 Return @code{#t} if @var{font} is a bold font.
1364 @end deffn
1365
1366 @deffn {Procedure} font-italic? @var{font}
1367 Return @code{#t} if @var{font} is an italicized font.
1368 @end deffn
1369
1370 @deffn {Procedure} draw-text @var{font} @var{text} @var{position}
1371 [#:origin] [#:scale] [#:rotation] [#:blend-mode]
1372 [#:start 0] [#:end @code{(string-length text)}]
1373
1374 Draw the string @var{text} with the first character starting at
1375 @var{position} using @var{font}.
1376
1377 @example
1378 (draw-text font "Hello, world!" (vec2 128.0 128.0))
1379 @end example
1380
1381 To render a substring of @var{text}, use the @var{start} and @var{end}
1382 arguments.
1383
1384 Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
1385 the other arguments.
1386 @end deffn
1387
1388 @node Blending and Depth Testing
1389 @subsection Blending and Depth Testing
1390
1391 @node Vertex Arrays
1392 @subsection Vertex Arrays
1393
1394 @node Shaders
1395 @subsection Shaders
1396
1397 Shaders are programs for the GPU to evaluate. They are written in the
1398 OpenGL Shading Language, or GLSL. Chickadee does not currently
1399 provide a Scheme-like domain specific language for writing shaders.
1400 Since shaders must be written in GLSL and not Scheme, they are
1401 considered an advanced feature.
1402
1403 @node Framebuffers
1404 @subsection Framebuffers
1405
1406 A framebuffer is a chunk of memory that the GPU can render things
1407 onto. By default, the framebuffer that is used for rendering is the
1408 one belonging to the game window, but custom framebuffers can be used
1409 as well. A common use-case for custom framebuffers is applying
1410 post-processing effects: The entire scene is rendered to a
1411 framebuffer, and then the contents of that framebuffer are applied to
1412 a post-processing shader and rendered to the game window. The
1413 post-processing shader could do any number of things: scaling,
1414 antialiasing, motion blur, etc.
1415
1416 @deffn {Procedure} make-framebuffer @var{width} @var{height} [#:min-filter 'linear] [#:mag-filter 'linear] [#:wrap-s 'repeat] [#:wrap-t 'repeat]
1417
1418 Create a new framebuffer that is @var{width} pixels wide and @var{height} pixels high.
1419
1420 @var{min-filter} and @var{mag-filter} determine the scaling algorithm
1421 applied to the framebuffer when rendering. By default, linear scaling
1422 is used in both cases. To perform no smoothing at all, use
1423 @code{nearest} for simple nearest neighbor scaling. This is typically
1424 the best choice for pixel art games.
1425 @end deffn
1426
1427 @deffn {Procedure} framebuffer? @var{obj}
1428 Return @code{#t} if @var{obj} is a framebuffer.
1429 @end deffn
1430
1431 @deffn {Procedure} framebuffer-texture @var{fb}
1432 Return the texture backing the framebuffer @var{fb}.
1433 @end deffn
1434
1435 @deffn {Procedure} framebuffer-viewport @var{fb}
1436 Return the default viewport (@pxref{Viewports}) used by the
1437 framebuffer @var{fb}.
1438 @end deffn
1439
1440 @deffn {Procedure} null-framebuffer
1441 The default framebuffer.
1442 @end deffn
1443
1444 @node Viewports
1445 @subsection Viewports
1446
1447 @node Scripting
1448 @section Scripting
1449
1450 Game logic is a web of asynchronous events that are carefully
1451 coordinated to bring the game world to life. In order to make an
1452 enemy follow and attack the player, or move an NPC back and forth in
1453 front of the item shop, or do both at the same time, a scripting
1454 system is a necessity. Chickadee comes with an asynchronous
1455 programming system in the @code{(chickadee scripting)} module.
1456 Lightweight, cooperative threads known as ``scripts'' allow the
1457 programmer to write asynchronous code as if it were synchronous, and
1458 allow many such ``threads'' to run concurrently.
1459
1460 But before we dig deeper into scripts, let's discuss the simple act
1461 of scheduling tasks.
1462
1463 @menu
1464 * Agendas:: Scheduling tasks.
1465 * Scripts:: Cooperative multitasking.
1466 * Tweening:: Animations.
1467 * Channels:: Publish data to listeners.
1468 @end menu
1469
1470 @node Agendas
1471 @subsection Agendas
1472
1473 To schedule a task to be performed later, an ``agenda'' is used.
1474 There is a default, global agenda that is ready to be used, or
1475 additional agendas may be created for different purposes. The
1476 following example prints the text ``hello'' when the agenda has
1477 advanced to time unit 10.
1478
1479 @example
1480 (at 10 (display "hello\n"))
1481 @end example
1482
1483 Most of the time it is more convenient to schedule tasks relative to
1484 the current time. This is where @code{after} comes in handy:
1485
1486 @example
1487 (after 10 (display "hello\n"))
1488 @end example
1489
1490 Time units in the agenda are in no way connected to real time. It's
1491 up to the programmer to decide what agenda time means. A simple and
1492 effective approach is to map each call of the update hook
1493 (@pxref{Kernel}) to 1 unit of agenda time, like so:
1494
1495 @example
1496 (add-hook! update-hook (lambda (dt) (update-agenda 1)))
1497 @end example
1498
1499 It is important to call @code{update-agenda} periodically, otherwise
1500 no tasks will ever be run!
1501
1502 In addition to using the global agenda, it is useful to have multiple
1503 agendas for different purposes. For example, the game world can use a
1504 different agenda than the user interface, so that pausing the game is
1505 a simple matter of not updating the world's agenda while continuing to
1506 update the user interface's agenda. The current agenda is dynamically
1507 scoped and can be changed using the @code{with-agenda} special form:
1508
1509 @example
1510 (define game-world-agenda (make-agenda))
1511
1512 (with-agenda game-world-agenda
1513 (at 60 (spawn-goblin))
1514 (at 120 (spawn-goblin))
1515 (at 240 (spawn-goblin-king)))
1516 @end example
1517
1518 @deffn {Procedure} make-agenda
1519 Return a new task scheduler.
1520 @end deffn
1521
1522 @deffn {Procedure} agenda? @var{obj}
1523 Return @code{#t} if @var{obj} is an agenda.
1524 @end deffn
1525
1526 @deffn {Procedure} current-agenda
1527 @deffnx {Procedure} current-agenda @var{agenda}
1528 When called with no arguments, return the current agenda. When called
1529 with one argument, set the current agenda to @var{agenda}.
1530 @end deffn
1531
1532 @deffn {Syntax} with-agenda @var{agenda} @var{body} @dots{}
1533 Evaluate @var{body} with the current agenda set to @var{agenda}.
1534 @end deffn
1535
1536 @deffn {Procedure} agenda-time
1537 Return the current agenda time.
1538 @end deffn
1539
1540 @deffn {Procedure} update-agenda @var{dt}
1541 Advance the current agenda by @var{dt}.
1542 @end deffn
1543
1544 @deffn {Procedure} schedule-at @var{time} @var{thunk}
1545 Schedule @var{thunk}, a procedure of zero arguments, to be run at
1546 @var{time}.
1547 @end deffn
1548
1549 @deffn {Procedure} schedule-after @var{delay} @var{thunk}
1550 Schedule @var{thunk}, a procedure of zero arguments, to be run after
1551 @var{delay}.
1552 @end deffn
1553
1554 @deffn {Procedure} schedule-every @var{interval} @var{thunk} [@var{n}]
1555 Schedule @var{thunk}, a procedure of zero arguments, to be run every
1556 @var{interval} amount of time. Repeat this @var{n} times, or
1557 indefinitely if not specified.
1558 @end deffn
1559
1560 @deffn {Syntax} at @var{time} @var{body} @dots{}
1561 Schedule @var{body} to be evaluated at @var{time}.
1562 @end deffn
1563
1564 @deffn {Syntax} after @var{delay} @var{body} @dots{}
1565 Schedule @var{body} to be evaluated after @var{delay}.
1566 @end deffn
1567
1568 @deffn {Syntax} every @var{interval} @var{body} @dots{}
1569 @deffnx {Syntax} every (@var{interval} @var{n}) @var{body} @dots{}
1570 Schedule @var{body} to be evaluated every @var{interval} amount of
1571 time. Repeat this @var{n} times, or indefinitely if not specified.
1572 @end deffn
1573
1574 @node Scripts
1575 @subsection Scripts
1576
1577 Now that we can schedule tasks, let's take things to the next level.
1578 It sure would be great if we could make procedures that described a
1579 series of actions that happened over time, especially if we could do
1580 so without contorting our code into a nest of callback procedures.
1581 This is where scripts come in. With scripts we can write code in a
1582 linear way, in a manner that appears to be synchronous, but with the
1583 ability to suspend periodically in order to let other scripts have a
1584 turn and prevent blocking the game loop. Building on top of the
1585 scheduling that agendas provide, here is a script that models a child
1586 trying to get their mother's attention:
1587
1588 @example
1589 (script
1590 (while #t
1591 (display "mom!")
1592 (newline)
1593 (sleep 60))) ; where 60 = 1 second of real time
1594 @end example
1595
1596 This code runs in an endless loop, but the @code{sleep} procedure
1597 suspends the script and schedules it to be run later by the agenda.
1598 So, after each iteration of the loop, control is returned back to the
1599 game loop and the program is not stuck spinning in a loop that will
1600 never exit. Pretty neat, eh?
1601
1602 Scripts can suspend to any capable handler, not just the agenda.
1603 The @code{yield} procedure will suspend the current script and pass
1604 its ``continuation'' to a handler procedure. This handler procedure
1605 could do anything. Perhaps the handler stashes the continuation
1606 somewhere where it will be resumed when the user presses a specific
1607 key on the keyboard, or maybe it will be resumed when the player picks
1608 up an item off of the dungeon floor; the sky is the limit.
1609
1610 Sometimes it is necessary to abruptly terminate a script after it has
1611 been started. For example, when an enemy is defeated their AI routine
1612 needs to be shut down. When a script is spawned, a handle to that
1613 script is returned that can be used to cancel it when desired.
1614
1615 @example
1616 (define script (script (while #t (display "hey\n") (sleep 60))))
1617 ;; sometime later
1618 (cancel-script script)
1619 @end example
1620
1621 @deffn {Procedure} spawn-script @var{thunk}
1622 Apply @var{thunk} as a script and return a handle to it.
1623 @end deffn
1624
1625 @deffn {Syntax} script @var{body} @dots{}
1626 Evaluate @var{body} as a script and return a handle to it.
1627 @end deffn
1628
1629 @deffn {Procedure} script? @var{obj}
1630 Return @code{#t} if @var{obj} is a script handle.
1631 @end deffn
1632
1633 @deffn {Procedure} script-cancelled? @var{obj}
1634 Return @code{#t} if @var{obj} has been cancelled.
1635 @end deffn
1636
1637 @deffn {Procedure} script-running? @var{obj}
1638 Return @code{#t} if @var{obj} has not yet terminated or been
1639 cancelled.
1640 @end deffn
1641
1642 @deffn {Procedure} script-complete? @var{obj}
1643 Return @code{#t} if @var{obj} has terminated.
1644 @end deffn
1645
1646 @deffn {Procedure} cancel-script @var{co}
1647 Prevent further execution of the script @var{co}.
1648 @end deffn
1649
1650 @deffn {Procedure} yield @var{handler}
1651 Suspend the current script and pass its continuation to the
1652 procedure @var{handler}.
1653 @end deffn
1654
1655 @deffn {Procedure} sleep @var{duration}
1656 Wait @var{duration} before resuming the current script.
1657 @end deffn
1658
1659 @deffn {Procedure} channel-get @var{channel}
1660 Wait for a message from @var{channel}.
1661 @end deffn
1662
1663 @deffn {Syntax} forever @var{body} @dots{}
1664 Evaluate @var{body} in an endless loop.
1665 @end deffn
1666
1667 @node Tweening
1668 @subsection Tweening
1669
1670 Tweening is the process of transitioning something from an initial
1671 state to a final state over a pre-determined period of time. In other
1672 words, tweening is a way to create animation. The @code{tween}
1673 procedure can be used within any script like so:
1674
1675 @example
1676 (define x 0)
1677 (script
1678 ;; 0 to 100 in 60 ticks of the agenda.
1679 (tween 60 0 100 (lambda (y) (set! x y))))
1680 @end example
1681
1682 @deffn {Procedure} tween @var{duration} @var{start} @var{end} @var{proc} [#:step 1 #:ease @code{smoothstep} #:interpolate @code{lerp}]
1683 Transition a value from @var{start} to @var{end} over @var{duration},
1684 sending each succesive value to @var{proc}. @var{step} controls the
1685 amount of time between each update of the animation.
1686
1687 To control how the animation goes from the initial to final state, an
1688 ``easing'' procedure may be specified. By default, the
1689 @code{smoothstep} easing is used, which is a more pleasing default
1690 than a simplistic linear function. @xref{Easings} for a complete list
1691 of available easing procedures.
1692
1693 The @var{interpolate} procedure computes the values in between
1694 @var{start} and @var{end}. By default, linear interpolation (``lerp''
1695 for short) is used.
1696 @end deffn
1697
1698 @node Channels
1699 @subsection Channels
1700
1701 Channels are a tool for communicating amongst different scripts. One
1702 script can write a value to the channel and another can read from it.
1703 Reading or writing to a channel suspends that script until there is
1704 someone on the other end of the line to complete the transaction.
1705
1706 Here's a simplistic example:
1707
1708 @example
1709 (define c (make-channel))
1710
1711 (script
1712 (forever
1713 (let ((item (channel-get c)))
1714 (pk 'got item))))
1715
1716 (script
1717 (channel-put c 'sword)
1718 (channel-put c 'shield)
1719 (channel-put c 'potion))
1720 @end example
1721
1722 @deffn {Procedure} make-channel
1723 Return a new channel
1724 @end deffn
1725
1726 @deffn {Procedure} channel? @var{obj}
1727 Return @code{#t} if @var{obj} is a channel.
1728 @end deffn
1729
1730 @deffn {Procedure} channel-get @var{channel}
1731 Retrieve a value from @var{channel}. The current script suspends
1732 until a value is available.
1733 @end deffn
1734
1735 @deffn {Procedure} channel-put @var{channel} @var{data}
1736 Send @var{data} to @var{channel}. The current script suspends until
1737 another script is available to retrieve the value.
1738 @end deffn