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
406
407
408
409
410
411
|
* Features
** TODO [#A] Smooth animation helper
Remove the temporal aliasing in animation by interpolating between
current and previous state of animated objects.
** TODO [#B] Bitmap font rendering from tileset
Some fonts aren't available in TTF format, only as a tileset image.
It would very useful for 2D games to be able to render these. Even
better if the font rendering procedures are made polymorphic to
handle this new type of font.
** TODO [#B] Geometry combinators
A functional interface for composing complex geometry from the
simple building block of triangles. A square is 2 triangles, a
cube is 6 squares, etc. A triangle has 3 vertices with a
particular winding.
** TODO [#B] 3D model file loader
Use guile-assimp to support loading many 3D model file formats.
** TODO [#B] Multi-pass rendering pipelines
It's possible to do multi-pass rendering now by binding
framebuffers, shaders, etc. and running the same rendering code
again, but there's probably some nicer abstraction that could clean
this up.
** TODO [#B] GUI widgets
Provide a set of common graphical widgets such as buttons, scroll
bars, and sliders.
** TODO [#C] Tile maps
- [ ] Create a generic tilemap module
- [ ] Create a loader for Tiled .tmx map files.
** TODO [#C] A* pathfinding
A* is a commonly used pathfinding algorithm for games. Pathfinding
is such a common task that it would be nice to provide users with
a generic implementation.
** TODO [#C] Bounding box collision detection
Most games need simple bounding box collision detection. Provide an
efficient implementation that uses quad trees.
- [X] Rect module
- [ ] Quadtree module (needs more thought, a purely functional data
structure would be preferable)
** TODO [#C] Particle systems
Provide a highly configurible particle simulation system.
- [ ] Investigate ways to make it fast. Use guile-compost for
performance reasons.
** TODO [#C] Keymaps
Provide an Emacs-like way of defining key combinations so that
multi-button input is easy for users.
- [ ] Abstract away input methods
Controls can be bound to keys, mouse, whatever
- [ ] Basic sequences
Press A then B
- [ ] Simultaneous key presses
Press A and B at the same time
- [ ] Composing sequences
Press A then B + C
- [ ] Timeouts
Press A then B then C within 15 frames time
- [ ] Sequences with actions along the way
Press A to kick, then forward + B to uppercut, within 30 frames
time.
** TODO [#C] Shaders
- [X] Shader data type
- [ ] Scheme -> GLSL compiler
Port http://wiki.call-cc.org/eggref/4/glls to guile?
** TODO [#C] "Nine patches"
Images that have a resizable central area but fixed width/height
edges. See [[https://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch][this Android document]] for details.
** TODO [#C] Job control for agenda
Allow for pausing and cancelling jobs.
** TODO [#C] Async/threaded signals?
Not sure how to do this as some things, such as SDL and OpenGL
calls, *must* be done in the main thread. Maybe signals should
just stay synchronous.
** TODO [#C] Lighting
Ambient, point, directional, etc.
** TODO [#C] Instanced rendering
A nice optimization when rendering the same mesh a bunch of times.
* Improvements
** TODO [#A] Implement <rect>, <vector2>, <vector3>, and <vector4> as packed f64 bytevectors
Currently, it's expensive to use these types when performing OpenGL
operations such as writing to vertex buffer objects because Guile
does scm->f64 conversions before writing to a bytevector. To take
advantage of Guile 2.2's float unboxing, we can implement these
types as a record type with one field: a bytevector. The
bytevector will store all of the fields packed together. To take
advantage of unboxing, the procedures that get/set these "fields"
should be inlined.
** TODO [#B] Clean up imperative rendering API
The functional, monadic rendering API is nice and clean, but the
low-level imperative API is very messy. Perhaps it could use some
syntactic sugar for all of the "call-with-foo" forms. Also, a
naming convention needs to clearly differentiate procedures/macros
in the imperative API from those in the high-level API.
Originally, I didn't expect users to really ever have to use the
imperative API, but the introduction of sprite batches has made me
realize that writing custom low-level rendering routines will be
common enough to merit a nice API.
** TODO [#B] Treat shaders like procedures
One can view a draw call as the application of a shader program.
The arguments to the shader program are uniforms and vertices.
** TODO [#B] Use uniform buffer objects
Uniform buffer objects allow setting many uniform values at once,
rather than performing a GPU call for each, which results in better
performance.
** TODO [#C] inotify-based live reloading
Better than periodically making 'stat' calls in a loop.
* Documentation
** TODO Document rendering API
I can't settle on a rendering API, so I haven't bothered making
good docs for it. Once the above rendering tasks are complete,
it's probably safe to write docs.
** TODO Write a tutorial
Walk a beginner through the basic features of Sly and establish a
simple development workflow.
- Start the game loop
- Render a sprite
- Move the sprite
- Live hack
* Bugs
* Releases
** DONE 0.1 Release
A 0.1 release was made under the project's old name, guile-2d. Now
that things have changed so drastically and the name has been
changed, a new 0.1 release will be made.
- [X] New REPL server
Use the (system repl coop-server) module in Guile 2.0.11.
- [ ] Screencast
- [-] Relatively complete documentation (it's a start)
- [X] Clean up font module
- [X] Add GLSL shaders
- [X] Finish FRP module
- [X] Make basic webpage with HTML docs
- [X] Basic rendering (must support sprites and text)
* Archived Tasks
** DONE [#A] Game loop
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Features
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
Provide a game loop structure that responds to input events,
updates the game state, renders the scene. Use a fixed update
timestep and cap the maximum FPS.
** DONE [#A] Allow modules to declare state via signals, including OpenGL resources
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Improvements
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
This is a tricky one. The major headache with my Lisp Game Jam
attempt was that the signal framework had to be abandoned
*everywhere* except the top-level environment of the script that
starts the game loop. The reason for this was that the game state
typically required that the SDL window was opened and the OpenGL
context was available in order to work. Thus, at the top-level, we
first had to open a window and only then could we define signals.
The goal here would be to eliminate this major restriction so that
a game can be factored into many Guile modules and still declare
time varying state with signals. One important consequence here is
that all OpenGL resources *must* be declared as signals that wait
for the game loop to start before loading.
** DONE [#A] Implement sprite batch in terms of a mesh
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Improvements
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
Fix code that assumes meshes to be static, allowing for the dynamic
sprite batch use-case.
** DONE [#A] Pure Scheme 4x4 matrix multiplication implementation
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Improvements
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
Guile 2.1.2's float unboxing optimizations should enable this to be
both fast and not allocate so much. The GSL dependency can be
removed (yay!) once this is complete. Be sure to use Guile's ,x
metacommand to view the disassembly to ensure that the necessary
optimizations are indeed being used.
** DONE [#B] Use a single OpenGL resource guardian structure
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Improvements
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
This will deduplicate code amongst all Scheme data types that wrap
OpenGL resources, because right now each one uses its own separate
guardian.
** DONE [#A] Input
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Features
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
Provide hooks to respond to keyboard, mouse, and joystick events.
Wrap SDL keycode, mouse button, etc. constants in our own
enumeration.
- [X] Keyboard
- [X] Mouse
- [X] Window (active, resize, quit)
- [X] Joystick
** DONE [#A] Sprites
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Features
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
Encapsulates an image and all of its transformations: position,
rotation, scale, color, etc.
- [X] Use SDL2_image
- [X] Add support for texture regions
- [X] Add support for animations
- [X] Use a sprite batch when drawing if one is currently bound
** DONE [#A] Sprite batches
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Features
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
Efficiently render a large number of sprites. Only change OpenGL
context when necessary. For example, don't change texture when
rendering several sprites in a row that use the same one.
- Use streaming vertex buffers
- See: https://www.opengl.org/wiki/Buffer_Object#Mapping
- See: https://www.opengl.org/wiki/Buffer_Object_Streaming
- See: https://bitbucket.org/rude/love/src/d95dfb67079a60f8de64304dac9002544695f1bb/src/modules/graphics/opengl/SpriteBatch.cpp?at=default
** DONE [#A] Tilesets
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Features
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
Break an image up into many small pieces. Useful for creating maps.
- [X] Algorithm to split texture into tiles
- [X] <tileset> type
** DONE [#A] Coroutines
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Features
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
Provide a way for users to easily script asynchronous behaviors
using coroutines and a scheduler.
- [X] Coroutines
- [X] Agenda
** DONE [#A] Vectors and matrices
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Features
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
Vectors and matrices are needed constantly for games. Provide an
easy-to-use module that provides procedures for common
vector/matrix math operations
- [X] Vectors
- [X] Matrices
** DONE [#A] Fonts
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Features
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
- [X] Write wrappers for needed FTGL functions
- [X] Write font rendering procedures
** DONE [#A] Sound
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Features
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
Provide helpful wrappers around SDL sound procedures?
** DONE [#A] REPL
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Features
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
Provide a REPL that plays nice with the game loop. Easier said than
done.
- [X] Modify Guile's REPL to work with the game loop
- Short-term solution that *mostly* works
- [X] Write a new REPL that runs in the current thread
- Use coroutines
- Read user input from a separate thread so as to not block the
main thread
- Will be available in Guile 2.0.10!
** DONE [#A] Upgrade to SDL2
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Features
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
- Write necessary bindings and release [[https://git.dthompson.us/guile-sdl2.git][guile-sdl2]].
- Replace freeimage with sdl_image 2.0
** DONE [#B] Animations
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Features
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
Create a data type to represent an animated sequence of textures
and/or texture regions.
** DONE [#B] Asset Management
:PROPERTIES:
:ARCHIVE_TIME: 2016-02-27 Sat 12:07
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Features
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
- [X] Live asset reloading
** DONE [#A] Actors and scripts
:PROPERTIES:
:ARCHIVE_TIME: 2016-04-24 Sun 19:22
:ARCHIVE_FILE: ~/Code/sly/TODO.org
:ARCHIVE_OLPATH: Features
:ARCHIVE_CATEGORY: TODO
:ARCHIVE_TODO: DONE
:END:
Provide a purely functional means of scripting objects using a
monadic combinator interface.
|