forked from CorsixTH/CorsixTH-Graphics
-
Notifications
You must be signed in to change notification settings - Fork 0
/
manual.html
540 lines (451 loc) · 18.5 KB
/
manual.html
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
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>Making free animated graphics</title>
<style type="text/css">
/*
:Author: David Goodger ([email protected])
:Id: $Id: html4css1.css 7614 2013-02-21 15:55:51Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="making-free-animated-graphics">
<h1 class="title">Making free animated graphics</h1>
<p>This document explains how to make animation files that the CorsixTH program
can load and use in the game.</p>
<p>In CorsixTH, everything is animated. A swinging door, a walking nurse, or an
operation being performed. Even a desk or a plant is animated (repeatedly
showing the same picture, so the object looks like it is standing still).</p>
<p>In the general case however, an animation has different pictures showing
through time. A single picture displayed at a point in time is called
a <em>frame</em>. By showing slightly different pictures with each frame, and
displaying enough frames per second, the illusion of fluent motion is created.</p>
<p>A frame may consist of a single <em>sprite</em>, but it may also have many different
sprites. The advantages of having several sprites that together make up the
frame is that you can compose an animation, different parts of the animation
can be added, removed, or changed independently. Also, it enables layering of
the sprites. Sprites are rendered first to last. By adding an operating table
as one of the first elements, it can stay the same no matter what is moving on
top or in front of it. Last but not least, sprites can be re-used between
animations. All of this enables reduction of the number of sprites, which
translates to fewer sprites, and eventually reduced memory usage.</p>
<div class="section" id="animation-specification-file">
<h1>Animation specification file</h1>
<p>In an animation specification file, the animations are defined. It looks
like:</p>
<pre class="literal-block">
animation "foo" {
tile_size = 64;
view = north;
frame {
sound = 1;
element {
base = "spritefile.png";
x_offset = -25;
y_offset = -30;
alpha = 50;
hor_flip;
}
element {
...
}
}
frame {
...
}
...
}
animation "..." {
...
}
...
</pre>
<p>The file has a sequence of <tt class="docutils literal">animation</tt> blocks. Each animation has a name
(<tt class="docutils literal">"foo"</tt> in the example), and properties <tt class="docutils literal">tile_size</tt> and <tt class="docutils literal">view</tt>. The
former is optional, and defaults to 64. At the time of writing this manual,
that is also the only valid value for the tile size. In the future, the
CorsixTH program may be extended with other tile sizes.</p>
<p>The <tt class="docutils literal">view</tt> property indicates that this <tt class="docutils literal">"foo"</tt> animation is for the case
where the object being animated has been built in <tt class="docutils literal">north</tt> direction. Often
several animations exist with the same name, but a different viewing direction
(<tt class="docutils literal">north</tt>, <tt class="docutils literal">east</tt>, <tt class="docutils literal">south</tt>, and <tt class="docutils literal">west</tt> directions exist). For example a
swinging door in a north-south wall versus a swinging door in an east-west
wall. At first, only some of the possible directions will be used by the
CorsixTH program.</p>
<p>Below the properties of the animations come the frames. An animation has at
least one frame, but there can be dozens to hundreds frames, depending on the
length of the animation. All animations with the same name (but different view
direction) must have the same number of frames. (It would be weird if a
treatment would be faster in one direction and slower in another direction.)</p>
<p>Each frame starts with a <tt class="docutils literal">frame</tt> keyword. Directly below a <tt class="docutils literal">frame</tt> are its
properties, namely <tt class="docutils literal">sound</tt>. If a non-zero value is used, it denotes that the
sound matching with that number should be played when this frame is displayed.</p>
<p>In a frame, there are one or more <tt class="docutils literal">element</tt> blocks. Each element defines a
sprite to be shown at a stated position. A simple case is that a sprite has
its own <tt class="docutils literal">.png</tt> file, as shown here (other cases are explained below).
If a sprite is in its own sprite file, only mentioning the name of the
<tt class="docutils literal">.png</tt> file is sufficient as in <tt class="docutils literal">base = "spritefile.png;</tt>. The next
problem is where to position the sprite in the animation. Each animation has
an origin point (where depends on the animation). The <tt class="docutils literal">x_offset</tt> and
<tt class="docutils literal">y_offset</tt> define the number of pixels to the right and down, relative to
the origin, to display the sprite. (The origin is often near the bottom of the
animation, these number are usually negative, since <tt class="docutils literal"><span class="pre">-25</span></tt> to the right means
<tt class="docutils literal">25</tt> to the left, similarly, <tt class="docutils literal"><span class="pre">-30</span></tt> down means <tt class="docutils literal">30</tt> up.)</p>
<p>After taking a sprite from its file, it is cropped. The offsets are adjusted
as well, so the final position of the sprite is not changed.</p>
<p>The <tt class="docutils literal">alpha = 50;</tt> is an effect to make the sprite semi-transparent (<tt class="docutils literal">50%</tt>
opaque). You can also use <tt class="docutils literal">75</tt> for 75% opaqueness, and of course <tt class="docutils literal">100</tt> for
full opaqueness.
The <tt class="docutils literal">hor_flip</tt> flips right and left of the sprite, to save you from making a
new sprite. There is also a <tt class="docutils literal">vert_flip</tt> for flipping the sprite vertically.
The flip settings do not take a value.</p>
</div>
<div class="section" id="taking-a-sprite-from-a-sprite-sheet">
<h1>Taking a sprite from a sprite sheet</h1>
<p>A second common form of sprites is to have a sprite sheet, a large image
file, containing many sprites, each in its own area of the image. Only
mentioning the file is not sufficient any more in that case, you also have to
define the area to take from the file. That looks like:</p>
<pre class="literal-block">
base = "spritesheet.png";
left = 10;
top = 110;
width = 60;
height = 40;
</pre>
<p>The name of the sprite sheet file is given. The <tt class="docutils literal">left</tt> and <tt class="docutils literal">top</tt> define
the top-left coordinate in the sheet of the sprite where the area that is
wanted, starts. The <tt class="docutils literal">width</tt> defines the horizontal length, while the
<tt class="docutils literal">height</tt> defines the vertical length.</p>
<p>The given area is taken from the file, and treated like that area is the entire
file. The other steps are just as explained above, the sprite gets offsets, it
is cropped, and effects are applied.</p>
</div>
<div class="section" id="recolour-images">
<h1>Recolour images</h1>
<p>Recolouring is the process of changing the colour of part of the sprite, for
example to have different colours of cloths.</p>
<p>It is currently unclear how much use this will have (conditional displaying
explained below is another way to achieve it too), but the future will tell.</p>
<p>Recolouring can be done with a single sprite file, or with a sprite sheet. The
example here shows the case of a sprite file. In an <tt class="docutils literal">element</tt>, it looks
like:</p>
<pre class="literal-block">
base = "spritefile.png";
recolour = "recolourfile.png";
layer 4 = 2;
</pre>
<p>The <tt class="docutils literal">base</tt> is as before, it defines a 32bpp image file. The <tt class="docutils literal">recolour</tt>
also defines a file, but that must be an 8bpp image file with the same image
dimensions as the file given in <tt class="docutils literal">base</tt>. The palette of the 8bpp image is not
used, only the numeric values are of interest. For each pixel of the sprite
(in case of a sprite sheet, each pixel in the defined area), the numeric index
of the pixel at the same position in the recolour file is consulted to decide
what to do. If its numeric value is 0, no recolouring is applied. If it is any
other value (for example, it is <tt class="docutils literal">1</tt>), the intensity of the 32bpp pixel is
determined instead. That intensity is used by the CorsixTH program as index in
recolour table 1 to decide the actual colour to display.</p>
<p>Note that recolour table 1 will change depending on how to recolour. Non-zero
numeric values in the 8bpp images are therefore like logical layers (a
<tt class="docutils literal">cloth</tt> layer), rather than pointing to a known table.</p>
<p>If the numeric values in the recolour 8bpp file are not correct, <tt class="docutils literal">layer x
= y;</tt> can be used to change them. The meaning of such a statement is 'if you
encounter numeric value x, treat it as-if it is value y'. The renumbering is
not transitive, for example:</p>
<pre class="literal-block">
layer 1 = 2;
layer 2 = 1;
</pre>
<p>will swap layers 1 and 2.</p>
</div>
<div class="section" id="conditional-displaying">
<h1>Conditional displaying</h1>
<p>CorsixTH also has a conditional display feature for an element. Confusingly,
this feature uses LayerClass and LayerId in the program. To avoid confusion
with recolour layers, the animation encoder program names it <em>conditional
displaying</em>. If you write the line:</p>
<pre class="literal-block">
display_if 3 = 2;
</pre>
<p>in an element, the element will be displayed if and only if the value of layer
class <tt class="docutils literal">3</tt> is equal to <tt class="docutils literal">2</tt>.</p>
<p>At the time of writing, there is limited information available on these
display condition values. The documentation says there are thirteen layer
classes (<tt class="docutils literal">0</tt> to <tt class="docutils literal">12</tt>), and layer classes <tt class="docutils literal">0</tt> and <tt class="docutils literal">1</tt> are ignored (that
is, the element is always rendered, no matter what value you specify).</p>
<p>As more information becomes available, it may be useful to add names for
classes and ids to the animation encoder, to increase readability.</p>
</div>
<div class="section" id="loading-animation-files-into-corsixth">
<h1>Loading animation files into CorsixTH</h1>
<p>Not yet known.</p>
</div>
<div class="section" id="compiling-the-animation-encoder-program">
<h1>Compiling the animation encoder program</h1>
<p>In the <tt class="docutils literal">AnimationEncoder</tt> directory are the source files of the <tt class="docutils literal">encode</tt>
program, that takes an animation specification file, and produces an animation
data file that can be read by CorsixTH.</p>
<p>To build the entire program from its sources, you will need a scanner
generator (<em>lex</em> or <em>flex</em>), and a parser generator (<em>yacc</em> or <em>bison</em>). To
compile all code, you need a C++ compiler, for example <em>g++</em>. The code uses
<tt class="docutils literal">libpng</tt> for reading the images, so that library must be available to build
against as well. The build process for a typical Linux machine is defined in
the <tt class="docutils literal">mk</tt> file.</p>
<p>If you don't have a scanner generator or a parser generator, the source code
that they generate is also included in the directory, allowing you to skip
those generation steps.</p>
<!-- vim: tw=78 spell sw=4 sts=4 -->
</div>
</div>
</body>
</html>