render: Refactor sprite rendering.
[chickadee.git] / doc / api.texi
1 @menu
2 * Kernel:: The fundamental components.
3 * Input:: Keyboard, mouse, and controller input.
4 * Math:: Linear algebra and more.
5 * Graphics:: Eye candy.
6 * Audio:: Sound effects and music.
7 * Buffers:: Splitting games into logical components.
8 * Scripting:: Bringing the game world to life.
9 @end menu
10
11 @node Kernel
12 @section Kernel
13
14 At the very core of Chickadee, in the @code{(chickadee)} module, lies
15 an event loop. This loop, or ``kernel'', is responsible for creating
16 and managing the game window, dispatching input events, ensuring that
17 the game is updated at the desired interval, and rendering graphics.
18 The kernel implements what is known as a ``fixed timestep'' game loop,
19 meaning that the game simulation will be advanced by a fixed interval
20 of time and will never vary from frame to frame, unlike some other
21 styles of game loops. The appropriately named @code{run-game} and
22 @code{abort-game} procedures are the entry and exit points to the
23 Chickadee kernel.
24
25 On its own, the kernel does not do very much at all. In order to
26 actually respond to input events, update game state, or draw something
27 to the game window, a hacker with a penchant for game development must
28 latch onto extension points built into the kernel, called ``hooks'',
29 and specify what action ought to be taken for any given event. For
30 example, the @code{key-press-hook} can be used to respond to the
31 @code{a} key being pressed by swinging the player's mighty sword.
32 There are many hooks available, so read on to learn about all of them.
33 For information about using Guile's hook API, see @xref{Hooks,,,
34 guile, GNU Guile Reference Manual}.
35
36 @deffn {Procedure} run-game [#:window-title "Chickadee!"] @
37 [#:window-width 640] [#:window-height 480] [#:window-fullscreen? #f] @
38 [#:update-hz 60]
39
40 Start the event loop. This procedure will not return until
41 @code{abort-game} is called.
42
43 The @code{update-hook} will be run @var{update-hz} times per second.
44
45 A new graphical window will be opened with @var{window-width} x
46 @var{window-height} as its dimensions, @var{window-title} as its
47 title, and in fullscreen mode if @var{window-fullscreen?} is
48 @code{#t}.
49 @end deffn
50
51 @deffn {Procedure} abort-game
52 Stop the currently running Chickadee event loop.
53 @end deffn
54
55 @deffn {Procedure} time
56 Return the current game time in milliseconds.
57 @end deffn
58
59 @defvr {Variable} load-hook
60 A hook that is run once when the event loop boots, before any other
61 hook is run. This hook is run with zero arguments.
62
63 @example
64 (add-hook! load-hook (lambda () (display "hello!\n")))
65 @end example
66
67 @end defvr
68
69 @defvr {Variable} update-hook
70 A hook that is run every time the game simulation should be advanced.
71 This hook is run with a single argument @var{dt}, the fixed timestep
72 that was configured when the event loop was started, in milliseconds.
73
74 @example
75 (add-hook! update-hook (lambda (dt) (display "tick!\n")))
76 @end example
77
78 @end defvr
79
80 @defvr {Variable} before-draw-hook
81 A hook that is run before a frame is rendered. This hook is run with
82 zero arguments.
83
84 @example
85 (add-hook! before-draw-hook (lambda () (display "about to draw!\n")))
86 @end example
87
88 @end defvr
89
90 @defvr {Variable} after-draw-hook
91 A hook that is run after a frame is rendered. This hook is run with
92 zero arguments.
93
94 @example
95 (add-hook! after-draw-hook (lambda () (display "done drawing!\n")))
96 @end example
97
98 Combined with @code{before-draw-hook}, one can perform a frames per
99 second calculation to monitor game performance and stability.
100
101 @end defvr
102
103 @defvr {Variable} draw-hook
104 A hook that is run each time a frame should be rendered. This hook is
105 run with a single argument @var{alpha}, a value in the range [0, 1]
106 which represents how much time has past since the last game state
107 update relative to the upcoming game state update, as a percentage.
108 Because the game state is updated independent of rendering, it is
109 often the case that rendering is occuring between two updates. If the
110 game is rendered as it was during the last update, a strange
111 side-effect will occur that makes animation appear rough or
112 ``choppy''. To counter this, the @var{alpha} value can be used to
113 perfrom a linear interpolation of a moving object between its current
114 position and its previous position. This odd trick has the pleasing
115 result of making the animation look smooth again, but requires keeping
116 track of previous state.
117
118 @c TODO: Add example of linear interpolation
119
120 @example
121 (add-hook! draw-hook (lambda (alpha) (display "<(._.<) \n")))
122 @end example
123
124 @end defvr
125
126 @defvr {Variable} quit-hook
127 A hook that is run when the user clicks the close button on the game
128 window. This hook is run with zero arguments.
129
130 @example
131 (add-hook! quit-hook (lambda () (display "bye!\n")))
132 @end example
133
134 @end defvr
135
136 @defvr {Variable} key-press-hook
137 A hook that is run when a key is pressed on the keyboard. This hook
138 is run with four arguments:
139
140 @enumerate
141 @item
142 @var{key}: The symbolic name of the ``virtual'' key that was pressed.
143 For example: @code{backspace}. It's called a virtual key because the
144 operating system may map a physical keyboard key to another key
145 entirely, such as how the author binds the ``caps lock'' key to mean
146 ``control''.
147
148 @item
149 @var{scancode}: The symbolic name of the physical key that was
150 pressed.
151
152 @item
153 @var{modifiers}: A list of the symbolic names of modifier keys that
154 were being held down when the key was pressed. Possible values
155 include @code{ctrl}, @code{alt}, and @code{shift}.
156
157 @item
158 @var{repeat?}: @code{#t} if this is a repeated press of the same key.
159
160 @end enumerate
161
162 @example
163 (add-hook! key-press-hook
164 (lambda (key scancode modifiers repeat?)
165 (display "pressed key: ")
166 (display key)
167 (newline)))
168 @end example
169
170 @end defvr
171
172 @defvr {Variable} key-release-hook
173 A hook that is run when a key is released on the keyboard. This hook
174 is run with three arguments:
175
176 @enumerate
177 @item
178 @var{key}: The symbolic name of the ``virtual'' key that was released.
179
180 @item
181 @var{scancode}: The symbolic name of the physical key that was
182 released.
183
184 @item
185 @var{modifiers}: A list of the symbolic names of modifier keys that
186 were being held down when the key was released.
187
188 @end enumerate
189
190 @end defvr
191
192 @defvr {Variable} text-input-hook
193 A hook that is run when printable text is typed on the keyboard. This
194 hook is run with a single argument, @var{text}, a string containing
195 the text that was entered.
196 @end defvr
197
198 @defvr {Variable} mouse-press-hook
199 A hook that is run when a mouse button is pressed. This hook is run
200 with four arguments:
201
202 @enumerate
203
204 @item
205 @var{button}: The symbolic name of the button that was pressed, such
206 as @code{left}, @code{middle}, or @code{right}.
207
208 @item
209 @var{clicks}: The number of times the button has been clicked in a row.
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 @end enumerate
218
219 @end defvr
220
221 @defvr {Variable} mouse-release-hook
222 A hook that is run when a mouse button is released. This hook is run
223 with three arguments:
224
225 @enumerate
226
227 @item
228 @var{button}: The symbolic name of the button that was released.
229
230 @item
231 @var{x}: The x coordinate of the mouse cursor.
232
233 @item
234 @var{y}: The y coordinate of the mouse cursor.
235
236 @end enumerate
237
238 @end defvr
239
240 @defvr {Variable} mouse-move-hook
241 A hook that is run when the mouse is moved. This hook is run with
242 five arguments:
243
244 @enumerate
245
246 @item
247 @var{x}: The x coordinate of the mouse cursor.
248
249 @item
250 @var{y}: The y coordinate of the mouse cursor.
251
252 @item
253 @var{dx}: The amount the mouse has moved along the x axis since the
254 last mouse move event.
255
256 @item
257 @var{dy}: The amount the mouse has moved along the y axis since the
258 last mouse move event.
259
260 @item
261 @var{buttons}: A list of the buttons that were pressed down when the
262 mouse was moved.
263
264 @end enumerate
265
266 @end defvr
267
268 @defvr {Variable} controller-add-hook
269 A hook that is run when a game controller is connected. This hook is
270 run with a single argument, @var{controller}, the controller that was
271 connected.
272 @end defvr
273
274 @defvr {Variable} controller-remove-hook
275 A hook that is run when a game controller is disconnected. This hook
276 is run with a single argument, @var{controller}, the controller that
277 was disconnected.
278 @end defvr
279
280 @defvr {Variable} controller-press-hook
281 A hook that is run when a button on a game controller is pressed.
282 This hook is run with two arguments:
283
284 @enumerate
285
286 @item
287 @var{controller}: The controller that triggered the event.
288
289 @item
290 @var{button}: The symbolic name of the button that was pressed.
291 Possible buttons are:
292
293 @itemize
294 @item
295 @code{a}
296 @item
297 @code{b}
298 @item
299 @code{x}
300 @item
301 @code{y}
302 @item
303 @code{back}
304 @item
305 @code{guide}
306 @item
307 @code{start}
308 @item
309 @code{left-stick}
310 @item
311 @code{right-stick}
312 @item
313 @code{left-shoulder}
314 @item
315 @code{right-shoulder}
316 @item
317 @code{dpad-up}
318 @item
319 @code{dpad-down}
320 @item
321 @code{dpad-left}
322 @item
323 @code{dpad-right}
324
325 @end itemize
326
327 @end enumerate
328
329 @end defvr
330
331 @defvr {Variable} controller-release-hook
332 A hook that is run when a button on a game controller is released.
333
334 This hook is run with two arguments:
335
336 @enumerate
337
338 @item
339 @var{controller}: The controller that triggered the event.
340
341 @item
342 @var{button}: The symbolic name of the button that was released.
343
344 @end enumerate
345
346 @end defvr
347
348 @defvr {Variable} controller-move-hook
349 A hook that is run when an analog stick or trigger on a game
350 controller is moved. This hook is run with three arguments
351
352 @enumerate
353
354 @item
355 @var{controller}: The controller that triggered the event.
356
357 @item
358 @var{axis}: The symbolic name of the axis that was moved. Possible
359 values are:
360
361 @itemize
362 @item
363 @code{left-x}
364 @item
365 @code{left-y}
366 @item
367 @code{right-x}
368 @item
369 @code{right-y}
370 @item
371 @code{trigger-left}
372 @item
373 @code{trigger-right}
374 @end itemize
375
376 @end enumerate
377
378 @end defvr
379
380 @node Input
381 @section Input
382
383 Chickadee can handle input events from the keyboard, mouse, and game
384 controllers.
385
386 @menu
387 * Keyboard:: Keyboard input.
388 @end menu
389
390 @node Keyboard
391 @subsection Keyboard
392
393 @deffn {Procedure} key-pressed? @var{key}
394 Return @code{#t} if @var{key} is currently being pressed.
395 @end deffn
396
397 @deffn {Procedure} key-released? @var{key}
398 Return @code{#t} if @var{key} is not currently being pressed.
399 @end deffn
400
401 @node Math
402 @section Math
403
404 Chickadee contains data types and procedures for performing the most
405 common computations in video game simulations such as linear algebra
406 with vectors and matrices and axis-aligned bounding box collision
407 detection.
408
409 @menu
410 * Basics:: Commonly used, miscellaneous things.
411 * Vectors:: Euclidean vectors.
412 * Matrices:: Transformation matrices.
413 * Quaternions:: Rotations.
414 * Rectangles:: Axis-aligned bounding boxes.
415 * Easings:: Easing functions for interesting animations.
416 @end menu
417
418 @node Basics
419 @subsection Basics
420
421 @defvar pi
422 An essential constant for all trigonometry. @code{@U{03C0}} is the ratio
423 of a circle's circumferences to its diameter. Since @code{@U{03C0}} is an
424 irrational number, the @var{pi} in Chickadee is a mere floating point
425 approximation that is ``good enough.''
426 @end defvar
427
428 @defvar pi/2
429 Half of @var{pi}.
430 @end defvar
431
432 @deffn {Procedure} cotan @var{z}
433 Return the cotangent of @var{z}.
434 @end deffn
435
436 @node Vectors
437 @subsection Vectors
438
439 @node Matrices
440 @subsection Matrices
441
442 @node Quaternions
443 @subsection Quaternions
444
445 In game development, the quaternion is most often used to represent
446 rotations. Why not use a matrix for that, you may ask. Unlike
447 matrices, quaternions can be interpolated (animated) and produce a
448 meaningful result. When interpolating two quaternions, there is a
449 smooth transition from one rotation to another, whereas interpolating
450 two matrices would yield garbage.
451
452 @deffn {Procedure} quaternion @var{x} @var{y} @var{z} @var{w}
453 Return a new quaternion with values @var{x}, @var{y}, @var{z}, and
454 @var{w}.
455 @end deffn
456
457 @deffn {Procedure} quaternion? @var{obj}
458 Return @code{#t} if @var{obj} is a quaternion.
459 @end deffn
460
461 @deffn {Procedure} quaternion-w @var{q}
462 Return the W component of the quaternion @var{q}.
463 @end deffn
464
465 @deffn {Procedure} quaternion-x @var{q}
466 Return the X component of the quaternion @var{q}.
467 @end deffn
468
469 @deffn {Procedure} quaternion-y @var{q}
470 Return the Y component of the quaternion @var{q}.
471 @end deffn
472
473 @deffn {Procedure} quaternion-z @var{q}
474 Return the Z component of the quaternion @var{q}.
475 @end deffn
476
477 @deffn {Procedure} make-identity-quaternion
478 Return the identity quaternion.
479 @end deffn
480
481 @node Rectangles
482 @subsection Rectangles
483
484 @node Easings
485 @subsection Easings
486
487 @deffn {Procedure} linear @var{t}
488 @end deffn
489
490 @deffn {Procedure} smoothstep @var{t}
491 @end deffn
492
493 @deffn {Procedure} ease-in-quad @var{t}
494 @end deffn
495
496 @deffn {Procedure} ease-out-quad @var{t}
497 @end deffn
498
499 @deffn {Procedure} ease-in-out-quad @var{t}
500 @end deffn
501
502 @deffn {Procedure} ease-in-cubic @var{t}
503 @end deffn
504
505 @deffn {Procedure} ease-out-cubic @var{t}
506 @end deffn
507
508 @deffn {Procedure} ease-in-out-cubic @var{t}
509 @end deffn
510
511 @deffn {Procedure} ease-in-quart @var{t}
512 @end deffn
513
514 @deffn {Procedure} ease-out-quart @var{t}
515 @end deffn
516
517 @deffn {Procedure} ease-in-out-quart @var{t}
518 @end deffn
519
520 @deffn {Procedure} ease-in-quint @var{t}
521 @end deffn
522
523 @deffn {Procedure} ease-out-quint @var{t}
524 @end deffn
525
526 @deffn {Procedure} ease-in-out-quint @var{t}
527 @end deffn
528
529 @deffn {Procedure} ease-in-sine @var{t}
530 @end deffn
531
532 @deffn {Procedure} ease-out-sine @var{t}
533 @end deffn
534
535 @deffn {Procedure} ease-in-out-sine @var{t}
536 @end deffn
537
538 @node Graphics
539 @section Graphics
540
541 Chickadee aims to make hardware-accelerated graphics rendering as
542 simple and efficient as possible by providing high-level APIs that
543 interact with the low-level OpenGL API under the hood. Anyone that
544 has worked with OpenGL directly knows that it has a steep learning
545 curve and a lot of effort is needed to render even a single triangle.
546 The Chickadee rendering engine attempts to make it easy to do common
547 tasks like rendering a sprite while also providing all of the building
548 blocks to implement additional rendering techniques.
549
550 @menu
551 * Rendering Engine:: Rendering state management.
552 * Textures:: 2D images.
553 * Sprites:: Draw 2D images.
554 * Lines and Shapes:: Draw line segments and polygons.
555 * Fonts:: Drawing text.
556 * Blending and Depth Testing:: Control how pixels are combined.
557 * Vertex Arrays:: Create 2D/3D models.
558 * Shaders:: Create custom GPU programs.
559 * Framebuffers:: Render to texture.
560 * Viewports:: Restrict rendering to
561 @end menu
562
563 @node Rendering Engine
564 @subsection Rendering Engine
565
566 Chickadee defines rendering using a metaphor familiar to Scheme
567 programmers: procedure application. A shader (@pxref{Shaders}) is
568 like a procedure for the GPU to apply. Shaders are passed arguments:
569 A vertex array containing the geometry to render (@pxref{Vertex
570 Arrays}) and zero or more keyword arguments that the shader
571 understands. Similar to how Scheme has @code{apply} for calling
572 procedures, Chickadee provides @code{gpu-apply} for calling shaders.
573
574 Additionally, there is some dynamic state that effects how
575 @code{gpu-apply} will behave. Things like the current viewport,
576 framebuffer, and blend mode are stored as dynamic state because it
577 would be tedious to have to have to specify them each time
578 @code{gpu-apply} is called.
579
580 The following procedures and syntax can be found in the
581 @code{(chickadee render)} module.
582
583 @deffn {Syntax} gpu-apply @var{shader} @var{vertex-array} @
584 [#:uniform-key @var{uniform-value} ...]
585 @deffnx {Syntax} gpu-apply* @var{shader} @var{vertex-array} @
586 @var{count} [#:uniform-key @var{uniform-value} ...]
587
588 Render @var{vertex-array} using @var{shader} with the uniform values
589 specified in the following keyword arguments.
590
591 While @code{gpu-apply} will draw every vertex in @var{vertex-array},
592 @code{gpu-apply*} will only draw @var{count} vertices.
593
594 @end deffn
595
596 @deffn {Procedure} current-viewport
597 Return the currently bound viewport. @xref{Viewports} for more
598 details about using viewports.
599 @end deffn
600
601 @deffn {Procedure} current-framebuffer
602 Return the currently bound framebuffer. @xref{Framebuffers} for more
603 details about using framebuffers.
604 @end deffn
605
606 @deffn {Procedure} current-blend-mode
607 Return the currently bound blend mode. @xref{Blending and Depth
608 Testing} for more details about using blend modes.
609 @end deffn
610
611 @deffn {Procedure} current-depth-test
612 Return @code{#t} if depth testing is currently enabled.
613 @xref{Blending and Depth Testing} for more details about using the
614 depth test.
615 @end deffn
616
617 @deffn {Procedure} current-texture
618 Return the currently bound texture. @xref{Textures} for more details
619 about using textures.
620 @end deffn
621
622 @deffn {Procedure} current-projection
623 Return the currently bound projection matrix. @xref{Matrices} for
624 more details about matrices.
625 @end deffn
626
627 @deffn {Syntax} with-viewport @var{viewport} @var{body} ...
628 Evaluate @var{body} with the current viewport bound to @var{viewport}.
629 @end deffn
630
631 @deffn {Syntax} with-framebuffer @var{framebuffer} @var{body} ...
632 Evaluate @var{body} with the current framebuffer bound to
633 @var{framebuffer}.
634 @end deffn
635
636 @deffn {Syntax} with-blend-mode @var{blend-mode} @var{body} ...
637 Evaluate @var{body} with the current blend mode bound to
638 @var{blend-mode}.
639 @end deffn
640
641 @deffn {Syntax} with-depth-test @var{depth-test?} @var{body} ...
642 Evaluate @var{body} with the depth-test disabled if @var{depth-test?}
643 is @code{#f}, or enabled otherwise.
644 @end deffn
645
646 @deffn {Syntax} with-texture @var{texture} @var{body} ...
647 Evaluate @var{body} with the current texture bound to @var{texture}.
648 @end deffn
649
650 @deffn {Syntax} with-projection @var{projection} @var{body} ...
651 Evaluate @var{body} with the current projection matrix bound to
652 @var{projection}.
653 @end deffn
654
655 @node Textures
656 @subsection Textures
657
658 @deffn {Procedure} load-image @var{file} [#:min-filter nearest] @
659 [#:mag-filter nearest] [#:wrap-s repeat] [#:wrap-t repeat]
660
661 Load the image data from @var{file} and return a new texture object.
662
663 @var{min-filter} and @var{mag-filter} describe the method that should
664 be used for minification and magnification when rendering,
665 respectively. Possible values are @code{nearest} and @code{linear}.
666
667 @var{wrap-s} and @var{wrap-t} describe how to interpret texture
668 coordinates that are greater than @code{1.0}. Possible values are
669 @code{repeat}, @code{clamp}, @code{clamp-to-border}, and
670 @code{clamp-to-edge}.
671
672 @end deffn
673
674 @node Sprites
675 @subsection Sprites
676
677 For those who are new to this game, a sprite is a 2D rectangular
678 bitmap that is rendered to the screen. For 2D games, sprites are the
679 most essential graphical abstraction. They are used for drawing maps,
680 players, NPCs, items, particles, text, etc. In Chickadee, bitmaps are
681 stored in textures (@pxref{Textures}) and can be used to draw sprites
682 via the @code{draw-sprite} procedure.
683
684 @deffn {Procedure} draw-sprite @var{texture} @var{position} @
685 [#:origin] [#:scale] [#:rotation] [#:blend-mode alpha] @
686 [#:rect] [#:shader]
687
688 Draw @var{texture} at @var{position}.
689
690 Optionally, other transformations may be applied to the sprite.
691 @var{rotation} specifies the angle to rotate the sprite, in radians.
692 @var{scale} specifies the scaling factor as a 2D vector. All
693 transformations are applied relative to @var{origin}, a 2D vector,
694 which defaults to the lower-left corner.
695
696 Alpha blending is used by default but the blending method can be
697 changed by specifying @var{blend-mode}.
698
699 The area drawn to is as big as the texture, by default. To draw to an
700 arbitrary section of the screen, specify @var{rect}.
701
702 Finally, advanced users may specify @var{shader} to change the way the
703 sprite is rendered entirely.
704 @end deffn
705
706 It's not uncommon to need to draw hundreds or thousands of sprites
707 each frame. However, GPUs (graphics processing units) are tricky
708 beasts that prefer to be sent few, large chunks of data to render
709 rather than many, small chunks. Using @code{draw-sprite} on its own
710 will involve at least one GPU call @emph{per sprite}, which will
711 quickly lead to poor performance. To deal with this, a technique
712 known as ``sprite batching'' can be used. Instead of drawing each
713 sprite immediately, the sprite batch will build up a large of buffer
714 of sprites to draw and defer rendering until the last possible moment.
715 Batching isn't a panacea, though. Batching only works if the sprites
716 being drawn share as much in common as possible. Every time you draw
717 a sprite with a different texture or blend mode, the batch will be
718 sent off to the GPU. Therefore, batching is most useful if you
719 minimize such changes. A good strategy for reducing texture changes
720 is to stuff many bitmaps into a single image file and create a
721 ``texture atlas'' (@pxref{Textures}) to access the sub-images within.
722
723 Taking advantage of sprite batching in Chickadee is easy, just wrap
724 the code that is calling @code{draw-sprite} a lot in the
725 @code{with-batched-sprites} form.
726
727 @deffn {Syntax} with-batched-sprites @var{body} @dots{}
728 Use batched rendering for all @code{draw-sprite} calls within
729 @var{body}.
730 @end deffn
731
732 With a basic sprite abstraction in place, it's possible to build other
733 abstractions on top of it. One such example is the ``nine patch''. A
734 nine patch is a sprite that can be rendered at various sizes without
735 becoming distorted. This is achieved by diving up the sprite into
736 nine regions:
737
738 @itemize
739 @item
740 the center, which can be scaled horizontally and vertically
741 @item
742 the four corners, which can never be scaled
743 @item
744 the left and right sides, which can be scaled vertically
745 @item
746 the top and bottom sides, which can be scaled horizontally
747 @end itemize
748
749 The one caveat is that the bitmap regions must be designed in such a
750 way so that they are not distorted when stretched along the affected
751 axes. For example, that means that the top and bottom sides could
752 have varying colored pixels vertically, but not horizontally.
753
754 The most common application of this technique is for graphical user
755 interface widgets like buttons and dialog boxes. By using a nine
756 patch, they can be rendered at any size without unappealing scaling
757 artifacts.
758
759 @deffn {Procedure} draw-nine-patch @var{texture} @var{rect} @
760 [#:margin 0] [#:top-margin margin] [#:bottom-margin margin] @
761 [#:left-margin margin] [#:right-margin margin] @
762 [#:origin] [#:scale] [#:rotation] [#:blend-mode alpha] @
763 [#:shader]
764
765 Draw a nine patch sprite. A nine patch sprite renders @var{texture}
766 as a @var{width} x @var{height} rectangle whose stretchable areas are
767 defined by the given margin measurements @var{top-margin},
768 @var{bottom-margin}, @var{left-margin}, and @var{right-margin}. The
769 @var{margin} argument may be used to configure all four margins at
770 once.
771
772 Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
773 the other arguments.
774 @end deffn
775
776 @node Lines and Shapes
777 @subsection Lines and Shapes
778
779 Sprites are fun, but sometimes simple, untextured lines and polygons
780 are desired. That's where the @code{(chickadee render shapes)} module
781 comes in!
782
783 @deffn {Procedure} draw-line @var{start} @var{end} @
784 [#:thickness 0.5] [#:feather 1.0] [#:cap round] [#:color] @
785 [#:shader]
786
787 Draw a line segment from @var{start} to @var{end}. The line will be
788 @var{thickness} pixels thick with an antialiased border @var{feather}
789 pixels wide. The line will be colored @var{color}. @var{cap}
790 specifies the type of end cap that should be used to terminate the
791 lines, either @code{none}, @code{butt}, @code{square}, @code{round},
792 @code{triangle-in}, or @code{triangle-out}. Advanced users may use
793 the @var{shader} argument to override the built-in line segment
794 shader.
795 @end deffn
796
797 @node Fonts
798 @subsection Fonts
799
800 Unlike the traditional TrueType font format that many are accustomed
801 to, Chickadee loads and renders bitmap fonts in the
802 @url{http://www.angelcode.com/products/bmfont/doc/file_format.html,
803 Angel Code format}. But why use this seemingly obscure format? It's
804 easy to find TTFs but not easy to find FNTs (the canonical file
805 extension used for Angel Code fonts) and bitmap fonts don't scale
806 well. The reason is efficiency.
807
808 If all of the glyphs of a font are pre-rendered and packed into an
809 image file then it becomes possible to use a texture atlas
810 (@pxref{Textures}) and a sprite batch (@pxref{Sprites}) when
811 rendering, which is a more efficient way to render fonts than using,
812 say, @url{https://www.libsdl.org/projects/SDL_ttf/, SDL_ttf} or other
813 solutions that involve using the FreeType library directly.
814
815 Now what about scaling? In libraries that use TTF fonts, one must
816 choose the size that the glyphs will be rasterized at up front. To
817 use @code{n} sizes of the same font, one must load @code{n} variants
818 of that font. If the size of the text is dynamic, some kind of
819 texture scaling algorithm must be used and the text will inevitably
820 look blurry. At first glance, using bitmap fonts seem to have an even
821 worse issue. Instead of just loading the same font @code{n} times at
822 different sizes, one would need to generate @code{n} image files for
823 each font size needed. This is where the ``signed distance field''
824 rendering technique comes in. Introduced by
825 @url{http://www.valvesoftware.com/.../2007/SIGGRAPH2007_AlphaTestedMagnification.pdf,
826 Valve} in 2007, signed distance field fonts can be efficiently stored
827 in a bitmap and be rendered at arbitrary scale factors with good
828 results.
829
830 While Chickadee does not yet offer a tool for converting TTF fonts
831 into FNT fonts, tools such as
832 @url{https://github.com/libgdx/libgdx/wiki/Hiero, Hiero} may be used
833 in the meantime.
834
835 The following procedures can be found in the @code{(chickadee render
836 font)} module.
837
838 @deffn {Procedure} load-font @var{file}
839 Load the Angel Code formatted XML document in @var{file} and return a
840 new font object.
841 @end deffn
842
843 @deffn {Procedure} font? @var{obj}
844 Return @code{#t} if @var{obj} is a font object.
845 @end deffn
846
847 @deffn {Procedure} font-face @var{font}
848 Return the name of @var{font}.
849 @end deffn
850
851 @deffn {Procedure} font-line-height @var{font}
852 Return the line height of @var{font}.
853 @end deffn
854
855 @deffn {Procedure} font-line-height @var{font}
856 Return the line height of @var{font}.
857 @end deffn
858
859 @deffn {Procedure} font-bold? @var{font}
860 Return @code{#t} if @var{font} is a bold font.
861 @end deffn
862
863 @deffn {Procedure} font-italic? @var{font}
864 Return @code{#t} if @var{font} is an italicized font.
865 @end deffn
866
867 @deffn {Procedure} draw-text @var{font} @var{text} @var{position}
868 [#:origin] [#:scale] [#:rotation] [#:blend-mode]
869
870 Draw the string @var{text} with the first character starting at
871 @var{position} using @var{font}.
872
873 @example
874 (draw-text font "Hello, world!" (vec2 128.0 128.0))
875 @end example
876
877 Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
878 the other arguments.
879 @end deffn
880
881 @node Blending and Depth Testing
882 @subsection Blending and Depth Testing
883
884 @node Vertex Arrays
885 @subsection Vertex Arrays
886
887 @node Shaders
888 @subsection Shaders
889
890 Shaders are programs for the GPU to evaluate. They are written in the
891 OpenGL Shading Language, or GLSL. Chickadee does not currently
892 provide a Scheme-like domain specific language for writing shaders.
893 Since shaders must be written in GLSL and not Scheme, they are
894 considered an advanced feature.
895
896 @node Framebuffers
897 @subsection Framebuffers
898
899 @node Viewports
900 @subsection Viewports
901
902 @node Audio
903 @section Audio
904
905 Chickadee has two data types for audio: samples and music. Samples
906 are for short sound effects like explosions. Music is for, well,
907 uh@dots{}, music.
908
909 Supported file formats include WAV and OGG.
910
911 @deffn {Procedure} load-sample @var{file}
912 Load audio sample from @var{file}.
913 @end deffn
914
915 @deffn {Procedure} set-sample-volume! @var{volume}
916 Set the volume that all samples are played at to @var{volume}, an
917 integer value between 0 and 128.
918 @end deffn
919
920 @deffn {Procedure} play-sample @var{sample}
921 Play @var{sample}. Pretty straightforward!
922 @end deffn
923
924 @deffn {Procedure} load-music @var{file}
925 Load music from @var{file}.
926 @end deffn
927
928 @deffn {Procedure} music-volume
929 Return the volume level for music, an integer value between 0 and 128.
930 @end deffn
931
932 @deffn {Procedure} set-music-volume! @var{volume}
933 Set the volume that music is played at to @var{volume}, an integer
934 value between 0 and 128.
935 @end deffn
936
937 @deffn {Procedure} play-music @var{music} [@var{loop?}]
938 Play @var{music}. If @var{loop?}, play it over and over and over and
939 over and@dots{}
940 @end deffn
941
942 @deffn {Procedure} pause-music
943 Pause the current music track.
944 @end deffn
945
946 @deffn {Procedure} resume-music
947 Resume the current music track.
948 @end deffn
949
950 @deffn {Procedure} rewind-music
951 estart the current music track from the beginning.
952 @end deffn
953
954 @deffn {Procedure} stop-music
955 Stop playing the current music track.
956 @end deffn
957
958 @deffn {Procedure} music-playing?
959 Return @code{#t} if music is currently playing.
960 @end deffn
961
962 @deffn {Procedure} music-paused?
963 Return @code{#t} if music is currently paused.
964 @end deffn
965
966 @node Buffers
967 @section Buffers
968
969 Games are big state machines and they can get complex quickly, thus we
970 need tools to manage that complexity. One useful technique is to
971 separate the many ``screens'' of a game (such as the main menu, player
972 select screen, high score table, game over screen, etc.) from each
973 other, so that it is possible to program the logic for one section of
974 the game independent of another. In Chickadee, these ``screens'' are
975 called ``buffers''. In other game engines this same construct may be
976 called a ``scene'' or ``room''.
977
978 A buffer knows how to update its state, render, handle input events,
979 etc. Only one buffer is ever active at a time, and the current buffer
980 can be changed with procedures like @code{push-buffer},
981 @code{replace-buffer}, and @code{pop-buffer}.
982
983 Buffers are implemented using Guile's object oriented programming
984 system (@pxref{GOOPS,,, guile, GNU Guile Reference Manual}). Each
985 type of buffer is represented as a subclass of the @code{<buffer>}
986 class. Once a new buffer class has been created, there are many
987 methods that can be specialized for that class.
988
989 To install buffer support and set the initial buffer, call the
990 @code{use-buffers!} procedure.
991
992 Let's take a look at a simple example to see how it all comes
993 together:
994
995 @example
996 (use-modules (chickadee)
997 (chickadee buffer)
998 (chickadee math vector)
999 (chickadee render sprite)
1000 (chickadee render texture)
1001 (oop goops))
1002
1003 ;; Define a new buffer type.
1004 (define-class <splash-screen> (<buffer>)
1005 (chickadee #:accessor chickadee #:init-value #f))
1006
1007 ;; Define the logic for when the buffer is first activated.
1008 (define-method (start (splash <splash-screen>))
1009 (set! (chickadee splash) (load-image "images/chickadee.png")))
1010
1011 ;; Define how the buffer should be rendered.
1012 (define-method (draw (splash <splash-screen>) alpha)
1013 (draw-sprite (chickadee splash) (vec2 256.0 176.0)))
1014
1015 ;; Hook into the game engine and make the splash screen the initial buffer.
1016 (use-buffers! (make <splash-screen>))
1017
1018 ;; Start the game!
1019 (run-game)
1020 @end example
1021
1022 @deffn {Class} <buffer>
1023 The parent class for all buffers.
1024 @end deffn
1025
1026 @deffn {Method} started? @var{buffer}
1027 Return @code{#t} if @var{buffer} has been activated by the game engine.
1028 @end deffn
1029
1030 @deffn {Method} start @var{buffer}
1031 Called when @var{buffer} becomes the current buffer for the first time.
1032 @end deffn
1033
1034 @deffn {Method} stop @var{buffer}
1035 Called when @var{buffer} is no longer in use.
1036 @end deffn
1037
1038 @deffn {Method} pause @var{buffer}
1039 Called when @var{buffer} is no longer the current buffer but still in
1040 use.
1041 @end deffn
1042
1043 @deffn {Method} resume @var{buffer}
1044 Called when @var{buffer} becomes the current buffer after having been
1045 suspended.
1046 @end deffn
1047
1048 The following methods are simply wrappers around the hooks described
1049 in @xref{Kernel}, so see that section for more detail about the
1050 arguments to these methods. The engine calls these methods with the
1051 current buffer as the first argument.
1052
1053 @deffn {Method} update @var{buffer} @var{dt}
1054 Advance the simulation running in @var{buffer} by @var{dt} units of
1055 time.
1056 @end deffn
1057
1058 @deffn {Method} abort @var{buffer}
1059 Called when the user tries to close the game window.
1060 @end deffn
1061
1062 @deffn {Method} before-draw @var{buffer}
1063 Called before @var{buffer} is rendered.
1064 @end deffn
1065
1066 @deffn {Method} after-draw @var{buffer}
1067 Called after @var{buffer} is rendered.
1068 @end deffn
1069
1070 @deffn {Method} draw @var{buffer} @var{alpha}
1071 Render @var{buffer}.
1072 @end deffn
1073
1074 @deffn {Method} key-press @var{buffer} @var{key} @var{scancode} @var{modifiers} @var{repeat?}
1075 Handle key press event.
1076 @end deffn
1077
1078 @deffn {Method} key-release @var{buffer} @var{key} @var{scancode} @var{modifiers}
1079 Handle key release event.
1080 @end deffn
1081
1082 @deffn {Method} text-input @var{buffer} @var{text}
1083 Handle text input event.
1084 @end deffn
1085
1086 @deffn {Method} mouse-press @var{buffer} @var{button} @var{clicks} @var{x} @var{y}
1087 Handle mouse press event.
1088 @end deffn
1089
1090 @deffn {Method} mouse-release @var{buffer} @var{button} @var{x} @var{y}
1091 Handle mouse release event.
1092 @end deffn
1093
1094 @deffn {Method} mouse-move @var{buffer} @var{x} @var{y} @var{x-rel} @var{y-rel} @var{buttons}
1095 Handle mouse move event.
1096 @end deffn
1097
1098 @deffn {Method} controller-add @var{buffer} @var{controller}
1099 Handle controller add event.
1100 @end deffn
1101
1102 @deffn {Method} controller-remove @var{buffer} @var{controller}
1103 Handle controller remove event.
1104 @end deffn
1105
1106 @deffn {Method} controller-press @var{buffer} @var{controller} @var{button}
1107 Handle controller press event.
1108 @end deffn
1109
1110 @deffn {Method} controller-release @var{buffer} @var{controller} @var{button}
1111 Handle controller release event.
1112 @end deffn
1113
1114 @deffn {Method} controller-move @var{buffer} @var{controller} @var{axis} @var{value}
1115 Handle controller move event.
1116 @end deffn
1117
1118 The following procedures are used to manage the buffer stack:
1119
1120 @deffn {Procedure} use-buffers! @var{initial-buffer}
1121 Install buffers into the game engine and set the current buffer to
1122 @var{initial-buffer}.
1123 @end deffn
1124
1125 @deffn {Procedure} push-buffer! @var{buffer}
1126 Pause the current buffer and switch to @var{buffer}.
1127 @end deffn
1128
1129 @deffn {Procedure} pop-buffer!
1130 Stop the current buffer and switch back to the previously active
1131 buffer, or terminate the game loop if the buffer stack is empty.
1132 @end deffn
1133
1134 @deffn {Procedure} replace-buffer! @var{buffer}
1135 Stop the current buffer and switch to @var{buffer}
1136 @end deffn
1137
1138 @deffn {Procedure} current-buffer
1139 Return the current buffer.
1140 @end deffn
1141
1142 @node Scripting
1143 @section Scripting
1144
1145 Game logic is a web of asynchronous events that are carefully
1146 coordinated to bring the game world to life. In order to make an
1147 enemy follow and attack the player, or move an NPC back and forth in
1148 front of the item shop, or do both at the same time, a scripting
1149 system is a necessity. Chickadee comes with an asynchronous
1150 programming system in the @code{(chickadee scripting)} module.
1151 Lightweight, cooperative threads known as ``scripts'' allow the
1152 programmer to write asynchronous code as if it were synchronous, and
1153 allow many such ``threads'' to run concurrently.
1154
1155 But before we dig deeper into scripts, let's discuss the simple act
1156 of scheduling tasks.
1157
1158 @menu
1159 * Agendas:: Scheduling tasks.
1160 * Scripts:: Cooperative multitasking.
1161 * Tweening:: Animations.
1162 * Channels:: Publish data to listeners.
1163 @end menu
1164
1165 @node Agendas
1166 @subsection Agendas
1167
1168 To schedule a task to be performed later, an ``agenda'' is used.
1169 There is a default, global agenda that is ready to be used, or
1170 additional agendas may be created for different purposes. The
1171 following example prints the text ``hello'' when the agenda has
1172 advanced to time unit 10.
1173
1174 @example
1175 (at 10 (display "hello\n"))
1176 @end example
1177
1178 Most of the time it is more convenient to schedule tasks relative to
1179 the current time. This is where @code{after} comes in handy:
1180
1181 @example
1182 (after 10 (display "hello\n"))
1183 @end example
1184
1185 Time units in the agenda are in no way connected to real time. It's
1186 up to the programmer to decide what agenda time means. A simple and
1187 effective approach is to map each call of the update hook
1188 (@pxref{Kernel}) to 1 unit of agenda time, like so:
1189
1190 @example
1191 (add-hook! update-hook (lambda (dt) (update-agenda 1)))
1192 @end example
1193
1194 It is important to call @code{update-agenda} periodically, otherwise
1195 no tasks will ever be run!
1196
1197 In addition to using the global agenda, it is useful to have multiple
1198 agendas for different purposes. For example, the game world can use a
1199 different agenda than the user interface, so that pausing the game is
1200 a simple matter of not updating the world's agenda while continuing to
1201 update the user interface's agenda. The current agenda is dynamically
1202 scoped and can be changed using the @code{with-agenda} special form:
1203
1204 @example
1205 (define game-world-agenda (make-agenda))
1206
1207 (with-agenda game-world-agenda
1208 (at 60 (spawn-goblin))
1209 (at 120 (spawn-goblin))
1210 (at 240 (spawn-goblin-king)))
1211 @end example
1212
1213 @deffn {Procedure} make-agenda
1214 Return a new task scheduler.
1215 @end deffn
1216
1217 @deffn {Procedure} agenda? @var{obj}
1218 Return @code{#t} if @var{obj} is an agenda.
1219 @end deffn
1220
1221 @deffn {Procedure} current-agenda
1222 @deffnx {Procedure} current-agenda @var{agenda}
1223 When called with no arguments, return the current agenda. When called
1224 with one argument, set the current agenda to @var{agenda}.
1225 @end deffn
1226
1227 @deffn {Syntax} with-agenda @var{agenda} @var{body} @dots{}
1228 Evaluate @var{body} with the current agenda set to @var{agenda}.
1229 @end deffn
1230
1231 @deffn {Procedure} agenda-time
1232 Return the current agenda time.
1233 @end deffn
1234
1235 @deffn {Procedure} update-agenda @var{dt}
1236 Advance the current agenda by @var{dt}.
1237 @end deffn
1238
1239 @deffn {Procedure} schedule-at @var{time} @var{thunk}
1240 Schedule @var{thunk}, a procedure of zero arguments, to be run at
1241 @var{time}.
1242 @end deffn
1243
1244 @deffn {Procedure} schedule-after @var{delay} @var{thunk}
1245 Schedule @var{thunk}, a procedure of zero arguments, to be run after
1246 @var{delay}.
1247 @end deffn
1248
1249 @deffn {Procedure} schedule-every @var{interval} @var{thunk} [@var{n}]
1250 Schedule @var{thunk}, a procedure of zero arguments, to be run every
1251 @var{interval} amount of time. Repeat this @var{n} times, or
1252 indefinitely if not specified.
1253 @end deffn
1254
1255 @deffn {Syntax} at @var{time} @var{body} @dots{}
1256 Schedule @var{body} to be evaluated at @var{time}.
1257 @end deffn
1258
1259 @deffn {Syntax} after @var{delay} @var{body} @dots{}
1260 Schedule @var{body} to be evaluated after @var{delay}.
1261 @end deffn
1262
1263 @deffn {Syntax} every @var{interval} @var{body} @dots{}
1264 @deffnx {Syntax} every (@var{interval} @var{n}) @var{body} @dots{}
1265 Schedule @var{body} to be evaluated every @var{interval} amount of
1266 time. Repeat this @var{n} times, or indefinitely if not specified.
1267 @end deffn
1268
1269 @node Scripts
1270 @subsection Scripts
1271
1272 Now that we can schedule tasks, let's take things to the next level.
1273 It sure would be great if we could make procedures that described a
1274 series of actions that happened over time, especially if we could do
1275 so without contorting our code into a nest of callback procedures.
1276 This is where scripts come in. With scripts we can write code in a
1277 linear way, in a manner that appears to be synchronous, but with the
1278 ability to suspend periodically in order to let other scripts have a
1279 turn and prevent blocking the game loop. Building on top of the
1280 scheduling that agendas provide, here is a script that models a child
1281 trying to get their mother's attention:
1282
1283 @example
1284 (script
1285 (while #t
1286 (display "mom!")
1287 (newline)
1288 (sleep 60))) ; where 60 = 1 second of real time
1289 @end example
1290
1291 This code runs in an endless loop, but the @code{sleep} procedure
1292 suspends the script and schedules it to be run later by the agenda.
1293 So, after each iteration of the loop, control is returned back to the
1294 game loop and the program is not stuck spinning in a loop that will
1295 never exit. Pretty neat, eh?
1296
1297 Scripts can suspend to any capable handler, not just the agenda.
1298 The @code{yield} procedure will suspend the current script and pass
1299 its ``continuation'' to a handler procedure. This handler procedure
1300 could do anything. Perhaps the handler stashes the continuation
1301 somewhere where it will be resumed when the user presses a specific
1302 key on the keyboard, or maybe it will be resumed when the player picks
1303 up an item off of the dungeon floor; the sky is the limit.
1304
1305 Sometimes it is necessary to abruptly terminate a script after it has
1306 been started. For example, when an enemy is defeated their AI routine
1307 needs to be shut down. When a script is spawned, a handle to that
1308 script is returned that can be used to cancel it when desired.
1309
1310 @example
1311 (define script (script (while #t (display "hey\n") (sleep 60))))
1312 ;; sometime later
1313 (cancel-script script)
1314 @end example
1315
1316 @deffn {Procedure} spawn-script @var{thunk}
1317 Apply @var{thunk} as a script and return a handle to it.
1318 @end deffn
1319
1320 @deffn {Syntax} script @var{body} @dots{}
1321 Evaluate @var{body} as a script and return a handle to it.
1322 @end deffn
1323
1324 @deffn {Procedure} script? @var{obj}
1325 Return @code{#t} if @var{obj} is a script handle.
1326 @end deffn
1327
1328 @deffn {Procedure} script-cancelled? @var{obj}
1329 Return @code{#t} if @var{obj} has been cancelled.
1330 @end deffn
1331
1332 @deffn {Procedure} script-running? @var{obj}
1333 Return @code{#t} if @var{obj} has not yet terminated or been
1334 cancelled.
1335 @end deffn
1336
1337 @deffn {Procedure} script-complete? @var{obj}
1338 Return @code{#t} if @var{obj} has terminated.
1339 @end deffn
1340
1341 @deffn {Procedure} cancel-script @var{co}
1342 Prevent further execution of the script @var{co}.
1343 @end deffn
1344
1345 @deffn {Procedure} yield @var{handler}
1346 Suspend the current script and pass its continuation to the
1347 procedure @var{handler}.
1348 @end deffn
1349
1350 @deffn {Procedure} sleep @var{duration}
1351 Wait @var{duration} before resuming the current script.
1352 @end deffn
1353
1354 @deffn {Procedure} channel-get @var{channel}
1355 Wait for a message from @var{channel}.
1356 @end deffn
1357
1358 @deffn {Syntax} forever @var{body} @dots{}
1359 Evaluate @var{body} in an endless loop.
1360 @end deffn
1361
1362 @node Tweening
1363 @subsection Tweening
1364
1365 Tweening is the process of transitioning something from an initial
1366 state to a final state over a pre-determined period of time. In other
1367 words, tweening is a way to create animation. The @code{tween}
1368 procedure can be used within any script like so:
1369
1370 @example
1371 (define x 0)
1372 (script
1373 ;; 0 to 100 in 60 ticks of the agenda.
1374 (tween 60 0 100 (lambda (y) (set! x y))))
1375 @end example
1376
1377 @deffn {Procedure} tween @var{duration} @var{start} @var{end} @var{proc} [#:step 1 #:ease @code{smoothstep} #:interpolate @code{lerp}]
1378 Transition a value from @var{start} to @var{end} over @var{duration},
1379 sending each succesive value to @var{proc}. @var{step} controls the
1380 amount of time between each update of the animation.
1381
1382 To control how the animation goes from the initial to final state, an
1383 ``easing'' procedure may be specified. By default, the
1384 @code{smoothstep} easing is used, which is a more pleasing default
1385 than a simplistic linear function. @xref{Easings} for a complete list
1386 of available easing procedures.
1387
1388 The @var{interpolate} procedure computes the values in between
1389 @var{start} and @var{end}. By default, linear interpolation (``lerp''
1390 for short) is used.
1391 @end deffn
1392
1393 @node Channels
1394 @subsection Channels
1395
1396 Channels are a tool for communicating amongst different scripts. One
1397 script can write a value to the channel and another can read from it.
1398 Reading or writing to a channel suspends that script until there is
1399 someone on the other end of the line to complete the transaction.
1400
1401 Here's a simplistic example:
1402
1403 @example
1404 (define c (make-channel))
1405
1406 (script
1407 (forever
1408 (let ((item (channel-get c)))
1409 (pk 'got item))))
1410
1411 (script
1412 (channel-put c 'sword)
1413 (channel-put c 'shield)
1414 (channel-put c 'potion))
1415 @end example
1416
1417 @deffn {Procedure} make-channel
1418 Return a new channel
1419 @end deffn
1420
1421 @deffn {Procedure} channel? @var{obj}
1422 Return @code{#t} if @var{obj} is a channel.
1423 @end deffn
1424
1425 @deffn {Procedure} channel-get @var{channel}
1426 Retrieve a value from @var{channel}. The current script suspends
1427 until a value is available.
1428 @end deffn
1429
1430 @deffn {Procedure} channel-put @var{channel} @var{data}
1431 Send @var{data} to @var{channel}. The current script suspends until
1432 another script is available to retrieve the value.
1433 @end deffn