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