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