1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<!-- Copyright (C) 2017, 2018, 2019 David Thompson davet@gnu.org
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
A copy of the license is also available from the Free Software
Foundation Web site at http://www.gnu.org/licenses/fdl.html.
* Chickadee: (chickadee). Game programming toolkit for Guile.
The document was typeset with
http://www.texinfo.org/ (GNU Texinfo).
-->
<!-- Created by GNU Texinfo 6.5, http://www.gnu.org/software/texinfo/ -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Kernel (The Chickadee Game Toolkit)</title>
<meta name="description" content="Kernel (The Chickadee Game Toolkit)">
<meta name="keywords" content="Kernel (The Chickadee Game Toolkit)">
<meta name="resource-type" content="document">
<meta name="distribution" content="global">
<meta name="Generator" content="makeinfo">
<link href="index.html#Top" rel="start" title="Top">
<link href="Index.html#Index" rel="index" title="Index">
<link href="index.html#SEC_Contents" rel="contents" title="Table of Contents">
<link href="API-Reference.html#API-Reference" rel="up" title="API Reference">
<link href="Math.html#Math" rel="next" title="Math">
<link href="API-Reference.html#API-Reference" rel="prev" title="API Reference">
<style type="text/css">
<!--
a.summary-letter {text-decoration: none}
blockquote.indentedblock {margin-right: 0em}
blockquote.smallindentedblock {margin-right: 0em; font-size: smaller}
blockquote.smallquotation {font-size: smaller}
div.display {margin-left: 3.2em}
div.example {margin-left: 3.2em}
div.lisp {margin-left: 3.2em}
div.smalldisplay {margin-left: 3.2em}
div.smallexample {margin-left: 3.2em}
div.smalllisp {margin-left: 3.2em}
kbd {font-style: oblique}
pre.display {font-family: inherit}
pre.format {font-family: inherit}
pre.menu-comment {font-family: serif}
pre.menu-preformatted {font-family: serif}
pre.smalldisplay {font-family: inherit; font-size: smaller}
pre.smallexample {font-size: smaller}
pre.smallformat {font-family: inherit; font-size: smaller}
pre.smalllisp {font-size: smaller}
span.nolinebreak {white-space: nowrap}
span.roman {font-family: initial; font-weight: normal}
span.sansserif {font-family: sans-serif; font-weight: normal}
ul.no-bullet {list-style: none}
@media (min-width: 1140px) {
body {
margin-left: 14rem;
margin-right: 4rem;
max-width: 52rem;
}
}
@media (min-width: 800px) and (max-width: 1140px) {
body {
margin-left: 6rem;
margin-right: 4rem;
max-width: 52rem;
}
}
@media (max-width: 800px) {
body {
margin: 1rem;
}
}
-->
</style>
<link rel="stylesheet" type="text/css" href="https://dthompson.us/css/dthompson.css">
</head>
<body lang="en">
<a name="Kernel"></a>
<div class="header">
<p>
Next: <a href="Math.html#Math" accesskey="n" rel="next">Math</a>, Up: <a href="API-Reference.html#API-Reference" accesskey="u" rel="up">API Reference</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Index.html#Index" title="Index" rel="index">Index</a>]</p>
</div>
<hr>
<a name="Kernel-1"></a>
<h3 class="section">2.1 Kernel</h3>
<p>At the very core of Chickadee, in the <code>(chickadee game-loop)</code>
module, lies an event loop. This loop, or “kernel”, is responsible
for ensuring that the game is updated at the desired interval,
rendering the current state of the game world, and handling errors if
they occur. The kernel implements what is known as a “fixed
timestep” game loop, meaning that the game simulation will be
advanced by a fixed interval of time and will never vary from frame to
frame, unlike some other styles of game loops. The appropriately
named <code>run-game*</code> and <code>abort-game</code> procedures are the entry
and exit points to the Chickadee game loop kernel.
</p>
<p>On its own, the kernel does not do very much at all. In order to
actually respond to input events, update game state, or render output,
the programmer must provide an engine. But donât worry, you donât
have to start from scratch! Chickadee comes with a simple engine that
uses SDL to create a graphical window and handle input devices, and
OpenGL to handle rendering. This default engine is enough for most
users to get started writing games quickly. More advanced users may
want to write a custom engine that uses a different I/O system.
Perhaps you are writing a text adventure or roguelike that reads from
and writes to a terminal instead of a graphical window. The game loop
kernel makes no assumptions.
</p>
<dl>
<dt><a name="index-run_002dgame"></a>Procedure: <strong>run-game</strong> <em>[#:update] [#:render] [#:time] [#:error] [#:update-hz 60]</em></dt>
<dd>
<p>Start the game loop. This procedure will not return until
<code>abort-game</code> is called.
</p>
<p>The core game loop is generic and requires four additional procedures
to operate:
</p>
<ul>
<li> <var>update</var>: Called <var>update-hz</var> times per second to advance the
game simulation. This procedure is called with a single argument: The
amount of time that has passed since the last update, in milliseconds.
</li><li> <var>render</var>: Called each iteration of the loop to render the game to
the desired output device. This procedure is called with a single
argument: A value in the range [0, 1] which represents how much time
has past since the last game state update relative to the upcoming
game state update, as a percentage. Because the game state is updated
independent of rendering, it is often the case that rendering is
occuring between two updates. If the game is rendered as it was
during the last update, a strange side-effect will occur that makes
animation appear rough or “choppy”. To counter this, the
<var>alpha</var> value can be used to perfrom a linear interpolation of a
moving object between its current position and its previous position.
This odd trick has the pleasing result of making the animation look
smooth again, but requires keeping track of previous state.
</li><li> <var>time</var>: Called to get the current time in milliseconds. This
procedure is called with no arguments.
</li><li> <var>error</var>: Called when an error from the <var>update</var> or
<var>render</var> procedures reaches the game loop. This procedure is
called with three arguments: The call stack, the error key, and the
error arguments. If no error handler is provided, the default
behavior is to simply re-throw the error.
</li></ul>
</dd></dl>
<dl>
<dt><a name="index-abort_002dgame"></a>Procedure: <strong>abort-game</strong></dt>
<dd><p>Stop the currently running Chickadee game loop.
</p></dd></dl>
<p>Since most users will want to write 2D/3D games with hardware
accelerated graphics rendering, controlled via keyboard, mouse, or
game controller, Chickadee comes with an easy to use engine just for
this purpose in the <code>(chickadee)</code> module: <code>run-game</code>.
</p>
<dl>
<dt><a name="index-run_002dgame-1"></a>Procedure: <strong>run-game</strong> <em>[#:window-title "Chickadee!"] [#:window-width 640] [#:window-height 480] [#:window-fullscreen? <code>#f</code>] [#:update-hz 60] [#:load] [#:update] [#:draw] [#:quit] [#:key-press] [#:key-release] [#:text-input] [#:mouse-press] [#:mouse-release] [#:mouse-move] [#:controller-add] [#:controller-remove] [#:controller-press] [#:controller-release] [#:controller-move] [#:error]</em></dt>
<dd>
<p>Run the Chickadee game loop using the SDL engine in OpenGL mode.
</p>
<p>A new graphical window will be opened with <var>window-width</var> x
<var>window-height</var> as its dimensions, <var>window-title</var> as its
title, and in fullscreen mode if <var>window-fullscreen?</var> is
<code>#t</code>.
</p>
<ul>
<li> <var>load</var>: Called with zero arguments when the game window has opened
but before the game loop has started. Can be used to perform
initialization that requires an open window and OpenGL context such as
loading textures.
</li><li> <var>update</var>: Called <var>update-hz</var> times per second with one
argument: The amount of time to advance the game simulation.
</li><li> <var>draw</var>: Called each time a frame should be rendered with a single
argument known as the <code>alpha</code> value. See the documentation for
<code>run-game</code> for an explanation of this value.
</li><li> <var>quit</var>: Called with zero arguments when the user tries to close
the game window. The default behavior is to exit the game.
</li><li> <var>key-press</var>: Called with four arguments when a key is pressed on
the keyboard:
<ol>
<li> <var>key</var>: The symbolic name of the “virtual” key that was pressed.
For example: <code>backspace</code>. It’s called a virtual key because the
operating system may map a physical keyboard key to another key
entirely, such as how the author likes to bind the “caps lock” key
to mean “control”.
</li><li> <var>scancode</var>: The symbolic name of the physical key that was
pressed.
</li><li> <var>modifiers</var>: A list of the symbolic names of modifier keys that
were being held down when the key was pressed. Possible values
include <code>ctrl</code>, <code>alt</code>, and <code>shift</code>.
</li><li> <var>repeat?</var>: <code>#t</code> if this is a repeated press of the same key.
</li></ol>
</li><li> <var>key-release</var>: Called with three arguments when a key is released
on the keyboard:
<ol>
<li> <var>key</var>: The symbolic name of the “virtual” key that was released.
</li><li> <var>scancode</var>: The symbolic name of the physical key that was
released.
</li><li> <var>modifiers</var>: A list of the symbolic names of modifier keys that
were being held down when the key was released.
</li></ol>
</li><li> <var>text-input</var>: Called with a single argument, a string of text,
when printable text is typed on the keyboard.
</li><li> <var>mouse-press</var>: Called with four arguments when a mouse button is
pressed:
<ol>
<li> <var>button</var>: The symbolic name of the button that was pressed, such
as <code>left</code>, <code>middle</code>, or <code>right</code>.
</li><li> <var>clicks</var>: The number of times the button has been clicked in a row.
</li><li> <var>x</var>: The x coordinate of the mouse cursor.
</li><li> <var>y</var>: The y coordinate of the mouse cursor.
</li></ol>
</li><li> <var>mouse-release</var>: Called with three arguments when a mouse button
is released:
<ol>
<li> <var>button</var>: The symbolic name of the button that was released.
</li><li> <var>x</var>: The x coordinate of the mouse cursor.
</li><li> <var>y</var>: The y coordinate of the mouse cursor.
</li></ol>
</li><li> <var>mouse-move</var>: Called with five arguments when the mouse is moved:
<ol>
<li> <var>x</var>: The x coordinate of the mouse cursor.
</li><li> <var>y</var>: The y coordinate of the mouse cursor.
</li><li> <var>dx</var>: The amount the mouse has moved along the x axis since the
last mouse move event.
</li><li> <var>dy</var>: The amount the mouse has moved along the y axis since the
last mouse move event.
</li><li> <var>buttons</var>: A list of the buttons that were pressed down when the
mouse was moved.
</li></ol>
</li><li> <var>controller-add</var>: Called with a single argument, an SDL game
controller object, when a game controller is connected.
</li><li> <var>controller-remove</var>: Called with a single argument, an SDL game
controller object, when a game controller is disconnected.
</li><li> <var>controller-press</var>: Called with two arguments when a button on a
game controller is pressed:
<ol>
<li> <var>controller</var>: The controller that triggered the event.
</li><li> <var>button</var>: The symbolic name of the button that was pressed.
Possible buttons are:
<ul>
<li> <code>a</code>
</li><li> <code>b</code>
</li><li> <code>x</code>
</li><li> <code>y</code>
</li><li> <code>back</code>
</li><li> <code>guide</code>
</li><li> <code>start</code>
</li><li> <code>left-stick</code>
</li><li> <code>right-stick</code>
</li><li> <code>left-shoulder</code>
</li><li> <code>right-shoulder</code>
</li><li> <code>dpad-up</code>
</li><li> <code>dpad-down</code>
</li><li> <code>dpad-left</code>
</li><li> <code>dpad-right</code>
</li></ul>
</li></ol>
</li><li> <var>controller-release</var>: Called with two arguments when a button on a
game controller is released:
<ol>
<li> <var>controller</var>: The controller that triggered the event.
</li><li> <var>button</var>: The symbolic name of the button that was released.
</li></ol>
</li><li> <var>controller-move</var>: Called with three arguments when an analog
stick or trigger on a game controller is moved:
<ol>
<li> <var>controller</var>: The controller that triggered the event.
</li><li> <var>axis</var>: The symbolic name of the axis that was moved. Possible
values are:
<ul>
<li> <code>left-x</code>
</li><li> <code>left-y</code>
</li><li> <code>right-x</code>
</li><li> <code>right-y</code>
</li><li> <code>trigger-left</code>
</li><li> <code>trigger-right</code>
</li></ul>
</li></ol>
</li><li> <var>error</var>: Called with three arguments when an error occurs:
<ol>
<li> <var>stack</var>: The call stack at the point of error.
</li><li> <var>key</var>: The exception key.
</li><li> <var>args</var>: The arguments thrown with the exception.
</li></ol>
<p>The default behavior is to re-throw the error.
</p>
</li></ul>
</dd></dl>
<a name="Live-Coding"></a>
<h4 class="subsection">2.1.1 Live Coding</h4>
<p>One of the biggest appeals of any Lisp dialect is the ability to use
the “read-eval-print loop” (REPL for short) to build programs
iteratively and interactively while the program is running. However,
programs that run in an event loop and respond to user input (such as
a video game) require special care for this workflow to be pleasant.
Chickadee provides no built-in support for live coding, but it’s
fairly easy to hook up a special kind of REPL yourself.
</p>
<p>First, create a cooperative REPL server (It’s important to use Guile’s
cooperative REPL server instead of the standard REPL server in
<code>(system repl server)</code> to avoid thread synchronization issues):
</p>
<div class="example">
<pre class="example">(use-modules (system repl coop-server))
(define repl (spawn-coop-repl-server))
</pre></div>
<p>Then, in the game loop’s update procedure, add this:
</p>
<div class="example">
<pre class="example">(poll-coop-repl-server repl)
</pre></div>
<p>To use the REPL, connect to it via port 37146. Telnet will do the
trick, but using the <a href="https://www.nongnu.org/geiser/">Geiser</a>
extension for Emacs is by far the best way to develop at the REPL with
Guile. Use <code>M-x connect-to-guile</code> to connect to the REPL server.
</p>
<p>Happy hacking!
</p>
<hr>
<div class="header">
<p>
Next: <a href="Math.html#Math" accesskey="n" rel="next">Math</a>, Up: <a href="API-Reference.html#API-Reference" accesskey="u" rel="up">API Reference</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Index.html#Index" title="Index" rel="index">Index</a>]</p>
</div>
</body>
</html>
|