Codebase list holotz-castle / 6aaa6ec
Import Upstream version 1.3.14 Markus Koschany 3 years ago
1505 changed file(s) with 52229 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Formato de ficheros ASE
23 * @file JASEFormat.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 20/09/2003
26 * @version 0.0.1 - 20/09/2003 - Primera versión.
27 */
28
29 #include <JLib/Graphics/JASEFormat.h>
30
31 u32 JASEFormat::nextTextureId;
32 u32 JASEFormat::textureBaseId;
33
34 // Destructor
35 JASEFormat::~JASEFormat()
36 {
37 if (materials)
38 delete[] materials;
39
40 if (objects)
41 {
42 for (s32 i = 0; i < numObjects; ++i)
43 {
44 if (objects[i].vertices)
45 delete[] objects[i].vertices;
46
47 if (objects[i].tVertices)
48 delete[] objects[i].tVertices;
49
50 if (objects[i].vertexNormals)
51 delete[] objects[i].vertexNormals;
52
53 if (objects[i].faces)
54 delete[] objects[i].faces;
55
56 if (objects[i].tFaces)
57 delete[] objects[i].tFaces;
58 }
59
60 delete[] objects;
61 }
62 };
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Etiquetas de ficheros ASE
23 * @file JASEFormat.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 20/09/2003
26 * @version 0.0.1 - 20/09/2003 - Primera versión.
27 */
28
29 #ifndef _JASEFORMAT_INCLUDED
30 #define _JASEFORMAT_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Util/JObject.h>
34
35 // Tags del formato ASE. Son las cadenas a utilizar por scanf más adelante.
36
37 /** Cabecera de fichero. */
38 #define JASETAG_FILE_HEADER "*3DSMAX_ASCIIEXPORT"
39
40 /** La versión para la que se hace, no cuenta para validar el ase. */
41 #define JASETAG_FILE_VERSION "200"
42
43 /** Escena. */
44 #define JASETAG_SCENE "*SCENE"
45 /** Ordinal del primer cuadro. */
46 #define JASETAG_SCENE_FIRSTFRAME "*SCENE_FIRSTFRAME"
47 /** Ordinal del último cuadro. */
48 #define JASETAG_SCENE_LASTFRAME "*SCENE_LASTFRAME"
49 /** Lista de materiales. */
50 #define JASETAG_MATERIAL_LIST "*MATERIAL_LIST"
51 /** Número de materiales. */
52 #define JASETAG_MATERIAL_COUNT "*MATERIAL_COUNT"
53 /** Material. */
54 #define JASETAG_MATERIAL "*MATERIAL"
55 /** Núemro de submateriales. */
56 #define JASETAG_SUBMATERIAL_COUNT "*NUMSUBMTLS"
57 /** Submaterial. */
58 #define JASETAG_SUBMATERIAL "*SUBMATERIAL"
59 /** Tipo de material. */
60 #define JASETAG_MATERIAL_CLASS "*MATERIAL_CLASS"
61 /** Material Multi/sub-objeto. */
62 #define JASEVAL_MULTI_SUBOBJECT "\"Multi/Sub-Object\""
63 /** Material estándar. */
64 #define JASEVAL_STANDARD "\"Standard\""
65 /** Color ambiente del material. */
66 #define JASETAG_MATERIAL_AMBIENT "*MATERIAL_AMBIENT"
67 /** Color difuso del material. */
68 #define JASETAG_MATERIAL_DIFFUSE "*MATERIAL_DIFFUSE"
69 /** Color especular del material. */
70 #define JASETAG_MATERIAL_SPECULAR "*MATERIAL_SPECULAR"
71 /** Flag de brillo del material. */
72 #define JASETAG_MATERIAL_SHINE "*MATERIAL_SHINE"
73 /** Intensidad de brillo del material. */
74 #define JASETAG_MATERIAL_SHINESTRENGTH "*MATERIAL_SHINESTRENGTH"
75 /** Transparencia del material. */
76 #define JASETAG_MATERIAL_TRANSPARENCY "*MATERIAL_TRANSPARENCY"
77 /** Iluminación propia. */
78 #define JASETAG_MATERIAL_SELFILLUM "*MATERIAL_SELFILLUM"
79 /** Tipo XP. */
80 #define JASETAG_MATERIAL_XP_TYPE "*MATERIAL_XP_TYPE"
81 /** Mapa difuso del material. */
82 #define JASETAG_MATERIAL_MAP_DIFFUSE "*MAP_DIFFUSE"
83 /** Subnúmero del mapa del material. */
84 #define JASETAG_MATERIAL_MAP_SUBNO "*MAP_SUBNO"
85 /** Textura del material. */
86 #define JASETAG_MATERIAL_BITMAP "*BITMAP"
87 /** Objeto. */
88 #define JASETAG_GEOMOBJECT "*GEOMOBJECT"
89 /** Nombre. */
90 #define JASETAG_NODE_NAME "*NODE_NAME"
91 /** Geometría. */
92 #define JASETAG_MESH "*MESH"
93 /** Tiempo dentro de la animación. */
94 #define JASETAG_TIMEVALUE "*TIMEVALUE"
95 /** Númerod evértices. */
96 #define JASETAG_MESH_NUMVERTEX "*MESH_NUMVERTEX"
97 /** Número de caras. */
98 #define JASETAG_MESH_NUMFACES "*MESH_NUMFACES"
99 /** Lista de vértices. */
100 #define JASETAG_MESH_VERTEX_LIST "*MESH_VERTEX_LIST"
101 /** Vértice. */
102 #define JASETAG_MESH_VERTEX "*MESH_VERTEX"
103 /** Lista de caras. */
104 #define JASETAG_MESH_FACE_LIST "*MESH_FACE_LIST"
105 /** Cara. */
106 #define JASETAG_MESH_FACE "*MESH_FACE"
107 /** Primer vértice. */
108 #define JASETAG_MESH_A "A:"
109 /** Segundo vértice. */
110 #define JASETAG_MESH_B "B:"
111 /** Tercer vértice. */
112 #define JASETAG_MESH_C "C:"
113 /** ID del material asociado. */
114 #define JASETAG_MESH_MTLID "*MESH_MTLID"
115 /** Núemro de vértices con textura. */
116 #define JASETAG_MESH_NUMTVERTEX "*MESH_NUMTVERTEX"
117 /** Lista de vértices con textura. */
118 #define JASETAG_MESH_TVERTLIST "*MESH_TVERTLIST"
119 /** Vértice con textura. */
120 #define JASETAG_MESH_TVERT "*MESH_TVERT"
121 /** Número de caras con textura. */
122 #define JASETAG_MESH_NUMTVFACES "*MESH_NUMTVFACES"
123 /** Lista de caras con textura. */
124 #define JASETAG_MESH_TFACELIST "*MESH_TFACELIST"
125 /** Cara con textura. */
126 #define JASETAG_MESH_TFACE "*MESH_TFACE"
127 /** Lista de normales. */
128 #define JASETAG_MESH_NORMALS "*MESH_NORMALS"
129 /** Normales de cara. */
130 #define JASETAG_MESH_FACENORMAL "*MESH_FACENORMAL"
131 /** Normales de vértice. */
132 #define JASETAG_MESH_VERTEXNORMAL "*MESH_VERTEXNORMAL"
133 /** Núemro de material. */
134 #define JASETAG_MATERIAL_REF "*MATERIAL_REF"
135
136 #endif // _JASEFORMAT_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 20/09/2003
25 // @description: Cargador de ficheros ASE
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #include <JLib/Graphics/JASELoader.h>
29 #include <JLib/Math/JVector.h>
30
31 s32 JASELoader::Load(const s8 *fileName, JASEFormat *fmt)
32 {
33 if (!fmt)
34 return 3;
35
36 if (!f.Open(fileName) || !f.Read())
37 return 1;
38
39 // La cabecera debe coincidir, no exigimos tanto a la versión,
40 // al menos lo intentamos
41 if (!f.FindNext(JASETAG_FILE_HEADER) || !f.SkipNextWord())
42 return false;
43
44 // Versión del fichero
45 f.ReadInteger(&fmt->fileVersion);
46
47 // Primer frame
48 if (!f.FindNext(JASETAG_SCENE_FIRSTFRAME) || !f.SkipNextWord())
49 fmt->firstFrame = 0;
50 else
51 f.ReadInteger(&fmt->firstFrame);
52
53 // Último frame
54 if (!f.FindNext(JASETAG_SCENE_LASTFRAME) || !f.SkipNextWord())
55 fmt->lastFrame = 0;
56 else
57 f.ReadInteger(&fmt->lastFrame);
58
59 if (LoadMaterials(fmt))
60 if (LoadObjects(fmt))
61 return 0;
62
63 return 2;
64 }
65
66 // Carga los materiales del fichero ASE.
67 // Devuelve true si todo fue bien, false en caso contrario.
68 bool JASELoader::LoadMaterials(JASEFormat *fmt)
69 {
70 f.StartOfDocument();
71
72 if (!f.FindNext(JASETAG_MATERIAL_COUNT))
73 return false;
74
75 f.SkipNextWord();
76 f.ReadInteger(&fmt->numMaterials);
77
78 // Contamos como materiales los submateriales que haya
79 f.StartOfDocument();
80 s32 c = 0;
81 while (f.FindNext(JASETAG_SUBMATERIAL_COUNT))
82 {
83 f.SkipNextWord();
84 f.ReadInteger(&c);
85 fmt->numMaterials += c;
86 }
87
88 f.StartOfDocument();
89 fmt->materials = new JASEMaterial[fmt->numMaterials];
90 fmt->numTextures = 0;
91 memset(fmt->materials, 0, sizeof(JASEMaterial) * fmt->numMaterials);
92
93 JASEMaterial *mats = fmt->materials;
94 s32 i = 0;
95 while (i < fmt->numMaterials)
96 {
97 // En el nivel superior no hay submateriales
98 mats[i].parentId = -1;
99 mats[i].isSubMaterial = false;
100
101 f.FindNext(JASETAG_MATERIAL_LIST);
102 f.SkipNextWord();
103 f.FindNext(JASETAG_MATERIAL_COUNT);
104 f.SkipNextWord();
105 f.FindNext(JASETAG_MATERIAL);
106 f.SkipNextWord();
107 f.ReadInteger(&mats[i].id);
108
109 // Tipo de material
110 f.FindNext(JASETAG_MATERIAL_CLASS);
111 f.SkipNextWord();
112 f.ReadWord(mats[i].mtlClass);
113
114 // Color ambiente
115 f.FindNext(JASETAG_MATERIAL_AMBIENT); f.SkipNextWord();
116 f.ReadFloat(&mats[i].ambient.r); f.ReadFloat(&mats[i].ambient.g); f.ReadFloat(&mats[i].ambient.b);
117
118 // Color difuso
119 f.FindNext(JASETAG_MATERIAL_DIFFUSE); f.SkipNextWord();
120 f.ReadFloat(&mats[i].diffuse.r); f.ReadFloat(&mats[i].diffuse.g); f.ReadFloat(&mats[i].diffuse.b);
121
122 // Color especular
123 f.FindNext(JASETAG_MATERIAL_SPECULAR); f.SkipNextWord();
124 f.ReadFloat(&mats[i].specular.r); f.ReadFloat(&mats[i].specular.g); f.ReadFloat(&mats[i].specular.b);
125
126 // Brillo
127 f.FindNext(JASETAG_MATERIAL_SHINE); f.SkipNextWord();
128 f.ReadFloat(&mats[i].shine);
129
130 // Fuerza de brillo
131 f.FindNext(JASETAG_MATERIAL_SHINESTRENGTH); f.SkipNextWord();
132 f.ReadFloat(&mats[i].shineStrenght);
133
134 // Transparencia
135 f.FindNext(JASETAG_MATERIAL_TRANSPARENCY); f.SkipNextWord();
136 f.ReadFloat(&mats[i].transparency);
137
138 s8 str[32]; // Cadena auxiliar
139
140 if (0 == strcmp(mats[i].mtlClass, JASEVAL_MULTI_SUBOBJECT))
141 {
142 // Material multi/subobjeto: procesamos los submateriales
143 // No tiene el parámetro selfIllum
144 mats[i].isMulti = true;
145
146 f.FindNext(JASETAG_SUBMATERIAL_COUNT);
147 f.SkipNextWord();
148 f.ReadInteger(&mats[i].numSubMaterials);
149
150 for (s32 j = i+1; j < i + 1 + mats[i].numSubMaterials; ++j)
151 {
152 mats[j].parentId = mats[i].id;
153 f.FindNext(JASETAG_SUBMATERIAL); f.SkipNextWord();
154 f.ReadInteger(&mats[j].id);
155
156 // Sólo está permitido un nivel de jerarquía, así que no comprobamos
157 // si es Multi/Sub-object
158 f.FindNext(JASETAG_MATERIAL_CLASS);
159 f.SkipNextWord();
160 f.ReadWord(mats[j].mtlClass);
161 mats[j].isSubMaterial = true;
162
163 // Color ambiente
164 f.FindNext(JASETAG_MATERIAL_AMBIENT); f.SkipNextWord();
165 f.ReadFloat(&mats[j].ambient.r); f.ReadFloat(&mats[j].ambient.g); f.ReadFloat(&mats[j].ambient.b);
166
167 // Color difuso
168 f.FindNext(JASETAG_MATERIAL_DIFFUSE); f.SkipNextWord();
169 f.ReadFloat(&mats[j].diffuse.r); f.ReadFloat(&mats[j].diffuse.g); f.ReadFloat(&mats[j].diffuse.b);
170
171 // Color especular
172 f.FindNext(JASETAG_MATERIAL_SPECULAR); f.SkipNextWord();
173 f.ReadFloat(&mats[j].specular.r); f.ReadFloat(&mats[j].specular.g); f.ReadFloat(&mats[j].specular.b);
174
175 // Brillo
176 f.FindNext(JASETAG_MATERIAL_SHINE); f.SkipNextWord();
177 f.ReadFloat(&mats[j].shine);
178
179 // Fuerza de brillo
180 f.FindNext(JASETAG_MATERIAL_SHINESTRENGTH); f.SkipNextWord();
181 f.ReadFloat(&mats[j].shineStrenght);
182
183 // Transparencia
184 f.FindNext(JASETAG_MATERIAL_TRANSPARENCY); f.SkipNextWord();
185 f.ReadFloat(&mats[j].transparency);
186
187 // Iluminación propia
188 f.FindNext(JASETAG_MATERIAL_SELFILLUM); f.SkipNextWord();
189 f.ReadFloat(&mats[j].selfIllum);
190
191 // Si tiene una textura asociada aparecerá en la línea siguiente a
192 // MATERIAL_XP_TYPE
193 f.FindNext(JASETAG_MATERIAL_XP_TYPE);
194 f.NextLine();
195 f.ReadWord(str);
196
197 if (strcmp(str, JASETAG_MATERIAL_MAP_DIFFUSE) == 0)
198 {
199 ++fmt->numTextures;
200 mats[j].hasTexture = true;
201 mats[j].textureId = fmt->GetTextureId();
202
203 f.FindNext(JASETAG_MATERIAL_BITMAP); f.SkipNextWord();
204 f.ReadWord(mats[j].texture);
205 u32 len = (u32)strlen(mats[j].texture);
206 memmove(&mats[j].texture[0], &mats[j].texture[1], len - 1);
207 mats[j].texture[len - 2] = 0;
208 }
209 }
210 }
211 else
212 {
213 // Material standard u otro
214 mats[i].isMulti = false;
215 mats[i].numSubMaterials = 0;
216
217 // Iluminación propia
218 f.FindNext(JASETAG_MATERIAL_SELFILLUM); f.SkipNextWord();
219 f.ReadFloat(&mats[i].selfIllum);
220
221 // Si tiene una textura asociada aparecerá en la línea siguiente a
222 // MATERIAL_XP_TYPE
223 f.FindNext(JASETAG_MATERIAL_XP_TYPE);
224 f.NextLine();
225 f.ReadWord(str);
226
227 if (strcmp(str, JASETAG_MATERIAL_MAP_DIFFUSE) == 0)
228 {
229 ++fmt->numTextures;
230 mats[i].hasTexture = true;
231 mats[i].textureId = fmt->GetTextureId();
232
233 f.FindNext(JASETAG_MATERIAL_BITMAP); f.SkipNextWord();
234 f.ReadWord(mats[i].texture);
235 u32 len = (u32)strlen(mats[i].texture);
236 memmove(&mats[i].texture[0], &mats[i].texture[1], len - 1);
237 mats[i].texture[len - 2] = 0;
238 }
239 }
240
241 // Acumulamos los submateriales procesados y/o el actual
242 i += mats[i].numSubMaterials + 1;
243 }
244
245 return true;
246 }
247
248 // Carga los objetos (geometría) del fichero ASE.
249 // Devuelve true si todo fue bien, false en otro caso.
250 bool JASELoader::LoadObjects(JASEFormat *fmt)
251 {
252 f.StartOfDocument();
253
254 // Cuenta los objetos
255 fmt->numObjects = 0;
256 while (f.FindNext(JASETAG_GEOMOBJECT))
257 {
258 f.SkipNextWord();
259 ++fmt->numObjects;
260 }
261
262 // Crea el array de objetos
263 fmt->objects = new JASEMesh[fmt->numObjects];
264 JASEMesh *objs = fmt->objects;
265
266 f.StartOfDocument();
267
268 for (s32 i = 0; i < fmt->numObjects; ++i)
269 {
270 // Nombre
271 f.FindNext(JASETAG_NODE_NAME); f.SkipNextWord();
272 f.ReadWord(objs[i].name);
273
274 // Quita las comillas
275 u32 len = (u32)strlen(objs[i].name);
276 memmove(&objs[i].name[0], &objs[i].name[1], len - 1);
277 objs[i].name[len - 2] = 0;
278
279 // Procesa la geometría...
280 f.FindNext(JASETAG_MESH); f.SkipNextWord();
281 s8 *oldPos = f.GetPos();
282
283 // Número de vértices: crea el array de vértices y de normales
284 if (i == 64)
285 i = i;
286 f.FindNext(JASETAG_MESH_NUMVERTEX); f.SkipNextWord();
287 f.ReadInteger(&objs[i].numVertices);
288 objs[i].vertices = new JASEVertex[objs[i].numVertices];
289
290 JASEVertex *verts = objs[i].vertices;
291
292 // Número de caras: crea el array de caras
293 f.FindNext(JASETAG_MESH_NUMFACES); f.SkipNextWord();
294 f.ReadInteger(&objs[i].numFaces);
295 objs[i].faces = new JASEFace[objs[i].numFaces];
296
297 JASEFace *faces = objs[i].faces;
298
299 // Lista de vértices
300 f.FindNext(JASETAG_MESH_VERTEX_LIST); f.SkipNextWord();
301 for (s32 j = 0; j < objs[i].numVertices; ++j)
302 {
303 f.FindNext(JASETAG_MESH_VERTEX); f.SkipNextWord(); f.SkipNextWord(); // Saltamos el índice de vértice
304
305 // OJO! MAX da la vuelta... hay que cambiar Y por -Z
306 f.ReadFloat(&verts[j].x); f.ReadFloat(&verts[j].z); f.ReadFloat(&verts[j].y);
307 verts[j].z = -verts[j].z;
308 }
309
310 // Buscamos primero la referencia del material...
311 s32 mtlRef;
312
313 f.FindNext(JASETAG_MATERIAL_REF);f.SkipNextWord();
314 f.ReadInteger(&mtlRef);
315
316 // ...Buscamos el material correspondiente a esa referencia...
317 s32 mtlIndex = 0;
318 while (mtlIndex < fmt->numMaterials && fmt->materials[mtlIndex].id != mtlRef)
319 {
320 // Avanzamos el nº de submateriales que indique este material y vamos al siguiente
321 if (fmt->materials[mtlIndex].isMulti)
322 mtlIndex += fmt->materials[mtlIndex].numSubMaterials;
323 else
324 ++mtlIndex;
325 }
326
327 // Si no lo encuentra, salimos
328 if (fmt->materials[mtlIndex].id != mtlRef)
329 return false;
330
331 // Si lo encontró, volvemos al punto de inicio
332 f.SetPos(oldPos);
333
334 // Asignamos el material a la cara (queda pendiente ponerle textura) ...
335 s32 vInd;
336
337 if (fmt->materials[mtlIndex].isMulti)
338 {
339 // Lista de caras
340 s32 m;
341
342 f.FindNext(JASETAG_MESH_FACE_LIST); f.SkipNextWord();
343 for (s32 k = 0; k < objs[i].numFaces; ++k)
344 {
345 // A:
346 f.FindNext(JASETAG_MESH_A); f.SkipNextWord();
347 f.ReadInteger(&faces[k].v1);
348 // B:
349 f.FindNext(JASETAG_MESH_B); f.SkipNextWord();
350 f.ReadInteger(&faces[k].v2);
351 // C:
352 f.FindNext(JASETAG_MESH_C); f.SkipNextWord();
353 f.ReadInteger(&faces[k].v3);
354
355 // MTLID
356 f.FindNext(JASETAG_MESH_MTLID); f.SkipNextWord();
357 f.ReadInteger(&m);
358
359 // Si es Multi/subobjeto debemos atender al MTLID de las caras...
360 // v. nota al comienzo del .h
361 faces[k].material = &fmt->materials[mtlIndex + 1 + (m%fmt->materials[mtlIndex].numSubMaterials)];
362 }
363 }
364 else
365 {
366 // MATERIAL_REF
367
368 // Lista de caras
369 f.FindNext(JASETAG_MESH_FACE_LIST); f.SkipNextWord();
370 for (s32 k = 0; k < objs[i].numFaces; ++k)
371 {
372 f.FindNext(JASETAG_MESH_FACE);
373 // A:
374 f.FindNext(JASETAG_MESH_A); f.SkipNextWord();
375 f.ReadInteger(&faces[k].v1);
376 // B:
377 f.FindNext(JASETAG_MESH_B); f.SkipNextWord();
378 f.ReadInteger(&faces[k].v2);
379 // C:
380 f.FindNext(JASETAG_MESH_C); f.SkipNextWord();
381 f.ReadInteger(&faces[k].v3);
382
383 // Al no tener un material Multi asignado, todas las caras tienen el
384 // material indicado en MATERIAL_REF
385 faces[k].material = &fmt->materials[mtlIndex];
386 }
387 }
388
389 // Texturas.
390
391 // El número de vértices de textura puede ser (y, en general, será)
392 // diferente al número de vértices totales
393 f.FindNext(JASETAG_MESH_NUMTVERTEX); f.SkipNextWord();
394 f.ReadInteger(&objs[i].numTVertices);
395
396 // Creamos el array de vértices de textura y lo rellenamos
397 objs[i].tVertices = new JASETextureVertex[objs[i].numTVertices];
398
399 if (f.FindNext(JASETAG_MESH_TVERTLIST))
400 {
401 f.SkipNextWord();
402 for (s32 b = 0; b < objs[i].numTVertices; ++b)
403 {
404 f.FindNext(JASETAG_MESH_TVERT); f.SkipNextWord(); f.SkipNextWord();
405
406 // OJO: Comprobar que x e y corresponden a las mismas U, V en OpenGL
407 f.ReadFloat(&objs[i].tVertices[b].u);
408 f.ReadFloat(&objs[i].tVertices[b].v);
409 }
410 }
411
412 // El número de caras de textura puede es
413 // igual al número de caras totales
414 if (f.FindNext(JASETAG_MESH_NUMTVFACES))
415 {
416 f.SkipNextWord();
417 f.ReadInteger(&objs[i].numTFaces);
418
419 // Creamos el array de caras de textura y lo rellenamos
420 if (objs[i].numTFaces > 0)
421 {
422 objs[i].tFaces = new JASETextureFace[objs[i].numTFaces];
423
424 f.FindNext(JASETAG_MESH_TFACELIST); f.SkipNextWord();
425 for (s32 c = 0; c < objs[i].numTFaces; ++c)
426 {
427 f.FindNext(JASETAG_MESH_TFACE); f.SkipNextWord(); f.SkipNextWord();
428 f.ReadInteger(&objs[i].tFaces[c].v1);
429 f.ReadInteger(&objs[i].tFaces[c].v2);
430 f.ReadInteger(&objs[i].tFaces[c].v3);
431 }
432 }
433 }
434
435 // Calcula las normales a las caras
436 objs[i].vertexNormals = new JASEVertex[objs[i].numVertices];
437 memset(objs[i].vertexNormals, 0, sizeof(JASEVertex) * objs[i].numVertices);
438
439 JASEVertex *vNorm = objs[i].vertexNormals;
440 JVector v1, v2, v3, vt1, vt2, vn;
441
442 for (s32 d = 0; d < objs[i].numFaces; ++d)
443 {
444 if (d == 35)
445 d = d;
446
447 v1 = JVector(objs[i].vertices[faces[d].v1].x,
448 objs[i].vertices[faces[d].v1].y,
449 objs[i].vertices[faces[d].v1].z);
450 v2 = JVector(objs[i].vertices[faces[d].v2].x,
451 objs[i].vertices[faces[d].v2].y,
452 objs[i].vertices[faces[d].v2].z);
453 v3 = JVector(objs[i].vertices[faces[d].v3].x,
454 objs[i].vertices[faces[d].v3].y,
455 objs[i].vertices[faces[d].v3].z);
456
457 vt1 = (v3 - v1);
458 vt2 = (v3 - v2);
459 vn = vt1.Cross(vt2);
460 vn.Normalize();
461 faces[d].normal.x = vn.x;
462 faces[d].normal.y = vn.y;
463 faces[d].normal.z = vn.z;
464 }
465
466 // Asigna las normales a cada vértice
467 s32 *shared = new s32[objs[i].numVertices];
468 memset(shared, 0, sizeof(s32) * objs[i].numVertices);
469
470 for (s32 k = 0; k < objs[i].numFaces; ++k)
471 {
472 if (i == 219 && k == 68)
473 i = i;
474
475 // Si algún día quieres quedarte con las normales del ASE...
476 /*
477 f.FindNext(JASETAG_MESH_FACENORMAL); f.SkipNextWord(); f.SkipNextWord();
478 f.ReadFloat(&faces[k].normal.x);
479 f.ReadFloat(&faces[k].normal.z); // Por el cambio de MAX y -> -z
480 f.ReadFloat(&faces[k].normal.y);
481 faces[k].normal.z = -faces[k].normal.z;
482 */
483
484 // Suma las normales dadas a cada vértice de la cara. Resultado:
485 // al final todas las normales estarán promediadas en cada vértice.
486 f.FindNext(JASETAG_MESH_VERTEXNORMAL); f.SkipNextWord();
487 f.ReadInteger(&vInd);
488 vNorm[vInd].x += faces[k].normal.x;
489 vNorm[vInd].y += faces[k].normal.y;
490 vNorm[vInd].z += faces[k].normal.z;
491 ++shared[vInd];
492
493 f.FindNext(JASETAG_MESH_VERTEXNORMAL); f.SkipNextWord();
494 f.ReadInteger(&vInd);
495 vNorm[vInd].x += faces[k].normal.x;
496 vNorm[vInd].y += faces[k].normal.y;
497 vNorm[vInd].z += faces[k].normal.z;
498 ++shared[vInd];
499
500 f.FindNext(JASETAG_MESH_VERTEXNORMAL); f.SkipNextWord();
501 f.ReadInteger(&vInd);
502 vNorm[vInd].x += faces[k].normal.x;
503 vNorm[vInd].y += faces[k].normal.y;
504 vNorm[vInd].z += faces[k].normal.z;
505 ++shared[vInd];
506 }
507
508 // Promedia y normaliza las normales sumadas para cada vértice
509 for (s32 h = 0; h < objs[i].numVertices; ++h)
510 {
511 vn = JVector(objs[i].vertexNormals[h].x,
512 objs[i].vertexNormals[h].y,
513 objs[i].vertexNormals[h].z);
514 vn /= JScalar(shared[h]);
515 vn.Normalize();
516 objs[i].vertexNormals[h].x = vn.x;
517 objs[i].vertexNormals[h].y = vn.y;
518 objs[i].vertexNormals[h].z = vn.z;
519 }
520
521 delete[] shared;
522 }
523
524 return true;
525 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Cargador de ficheros ASE.
23 * @author: Juan Carlos Seijo Pérez
24 * @date: 20/09/2003
25 * @notes: Curiosidad de MAX 5, pongo el ejemplo:
26 * Supongamos una escena con tres bolas que comparten el mismo material multi/subobjeto
27 * compuesto de tres submateriales de id 1, 2 y 3, respectivamente. Si las bolas
28 * tienen id's 1, 2 y 3 respectivamente se asignarán de esa forma los submateriales
29 * a cada una de ellas. Sin embargo si alguna de ellas tiene un valor diferente (mayor),
30 * el material que aplica MAX es el resto de dividir el id de la bola menos uno entre el número
31 * de submateriales del material y todo eso más uno.
32 * Así si las bolas tienen id's 1, 22, 8, respectivamente,
33 * - a la bola con MTLID 1 se le asigna el submaterial: ((1-1)%3) + 1 = (0%3) + 1 = 0 + 1 = 1
34 * - a la bola con MTLID 23 se le asigna el submaterial: ((23-1)%3) + 1 = (21%3) + 1 = 0 + 1 = 1
35 * - a la bola con MTLID 7 se le asigna el submaterial: ((8-1)%3) + 1 = (7%3) + 1 = 1 + 1 = 2
36 *
37 * Notad que en el ASE el MTLID es uno menos que en la escena ya.
38 */
39
40 #ifndef _JASELOADER_INCLUDED
41 #define _JASELOADER_INCLUDED
42
43 #include <JLib/Util/JTypes.h>
44 #include <JLib/Util/JTextFile.h>
45 #include <JLib/Graphics/JASEFormat.h>
46
47 /** Cargador de ficheros ASE.
48 */
49 class JASELoader : public JObject
50 {
51 JTextFile f; /**< Fichero ASE */
52
53 /** Carga los objetos (geometría) del fichero ASE.
54 * @return <b>true</b> si todo fue bien, <b>false</b> en otro caso.
55 */
56 bool LoadObjects(JASEFormat *fmt);
57
58 /** Carga los materiales del fichero ASE.
59 * @return <b>true</b> si todo fue bien, <b>false</b> en otro caso.
60 */
61 bool LoadMaterials(JASEFormat *fmt);
62
63 public:
64 /** Carga un fichero ase.
65 * @return: 0 - si el fichero se cargó correctamente,
66 * 1 - si no existe el fichero,
67 * 2 - si el formato está corrupto,
68 * 3 - si fmt es nulo.
69 */
70 s32 Load(const s8 *fileName, JASEFormat *fmt);
71 };
72
73 #endif // _JASELOADER_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clase base de un control de interfaz de usuario.
23 * @file JControl.cpp.
24 * @author Juan Carlos Seijo Pérez.
25 * @date 27/10/2003.
26 * @version 0.0.1 - 27/10/2003 - Primera versión.
27 */
28
29 #include <JLib/Graphics/JControl.h>
30
31 u32 JControl::controlCount;
32
33 const u32 JControl::VISIBLE = 0x00000001;
34 const u32 JControl::FOCUSED = 0x00000002;
35 const u32 JControl::ENABLED = 0x00000004;
36 const u32 JControl::SELECTED = 0x00000008;
37
38 // Constructor
39 JControl::JControl(JControl *_parent,
40 u32 _state) : parent(_parent), focusIndex(++controlCount), state(_state),
41 focus(0), unfocus(0), enable(0), disable(0), appear(0), disappear(0),
42 select(0), unselect(0), focusData(0), unfocusData(0),
43 enableData(0), disableData(0), appearData(0), disappearData(0),
44 selectData(0), unselectData(0)
45
46 {
47 id = controlCount;
48 }
49
50 // Destructor
51 JControl::~JControl()
52 {
53 --controlCount;
54 }
55
56 // Actualiza el control. Devuelve el estado del control.
57 void JControl::Draw()
58 {
59 if (Visible())
60 {
61 if (Enabled())
62 {
63 if (Selected())
64 {
65 DrawSelected();
66 }
67 else if (Focused())
68 {
69 DrawFocus();
70 }
71 else
72 {
73 DrawVisible();
74 }
75 }
76 else
77 {
78 DrawDisabled();
79 }
80 }
81 }
82
83 // Actualiza el control. Devuelve el estado del control.
84 s32 JControl::Update()
85 {
86 if (Visible())
87 {
88 if (Enabled())
89 {
90 if (Selected())
91 {
92 return UpdateSelected();
93 }
94 else if (Focused())
95 {
96 return UpdateFocus();
97 }
98 else
99 {
100 return UpdateVisible();
101 }
102 }
103 else
104 {
105 return UpdateDisabled();
106 }
107 }
108
109 return state;
110 }
111
112 // Muestra el control
113 void JControl:: Appear()
114 {
115 if (!Visible())
116 {
117 state &= VISIBLE;
118
119 OnAppear();
120 }
121 }
122
123 // Oculta el control
124 void JControl:: Disappear()
125 {
126 if (Visible())
127 {
128 state &= ~VISIBLE;
129
130 OnDisappear();
131 }
132 }
133
134 // Habilita el control
135 void JControl:: Enable()
136 {
137 if (!Enabled())
138 {
139 state &= ENABLED;
140
141 OnEnable();
142 }
143 }
144
145 // Deshabilita el control
146 void JControl:: Disable()
147 {
148 if (Enabled())
149 {
150 state &= ~ENABLED;
151
152 OnDisable();
153 }
154 }
155
156 // Enfoca el control
157 void JControl:: Focus()
158 {
159 if (!Focused())
160 {
161 state &= FOCUSED;
162
163 OnFocus();
164 }
165 }
166
167 // Desenfoca el control
168 void JControl:: Unfocus()
169 {
170 if (Focused())
171 {
172 state &= ~FOCUSED;
173
174 OnUnfocus();
175 }
176 }
177
178 // Selecciona el control
179 void JControl:: Select()
180 {
181 if (!Selected())
182 {
183 state &= SELECTED;
184
185 OnSelect();
186 }
187 }
188
189 // Deselecciona el control
190 void JControl:: Unselect()
191 {
192 if (Selected())
193 {
194 state &= ~SELECTED;
195
196 OnUnselect();
197 }
198 }
199
200 u32 JControl::Load(JRW &f)
201 {
202 // Carga el índice de control y del control padre
203 if (0 == f.ReadLE32(&id) ||
204 0 == f.ReadLE32(&parentId))
205 {
206 return 1;
207 }
208
209 return 0;
210 }
211
212 u32 JControl::Save(JRW &f)
213 {
214 // Carga el índice de control y del control padre
215 if (0 == f.WriteLE32(&id) ||
216 0 == f.WriteLE32(&parentId))
217 {
218 return 1;
219 }
220
221 return 0;
222 }
223
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clase base de un control de interfaz de usuario.
23 * @file JControl.h.
24 * @author Juan Carlos Seijo Pérez.
25 * @date 27/10/2003.
26 * @version 0.0.1 - 27/10/2003 - Primera versión.
27 */
28
29 #ifndef _JCONTROL_INCLUDED
30 #define _JCONTROL_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Graphics/JDrawable.h>
34 #include <string.h>
35
36 class JUI;
37
38 /** Tipo de control.
39 */
40 typedef enum
41 {
42 JCONTROLTYPE_IMAGE = 0, /**< Imágenes estáticas. */
43 JCONTROLTYPE_IMAGESPRITE, /**< Sprite de imágenes. */
44 JCONTROLTYPE_MESH, /**< Geometría. */
45 JCONTROLTYPE_MESHSPRITE, /**< Sprite de geometría. */
46 } JControlType;
47
48 /** Clase base de un control de interfaz de usuario.
49 */
50 class JControl : public JDrawable
51 {
52 friend class JUI;
53
54 private:
55 static u32 controlCount; /**< Lleva cuenta del nº de controles. */
56
57 protected:
58 JControlType type; /**< Tipo de control. */
59 u32 id; /**< Identificador de control. */
60 u32 parentId; /**< Identificador del control padre. */
61 JControl * parent; /**< Control padre. */
62 u32 focusIndex; /**< Índice de enfoque. */
63 u32 state; /**< Estado del control. */
64 void (*focus)(JControl *c, void *data); /**< Función de enfoque. */
65 void (*unfocus)(JControl *c, void *data); /**< Función de desenfoque. */
66 void (*enable)(JControl *c, void *data); /**< Función de habilitación. */
67 void (*disable)(JControl *c, void *data); /**< Función de deshabilitación. */
68 void (*appear)(JControl *c, void *data); /**< Función de aparición. */
69 void (*disappear)(JControl *c, void *data); /**< Función de desaparición. */
70 void (*select)(JControl *c, void *data); /**< Función de selección. */
71 void (*unselect)(JControl *c, void *data); /**< Función de deselección. */
72 void *focusData; /**< Datos adicionales de enfoque. */
73 void *unfocusData; /**< Datos adicionales de desenfoque. */
74 void *enableData; /**< Datos adicionales de habilitación. */
75 void *disableData; /**< Datos adicionales de deshabilitar. */
76 void *appearData; /**< Datos adicionales de aparición. */
77 void *disappearData; /**< Datos adicionales de desaparición. */
78 void *selectData; /**< Datos adicionales de selección. */
79 void *unselectData; /**< Datos adicionales de deselección. */
80
81 /** Acción a realizar cuando recibe el enfoque. */
82 void OnFocus() {if (focus) focus(this, focusData);};
83
84 /** Acción a realizar cuando pierde el enfoque. */
85 void OnUnfocus() {if (unfocus) unfocus(this, unfocusData);};
86
87 /** Acción a realizar cuando es activado. */
88 void OnEnable() {if (enable) enable(this, enableData);};
89
90 /** Acción a realizar cuando es desactivado. */
91 void OnDisable() {if (disable) disable(this, disableData);};
92
93 /** Acción a realizar cuando aparece. */
94 void OnAppear() {if (appear) appear(this, appearData);};
95
96 /** Acción a realizar cuando desaparece. */
97 void OnDisappear() {if (disappear) disappear(this, disappearData);};
98
99 /** Acción a realizar cuando se selecciona. */
100 void OnSelect() {if (select) select(this, selectData);};
101
102 /** Acción a realizar cuando se deselecciona. */
103 void OnUnselect() {if (unselect) unselect(this, unselectData);};
104
105 public:
106 static const u32 VISIBLE; /**< Flag de visibilidad. */
107 static const u32 FOCUSED; /**< Flag de enfoque. */
108 static const u32 ENABLED; /**< Flag de habilitación. */
109 static const u32 SELECTED; /**< Flag de selección. */
110
111 /** Crea un control vacío.
112 */
113 JControl(JControl *_parent = 0, u32 _state = VISIBLE & ENABLED);
114
115 /** Devuelve el identificador de este control.
116 * @return Identificador del control.
117 */
118 u32 Id() {return id;}
119
120 /** Devuelve el control padre.
121 * @return Control padre de este, 0 si no tiene.
122 */
123 JControl * Parent() {return parent;}
124
125 /** Función de dibujo. */
126 virtual void Draw();
127
128 /** Función de actualización cuando está visible.
129 * @return Dependiente de la implementación.
130 */
131 virtual s32 Update();
132
133 /** Función de dibujo cuando está únicamente visible. */
134 virtual void DrawVisible() = 0;
135
136 /** Función de dibujo cuando está enfocado. */
137 virtual void DrawFocus() = 0;
138
139 /** Función de dibujo cuando está deshabilitado. */
140 virtual void DrawDisabled() = 0;
141
142 /** Función de dibujo cuando está seleccionado. */
143 virtual void DrawSelected() = 0;
144
145 /** Función de actualización cuando está únicamente visible.
146 * @return Máscara de estado del control.
147 */
148 virtual s32 UpdateVisible() = 0;
149
150 /** Función de actualización cuando está enfocado.
151 * @return Dependiente de la implementación.
152 */
153 virtual s32 UpdateFocus() = 0;
154
155 /** Función de actualización cuando está deshabilitado.
156 * @return Dependiente de la implementación.
157 */
158 virtual s32 UpdateDisabled() = 0;
159
160 /** Función de actualización cuando está seleccionado.
161 * @return Dependiente de la implementación.
162 */
163 virtual s32 UpdateSelected() = 0;
164
165 /** Muestra el control.
166 */
167 virtual void Appear();
168
169 /** Oculta el control.
170 */
171 virtual void Disappear();
172
173 /** Habilita el control.
174 */
175 virtual void Enable();
176
177 /** Deshabilita el control.
178 */
179 virtual void Disable();
180
181 /** Enfoca el control.
182 */
183 virtual void Focus();
184
185 /** Desenfoca el control.
186 */
187 virtual void Unfocus();
188
189 /** Selecciona el control.
190 */
191 virtual void Select();
192
193 /** Deselecciona el control.
194 */
195 virtual void Unselect();
196
197 /** Establece la función para cuando recibe el enfoque.
198 * @param func Función callback a llamara cuando se produce el evento.
199 * @param data Datos adicionales.
200 */
201 void SetOnFocus(void (*func)(JControl*, void *), void *data = 0) {focus = func; focusData = data;};
202
203 /** Establece la función para cuando pierde el enfoque.
204 * @param func Función callback a llamara cuando se produce el evento.
205 * @param data Datos adicionales.
206 */
207 void SetOnUnfocus(void (*func)(JControl*, void *), void *data = 0) {unfocus = func; unfocusData = data;};
208
209 /** Establece la función para cuando es activado.
210 * @param func Función callback a llamara cuando se produce el evento.
211 * @param data Datos adicionales.
212 */
213 void SetOnEnable(void (*func)(JControl*, void *), void *data = 0) {enable = func; enableData = data;};
214
215 /** Establece la función para cuando es desactivado.
216 * @param func Función callback a llamara cuando se produce el evento.
217 * @param data Datos adicionales.
218 */
219 void SetOnDisable(void (*func)(JControl*, void *), void *data = 0) {disable = func; disableData = data;};
220
221 /** Establece la función para cuando aparece.
222 * @param func Función callback a llamara cuando se produce el evento.
223 * @param data Datos adicionales.
224 */
225 void SetOnAppear(void (*func)(JControl*, void *), void *data = 0) {appear = func; appearData = data;};
226
227 /** Establece la función para cuando desaparece.
228 * @param func Función callback a llamara cuando se produce el evento.
229 * @param data Datos adicionales.
230 */
231 void SetOnDisappear(void (*func)(JControl*, void *), void *data = 0) {disappear = func; disappearData = data;};
232
233 /** Establece la función para cuando se selecciona.
234 * @param func Función callback a llamara cuando se produce el evento.
235 * @param data Datos adicionales.
236 */
237 void SetOnSelect(void (*func)(JControl*, void *), void *data = 0) {select = func; selectData = data;};
238
239 /** Establece la función para cuando se deselecciona.
240 * @param func Función callback a llamara cuando se produce el evento.
241 * @param data Datos adicionales.
242 */
243 void SetOnUnselect(void (*func)(JControl*, void *), void *data = 0) {unselect = func; unselectData = data;};
244
245 /** Determina si el control está visible.
246 * @return <b>true</b> si lo está, <b>false</b> si no.
247 */
248 bool Visible() {return 0 != (state & VISIBLE);}
249
250 /** Determina si el control está enfocado.
251 * @return <b>true</b> si lo está, <b>false</b> si no.
252 */
253 bool Focused() {return 0 != (state & FOCUSED);}
254
255 /** Determina si el control está seleccionado.
256 * @return <b>true</b> si lo está, <b>false</b> si no.
257 */
258 bool Selected() {return 0 != (state & SELECTED);}
259
260 /** Determina si el control está activado.
261 * @return <b>true</b> si lo está, <b>false</b> si no.
262 */
263 bool Enabled() {return 0 != (state & ENABLED);}
264
265 /** Carga el control desde un fichero.
266 * @param f Fichero abierto y posicionado para cargar el objeto.
267 * @return 0 si todo va bien, 1 en caso de error de E/S,
268 * 2 en caso de incoherencia de los datos.
269 */
270 u32 Load(JRW &f);
271
272 /** Salva la interfaz a un fichero de definición de interfaz.
273 * @param f Fichero abierto y posicionado para salvar el objeto.
274 * @return 0 si todo va bien, 1 en caso de error de E/S,
275 * 2 en caso de incoherencia de los datos.
276 */
277 u32 Save(JRW &f);
278
279 /** Libera la memoria asociada.
280 */
281 virtual ~JControl();
282 };
283
284 #endif // _JCONTROL_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Control de interfaz de usuario compuesto por imágenes.
23 * @file JControlImage.cpp
24 * @author Juan Carlos Seijo Pérez.
25 * @date 27/10/2003.
26 * @version 0.0.1 - 27/10/2003 - Primera versión.
27 */
28
29 #include <JLib/Graphics/JControlImage.h>
30
31 // Destructor
32 void JControlImage::Destroy()
33 {
34 imgNormal.Destroy();
35 imgDisabled.Destroy();
36 imgFocused.Destroy();
37 imgSelected.Destroy();
38 }
39
40 bool JControlImage::Init(JImage &normal, JImage &disabled, JImage &focused, JImage &selected)
41 {
42 imgNormal.Ref(normal);
43 imgDisabled.Ref(disabled);
44 imgFocused.Ref(focused);
45 imgSelected.Ref(selected);
46
47 return true;
48 }
49
50 // Función de dibujo cuando está visible
51 void JControlImage::DrawVisible()
52 {
53 imgNormal.Draw();
54 }
55
56 // Función de dibujo cuando está enfocado
57 void JControlImage::DrawFocus()
58 {
59 imgFocused.Draw();
60 }
61
62 // Función de dibujo cuando está deshabilitado
63 void JControlImage::DrawDisabled()
64 {
65 imgDisabled.Draw();
66 }
67
68 // Función de dibujo cuando está seleccionado
69 void JControlImage::DrawSelected()
70 {
71 imgSelected.Draw();
72 }
73
74 // Función de actualización cuando está visible
75 s32 JControlImage::UpdateVisible()
76 {
77 return state;
78 }
79
80 // Función de actualización cuando está enfocado
81 s32 JControlImage::UpdateFocus()
82 {
83 return state;
84 }
85
86 // Función de actualización cuando está deshabilitado
87 s32 JControlImage::UpdateDisabled()
88 {
89 return state;
90 }
91
92 // Función de actualización cuando está seleccionado
93 s32 JControlImage::UpdateSelected()
94 {
95 return state;
96 }
97
98 u32 JControlImage::Load(JRW &f)
99 {
100 // Carga la parte común del control (id e id del padre)
101 if (0 != JControl::Load(f))
102 {
103 return 2;
104 }
105
106 // Carga las imágenes de control
107 if (0 != imgNormal.Load(f) ||
108 0 != imgFocused.Load(f) ||
109 0 != imgSelected.Load(f) ||
110 0 != imgDisabled.Load(f))
111 {
112 return 2;
113 }
114
115 return 0;
116 }
117
118 u32 JControlImage::Save(JRW &f)
119 {
120 // Salva la parte común del control (id e id del padre)
121 if (0 != JControl::Save(f))
122 {
123 return 2;
124 }
125
126 // Salva las imágenes de control
127 if (0 != imgNormal.Save(f) ||
128 0 != imgFocused.Save(f) ||
129 0 != imgSelected.Save(f) ||
130 0 != imgDisabled.Save(f))
131 {
132 return 2;
133 }
134
135 return 0;
136 }
137
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Control de interfaz de usuario compuesto por imágenes.
23 * @file JControlImage.h.
24 * @author Juan Carlos Seijo Pérez.
25 * @date 27/10/2003.
26 * @version 0.0.1 - 27/10/2003 - Primera versión.
27 */
28
29 #ifndef _JIMAGECONTROL_INCLUDED
30 #define _JIMAGECONTROL_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Graphics/JControl.h>
34 #include <JLib/Graphics/JImage.h>
35 #include <SDL.h>
36
37 /** Control de interfaz de usuario compuesto por imágenes.
38 */
39 class JControlImage : public JControl
40 {
41 protected:
42 JImage imgNormal; /**< Imagen en estado normal */
43 JImage imgDisabled; /**< Imagen en estado deshabilitado */
44 JImage imgFocused; /**< Imagen en estado enfocado */
45 JImage imgSelected; /**< Imagen en estado seleccionado */
46
47 /** Destructor
48 */
49 void Destroy();
50
51 public:
52 /** Crea un control de imágenes vacío. Init o Load deben ser llamados antes de usarlo.
53 */
54 JControlImage() : JControl(), imgNormal(0), imgDisabled(0), imgFocused(0), imgSelected(0)
55 {}
56
57 /** Inicializa el control a partir de las imágenes dadas.
58 * @return <b>true</b> si se inicializó correctamente, <b>false</b> si no.
59 */
60 bool Init(JImage &normal, JImage &disabled, JImage &focused, JImage &selected);
61
62 /** Función de dibujo cuando está visible */
63 virtual void DrawVisible();
64
65 /** Función de dibujo cuando está enfocado */
66 virtual void DrawFocus();
67
68 /** Función de dibujo cuando está deshabilitado */
69 virtual void DrawDisabled();
70
71 /** Función de dibujo cuando está seleccionado */
72 virtual void DrawSelected();
73
74 /** Función de actualización cuando está visible */
75 virtual s32 UpdateVisible();
76
77 /** Función de actualización cuando está enfocado */
78 virtual s32 UpdateFocus();
79
80 /** Función de actualización cuando está deshabilitado */
81 virtual s32 UpdateDisabled();
82
83 /** Función de actualización cuando está seleccionado */
84 virtual s32 UpdateSelected();
85
86 /** Carga el control desde un fichero.
87 * @param f Fichero abierto y posicionado para cargar el objeto.
88 * @return 0 si todo va bien, 1 en caso de error de E/S,
89 * 2 en caso de incoherencia de los datos.
90 */
91 u32 Load(JRW &f);
92
93 /** Salva la interfaz a un fichero de definición de interfaz.
94 * @param f Fichero abierto y posicionado para salvar el objeto.
95 * @return 0 si todo va bien, 1 en caso de error de E/S,
96 * 2 en caso de incoherencia de los datos.
97 */
98 u32 Save(JRW &f);
99 };
100
101 #endif // _JIMAGECONTROL_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clase base de todos los objetos dibujables.
23 * @file JDrawable.h.
24 * @author Juan Carlos Seijo Pérez.
25 * @date 15/11/2003.
26 * @version 0.0.1 - 15/11/2003 - Primera versión.
27 * @version 0.0.2 - 25/09/2004 - Modificación del método 2D de Pos() para aceptar floats (quita libertad sino).
28 */
29
30 #ifndef _JDRAWABLE_INCLUDED
31 #define _JDRAWABLE_INCLUDED
32
33 #include <JLib/Util/JTypes.h>
34 #include <stdio.h>
35 #include <JLib/Util/JObject.h>
36 #include <JLib/Util/JLoadSave.h>
37 #include <JLib/Math/JVector.h>
38
39 /** Clase base de todos los objetos dibujables.
40 */
41 class JDrawable : public JObject
42 {
43 protected:
44 JVector pos; /**< Posición del objeto. */
45
46 public:
47 /** Libera memoria.
48 */
49 virtual ~JDrawable() {}
50
51 /** Dibuja el objeto. Debe ser implementada en la clase hija.
52 */
53 virtual void Draw() {return;}
54
55 /** Actualiza el objeto.
56 */
57 virtual s32 Update() {return 0;}
58
59 /** Recupera la posición de este objeto.
60 * @return Posición del objeto.
61 */
62 virtual const JVector & Pos() const {return pos;}
63
64 /** Establece la posición de este objeto.
65 * @param newPos Nueva posición del objeto.
66 */
67 virtual void Pos(const JVector &newPos) {pos = newPos;}
68
69 /** Establece la posición de este objeto.
70 * @param x Nueva coordenada x.
71 * @param y Nueva coordenada y.
72 * @param z Nueva coordenada z.
73 */
74 virtual void Pos(float x, float y, float z) {pos.x = x; pos.y = y; pos.z = z;}
75
76 /* Establece la posición de este objeto. Útil para 2D.
77 * @param x Nueva coordenada x.
78 * @param y Nueva coordenada y.
79 */
80 virtual void Pos(float x, float y) {pos.x = x; pos.y = y;}
81
82 /** Establece la posición x de este objeto.
83 * @param x Nueva coordenada x.
84 */
85 virtual void X(float x) {pos.x = x;}
86
87 /** Devuelve la posición x de este objeto.
88 * @return Coordenada x del objeto.
89 */
90 virtual float X() const {return pos.x;}
91
92 /** Establece la posición y de este objeto.
93 * @param y Nueva coordenada y.
94 */
95 virtual void Y(float y) {pos.y = y;}
96
97 /** Devuelve la posición y de este objeto.
98 * @return Coordenada y del objeto.
99 */
100 virtual float Y() const {return pos.y;}
101
102 /** Establece la posición z de este objeto.
103 * @param z Nueva coordenada z.
104 */
105 virtual void Z(float z) {pos.z = z;}
106
107 /** Devuelve la posición z de este objeto.
108 * @return Coordenada z del objeto.
109 */
110 virtual float Z() const {return pos.z;}
111 };
112
113 #endif // _JDRAWABLE_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Fuente para mostrar texto en pantalla.
23 * @file JFont.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 18/04/2004
26 * @version 0.0.1 - 18/04/2004 - Primera versión.
27 */
28
29 #include <JLib/Graphics/JFont.h>
30
31 JImage * JFont::Printf(JFontRenderType type, JFontAlign align, SDL_Color &fg, SDL_Color &bg, char *str)
32 {
33 // Renderiza cada línea
34 char *c = str;
35 s32 lines = 1;
36
37 // Cuenta las líneas
38 while (*c)
39 {
40 if (*c == '\n')
41 {
42 ++lines;
43 }
44
45 ++c;
46 }
47
48 JImage **img = new JImage*[lines];
49 memset(img, 0, lines*sizeof(JImage*));
50 char *cur = str;
51 s32 line = 0;
52 s32 w = 0, h = 0;
53 c = str;
54
55 while (*c)
56 {
57 if (*c == '\n' || *(c + 1) == 0)
58 {
59 // New line!
60 if (*c == '\n')
61 *c = 0;
62
63 if (!*cur)
64 {
65 // Skip empty strings
66 img[line] = 0;
67 h += LineDistance();
68 ++line;
69 cur = c + 1;
70 *c = '\n';
71 ++c;
72 continue;
73 }
74
75 switch (type)
76 {
77 default:
78 case JFONTRENDERTYPE_SOLID:
79 img[line] = RenderTextSolid(cur, fg);
80
81 // Tenemos 8 bits, queremos MÁS!
82 img[line]->Convert(SDL_GetVideoSurface()->format, SDL_GetVideoSurface()->flags);
83
84 // Quita el flag SDL_SRCALPHA de forma que se copie el valor del canal alfa a la composición
85 img[line]->Alpha(0, 0);
86 break;
87
88 case JFONTRENDERTYPE_SHADED:
89 img[line] = RenderTextShaded(cur, fg, bg);
90
91 // Tenemos 8 bits, queremos MÁS!
92 img[line]->Convert(SDL_GetVideoSurface()->format, SDL_GetVideoSurface()->flags);
93
94 // Quita el flag SDL_SRCALPHA de forma que se copie el valor del canal alfa a la composición
95 img[line]->Alpha(0, 0);
96 break;
97
98 case JFONTRENDERTYPE_BLENDED:
99 img[line] = RenderTextBlended(cur, fg);
100 // Quita el flag SDL_SRCALPHA de forma que se copie el valor del canal alfa a la composición
101 img[line]->Alpha(0, 0);
102
103 break;
104 }
105
106 // Checks the max width
107 if (img[line]->Width() > w)
108 {
109 w = img[line]->Width();
110 }
111
112 switch (align)
113 {
114 case JFONTALIGN_LEFT:
115 img[line]->Pos(0, h);
116 break;
117
118 case JFONTALIGN_RIGHT:
119 img[line]->Pos(w - img[line]->Width(), h);
120 break;
121
122 case JFONTALIGN_CENTER:
123 img[line]->Pos((w - img[line]->Width())/2, h);
124 break;
125 }
126
127 h += LineDistance();
128
129 ++line;
130 cur = c + 1;
131 *c = '\n';
132 }
133
134 ++c;
135 }
136
137 JImage *ret = new JImage;
138
139 SDL_PixelFormat *fmt = img[0]->Format();
140 ret->Create(w, h, img[0]->Format()->BitsPerPixel, 0, fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask);
141
142 s32 x;
143
144 for (line = 0; line < lines; ++line)
145 {
146 if (img[line])
147 {
148 switch (align)
149 {
150 case JFONTALIGN_LEFT:
151 x = 0;
152 break;
153
154 case JFONTALIGN_RIGHT:
155 x = w - img[line]->Width();
156 break;
157
158 case JFONTALIGN_CENTER:
159 x = (w - img[line]->Width())/2;
160 break;
161
162 default:
163 x = 0;
164 break;
165 }
166
167 ret->Paste(img[line],
168 0,
169 0,
170 (s32)img[line]->Width(),
171 (s32)img[line]->Height(),
172 x,
173 (s32)img[line]->Y());
174
175 delete img[line];
176 }
177 }
178
179 delete[] img;
180
181 return ret;
182 }
183
184 JImage * JFont::PrintfSolid(JFontAlign align, SDL_Color &fg, const char *strFormat, ...)
185 {
186 // Formatea el texto
187 va_list vlist;
188 s8 str[4096];
189
190 va_start(vlist, strFormat);
191 vsprintf(str, strFormat, vlist);
192 va_end(vlist);
193
194 // Renderiza el texto
195 SDL_Color color; // Dummy
196 return Printf(JFONTRENDERTYPE_SOLID, align, fg, color, str);
197 }
198
199 JImage * JFont::PrintfShaded(JFontAlign align, SDL_Color &fg, SDL_Color &bg, const char *strFormat, ...)
200 {
201 // Formatea el texto
202 va_list vlist;
203 s8 str[4096];
204
205 va_start(vlist, strFormat);
206 vsprintf(str, strFormat, vlist);
207 va_end(vlist);
208
209 // Renderiza el texto
210 return Printf(JFONTRENDERTYPE_SHADED, align, fg, bg, str);
211 }
212
213 JImage * JFont::PrintfBlended(JFontAlign align, SDL_Color &fg, const char *strFormat, ...)
214 {
215 // Formatea el texto
216 va_list vlist;
217 s8 str[4096];
218
219 va_start(vlist, strFormat);
220 vsprintf(str, strFormat, vlist);
221 va_end(vlist);
222
223 // Renderiza el texto
224 SDL_Color color; // Dummy
225 return Printf(JFONTRENDERTYPE_BLENDED, align, fg, color, str);
226 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Fuente para mostrar texto en pantalla.
23 * @file JFont.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 27/03/2004
26 * @version 0.0.1 - 27/03/2004 - Primera versión.
27 */
28
29 #ifndef _JFONT_INCLUDED
30 #define _JFONT_INCLUDED
31
32 #include <JLib/Graphics/JImage.h>
33 #include <SDL_ttf.h>
34 #include <stdarg.h>
35
36 /** Alineación del texto a renderizar.
37 */
38 typedef enum JFontAlign
39 {
40 JFONTALIGN_LEFT = 0, /**< Alineado a la izquierda. */
41 JFONTALIGN_RIGHT, /**< Alineado a la derecha. */
42 JFONTALIGN_CENTER, /**< Centrado. */
43 };
44
45 /** Clase wrapper de la clase SDL_Font de la librería SDL_ttf.
46 * Permite mostrar texto en pantalla.
47 */
48 class JFont
49 {
50 /** Tipo de renderizado a usar
51 */
52 typedef enum JFontRenderType
53 {
54 JFONTRENDERTYPE_SOLID = 0, /**< Sólido con colorkey. */
55 JFONTRENDERTYPE_SHADED, /**< Con antialiasing en fondo sólido. */
56 JFONTRENDERTYPE_BLENDED, /**< Con antializasing en fondo transparente. */
57 };
58
59 TTF_Font *font;
60
61 /** Función de renderizado de las PrintfXXX.
62 * @param type Tipo de render a emplear.
63 * @param align Alineación del texto.
64 * @param fg Color de fuente.
65 * @param bg Color de fondo (sólo para JFONTRENDERTYPE_SHADED).
66 * @param str Texto a renderizar.
67 */
68 JImage * Printf(JFontRenderType type, JFontAlign align, SDL_Color &fg, SDL_Color &bg, char *str);
69
70 public:
71 /** Crea una fuente vacía.
72 */
73 JFont() : font(0)
74 {}
75
76 /** Recupera la versión de ejecución de SDL_ttf. El objeto devuelto tiene
77 * tres campos: major, minor y patch, que identifican la versión.
78 * @return La versión de ejecución SDL_ttf.
79 */
80 const SDL_version * GetLinkedVersion() {return TTF_Linked_Version();}
81
82 /** Inicializa el subsistema de fuentes. Sólo es necesaria la primera vez.
83 * @return <b>true</b> si todo va bien, <b>false</b> en caso contrario.
84 */
85 static bool Init()
86 {
87 if (TTF_WasInit() == 0)
88 {
89 return (-1 != TTF_Init());
90 }
91
92 return true;
93 }
94
95 /** Devuelve la cadena de error del último error.
96 * @return Cadena de error del último error.
97 */
98 static const char * GetError()
99 {
100 return TTF_GetError();
101 }
102
103 /** Abre la fuente del fichero indicado.
104 * @param filename Nombre del fichero .ttf o .fon.
105 * @param size Tamaño en pixels (aproximado).
106 * @return <b>true</b> si se pudo abrir, <b>false</b> si no.
107 */
108 bool Open(const char * filename, s32 size)
109 {
110 Destroy();
111 return (0 != (font = TTF_OpenFont(filename, size)));
112 }
113
114 /** Establece el estilo.
115 * @param style Nuevo estilo. Puede ser una combinación de
116 * TTF_STYLE_NORMAL, TTF_STYLE_BOLD, TTF_STYLE_ITALIC o TTF_STYLE_UNDERLINE.
117 */
118 void Style(s32 style)
119 {
120 TTF_SetFontStyle(font, style);
121 }
122
123 /** Recupera el estilo.
124 * @return Estilo actual como combinación de TTF_STYLE_NORMAL,
125 * TTF_STYLE_BOLD, TTF_STYLE_ITALIC y TTF_STYLE_UNDERLINE.
126 */
127 s32 Style()
128 {
129 return TTF_GetFontStyle(font);
130 }
131
132 /** Devuelve la altura máxima de la fuente.
133 * @return Altura máxima de la fuente.
134 */
135 s32 Height()
136 {
137 return TTF_FontHeight(font);
138 }
139
140 /** Devuelve el ascenso de la fuente.
141 * @return Ascenso de la fuente.
142 */
143 s32 Ascent()
144 {
145 return TTF_FontAscent(font);
146 }
147
148 /** Devuelve el descenso de la fuente.
149 * @return Descenso de la fuente.
150 */
151 s32 Descent()
152 {
153 return TTF_FontDescent(font);
154 }
155
156 /** Devuelve la separación recomendada de línea.
157 * @return Separación recomendada de línea.
158 */
159 s32 LineDistance()
160 {
161 return TTF_FontLineSkip(font);
162 }
163
164 /** Renderiza el texto dado de forma rápida.
165 * @param text Texto a renderizar.
166 * @param fg Color de fuente.
167 */
168 JImage * RenderTextSolid(const char * text, SDL_Color &fg)
169 {
170 SDL_Surface *s = TTF_RenderUTF8_Solid(font, text, fg);
171 return s != 0 ? new JImage(s) : 0;
172 }
173
174 /** Renderiza el texto UNICODE dado de forma rápida.
175 * @param text Texto a renderizar.
176 * @param fg Color de fuente.
177 */
178 JImage * RenderUNICODESolid(const u16 *text, SDL_Color &fg)
179 {
180 SDL_Surface *s = TTF_RenderUNICODE_Solid(font, text, fg);
181 return s != 0 ? new JImage(s) : 0;
182 }
183
184 /** Renderiza el caracter dado de forma rápida.
185 * @param c Caracter a renderizar.
186 * @param fg Color de fuente.
187 */
188 JImage * RenderGlyphSolid(char c, SDL_Color &fg)
189 {
190 SDL_Surface *s = TTF_RenderGlyph_Solid(font, c, fg);
191 return s != 0 ? new JImage(s) : 0;
192 }
193
194 /** Renderiza el texto dado suavizado sobre fondo sólido.
195 * @param text Texto a renderizar.
196 * @param fg Color de fuente.
197 * @param bg Color de fondo.
198 */
199 JImage * RenderTextShaded(const char * text, SDL_Color &fg, SDL_Color &bg)
200 {
201 SDL_Surface *s = TTF_RenderUTF8_Shaded(font, text, fg, bg);
202 return s != 0 ? new JImage(s) : 0;
203 }
204
205 /** Renderiza el texto UNICODE dado suavizado sobre fondo sólido.
206 * @param text Texto a renderizar.
207 * @param fg Color de fuente.
208 * @param bg Color de fondo.
209 */
210 JImage * RenderUNICODEShaded(const u16 *text, SDL_Color &fg, SDL_Color &bg)
211 {
212 SDL_Surface *s = TTF_RenderUNICODE_Shaded(font, text, fg, bg);
213 return s != 0 ? new JImage(s) : 0;
214 }
215
216 /** Renderiza el caracter dado suavizado sobre fondo sólido.
217 * @param c Caracter a renderizar.
218 * @param fg Color de fuente.
219 * @param bg Color de fondo.
220 */
221 JImage * RenderGlyphShaded(char c, SDL_Color &fg, SDL_Color &bg)
222 {
223 SDL_Surface *s = TTF_RenderGlyph_Shaded(font, c, fg, bg);
224 return s != 0 ? new JImage(s) : 0;
225 }
226
227 /** Renderiza el texto dado suavizado sobre fondo transparente.
228 * @param text Texto a renderizar.
229 * @param fg Color de fuente.
230 */
231 JImage * RenderTextBlended(const char * text, SDL_Color &fg)
232 {
233 SDL_Surface *s = TTF_RenderUTF8_Blended(font, text, fg);
234 return s != 0 ? new JImage(s) : 0;
235 }
236
237 /** Renderiza el texto dado suavizado sobre fondo transparente.
238 * @param text Texto a renderizar.
239 * @param fg Color de fuente.
240 */
241 JImage * RenderUNICODEBlended(const u16 * text, SDL_Color &fg)
242 {
243 SDL_Surface *s = TTF_RenderUNICODE_Blended(font, text, fg);
244 return s != 0 ? new JImage(s) : 0;
245 }
246
247 /** Renderiza el caracter dado suavizado sobre fondo transparente.
248 * @param c Caracter a renderizar.
249 * @param fg Color de fuente.
250 */
251 JImage * RenderGlyphBlended(char c, SDL_Color &fg)
252 {
253 SDL_Surface *s = TTF_RenderGlyph_Blended(font, c, fg);
254 return s != 0 ? new JImage(s) : 0;
255 }
256
257 /** Destruye el objeto, liberando la memoria asociada.
258 */
259 void Destroy()
260 {
261 if (font != 0)
262 {
263 TTF_CloseFont(font);
264 font = 0;
265 }
266 }
267
268 /** Renderiza el texto con formato dado de forma rápida.
269 * @param align Alineación del texto.
270 * @param fg Color de fuente.
271 * @param strFormat Texto a renderizar.
272 * @param ... Argumentos adicionales tipo printf().
273 */
274 JImage * PrintfSolid(JFontAlign align, SDL_Color &fg, const char *strFormat, ...);
275
276 /** Renderiza el texto con formato suavizado sobre fondo sólido.
277 * @param align Alineación del texto.
278 * @param fg Color de fuente.
279 * @param bg Color de fondo.
280 * @param strFormat Texto a renderizar.
281 * @param ... Argumentos adicionales tipo printf().
282 */
283 JImage * PrintfShaded(JFontAlign align, SDL_Color &fg, SDL_Color &bg, const char *strFormat, ...);
284
285 /** Renderiza el texto con formato suavizado sobre fondo transparente.
286 * @param align Alineación del texto.
287 * @param fg Color de fuente.
288 * @param strFormat Texto a renderizar.
289 * @param ... Argumentos adicionales tipo printf().
290 */
291 JImage * PrintfBlended(JFontAlign align, SDL_Color &fg, const char *strFormat, ...);
292
293 /** Destruye el objeto, liberando la memoria asociada.
294 */
295 ~JFont()
296 {
297 Destroy();
298 }
299 };
300
301 #endif // _JFONT_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 01/04/2003
25 // @description: Ejes coordenados
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #include <JLib/Graphics/JGLAxes.h>
29
30 // Crea unos ejes coordenados
31 JGLAxes::JGLAxes(bool bshowDivs,
32 float flength,
33 float fxRed, float fxGreen, float fxBlue,
34 float fyRed, float fyGreen, float fyBlue,
35 float fzRed, float fzGreen, float fzBlue)
36 {
37 showDivs = bshowDivs;
38 length = flength;
39 xRed = fxRed; xGreen = fxGreen; xBlue = fxBlue;
40 yRed = fyRed; yGreen = fyGreen; yBlue = fyBlue;
41 zRed = fzRed; zGreen = fzGreen; zBlue = fzBlue;
42 nList = 0;
43
44 RebuildList();
45 }
46
47 // Crea la lista de OpenGL
48 void JGLAxes::RebuildList()
49 {
50 if (nList != 0)
51 glDeleteLists(nList, 1);
52
53 nList = glGenLists(1);
54
55 glNewList(nList, GL_COMPILE);
56
57 glPointSize(2.0f);
58 glBegin(GL_LINES);
59 glColor3f(xRed, xGreen, xBlue);
60 glVertex3f(-length, 0.0f, 0.0f);
61 glVertex3f( length, 0.0f, 0.0f);
62 glEnd();
63
64 // Pone varias divisiones
65 if (showDivs)
66 {
67 glBegin(GL_POINTS);
68 for (float i = -length + (0.1f * length); i < length; i += (0.1f * length))
69 glVertex3f(i, 0.0f, 0.0f);
70 glEnd();
71 }
72
73 glBegin(GL_LINES);
74 glColor3f(yRed, yGreen, yBlue);
75 glVertex3f(0.0f, -length, 0.0f);
76 glVertex3f(0.0f, length, 0.0f);
77 glEnd();
78
79 // Pone varias divisiones
80 if (showDivs)
81 {
82 glBegin(GL_POINTS);
83 for (float i = -length + (0.1f * length); i < length; i += (0.1f * length))
84 glVertex3f(0.0f, i, 0.0f);
85 glEnd();
86 }
87
88 glBegin(GL_LINES);
89 glColor3f(zRed, zGreen, zBlue);
90 glVertex3f(0.0f, 0.0f, -length);
91 glVertex3f(0.0f, 0.0f, length);
92 glEnd();
93
94 // Pone varias divisiones
95 if (showDivs)
96 {
97 glBegin(GL_POINTS);
98 for (float i = -length + (0.1f * length); i < length; i += (0.1f * length))
99 glVertex3f(0.0f, 0.0f, i);
100 glEnd();
101 }
102
103 glEndList();
104 }
105
106 // Pinta los ejes
107 void JGLAxes::Draw()
108 {
109 glCallList(nList);
110 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 01/04/2003
25 // @description: Ejes coordenados
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #ifndef _JGLAXES_INCLUDED
29 #define _JGLAXES_INCLUDED
30
31 #include <JLib/Util/JTypes.h>
32 #include <JLib/Graphics/JDrawable.h>
33 #include <SDL.h>
34 #include <GL/gl.h>
35
36 class JGLAxes : public JDrawable
37 {
38 public:
39 GLuint nList;
40 float length;
41 float xRed, xGreen, xBlue;
42 float yRed, yGreen, yBlue;
43 float zRed, zGreen, zBlue;
44 bool showDivs;
45
46 // Crea unos ejes coordenados
47 JGLAxes(bool bshowDivs = true,
48 float flength = 2.0f,
49 float fxRed = 1.0f, float fxGreen = 0.0f, float fxBlue = 0.0f,
50 float fyRed = 0.0f, float fyGreen = 1.0f, float fyBlue = 0.0f,
51 float fzRed = 0.0f, float fzGreen = 0.0f, float fzBlue = 1.0f);
52
53 // Crea la lista de OpenGL
54 void RebuildList();
55
56 // Pinta los ejes
57 void Draw();
58 };
59
60 #endif // _JGLAXES_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 29/04/2003
25 // @description: Cámara.
26 //
27 // ^ __> Vista (ejes locales de cámara):
28 // | up ^ z (yaw)
29 // | __________> |
30 // /---\ eye-target * |
31 // | x |O---------------------->*** | x (pitch)
32 // \---/ eye target o-------->
33 // y (roll)
34 ///////////////////////////////////////////////////////////////////////////////
35
36 #include <JLib/Graphics/JGLCamera.h>
37
38 // Crea una cámara
39 JGLCamera::JGLCamera(JPoint _eye,
40 JPoint _target,
41 JVector _up)
42 {
43 orgEye = _eye;
44 orgTarget = _target;
45 orgUp = _up;
46
47 Reset();
48 }
49
50 // Calcula los vectores base en función del ojo y el objetivo
51 void JGLCamera::ComputeBasis()
52 {
53 // Usa el eje z de esta cámara para apuntar al objetivo
54 camera.R[2] = (camera.O - target).Unit();
55
56 // El eje x será perpendicular al plano formado por up y eye-target
57 camera.R[0] = camera.R[1].Cross(camera.R[2]).Unit();
58
59 // El eje y es ortogonal a los anteriores
60 camera.R[1] = camera.R[2].Cross(camera.R[0]).Unit();
61 }
62
63 // Modifica la posición de la cámara (eye) la cantidad indicada
64 void JGLCamera::Translate(JVector deltaPos)
65 {
66 deltaPos = camera.TransformVectorToParent(deltaPos);
67 camera.O += deltaPos;
68
69 ComputeBasis();
70 }
71
72 // Mueve la cámara (eye) a la posición indicada
73 void JGLCamera::TranslateTo(JVector pos)
74 {
75 camera.O = pos;
76
77 ComputeBasis();
78 }
79
80 // Rota la cámara en torno al eje x pasando por el objetivo
81 void JGLCamera::Rotate(float x, float y, float z)
82 {
83 JScalar tLen = (camera.O - target).Length();
84 camera.O = target;
85
86 camera.RotateAboutX(x);
87 camera.RotateAboutY(y);
88 camera.RotateAboutZ(z);
89
90 camera.O += camera.R[2] * tLen;
91 }
92
93 // Modifica la posición del objetivo la cantidad indicada
94 void JGLCamera::TargetTranslate(JVector deltaTarget)
95 {
96 deltaTarget = camera.TransformVectorToParent(deltaTarget);
97 target += deltaTarget;
98
99 ComputeBasis();
100 }
101
102 // Mueve la posición de objetivo a la posición indicada
103 void JGLCamera::TargetTranslateTo(JVector pos)
104 {
105 target = camera.TransformVectorToParent(pos);
106
107 ComputeBasis();
108 }
109
110 // Rota la cámara en torno:
111 // - al eje x (Pitch, dirección perpendicular al plano eye-target/up)
112 // - al eje y (Yaw, dirección up)
113 // - al eje z (Roll, dirección eye-target)
114 void JGLCamera::TargetRotate(float x, float y, float z)
115 {
116 float tLen = (camera.O - target).Length();
117 target = camera.O;
118
119 camera.RotateAboutX(x); // Giramos la cantidad indicada
120 camera.RotateAboutY(y);
121 camera.RotateAboutZ(z);
122
123 target -= camera.R[2] * tLen; // Desplazamos la longitud original en la nueva dirección
124 }
125
126 // Zoom. Especifica la distancia eye-target
127 void JGLCamera::Zoom(float distance)
128 {
129 if (distance <= 0)
130 return;
131
132 camera.O = target;
133 camera.O -= (camera.R[2] * distance);
134
135 ComputeBasis();
136 }
137
138 // Ajusta la perspectiva (más o menos distorsión)
139 void JGLCamera::Perspective(float distortAmount)
140 {
141 }
142
143 // Establece la proyección de cámara
144 void JGLCamera::Set()
145 {
146 glLoadIdentity();
147 gluLookAt(camera.O.x, camera.O.y, camera.O.z,
148 target.x, target.y, target.z,
149 camera.Y().x, camera.Y().y, camera.Y().z);
150 }
151
152 // Reset de cámara
153 void JGLCamera::Reset()
154 {
155 camera.O = orgEye;
156 target = orgTarget;
157
158 // Inicializamos el eje Y de la base al vector up que nos dan
159 camera.R[1] = orgUp;
160
161 ComputeBasis();
162 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 29/04/2003
25 // @description: Cámara.
26 //
27 // ^ __> Vista (ejes locales de cámara):
28 // | up ^ y (yaw)
29 // | __________> |
30 // /---\ eye-target * |
31 // | x |O---------------------->*** | x (pitch)
32 // \---/ eye target o-------->
33 // z (roll)
34 ///////////////////////////////////////////////////////////////////////////////
35
36 #ifndef _JGLCAMERA_INCLUDED
37 #define _JGLCAMERA_INCLUDED
38
39 #include <JLib/Util/JTypes.h>
40 #include <JLib/Util/JObject.h>
41 #include <JLib/Math/JMath.h>
42 #include <SDL.h>
43 #include <GL/gl.h>
44 #include <GL/glu.h>
45
46 class JGLCamera : public JObject
47 {
48 public:
49 float humanize; // Factor de irregularidad de movimiento
50 float spring; // Factor de suavizado de movimiento
51 float zoom; // Factor de zoom
52 JPoint orgTarget; // Objetivo original
53 JPoint orgEye; // Punto de vista original
54 JVector orgUp; // Sentido vertical original
55 JPoint target; // Objetivo
56 JCoordAxes camera; // Base de la cámara
57
58 // Crea una cámara
59 JGLCamera(JPoint _eye,
60 JPoint _target,
61 JVector _up);
62
63 // Calcula los vectores base en función del ojo y el objetivo
64 void ComputeBasis();
65
66 // Modifica la posición de la cámara (eye) la cantidad indicada
67 void Translate(JVector deltaPos);
68
69 // Mueve la cámara (eye) a la posición indicada
70 void TranslateTo(JVector pos);
71
72 // Rota la cámara en torno:
73 // - al eje x (Pitch, dirección perpendicular al plano eye-target/up)
74 // - al eje y (Roll, dirección eye-target)
75 // - al eje z (Yaw, dirección up)
76 void Rotate(float x, float y, float z);
77
78 // Modifica la posición del objetivo la cantidad indicada
79 void TargetTranslate(JVector deltaTarget);
80
81 // Mueve la posición de objetivo a la posición indicada
82 void TargetTranslateTo(JVector pos);
83
84 // Rota la cámara en torno a un eje pasando por el objetivo
85 void TargetRotate(float x, float y, float z);
86
87 // Zoom. Especifica la cantidad de zoom
88 void Zoom(float amount);
89
90 // Ajusta la perspectiva (más o menos distorsión)
91 void Perspective(float distortAmount);
92
93 // Establece la proyección de cámara
94 void Set();
95
96 // Reset de cámara
97 void Reset();
98 };
99
100 #endif // _JGLCAMERA_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 01/04/2003
25 // @description: Funciones y estructuras para color.
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #ifndef _JGLCOLOR_INCLUDED
29 #define _JGLCOLOR_INCLUDED
30
31 #include <JLib/Util/JTypes.h>
32 #include <JLib/Util/JObject.h>
33
34 // Estructura de definición de color tipo float
35 class JGLColorf : public JObject
36 {
37 public:
38 float r; // Componente roja (0.0f - 1.0f)
39 float g; // Componente verde (0.0f - 1.0f)
40 float b; // Componente azul (0.0f - 1.0f)
41 float a; // Componente alfa (0.0f - 1.0f)
42
43 // Constructor
44 JGLColorf() : r(1.0f), g(1.0f), b(1.0f), a(1.0f) {};
45
46 // Constructor
47 JGLColorf(float _r, float _g, float _b, float _a = 0.0f)
48 : r(_r), g(_g), b(_b), a(_a) {};
49
50 // Constructor
51 JGLColorf(float *arr)
52 : r(arr[0]), g(arr[1]), b(arr[2]), a(arr[3]) {};
53
54 // Asignación de colores
55 const JGLColorf& operator = (const JGLColorf &c)
56 {
57 r = c.r;
58 g = c.g;
59 b = c.b;
60 a = c.a;
61
62 return *this;
63 }
64
65 // Adición de colores
66 const JGLColorf& operator += (const JGLColorf &c)
67 {
68 r += c.r;
69 g += c.g;
70 b += c.b;
71 a += c.a;
72
73 return *this;
74 }
75 };
76
77 const JGLColorf RED = JGLColorf(1.0f, 0.0f, 0.0f, 1.0f);
78 const JGLColorf GREEN = JGLColorf(0.0f, 1.0f, 0.0f, 1.0f);
79 const JGLColorf BLUE = JGLColorf(0.0f, 0.0f, 1.0f, 1.0f);
80 const JGLColorf BLACK = JGLColorf(0.0f, 0.0f, 0.0f, 1.0f);
81 const JGLColorf YELLOW = JGLColorf(1.0f, 1.0f, 0.0f, 1.0f);
82 const JGLColorf CYAN = JGLColorf(0.0f, 1.0f, 1.0f, 1.0f);
83 const JGLColorf MAGENTA = JGLColorf(1.0f, 0.0f, 1.0f, 1.0f);
84 const JGLColorf ORANGE = JGLColorf(1.0f, 0.5f, 0.0f, 1.0f);
85 const JGLColorf PINK = JGLColorf(1.0f, 0.0f, 0.5f, 1.0f);
86 const JGLColorf PURPLE = JGLColorf(0.5f, 0.0f, 1.0f, 1.0f);
87 const JGLColorf INDIGO = JGLColorf(0.0f, 0.5f, 1.0f, 1.0f);
88 const JGLColorf YELLOWGREEN = JGLColorf(0.5f, 1.0f, 0.0f, 1.0f);
89 const JGLColorf TURQUOISE = JGLColorf(0.0f, 1.0f, 0.5f, 1.0f);
90 const JGLColorf GRAY = JGLColorf(0.5f, 0.5f, 0.5f, 1.0f);
91 const JGLColorf WHITE = JGLColorf(1.0f, 1.0f, 1.0f, 1.0f);
92 const JGLColorf LIGHTGRAY = JGLColorf(0.25f, 0.25f, 0.25f, 1.0f);
93
94 // Estructura de definición de color tipo unsigned byte
95 class JGLColorub
96 {
97 public:
98 u8 r; // Componente roja (0 - 255)
99 u8 g; // Componente verde (0 - 255)
100 u8 b; // Componente azul (0 - 255)
101 u8 a; // Componente alfa (0 - 255)
102
103 // Constructor
104 JGLColorub() : r(255), g(255), b(255), a(255) {};
105
106 // Constructor
107 JGLColorub(u8 _r, u8 _g, u8 _b, u8 _a = 255)
108 : r(_r), g(_g), b(_b), a(_a) {};
109
110 // Asignación de colores
111 const JGLColorub& operator = (JGLColorub& c)
112 {
113 r = c.r;
114 g = c.g;
115 b = c.b;
116 a = c.a;
117 return *this;
118 }
119 };
120
121 // Pasa de color decimal (0-1) a byte (0-255)
122 inline JGLColorub JGLColorf2ub(JGLColorf &color)
123 {
124 return JGLColorub((u8)color.r*255,
125 (u8)color.g*255,
126 (u8)color.b*255,
127 (u8)color.a*255);
128 };
129
130 // Pasa de color byte (0-255) a decimal (0-1)
131 inline JGLColorf JGLColorub2f(JGLColorub &color)
132 {
133 return JGLColorf(color.r/255.0f,
134 color.g/255.0f,
135 color.b/255.0f,
136 color.a/255.0f);
137 };
138
139 #endif // _JGLCOLOR_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 20/10/2003
25 // @description: Consola de texto para OpenGL independiente de la plataforma.
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #include <JLib/Graphics/JGLConsole.h>
29
30 // Constructor
31 JGLConsole::JGLConsole()
32 {
33 nextLine = 0;
34 lines = 0;
35 visible = true;
36 isFull = false;
37 chars = (u8 (*)[8])JGLCONSOLEFONT1;
38 ChangeSettings(10, JGLCONSOLE_FONT1);
39 }
40
41 // Destructor
42 JGLConsole::~JGLConsole()
43 {
44 if (lines)
45 delete[] lines;
46 }
47
48 // Cambia los valores por defecto de la consola
49 void JGLConsole::ChangeSettings(s32 _maxLines, JGLCONSOLE_FONT _font)
50 {
51 if (lines)
52 {
53 delete[] lines;
54 }
55
56 maxLines = _maxLines > 0 ? _maxLines : 10;
57 font = _font;
58
59 switch (font)
60 {
61 case JGLCONSOLE_FONT1:
62 chars = (u8 (*)[8])JGLCONSOLEFONT2;
63 break;
64
65 default:
66 case JGLCONSOLE_FONT2:
67 chars = (u8 (*)[8])JGLCONSOLEFONT1;
68 break;
69 }
70
71 lines = new JGLConsoleLine[maxLines];
72 for (s32 i = 0; i < maxLines; ++i)
73 {
74 *lines[i].str = 0;
75 }
76 nextLine = 0;
77 }
78
79 // Dibuja la consola si está visible
80 void JGLConsole::Draw()
81 {
82 if (visible)
83 {
84 //s32 rp[4];
85 //glGetIntegerv(GL_CURRENT_RASTER_POSITION, rp);
86
87 for (s32 i = 0, len = 0; i < maxLines; ++i)
88 {
89 if (*lines[i].str)
90 {
91 len = (u32)strlen(lines[i].str);
92 //Printf("(%d, %d, %d, %d)", rp[0], rp[1], rp[2], rp[3]);
93 //glRasterPos2d(rp[0], rp[1] + (8 * lines[i].line));
94 //glRasterPos2d(rp[0], 10);
95 glRasterPos2d(0, 10);
96
97 for (s32 j = 0; j < len; ++j)
98 {
99 GLenum e;
100 glBitmap(8, 8, 0, 0, 0, 0, ((u8 *)&chars[(u8)lines[i].str[j]]));
101 e = glGetError();
102 e = e;
103 }
104 }
105 }
106 }
107 }
108
109 // Añade una cadena a la consola (tipo 'printf()')
110 void JGLConsole::Printf(const s8 *str, ...)
111 {
112 if (nextLine == maxLines)
113 {
114 nextLine = 0;
115 isFull = true;
116 }
117
118 if (isFull)
119 {
120 // Desplaza el texto de la consola una línea hacia arriba
121 for (s32 i = 0; i < maxLines; ++i)
122 {
123 --lines[i].line;
124 }
125 }
126
127 va_list vlist;
128 s8 _str[JGLCONSOLE_MAX_LINE];
129
130 va_start(vlist, str);
131 vsprintf(_str, str, vlist);
132 va_end(vlist);
133
134 strcpy(lines[nextLine].str, _str);
135 lines[nextLine].line = isFull ? maxLines - 1 : nextLine;
136 ++nextLine;
137 }
138
139 // Borra la consola
140 void JGLConsole::Clear()
141 {
142 for (s32 i = 0; i < maxLines; ++i)
143 {
144 *lines[i].str = 0;
145 }
146
147 nextLine = 0;
148 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 20/10/2003
25 // @description: Consola de texto para OpenGL independiente de la plataforma.
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #ifndef _JGLCONSOLE_INCLUDED
29 #define _JGLCONSOLE_INCLUDED
30
31 #include <JLib/Util/JTypes.h>
32 #include <JLib/Graphics/JDrawable.h>
33 #include <JLib/Graphics/JGLConsoleFont.h>
34 #include <GL/gl.h>
35 #include <string.h>
36 #include <stdio.h>
37 #include <stdarg.h>
38
39 #define JGLCONSOLE_MAX_LINE 128
40
41 typedef enum
42 {
43 JGLCONSOLE_FONT1 = 1,
44 JGLCONSOLE_FONT2
45 } JGLCONSOLE_FONT;
46
47 // Línea de texto en la consola
48 typedef struct _JGLConsoleLine
49 {
50 s8 str[JGLCONSOLE_MAX_LINE]; // Cadena a mostrar
51 s32 line; // Línea en la que se muestra
52 } JGLConsoleLine;
53
54 class JGLConsole : public JDrawable
55 {
56 s32 maxLines; // Nº de líneas en pantalla
57 bool visible; // Flag de visibilidad
58 s32 nextLine; // Siguiente línea libre
59 bool isFull; // Indicador de texto en la última línea
60 u8 (*chars)[8]; // Puntero a los caracteres
61 JGLCONSOLE_FONT font; // Fuente usada
62 JGLConsoleLine *lines; // Líneas en pantalla
63
64 public:
65
66 // Constructor
67 JGLConsole();
68
69 // Destructor
70 ~JGLConsole();
71
72 // Inicializa la consola
73 void ChangeSettings(s32 _maxLines, JGLCONSOLE_FONT _font);
74
75 // Dibuja la consola si está visible
76 void Draw();
77
78 // Añade una cadena a la consola (tipo 'printf()')
79 void Printf(const s8 *str, ...);
80
81 // Borra la consola
82 void Clear();
83
84 // Muestra/oculta la consola
85 void SetVisible(bool b) {visible = b;}
86
87 // Determina si la consola está visible
88 bool IsVisible() {return visible;}
89 };
90
91 #endif // _JGLCONSOLE_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 20/10/2003
25 // @description: Consola de texto para OpenGL independiente de la plataforma.
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #ifndef _JGLCONSOLEFONT_INCLUDED
29 #define _JGLCONSOLEFONT_INCLUDED
30
31 #include <JLib/Util/JTypes.h>
32 const u8 JGLCONSOLEFONT1[256][8] = {
33 {0x00,0x00,0x00,0x40,0x80,0x80,0x80,0x40,},
34 {0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,},
35 {0x00,0x00,0x00,0xc0,0x80,0xc0,0x40,0xc0,},
36 {0x00,0x00,0x00,0xc0,0x40,0xc0,0x40,0xc0,},
37 {0x00,0x00,0x00,0x40,0x40,0xc0,0x80,0x80,},
38 {0x00,0x00,0x00,0xc0,0x40,0xc0,0x80,0xc0,},
39 {0x00,0x00,0x00,0xc0,0xc0,0xc0,0x80,0x80,},
40 {0x00,0x00,0x00,0x80,0x80,0x80,0x40,0xc0,},
41 {0x00,0x00,0x00,0x40,0x80,0x40,0x80,0x40,},
42 {0x00,0x00,0x00,0x40,0x40,0xc0,0xc0,0xc0,},
43 {0x00,0x00,0x00,0x90,0xa0,0xa0,0xa0,0x90,},
44 {0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90,},
45 {0x00,0x00,0x00,0xb0,0xa0,0xb0,0x90,0xb0,},
46 {0x00,0x00,0x00,0xb0,0x90,0xb0,0x90,0xb0,},
47 {0x00,0x00,0x00,0x90,0x90,0xb0,0xa0,0xa0,},
48 {0x00,0x00,0x00,0xb0,0x90,0xb0,0xa0,0xb0,},
49 {0x00,0x00,0x00,0x98,0x98,0x98,0x90,0x90,},
50 {0x00,0x00,0x00,0x90,0x90,0x90,0x88,0x98,},
51 {0x00,0x00,0x00,0x98,0x98,0x80,0x98,0x98,},
52 {0x00,0x00,0x00,0x88,0x88,0x98,0x98,0x98,},
53 {0x00,0x00,0x00,0xc8,0x90,0xd0,0x50,0xc8,},
54 {0x00,0x00,0x00,0xd0,0x90,0xd0,0x50,0xd0,},
55 {0x00,0x00,0x00,0xd8,0x90,0xd8,0x48,0xd8,},
56 {0x00,0x00,0x00,0xd8,0x88,0xd8,0x48,0xd8,},
57 {0x00,0x00,0x00,0xc8,0x88,0xd8,0x50,0xd0,},
58 {0x00,0x00,0x00,0xd8,0x88,0xd8,0x50,0xd8,},
59 {0x00,0x00,0x00,0xd8,0x98,0xd8,0x50,0xd0,},
60 {0x00,0x00,0x00,0xd0,0x90,0xd0,0x48,0xd8,},
61 {0x00,0x00,0x00,0xc8,0x90,0xc8,0x50,0xc8,},
62 {0x00,0x00,0x00,0xc8,0x88,0xd8,0x58,0xd8,},
63 {0x00,0x00,0x00,0xc8,0x50,0xd0,0x50,0xc8,},
64 {0x00,0x00,0x00,0xd0,0x50,0xd0,0x50,0xd0,},
65 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,},
66 {0x00,0x10,0x00,0x10,0x10,0x20,0x20,0x20,},
67 {0x00,0x00,0x00,0x00,0x00,0x28,0x6c,0x6c,},
68 {0x00,0x44,0xfe,0x44,0x44,0x44,0xfe,0x44,},
69 {0x00,0x10,0x7c,0x12,0x7c,0x90,0x7c,0x10,},
70 {0x00,0x04,0x4a,0x24,0x10,0x48,0xa4,0x40,},
71 {0x00,0x70,0x8c,0x88,0x54,0x20,0x40,0x38,},
72 {0x00,0x00,0x00,0x00,0x00,0x10,0x30,0x30,},
73 {0x00,0x18,0x20,0x20,0x20,0x20,0x10,0x08,},
74 {0x00,0x20,0x10,0x08,0x08,0x08,0x08,0x30,},
75 {0x00,0x00,0x54,0x38,0x7c,0x38,0x54,0x00,},
76 {0x00,0x00,0x10,0x10,0x7c,0x10,0x10,0x00,},
77 {0x00,0x10,0x30,0x20,0x00,0x00,0x00,0x00,},
78 {0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,},
79 {0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,},
80 {0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x00,},
81 {0x00,0xbc,0x42,0xa2,0x92,0x8a,0x84,0x7a,},
82 {0x00,0x08,0x08,0x28,0x18,0x08,0x08,0x08,},
83 {0x00,0x7e,0x80,0x40,0x3c,0x02,0x84,0x78,},
84 {0x00,0x60,0x90,0x88,0x04,0x3c,0x04,0xfc,},
85 {0x00,0x02,0x02,0x3e,0x42,0x82,0x82,0x82,},
86 {0x00,0xf0,0x08,0x04,0x02,0xfc,0x80,0xfe,},
87 {0x00,0x3c,0x42,0x82,0x84,0xf8,0x80,0x70,},
88 {0x00,0x80,0x80,0x40,0x20,0x1c,0x02,0xfe,},
89 {0x00,0x7c,0x82,0x82,0x82,0x7c,0x82,0x7c,},
90 {0x00,0xe0,0x10,0x08,0x7c,0x82,0x82,0x7c,},
91 {0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,},
92 {0x00,0x10,0x30,0x20,0x00,0x30,0x30,0x00,},
93 {0x00,0x08,0x10,0x20,0x40,0x20,0x10,0x08,},
94 {0x00,0x00,0x00,0x7c,0x00,0x7c,0x00,0x00,},
95 {0x00,0x20,0x10,0x08,0x04,0x08,0x10,0x20,},
96 {0x00,0x10,0x00,0x10,0x18,0x04,0x44,0x38,},
97 {0x00,0x38,0x40,0x9c,0xaa,0x92,0x44,0x38,},
98 {0x00,0x82,0x82,0x82,0x7e,0x22,0x12,0x0c,},
99 {0x00,0xfc,0x82,0x84,0xf8,0x84,0x82,0xfc,},
100 {0x00,0x7e,0x80,0x80,0x40,0x20,0x10,0x0e,},
101 {0x00,0xfc,0x82,0x82,0x84,0x88,0x90,0xe0,},
102 {0x00,0xfe,0x80,0x80,0x7c,0x20,0x10,0x0e,},
103 {0x00,0x80,0x80,0x80,0x78,0x20,0x10,0x0e,},
104 {0x00,0x7c,0x82,0x82,0x46,0x20,0x10,0x0e,},
105 {0x00,0x82,0x82,0x82,0xfe,0x82,0x82,0x82,},
106 {0x00,0xfe,0x10,0x10,0x10,0x10,0x10,0xfe,},
107 {0x00,0x7c,0x82,0x82,0x44,0x08,0x10,0xe0,},
108 {0x00,0x82,0x84,0x88,0x90,0xe0,0x90,0x88,},
109 {0x00,0xfe,0x80,0x80,0x40,0x20,0x10,0x08,},
110 {0x00,0x82,0x82,0x8a,0x96,0xa2,0xc0,0x80,},
111 {0x00,0x82,0x86,0x8a,0x92,0xa0,0xc0,0x80,},
112 {0x00,0x70,0x88,0x84,0x82,0x42,0x22,0x1c,},
113 {0x00,0x80,0x80,0xf0,0x88,0x84,0x82,0xfc,},
114 {0x00,0x72,0x8c,0x8c,0x82,0x42,0x22,0x1c,},
115 {0x00,0x82,0x84,0x88,0xf0,0x88,0x84,0xf8,},
116 {0x00,0xf0,0x08,0x04,0x38,0x40,0x20,0x1e,},
117 {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0xfe,},
118 {0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x82,},
119 {0x00,0x06,0x0a,0x12,0x22,0x42,0x82,0x82,},
120 {0x00,0x12,0x36,0x5a,0x92,0x82,0x82,0x82,},
121 {0x00,0x82,0x44,0x28,0x10,0x28,0x44,0x82,},
122 {0x00,0xe0,0x10,0x08,0x14,0x22,0x42,0x42,},
123 {0x00,0xfe,0x40,0x20,0x10,0x08,0x04,0xfe,},
124 {0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x38,},
125 {0x00,0x00,0x04,0x08,0x10,0x20,0x40,0x00,},
126 {0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x38,},
127 {0x00,0x00,0x00,0x00,0x00,0x44,0x28,0x10,},
128 {0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,},
129 {0x00,0x00,0x00,0x00,0x00,0x08,0x18,0x30,},
130 {0x00,0x7e,0x82,0x7e,0x02,0x1c,0x00,0x00,},
131 {0x00,0xfc,0x82,0x84,0xf8,0x80,0x80,0x00,},
132 {0x00,0x7e,0x80,0x40,0x3e,0x00,0x00,0x00,},
133 {0x00,0x7e,0x82,0x42,0x3e,0x02,0x02,0x00,},
134 {0x00,0x38,0x40,0xfc,0x42,0x3c,0x00,0x00,},
135 {0x00,0x80,0x80,0x70,0x20,0x1e,0x00,0x00,},
136 {0x00,0x38,0x04,0x7e,0x84,0x78,0x00,0x00,},
137 {0x00,0x82,0x82,0x84,0xf8,0x80,0x00,0x00,},
138 {0x00,0xfe,0x08,0x08,0x10,0x00,0x08,0x00,},
139 {0x00,0x78,0x84,0x82,0x0c,0x00,0x08,0x00,},
140 {0x00,0x82,0x84,0xf8,0x90,0x88,0x00,0x00,},
141 {0x00,0x3e,0x40,0x80,0x80,0x80,0x00,0x00,},
142 {0x00,0x82,0x82,0x42,0x2a,0x14,0x00,0x00,},
143 {0x00,0x82,0x82,0x84,0xc8,0xb0,0x00,0x00,},
144 {0x00,0x78,0x84,0x82,0x42,0x3c,0x00,0x00,},
145 {0x00,0x80,0xf8,0x84,0x82,0xfc,0x00,0x00,},
146 {0x00,0x02,0x7e,0x82,0x42,0x3c,0x00,0x00,},
147 {0x00,0x80,0x80,0xc0,0xa0,0x9e,0x00,0x00,},
148 {0x00,0xf8,0x04,0x18,0x20,0x1e,0x00,0x00,},
149 {0x00,0x06,0x08,0x10,0x10,0xf8,0x10,0x00,},
150 {0x00,0x7c,0x82,0x82,0x82,0x82,0x00,0x00,},
151 {0x00,0x0e,0x12,0x22,0x42,0x82,0x00,0x00,},
152 {0x00,0x2c,0x52,0x82,0x82,0x82,0x00,0x00,},
153 {0x00,0x82,0x44,0x38,0x44,0x82,0x00,0x00,},
154 {0x00,0xe0,0x10,0x08,0x14,0x22,0x00,0x00,},
155 {0x00,0x3e,0x20,0x10,0x08,0xf8,0x00,0x00,},
156 {0x00,0x18,0x20,0x20,0x40,0x20,0x20,0x18,},
157 {0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,},
158 {0x00,0x30,0x08,0x08,0x04,0x08,0x08,0x30,},
159 {0x00,0x00,0x00,0x00,0x0c,0x92,0x60,0x00,},
160 {0x00,0x00,0xd1,0x8a,0xca,0x92,0xc9,0x00,},
161 {0x00,0x3e,0x40,0xf8,0x40,0xfc,0x20,0x1e,},
162 {0x00,0x00,0x00,0x99,0x91,0x9b,0x8b,0x9b,},
163 {0x00,0x60,0x30,0x18,0x00,0x00,0x00,0x00,},
164 {0x00,0x60,0x90,0x10,0x38,0x10,0x12,0x0c,},
165 {0x00,0xcc,0x66,0x33,0x00,0x00,0x00,0x00,},
166 {0x00,0x54,0x00,0x00,0x00,0x00,0x00,0x00,},
167 {0x00,0x10,0x10,0x10,0x10,0x38,0x7c,0x10,},
168 {0x00,0x10,0x7c,0x10,0x10,0x10,0x7c,0x10,},
169 {0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,},
170 {0x00,0x8a,0x55,0x2a,0x10,0x48,0xa4,0x42,},
171 {0x00,0xfc,0x02,0x7c,0x80,0x7e,0x10,0x38,},
172 {0x00,0x10,0x20,0x40,0x20,0x10,0x00,0x00,},
173 {0x00,0x78,0x44,0x44,0x74,0x44,0x44,0x78,},
174 {0x00,0x00,0x00,0x8a,0x8a,0x9a,0x92,0x92,},
175 {0x00,0xfe,0x80,0x7c,0x02,0xfe,0x10,0x38,},
176 {0x00,0x00,0x00,0x8b,0x89,0x9b,0x91,0x93,},
177 {0x00,0x00,0x00,0x89,0x89,0x9b,0x92,0x92,},
178 {0x00,0x00,0x00,0x00,0x00,0x0c,0x18,0x30,},
179 {0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x18,},
180 {0x00,0x00,0x00,0x00,0x00,0x24,0x48,0x90,},
181 {0x00,0x00,0x00,0x00,0x00,0x48,0x24,0x12,},
182 {0x00,0x00,0x38,0x7c,0x7c,0x7c,0x38,0x00,},
183 {0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,},
184 {0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,},
185 {0x00,0x00,0x00,0x00,0x00,0x08,0x54,0x20,},
186 {0x00,0x00,0x00,0x00,0x00,0x4a,0x4e,0xea,},
187 {0x00,0xfc,0x02,0x7c,0x80,0x7e,0x10,0x38,},
188 {0x00,0x10,0x08,0x04,0x08,0x10,0x00,0x00,},
189 {0x00,0x6e,0x90,0x90,0x9c,0x92,0x92,0x6c,},
190 {0x00,0x00,0x00,0x9a,0x8a,0x9a,0x91,0x9b,},
191 {0x00,0xfe,0x80,0x78,0x04,0xfc,0x10,0x38,},
192 {0x00,0x38,0x10,0x38,0x44,0xee,0x00,0x44,},
193 {0x00,0x00,0x00,0x99,0x9a,0x9a,0x92,0x91,},
194 {0x00,0x20,0x20,0x20,0x10,0x10,0x00,0x10,},
195 {0x00,0x10,0x7c,0x80,0x40,0x20,0x1e,0x08,},
196 {0x00,0x7e,0x20,0x10,0x7c,0x20,0x24,0x18,},
197 {0x00,0x00,0x54,0x28,0x44,0x28,0x54,0x00,},
198 {0x38,0x10,0x7c,0x10,0xfe,0x10,0x28,0xc6,},
199 {0x00,0x10,0x10,0x10,0x00,0x10,0x10,0x10,},
200 {0x00,0xf0,0x0c,0x32,0x4c,0xb0,0x40,0x3c,},
201 {0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x6c,},
202 {0x00,0x38,0x44,0xba,0xa2,0xba,0x44,0x38,},
203 {0x00,0x00,0x00,0x00,0x38,0x38,0x08,0x30,},
204 {0x00,0x00,0x12,0x24,0x48,0x24,0x12,0x00,},
205 {0x00,0x00,0x04,0x04,0x7c,0x00,0x00,0x00,},
206 {0x00,0x7c,0xaa,0xaa,0xb2,0xaa,0x92,0x7c,},
207 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,},
208 {0x00,0x00,0x00,0x93,0x91,0x93,0x8a,0x9b,},
209 {0x00,0x00,0x00,0x00,0x30,0x48,0x48,0x30,},
210 {0x00,0x7c,0x00,0x10,0x10,0x7c,0x10,0x10,},
211 {0x00,0x00,0x00,0x3c,0x10,0x08,0x24,0x18,},
212 {0x00,0x00,0x00,0x30,0x08,0x18,0x08,0x38,},
213 {0x00,0x00,0x00,0x00,0x00,0x20,0x10,0x08,},
214 {0x00,0x80,0x80,0x84,0xf8,0x88,0x88,0x00,},
215 {0x00,0xe8,0x28,0x28,0x68,0xa8,0xa8,0x7c,},
216 {0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,},
217 {0x00,0x18,0x08,0x00,0x00,0x00,0x00,0x00,},
218 {0x00,0x00,0x00,0x38,0x10,0x10,0x30,0x10,},
219 {0x00,0x00,0x00,0x10,0x28,0x28,0x28,0x10,},
220 {0x00,0x00,0x48,0x24,0x12,0x24,0x48,0x00,},
221 {0x00,0x82,0x4e,0x2a,0x10,0x48,0x44,0x42,},
222 {0x00,0x86,0x44,0x22,0x16,0x48,0x44,0x42,},
223 {0x00,0x82,0x4e,0xea,0x50,0xc8,0x44,0xc2,},
224 {0x00,0x38,0x44,0x40,0x30,0x10,0x00,0x10,},
225 {0x00,0x82,0x7e,0x22,0x12,0x0c,0x04,0x08,},
226 {0x00,0x82,0x7e,0x22,0x12,0x0c,0x04,0x02,},
227 {0x00,0x82,0x7e,0x22,0x12,0x0c,0x0a,0x04,},
228 {0x00,0x82,0x7e,0x22,0x12,0x0c,0x14,0x0a,},
229 {0x00,0x82,0x7e,0x22,0x12,0x0c,0x00,0x12,},
230 {0x00,0x82,0x7e,0x22,0x12,0x0c,0x12,0x0c,},
231 {0x00,0x8e,0xf8,0x48,0x4c,0x28,0x28,0x1e,},
232 {0x00,0x18,0x08,0x7e,0x80,0x40,0x20,0x1e,},
233 {0x00,0xfe,0x40,0x38,0x10,0x0e,0x04,0x08,},
234 {0x00,0xfe,0x40,0x38,0x10,0x0e,0x04,0x02,},
235 {0x00,0xfe,0x40,0x38,0x10,0x0e,0x0a,0x04,},
236 {0x00,0xfe,0x40,0x38,0x10,0x0e,0x00,0x12,},
237 {0x00,0xfe,0x10,0x10,0x10,0xfe,0x08,0x10,},
238 {0x00,0xfe,0x10,0x10,0x10,0xfe,0x10,0x08,},
239 {0x00,0xfe,0x10,0x10,0x10,0xfe,0x28,0x10,},
240 {0x00,0xfe,0x10,0x10,0x10,0xfe,0x00,0x44,},
241 {0x00,0x78,0x44,0x44,0x74,0x44,0x44,0x78,},
242 {0x00,0x82,0x86,0x8a,0x92,0xa0,0xc0,0x9e,},
243 {0x00,0x78,0x84,0x82,0x42,0x3c,0x08,0x10,},
244 {0x00,0x78,0x84,0x82,0x42,0x3c,0x08,0x04,},
245 {0x00,0x78,0x84,0x82,0x42,0x3c,0x14,0x08,},
246 {0x00,0x78,0x84,0x82,0x42,0x3c,0x14,0x0a,},
247 {0x00,0x78,0x84,0x82,0x42,0x3c,0x00,0x12,},
248 {0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x00,},
249 {0x00,0xb0,0x48,0xa4,0x92,0x4a,0x24,0x1a,},
250 {0x00,0x7c,0x82,0x82,0x82,0x82,0x10,0x20,},
251 {0x00,0x7c,0x82,0x82,0x82,0x82,0x10,0x08,},
252 {0x00,0x7c,0x82,0x82,0x82,0x82,0x28,0x10,},
253 {0x00,0x7c,0x82,0x82,0x82,0x82,0x00,0x44,},
254 {0x00,0xe0,0x10,0x18,0x24,0x42,0x52,0x08,},
255 {0x00,0xfc,0x40,0x70,0x48,0x70,0x40,0xfc,},
256 {0x00,0xb8,0x84,0x84,0x88,0x90,0x48,0x30,},
257 {0x00,0x7e,0x82,0x7e,0x02,0x1c,0x08,0x10,},
258 {0x00,0x7e,0x82,0x7e,0x02,0x1c,0x08,0x04,},
259 {0x00,0x7e,0x82,0x7e,0x02,0x1c,0x14,0x08,},
260 {0x00,0x7e,0x82,0x7e,0x02,0x1c,0x28,0x14,},
261 {0x00,0x7e,0x82,0x7e,0x02,0x1c,0x00,0x24,},
262 {0x00,0x7e,0x82,0x7e,0x02,0x1c,0x24,0x18,},
263 {0x00,0x7c,0x90,0x7c,0x12,0x6c,0x00,0x00,},
264 {0x00,0x18,0x08,0x7e,0x80,0x40,0x20,0x1e,},
265 {0x00,0x38,0x40,0xfc,0x42,0x3c,0x10,0x20,},
266 {0x00,0x38,0x40,0xfc,0x42,0x3c,0x08,0x04,},
267 {0x00,0x38,0x40,0xfc,0x42,0x3c,0x28,0x10,},
268 {0x00,0x38,0x40,0xfc,0x42,0x3c,0x00,0x24,},
269 {0x00,0xfe,0x08,0x08,0x10,0x00,0x08,0x10,},
270 {0x00,0xfe,0x08,0x08,0x10,0x00,0x08,0x04,},
271 {0x00,0xfe,0x08,0x08,0x10,0x00,0x28,0x10,},
272 {0x00,0xfe,0x08,0x08,0x10,0x00,0x00,0x48,},
273 {0x00,0x7c,0x82,0x82,0x7c,0x28,0x4c,0x32,},
274 {0x00,0x82,0x82,0x84,0xc8,0xb0,0x00,0xf0,},
275 {0x00,0x78,0x84,0x82,0x42,0x3c,0x10,0x20,},
276 {0x00,0x78,0x84,0x82,0x42,0x3c,0x08,0x04,},
277 {0x00,0x78,0x84,0x82,0x42,0x3c,0x14,0x08,},
278 {0x00,0x78,0x84,0x82,0x42,0x3c,0x28,0x14,},
279 {0x00,0x78,0x84,0x82,0x42,0x3c,0x00,0x12,},
280 {0x00,0x00,0x10,0x00,0x7c,0x00,0x10,0x00,},
281 {0x00,0xf8,0xe4,0x9a,0x46,0x3e,0x00,0x00,},
282 {0x00,0x7c,0x82,0x82,0x82,0x82,0x10,0x20,},
283 {0x00,0x7c,0x82,0x82,0x82,0x82,0x10,0x08,},
284 {0x00,0x7c,0x82,0x82,0x82,0x82,0x28,0x10,},
285 {0x00,0x7c,0x82,0x82,0x82,0x82,0x00,0x44,},
286 {0x00,0xe0,0x10,0x18,0x24,0x42,0x10,0x08,},
287 {0x00,0xc0,0x5c,0x62,0x62,0x62,0x5c,0xc0,},
288 {0x00,0x00,0x00,0xdb,0x89,0xdb,0x52,0xdb,},
289 };
290
291 const u8 JGLCONSOLEFONT2[256][8] = {
292 {0x00,0x00,0x00,0x40,0x80,0x80,0x80,0x40,},
293 {0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,},
294 {0x00,0x00,0x00,0xc0,0x80,0xc0,0x40,0xc0,},
295 {0x00,0x00,0x00,0xc0,0x40,0xc0,0x40,0xc0,},
296 {0x00,0x00,0x00,0x40,0x40,0xc0,0x80,0x80,},
297 {0x00,0x00,0x00,0xc0,0x40,0xc0,0x80,0xc0,},
298 {0x00,0x00,0x00,0xc0,0xc0,0xc0,0x80,0x80,},
299 {0x00,0x00,0x00,0x80,0x80,0x80,0x40,0xc0,},
300 {0x00,0x00,0x00,0x40,0x80,0x40,0x80,0x40,},
301 {0x00,0x00,0x00,0x40,0x40,0xc0,0xc0,0xc0,},
302 {0x00,0x00,0x00,0x90,0xa0,0xa0,0xa0,0x90,},
303 {0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90,},
304 {0x00,0x00,0x00,0xb0,0xa0,0xb0,0x90,0xb0,},
305 {0x00,0x00,0x00,0xb0,0x90,0xb0,0x90,0xb0,},
306 {0x00,0x00,0x00,0x90,0x90,0xb0,0xa0,0xa0,},
307 {0x00,0x00,0x00,0xb0,0x90,0xb0,0xa0,0xb0,},
308 {0x00,0x00,0x00,0x98,0x98,0x98,0x90,0x90,},
309 {0x00,0x00,0x00,0x90,0x90,0x90,0x88,0x98,},
310 {0x00,0x00,0x00,0x98,0x98,0x80,0x98,0x98,},
311 {0x00,0x00,0x00,0x88,0x88,0x98,0x98,0x98,},
312 {0x00,0x00,0x00,0xc8,0x90,0xd0,0x50,0xc8,},
313 {0x00,0x00,0x00,0xd0,0x90,0xd0,0x50,0xd0,},
314 {0x00,0x00,0x00,0xd8,0x90,0xd8,0x48,0xd8,},
315 {0x00,0x00,0x00,0xd8,0x88,0xd8,0x48,0xd8,},
316 {0x00,0x00,0x00,0xc8,0x88,0xd8,0x50,0xd0,},
317 {0x00,0x00,0x00,0xd8,0x88,0xd8,0x50,0xd8,},
318 {0x00,0x00,0x00,0xd8,0x98,0xd8,0x50,0xd0,},
319 {0x00,0x00,0x00,0xd0,0x90,0xd0,0x48,0xd8,},
320 {0x00,0x00,0x00,0xc8,0x90,0xc8,0x50,0xc8,},
321 {0x00,0x00,0x00,0xc8,0x88,0xd8,0x58,0xd8,},
322 {0x00,0x00,0x00,0xc8,0x50,0xd0,0x50,0xc8,},
323 {0x00,0x00,0x00,0xd0,0x50,0xd0,0x50,0xd0,},
324 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,},
325 {0x00,0x10,0x00,0x10,0x10,0x20,0x20,0x20,},
326 {0x00,0x00,0x00,0x00,0x00,0x28,0x6c,0x6c,},
327 {0x00,0x44,0xfe,0x44,0x44,0x44,0xfe,0x44,},
328 {0x00,0x10,0x7c,0x12,0x7c,0x90,0x7c,0x10,},
329 {0x00,0x04,0x4a,0x24,0x10,0x48,0xa4,0x40,},
330 {0x00,0x70,0x8c,0x88,0x54,0x20,0x40,0x38,},
331 {0x00,0x00,0x00,0x00,0x00,0x10,0x30,0x30,},
332 {0x00,0x18,0x20,0x20,0x20,0x20,0x10,0x08,},
333 {0x00,0x20,0x10,0x08,0x08,0x08,0x08,0x30,},
334 {0x00,0x00,0x54,0x38,0x7c,0x38,0x54,0x00,},
335 {0x00,0x00,0x10,0x10,0x7c,0x10,0x10,0x00,},
336 {0x00,0x10,0x30,0x20,0x00,0x00,0x00,0x00,},
337 {0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,},
338 {0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,},
339 {0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x00,},
340 {0x00,0x7c,0xfe,0xb2,0x9a,0x8e,0xfe,0x7c,},
341 {0x00,0x08,0x08,0x08,0x08,0x38,0x38,0x18,},
342 {0x00,0xfe,0xfe,0xe0,0x7c,0x0e,0xfe,0x7c,},
343 {0x00,0x7c,0xfe,0x86,0x1e,0x06,0xfe,0xfe,},
344 {0x00,0x06,0x06,0xfe,0xfe,0xc6,0xc6,0xc6,},
345 {0x00,0xfe,0xfe,0x06,0xfe,0xc0,0xfe,0xfe,},
346 {0x00,0x7c,0xfe,0xc6,0xfc,0xc0,0xfe,0x7e,},
347 {0x00,0x30,0x30,0x30,0x18,0x0c,0xfe,0xfe,},
348 {0x00,0x7c,0xfe,0xc6,0x7c,0xc6,0xfe,0x7c,},
349 {0x00,0x30,0x18,0x7c,0xfe,0xc6,0xfe,0x7c,},
350 {0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,},
351 {0x00,0x10,0x30,0x20,0x00,0x30,0x30,0x00,},
352 {0x00,0x08,0x10,0x20,0x40,0x20,0x10,0x08,},
353 {0x00,0x00,0x00,0x7c,0x00,0x7c,0x00,0x00,},
354 {0x00,0x20,0x10,0x08,0x04,0x08,0x10,0x20,},
355 {0x00,0x10,0x00,0x10,0x18,0x04,0x44,0x38,},
356 {0x00,0x38,0x40,0x9c,0xaa,0x92,0x44,0x38,},
357 {0x00,0x82,0x82,0xfe,0xfe,0x82,0xfe,0x7c,},
358 {0x00,0xfc,0xfe,0x84,0xf8,0x84,0xfe,0xfc,},
359 {0x00,0x7e,0xfe,0x80,0x80,0x80,0xfe,0x7e,},
360 {0x00,0xfc,0xfe,0x82,0x82,0x82,0xfe,0xfc,},
361 {0x00,0x7e,0xfe,0x80,0xfc,0x80,0xfe,0x7e,},
362 {0x00,0x80,0x80,0x80,0xf8,0x80,0xfe,0x7e,},
363 {0x00,0x7c,0xfe,0x82,0x8e,0x80,0xfe,0x7e,},
364 {0x00,0x82,0x82,0xfe,0xfe,0x82,0x82,0x82,},
365 {0x00,0xfe,0xfe,0x10,0x10,0x10,0xfe,0xfe,},
366 {0x00,0x7c,0xfe,0x82,0x02,0x02,0xfe,0xfc,},
367 {0x00,0x86,0x8c,0x98,0x90,0xf0,0x98,0x8c,},
368 {0x00,0xfe,0xfe,0x80,0x80,0x80,0x80,0x80,},
369 {0x00,0x82,0x82,0x82,0x92,0xba,0xee,0xc6,},
370 {0x00,0x86,0x8e,0x9a,0xb2,0xe2,0xc2,0x82,},
371 {0x00,0x7c,0xfe,0x82,0x82,0x82,0xfe,0x7c,},
372 {0x00,0x80,0x80,0xfc,0xfe,0x82,0xfe,0xfc,},
373 {0x00,0x7a,0xfc,0x8a,0x82,0x82,0xfe,0x7c,},
374 {0x00,0x82,0x86,0xfc,0xfe,0x82,0xfe,0xfc,},
375 {0x00,0xfc,0xfe,0x02,0x7c,0x80,0xfe,0x7e,},
376 {0x00,0x10,0x10,0x10,0x10,0x10,0xfe,0xfe,},
377 {0x00,0x7c,0xfe,0x82,0x82,0x82,0x82,0x82,},
378 {0x00,0x38,0x6c,0xc6,0x82,0x82,0x82,0x82,},
379 {0x00,0x28,0x7c,0xd6,0x92,0x92,0x82,0x82,},
380 {0x00,0xc6,0x6c,0x38,0x38,0x6c,0xc6,0x82,},
381 {0x00,0x10,0x10,0x10,0x38,0x6c,0xc6,0x82,},
382 {0x00,0xfe,0xfe,0x60,0x38,0x0c,0xfe,0xfe,},
383 {0x00,0x38,0x38,0x20,0x20,0x20,0x38,0x38,},
384 {0x00,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,},
385 {0x00,0x38,0x38,0x08,0x08,0x08,0x38,0x38,},
386 {0x00,0x00,0x00,0x00,0x44,0x6c,0x38,0x10,},
387 {0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,},
388 {0x00,0x00,0x00,0x00,0x08,0x18,0x38,0x70,},
389 {0x00,0x7e,0xfe,0x82,0x7e,0x02,0x3c,0x00,},
390 {0x00,0xfc,0xfe,0x82,0x82,0xfc,0x80,0x80,},
391 {0x00,0x7e,0xfe,0x80,0x80,0x7e,0x00,0x00,},
392 {0x00,0x7e,0xfe,0x82,0x82,0x7e,0x02,0x02,},
393 {0x00,0x7e,0xfe,0x80,0xfe,0x82,0x7c,0x00,},
394 {0x00,0x80,0x80,0xf8,0x80,0xfe,0x7e,0x00,},
395 {0x00,0xfc,0xfe,0x02,0x7e,0x82,0x7c,0x00,},
396 {0x00,0x82,0x82,0xfe,0xfc,0x80,0x80,0x80,},
397 {0x00,0x38,0x38,0x10,0x10,0x10,0x00,0x10,},
398 {0x00,0x78,0xfc,0x84,0x04,0x04,0x00,0x04,},
399 {0x00,0x86,0x8c,0xf8,0xf0,0x98,0x80,0x80,},
400 {0x00,0x38,0x78,0x40,0x40,0x40,0x40,0x40,},
401 {0x00,0x82,0x82,0xfe,0xfe,0x6c,0x00,0x00,},
402 {0x00,0x82,0x82,0xc2,0xfe,0xbc,0x00,0x00,},
403 {0x00,0x7c,0xfe,0x82,0x82,0x7c,0x00,0x00,},
404 {0x00,0x80,0xfc,0xfe,0x82,0xfc,0x00,0x00,},
405 {0x00,0x02,0x7e,0xfe,0x82,0x7e,0x00,0x00,},
406 {0x00,0x80,0x80,0xc0,0xfe,0xbe,0x00,0x00,},
407 {0x00,0xfc,0xfe,0x3c,0x60,0x3e,0x00,0x00,},
408 {0x00,0x1c,0x3c,0x20,0x20,0xf8,0x20,0x20,},
409 {0x00,0x7c,0xfe,0x82,0x82,0x82,0x00,0x00,},
410 {0x00,0x10,0x38,0x6c,0xc6,0x82,0x00,0x00,},
411 {0x00,0x7c,0xd6,0x92,0x82,0x82,0x00,0x00,},
412 {0x00,0xc6,0x6c,0x7c,0xc6,0x82,0x00,0x00,},
413 {0x00,0x10,0x10,0x7c,0xfe,0x82,0x00,0x00,},
414 {0x00,0x7e,0x7e,0x30,0x08,0xfc,0x00,0x00,},
415 {0x00,0x18,0x38,0x20,0x40,0x20,0x38,0x18,},
416 {0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,},
417 {0x00,0x30,0x38,0x08,0x04,0x08,0x38,0x30,},
418 {0x00,0x00,0x00,0x00,0x0c,0x92,0x60,0x00,},
419 {0x00,0x00,0xd1,0x8a,0xca,0x92,0xc9,0x00,},
420 {0x00,0x3e,0x40,0xf8,0x40,0xfc,0x20,0x1e,},
421 {0x00,0x00,0x00,0x99,0x91,0x9b,0x8b,0x9b,},
422 {0x00,0x60,0x30,0x18,0x00,0x00,0x00,0x00,},
423 {0x00,0x60,0x90,0x10,0x38,0x10,0x12,0x0c,},
424 {0x00,0xcc,0x66,0x33,0x00,0x00,0x00,0x00,},
425 {0x00,0x54,0x00,0x00,0x00,0x00,0x00,0x00,},
426 {0x00,0x10,0x10,0x10,0x10,0x38,0x7c,0x10,},
427 {0x00,0x10,0x7c,0x10,0x10,0x10,0x7c,0x10,},
428 {0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,},
429 {0x00,0x8a,0x55,0x2a,0x10,0x48,0xa4,0x42,},
430 {0x00,0xfc,0x02,0x7c,0x80,0x7e,0x10,0x38,},
431 {0x00,0x10,0x20,0x40,0x20,0x10,0x00,0x00,},
432 {0x00,0x78,0x44,0x44,0x74,0x44,0x44,0x78,},
433 {0x00,0x00,0x00,0x8a,0x8a,0x9a,0x92,0x92,},
434 {0x00,0xfe,0x80,0x7c,0x02,0xfe,0x10,0x38,},
435 {0x00,0x00,0x00,0x8b,0x89,0x9b,0x91,0x93,},
436 {0x00,0x00,0x00,0x89,0x89,0x9b,0x92,0x92,},
437 {0x00,0x00,0x00,0x00,0x00,0x0c,0x18,0x30,},
438 {0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x18,},
439 {0x00,0x00,0x00,0x00,0x00,0x24,0x48,0x90,},
440 {0x00,0x00,0x00,0x00,0x00,0x48,0x24,0x12,},
441 {0x00,0x00,0x38,0x7c,0x7c,0x7c,0x38,0x00,},
442 {0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,},
443 {0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,},
444 {0x00,0x00,0x00,0x00,0x00,0x08,0x54,0x20,},
445 {0x00,0x00,0x00,0x00,0x00,0x4a,0x4e,0xea,},
446 {0x00,0xfc,0x02,0x7c,0x80,0x7e,0x10,0x38,},
447 {0x00,0x10,0x08,0x04,0x08,0x10,0x00,0x00,},
448 {0x00,0x6e,0x90,0x90,0x9c,0x92,0x92,0x6c,},
449 {0x00,0x00,0x00,0x9a,0x8a,0x9a,0x91,0x9b,},
450 {0x00,0xfe,0x80,0x78,0x04,0xfc,0x10,0x38,},
451 {0x00,0x38,0x10,0x38,0x44,0xee,0x00,0x44,},
452 {0x00,0x00,0x00,0x99,0x9a,0x9a,0x92,0x91,},
453 {0x00,0x20,0x20,0x20,0x10,0x10,0x00,0x10,},
454 {0x00,0x10,0x7c,0x80,0x40,0x20,0x1e,0x08,},
455 {0x00,0x7e,0x20,0x10,0x7c,0x20,0x24,0x18,},
456 {0x00,0x00,0x54,0x28,0x44,0x28,0x54,0x00,},
457 {0x38,0x10,0x7c,0x10,0xfe,0x10,0x28,0xc6,},
458 {0x00,0x10,0x10,0x10,0x00,0x10,0x10,0x10,},
459 {0x00,0xf0,0x0c,0x32,0x4c,0xb0,0x40,0x3c,},
460 {0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x6c,},
461 {0x00,0x38,0x44,0xba,0xa2,0xba,0x44,0x38,},
462 {0x00,0x00,0x00,0x00,0x38,0x38,0x08,0x30,},
463 {0x00,0x00,0x12,0x24,0x48,0x24,0x12,0x00,},
464 {0x00,0x00,0x04,0x04,0x7c,0x00,0x00,0x00,},
465 {0x00,0x7c,0xaa,0xaa,0xb2,0xaa,0x92,0x7c,},
466 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,},
467 {0x00,0x00,0x00,0x93,0x91,0x93,0x8a,0x9b,},
468 {0x00,0x00,0x00,0x00,0x30,0x48,0x48,0x30,},
469 {0x00,0x7c,0x00,0x10,0x10,0x7c,0x10,0x10,},
470 {0x00,0x00,0x00,0x3c,0x10,0x08,0x24,0x18,},
471 {0x00,0x00,0x00,0x30,0x08,0x18,0x08,0x38,},
472 {0x00,0x00,0x00,0x00,0x00,0x20,0x10,0x08,},
473 {0x00,0x80,0x80,0x84,0xf8,0x88,0x88,0x00,},
474 {0x00,0xe8,0x28,0x28,0x68,0xa8,0xa8,0x7c,},
475 {0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,},
476 {0x00,0x18,0x08,0x00,0x00,0x00,0x00,0x00,},
477 {0x00,0x00,0x00,0x38,0x10,0x10,0x30,0x10,},
478 {0x00,0x00,0x00,0x10,0x28,0x28,0x28,0x10,},
479 {0x00,0x00,0x48,0x24,0x12,0x24,0x48,0x00,},
480 {0x00,0x82,0x4e,0x2a,0x10,0x48,0x44,0x42,},
481 {0x00,0x86,0x44,0x22,0x16,0x48,0x44,0x42,},
482 {0x00,0x82,0x4e,0xea,0x50,0xc8,0x44,0xc2,},
483 {0x00,0x38,0x44,0x40,0x30,0x10,0x00,0x10,},
484 {0x00,0x82,0xfe,0xfe,0x82,0x7c,0x10,0x20,},
485 {0x00,0x82,0xfe,0xfe,0x82,0x7c,0x10,0x08,},
486 {0x00,0x82,0xfe,0xfe,0x82,0x7c,0x28,0x10,},
487 {0x00,0x82,0xfe,0xfe,0x82,0x7c,0x48,0x34,},
488 {0x00,0x82,0xfe,0xfe,0x82,0x7c,0x00,0x44,},
489 {0x00,0x82,0xfe,0xfe,0x82,0x7c,0x28,0x38,},
490 {0x00,0x8e,0xf8,0x48,0x4c,0x28,0x28,0x1e,},
491 {0x00,0x18,0x08,0x7e,0x80,0x40,0x20,0x1e,},
492 {0x00,0x7e,0x80,0xf8,0x80,0x7e,0x04,0x08,},
493 {0x00,0x7e,0x80,0xf8,0x80,0x7e,0x04,0x02,},
494 {0x00,0x7e,0x80,0xf8,0x80,0x7e,0x0a,0x04,},
495 {0x00,0x7e,0x80,0xf8,0x80,0x7e,0x00,0x12,},
496 {0x00,0xfe,0x10,0x10,0x10,0xfe,0x08,0x10,},
497 {0x00,0xfe,0x10,0x10,0x10,0xfe,0x10,0x08,},
498 {0x00,0xfe,0x10,0x10,0x10,0xfe,0x28,0x10,},
499 {0x00,0xfe,0x10,0x10,0x10,0xfe,0x00,0x44,},
500 {0x00,0x78,0x44,0x44,0x74,0x44,0x44,0x78,},
501 {0x00,0x86,0x8e,0x9a,0xb2,0xe2,0xc2,0xba,},
502 {0x00,0x7c,0x82,0x82,0x82,0x7c,0x10,0x20,},
503 {0x00,0x7c,0x82,0x82,0x82,0x7c,0x10,0x08,},
504 {0x00,0x7c,0x82,0x82,0x82,0x7c,0x28,0x10,},
505 {0x00,0x7c,0x82,0x82,0x82,0x7c,0x48,0x34,},
506 {0x00,0x7c,0x82,0x82,0x82,0x7c,0x00,0x44,},
507 {0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x00,},
508 {0x00,0xb0,0x48,0xa4,0x92,0x4a,0x24,0x1a,},
509 {0x00,0x7c,0x82,0x82,0x82,0x82,0x10,0x20,},
510 {0x00,0x7c,0x82,0x82,0x82,0x82,0x10,0x08,},
511 {0x00,0x7c,0x82,0x82,0x82,0x82,0x28,0x10,},
512 {0x00,0x7c,0x82,0x82,0x82,0x82,0x00,0x44,},
513 {0x00,0xe0,0x10,0x18,0x24,0x42,0x52,0x08,},
514 {0x00,0xfc,0x40,0x70,0x48,0x70,0x40,0xfc,},
515 {0x00,0xb8,0x84,0x84,0x88,0x90,0x48,0x30,},
516 {0x00,0x7e,0x82,0x7e,0x02,0x1c,0x08,0x10,},
517 {0x00,0x7e,0x82,0x7e,0x02,0x1c,0x08,0x04,},
518 {0x00,0x7e,0x82,0x7e,0x02,0x1c,0x14,0x08,},
519 {0x00,0x7e,0x82,0x7e,0x02,0x1c,0x28,0x14,},
520 {0x00,0x7e,0x82,0x7e,0x02,0x1c,0x00,0x24,},
521 {0x00,0x7e,0x82,0x7e,0x02,0x1c,0x24,0x18,},
522 {0x00,0x7c,0x90,0x7c,0x12,0x6c,0x00,0x00,},
523 {0x00,0x18,0x08,0x7e,0x80,0x40,0x20,0x1e,},
524 {0x00,0x7e,0x80,0xfe,0x82,0x7c,0x10,0x20,},
525 {0x00,0x7e,0x80,0xfe,0x82,0x7c,0x08,0x04,},
526 {0x00,0x7e,0x80,0xfe,0x82,0x7c,0x28,0x10,},
527 {0x00,0x7e,0x80,0xfe,0x82,0x7c,0x00,0x24,},
528 {0x00,0x38,0x38,0x10,0x10,0x00,0x10,0x20,},
529 {0x00,0x38,0x38,0x10,0x10,0x00,0x10,0x08,},
530 {0x00,0x38,0x38,0x10,0x10,0x00,0x28,0x10,},
531 {0x00,0x38,0x38,0x10,0x10,0x00,0x00,0x44,},
532 {0x00,0x7c,0x82,0x82,0x7c,0x28,0x4c,0x32,},
533 {0x00,0x82,0x82,0xc2,0xfe,0xbc,0x00,0x7c,},
534 {0x00,0x7c,0x82,0x82,0x82,0x7c,0x10,0x20,},
535 {0x00,0x7c,0x82,0x82,0x82,0x7c,0x10,0x08,},
536 {0x00,0x7c,0x82,0x82,0x82,0x7c,0x28,0x10,},
537 {0x00,0x7c,0x82,0x82,0x82,0x7c,0x48,0x34,},
538 {0x00,0x7c,0x82,0x82,0x82,0x7c,0x00,0x44,},
539 {0x00,0x00,0x10,0x00,0x7c,0x00,0x10,0x00,},
540 {0x00,0xf8,0xe4,0x9a,0x46,0x3e,0x00,0x00,},
541 {0x00,0x7c,0x82,0x82,0x82,0x82,0x10,0x20,},
542 {0x00,0x7c,0x82,0x82,0x82,0x82,0x10,0x08,},
543 {0x00,0x7c,0x82,0x82,0x82,0x82,0x28,0x10,},
544 {0x00,0x7c,0x82,0x82,0x82,0x82,0x00,0x44,},
545 {0x00,0xe0,0x10,0x18,0x24,0x42,0x10,0x08,},
546 {0x00,0xc0,0x5c,0x62,0x62,0x62,0x5c,0xc0,},
547 {0x00,0x00,0x00,0xdb,0x89,0xdb,0x52,0xdb,},
548 };
549
550 #endif // _JGLCONSOLEFONT_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 01/04/2003
25 // @description: Ejes coordenados
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #include <JLib/Graphics/JGLGrid.h>
29
30 const u8 JGLGrid::XY = 0; // Cuadrícula en plano XY
31 const u8 JGLGrid::YZ = 1; // Cuadrícula en plano YZ
32 const u8 JGLGrid::ZX = 2; // Cuadrícula en plano ZX
33
34 // Crea unos ejes coordenados
35 JGLGrid::JGLGrid(s32 _divs,
36 float fScale,
37 JGLColorf _color,
38 const u8 _orient)
39 {
40 scale = fScale;
41 color = _color;
42 divs = _divs;
43 orient = _orient;
44 nList = 0;
45
46 RebuildList();
47 }
48
49 // Crea la lista de OpenGL
50 void JGLGrid::RebuildList()
51 {
52 if (nList != 0)
53 glDeleteLists(nList, 1);
54
55 nList = glGenLists(1);
56
57 float delta;
58 delta = scale/divs;
59
60 glNewList(nList, GL_COMPILE);
61
62 // Pinta la cuadrícula
63 glBegin(GL_LINES);
64 glColor3f(color.r, color.g, color.b);
65
66 switch(orient)
67 {
68 case XY:
69 {
70 for (s32 i = 0; i <= 2 * divs; ++i)
71 {
72 glVertex3f(scale - (i * delta), scale, 0.0f);
73 glVertex3f(scale - (i * delta), -scale, 0.0f);
74 glVertex3f(scale, scale - (i * delta), 0.0f);
75 glVertex3f(-scale, scale - (i * delta), 0.0f);
76 }
77 break;
78 }
79 case YZ:
80 {
81 for (s32 i = 0; i <= 2 * divs; ++i)
82 {
83 glVertex3f(0.0f, scale - (i * delta), scale);
84 glVertex3f(0.0f, scale - (i * delta), -scale);
85 glVertex3f(0.0f, scale, scale - (i * delta));
86 glVertex3f(0.0f, -scale, scale - (i * delta));
87 }
88 break;
89 }
90 default:
91 case ZX:
92 {
93 for (s32 i = 0; i <= 2 * divs; ++i)
94 {
95 glVertex3f(scale - (i * delta), 0.0f, scale);
96 glVertex3f(scale - (i * delta), 0.0f, -scale);
97 glVertex3f(scale, 0.0f, scale - (i * delta));
98 glVertex3f(-scale, 0.0f, scale - (i * delta));
99 }
100 break;
101 }
102 }
103
104 glEnd();
105
106 glEndList();
107 }
108
109 // Pinta la cuadrícula
110 void JGLGrid::Draw()
111 {
112 glCallList(nList);
113 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 01/04/2003
25 // @description: Cuadrícula
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #ifndef _JGLGRID_INCLUDED
29 #define _JGLGRID_INCLUDED
30
31 #include <JLib/Util/JTypes.h>
32 #include <JLib/Graphics/JDrawable.h>
33 #include <JLib/Graphics/JGLColor.h>
34 #include <SDL.h>
35 #include <GL/gl.h>
36
37 class JGLGrid : public JDrawable
38 {
39 public:
40 GLuint nList; // Índice de lista de OpengGL
41 float scale; // Escala de cuadrante
42 s32 divs; // Divisiones por cuadrante
43 JGLColorf color; // Color
44 u8 orient; // Orientación
45
46 static const u8 XY; // Cuadrícula en plano XY
47 static const u8 YZ; // Cuadrícula en plano YZ
48 static const u8 ZX; // Cuadrícula en plano ZX
49
50 // Crea unos ejes coordenados
51 JGLGrid(s32 _divs = 10,
52 float fScale = 10.0f,
53 JGLColorf _color = JGLColorf(0.0f, 1.0f, 0.0f, 1.0f),
54 const u8 _orient = ZX);
55
56 // Crea la lista de OpenGL
57 void RebuildList();
58
59 // Pinta la cuadrícula
60 void Draw();
61 };
62
63 #endif // _JGLGRID_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clase para la presentación de imágenes OpenGL.
23 * @file JGLImage.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 19/05/2004
26 * @version 0.0.1 - 19/05/2004 - Primera versión.
27 */
28
29 #include <JLib/Graphics/JGLImage.h>
30
31 bool JGLImage::Init(JImage *image, bool withMipmaps)
32 {
33 if (image == 0)
34 {
35 return false;
36 }
37
38 s32 w = JGLTexture::Next2Power(image->Width());
39 s32 h = JGLTexture::Next2Power(image->Height());
40 JImage *img;
41
42 // Si la anchura o la altura no son potencia de dos, tenemos que
43 // cambiar el tamaño de la imagen
44 if (w != image->Width() || h != image->Height())
45 {
46 img = new JImage(w, h, image->BitsPP());
47 if (!img || !img->Paste(image, 0, 0, image->Width(), image->Height(), 0, 0))
48 {
49 JDELETE(img);
50
51 return false;
52 }
53 }
54 else
55 {
56 img = image;
57 }
58
59 bool ok = texture.Create(img, withMipmaps);
60
61 if (img != image)
62 {
63 delete img;
64 }
65
66 if (!ok)
67 {
68 return false;
69 }
70
71 // Crea la lista de visualización
72 listIndex = glGenLists(1);
73
74 if (listIndex == 0)
75 {
76 texture.Destroy();
77
78 return false;
79 }
80
81 float tw, th, halfW, halfH;
82 tw = float(image->Width())/float(w);
83 th = float(image->Height())/float(h);
84 halfW = float(image->Width())/2.0f;
85 halfH = float(image->Height())/2.0f;
86
87 //fprintf(stderr, "Imagen tw%f th%f iw%d ih%d w%d h%d\n", tw, th, image->Width(), image->Height(), w, h);
88
89 glNewList(listIndex, GL_COMPILE);
90
91 texture.GLBind();
92
93 // 2-3-5-7
94 // |\|\|\| CCW
95 // 0-1-4-6
96 glBegin(GL_TRIANGLE_STRIP);
97
98 // Bottom left
99 //glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
100 texture.GLCoord2f(0.0f, th);
101 glVertex3f(-halfW, -halfH, 0.0f);
102
103 // Bottom right
104 texture.GLCoord2f(tw, th);
105 glVertex3f(halfW, -halfH, 0.0f);
106
107 // Top left
108 texture.GLCoord2f(0.0f, 0.0f);
109 glVertex3f(-halfW, halfH, 0.0f);
110
111 // Top right
112 texture.GLCoord2f(tw, 0.0f);
113 glVertex3f(halfW, halfH, 0.0f);
114
115 glEnd();
116
117 glEndList();
118
119 return ok;
120 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clase para la presentación de imágenes OpenGL.
23 * @file JGLImage.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 19/05/2004
26 * @version 0.0.1 - 19/05/2004 - Primera versión.
27 */
28
29 #ifndef _JGLIMAGE_INCLUDED
30 #define _JGLIMAGE_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Graphics/JDrawable.h>
34 #include <JLib/Graphics/JImage.h>
35 #include <JLib/Graphics/JGLTexture.h>
36
37 /** Permite mostrar imágenes en OpenGL de forma simple.
38 */
39 class JGLImage : public JDrawable
40 {
41 JGLTexture texture; /**< Textura OpenGL asociada. */
42 u32 listIndex; /**< Índice de lista de visualización. */
43
44 public:
45 /** Crea la imagen openGL vacía. Se debe llamar a Init antes de comenzar a usarla.
46 */
47 JGLImage() : listIndex(0)
48 {}
49
50 /** Carga la imagen dada en una textura OpenGL y prepara la lista de visualización
51 * para mostrarla en pantalla.
52 * @param image Imagen a cargar.
53 * @param withMipmaps Determina si la debe crear con niveles de mipmaps o no.
54 * @return <b>true</b> si se cargó correctamente, <b>false</b> si no.
55 * @todo implementar malla.
56 */
57 bool Init(JImage *image, bool withMipmaps = false);
58
59 /** Devuelve la textura OpenGL.
60 * @return Textura asociada.
61 */
62 const JGLTexture & Texture() {return texture;}
63
64 /** Dibuja la imagen.
65 */
66 void Draw() {glCallList(listIndex);}
67
68 /** Devuelve la anchura de la imagen.
69 * @return Anchura de la imagen.
70 */
71 s32 Width() {return texture.Width();}
72
73 /** Devuelve la altura de la imagen.
74 * @return Altura de la imagen.
75 */
76 s32 Height() {return texture.Height();}
77
78 /** Destruye el objeto.
79 */
80 virtual ~JGLImage()
81 {}
82 };
83
84 #endif // _JGLIMAGE_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 01/04/2003
25 // @description: Funciones para texturas.
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #include <JLib/Graphics/JGLLight.h>
29
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 01/11/2003
25 // @description: Luz OpenGL.
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #ifndef _JGLLIGHT_INCLUDED
29 #define _JGLLIGHT_INCLUDED
30
31 #include <JLib/Util/JTypes.h>
32 #include <JLib/Util/JObject.h>
33 #include <JLib/Math/JVector.h>
34 #include <JLib/Graphics/JGLColor.h>
35 #include <SDL.h>
36 #include <GL/gl.h>
37
38 // Clase para gestión de texturas
39 class JGLLight : public JObject
40 {
41 s32 number; // Número de luz OpenGL
42 JVector pos; // Posición
43 JVector dir; // Dirección
44 float cutOff; // Ángulo de apertura
45 JGLColorf ambient; // Color ambiente
46 JGLColorf diffuse; // Color difuso
47 JGLColorf specular; // Color especular
48
49 public:
50 // Constructor
51 JGLLight(s32 index = 0) : number(index){}
52
53 // Destructor
54 ~JGLLight() {}
55
56 // Devuelve el número de orden OpenGL (GL_LIGHT0, etc.)
57 s32 Number() {return number;}
58
59 // Establece el número de orden (GL_LIGHT0, etc.)
60 void Number(s32 n) {number = n;}
61
62 // Devuelve la posición
63 JVector & Pos() {return pos;}
64
65 // Establece la posición
66 void Pos(float x, float y, float z) {pos.x = x; pos.y = y; pos.z = z; glLightfv(number, GL_POSITION, (float *)&pos);}
67
68 // Establece la posición
69 void Pos(JVector &newPos) {pos = newPos; glLightfv(number, GL_POSITION, (float *)&pos);}
70
71 // Devuelve la dirección
72 const JVector & GetDir() {return dir;}
73
74 // Establece la dirección
75 void Dir(float x, float y, float z) {dir.x = x; dir.y = y; dir.z = z; glLightfv(number, GL_POSITION, (float *)&dir);}
76
77 // Establece la dirección
78 void Dir(JVector &newDir) {dir = newDir; glLightfv(number, GL_SPOT_DIRECTION, (float *)&dir);}
79
80 // Devuelve el ángulo de apertura
81 float CutOff() {return cutOff;}
82
83 // Establece el ángulo de apertura
84 void CutOff(float _cutOff) {cutOff = _cutOff; glLightfv(number, GL_SPOT_CUTOFF, &cutOff);}
85
86 // Devuelve el color ambiente
87 JGLColorf & Ambient() {return ambient;}
88
89 // Establece el color ambiente
90 void Ambient(float r, float g, float b, float a)
91 {ambient.r = r; ambient.g = g; ambient.b = b; ambient.a = a; glLightfv(number, GL_AMBIENT, (float *)&ambient);}
92
93 // Establece el color ambiente
94 void Ambient(JGLColorf &color) {ambient = color; glLightfv(number, GL_AMBIENT, (float *)&ambient);}
95
96 // Devuelve el color difuso
97 JGLColorf & Diffuse() {return diffuse;}
98
99 // Establece el color difuso
100 void Diffuse(float r, float g, float b, float a)
101 {diffuse.r = r; diffuse.g = g; diffuse.b = b; diffuse.a = a; glLightfv(number, GL_DIFFUSE, (float *)&diffuse);}
102
103 // Establece el color difuso
104 void Diffuse(JGLColorf &color) {diffuse = color; glLightfv(number, GL_DIFFUSE, (float *)&diffuse);}
105
106 // Devuelve el color especular
107 JGLColorf & Specular() {return specular;}
108
109 // Establece el color especular
110 void Specular(float r, float g, float b, float a)
111 {specular.r = r; specular.g = g; specular.b = b; specular.a = a; glLightfv(number, GL_SPECULAR, (float *)&specular);}
112
113 // Establece el color especular
114 void Specular(JGLColorf &color) {specular = color; glLightfv(number, GL_SPECULAR, (float *)&specular);}
115 };
116
117 #endif // _JGLLIGHT_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clases de geometría 3D para OpenGL.
23 * @file JGLMesh.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 10/05/2004
26 * @version 0.0.1 - 10/05/2004 - Primera versión.
27 */
28
29 #include <JLib/Graphics/JGLMesh.h>
30
31 /** Dibuja la geometría.
32 */
33 void JGLMesh::Draw()
34 {
35 // Pinta el objeto cargado
36 for (int i = 0; i < numObjects; ++i)
37 {
38 // Por cada cara (flat)
39 for (int j = 0; j < objects[i].numFaces; ++j)
40 {
41 if (objects[i].faces[j].material->Texture())
42 {
43 glDisable(GL_COLOR_MATERIAL);
44 glEnable(GL_TEXTURE_2D);
45 objects[i].faces[j].material->Texture()->GLBind();
46
47 glBegin(GL_TRIANGLES);
48 glNormal3fv((GLfloat*)&objects[i].vertexNormals[objects[i].faces[j].v1]);
49 glTexCoord2f(objects[i].tVertices[objects[i].tFaces[j].v1].u,
50 objects[i].tVertices[objects[i].tFaces[j].v1].v);
51 glVertex3fv((GLfloat*)&objects[i].vertices[objects[i].faces[j].v1]);
52
53 glNormal3fv((GLfloat*)&objects[i].vertexNormals[objects[i].faces[j].v2]);
54 glTexCoord2f(objects[i].tVertices[objects[i].tFaces[j].v2].u,
55 objects[i].tVertices[objects[i].tFaces[j].v2].v);
56 glVertex3fv((GLfloat*)&objects[i].vertices[objects[i].faces[j].v2]);
57
58 glNormal3fv((GLfloat*)&objects[i].vertexNormals[objects[i].faces[j].v3]);
59 glTexCoord2f(objects[i].tVertices[objects[i].tFaces[j].v3].u,
60 objects[i].tVertices[objects[i].tFaces[j].v3].v);
61 glVertex3fv((GLfloat*)&objects[i].vertices[objects[i].faces[j].v3]);
62 glEnd();
63 }
64 else
65 {
66 glDisable(GL_TEXTURE_2D);
67 glEnable(GL_COLOR_MATERIAL);
68 glColor3fv((GLfloat*)&objects[i].faces[j].material->diffuse);
69
70 glBegin(GL_TRIANGLES);
71 glNormal3fv((GLfloat*)&objects[i].vertexNormals[objects[i].faces[j].v1]);
72 glVertex3fv((GLfloat*)&objects[i].vertices[objects[i].faces[j].v1]);
73
74 glNormal3fv((GLfloat*)&objects[i].vertexNormals[objects[i].faces[j].v2]);
75 glVertex3fv((GLfloat*)&objects[i].vertices[objects[i].faces[j].v2]);
76
77 glNormal3fv((GLfloat*)&objects[i].vertexNormals[objects[i].faces[j].v3]);
78 glVertex3fv((GLfloat*)&objects[i].vertices[objects[i].faces[j].v3]);
79 glEnd();
80 }
81 }
82 }
83 }
84
85 void JMaterial::Destroy()
86 {
87 JDELETE(texture);
88 }
89
90 void JGLMeshObject::Destroy()
91 {
92 JDELETE_ARRAY(vertices);
93 JDELETE_ARRAY(tVertices);
94 JDELETE_ARRAY(vertexNormals);
95 JDELETE_ARRAY(faces);
96 JDELETE_ARRAY(tFaces);
97 }
98
99 void JGLMesh::Destroy()
100 {
101 JDELETE_ARRAY(materials);
102 JDELETE_ARRAY(objects);
103 }
104
105 bool JGLMesh::LoadASE(const JString &filename)
106 {
107 // Destruye posibles geometrías anteriores
108 Destroy();
109
110 if (!f.Load(filename))
111 return false;
112
113 // La cabecera debe coincidir, no exigimos tanto a la versión,
114 // al menos lo intentamos
115 if (!f.FindNext(JASETAG_FILE_HEADER) || !f.SkipNextWord())
116 return false;
117
118 /*
119 // Versión del fichero
120 f.ReadInteger(&fileVersion);
121
122 // Primer frame
123 if (!f.FindNext(JASETAG_SCENE_FIRSTFRAME) || !f.SkipNextWord())
124 firstFrame = 0;
125 else
126 f.ReadInteger(&firstFrame);
127
128 // Último frame
129 if (!f.FindNext(JASETAG_SCENE_LASTFRAME) || !f.SkipNextWord())
130 lastFrame = 0;
131 else
132 f.ReadInteger(&lastFrame);
133 */
134
135 if (LoadASEMaterials())
136 if (LoadASEObjects())
137 return true;
138
139 return false;
140 }
141
142 // Carga los materiales del fichero ASE.
143 // Devuelve true si todo fue bien, false en caso contrario.
144 bool JGLMesh::LoadASEMaterials()
145 {
146 f.StartOfDocument();
147
148 if (!f.FindNext(JASETAG_MATERIAL_COUNT))
149 return false;
150
151 f.SkipNextWord();
152 f.ReadInteger(&numMaterials);
153
154 // Contamos como materiales los submateriales que haya
155 f.StartOfDocument();
156 s32 c = 0;
157 while (f.FindNext(JASETAG_SUBMATERIAL_COUNT))
158 {
159 f.SkipNextWord();
160 f.ReadInteger(&c);
161 numMaterials += c;
162 }
163
164 f.StartOfDocument();
165 materials = new JMaterial[numMaterials];
166 memset(materials, 0, sizeof(JMaterial) * numMaterials);
167
168 JMaterial *mats = materials;
169 s32 i = 0;
170 while (i < numMaterials)
171 {
172 // En el nivel superior no hay submateriales
173 mats[i].parentId = -1;
174 mats[i].isSubMaterial = false;
175
176 f.FindNext(JASETAG_MATERIAL_LIST);
177 f.SkipNextWord();
178 f.FindNext(JASETAG_MATERIAL_COUNT);
179 f.SkipNextWord();
180 f.FindNext(JASETAG_MATERIAL);
181 f.SkipNextWord();
182 f.ReadInteger(&mats[i].id);
183
184 // Tipo de material
185 f.FindNext(JASETAG_MATERIAL_CLASS);
186 f.SkipNextWord();
187 f.ReadWord(mats[i].mtlClass);
188
189 // Color ambiente
190 f.FindNext(JASETAG_MATERIAL_AMBIENT); f.SkipNextWord();
191 f.ReadFloat(&mats[i].ambient.r); f.ReadFloat(&mats[i].ambient.g); f.ReadFloat(&mats[i].ambient.b);
192
193 // Color difuso
194 f.FindNext(JASETAG_MATERIAL_DIFFUSE); f.SkipNextWord();
195 f.ReadFloat(&mats[i].diffuse.r); f.ReadFloat(&mats[i].diffuse.g); f.ReadFloat(&mats[i].diffuse.b);
196
197 // Color especular
198 f.FindNext(JASETAG_MATERIAL_SPECULAR); f.SkipNextWord();
199 f.ReadFloat(&mats[i].specular.r); f.ReadFloat(&mats[i].specular.g); f.ReadFloat(&mats[i].specular.b);
200
201 // Brillo
202 f.FindNext(JASETAG_MATERIAL_SHINE); f.SkipNextWord();
203 f.ReadFloat(&mats[i].shine);
204
205 // Fuerza de brillo
206 f.FindNext(JASETAG_MATERIAL_SHINESTRENGTH); f.SkipNextWord();
207 f.ReadFloat(&mats[i].shineStrenght);
208
209 // Transparencia
210 f.FindNext(JASETAG_MATERIAL_TRANSPARENCY); f.SkipNextWord();
211 f.ReadFloat(&mats[i].transparency);
212
213 s8 str[32]; // Cadena auxiliar
214
215 if (0 == strcmp(mats[i].mtlClass, JASEVAL_MULTI_SUBOBJECT))
216 {
217 // Material multi/subobjeto: procesamos los submateriales
218 // No tiene el parámetro selfIllum
219 mats[i].isMulti = true;
220
221 f.FindNext(JASETAG_SUBMATERIAL_COUNT);
222 f.SkipNextWord();
223 f.ReadInteger(&mats[i].numSubMaterials);
224
225 for (s32 j = i+1; j < i + 1 + mats[i].numSubMaterials; ++j)
226 {
227 mats[j].parentId = mats[i].id;
228 f.FindNext(JASETAG_SUBMATERIAL); f.SkipNextWord();
229 f.ReadInteger(&mats[j].id);
230
231 // Sólo está permitido un nivel de jerarquía, así que no comprobamos
232 // si es Multi/Sub-object
233 f.FindNext(JASETAG_MATERIAL_CLASS);
234 f.SkipNextWord();
235 f.ReadWord(mats[j].mtlClass);
236 mats[j].isSubMaterial = true;
237
238 // Color ambiente
239 f.FindNext(JASETAG_MATERIAL_AMBIENT); f.SkipNextWord();
240 f.ReadFloat(&mats[j].ambient.r); f.ReadFloat(&mats[j].ambient.g); f.ReadFloat(&mats[j].ambient.b);
241
242 // Color difuso
243 f.FindNext(JASETAG_MATERIAL_DIFFUSE); f.SkipNextWord();
244 f.ReadFloat(&mats[j].diffuse.r); f.ReadFloat(&mats[j].diffuse.g); f.ReadFloat(&mats[j].diffuse.b);
245
246 // Color especular
247 f.FindNext(JASETAG_MATERIAL_SPECULAR); f.SkipNextWord();
248 f.ReadFloat(&mats[j].specular.r); f.ReadFloat(&mats[j].specular.g); f.ReadFloat(&mats[j].specular.b);
249
250 // Brillo
251 f.FindNext(JASETAG_MATERIAL_SHINE); f.SkipNextWord();
252 f.ReadFloat(&mats[j].shine);
253
254 // Fuerza de brillo
255 f.FindNext(JASETAG_MATERIAL_SHINESTRENGTH); f.SkipNextWord();
256 f.ReadFloat(&mats[j].shineStrenght);
257
258 // Transparencia
259 f.FindNext(JASETAG_MATERIAL_TRANSPARENCY); f.SkipNextWord();
260 f.ReadFloat(&mats[j].transparency);
261
262 // Iluminación propia
263 f.FindNext(JASETAG_MATERIAL_SELFILLUM); f.SkipNextWord();
264 f.ReadFloat(&mats[j].selfIllum);
265
266 // Si tiene una textura asociada aparecerá en la línea siguiente a
267 // MATERIAL_XP_TYPE
268 f.FindNext(JASETAG_MATERIAL_XP_TYPE);
269 f.NextLine();
270 f.ReadWord(str);
271
272 if (strcmp(str, JASETAG_MATERIAL_MAP_DIFFUSE) == 0)
273 {
274 char texFile[256];
275 mats[j].texture = new JGLTexture;
276
277 f.FindNext(JASETAG_MATERIAL_BITMAP); f.SkipNextWord();
278 f.ReadWord(texFile);
279
280 // Quita las comillas
281 u32 len = (u32)strlen(texFile);
282 memmove(&texFile[0], &texFile[1], len - 1);
283 texFile[len - 2] = 0;
284
285 /**< @todo Comprobar rendimiento con mipmaps y sin ellos. */
286 // Carga la textura con mipmaps
287 mats[j].texture->Load(texFile, true);
288 }
289 }
290 }
291 else
292 {
293 // Material standard u otro
294 mats[i].isMulti = false;
295 mats[i].numSubMaterials = 0;
296
297 // Iluminación propia
298 f.FindNext(JASETAG_MATERIAL_SELFILLUM); f.SkipNextWord();
299 f.ReadFloat(&mats[i].selfIllum);
300
301 // Si tiene una textura asociada aparecerá en la línea siguiente a
302 // MATERIAL_XP_TYPE
303 f.FindNext(JASETAG_MATERIAL_XP_TYPE);
304 f.NextLine();
305 f.ReadWord(str);
306
307 if (strcmp(str, JASETAG_MATERIAL_MAP_DIFFUSE) == 0)
308 {
309 char texFile[256];
310
311 mats[i].texture = new JGLTexture;
312
313 f.FindNext(JASETAG_MATERIAL_BITMAP); f.SkipNextWord();
314 f.ReadWord(texFile);
315 u32 len = (u32)strlen(texFile);
316 memmove(&texFile[0], &texFile[1], len - 1);
317 texFile[len - 2] = 0;
318
319 // Quita las comillas
320 u32 leng = (u32)strlen(texFile);
321 memmove(&texFile[0], &texFile[1], leng - 1);
322 texFile[leng - 2] = 0;
323
324 /**< @todo Comprobar rendimiento con mipmaps y sin ellos. */
325 // Carga la textura con mipmaps
326 mats[i].texture->Load(texFile, true);
327 }
328 }
329
330 // Acumulamos los submateriales procesados y/o el actual
331 i += mats[i].numSubMaterials + 1;
332 }
333
334 return true;
335 }
336
337 // Carga los objetos (geometría) del fichero ASE.
338 // Devuelve true si todo fue bien, false en otro caso.
339 bool JGLMesh::LoadASEObjects()
340 {
341 f.StartOfDocument();
342
343 // Cuenta los objetos
344 numObjects = 0;
345 while (f.FindNext(JASETAG_GEOMOBJECT))
346 {
347 f.SkipNextWord();
348 ++numObjects;
349 }
350
351 // Crea el array de objetos
352 objects = new JGLMeshObject[numObjects];
353 JGLMeshObject *objs = objects;
354
355 f.StartOfDocument();
356 char str[256];
357
358 for (s32 i = 0; i < numObjects; ++i)
359 {
360 // Nombre
361 f.FindNext(JASETAG_NODE_NAME); f.SkipNextWord();
362 f.ReadWord(str);
363
364 // Quita las comillas
365 u32 len = (u32)strlen(str);
366 memmove(&str[0], &str[1], len - 1);
367 str[len - 2] = 0;
368 objs[i].name = str;
369
370 // Procesa la geometría...
371 f.FindNext(JASETAG_MESH); f.SkipNextWord();
372 s8 *oldPos = f.GetPos();
373
374 // Número de vértices: crea el array de vértices y de normales
375 if (i == 64)
376 i = i;
377 f.FindNext(JASETAG_MESH_NUMVERTEX); f.SkipNextWord();
378 f.ReadInteger(&objs[i].numVertices);
379 objs[i].vertices = new JVertex[objs[i].numVertices];
380
381 JVertex *verts = objs[i].vertices;
382
383 // Número de caras: crea el array de caras
384 f.FindNext(JASETAG_MESH_NUMFACES); f.SkipNextWord();
385 f.ReadInteger(&objs[i].numFaces);
386 objs[i].faces = new JFace[objs[i].numFaces];
387
388 JFace *faces = objs[i].faces;
389
390 // Lista de vértices
391 f.FindNext(JASETAG_MESH_VERTEX_LIST); f.SkipNextWord();
392 for (s32 j = 0; j < objs[i].numVertices; ++j)
393 {
394 f.FindNext(JASETAG_MESH_VERTEX); f.SkipNextWord(); f.SkipNextWord(); // Saltamos el índice de vértice
395
396 // OJO! MAX da la vuelta... hay que cambiar Y por -Z
397 f.ReadFloat(&verts[j].x); f.ReadFloat(&verts[j].z); f.ReadFloat(&verts[j].y);
398 verts[j].z = -verts[j].z;
399 }
400
401 // Buscamos primero la referencia del material...
402 s32 mtlRef;
403
404 f.FindNext(JASETAG_MATERIAL_REF);f.SkipNextWord();
405 f.ReadInteger(&mtlRef);
406
407 // ...Buscamos el material correspondiente a esa referencia...
408 s32 mtlIndex = 0;
409 while (mtlIndex < numMaterials && materials[mtlIndex].id != mtlRef)
410 {
411 // Avanzamos el nº de submateriales que indique este material y vamos al siguiente
412 if (materials[mtlIndex].isMulti)
413 mtlIndex += materials[mtlIndex].numSubMaterials;
414 else
415 ++mtlIndex;
416 }
417
418 // Si no lo encuentra, salimos
419 if (materials[mtlIndex].id != mtlRef)
420 return false;
421
422 // Si lo encontró, volvemos al punto de inicio
423 f.SetPos(oldPos);
424
425 // Asignamos el material a la cara (queda pendiente ponerle textura) ...
426 s32 vInd;
427
428 if (materials[mtlIndex].isMulti)
429 {
430 // Lista de caras
431 s32 m;
432
433 f.FindNext(JASETAG_MESH_FACE_LIST); f.SkipNextWord();
434 for (s32 k = 0; k < objs[i].numFaces; ++k)
435 {
436 // A:
437 f.FindNext(JASETAG_MESH_A); f.SkipNextWord();
438 f.ReadInteger(&faces[k].v1);
439 // B:
440 f.FindNext(JASETAG_MESH_B); f.SkipNextWord();
441 f.ReadInteger(&faces[k].v2);
442 // C:
443 f.FindNext(JASETAG_MESH_C); f.SkipNextWord();
444 f.ReadInteger(&faces[k].v3);
445
446 // MTLID
447 f.FindNext(JASETAG_MESH_MTLID); f.SkipNextWord();
448 f.ReadInteger(&m);
449
450 // Si es Multi/subobjeto debemos atender al MTLID de las caras...
451 // v. nota al comienzo del .h
452 faces[k].material = &materials[mtlIndex + 1 + (m%materials[mtlIndex].numSubMaterials)];
453 }
454 }
455 else
456 {
457 // MATERIAL_REF
458
459 // Lista de caras
460 f.FindNext(JASETAG_MESH_FACE_LIST); f.SkipNextWord();
461 for (s32 k = 0; k < objs[i].numFaces; ++k)
462 {
463 f.FindNext(JASETAG_MESH_FACE);
464 // A:
465 f.FindNext(JASETAG_MESH_A); f.SkipNextWord();
466 f.ReadInteger(&faces[k].v1);
467 // B:
468 f.FindNext(JASETAG_MESH_B); f.SkipNextWord();
469 f.ReadInteger(&faces[k].v2);
470 // C:
471 f.FindNext(JASETAG_MESH_C); f.SkipNextWord();
472 f.ReadInteger(&faces[k].v3);
473
474 // Al no tener un material Multi asignado, todas las caras tienen el
475 // material indicado en MATERIAL_REF
476 faces[k].material = &materials[mtlIndex];
477 }
478 }
479
480 // Texturas.
481
482 // El número de vértices de textura puede ser (y, en general, será)
483 // diferente al número de vértices totales
484 f.FindNext(JASETAG_MESH_NUMTVERTEX); f.SkipNextWord();
485 f.ReadInteger(&objs[i].numTVertices);
486
487 // Creamos el array de vértices de textura y lo rellenamos
488 objs[i].tVertices = new JTextureVertex[objs[i].numTVertices];
489
490 if (f.FindNext(JASETAG_MESH_TVERTLIST))
491 {
492 f.SkipNextWord();
493 for (s32 b = 0; b < objs[i].numTVertices; ++b)
494 {
495 f.FindNext(JASETAG_MESH_TVERT); f.SkipNextWord(); f.SkipNextWord();
496
497 // OJO: Comprobar que x e y corresponden a las mismas U, V en OpenGL
498 f.ReadFloat(&objs[i].tVertices[b].u);
499 f.ReadFloat(&objs[i].tVertices[b].v);
500 }
501 }
502
503 // El número de caras de textura puede es
504 // igual al número de caras totales
505 if (f.FindNext(JASETAG_MESH_NUMTVFACES))
506 {
507 f.SkipNextWord();
508 f.ReadInteger(&objs[i].numTFaces);
509
510 // Creamos el array de caras de textura y lo rellenamos
511 if (objs[i].numTFaces > 0)
512 {
513 objs[i].tFaces = new JTextureFace[objs[i].numTFaces];
514
515 f.FindNext(JASETAG_MESH_TFACELIST); f.SkipNextWord();
516 for (s32 c = 0; c < objs[i].numTFaces; ++c)
517 {
518 f.FindNext(JASETAG_MESH_TFACE); f.SkipNextWord(); f.SkipNextWord();
519 f.ReadInteger(&objs[i].tFaces[c].v1);
520 f.ReadInteger(&objs[i].tFaces[c].v2);
521 f.ReadInteger(&objs[i].tFaces[c].v3);
522 }
523 }
524 }
525
526 // Calcula las normales a las caras
527 objs[i].vertexNormals = new JVertex[objs[i].numVertices];
528 memset(objs[i].vertexNormals, 0, sizeof(JVertex) * objs[i].numVertices);
529
530 JVertex *vNorm = objs[i].vertexNormals;
531 JVector v1, v2, v3, vt1, vt2, vn;
532
533 for (s32 d = 0; d < objs[i].numFaces; ++d)
534 {
535 if (d == 35)
536 d = d;
537
538 v1 = JVector(objs[i].vertices[faces[d].v1].x,
539 objs[i].vertices[faces[d].v1].y,
540 objs[i].vertices[faces[d].v1].z);
541 v2 = JVector(objs[i].vertices[faces[d].v2].x,
542 objs[i].vertices[faces[d].v2].y,
543 objs[i].vertices[faces[d].v2].z);
544 v3 = JVector(objs[i].vertices[faces[d].v3].x,
545 objs[i].vertices[faces[d].v3].y,
546 objs[i].vertices[faces[d].v3].z);
547
548 vt1 = (v3 - v1);
549 vt2 = (v3 - v2);
550 vn = vt1.Cross(vt2);
551 vn.Normalize();
552 faces[d].normal.x = vn.x;
553 faces[d].normal.y = vn.y;
554 faces[d].normal.z = vn.z;
555 }
556
557 // Asigna las normales a cada vértice
558 s32 *shared = new s32[objs[i].numVertices];
559 memset(shared, 0, sizeof(s32) * objs[i].numVertices);
560
561 for (s32 k = 0; k < objs[i].numFaces; ++k)
562 {
563 if (i == 219 && k == 68)
564 i = i;
565
566 // Si algún día quieres quedarte con las normales del ASE...
567 /*
568 f.FindNext(JASETAG_MESH_FACENORMAL); f.SkipNextWord(); f.SkipNextWord();
569 f.ReadFloat(&faces[k].normal.x);
570 f.ReadFloat(&faces[k].normal.z); // Por el cambio de MAX y -> -z
571 f.ReadFloat(&faces[k].normal.y);
572 faces[k].normal.z = -faces[k].normal.z;
573 */
574
575 // Suma las normales dadas a cada vértice de la cara. Resultado:
576 // al final todas las normales estarán promediadas en cada vértice.
577 f.FindNext(JASETAG_MESH_VERTEXNORMAL); f.SkipNextWord();
578 f.ReadInteger(&vInd);
579 vNorm[vInd].x += faces[k].normal.x;
580 vNorm[vInd].y += faces[k].normal.y;
581 vNorm[vInd].z += faces[k].normal.z;
582 ++shared[vInd];
583
584 f.FindNext(JASETAG_MESH_VERTEXNORMAL); f.SkipNextWord();
585 f.ReadInteger(&vInd);
586 vNorm[vInd].x += faces[k].normal.x;
587 vNorm[vInd].y += faces[k].normal.y;
588 vNorm[vInd].z += faces[k].normal.z;
589 ++shared[vInd];
590
591 f.FindNext(JASETAG_MESH_VERTEXNORMAL); f.SkipNextWord();
592 f.ReadInteger(&vInd);
593 vNorm[vInd].x += faces[k].normal.x;
594 vNorm[vInd].y += faces[k].normal.y;
595 vNorm[vInd].z += faces[k].normal.z;
596 ++shared[vInd];
597 }
598
599 // Promedia y normaliza las normales sumadas para cada vértice
600 for (s32 h = 0; h < objs[i].numVertices; ++h)
601 {
602 vn = JVector(objs[i].vertexNormals[h].x,
603 objs[i].vertexNormals[h].y,
604 objs[i].vertexNormals[h].z);
605 vn /= JScalar(shared[h]);
606 vn.Normalize();
607 objs[i].vertexNormals[h].x = vn.x;
608 objs[i].vertexNormals[h].y = vn.y;
609 objs[i].vertexNormals[h].z = vn.z;
610 }
611
612 delete[] shared;
613 }
614
615 return true;
616 }
617
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Definiciones para geometría 3D para OpenGL.
23 * @file JGLMesh.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 10/05/2004
26 * @version 0.0.1 - 10/05/2004 - Primera versión.
27 * @notes: Ficheros ASE - Curiosidad de MAX 5, pongo el ejemplo:
28 * Supongamos una escena con tres bolas que comparten el mismo material multi/subobjeto
29 * compuesto de tres submateriales de id 1, 2 y 3, respectivamente. Si las bolas
30 * tienen id's 1, 2 y 3 respectivamente se asignarán de esa forma los submateriales
31 * a cada una de ellas. Sin embargo si alguna de ellas tiene un valor diferente (mayor),
32 * el material que aplica MAX es el resto de dividir el id de la bola menos uno entre el número
33 * de submateriales del material y todo eso más uno.
34 * Así si las bolas tienen id's 1, 22 y 7, respectivamente,
35 * - a la bola con MTLID 1 se le asigna el submaterial: ((1-1)%3) + 1 = (0%3) + 1 = 0 + 1 = 1
36 * - a la bola con MTLID 23 se le asigna el submaterial: ((23-1)%3) + 1 = (21%3) + 1 = 0 + 1 = 1
37 * - a la bola con MTLID 7 se le asigna el submaterial: ((8-1)%3) + 1 = (7%3) + 1 = 1 + 1 = 2
38 *
39 * Notad que en el fichero ASE el MTLID es uno menos que en la escena ya.
40 */
41
42 #ifndef _JGLMESH_INCLUDED
43 #define _JGLMESH_INCLUDED
44
45 #include <JLib/Util/JTypes.h>
46 #include <JLib/Util/JString.h>
47 #include <JLib/Util/JTextFile.h>
48 #include <JLib/Math/JVector.h>
49 #include <JLib/Graphics/JDrawable.h>
50 #include <JLib/Graphics/JASEFormat.h>
51 #include <JLib/Graphics/JGLTexture.h>
52
53 /** Color RGB. Todas las componentes van de 0.0f a 1.0f.
54 */
55 struct JColor
56 {
57 float r; /**< Componente roja. */
58 float g; /**< Componente verde. */
59 float b; /**< Componente azul. */
60 float a; /**< Componente alfa. */
61 };
62
63 class JMaterial
64 {
65 public:
66 /** Crea un material vacío.
67 */
68 JMaterial(): texture(0)
69 {}
70
71 JGLTexture *texture; /**< Textura asociada. */
72 s32 parentId; /**< Id del padre. */
73 s32 id; /**< Id. */
74 bool isSubMaterial; /**< Indica si es submaterial. */
75 bool isMulti; /**< Indica si es Multi/sub-objeto. */
76 s32 numSubMaterials; /**< Númeor de submateriales. */
77 s8 mtlClass[32]; /**< Tipo de material. */
78 JColor ambient; /**< Color ambiente. */
79 JColor diffuse; /**< Color difuso. */
80 JColor specular; /**< Color especular. */
81 float shine; /**< Cantidad de brillo. */
82 float shineStrenght; /**< Intensidad de brillo. */
83 float transparency; /**< Transparencia. */
84 float selfIllum; /**< Iluminación propia. */
85
86 /** Devuelve la textura asociada a este material.
87 * @return La textura asociada a este material.
88 */
89 JGLTexture * Texture()
90 {
91 return texture;
92 }
93
94 /** Libera los recursos asociados.
95 */
96 void Destroy();
97
98 /** Destruye el material y libera los recursos asociados.
99 */
100 ~JMaterial() {Destroy();}
101 };
102
103 typedef JVector JVertex;
104
105 /** Coordenada de textura.
106 */
107 struct JTextureVertex
108 {
109 float u; /**< Componente u. */
110 float v; /**< Componente v. */
111 };
112
113 /** Cara.
114 */
115 class JFace
116 {
117 public:
118 /** Crea el objeto.
119 */
120 JFace() : material(0) {}
121 s32 v1; /**< Vértice 1. */
122 s32 v2; /**< Vértice 2. */
123 s32 v3; /**< Vértice 3. */
124 JMaterial *material; /**< material asociado. */
125 JVector normal; /**< Vector normal. */
126 };
127
128 /** Cara con textura.
129 */
130 struct JTextureFace
131 {
132 s32 v1; /**< Vértice 1. */
133 s32 v2; /**< Vértice 2. */
134 s32 v3; /**< Vértice 3. */
135 };
136
137 /** Clase de objeto 3D para OpenGL. Un objeto se compone de
138 * vértices agrupados en caras, posiblemente texturizadas.
139 * Nótese que los materiales se asignan a nivel de geometría.
140 */
141 class JGLMeshObject
142 {
143 public:
144 JString name; /**< Nombre. */
145 s32 numVertices; /**< Número de vértices. */
146 s32 numTVertices; /**< Número de vértices de textura. */
147 s32 numFaces; /**< Número de caras. */
148 s32 numTFaces; /**< Número de caras de textura. */
149 JVertex *vertices; /**< Vértices. */
150 JTextureVertex *tVertices; /**< Vértices de textura. */
151 JVector *vertexNormals; /**< Normales a los vértices. */
152 JFace *faces; /**< Caras. */
153 JTextureFace *tFaces; /**< Caras de textura. */
154
155 /** Crea el objeto vacío.
156 */
157 JGLMeshObject() : vertices(0), tVertices(0), vertexNormals(0), faces(0), tFaces(0)
158 {}
159
160 /** Devuelve el nombre de esta geometría.
161 * @return nombre de esta geometría.
162 */
163 const JString & Name()
164 {
165 return name;
166 }
167
168 /** Establece el nombre de esta geometría.
169 * @param newName nombre de esta geometría.
170 */
171 void Name(const JString & newName)
172 {
173 name = newName;
174 }
175
176 /** Devuelve el número de vértices de la geometría.
177 * @return Número de vértices de la geometría.
178 */
179 s32 NumVertices()
180 {
181 return numVertices;
182 }
183
184 /** Devuelve el número de vértices de textura de la geometría.
185 * @return El número de vértices de textura de la geometría.
186 */
187 s32 NumTVertices()
188 {
189 return numTVertices;
190 }
191
192 /** Devuelve el número de caras de la geometría.
193 * @return El número de caras de la geometría.
194 */
195 s32 NumFaces()
196 {
197 return numFaces;
198 }
199
200 /** Devuelve el número de caras de textura de la geometría.
201 * @return El número de caras de textura de la geometría.
202 */
203 s32 NumTFaces()
204 {
205 return numTFaces;
206 }
207
208 /** Devuelve los vértices de la geometría.
209 * @return Vértices de la geometría.
210 */
211 JVertex * Vertices()
212 {
213 return vertices;
214 }
215
216 /** Devuelve los vértices de textura de la geometría.
217 * @return Vértices De Textura de la geometría.
218 */
219 JTextureVertex * TVertices()
220 {
221 return tVertices;
222 }
223
224 /** Devuelve las normales a los vértices de la geometría.
225 * @return Las normales a los vértices de la geometría.
226 */
227 JVector * VertexNormals()
228 {
229 return vertexNormals;
230 }
231
232 /** Devuelve las caras de la geometría.
233 * @return Las caras de la geometría.
234 */
235 JFace * Faces()
236 {
237 return faces;
238 }
239
240 /** Devuelve las caras de textura de la geometría.
241 * @return Las caras de textura de la geometría.
242 */
243 JTextureFace * TFaces()
244 {
245 return tFaces;
246 }
247
248 /** Libera los recursos asociados a este objeto.
249 */
250 void Destroy();
251
252 /** Destruye el objeto.
253 */
254 virtual ~JGLMeshObject() {Destroy();}
255 };
256
257 /** Clase de geometría 3D para OpenGL. Consiste de una serie de objetos 3D
258 * y sus correspondientes materiales.
259 */
260 class JGLMesh : public JDrawable
261 {
262 protected:
263 s32 numMaterials; /**< Número de materiales. */
264 s32 numObjects; /**< Número de objetos. */
265 JMaterial *materials; /**< Materiales. */
266 JGLMeshObject *objects; /**< Objetos 3D de esta geometría. */
267
268 JTextFile f; /**< Fichero de carga de objetos. */
269
270 /** Carga los materiales de la geometría desde el fichero ASE abierto por LoadASE.
271 * @return <b>true</b> si se pudieron cargar, <b>false</b> si no.
272 */
273 bool LoadASEMaterials();
274
275 /** Carga los objetos de la geometría desde el fichero ASE abierto por LoadASE.
276 * @return <b>true</b> si se pudieron cargar, <b>false</b> si no.
277 */
278 bool LoadASEObjects();
279
280 public:
281 /** Construye la geometría vacía, lista para cargarse con Load().
282 */
283 JGLMesh() : materials(0), objects(0)
284 {}
285
286 /** Devuelve el número de materiales de la geometría.
287 * @return El número de materiales de la geometría.
288 */
289 s32 NumMaterials()
290 {
291 return numMaterials;
292 }
293
294 /** Devuelve el número de objetos de esta geometría.
295 * @return El número de objetos de esta geometría.
296 */
297 s32 NumObjects()
298 {
299 return numObjects;
300 }
301
302 /** Devuelve los materiales de la geometría.
303 * @return Los materiales de la geometría.
304 */
305 JMaterial * Materials()
306 {
307 return materials;
308 }
309
310 /** Devuelve los objetos de esta geometría.
311 * @return los objetos de esta geometría.
312 */
313 JGLMeshObject * Objects()
314 {
315 return objects;
316 }
317
318 /** Dibuja la geometría.
319 */
320 void Draw();
321
322 /** Carga la geometría desde el fichero dado.
323 * Por ahora el fichero puede ser formato ASE únicamente.
324 * @return <b>true</b> si se pudo cargar, <b>false</b> si no.
325 */
326 bool LoadASE(const JString &filename);
327
328 /** Carga la geometría desde el fichero J3D dado. Los ficheros J3D se generan a partir de Blender (www.blender.org)
329 * con ayuda del script de exportación 'JExporter'.
330 * @return <b>true</b> si se pudo cargar, <b>false</b> si no.
331 */
332 bool LoadJ3D(const JString &filename);
333
334 /** Libera los recursos asociados a este objeto.
335 */
336 void Destroy();
337
338 /** Destruye el objeto.
339 */
340 virtual ~JGLMesh() {Destroy();}
341 };
342
343 #endif // _JGLMESH_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 30/04/2003
25 // @description: Texto en pantalla con funciones de fonto (OpenGL)
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #include <JLib/Graphics/JGLText.h>
29
30 extern JGLApp *g_pApp;
31
32 // Constructor
33 JGLText::JGLText()
34 {
35 list = 0;
36 }
37
38 // Destructor
39 JGLText::~JGLText()
40 {
41 // Borra la lista
42 if (list != 0)
43 glDeleteLists(list, 255);
44 }
45
46 // Inicializa la fuente
47 bool JGLText::Init(const char* name /* = "Courier New"*/,
48 int fontSize /*= 12*/,
49 int fontWeight /*= 30*/,
50 bool cursive /*= false*/,
51 bool underscore /*= false*/,
52 bool bitmapFont /*= true*/)
53 {
54 strcpy(font.name, name);
55 font.fontSize = fontSize;
56 font.fontWeight = fontWeight;
57 font.cursive = cursive;
58 font.underscore = underscore;
59 font.bitmapFont = bitmapFont;
60
61 return BuildFont();
62 }
63
64 // Inicializa la fuente
65 bool JGLText::Init(JFont *_font)
66 {
67 if (!_font)
68 {
69 // Pone la fuente por defecto
70 return Init();
71 }
72 else
73 {
74 memcpy(&font, _font, sizeof(JFont));
75 }
76
77 return BuildFont();
78 }
79
80 // Crea las listas de fuente
81 bool JGLText::BuildFont()
82 {
83 if (list != 0)
84 glDeleteLists(list, 255);
85
86 list = glGenLists(255);
87
88 if (list != 0)
89 {
90 // Crea la fuente a partir de las de windows
91 HFONT fnt = CreateFont(-font.fontSize,
92 0,
93 0,
94 0,
95 font.fontWeight,
96 font.cursive,
97 font.underscore,
98 0,
99 ANSI_CHARSET,
100 OUT_DEFAULT_PRECIS,
101 CLIP_DEFAULT_PRECIS,
102 ANTIALIASED_QUALITY,
103 DEFAULT_PITCH | FF_SWISS,
104 font.name);
105
106 HFONT fntOld = (HFONT)SelectObject(g_pApp->hDC, fnt);
107
108 // Crea la lista de OpenGL
109 if (font.bitmapFont)
110 {
111 wglUseFontBitmaps(g_pApp->hDC, 0, 255, list);
112 }
113 else
114 {
115 wglUseFontOutlines(g_pApp->hDC, 0, 255, list, 0.0f, 0.0f, WGL_FONT_POLYGONS, 0);
116 }
117
118 // Toma la anchura de cada caracter
119 GetCharWidth32(g_pApp->hDC, 0, 255, widths);
120
121 SelectObject(g_pApp->hDC, fntOld);
122 DeleteObject(fnt);
123
124 return true;
125 }
126
127 return false;
128 }
129
130 // Comienza la escritura de texto
131 void JGLText::Begin()
132 {
133 // Cambia a 2D
134 glMatrixMode(GL_PROJECTION);
135 glPushMatrix();
136 glLoadIdentity();
137 glOrtho(0.0, g_pApp->width, g_pApp->height, 0.0, -1.0, 1.0);
138 glMatrixMode(GL_MODELVIEW);
139 glPushMatrix();
140 glLoadIdentity();
141
142 // PARA TEXTURAS
143
144 // Push the neccessary Attributes on the stack
145 /*
146 glPushAttrib(GL_TEXTURE_BIT|GL_ENABLE_BIT);
147
148 glBindTexture(GL_TEXTURE_2D, fontID);
149 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
150 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
151 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
152 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
153 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
154 glEnable(GL_TEXTURE_2D);*/
155
156 // Always Draw in Front
157 //glDisable(GL_DEPTH_TEST);
158 //glDisable(GL_CULL_FACE);
159 }
160
161 // Dibuja en pantalla la cadena dada en la posición dada
162 void JGLText::Draw(int x, int y, const char *text)
163 {
164 float xoff = (float)x, yoff = (float)y;
165 size_t len = strlen(text);
166 glRasterPos2f(xoff, yoff);
167
168 // Dibuja los caracteres en pantalla
169 for (unsigned int i = 0; i < len; ++i)
170 {
171 if (text[i] == 10)
172 {
173 yoff += font.fontSize;
174 xoff = (float)x;
175 glRasterPos2f(xoff, yoff);
176 }
177 else
178 {
179 glCallList(text[i]);
180 xoff += widths[text[i]];
181 }
182
183 glRasterPos2f(xoff, yoff);
184 }
185 }
186
187 // Muestra un mensaje (tipo 'printf()')
188 void JGLText::Printf(int x, int y, const char *str, ...)
189 {
190 va_list vlist;
191 char _str[1024];
192
193 va_start(vlist, str);
194 vsprintf(_str, str, vlist);
195 va_end(vlist);
196
197 Draw(x, y, _str);
198 }
199
200 // Finaliza la escritura de texto
201 void JGLText::End()
202 {
203 // Restaura las matrices originales
204 glMatrixMode(GL_PROJECTION);
205 glPopMatrix();
206 glMatrixMode(GL_MODELVIEW);
207 glPopMatrix();
208 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 30/04/2003
25 // @description: Texto en pantalla con funciones de formato (OpenGL)
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #ifndef _JGLTEXT_INCLUDED
29 #define _JGLTEXT_INCLUDED
30
31 #include <JLib/Util/JObject.h>
32 #include <JLib/Util/JString.h>
33 #include <JLib/Util/JGLApp.h>
34 #include <JLib/Graphics/JFont.h>
35 #include <SDL.h>
36 #include <GL/gl.h>
37
38 class JGLText : public JObject
39 {
40 public:
41 GLuint list; // Lista base OpenGL
42 JFont font; // Formato de fuente
43 int widths[256]; // Anchuras por caracter
44 int lineHeight; // Altura de línea
45
46 // Constructor
47 JGLText();
48
49 // Destructor
50 ~JGLText();
51
52 // Inicializa la fuente
53 bool Init(const char* name = "Courier New",
54 int fontSize = 12,
55 int fontWeight = 30,
56 bool cursive = false,
57 bool underscore = false,
58 bool bitmapFont = true);
59
60 // Inicializa la fuente
61 bool Init(JFont *_font);
62
63 // Crea las listas de fuente
64 bool BuildFont();
65
66 // Comienza la escritura de texto
67 void Begin();
68
69 // Dibuja en pantalla la cadena dada en la posición dada
70 void Draw(int x, int y, const char *text);
71
72 // Muestra un mensaje (tipo 'printf()')
73 void Printf(int x, int y, const char *str, ...);
74
75 // Finaliza la escritura de texto
76 void End();
77 };
78
79 #endif // _JGLTEXT_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clase para gestión de texturas. El objeto JGLTexture consta de las
23 * coordenadas de textura dentro de la superficie de datos y de un índice
24 * de textura OpenGL. El llamador es responsable de que la textura sea válida
25 * (por ejemplo de ancho y alto como potencia de 2, donde se aplique o
26 * dimensiones mínimas y/o máximas dependientes de la implementación OpenGL).
27 * @file JGLTexture.cpp
28 * @author Juan Carlos Seijo Pérez
29 * @date 01/04/2003
30 * @version 0.0.1 - 01/04/2003 - Primera Versión.
31 */
32
33 #include <JLib/Graphics/JGLTexture.h>
34
35 // Constructor
36 JGLTexture::JGLTexture() : instance(0)
37 {}
38
39 // Libera la memoria asociada
40 void JGLTexture::Destroy()
41 {
42 if (instance)
43 {
44 --(instance->refCount);
45
46 if (instance->refCount == 0)
47 {
48 {s32 rettt = glGetError(); if (rettt) printf("%s (%d) Error OpenGL: %s\n", __FILE__, __LINE__, gluErrorString(rettt));};
49 if (!glIsTexture(instance->id)) printf("JGLTexture::Destroy() id es %d, IsTexture=%d\n", instance->id, glIsTexture(instance->id));
50 {s32 rettt = glGetError(); if (rettt) printf("%s (%d) Error OpenGL: %s\n", __FILE__, __LINE__, gluErrorString(rettt));};
51 glDeleteTextures(1, (GLuint *)&instance->id);
52 delete instance;
53 }
54
55 instance = 0;
56 }
57 }
58
59 u32 JGLTexture::Next2Power(u32 value)
60 {
61 u32 newVal = 1;
62 while (value > newVal)
63 {
64 newVal <<= 1;
65 }
66
67 return newVal;
68 }
69
70 // Crea la textura a partir de un buffer.
71 u32 JGLTexture::Create(JImage *image, bool withMipmaps /*= false*/, s32 internalFormat /*= 4*/, s32 border /*= 0*/, s32 format /*= GL_RGBA*/, s32 type /*= GL_UNSIGNED_BYTE*/)
72 {
73 {s32 rettt = glGetError(); if (rettt) printf("%s (%d) Error OpenGL: %s\n", __FILE__, __LINE__, gluErrorString(rettt));};
74
75 // Si no hay datos
76 if(!image)
77 return 0;
78
79 Destroy();
80
81 instance = new JGLTexture::JInstance;
82 ++(instance->refCount);
83
84 instance->width = image->Width();
85 instance->height = image->Height();
86 instance->bpp = image->BitsPP();
87
88 instance->hasMipmaps = withMipmaps;
89
90 // Genera la textura con el ID asociado en el array
91 {s32 rettt = glGetError(); if (rettt) printf("%s (%d) Error OpenGL: %s\n", __FILE__, __LINE__, gluErrorString(rettt));};
92 glGenTextures(1, (GLuint *)&instance->id);
93 {s32 rettt = glGetError(); if (rettt) printf("%s (%d) Error OpenGL: %s\n", __FILE__, __LINE__, gluErrorString(rettt));};
94
95 if (0 == instance->id)
96 {
97 fprintf(stderr, "JGLTexture: No se pudo generar la textura.\n");
98 JDELETE(instance);
99
100 return 0;
101 }
102
103 // Enlaza el ID a la textura
104 {s32 rettt = glGetError(); if (rettt) printf("%s (%d) Error OpenGL: %s\n", __FILE__, __LINE__, gluErrorString(rettt));};
105 glBindTexture(GL_TEXTURE_2D, instance->id);
106 {s32 rettt = glGetError(); if (rettt) printf("%s (%d) Error OpenGL: %s\n", __FILE__, __LINE__, gluErrorString(rettt));};
107
108 // Crea los mipmaps, si es necesario
109 if (instance->hasMipmaps)
110 {
111 {s32 rettt = glGetError(); if (rettt) printf("%s (%d) Error OpenGL: %s\n", __FILE__, __LINE__, gluErrorString(rettt));};
112 if (0 != gluBuild2DMipmaps(GL_TEXTURE_2D,
113 internalFormat,
114 image->Width(),
115 image->Height(),
116 format,
117 type,
118 image->Pixels()))
119 {
120 fprintf(stderr, "No se pudieron construir los mipmaps: %s\n", gluErrorString(glGetError()));
121 Destroy();
122
123 return 0;
124 }
125 {s32 rettt = glGetError(); if (rettt) printf("%s (%d) Error OpenGL: %s\n", __FILE__, __LINE__, gluErrorString(rettt));};
126 }
127 else
128 {
129 glGetError();
130
131 image->Lock();
132 glTexImage2D(GL_TEXTURE_2D,
133 0,
134 internalFormat,
135 image->Width(),
136 image->Height(),
137 border,
138 format,
139 type,
140 image->Pixels());
141 image->Unlock();
142
143 u32 ret = glGetError();
144 if (ret != 0)
145 {
146 fprintf(stderr, "Fallo al invocar glTexImage2D(). Error de OpenGL: %s\n", gluErrorString(ret));
147 fprintf(stderr, "Invocado con internalFormat %d, width %d, height %d, border %d, format %d (GL_RGBA es %d), type %d (GL_UNSIGNED_BYTE es %d), pixels es %p\n",
148 internalFormat, image->Width(), image->Height(), border, format, type, image->Pixels());
149 Destroy();
150
151 return 0;
152 }
153 }
154
155 {s32 rettt = glGetError(); if (rettt) printf("%s (%d) Error OpenGL: %s\n", __FILE__, __LINE__, gluErrorString(rettt));};
156 // Calidad de la textura
157 if (instance->hasMipmaps)
158 {
159 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
160 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
161 }
162 else
163 {
164 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
165 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
166 }
167
168 {s32 rettt = glGetError(); if (rettt) printf("%s (%d) Error OpenGL: %s\n", __FILE__, __LINE__, gluErrorString(rettt));};
169 return instance->id;
170 }
171
172 // Crea la textura desde un fichero bmp, tga o jpg.
173 // Devuelve el id de textura.
174 u32 JGLTexture::Load(const char *fileName, bool withMipmaps /*= false*/, s32 internalFormat /*= 4*/, s32 border /*= 0*/, s32 format /*= GL_RGBA*/, s32 type /*= GL_UNSIGNED_BYTE*/)
175 {
176 {s32 rettt = glGetError(); if (rettt) printf("%s (%d) Error OpenGL: %s\n", __FILE__, __LINE__, gluErrorString(rettt));};
177 if (fileName == 0)
178 return 0;
179
180 JImage image;
181 if (!image.Load(fileName, 0))
182 {
183 return 0;
184 }
185
186 return Create(&image, withMipmaps, internalFormat, border, format, type);
187 }
188
189 // Constructor copia, referencia la textura.
190 JGLTexture::JGLTexture(JGLTexture &other) : instance(0)
191 {
192 Ref(other);
193 }
194
195 // Constructor copia, referencia la textura.
196 JGLTexture::JGLTexture(const JGLTexture &other) : instance(0)
197 {
198 Ref(other);
199 }
200
201 // Referencia la textura dada.
202 void JGLTexture::Ref(JGLTexture &other)
203 {
204 Destroy();
205
206 if (other.instance != 0)
207 {
208 instance = other.instance;
209 ++(instance->refCount);
210 }
211 }
212
213 // Referencia la textura dada.
214 void JGLTexture::Ref(const JGLTexture &other)
215 {
216 Destroy();
217
218 if (other.instance != 0)
219 {
220 instance = other.instance;
221 ++(instance->refCount);
222 }
223 }
224
225 // Referencia la textura dada.
226 JGLTexture & JGLTexture::operator=(JGLTexture &other)
227 {
228 Ref(other);
229 return *this;
230 }
231
232 // Referencia la textura dada.
233 JGLTexture & JGLTexture::operator=(const JGLTexture &other)
234 {
235 Ref(other);
236 return *this;
237 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clase para gestión de texturas. El objeto JGLTexture consta de las
23 * coordenadas de textura dentro de la superficie de datos y de un índice
24 * de textura OpenGL. El llamador es responsable de que la textura sea válida
25 * (por ejemplo de ancho y alto como potencia de 2, donde se aplique o
26 * dimensiones mínimas y/o máximas dependientes de la implementación OpenGL).
27 * @file JGLTexture.h
28 * @author Juan Carlos Seijo Pérez
29 * @date 01/04/2003
30 * @version 0.0.1 - 01/04/2003 - Primera Versión.
31 */
32
33 #ifndef _JGLTEXTURE_INCLUDED
34 #define _JGLTEXTURE_INCLUDED
35
36 #include <JLib/Util/JTypes.h>
37 #include <JLib/Util/JObject.h>
38 #include <JLib/Graphics/JImage.h>
39 #include <GL/gl.h>
40 #include <GL/glu.h>
41
42 #ifndef GL_CLAMP_TO_EDGE
43 #define GL_CLAMP_TO_EDGE GL_CLAMP
44 #endif//GL_CLAMP_TO_EDGE
45
46 /** Clase para gestión de texturas
47 */
48 class JGLTexture : public JObject
49 {
50 /** Instancia de textura. Sirve para llevar cuenta de las referencias a una misma textura creadas.
51 */
52 struct JInstance
53 {
54 JInstance() : id(0), refCount(0) {}
55 u32 id;
56 bool hasMipmaps;
57 s32 width;
58 s32 height;
59 s32 bpp;
60 u32 refCount;
61 } *instance;
62
63 // Crea la textura.
64 u32 Create();
65
66 public:
67 // Constructor
68 JGLTexture();
69
70 // Constructor copia, referencia la textura.
71 JGLTexture(JGLTexture &other);
72
73 // Constructor copia, referencia la textura.
74 JGLTexture(const JGLTexture &other);
75
76 // Determina si esta textura es válida
77 bool Valid() {return instance != 0;}
78
79 // Crea la textura a partir de un buffer.
80 u32 Create(JImage *image, bool withMipmaps = true, s32 internalFormat = 4, s32 border = 0, s32 format = GL_RGBA, s32 type = GL_UNSIGNED_BYTE);
81
82 // Crea la textura desde un fichero bmp, targa, jpg, png, xpm o pcx.
83 // Devuelve el id de textura y no se queda una copia.
84 u32 Load(const char *fileName, bool withMipmaps = true, s32 internalFormat = 4, s32 border = 0, s32 format = GL_RGBA, s32 type = GL_UNSIGNED_BYTE);
85
86 // Libera la memoria asociada
87 void Destroy();
88
89 // Devuelve la siguiente potencia de dos por encima del valor dado.
90 static u32 Next2Power(u32 value);
91
92 // Devuelve el identificador de textura
93 u32 ID() {return instance ? instance->id : 0;}
94
95 // Devuelve la superficie de textura, debe estar enlazada a OpenGL (bind)
96 u8* Data() {u8 *data; glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); return data;}
97
98 // Devuelve la anchura de la textura
99 u32 Width() {return instance->width;}
100
101 // Devuelve la altura de la textura
102 u32 Height() {return instance->height;}
103
104 // Devuelve la profundidad de color
105 u32 BitsPP() {return instance->bpp;}
106
107 // Enlaza la textura a OpenGL
108 void GLBind() {glBindTexture(GL_TEXTURE_2D, instance->id);}
109
110 // Establece la repetición x e y
111 static void GLRepeat() {glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);}
112
113 // Establece clamp x e y
114 static void GLClamp() {glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);}
115
116 // Establece clamp to edge x e y
117 static void GLClampToEdge() {glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);}
118
119 // Establece el parámetro OpenGL dado para las texturas 2D
120 static void GLParameter(u32 param, u32 value) {glTexParameteri(GL_TEXTURE_2D, param, value);}
121
122 // Establece las coordenadas de textura
123 void GLCoord2f(float s, float t) {glTexCoord2f(s, t);}
124
125 // Establece las coordenadas de textura
126 void GLCoord2fv(const float *v) {glTexCoord2fv(v);}
127
128 // Establece las coordenadas de textura
129 void GLCoord2d(s32 s, s32 t) {glTexCoord2i(s, t);}
130
131 // Establece las coordenadas de textura
132 void GLCoord2dv(const s32 *v) {glTexCoord2iv(v);}
133
134 // Referencia la textura dada.
135 void Ref(JGLTexture &other);
136
137 // Referencia la textura dada.
138 JGLTexture & operator=(JGLTexture &other);
139
140 // Referencia la textura dada.
141 void Ref(const JGLTexture &other);
142
143 // Referencia la textura dada.
144 JGLTexture & operator=(const JGLTexture &other);
145
146 // Destructor
147 virtual ~JGLTexture() {Destroy();}
148 };
149
150 #endif // _JGLTEXTURE_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Vector en pantalla (OpenGL).
23 * @file JGLVector.cpp.
24 * @author Juan Carlos Seijo Pérez
25 * @date 30/04/2003
26 * @version 0.0.1 - 30/04/2003 - Primera versión.
27 */
28
29 #include <JLib/Graphics/JGLVector.h>
30
31 void JGLVector::Draw(JVector &pos)
32 {
33 glLineWidth(3.0f);
34 glBegin(GL_LINES);
35 glVertex3f(pos.x, pos.y, pos.z);
36 glVertex3f(x, y, z);
37 glEnd();
38 glLineWidth(1.0f);
39
40 JVector v(*this + pos);
41 JVector vr(v.Unit());
42 float len = v.Length();
43
44 if (len > 0.01)
45 {
46 JVector w(len, len, 0);
47 w = w.Cross(v).Unit();
48
49 glPointSize(5.0f);
50 glBegin(GL_POINTS);
51 glVertex3f(v.x, v.y, v.z);
52 //glVertex3f(v.x - vr.x + w.x, v.y - vr.y - w.y, v.z - vr.z - w.z);
53 //glVertex3f(v.x - vr.x + w.x, v.y - vr.y + w.y, v.z - vr.z + w.z);
54 glEnd();
55 glPointSize(1.0f);
56 }
57 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Vector en pantalla (OpenGL).
23 * @file JGLVector.h.
24 * @author Juan Carlos Seijo Pérez
25 * @date 30/04/2003
26 * @version 0.0.1 - 30/04/2003 - Primera versión.
27 */
28
29 #ifndef _JGLVECTOR_INCLUDED
30 #define _JGLVECTOR_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Math/JVector.h>
34 #include <SDL.h>
35 #include <GL/gl.h>
36
37 /** Vector en pantalla para OpenGL.
38 */
39 class JGLVector : public JVector
40 {
41 public:
42 /** Dibuja el vector en pantalla.
43 * @param pos Posición de origen del vector.
44 */
45 void Draw(JVector &pos);
46 };
47
48 #endif // _JGLVECTOR_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Imagen genérica
23 * @file JImage.cpp.
24 * @author Juan Carlos Seijo Pérez
25 * @date 14/10/2003
26 * @version 0.0.1 - 14/10/2003 - Primera varsión.
27 * @version 0.0.2 - 01/06/2004 - Adición de métodos de referencia y copia.
28 */
29
30 #include <JLib/Graphics/JImage.h>
31
32 // Constructor
33 JImage::JImage() : surface(0)
34 {
35 }
36
37 JImage::JImage(u32 w, u32 h, u32 _bpp)
38 : surface(0)
39 {
40 Create(w, h, _bpp);
41 }
42
43 // Constructor copia
44 JImage::JImage(JImage &img)
45 {
46 surface = SDL_ConvertSurface(img.Surface(), img.Surface()->format, img.Surface()->flags);
47 }
48
49 // Carga la imagen desde fichero. Soporta '.tga', '.bmp', '.jpg' y otros
50 bool JImage::Load(const char *filename, bool toDisplayFormat, u32 cKey)
51 {
52 surface = IMG_Load(filename);
53 if (surface != 0)
54 {
55 if (toDisplayFormat)
56 {
57 SDL_Surface *surf = SDL_DisplayFormat(surface);
58
59 if (0 != surf)
60 {
61 SDL_FreeSurface(surface);
62 surface = surf;
63 ColorKey(cKey);
64 }
65 }
66
67 return true;
68 }
69
70 return false;
71 }
72
73 void endian_swap2(void *_data, u32 bytes)
74 {
75 u32 i;
76 u16 *data = (u16*)_data;
77
78 for(i = 0; i < bytes>>1; ++i)
79 {
80 data[i] = SDL_Swap16(data[i]);
81 }
82 }
83
84 void endian_swap4(void *_data, u32 bytes)
85 {
86 u32 i;
87 u32 *data = (u32*)_data;
88
89 for(i = 0; i < bytes>>2; ++i) {
90 data[i] = SDL_Swap32(data[i]);
91 }
92 }
93
94
95 // Crea la superficie vacía
96 // Si data no es cero carga una copia en la superficie.
97 bool JImage::Create(u32 w, u32 h, u32 _bpp, void *data, u32 rMask, u32 gMask, u32 bMask, u32 aMask)
98 {
99 Destroy();
100
101 if (_bpp == 0)
102 {
103 _bpp = SDL_GetVideoSurface()->format->BitsPerPixel;
104 }
105
106 if (rMask == 0 &&
107 gMask == 0 &&
108 bMask == 0 &&
109 aMask == 0)
110 {
111 rMask = SDL_GetVideoSurface()->format->Rmask;
112 gMask = SDL_GetVideoSurface()->format->Gmask;
113 bMask = SDL_GetVideoSurface()->format->Bmask;
114 aMask = SDL_GetVideoSurface()->format->Amask;
115 }
116
117 // Si hay datos los carga a una superficie temporal...
118 if (data)
119 {
120 SDL_Surface *tmp;
121
122 if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
123 {
124 if(_bpp == 16)
125 {
126 endian_swap2(data, _bpp/8 * w * h);
127 }
128 else if(_bpp == 32)
129 {
130 endian_swap4(data, _bpp/8 * w * h);
131 }
132 }
133
134 tmp = SDL_CreateRGBSurfaceFrom(data, w, h, _bpp, _bpp/8 * w,
135 rMask, gMask, bMask, aMask);
136
137 if (tmp == 0)
138 {
139 printf("JImage::Create(): Error al crear tmp!\n");
140 return false;
141 }
142
143 surface = SDL_DisplayFormat(tmp);
144
145 SDL_FreeSurface(tmp);
146 if(surface == 0)
147 {
148 fprintf(stderr, "CreateRGBSurface failed: %s\n", SDL_GetError());
149 return false;
150 }
151
152 return true;
153 }
154 else
155 {
156 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, _bpp,
157 rMask, gMask, bMask, aMask);
158 if(surface == 0)
159 {
160 fprintf(stderr, "CreateRGBSurface failed: %s\n", SDL_GetError());
161 return false;
162 }
163
164 Fill(ColorKey());
165 }
166
167 return true;
168 }
169
170 // Dibuja la imagen
171 void JImage::Draw()
172 {
173 SDL_Rect rc;
174 rc.x = (s16)pos.x;
175 rc.y = (s16)pos.y;
176 rc.w = (u16)surface->w;
177 rc.h = (u16)surface->h;
178
179 SDL_BlitSurface(surface, 0, SDL_GetVideoSurface(), &rc);
180 }
181
182 // Dibuja la imagen en la posición dada.
183 void JImage::Draw(s32 x, s32 y)
184 {
185 SDL_Rect rc;
186 rc.x = (s16)x;
187 rc.y = (s16)y;
188 rc.w = (u16)surface->w;
189 rc.h = (u16)surface->h;
190
191 SDL_BlitSurface(surface, 0, SDL_GetVideoSurface(), &rc);
192 }
193
194 // Pega el contenido de una imagen en esta.
195 bool JImage::Paste(JImage *srcImg, s32 xSrc, s32 ySrc, s32 wSrc, s32 hSrc, s32 xDst, s32 yDst)
196 {
197 SDL_Rect srcRc, dstRc;
198 srcRc.x = (s16)xSrc;
199 srcRc.y = (s16)ySrc;
200 srcRc.w = (u16)wSrc;
201 srcRc.h = (u16)hSrc;
202 dstRc.x = (s16)xDst;
203 dstRc.y = (s16)yDst;
204 dstRc.w = (u16)wSrc;
205 dstRc.h = (u16)hSrc;
206
207 return 0 == SDL_BlitSurface(srcImg->surface, &srcRc, surface, &dstRc);
208 }
209
210 // Devuelve el valor del pixel en la posición dada.
211 // La imagen debe estar bloqueada.
212 u32 JImage::GetPixel(s32 x, s32 y)
213 {
214 s32 bpp = surface->format->BytesPerPixel;
215 u8 *p = (u8 *)surface->pixels + y * surface->pitch + x * bpp;
216
217 switch(bpp)
218 {
219 case 1:
220 return *p;
221
222 case 2:
223 return *(u16 *)p;
224
225 case 3:
226 if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
227 {
228 return p[0] << 16 | p[1] << 8 | p[2];
229 }
230 else
231 {
232 return p[0] | p[1] << 8 | p[2] << 16;
233 }
234
235 case 4:
236 return *(u32 *)p;
237
238 default:
239 return 0;
240 }
241 }
242
243 // Establece el valor del pixel en la posición dada.
244 // La imagen debe estar bloqueada.
245 void JImage::PutPixel(s32 x, s32 y, u32 color)
246 {
247 s32 bpp = surface->format->BytesPerPixel;
248 u8 *p = (u8 *)surface->pixels + y * surface->pitch + x * bpp;
249
250 switch(bpp)
251 {
252 case 1:
253 *p = (u8)color;
254 break;
255
256 case 2:
257 *(u16 *)p = (u16)color;
258 break;
259
260 case 3:
261 if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
262 p[0] = ((u8)(color >> 16)) & 0xff;
263 p[1] = ((u8)(color >> 8)) & 0xff;
264 p[2] = ((u8)color) & 0xff;
265 } else {
266 p[0] = ((u8)color) & 0xff;
267 p[1] = ((u8)(color >> 8)) & 0xff;
268 p[2] = ((u8)(color >> 16)) & 0xff;
269 }
270 break;
271
272 case 4:
273 *(u32 *)p = color;
274 break;
275 }
276 }
277
278 // Guarda la imagen como BMP
279 bool JImage::SaveAsBMP(const char *file)
280 {
281 return (0 == SDL_SaveBMP(surface, file));
282 }
283
284 // Carga la imagen.
285 u32 JImage::Load(JRW &f)
286 {
287 Destroy();
288
289 s32 w, h;
290 u32 ckey, sz, Rmask, Gmask, Bmask, Amask;
291 u8 bpp, *data;
292 if (f.ReadLE32(&w) && f.ReadLE32(&h) && f.Read8(&bpp) &&
293 f.ReadLE32(&Rmask) && f.ReadLE32(&Gmask) && f.ReadLE32(&Bmask) &&
294 f.ReadLE32(&Amask) && f.ReadLE32(&ckey) && f.ReadLE32(&sz))
295 {
296 data = new u8[sz];
297 if (f.Read(data, sz))
298 {
299 if (Create(w, h, bpp, data, Rmask, Gmask, Bmask, Amask))
300 {
301 ColorKey(ckey);
302
303 delete[] data;
304
305 return 0;
306 }
307 }
308
309 delete[] data;
310 }
311
312 return 1;
313 }
314
315 // Salva la imagen.
316 u32 JImage::Save(JRW &f)
317 {
318 u32 sz = Size();
319 if (f.WriteLE32(&surface->w) &&
320 f.WriteLE32(&surface->h) &&
321 f.Write8(&surface->format->BitsPerPixel) &&
322 f.WriteLE32(&surface->format->Rmask) &&
323 f.WriteLE32(&surface->format->Gmask) &&
324 f.WriteLE32(&surface->format->Bmask) &&
325 f.WriteLE32(&surface->format->Amask) &&
326 f.WriteLE32(&surface->format->colorkey) &&
327 f.WriteLE32(&sz))
328 {
329 if (0 == Lock())
330 {
331 // Salva cada línea, pues hemos de tener en cuenta el pitch en memoria
332 for (s32 j = 0; j < surface->h; ++j)
333 {
334 u8 *data = Line(j);
335 if (0 == f.Write(data, surface->w * BytesPP()))
336 {
337 // Error E/S
338 Unlock();
339 return 1;
340 }
341 }
342
343 Unlock();
344
345 return 0;
346 }
347 }
348
349 return 2;
350 }
351
352 u32 JImage::LoadImage(JRW &jrw)
353 {
354 Destroy();
355
356 if (0 == (surface = IMG_Load_RW(jrw.rwops, 0)))
357 {
358 return 1;
359 }
360
361 return 0;
362 }
363
364 JImage * JImage::Scale(float xp, float yp)
365 {
366 if (-1 == Lock())
367 {
368 return 0;
369 }
370
371 s32 newW = (s32)(surface->w * xp), newH = (s32)(surface->h * yp);
372
373 float dx = 1.0f/xp, dy = 1.0f/yp; // Tamaño de 1 pixel original en coordenadas de la nueva imagen
374
375
376 SDL_Color samp; // Muestra actual
377
378 JImage *img = new JImage(newW, newH, surface->format->BitsPerPixel);
379
380 if (-1 == img->Lock())
381 {
382 return 0;
383 }
384
385 // Recorre los puntos de la nueva imagen
386 float nx0, ny0; // Primer pixel interviniente en la imagen original para un pixel de la nueva
387 float rAccum, gAccum, bAccum, aAccum; // Acumulados de las componentes de la imagen
388 float xSize, ySize, ratio, x1, x2, y1, y2;
389
390 for (s32 j = 0; j < newH; ++j)
391 {
392 for (s32 i = 0; i < newW; ++i)
393 {
394 nx0 = float(i)/xp;
395 ny0 = float(j)/yp;
396 rAccum = gAccum = bAccum = aAccum = 0.0f;
397
398 for (float ny = ny0; ny < ny0 + dy; ++ny) // Acumula los píxeles intervinientes de la imagen original en el nuevo pixel
399 {
400 for (float nx = nx0; nx < nx0 + dx; ++nx)
401 {
402 SDL_GetRGBA(GetPixel((s32)nx, (s32)ny), surface->format, &samp.r, &samp.g, &samp.b, &samp.unused);
403
404 // Averigua la cuota de participación del pixel.
405 // Para ello vemos el cociente entre la superficie de pixel original en la nueva imagen
406 // y la supeficie total de un pixel en unidades de la nueva imagen
407 x1 = JMax(nx * xp, i);
408 x2 = JMin((nx + 1) * xp, (i + 1));
409 y1 = JMax(ny * yp, j);
410 y2 = JMin((ny + 1) * yp, (j + 1));
411
412 xSize = x2 - x1;
413 ySize = y2 - y1;
414 ratio = (xSize * ySize);
415
416 rAccum += float(samp.r) * ratio;
417 gAccum += float(samp.g) * ratio;
418 bAccum += float(samp.b) * ratio;
419 aAccum += float(samp.unused) * ratio;
420 }
421 }
422
423 // Finalmente añade el pixel a la nueva imagen
424 img->PutPixel(i, j, SDL_MapRGBA(surface->format, (u8)rAccum, (u8)gAccum, (u8)bAccum, (u8)aAccum));
425 }
426 }
427
428 Unlock();
429 img->Unlock();
430
431 return img;
432 }
433
434 // Destructor
435 void JImage::Destroy()
436 {
437 if (surface != 0)
438 {
439 SDL_FreeSurface(surface);
440 surface = 0;
441 }
442 }
443
444 void JImage::Ref(JImage &img)
445 {
446 Destroy();
447
448 /**< @todo Quitar esto cuando SDL soporte crear referencias con alguna función. */
449 surface = img.surface;
450
451 if (surface != 0)
452 {
453 ++surface->refcount;
454 pos = img.Pos();
455 }
456 }
457
458 void JImage::operator =(JImage &img)
459 {
460 Destroy();
461
462 /**< @todo Quitar esto cuando SDL soporte crear referencias con alguna función. */
463 surface = img.surface;
464
465 if (surface != 0)
466 {
467 ++surface->refcount;
468 pos = img.Pos();
469 }
470 }
471
472 void JImage::Copy(JImage &img)
473 {
474 Destroy();
475 surface = SDL_CreateRGBSurfaceFrom(img.Pixels(), img.Width(), img.Height(), img.BitsPP(), img.Surface()->pitch,
476 img.Format()->Rmask, img.Format()->Gmask, img.Format()->Bmask, img.Format()->Amask);
477
478 }
479
480 bool JImage::Convert(SDL_PixelFormat *fmt, u32 flags)
481 {
482 SDL_Surface *tmp;
483 if (0 != (tmp = SDL_ConvertSurface(surface, fmt, flags)))
484 {
485 Destroy();
486 surface = tmp;
487
488 return true;
489 }
490
491 return false;
492 }
493
494 JString JImage::DumpFromSurface(SDL_Surface *s)
495 {
496 JString s1, s2, s3, s4, s5, s6;
497 SDL_PixelFormat *fmt = s->format;
498
499 s1.Format("%dx%d@%d COLOR_KEY: %08x SURFACE_ALPHA: %d\n", s->w, s->h, fmt->BitsPerPixel, fmt->colorkey, fmt->alpha);
500 s2.Format("pitch: %d clip_rect: x%d y%d w%d h%d pixels: %p\n", s->pitch, s->clip_rect.x, s->clip_rect.y, s->clip_rect.w, s->clip_rect.h, s->pixels);
501 s3.Format("RGBAmask: R: 0x%08x G: 0x%08x B: 0x%08x A: 0x%08x\n", fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask);
502 s4.Format("RGBAshift: R: 0x%08x G: 0x%08x B: 0x%08x A: 0x%08x\n", fmt->Rshift, fmt->Gshift, fmt->Bshift, fmt->Ashift);
503 s5.Format("RGBAloss: R: 0x%08x G: 0x%08x B: 0x%08x A: 0x%08x\n", fmt->Rloss, fmt->Gloss, fmt->Bloss, fmt->Aloss);
504 s6.Format("Flags:\n"
505 "SDL_SWSURFACE: %s\n"
506 "SDL_HWSURFACE: %s\n"
507 "SDL_ASYNCBLIT: %s\n"
508 "SDL_ANYFORMAT: %s\n"
509 "SDL_HWPALETTE: %s\n"
510 "SDL_DOUBLEBUF: %s\n"
511 "SDL_FULLSCREEN: %s\n"
512 "SDL_OPENGL: %s\n"
513 "SDL_OPENGLBLIT: %s\n"
514 "SDL_RESIZABLE: %s\n"
515 "SDL_HWACCEL: %s\n"
516 "SDL_SRCCOLORKEY: %s\n"
517 "SDL_RLEACCEL: %s\n"
518 "SDL_SRCALPHA: %s\n"
519 "SDL_PREALLOC: %s\n",
520 (s->flags & SDL_SWSURFACE) ? "yes" : "no",
521 (s->flags & SDL_HWSURFACE) ? "yes" : "no",
522 (s->flags & SDL_ASYNCBLIT) ? "yes" : "no",
523 (s->flags & SDL_ANYFORMAT) ? "yes" : "no",
524 (s->flags & SDL_HWPALETTE) ? "yes" : "no",
525 (s->flags & SDL_DOUBLEBUF) ? "yes" : "no",
526 (s->flags & SDL_FULLSCREEN) ? "yes" : "no",
527 (s->flags & SDL_OPENGL) ? "yes" : "no",
528 (s->flags & SDL_OPENGLBLIT) ? "yes" : "no",
529 (s->flags & SDL_RESIZABLE) ? "yes" : "no",
530 (s->flags & SDL_HWACCEL) ? "yes" : "no",
531 (s->flags & SDL_SRCCOLORKEY) ? "yes" : "no",
532 (s->flags & SDL_RLEACCEL) ? "yes" : "no",
533 (s->flags & SDL_SRCALPHA) ? "yes" : "no",
534 (s->flags & SDL_PREALLOC) ? "yes" : "no");
535
536 JString str;
537 str += s1;
538 str += s2;
539 str += s3;
540 str += s4;
541 str += s5;
542 str += s6;
543
544 return str;
545 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Imagen genérica
23 * @file JImage.h.
24 * @author Juan Carlos Seijo Pérez
25 * @date 14/10/2003
26 * @version 0.0.1 - 14/10/2003 - Primera varsión.
27 * @version 0.0.2 - 01/06/2004 - Adición de métodos de referencia y copia.
28 * @version 0.0.3 - 04/04/2005 - Adición de métodos de manejo de JRW.
29 */
30
31 #ifndef _JIMAGE_INCLUDED
32 #define _JIMAGE_INCLUDED
33
34 #include <JLib/Util/JTypes.h>
35 #include <JLib/Graphics/JDrawable.h>
36 #include <JLib/Util/JString.h>
37 #include <JLib/Util/JUtil.h>
38 #include <SDL.h>
39 #include <SDL_image.h>
40
41 /** Imágen genérica.
42 */
43 class JImage : public JDrawable
44 {
45 protected:
46 SDL_Surface *surface; /**< Superficie SDL. */
47
48 public:
49 /** Crea una imagen vacía.
50 */
51 JImage();
52
53 /** Crea una imagen de anchura altura y profundidad dadas.
54 * Si la profundidad es cero, se toma la del framebuffer.
55 * @param w Anchura.
56 * @param h Altura.
57 * @param _bpp Profundidad en bits por pixel.
58 */
59 JImage(u32 w, u32 h, u32 _bpp = 0);
60
61 /** Crea la imagen a partir de la superficie SDL dada.
62 * No hace una copia, establece esta como la superficie interna.
63 * @param surf Superficie SDL con los datos.
64 */
65 JImage(SDL_Surface *surf) {surface = surf;}
66
67 /** Crea una imagen copia de la imagen dada.
68 * @param img Imagen que se quiere copiar.
69 * @see Ref().
70 */
71 JImage(JImage &img);
72
73 /** Libera la memoria asociada.
74 */
75 virtual ~JImage() {Destroy();}
76
77 /** Libera la memoria asociada.
78 */
79 void Destroy();
80
81 /** Carga la imagen desde fichero.
82 * @param filename Nombre del fichero con la imagen.
83 * @param toDisplayFormat Indica si se debe convertir al formato de pantalla.
84 * @param cKey Color transparente.
85 * @return <b>true</b> si todo fue bien, <b>false</b> en caso contrario.
86 */
87 bool Load(const char *filename, bool toDisplayFormat = true, u32 cKey = 0x00000000);
88
89 /** Crea la superficie de imagen vacía.
90 * Si data no es cero carga una copia en la superficie.
91 * @param w Anchura.
92 * @param h Altura.
93 * @param _bpp Profundidad en bits por pixel.
94 * @param data Datos de la superficie en el formato correcto o cero para crearla vacía.
95 * @param rMask Máscara de bits para el rojo.
96 * @param gMask Máscara de bits para el verde.
97 * @param bMask Máscara de bits para el azul.
98 * @param aMask Máscara de bits para el alfa.
99 */
100 bool Create(u32 w, u32 h, u32 _bpp, void *data = 0, u32 rMask = 0, u32 gMask = 0, u32 bMask = 0, u32 aMask = 0);
101
102 /** Devuelve la anchura.
103 * @return Anchura.
104 */
105 s32 Width() {return surface->w;};
106
107 /** Devuelve la altura.
108 * @return Altura.
109 */
110 s32 Height() {return surface->h;};
111
112 /** Devuelve la profundidad de color en bits
113 * @return Profundidad de color en bits.
114 */
115 s32 BitsPP() {return surface->format->BitsPerPixel;};
116
117 /** Devuelve la profundidad de color en bytes
118 * @return Profundidad de color en bytes.
119 */
120 s32 BytesPP() {return surface->format->BytesPerPixel;};
121
122 /** Devuelve los datos.
123 * @return Datos asociados.
124 */
125 u8 * Pixels() {return ((u8 *)surface->pixels);};
126
127 /** Devuelve el tamaño de línea, en bytes.
128 * @return El tamaño de línea, en bytes.
129 */
130 s32 Pitch() {return surface->pitch;};
131
132 /** Devuelve un puntero a la línea dada
133 * @param nRow Línea (coordenada y) a obtener un puntero a su comienzo.
134 * @return puntero a la línea dada.
135 */
136 u8 * Line(u32 nRow) {return (Pixels() + (surface->pitch * nRow));};
137
138 /** Devuelve el tamaño total en bytes de la imagen.
139 * @return Tamaño total en bytes de la imagen.
140 */
141 u32 Size() {return Width() * Height() * BytesPP();};
142
143 /** Bloquea la superficie.
144 * @return 0 si todo va bien, -1 en caso de error.
145 */
146 inline s32 Lock() {if (SDL_MUSTLOCK(surface)) return SDL_LockSurface(surface); return 0;}
147
148 /** Desbloquea la superficie.
149 */
150 void Unlock() {if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface);}
151
152 /** Establece el alfa global de la superficie, habilita el flag de alfa de superficie y deshabilita el alfa por píxel.
153 * @param alpha Nuevo valor de transparencia.
154 * @return 0 si todo va bien, -1 en caso de error.
155 */
156 s32 Alpha(u8 alpha, u32 flags = SDL_SRCALPHA | SDL_RLEACCEL) {return SDL_SetAlpha(surface, flags, alpha);}
157
158 /** Devuelve el alfa asociado a la superficie
159 * @return Alfa de la superficie.
160 */
161 u8 Alpha() {return surface->format->alpha;}
162
163 /** Establece el color transparente y habilita el uso de color transparente en la superficie.
164 * @param key Color transparente.
165 * @return 0 si todo va bien, -1 en caso de error.
166 */
167 s32 ColorKey(u32 key, u32 flags = SDL_SRCCOLORKEY | SDL_RLEACCEL) {return SDL_SetColorKey(surface, flags, key);}
168
169 /** Devuelve el color transparente
170 * @return Color transparente.
171 */
172 u32 ColorKey() {return surface->format->colorkey;}
173
174 /** Pega el contenido de una imagen en esta. No comprueba que
175 * no se sobrepasen los límites de la imagen.
176 * @return <b>true</b> si todo fue bien, <b>false</b> en caso contrario.
177 */
178 bool Paste(JImage *srcImg, s32 xSrc, s32 ySrc, s32 wSrc, s32 hSrc, s32 xDst = 0, s32 yDst = 0);
179
180 /** Devuelve la superficie.
181 * @return Superficie de datos de la imagen.
182 */
183 SDL_Surface * Surface() const {return surface;}
184
185 /** Devuelve el formato de pixel de esta imagen.
186 * @return Formato de pixel de esta imagen.
187 */
188 SDL_PixelFormat * Format() {return surface->format;}
189
190 /** Dibuja la imagen.
191 */
192 virtual void Draw();
193
194 /** Dibuja la imagen en la posición dada.
195 * @param x Posición x en pantalla.
196 * @param y Posición y en pantalla.
197 */
198 virtual void Draw(s32 x, s32 y);
199
200 /** Devuelve el valor del pixel en la posición dada.
201 * La imagen debe estar bloqueada.
202 * @param x Posición x desde la esquina superior izquierda.
203 * @param y Posición y desde la esquina superior izquierda.
204 * @return Color del pixel pedido.
205 */
206 u32 GetPixel(s32 x, s32 y);
207
208 /** Establece el valor del pixel en la posición dada.
209 * La imagen debe estar bloqueada.
210 * @param x Posición x desde la esquina superior izquierda.
211 * @param y Posición y desde la esquina superior izquierda.
212 * @param color Color del pixel dado.
213 */
214 void PutPixel(s32 x, s32 y, u32 color);
215
216 /** Guarda la imagen como BMP
217 * @param file Nombre del fichero donde se guardará.
218 * @return <b>true</b> si todo fue bien, <b>false</b> en caso contrario.
219 */
220 bool SaveAsBMP(const char *file);
221
222 /** Carga la imagen.
223 * @param f Fichero abierto y posicionado para cargar el objeto.
224 * @return 0 si todo va bien, 1 en caso de error de E/S.
225 * 2 en caso de incoherencia de los datos.
226 */
227 virtual u32 Load(JRW &f);
228
229 /** Salva la imagen.
230 * @param f Fichero abierto y posicionado para salvar el objeto.
231 * @return 0 si todo va bien, 1 en caso de error de E/S.
232 * 2 en caso de incoherencia de los datos.
233 */
234 virtual u32 Save(JRW &f);
235
236 /** Carga el objeto desde la posición actual del fichero dado. El objeto debe contener los datos de fichero
237 * en formato de imagen estándar de SDL_Image (TGA, BMP, JPG, etc.)
238 * @param jrw Objeto JRW posicionado correctamente.
239 * @return 0 si todo va bien, 1 en caso de error de E/S.
240 * 2 en caso de incoherencia de los datos.
241 */
242 virtual u32 LoadImage(JRW &jrw);
243
244 /** Crea una referencia de la imagen dada. Los datos apuntan al mismo sitio
245 * y cualquier modificación en una se reflejará en la otra. La imagen no
246 * se destruye hasta que se borran todas las referencias. Si la imagen dada
247 * está vacía, no crea la referencia.
248 */
249 void Ref(JImage &img);
250
251 /** Devuelve una referencia de la imagen asignada. Los datos apuntan al mismo sitio
252 * y cualquier modificación en una se reflejará en la otra. La imagen no
253 * se destruye hasta que se borran todas las referencias. Si la imagen dada
254 * está vacía, no crea la referencia.
255 */
256 void operator =(JImage &img);
257
258 /** Devuelve una copia de la imagen dada. Es equivalente al constructor copia.
259 */
260 void Copy(JImage &img);
261
262 /** Rellena la imagen con el color dado.
263 * @param color Color con el que rellenar.
264 */
265 void Fill(u32 color) {SDL_FillRect(surface, &surface->clip_rect, color);}
266
267 /** Escala la imagen el porcentaje dado en cada dirección. No altera esta imagen.
268 * @param xp Porcentaje de escalado en la dirección x.
269 * @param yp Porcentaje de escalado en la dirección y.
270 * @return Nueva imagen escalada.
271 */
272 JImage * Scale(float xp, float yp);
273
274 /** Convierte esta imagen al formato de la dada. También toma sus flags.
275 * @param fmt Formato de pixel al que convertir.
276 * @param flags Flags a asignar.
277 * @return <b>true</b> si se pudo convertir, <b>false</b> si no.
278 */
279 bool Convert(SDL_PixelFormat *fmt, u32 flags);
280
281 /** Retruns a string with information about this image.
282 * @return String with information about this image.
283 */
284 JString Dump() {return DumpFromSurface(surface);}
285
286 /** Retruns a string with information about an sdl surface.
287 * @return String with information about an sdl surface.
288 */
289 static JString DumpFromSurface(SDL_Surface *s);
290 };
291
292 #endif // _JIMAGE_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Menu en pantalla compuesto de imagénes.
23 * @file JImageMenu.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 28/04/2004
26 * @version 0.0.1 - 28/04/2004 - Primera versión.
27 * @version 0.0.2 - 25/09/2004 - Modificación del método 2D de Pos() para aceptar floats (quita libertad sino).
28 */
29
30 #include <JLib/Graphics/JImageMenu.h>
31
32 bool JImageMenuEntry::Select()
33 {
34 if (Action)
35 {
36 Action(data);
37 return true;
38 }
39
40 return false;
41 }
42
43 JImageMenu::JImageMenu()
44 {
45 curOption = options.NewIterator();
46 }
47
48 void JImageMenu::ApplyLayout(JTree<JImageMenuEntry *>::Iterator *it)
49 {
50 // Si es distribución libre, lo especificarán desde fuera
51 if (config.layout == JIMAGEMENU_FREE)
52 {
53 return;
54 }
55
56 s32 maxX = 0;
57 s32 xOff = 0, yOff = 0;
58
59 // Determina la anchura máxima entre todas las opciones de esta rama
60 do
61 {
62 maxX = maxX < it->Data()->Image()->Width() ? it->Data()->Image()->Width() : maxX;
63
64 // Renderiza los hijos
65 if (it->Child())
66 {
67 ApplyLayout(it);
68 }
69 } while (it->Next());
70
71 it->FirstInBranch();
72
73 // Aplica la distribución de menú
74 do
75 {
76 switch (config.layout)
77 {
78 case JIMAGEMENU_LEFT:
79 it->Data()->Image()->Pos(0, yOff);
80 it->Data()->HiImage()->Pos(0, yOff);
81 yOff += it->Data()->Image()->Height();
82 break;
83
84 case JIMAGEMENU_RIGHT:
85 xOff = -it->Data()->Image()->Width();
86 it->Data()->Image()->Pos(xOff, yOff);
87 it->Data()->HiImage()->Pos(xOff, yOff);
88 yOff += it->Data()->Image()->Height();
89 break;
90
91 case JIMAGEMENU_CENTER:
92 xOff = -(it->Data()->Image()->Width()/2);
93 it->Data()->Image()->Pos(xOff, yOff);
94 it->Data()->HiImage()->Pos(xOff, yOff);
95 yOff += it->Data()->Image()->Height();
96 break;
97
98 case JIMAGEMENU_SAMELINE:
99 it->Data()->Image()->Pos(xOff, 0);
100 it->Data()->HiImage()->Pos(xOff, 0);
101 xOff += it->Data()->Image()->Width();
102 break;
103
104 default:
105 break;
106 }
107 } while (it->Next());
108
109 it->Parent();
110 }
111
112 bool JImageMenu::Init(JImageMenuConfig &cfg)
113 {
114 if (curOption == 0)
115 {
116 // No es una aplicación válida o no se añadieron opciones
117 return false;
118 }
119
120 memcpy(&config, &cfg, sizeof(config));
121
122 // Renderiza las opciones de menú
123 curOption->Root();
124 ApplyLayout(curOption);
125
126 return true;
127 }
128
129 void JImageMenu::Pos(float x, float y)
130 {
131 pos.x = x;
132 pos.y = y;
133 if (curOption)
134 {
135 // Renderiza las opciones de menú
136 curOption->Root();
137 ApplyLayout(curOption);
138 }
139 }
140
141 void JImageMenu::Draw()
142 {
143 JTree<JImageMenuEntry *>::Iterator *it = new JTree<JImageMenuEntry *>::Iterator(*curOption);
144 JImage * img;
145
146 it->FirstInBranch();
147
148 do
149 {
150 // Si es la opción seleccionada muestra su imagen resaltada
151 if (it->Data() == curOption->Data())
152 {
153 img = it->Data()->HiImage();
154 }
155 else
156 {
157 img = it->Data()->Image();
158 }
159
160 img->Draw((s32)(X() + img->X()), (s32)(Y() + img->Y()));
161
162 } while (it->Next());
163
164 delete it;
165 }
166
167 void JImageMenu::TrackKeyboard(SDL_keysym key)
168 {
169 // Actualiza el estado según el teclado
170 if (config.trackKeyboard)
171 {
172 switch (key.sym)
173 {
174 case SDLK_TAB:
175 // SHIFT + TAB
176 if (JApp::App()->KeyMods() & KMOD_SHIFT)
177 {
178 // Opción anterior
179 curOption->Prev();
180 }
181 // TAB
182 else
183 {
184 // Opción siguiente
185 curOption->Next();
186 }
187 break;
188
189 case SDLK_UP:
190 case SDLK_LEFT:
191 // Opción anterior
192 curOption->Prev();
193 break;
194
195 case SDLK_DOWN:
196 case SDLK_RIGHT:
197 // Opción siguiente
198 curOption->Next();
199 break;
200
201 case SDLK_KP_ENTER:
202 case SDLK_RETURN:
203 // Ejecuta la acción asociada
204 if (!curOption->Data()->Select() && config.autoEnter)
205 {
206 // Si no hay acción asociada y se especificó autoEnter, intenta descender
207 // a la opción hija.
208 curOption->Child();
209 }
210 break;
211
212 case SDLK_ESCAPE:
213 // Va a la opción padre.
214 curOption->Parent();
215 break;
216
217 default:
218 break;
219 } // switch (key)
220 } // Track keyboard
221 }
222
223 void JImageMenu::TrackMouse(s32 bt, s32 x, s32 y)
224 {
225 // Actualiza el estado según el ratón
226 if (config.trackMouse)
227 {
228 JTree<JImageMenuEntry *>::Iterator *it = new JTree<JImageMenuEntry *>::Iterator(*curOption);
229 s32 mx, my;
230 bool found = false;
231 mx = JApp::App()->MouseX();
232 my = JApp::App()->MouseY();
233
234 it->FirstInBranch();
235
236 // Comprueba si está sobre alguna opción
237 do
238 {
239 if (mx > it->Data()->Image()->X() + X() &&
240 mx < it->Data()->Image()->X() + X() + it->Data()->Image()->Width() &&
241 my > it->Data()->Image()->Y() + Y() &&
242 my < it->Data()->Image()->Y() + Y() + it->Data()->Image()->Height())
243 {
244 // Está dentro, hace que sea la opción resaltada
245 found = true;
246
247 // Borra el iterador actual
248 delete(curOption);
249
250 curOption = it;
251 }
252 } while (!found && it->Next());
253
254
255 if (found)
256 {
257 // Si ahora está pulsado, activa el flag de pulsación
258 if (bt & SDL_BUTTON_LEFT)
259 {
260 // Ejecuta la acción asociada
261 if (!curOption->Data()->Select() && config.autoEnter)
262 {
263 // Si no hay acción asociada y se especificó autoEnter, intenta descender
264 // a la opción hija.
265 curOption->Child();
266 }
267 }
268 }
269
270 // Si encontró una opción bajo el cursor el iterador sobre esa opción
271 // pasa a ser el iterador de opción actual, no lo borra
272 if (!found)
273 delete it;
274 } // Track mouse
275 }
276
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Menu en pantalla compuesto de imágenes.
23 * @file JImageMenu.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 28/04/2004
26 * @version 0.0.1 - 28/04/2004 - Primera versión.
27 * @version 0.0.2 - 25/09/2004 - Modificación del método 2D de Pos() para aceptar floats (quita libertad sino).
28 */
29
30 #ifndef _JIMAGEMENU_INCLUDED
31 #define _JIMAGEMENU_INCLUDED
32
33 #include <JLib/Graphics/JDrawable.h>
34 #include <JLib/Graphics/JImage.h>
35 #include <JLib/Util/JApp.h>
36 #include <JLib/Util/JString.h>
37 #include <JLib/Util/JTree.h>
38 #include <JLib/Util/JTimer.h>
39
40 /** Distribución del menú.
41 */
42 typedef enum
43 {
44 JIMAGEMENU_LEFT = 1, /**< Alineado a la izquierda. */
45 JIMAGEMENU_RIGHT, /**< Alineado a la derecha. */
46 JIMAGEMENU_CENTER, /**< Centrado. */
47 JIMAGEMENU_SAMELINE, /**< Todas las opciones en la misma línea. */
48 JIMAGEMENU_FREE, /**< Opciones en cualquier posición */
49 } JImageMenuLayout;
50
51 /** Estructura de configuración del menú.
52 */
53 struct JImageMenuConfig
54 {
55 JImageMenuLayout layout; /**< Distribución del menú. */
56 bool trackMouse; /**< Indica si puede manejarse con ratón. */
57 bool trackKeyboard; /**< Indica si puede manejarse con teclado. */
58 bool trackJoystick; /**< Indica si puede manejarse con joystick/pad. */
59 bool autoEnter; /**< Indica si desciende si no hay acción asociada. */
60 };
61
62 /** Opción de menú básica.
63 */
64 class JImageMenuEntry
65 {
66 protected:
67 JImage *image; /**< Imagen asociada a la opción. */
68 JImage *hiImage; /**< Imagen asociada a la opción resaltada. */
69
70 void (*Action)(void *data); /**< Acción asociada a la opción de menú. */
71 void *data; /**< Datos asociados a la opción de menú. */
72
73 public:
74 /** Creates a menu entry.
75 * @param img Image for the item unhighlighted.
76 * @param hiImg Image for the item highlighted.
77 * @param pAct Pointer to function to call when the item is selected.
78 * @param actionData Pointer to additional data to be passed to the action function. In case you want to pass
79 * a value (not a pointer to the value) to store it into the pointer itself, you can use the macros
80 * JCAST_TSS_TO_VOIDPTR in JLib/Util/JTypes.h, where T in TSS is the signedness of the type (S or U)
81 * and SS is the size in bits (8, 16 or 32). Read carefully the comments in that file before using them.
82 */
83 JImageMenuEntry(JImage *img, JImage *hiImg, void (*pAct)(void *) = 0, void *actionData = 0)
84 : image(img), hiImage(hiImg), Action(pAct), data(actionData)
85 {}
86
87 /** Selecciona la opción de menú, llamando a la callback asociada, si existe.
88 * @return <b>true</b> en caso de haber acción asociada, <b>false</b> si no.
89 */
90 bool Select();
91
92 /** Devuelve la imagen asociada.
93 * @return La imagen asociada.
94 */
95 JImage * Image() {return image;}
96
97 /** Devuelve la imagen asociada al estado resaltado.
98 * @return La imagen asociada al estado resaltado.
99 */
100 JImage * HiImage() {return hiImage;}
101
102 /** Destruye el objeto.
103 */
104 ~JImageMenuEntry()
105 {}
106 };
107
108 /** Encapsula un menú de texto en pantalla.
109 */
110 class JImageMenu : public JDrawable
111 {
112 JTree<JImageMenuEntry *> options; /**< Árbol de opciones de menú. */
113 JTree<JImageMenuEntry *>::Iterator *curOption; /**< Opción actual. */
114 JImageMenuConfig config; /**< Parámetros de configuración del menú. */
115
116 /** Aplica la distribución de menú.
117 */
118 void ApplyLayout(JTree<JImageMenuEntry *>::Iterator *it);
119
120 public:
121 /** Crea un menú vacío.
122 */
123 JImageMenu();
124
125 /** Inicializa el menú con la configuración dada. Esta función debe
126 * ser llamada después de haber rellenado el árbol del menú.
127 * @param cfg Configuración del menú.
128 * @return <b>true</b> Si todo fue bien, <b>false</b> si no se encontró la
129 * fuente dada.
130 */
131 bool Init(JImageMenuConfig &cfg);
132
133 /** Devuelve el iterador de opción actual.
134 * @return Iterador de opción actual.
135 */
136 JTree<JImageMenuEntry *>::Iterator * Menu() {return curOption;}
137
138 /** Establece la posición del menú. La alineación se hace respecto de
139 * esta posición.
140 * @param x Posición x.
141 * @param y Posición y.
142 */
143 virtual void Pos(float x, float y);
144
145 /** Función de dibujo del menú.
146 */
147 virtual void Draw();
148
149 /** Procesa tecla arriba
150 */
151 virtual void TrackKeyboard(SDL_keysym key);
152
153 /** Procesa movimiento de mouse
154 */
155 virtual void TrackMouse(s32 bt, s32 x, s32 y);
156
157 /** Destruye el objeto y libera la memoria asociada.
158 */
159 virtual ~JImageMenu()
160 {
161 for (options.Begin(); options.End(); options.Next())
162 JDELETE(options.Cur());
163
164 options.Clear();
165 }
166 };
167
168 #endif // _JIMAGEMENU_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Sprite de imágenes.
23 * @file JImageSprite.cpp.
24 * @author Juan Carlos Seijo Pérez.
25 * @date 18/10/2003.
26 * @version 0.0.1 - 18/10/2003 - Primera versión.
27 * @version 0.0.2 - 01/06/2004 - Adición de método de copia.
28 */
29
30 #include <JLib/Graphics/JImageSprite.h>
31
32 // Constructor copia
33 JImageSprite::JImageSprite(JImageSprite &spr)
34 : wMax(0), hMax(0)
35 {
36 Ref(spr);
37 }
38
39 // Carga el sprite desde un fichero.
40 // Si frameW != 0 y frameH == 0, considera que las frames están en horizontal.
41 // Si frameW == 0 y frameH != 0, considera que las frames están en vertical.
42 // Si frameW != 0 y frameH != 0, intenta encajarlas en H o V, si no intenta encajar los cuadrados.
43 // Si frameW == 0 y frameH == 0 o hay una incoherencia o un error, devuelve false.
44 // Si todo va bien, devuelve true.
45 bool JImageSprite::Load(const JString &fileName, u32 frameW, u32 frameH, u32 _numFrames, u32 colorKey)
46 {
47 Destroy();
48
49 JImage img;
50 wMax = 0;
51 hMax = 0;
52
53 if (!img.Load(fileName))
54 return false;
55
56 if (_numFrames != 0)
57 {
58 numFrames = _numFrames;
59 }
60
61 // Para recorrer la imagen
62 u32 iMax, jMax;
63
64 if (frameW == 0)
65 {
66 if (frameH == 0)
67 {
68 return false;
69 }
70 else
71 {
72 // Frames en vertical.
73 if (numFrames == 0)
74 {
75 // Averigua las que caben en la altura de la imagen...
76 s32 mod = img.Height() % frameH;
77 s32 numFr = img.Height()/frameH;
78
79 // ERROR: No hay un número entero de frames
80 if (mod != 0)
81 return false;
82
83 numFrames = numFr;
84 }
85
86 // Límites de recorrido de la imagen
87 iMax = 1;
88 jMax = numFrames;
89 frameW = img.Width();
90 }
91 }
92 else
93 {
94 if (frameH == 0)
95 {
96 // Frames en horizontal.
97 if (numFrames == 0)
98 {
99 // Averigua las que caben en la anchura de la imagen...
100 s32 mod = img.Width() % frameW;
101 s32 numFr = img.Width()/frameW;
102
103 // ERROR: No hay un número entero de frames
104 if (mod != 0)
105 return false;
106
107 numFrames = numFr;
108 }
109
110 // Límites de recorrido de la imagen
111 iMax = numFrames;
112 jMax = 1;
113 frameH = img.Height();
114 }
115 else
116 {
117 // Frames con ancho y alto.
118 // Las supone dispuestas en un cuadrado de (n x frameW) x (m x frameH).
119 s32 modi, modj;
120 modi = img.Width()%frameW;
121 modj = img.Height()%frameH;
122
123 // ERROR: No hay un número entero de frames
124 if (modi != 0 || modj != 0)
125 return false;
126
127 iMax = img.Width()/frameW;
128 jMax = img.Height()/frameH;
129
130 // Si no se da el número de frames se asumen n x m
131 if (numFrames == 0)
132 {
133 numFrames = iMax * jMax;
134 }
135 }
136
137 frames = (JDrawable**)new JImage*[numFrames];
138
139 JImage *tmpImg;
140
141 // Extrae los frames del sprite de la imagen
142 for (u32 j = 0, count = 0; j < jMax && count < numFrames; ++j)
143 {
144 for (u32 i = 0; i < iMax && count < numFrames; ++i, ++count)
145 {
146 frames[(j * iMax) + i] = tmpImg = new JImage(frameW, frameH);
147 tmpImg->Paste(&img, i * frameW, j * frameH, frameW, frameH);
148 tmpImg->ColorKey(colorKey);
149 }
150 }
151
152 // Tamaño fijo de frame
153 wMax = frameW;
154 hMax = frameH;
155
156 return true;
157 }
158
159 return false;
160 }
161
162 // Crea el sprite a partir varios ficheros de imagen, uno por frame.
163 // Si todo va bien, devuelve true.
164 bool JImageSprite::Load(JString *imageFiles, u32 _numFrames, u32 colorKey)
165 {
166 Destroy();
167
168 bool error = false;
169 wMax = hMax = 0;
170 numFrames = _numFrames;
171 JImage *tmpImg;
172 frames = (JDrawable**)new JImage*[numFrames];
173 u32 i;
174
175 for (i = 0; i < numFrames && !error; ++i)
176 {
177 frames[i] = tmpImg = new JImage();
178
179 if (tmpImg->Load(imageFiles[i]))
180 {
181 tmpImg->ColorKey(colorKey);
182
183 // Asigna la anchura y altura máximas del sprite
184 if (wMax < tmpImg->Width())
185 wMax = tmpImg->Width();
186
187 if (hMax < tmpImg->Height())
188 hMax = tmpImg->Height();
189 }
190 else
191 {
192 delete tmpImg;
193 error = true;
194 }
195 }
196
197 if (error)
198 {
199 // Error al cargar
200 for (u32 j = 0; j < i; ++j)
201 {
202 delete frames[i];
203 frames[i] = 0;
204 }
205 }
206
207 return !error;
208 }
209
210 // Dibuja el sprite en pantalla
211 void JImageSprite::Draw()
212 {
213 SDL_Rect rc;
214 rc.x = (s16)(X() + frames[curFrame]->X());
215 rc.y = (s16)(Y() + frames[curFrame]->Y());
216
217 SDL_BlitSurface(((JImage *)frames[curFrame])->Surface(), 0, SDL_GetVideoSurface(), &rc);
218 }
219
220 // Utilidad para alinear arriba los frames del sprite
221 void JImageSprite::AlignUp()
222 {
223 for (u32 i = 0; i < numFrames; ++i)
224 {
225 frames[i]->Pos((s32)frames[i]->X(), 0);
226 }
227 }
228
229 // Utilidad para alinear abajo los frames del sprite
230 void JImageSprite::AlignDown()
231 {
232 for (u32 i = 0; i < numFrames; ++i)
233 {
234 frames[i]->Pos((s32)frames[i]->X(), (s32)(hMax - ((JImage*)frames[i])->Height()));
235 }
236 }
237
238 // Utilidad para alinear a la izquierda los frames del sprite
239 void JImageSprite::AlignLeft()
240 {
241 for (u32 i = 0; i < numFrames; ++i)
242 {
243 frames[i]->Pos(0, (s32)frames[i]->Y());
244 }
245 }
246
247 // Utilidad para alinear derecha los frames del sprite
248 void JImageSprite::AlignRight()
249 {
250 for (u32 i = 0; i < numFrames; ++i)
251 {
252 frames[i]->Pos((s32)(wMax - ((JImage*)frames[i])->Width()), (s32)frames[i]->Y());
253 }
254 }
255
256 // Utilidad para ajustar al máximo el borde del sprite
257 void JImageSprite::AdjustSize()
258 {
259 bool done;
260 s32 x, y, w, h;
261 s32 du = 0, dd = 0, dl = 0, dr = 0; // Cantidad de borde sobrante
262 JImage *img = 0, *tmpImg = 0;
263 SDL_Rect rc;
264
265 // Anchura y altura máximas del sprite
266 wMax = hMax = 0;
267
268 for (u32 n = 0; n < numFrames; ++n)
269 {
270 img = (JImage *)frames[n];
271 if (0 == img->Lock())
272 {
273 w = img->Width();
274 h = img->Height();
275
276 // Calcula por arriba
277 done = false;
278 for (y = 0; y < h && !done; ++y)
279 {
280 for (x = 0; x < w && !done; ++x)
281 {
282 if (img->GetPixel(x, y) != img->ColorKey())
283 done = true;
284 }
285 }
286
287 du = y - 1;
288
289 // Calcula por abajo
290 done = false;
291 for (y = h - 1; y >= 0 && !done; --y)
292 {
293 for (x = 0; x < w && !done; ++x)
294 {
295 if (img->GetPixel(x, y) != img->ColorKey())
296 done = true;
297 }
298 }
299
300 dd = h - 1 - y - 1;
301
302 // Calcula por la izquierda
303 done = false;
304 for (x = 0; x < w && !done; ++x)
305 {
306 for (y = 0; y < h && !done; ++y)
307 {
308 if (img->GetPixel(x, y) != img->ColorKey())
309 done = true;
310 }
311 }
312
313 dl = x - 1;
314
315 // Calcula por la derecha
316 done = false;
317 for (x = w - 1; x >= 0 && !done; --x)
318 {
319 for (y = 0; y < h && !done; ++y)
320 {
321 if (img->GetPixel(x, y) != img->ColorKey())
322 done = true;
323 }
324 }
325
326 dr = w - 1 - x - 1;
327
328 rc.x = (s16)dl;
329 rc.y = (s16)du;
330 rc.w = (u16)(w - dl - dr);
331 rc.h = (u16)(h - du - dd);
332
333 if (wMax < rc.w)
334 wMax = rc.w;
335
336 if (hMax < rc.h)
337 hMax = rc.h;
338
339 img->Unlock();
340
341 // Si no hay cambios lo deja
342 if (rc.w < w || rc.h < h)
343 {
344 // Reduce el area de la imagen
345 tmpImg = new JImage(rc.w, rc.h, img->BitsPP());
346 tmpImg->Paste(img, rc.x, rc.y, rc.w, rc.h);
347 tmpImg->ColorKey(img->ColorKey());
348
349 // Actualiza la posición relativa del frame dentro del sprite
350 // para no alterarla
351 tmpImg->Pos((s32)(tmpImg->X() + rc.x), (s32)(tmpImg->Y() + rc.y));
352
353 delete frames[n];
354 frames[n] = tmpImg;
355 }
356 }
357 }
358 }
359
360 // Carga el sprite.
361 u32 JImageSprite::Load(JRW &f)
362 {
363 if (f.ReadLE32(&fps) &&
364 f.ReadLE32(&numFrames) &&
365 f.ReadBool(&loop) &&
366 f.ReadBool(&goBack) &&
367 f.ReadBool(&backwards))
368 {
369 JImage *img;
370 s32 xPos, yPos;
371 u32 ok = 0;
372 u32 i;
373
374 frames = (JDrawable**)new JImage*[this->numFrames];
375
376 for (i = 0; i < numFrames && ok == 0; ++i)
377 {
378 frames[i] = img = new JImage;
379
380 // Carga las coordenadas relativas del frame
381 if (0 == f.ReadLE32(&xPos) ||
382 0 == f.ReadLE32(&yPos))
383 {
384 ok = 1; // Fallo de lectura
385 }
386 else
387 {
388 img->Pos(xPos, yPos);
389
390 // Carga la imagen
391 ok |= ((JImage *)frames[i])->Load(f);
392 if (ok == 0)
393 {
394 // Asigna la anchura y altura máximas del sprite
395 if (wMax < ((JImage *)frames[i])->Width())
396 wMax = ((JImage *)frames[i])->Width();
397
398 if (hMax < ((JImage *)frames[i])->Height())
399 hMax = ((JImage *)frames[i])->Height();
400 }
401 }
402 }
403
404 if (ok == 0)
405 {
406 Init(numFrames, fps, loop, goBack, backwards);
407 }
408 else
409 {
410 // Borra lo creado si hubo un error
411 for (u32 j = 0; j < i; ++j)
412 {
413 delete frames[j];
414 }
415
416 delete[] frames;
417 frames = 0;
418 }
419
420 return ok;
421 }
422
423 return 1;
424 }
425
426 // Salva el sprite
427 u32 JImageSprite::Save(JRW &f)
428 {
429 if (f.WriteLE32(&fps) &&
430 f.WriteLE32(&numFrames) &&
431 f.WriteBool(&loop) &&
432 f.WriteBool(&goBack) &&
433 f.WriteBool(&backwards))
434 {
435 JImage *img;
436 s32 xPos, yPos;
437
438 u32 ok = 0;
439
440 for (u32 i = 0; i < numFrames; ++i)
441 {
442 img = ((JImage *)frames[i]);
443
444 // Salva las coordenadas relativas del frame
445 xPos = (s32)img->X();
446 yPos = (s32)img->Y();
447 f.WriteLE32(&xPos);
448 f.WriteLE32(&yPos);
449
450 ok |= img->Save(f);
451 }
452
453 return ok;
454 }
455
456 return 1;
457 }
458
459 void JImageSprite::Ref(JImageSprite& spr)
460 {
461 Destroy();
462
463 Init(spr.NumFrames(), spr.FPS(), spr.Loop(), spr.GoBack(), spr.Backwards());
464 paused = spr.Paused();
465 wMax = spr.MaxW();
466 hMax = spr.MaxH();
467
468 frames = (JDrawable**)new JImage*[spr.NumFrames()];
469
470 // Referencia los frames del sprite
471 for (u32 i = 0; i < numFrames; ++i)
472 {
473 frames[i] = new JImage;
474 ((JImage *)frames[i])->Ref(*((JImage *)spr.Frame(i)));
475 }
476 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Sprite de imágenes.
23 * @file JImageSprite.h
24 * @author Juan Carlos Seijo Pérez.
25 * @date 18/10/2003.
26 * @version 0.0.1 - 18/10/2003 - Primera versión.
27 * @version 0.0.2 - 01/06/2004 - Adición de método de copia.
28 */
29
30 #ifndef _JIMAGESPRITE_INCLUDED
31 #define _JIMAGESPRITE_INCLUDED
32
33 #include <JLib/Util/JTypes.h>
34 #include <JLib/Graphics/JImage.h>
35 #include <JLib/Util/JString.h>
36 #include <JLib/Util/JLoadSave.h>
37 #include <JLib/Graphics/JSprite.h>
38
39 /** Sprite de imágenes.
40 */
41 class JImageSprite : public JSprite
42 {
43 protected:
44 s32 wMax; /**< Anchura del frame mayor. */
45 s32 hMax; /**< Altura del frame mayor. */
46
47 public:
48 /** Crea el objeto.
49 */
50 JImageSprite() : JSprite(), wMax(0), hMax(0) {}
51
52 /** Crea un sprite de imágenes a partir de otro dado.
53 */
54 JImageSprite(JImageSprite &spr);
55
56 /** Carga el sprite desde un fichero.
57 * Si _numFrames == 0 toma las que tenga internamente (0 por defecto).
58 * Si frameW != 0 y frameH == 0, considera que las frames están en horizontal.
59 * Si frameW == 0 y frameH != 0, considera que las frames están en vertical.
60 * Si frameW != 0 y frameH != 0, intenta encajarlas en H o V, si no intenta encajar los cuadrados.
61 * Si frameW == 0 y frameH == 0 o numFrames == 0 o hay una incoherencia o un error, devuelve false.
62 * @param fileName Nombre del fichero.
63 * @param frameW Anchura de cuadro.
64 * @param frameH Altura de cuadro.
65 * @param _numFrames Número de frames.
66 * @param colorKey Color transparente.
67 * @return Si todo va bien, devuelve <b>true</b>, si no, false.
68 */
69 bool Load(const JString &fileName, u32 frameW, u32 frameH = 0, u32 _numFrames = 0, u32 colorKey = 0x00000000);
70
71 /** Carga el sprite desde varios ficheros de imágenes.
72 * @param imageFiles Array con los nombres de los ficheros.
73 * @param _numFrames Número de ficheros (frames) del sprite.
74 * @param colorKey Color transparente.
75 * Si todo va bien, devuelve true.
76 */
77 bool Load(JString *imageFiles, u32 _numFrames, u32 colorKey = 0x00000000);
78
79 /** Dibuja el sprite en pantalla.
80 */
81 virtual void Draw();
82
83 /** Alinea arriba los frames del sprite.
84 */
85 void AlignUp();
86
87 /** Alinear abajo los frames del sprite.
88 */
89 void AlignDown();
90
91 /** Alinea a la izquierda los frames del sprite.
92 */
93 void AlignLeft();
94
95 /** Alinea a la derecha los frames del sprite.
96 */
97 void AlignRight();
98
99 /** Ajusta al máximo el borde del sprite.
100 */
101 void AdjustSize();
102
103 /** Devuelve la anchura máxima.
104 * @return Anchura máxima.
105 */
106 s32 MaxW() const {return wMax;}
107
108 /** Devuelve la altura máxima.
109 * @return Altura máxima.
110 */
111 s32 MaxH() const {return hMax;}
112
113 /** Devuelve el frame actual en forma de Image.
114 * @return Frame actual en forma de image.
115 */
116 JImage * CurImage() {return (JImage *)frames[curFrame];}
117
118 /** Carga el sprite.
119 * @param f Fichero posicionado para cargar el sprite.
120 * @return 0 si todo fue bien, 1 en caso de error de E/S, 2 en caso
121 * de error en los datos.
122 */
123 u32 Load(JRW &f);
124
125 /** Salva el sprite.
126 * @param f Fichero posicionado para salvar el sprite.
127 * @return 0 si todo fue bien, 1 en caso de error de E/S, 2 en caso
128 * de error en los datos.
129 */
130 u32 Save(JRW &f);
131
132 /** Libera la memoria asociada.
133 */
134 virtual ~JImageSprite(){}
135
136 /** Crea una referencia del sprite dado. Las imagenes se referencian, de forma que no
137 * se crea una copia de las mismas, ocupan la misma memoria. Es equivalente al
138 * constructor copia.
139 */
140 void Ref(JImageSprite &);
141 };
142
143 #endif // _JIMAGESPRITE_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Etiquetas de ficheros J3D
23 * @file JJ3DFormat.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 20/09/2003
26 * @version 0.0.1 - 20/09/2003 - Primera versión.
27 */
28
29 #ifndef _JJ3DFORMAT_INCLUDED
30 #define _JJ3DFORMAT_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Util/JObject.h>
34
35 // Tags del formato J3D. Son las cadenas a utilizar por scanf más adelante.
36
37 /** Cabecera de fichero. */
38 #define JJ3DTAG_TEXT_FILE_HEADER "J3DT"
39
40 /** Cabecera de fichero. */
41 #define JJ3DTAG_BIN_FILE_HEADER "J3DB"
42
43 /** La versión para la que se hace, no cuenta para validar el ase. */
44 #define JJ3DTAG_FILE_VERSION "0100"
45
46 /** Escena. */
47 #define JJ3DTAG_SCENE "*SCENE"
48 /** Ordinal del primer cuadro. */
49 #define JJ3DTAG_SCENE_FIRSTFRAME "*SCENE_FIRSTFRAME"
50 /** Ordinal del último cuadro. */
51 #define JJ3DTAG_SCENE_LASTFRAME "*SCENE_LASTFRAME"
52 /** Lista de materiales. */
53 #define JJ3DTAG_MATERIAL_LIST "*MATERIAL_LIST"
54 /** Número de materiales. */
55 #define JJ3DTAG_MATERIAL_COUNT "*MATERIAL_COUNT"
56 /** Material. */
57 #define JJ3DTAG_MATERIAL "*MATERIAL"
58 /** Núemro de submateriales. */
59 #define JJ3DTAG_SUBMATERIAL_COUNT "*NUMSUBMTLS"
60 /** Submaterial. */
61 #define JJ3DTAG_SUBMATERIAL "*SUBMATERIAL"
62 /** Tipo de material. */
63 #define JJ3DTAG_MATERIAL_CLASS "*MATERIAL_CLASS"
64 /** Material Multi/sub-objeto. */
65 #define JJ3DVAL_MULTI_SUBOBJECT "\"Multi/Sub-Object\""
66 /** Material estándar. */
67 #define JJ3DVAL_STANDARD "\"Standard\""
68 /** Color ambiente del material. */
69 #define JJ3DTAG_MATERIAL_AMBIENT "*MATERIAL_AMBIENT"
70 /** Color difuso del material. */
71 #define JJ3DTAG_MATERIAL_DIFFUSE "*MATERIAL_DIFFUSE"
72 /** Color especular del material. */
73 #define JJ3DTAG_MATERIAL_SPECULAR "*MATERIAL_SPECULAR"
74 /** Flag de brillo del material. */
75 #define JJ3DTAG_MATERIAL_SHINE "*MATERIAL_SHINE"
76 /** Intensidad de brillo del material. */
77 #define JJ3DTAG_MATERIAL_SHINESTRENGTH "*MATERIAL_SHINESTRENGTH"
78 /** Transparencia del material. */
79 #define JJ3DTAG_MATERIAL_TRANSPARENCY "*MATERIAL_TRANSPARENCY"
80 /** Iluminación propia. */
81 #define JJ3DTAG_MATERIAL_SELFILLUM "*MATERIAL_SELFILLUM"
82 /** Tipo XP. */
83 #define JJ3DTAG_MATERIAL_XP_TYPE "*MATERIAL_XP_TYPE"
84 /** Mapa difuso del material. */
85 #define JJ3DTAG_MATERIAL_MAP_DIFFUSE "*MAP_DIFFUSE"
86 /** Subnúmero del mapa del material. */
87 #define JJ3DTAG_MATERIAL_MAP_SUBNO "*MAP_SUBNO"
88 /** Textura del material. */
89 #define JJ3DTAG_MATERIAL_BITMAP "*BITMAP"
90 /** Objeto. */
91 #define JJ3DTAG_GEOMOBJECT "*GEOMOBJECT"
92 /** Nombre. */
93 #define JJ3DTAG_NODE_NAME "*NODE_NAME"
94 /** Geometría. */
95 #define JJ3DTAG_MESH "*MESH"
96 /** Tiempo dentro de la animación. */
97 #define JJ3DTAG_TIMEVALUE "*TIMEVALUE"
98 /** Númerod evértices. */
99 #define JJ3DTAG_MESH_NUMVERTEX "*MESH_NUMVERTEX"
100 /** Número de caras. */
101 #define JJ3DTAG_MESH_NUMFACES "*MESH_NUMFACES"
102 /** Lista de vértices. */
103 #define JJ3DTAG_MESH_VERTEX_LIST "*MESH_VERTEX_LIST"
104 /** Vértice. */
105 #define JJ3DTAG_MESH_VERTEX "*MESH_VERTEX"
106 /** Lista de caras. */
107 #define JJ3DTAG_MESH_FACE_LIST "*MESH_FACE_LIST"
108 /** Cara. */
109 #define JJ3DTAG_MESH_FACE "*MESH_FACE"
110 /** Primer vértice. */
111 #define JJ3DTAG_MESH_A "A:"
112 /** Segundo vértice. */
113 #define JJ3DTAG_MESH_B "B:"
114 /** Tercer vértice. */
115 #define JJ3DTAG_MESH_C "C:"
116 /** ID del material asociado. */
117 #define JJ3DTAG_MESH_MTLID "*MESH_MTLID"
118 /** Núemro de vértices con textura. */
119 #define JJ3DTAG_MESH_NUMTVERTEX "*MESH_NUMTVERTEX"
120 /** Lista de vértices con textura. */
121 #define JJ3DTAG_MESH_TVERTLIST "*MESH_TVERTLIST"
122 /** Vértice con textura. */
123 #define JJ3DTAG_MESH_TVERT "*MESH_TVERT"
124 /** Número de caras con textura. */
125 #define JJ3DTAG_MESH_NUMTVFACES "*MESH_NUMTVFACES"
126 /** Lista de caras con textura. */
127 #define JJ3DTAG_MESH_TFACELIST "*MESH_TFACELIST"
128 /** Cara con textura. */
129 #define JJ3DTAG_MESH_TFACE "*MESH_TFACE"
130 /** Lista de normales. */
131 #define JJ3DTAG_MESH_NORMALS "*MESH_NORMALS"
132 /** Normales de cara. */
133 #define JJ3DTAG_MESH_FACENORMAL "*MESH_FACENORMAL"
134 /** Normales de vértice. */
135 #define JJ3DTAG_MESH_VERTEXNORMAL "*MESH_VERTEXNORMAL"
136 /** Núemro de material. */
137 #define JJ3DTAG_MATERIAL_REF "*MATERIAL_REF"
138
139 #endif // _JJ3DFORMAT_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Sprite genérico.
23 * @file JSprite.cpp.
24 * @author Juan Carlos Seijo Pérez.
25 * @date 18/10/2003.
26 * @version 0.0.1 - 18/10/2003 - Primera versión.
27 */
28
29 #include <JLib/Graphics/JSprite.h>
30
31 // Inicializa el sprite con los parámetros dados. No crea el array de frames,
32 // puesto que lo debe hacer la clase hija.
33 void JSprite::Init(u32 nFrames, u32 _FPS, bool mustLoop, bool mustGoBack, bool mustGoBackwards)
34 {
35 if (nFrames)
36 numFrames = nFrames;
37
38 loop = mustLoop;
39 goBack = mustGoBack;
40 backwards = mustGoBackwards;
41
42 if (backwards)
43 {
44 firstFrame = numFrames - 1;
45 lastFrame = 0;
46 frameAdvance = -1;
47 }
48 else
49 {
50 firstFrame = 0;
51 lastFrame = numFrames - 1;
52 frameAdvance = 1;
53 }
54
55 curFrame = firstFrame;
56
57 FPS(_FPS);
58 }
59
60 // Pasa al siguiente frame si han pasado 1/fps segundos.
61 // Devuelve el frame actual si ha cambiado, -1 si no cambió
62 // y -2 si está en pausa.
63 s32 JSprite::Update()
64 {
65 if (!paused)
66 {
67 if (timer.Changed())
68 {
69 // Cambia de frame
70 if (curFrame == lastFrame)
71 {
72 if (loop)
73 {
74 // Si debe volver cambia el sentido
75 if (goBack)
76 {
77 s32 tmp;
78 tmp = lastFrame;
79 lastFrame = firstFrame;
80 firstFrame = tmp;
81
82 frameAdvance *= -1;
83 curFrame += frameAdvance;
84
85 return curFrame;
86 }
87 else
88 {
89 curFrame = firstFrame;
90
91 return curFrame;
92 }
93 }
94
95 return -1;
96 }
97 else
98 {
99 curFrame += frameAdvance;
100
101 return curFrame;
102 }
103 }
104 }
105
106 return -2;
107 }
108
109 // Establece el número de cuadros por segundo
110 void JSprite::FPS(const u32 newFPS)
111 {
112 fps = newFPS;
113
114 if (fps)
115 timer.Start(1000L/fps);
116 else
117 timer.Pause();
118 }
119
120 // Va al frame anterior
121 bool JSprite::PrevFrame()
122 {
123 if (curFrame > 0)
124 {
125 --curFrame;
126 return true;
127 }
128
129 return false;
130 }
131
132 // Va al frame siguiente
133 bool JSprite::NextFrame()
134 {
135 if (curFrame < numFrames - 1)
136 {
137 ++curFrame;
138 return true;
139 }
140
141 return false;
142 }
143
144 // Destruye el sprite, liberando la memoria asociada
145 void JSprite::Destroy()
146 {
147 if (frames)
148 {
149 for (u32 i = 0; i < numFrames; ++i)
150 {
151 JDELETE(frames[i]);
152 }
153
154 delete[] frames;
155 frames = 0;
156 }
157 }
158
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Sprite genérico.
23 * @file JSprite.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 18/10/2003
26 * @version 0.0.1 - 18/10/2003 - Primera versión.
27 * @note
28 * <pre>
29 * Combinaciones de loop, goBack y backwards (L,G,B)
30 *
31 * Tiempo 0 1 2 3 4 ...
32 * Frame 123 123 123
33 *
34 * Loop(false), GoBack(false), Backwards(false)
35 * Sprite o-- -o- --o --o --o ...
36 *
37 * Loop(false), GoBack(false), Backwards(true)
38 * --o -o- o-- o-- o-- ...
39 *
40 * Loop(true), GoBack(false), Backwards(false)
41 * o-- -o- --o o-- -o- ...
42 *
43 * Loop(true), GoBack(true), Backwards(false)
44 * o-- -o- --o -o- o-- -o- --o -o- ...
45 *
46 * Loop(true), GoBack(false), Backwards(true)
47 * --o -o- o-- --o -o- o-- --o ...
48 *
49 * Loop(true), GoBack(true), Backwards(true)
50 * --o -o- o-- -o- --o -o- o-- ...
51 *
52 * (No tiene efecto activar GoBack sin Loop.)
53 * </pre>
54 */
55
56 #ifndef _JSPRITE_INCLUDED
57 #define _JSPRITE_INCLUDED
58
59 #include <JLib/Util/JTypes.h>
60 #include <JLib/Util/JUtil.h>
61 #include <JLib/Graphics/JDrawable.h>
62 #include <JLib/Util/JTimer.h>
63 #include <JLib/Util/JFile.h>
64 #include <JLib/Util/JLoadSave.h>
65
66 /** Sprite genérico.
67 */
68 class JSprite : public JDrawable
69 {
70 protected:
71 JTimer timer; /**< Cronómetro del sprite */
72 u32 fps; /**< Cuadros por segundo */
73 u32 numFrames; /**< Número de cuadros */
74 JDrawable **frames; /**< Cuadros */
75 u32 lastFrame; /**< Último cuadro */
76 u32 firstFrame; /**< Primer cuadro */
77 s32 frameAdvance; /**< Incremento de frame */
78 u32 curFrame; /**< Índice del cuadro actual */
79 bool loop; /**< ¿Debe iniciar desde donde empezó? */
80 bool goBack; /**< ¿Debe volver hacia atrás cuando llegue al final? */
81 bool backwards; /**< ¿Debe ir siempre hacia atrás? */
82 bool paused; /**< ¿Debe pausar? */
83
84 public:
85 /** Crea un sprite vacío. Se debe usar init para inicializarlo.
86 */
87 JSprite() : fps(1), numFrames(0), frames(0), lastFrame(0), firstFrame(0),
88 frameAdvance(0), curFrame(0), loop(false), goBack(false), backwards(false), paused(false)
89 {}
90
91 /** Inicializa el sprite con los parámetros dados. No crea el array de frames,
92 * puesto que lo debe hacer la clase hija.
93 * @param nFrames Número de frames del sprite.
94 * @param _FPS Velocidad en cuadros por segundo.
95 * @param mustLoop Indicador de repetición.
96 * @param mustGoBack Indicador de sentido invertido.
97 * @param mustGoBackwards Indicador de vuelta al comienzo.
98 */
99 void Init(u32 nFrames, u32 _FPS, bool mustLoop = false, bool mustGoBack = false, bool mustGoBackwards = false);
100
101 /** Pasa al siguiente frame si han pasado 1/fps segundos.
102 * @return El nº de frame actual si ha cambiado, -1 si no cambió
103 * y -2 si está en pausa.
104 */
105 s32 Update();
106
107 /** Dibuja el sprite. Las x, y del sprite dan la posición global; las x, y de cada frame,
108 * el offset rpto. a la posición global
109 */
110 virtual void Draw() {frames[curFrame]->Draw();}
111
112 /** Destruye el sprite, liberando la memoria asociada.
113 */
114 void Destroy();
115
116 /** Destruye el sprite, liberando la memoria asociada.
117 */
118 virtual ~JSprite() {Destroy();}
119
120 /** Devuelve el número de cuadros por segundo.
121 * @return Número de cuadros por segundo.
122 */
123 const u32 FPS() {return fps;}
124
125 /** Establece el número de cuadros por segundo.
126 * @param newFPS Número de cuadros por segundo.
127 */
128 void FPS(const u32 newFPS);
129
130 /** Devuelve el número de cuadros totales en el sprite.
131 @return Número de cuadros totales en el sprite.
132 */
133 const u32 NumFrames() {return numFrames;}
134
135 /** Devuelve el índice del cuadro actual.
136 * @return Índice del cuadro actual.
137 */
138 const u32 CurFrame() {return curFrame;}
139
140 /** Establece el índice del cuadro actual.
141 * @param newFrame Índice del cuadro actual.
142 */
143 void CurFrame(const u32 newFrame)
144 {
145 if (newFrame >= 0 && newFrame < numFrames) curFrame = newFrame;
146 }
147
148 /** Devuelve el frame en la posición indicada.
149 * @param i Índice del frame a recuperar.
150 * @return Frame en la posición i.
151 */
152 JDrawable * Frame(u32 i) {return frames[i];}
153
154 /** Determina si debe volver al comienzo.
155 * @return <b>true</b> si al llegar al final el sprite vuelve al comienzo,
156 * <b>false</b> si no.
157 */
158 bool Loop() {return loop;}
159
160 /** Establece si al llegar al final, el sprite vuelve al comienzo
161 * @param mustLoop Nuevo valor de la propiedad.
162 */
163 void Loop(bool mustLoop) {loop = mustLoop;}
164
165 /** Determina si debe volver al comienzo.
166 * @return <b>true</b> si debe volver hacia atrás cuando llegue al final, <b>false</b> si no.
167 */
168 bool GoBack() {return goBack;}
169
170 /** Establece si debe volver al comienzo.
171 * @param mustGoBack <b>true</b> si debe volver hacia atrás cuando llegue al final, <b>false</b> si no.
172 */
173 void GoBack(bool mustGoBack) {goBack = mustGoBack;}
174
175 /** Determina si debe ir hacia atrás.
176 * @return <b>true</b> si debe ir siempre hacia atrás, <b>false</b> si no.
177 */
178 bool Backwards() {return backwards;}
179
180 /** Establece si debe ir siempre hacia atrás.
181 * @param mustGoBackwards <b>true</b> si debe ir hacia atrás, <b>false</b> si no.
182 */
183 void Backwards(bool mustGoBackwards) {backwards = mustGoBackwards;}
184
185 /** Pausa o reanuda la animación.
186 * @param pause <b>true</b> para pausarla, <b>false</b> para reanudarla.
187 */
188 void Paused(bool pause) {paused = pause;}
189
190 /** Determina si están en pausa la animación.
191 * @return <b>true</b> si está en pausa, <b>false</b> si no.
192 */
193 bool Paused() {return paused;}
194
195 /** Va al frame anterior.
196 * @return <b>true</b> si había frame anterior, <b>false</b> si no.
197 */
198 bool PrevFrame();
199
200 /** Va al frame siguiente
201 * @return <b>true</b> si había frame posterior, <b>false</b> si no.
202 */
203 bool NextFrame();
204
205 /** Va al primer frame.
206 */
207 void FirstFrame() {curFrame = firstFrame;}
208
209 /** Va al último frame
210 */
211 void LastFrame() {curFrame = lastFrame;}
212 };
213
214 #endif // _JSPRITE_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Menu en pantalla compuesto de cadenas de texto.
23 * @file JTextMenu.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 28/03/2004
26 * @version 0.0.1 - 28/03/2004 - Primera versión.
27 */
28
29 #include <JLib/Graphics/JTextMenu.h>
30
31 bool JTextMenuEntry::Init(JTextMenuConfig &cfg)
32 {
33 // Borra posibles imágenes anteriores
34 Destroy();
35
36 // Renderiza según el tipo elegido
37 switch (cfg.renderMode)
38 {
39 default:
40 case JTEXTMENU_SOLID:
41 image = cfg.font->RenderTextSolid(text, cfg.color);
42 hiImage = cfg.font->RenderTextSolid(text, cfg.hiColor);
43 break;
44
45 case JTEXTMENU_SHADED:
46 image = cfg.font->RenderTextShaded(text, cfg.color, cfg.backColor);
47 hiImage = cfg.font->RenderTextShaded(text, cfg.hiColor, cfg.hiBackColor);
48 break;
49
50 case JTEXTMENU_BLENDED:
51 image = cfg.font->RenderTextBlended(text, cfg.color);
52 hiImage = cfg.font->RenderTextBlended(text, cfg.hiColor);
53 break;
54 }
55
56 if (image != 0 && hiImage != 0)
57 return true;
58
59 return false;
60 }
61
62 bool JTextMenuEntry::Select()
63 {
64 if (Action)
65 {
66 Action(data);
67 return true;
68 }
69
70 return false;
71 }
72
73
74 JTextMenu::JTextMenu()
75 {
76 curOption = options.NewIterator();
77 maxW = maxH = 0;
78 }
79
80 void JTextMenu::ApplyLayout(JTree<JTextMenuEntry *>::Iterator *it)
81 {
82 s32 xOff = 0, yOff = 0;
83 s32 localW = 0, localH = 0;
84
85 do
86 {
87 // Determina la anchura y altura máximas entre todas las opciones de esta rama
88 if (config.layout != JTEXTMENU_SAMELINE)
89 {
90 xOff = it->Data()->Image()->Width();
91 }
92 else
93 {
94 xOff += it->Data()->Image()->Width();
95 }
96
97 if (config.layout != JTEXTMENU_SAMELINE)
98 {
99 if (yOff > 0)
100 {
101 // El número de espacios entre líneas es uno menos que el número de opciones
102 yOff += config.lineDistance;
103 }
104 yOff += it->Data()->Image()->Height();
105 }
106 else
107 {
108 yOff = 0;
109 }
110
111 localW = xOff > localW ? xOff : localW;
112 localH = yOff > localH ? yOff : localH;
113
114 // Distribuye a los hijos
115 if (it->Child())
116 {
117 ApplyLayout(it);
118 }
119 } while (it->Next());
120
121 xOff = 0;
122 it->FirstInBranch();
123
124 switch (config.layoutV)
125 {
126 // La posición y del menú es la del borde inferior
127 case JTEXTMENU_DOWN:
128 yOff = -localH;
129 break;
130
131 // La posición y del menú es la del centro
132 case JTEXTMENU_CENTER:
133 yOff = -localH/2;
134 break;
135
136 // La posición y del menú es la del borde superior
137 case JTEXTMENU_UP:
138 default:
139 yOff = 0;
140 break;
141 }
142
143 // Aplica la distribución de menú
144 do
145 {
146 switch (config.layout)
147 {
148 // La posición x del menú es la del borde izquierdo
149 case JTEXTMENU_LEFT:
150 it->Data()->Image()->Pos(0, yOff);
151 it->Data()->HiImage()->Pos(0, yOff);
152 yOff += it->Data()->Image()->Height() + config.lineDistance;
153 break;
154
155 // La posición x del menú es la del borde derecho
156 case JTEXTMENU_RIGHT:
157 xOff = -it->Data()->Image()->Width();
158 it->Data()->Image()->Pos(xOff, yOff);
159 it->Data()->HiImage()->Pos(xOff, yOff);
160 yOff += it->Data()->Image()->Height() + config.lineDistance;
161 break;
162
163 // La posición x del menú es la del centro
164 case JTEXTMENU_CENTER:
165 xOff = -it->Data()->Image()->Width()/2;
166 it->Data()->Image()->Pos(xOff, yOff);
167 it->Data()->HiImage()->Pos(xOff, yOff);
168 yOff += it->Data()->Image()->Height() + config.lineDistance;
169 break;
170
171 // La posición x del menú es la del borde izquierdo
172 case JTEXTMENU_SAMELINE:
173 it->Data()->Image()->Pos(xOff, 0);
174 it->Data()->HiImage()->Pos(xOff, 0);
175 xOff += it->Data()->Image()->Width();
176 break;
177
178 default:
179 break;
180 }
181 } while (it->Next());
182
183 it->Parent();
184 }
185
186 bool JTextMenu::RenderBranch(JTree<JTextMenuEntry *>::Iterator *it)
187 {
188 bool ok = true;
189 s32 xOff = 0, yOff = 0;
190
191 do
192 {
193 // Renderiza esta opción
194 ok = it->Data()->Init(config);
195
196 // Determina la anchura y altura máximas entre todas las opciones de esta rama
197 if (config.layout != JTEXTMENU_SAMELINE)
198 {
199 xOff = it->Data()->Image()->Width();
200 }
201 else
202 {
203 xOff += it->Data()->Image()->Width();
204 }
205
206 if (config.layout != JTEXTMENU_SAMELINE)
207 {
208 if (yOff > 0)
209 {
210 // El número de espacios entre líneas es uno menos que el número de opciones
211 yOff += config.lineDistance;
212 }
213 yOff += it->Data()->Image()->Height();
214 }
215 else
216 {
217 yOff = it->Data()->Image()->Height();
218 }
219
220 maxW = xOff > maxW ? xOff : maxW;
221 maxH = yOff > maxH ? yOff : maxH;
222
223 // Renderiza los hijos
224 if (ok && it->Child())
225 {
226 ok = RenderBranch(it);
227 }
228 } while (ok && it->Next());
229
230 it->Parent();
231
232 return ok;
233 }
234
235 bool JTextMenu::Init(JTextMenuConfig &cfg)
236 {
237 if (curOption == 0 || cfg.font == 0)
238 {
239 // Parámetro inválido
240 return false;
241 }
242
243 memcpy(&config, &cfg, sizeof(config));
244
245 // Altura de línea
246 if (config.lineDistance < 0)
247 {
248 config.lineDistance = config.font->LineDistance();
249 }
250
251 // Renderiza las opciones de menú
252 curOption->Root();
253 if (RenderBranch(curOption))
254 {
255 curOption->Root();
256 ApplyLayout(curOption);
257 curOption->Root();
258
259 return true;
260 }
261
262 return false;
263 }
264
265 void JTextMenu::Draw()
266 {
267 JTree<JTextMenuEntry *>::Iterator *it = new JTree<JTextMenuEntry *>::Iterator(*curOption);
268 s32 xOff, yOff;
269
270 it->FirstInBranch();
271
272 do
273 {
274 // Si es la opción seleccionada muestra su imagen resaltada
275 if (it->Data() == curOption->Data())
276 {
277 xOff = (s32)it->Data()->HiImage()->X();
278 yOff = (s32)it->Data()->HiImage()->Y();
279 it->Data()->HiImage()->Draw((s32)(X() + xOff), (s32)(Y() + yOff));
280 }
281 else
282 {
283 xOff = (s32)it->Data()->Image()->X();
284 yOff = (s32)it->Data()->Image()->Y();
285 it->Data()->Image()->Draw((s32)(X() + xOff), (s32)(Y() + yOff));
286 }
287 } while (it->Next());
288
289 delete it;
290 }
291
292 void JTextMenu::TrackKeyboard(SDL_keysym key)
293 {
294 // Actualiza el estado según el teclado
295 if (config.trackKeyboard)
296 {
297 switch (key.sym)
298 {
299 case SDLK_TAB:
300 // SHIFT + TAB
301 if (JApp::App()->KeyMods() & KMOD_SHIFT)
302 {
303 // Opción anterior
304 if (!curOption->Prev())
305 curOption->LastInBranch();
306 }
307 // TAB
308 else
309 {
310 // Opción siguiente
311 if (!curOption->Next())
312 curOption->FirstInBranch();
313 }
314 break;
315
316 case SDLK_UP:
317 case SDLK_LEFT:
318 // Opción anterior
319 if (!curOption->Prev())
320 curOption->LastInBranch();
321 break;
322
323 case SDLK_DOWN:
324 case SDLK_RIGHT:
325 // Opción siguiente
326 if (!curOption->Next())
327 curOption->FirstInBranch();
328 break;
329
330 case SDLK_KP_ENTER:
331 case SDLK_RETURN:
332 // Ejecuta la acción asociada
333 if (!curOption->Data()->Select() && config.autoEnter)
334 {
335 // Si no hay acción asociada y se especificó autoEnter, intenta descender
336 // a la opción hija.
337 curOption->Child();
338 }
339 break;
340
341 case SDLK_ESCAPE:
342 // Va a la opción padre.
343 curOption->Parent();
344 break;
345
346 default:
347 break;
348 } // switch (key)
349 } // Track keyboard
350 }
351
352 void JTextMenu::TrackMouse(s32 bt, s32 x, s32 y)
353 {
354 // Actualiza el estado según el ratón
355 if (config.trackMouse)
356 {
357 JTree<JTextMenuEntry *>::Iterator *it = new JTree<JTextMenuEntry *>::Iterator(*curOption);
358 s32 mx, my;
359 bool found = false;
360 mx = JApp::App()->MouseX();
361 my = JApp::App()->MouseY();
362
363 it->FirstInBranch();
364
365 // Comprueba si está sobre alguna opción
366 do
367 {
368 if (mx > it->Data()->Image()->X() + X() &&
369 mx < it->Data()->Image()->X() + X() + it->Data()->Image()->Width() &&
370 my > it->Data()->Image()->Y() + Y() &&
371 my < it->Data()->Image()->Y() + Y() + it->Data()->Image()->Height())
372 {
373 // Está dentro, hace que sea la opción resaltada
374 found = true;
375
376 // Borra el iterador actual
377 delete(curOption);
378
379 curOption = it;
380 }
381 } while (!found && it->Next());
382
383
384 if (found)
385 {
386 // Si ahora está pulsado, activa el flag de pulsación
387 if (bt & SDL_BUTTON_LEFT)
388 {
389 // Ejecuta la acción asociada
390 if (!curOption->Data()->Select() && config.autoEnter)
391 {
392 // Si no hay acción asociada y se especificó autoEnter, intenta descender
393 // a la opción hija.
394 curOption->Child();
395 }
396 }
397 }
398
399 // Si encontró una opción bajo el cursor el iterador sobre esa opción
400 // pasa a ser el iterador de opción actual, no lo borra
401 if (!found)
402 delete it;
403 } // Track mouse
404 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Menu en pantalla compuesto de cadenas de texto.
23 * @file JTextMenu.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 28/03/2004
26 * @version 0.0.1 - 28/03/2004 - Primera versión.
27 */
28
29 #ifndef _JTEXTMENU_INCLUDED
30 #define _JTEXTMENU_INCLUDED
31
32 #include <JLib/Graphics/JDrawable.h>
33 #include <JLib/Graphics/JImage.h>
34 #include <JLib/Graphics/JFont.h>
35 #include <JLib/Util/JApp.h>
36 #include <JLib/Util/JString.h>
37 #include <JLib/Util/JTree.h>
38 #include <JLib/Util/JTimer.h>
39
40 /** Modo de renderizado de la fuente del menú.
41 */
42 typedef enum
43 {
44 JTEXTMENU_SOLID = 1, /**< Sólido con colorkey. */
45 JTEXTMENU_SHADED, /**< Antialiasing con fondo sólido. */
46 JTEXTMENU_BLENDED, /**< Antialiasing con fondo transparente. */
47 } JTextMenuRenderStyle;
48
49 /** Distribución del menú.
50 */
51 typedef enum
52 {
53 JTEXTMENU_LEFT = 1, /**< Alineado a la izquierda. */
54 JTEXTMENU_RIGHT, /**< Alineado a la derecha. */
55 JTEXTMENU_CENTER, /**< Centrado. */
56 JTEXTMENU_SAMELINE, /**< Todas las opciones en la misma línea. */
57 JTEXTMENU_UP, /**< Alineado arriba. */
58 JTEXTMENU_DOWN, /**< Alineado abajo. */
59 } JTextMenuLayout;
60
61 /** Estructura de configuración del menú.
62 */
63 struct JTextMenuConfig
64 {
65 JFont * font; /**< Fuente a usar. */
66 SDL_Color color; /**< Color de fuente. */
67 SDL_Color backColor; /**< Color de fondo (JTEXTMENU_SHADED). */
68 SDL_Color hiColor; /**< Color resaltado. */
69 SDL_Color hiBackColor; /**< Color de fondo resaltado (JTEXTMENU_SHADED). */
70 s32 lineDistance; /**< Separación entre líneas (-1 para la predeterminada de la fuente). */
71 JTextMenuLayout layout; /**< Distribución del menú en horizontal. */
72 JTextMenuLayout layoutV; /**< Distribución del menú en vertical. */
73 JTextMenuRenderStyle renderMode; /**< Modo de renderizado. */
74 bool trackMouse; /**< Indica si puede manejarse con ratón. */
75 bool trackKeyboard; /**< Indica si puede manejarse con teclado. */
76 bool trackJoystick; /**< Indica si puede manejarse con joystick/pad. */
77 bool autoEnter; /**< Indica si desciende si no hay acción asociada. */
78 };
79
80 /** Opción de menú básica.
81 */
82 class JTextMenuEntry
83 {
84 protected:
85 public:
86 JImage *image; /**< Imagen asociada a la opción. */
87 JImage *hiImage; /**< Imagen asociada a la opción resaltada. */
88
89 JString text; /**< Texto de la opción de menú. */
90 void (*Action)(void *data); /**< Acción asociada a la opción de menú. */
91 void *data; /**< Datos asociados a la opción de menú. */
92
93 public:
94 JTextMenuEntry(const JString &str, void (*pAct)(void *) = 0, void *actionData = 0)
95 : image(0), hiImage(0), text(str), Action(pAct), data(actionData)
96 {}
97
98 /** Selecciona la opción de menú, llamando a la callback asociada, si existe.
99 * @return <b>true</b> en caso de haber acción asociada, <b>false</b> si no.
100 */
101 bool Select();
102
103 /** Devuelve la imagen asociada.
104 * @return La imagen asociada.
105 */
106 JImage * Image() {return image;}
107
108 /** Devuelve la imagen asociada al estado resaltado.
109 * @return La imagen asociada al estado resaltado.
110 */
111 JImage * HiImage() {return hiImage;}
112
113 /** Renderiza la opción de menú con la configuración dada.
114 * @param cfg Configuración de menú.
115 * @return <b>true</b> Si todo fue bien, <b>false</b> si no se pudo renderizar.
116 */
117 bool Init(JTextMenuConfig &cfg);
118
119 /** Devuelve el texto de esta opción.
120 */
121 const JString& Text() {return text;}
122
123 /** Destruye el objeto y libera las imagenes asociadas.
124 */
125 void Destroy()
126 {
127 JDELETE(image);
128 JDELETE(hiImage);
129 }
130
131 /** Destruye el objeto y libera las imagenes asociadas.
132 */
133 virtual ~JTextMenuEntry()
134 {
135 Destroy();
136 }
137 };
138
139 /** Encapsula un menú de texto en pantalla.
140 */
141 class JTextMenu : public JDrawable
142 {
143 JTree<JTextMenuEntry *> options; /**< Árbol de opciones de menú. */
144 JTree<JTextMenuEntry *>::Iterator *curOption; /**< Opción actual. */
145 JTextMenuConfig config; /**< Parámetros de configuración del menú. */
146 s32 maxW; /**< Anchura máxima. */
147 s32 maxH; /**< Altura máxima. */
148
149 /** Método recursivo de renderización de las opciones del menú.
150 * @param it Iterador de la opción actual.
151 * @return <b>true</b> Si todo fue bien, <b>false</b> si no hay memoria.
152 */
153 bool RenderBranch(JTree<JTextMenuEntry *>::Iterator *it);
154
155 /** Aplica la distribución de menú.
156 */
157 void ApplyLayout(JTree<JTextMenuEntry *>::Iterator *it);
158
159 public:
160 /** Crea un menú vacío. Init debe ser llamada antes de utilizar el objeto.
161 */
162 JTextMenu();
163
164 /** Inicializa el menú con la configuración dada. Esta función debe
165 * ser llamada después de haber rellenado el árbol del menú.
166 * @param cfg Configuración del menú.
167 * @return <b>true</b> Si todo fue bien, <b>false</b> si no se encontró la
168 * fuente dada.
169 */
170 bool Init(JTextMenuConfig &cfg);
171
172 /** Devuelve el iterador de opción actual.
173 * @return Iterador de opción actual.
174 */
175 JTree<JTextMenuEntry *>::Iterator * Menu() {return curOption;}
176
177 /** Función de dibujo del menú.
178 */
179 virtual void Draw();
180
181 /** Procesa tecla arriba
182 */
183 virtual void TrackKeyboard(SDL_keysym key);
184
185 /** Procesa movimiento de mouse
186 */
187 virtual void TrackMouse(s32 bt, s32 x, s32 y);
188
189 /** Devuelve la anchura máxima del menú.
190 * @return Anchura máxima del menú.
191 */
192 s32 MaxW() {return maxW;}
193
194 /** Devuelve la altura máxima del menú.
195 * @return Altura máxima del menú.
196 */
197 s32 MaxH() {return maxH;}
198
199 /** Destruye el objeto y libera la memoria asociada.
200 */
201 virtual ~JTextMenu()
202 {
203 for (options.Begin(); !options.End(); options.Next())
204 {
205 JDELETE(options.Cur());
206 }
207
208 options.Clear();
209 JDELETE(curOption);
210 }
211 };
212
213 #endif // _JTEXTMENU_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clase de gestión de una interfaz de usuario.
23 * @file JUI.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 13/06/2004
26 * @version 0.0.1 - 13/06/2004 - Primera versión.
27 */
28
29 #include <JLib/Graphics/JUI.h>
30
31 bool JUI::Init()
32 {
33 return true;
34 }
35
36 void JUI::Draw()
37 {
38 for (int i = 0; i < numControls; ++i)
39 {
40 controls[i]->Draw();
41 }
42 }
43
44 s32 JUI::Update()
45 {
46 for (int i = 0; i < numControls; ++i)
47 {
48 controls[i]->Update();
49 }
50
51 return 0;
52 }
53
54 s32 JUI::TrackMouse(s32 x, s32 y, s32 bt)
55 {
56 return 0;
57 }
58
59 s32 JUI::TrackKeyboard(s32 x, s32 y, s32 bt)
60 {
61 return 0;
62 }
63
64 u32 JUI::Load(JRW &f)
65 {
66 Destroy();
67
68 // Carga el número de controles de la interfaz
69 if (0 == f.ReadLE32(&numControls))
70 {
71 return 1;
72 }
73
74 // Crea el array de controles de la interfaz
75 controls = new JControl *[numControls];
76
77 // Carga los controles de la interfaz
78 u32 t = 0;
79 for (int i = 0; i < numControls; ++i)
80 {
81 if (0 == f.Read(&t, sizeof(t)))
82 {
83 Destroy();
84 return 2;
85 }
86
87 switch (t)
88 {
89 case JCONTROLTYPE_IMAGE:
90 controls[i] = new JControlImage;
91 break;
92
93 case JCONTROLTYPE_IMAGESPRITE:
94 break;
95
96 case JCONTROLTYPE_MESH:
97 break;
98
99 case JCONTROLTYPE_MESHSPRITE:
100 break;
101
102 default:
103 fprintf(stderr, "Control de interfaz de usuario no reconocido.\n");
104 Destroy();
105 return 2;
106 }
107
108 if (0 != controls[i]->Load(f))
109 {
110 return 2;
111 }
112 }
113
114 return 0;
115 }
116
117 u32 JUI::Save(JRW &f)
118 {
119 // Salva el número de controles de la interfaz
120 if (0 == f.WriteLE32(&numControls))
121 {
122 return 1;
123 }
124
125 // Salva los controles de la interfaz
126 for (int i = 0; i < numControls; ++i)
127 {
128 if (0 != controls[i]->Save(f))
129 {
130 return 2;
131 }
132 }
133
134 return 0;
135 }
136
137 void JUI::Destroy()
138 {
139 if (controls != 0)
140 {
141 for (int i = 0; i < numControls; ++i)
142 {
143 JDELETE(controls[i]);
144 }
145 }
146
147 JDELETE_ARRAY(controls);
148 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clase de gestión de una interfaz de usuario.
23 * @file JUI.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 13/06/2004
26 * @version 0.0.1 - 13/06/2004 - Primera versión.
27 */
28
29 #ifndef _JUI_INCLUDED
30 #define _JUI_INCLUDED
31
32 #include <JLib/Util/JObject.h>
33 #include <JLib/Graphics/JDrawable.h>
34 #include <JLib/Graphics/JControl.h>
35 #include <JLib/Graphics/JControlImage.h>
36
37 /** Clase de gestión de una interfaz de usuario.
38 */
39 class JUI : public JDrawable
40 {
41 s32 numControls; /**< Número de controles que contiene la interfaz. */
42 JControl **controls; /**< Controles que conforman la interfaz. */
43
44 public:
45 /** Contruye el objeto vacio. Init debe ser llamado para comenzar a usarlo.
46 */
47 JUI() : numControls(0), controls(0)
48 {}
49
50 /** Inicializa la interfaz.
51 */
52 bool Init();
53
54 /** Devuelve los controles de esta interfaz.
55 */
56 JControl **& Controls() {return controls;}
57
58 /** Dibuja la interfaz de usuario.
59 */
60 void Draw();
61
62 /** Actualiza la interfaz de usuario.
63 * @return Siempre 0.
64 */
65 s32 Update();
66
67 /** Actualiza la interfaz en función del ratón.
68 */
69 s32 TrackMouse(s32 x, s32 y, s32 bt);
70
71 /** Actualiza la interfaz en función del teclado.
72 */
73 s32 TrackKeyboard(s32 x, s32 y, s32 bt);
74
75 /** Carga la interfaz desde un fichero de definición de interfaz.
76 * @param f Fichero abierto y posicionado para cargar el objeto.
77 * @return 0 si todo va bien, 1 en caso de error de E/S,
78 * 2 en caso de incoherencia de los datos.
79 */
80 u32 Load(JRW &f);
81
82 /** Salva la interfaz a un fichero de definición de interfaz.
83 * @param f Fichero abierto y posicionado para salvar el objeto.
84 * @return 0 si todo va bien, 1 en caso de error de E/S,
85 * 2 en caso de incoherencia de los datos.
86 */
87 u32 Save(JRW &f);
88
89 /** Destruye los controles de la interfaz.
90 */
91 void Destroy();
92
93 /** Destruye el objeto.
94 */
95 ~JUI() {Destroy();};
96 };
97
98 #endif // _JUI_INCLUDED
0 # Makefile para JLib.
1 # (C) Juan Carlos Seijo Pérez - 2003.
2
3 ADD_INCLUDE=-I. -I/usr/local/include
4 GRAPHICS=JLib/Graphics
5 UTIL=JLib/Util
6 MATH=JLib/Math
7 SOUND=JLib/Sound
8 PHYSICS=JLib/Physics
9 JSPRITED=JLib/JSprited
10 JSCENED=JLib/JScened
11 TARGET=libJLib.so libJLib.a JSprited JScened
12
13 DBG_FLAG=-g
14 OPTIM=-O4 -mcpu=pentium2 -march=pentium2
15
16 WITH_LIBS=-lSDL -lSDL_image -lGL -lGLU -lfltk -lfltk_images
17
18 all: *.o
19
20 *.o: *.cpp *.h
21 echo $?
22 g++ $(DBG_FLAG) $(ADD_INCLUDE) -c -o $@ $<
23
24 .PHONY: clean
25 clean:
26 rm -rf *.o
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Includes JLib files.
23 * @file JLib.h
24 * @author Juan Carlos Seijo
25 * @date 07/03/2004
26 * @version 0.0.1 - 07/03/2004 - First version.
27 */
28
29 #ifndef _JLIB_INCLUDED
30 #define _JLIB_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33
34 #include <JLib/Graphics/JASEFormat.h>
35 #include <JLib/Graphics/JASELoader.h>
36 #include <JLib/Graphics/JControl.h>
37 #include <JLib/Graphics/JDrawable.h>
38 #include <JLib/Graphics/JGLAxes.h>
39 #include <JLib/Graphics/JGLCamera.h>
40 #include <JLib/Graphics/JGLColor.h>
41 #include <JLib/Graphics/JGLConsole.h>
42 #include <JLib/Graphics/JGLConsoleFont.h>
43 #include <JLib/Graphics/JGLGrid.h>
44 #include <JLib/Graphics/JGLLight.h>
45 #include <JLib/Graphics/JGLText.h>
46 #include <JLib/Graphics/JGLTexture.h>
47 #include <JLib/Graphics/JGLVector.h>
48 #include <JLib/Graphics/JImage.h>
49 #include <JLib/Graphics/JImageControl.h>
50 #include <JLib/Graphics/JImageSprite.h>
51 #include <JLib/Graphics/JSprite.h>
52 #include <JLib/Graphics/JTextMenu.h>
53 #include <JLib/Math/J2DPolygon.h>
54 #include <JLib/Math/J2DSegment.h>
55 #include <JLib/Math/J2DVector.h>
56 #include <JLib/Math/JBasis.h>
57 #include <JLib/Math/JCoordAxes.h>
58 #include <JLib/Math/JMath.h>
59 #include <JLib/Math/JMatrix.h>
60 #include <JLib/Math/JVector.h>
61 #include <JLib/Physics/JRigidBodyState.h>
62 #include <JLib/Sound/JMixer.h>
63 #include <JLib/Util/JApp.h>
64 #include <JLib/Util/JCompatibility.h>
65 #include <JLib/Util/JDebug.h>
66 #include <JLib/Util/JFile.h>
67 #include <JLib/Util/JFLTK.h>
68 #include <JLib/Util/JFS.h>
69 #include <JLib/Util/JGLApp.h>
70 #include <JLib/Util/JLoadSave.h>
71 #include <JLib/Util/JObject.h>
72 #include <JLib/Util/JString.h>
73 #include <JLib/Util/JTextFile.h>
74 #include <JLib/Util/JTextUtil.h>
75 #include <JLib/Util/JTimer.h>
76 #include <JLib/Util/JTree.h>
77 #include <JLib/Util/JUtil.h>
78 #include <JLib/Util/JFont.h>
79
80 #endif // _JLIB_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Polígono cerrado genérico
23 * @file J2DPolygon.cpp.
24 * @author Juan Carlos Seijo Pérez.
25 * @date 01/02/2004
26 * @version 0.0.1 - 01/02/2004 - Primera versión.
27 */
28
29 #include <JLib/Math/J2DPolygon.h>
30 #include <stdio.h>
31
32 void J2DPolygon::Init(s32 _numVertices, J2DPoint *_vertices)
33 {
34 Destroy();
35
36 numVertices = _numVertices;
37 vertices = new J2DPoint[numVertices];
38 memcpy(vertices, _vertices, numVertices * sizeof(J2DPoint));
39
40 segments = new J2DVector[numVertices];
41 normals = new J2DVector[numVertices];
42
43 // El vector normal en sentido CCW de (x, y) es (y, -x)
44 for (s32 i = 0; i < numVertices - 1; ++i)
45 {
46 segments[i] = _vertices[i] - _vertices[i + 1];
47 normals[i].Pos(segments[i].y, -segments[i].x);
48 }
49
50 segments[numVertices - 1] = _vertices[numVertices - 1] - _vertices[0];
51 normals[numVertices - 1].Pos(segments[numVertices - 1].y, -segments[numVertices - 1].x);
52 }
53
54 void J2DPolygon::Destroy()
55 {
56 JDELETE_ARRAY(vertices);
57 JDELETE_ARRAY(normals);
58 JDELETE_ARRAY(segments);
59 }
60
61 bool J2DPolygon::IsInside(J2DScalar x, J2DScalar y)
62 {
63 J2DVector v(x, y);
64 J2DVector vNorm, vTemp;
65 J2DScalar s = 1;
66
67 // Dejamos como caso más probable que esté fuera (en sentido CCW)
68 for (s32 i = 0; s >= 0 && i < numVertices; ++i)
69 {
70 vNorm = normals[i];
71 vTemp = vertices[i] - v;
72 //printf("vNorm (%f, %f). ", vNorm.X(), vNorm.Y());
73 //printf("vTemp (%f, %f). ", vTemp.X(), vTemp.Y());
74 s = (vNorm).Dot(vTemp);
75 //printf("Dot (%f).\n", s);
76 }
77
78 return s >= 0;
79 }
80
81 u32 J2DPolygon::Load(JFile &f)
82 {
83 // Salva el número de vértices
84 if (0 == f.Read(&numVertices, sizeof(numVertices)))
85 {
86 return 1;
87 }
88
89 // Salva los vértices
90 u32 ret = 0;
91 J2DPoint *v = new J2DPoint[numVertices];
92
93 for (s32 i = 0; 0 == ret && i < numVertices; ++i)
94 {
95 ret = v[i].Load(f);
96 }
97
98 if (ret == 0)
99 {
100 // Inicializa el polígono
101 Init(numVertices, v);
102 }
103
104 JDELETE_ARRAY(v);
105
106 return ret;
107 }
108
109 u32 J2DPolygon::Save(JFile &f)
110 {
111 // Salva el número de vértices
112 if (0 == f.Write(&numVertices, sizeof(numVertices)))
113 {
114 return 1;
115 }
116
117 // Salva los vértices
118 u32 ret = 0;
119
120 for (s32 i = 0; 0 == ret && i < numVertices; ++i)
121 {
122 ret = vertices[i].Save(f);
123 }
124
125 return ret;
126 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Polígono cerrado genérico
23 * @file J2DPolygon.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 01/02/2004
26 */
27
28 #ifndef _J2DPOLYGON_INCLUDED
29 #define _J2DPOLYGON_INCLUDED
30
31 #include <JLib/Util/JTypes.h>
32 #include <JLib/Util/JLoadSave.h>
33 #include <JLib/Math/J2DVector.h>
34 #include <string.h>
35 #include <math.h>
36
37 /** Polígono cerrado genérico.
38 * Consta de varios vértices conectados correlativamente.
39 */
40 class J2DPolygon : public JLoadSave
41 {
42 protected:
43 s32 numVertices; /**< Número de vértices del polígono */
44 J2DPoint* vertices; /**< Vértices del polígono */
45 J2DVector* segments; /**< Segmentos del polígono */
46 J2DVector* normals; /**< Normales a los segmentos del polígono */
47
48 public:
49 /** Constructor.
50 * Crea un polígono vacío.
51 */
52 J2DPolygon() : numVertices(0), vertices(0), segments(0), normals(0) {}
53
54
55 /** Constructor.
56 * Crea un polígono cerrado a partir de los vértices dados.
57 * @param _numVertices Número de vértices.
58 * @param _vertices Vértices.
59 */
60 J2DPolygon(s32 _numVertices, J2DPoint *_vertices) : numVertices(0), vertices(0), segments(0), normals(0)
61 {Init(_numVertices, _vertices);}
62
63 /** Inicializa el polígono con los vértices dados.
64 * @param _numVertices Número de vértices.
65 * @param _vertices Vértices.
66 */
67 void Init(s32 _numVertices, J2DPoint *_vertices);
68
69 /** Destructor.
70 * Libera memoria.
71 */
72 virtual ~J2DPolygon() {Destroy();}
73
74 /** Destruye el objeto y lo deja como si se acabará de crear con J2DPolygon.
75 */
76 void Destroy();
77
78 /** Determina si el punto dado está dentro del polígono.
79 * Por convenio, si un polígono está definido en
80 * sentido antihorario (CCW) entonces un punto está dentro si cae dentro del
81 * contorno cerrado del polígono. Si se define en sentido horario (CW), los puntos
82 * de dentro del contorno cerrado del polígono están fuera.
83 * @param x coordenada x del punto.
84 * @param y coordenada y del punto.
85 * @return true si el punto dado está dentro, false en caso contrario.
86 */
87 bool IsInside(J2DScalar x, J2DScalar y);
88
89 /** Carga el polígono
90 * @param f Fichero posicionado en este recurso
91 * @return 0 Si todo fue bien, 1 si hay error de E/S y 2 si hay error
92 * en los datos.
93 */
94 u32 Load(JFile &f);
95
96 /** Salva el polígono
97 * @param f Fichero posicionado en este recurso
98 * @return 0 Si todo fue bien, 1 si hay error de E/S y 2 si hay error
99 * en los datos.
100 */
101 u32 Save(JFile &f);
102 };
103
104 #endif // _J2DPOLYGON_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Segmento en el plano.
23 * @file J2DSegment.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 05/01/2004
26 * @version 0.0.1 - 05/01/2004 - Primera versión.
27 */
28
29 #ifndef _J2DSEGMENT_INCLUDED
30 #define _J2DSEGMENT_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Util/JLoadSave.h>
34
35 /** Encapsula un segmento en el plano. Coordenadas medidas como
36 * en pantalla (eje y positivo hacia abajo).
37 */
38 class J2DSegment : public JLoadSave
39 {
40 protected:
41 bool vertical; /**< Flag de verticalidad */
42 float lastX, lastY; /**< Último punto de intersección */
43 float x1, y1, x2, y2; /**< Inicio y fin del segmento */
44 float m; /**< Pendiente */
45 float n; /**< Desplazamiento */
46
47 /** Compara dos valores decimales con el margen 'epsilon' actual de la clase.
48 * @param a Primer valor.
49 * @param b Segundo valor.
50 */
51 bool NearlyEquals(float a, float b) const
52 {
53 return (a >= b - epsilon && a <= b + epsilon);
54 }
55
56 /** Recalcula la pendiente.
57 */
58 void RecalcM()
59 {
60 if (x1 == x2)
61 {
62 vertical = true;
63 m = n = 0;
64 }
65 else
66 {
67 m = (y2 - y1)/(x2 - x1);
68 n = y1 - (m * x1);
69 vertical = false;
70 }
71 }
72
73 public:
74 static const float epsilon; /**< Margen de comparación entre dos puntos */
75
76 /** Crea un nuevo segmento.
77 */
78 J2DSegment()
79 {}
80
81 /** Crea un nuevo segmento a partir de sus extremos.
82 * @param _x1 Coordenada x del primer extremo.
83 * @param _y1 Coordenada y del primer extremo.
84 * @param _x2 Coordenada x del segundo extremo.
85 * @param _y2 Coordenada y del segundo extremo.
86 */
87 J2DSegment(float _x1, float _y1, float _x2, float _y2)
88 : x1(_x1), y1(_y1), x2(_x2), y2(_y2)
89 {
90 RecalcM();
91 }
92
93 /** Determina si el segmento es vertical.
94 * @return <b>true</b> en caso de que sea vertical, <b>false</b> si no.
95 */
96 bool Vertical() const {return vertical;}
97
98 /** Devuelve la coordenada x del primer extremo.
99 * @return Coordenada x del primer extremo.
100 */
101 float X1() const {return x1;}
102
103 /** Devuelve la coordenada y del primer extremo.
104 * @return Coordenada y del primer extremo.
105 */
106 float Y1() const {return y1;}
107
108 /** Devuelve la coordenada x del segundo extremo.
109 * @return Coordenada x del segundo extremo.
110 */
111 float X2() const {return x2;}
112
113 /** Devuelve la coordenada y del segundo extremo.
114 * @return Coordenada y del segundo extremo.
115 */
116 float Y2() const {return y2;}
117
118 /** Devuelve la pendiente 'm' en la ecuación de la recta y = mx + n.
119 * @return Pendiente.
120 */
121 float M() const {return m;}
122
123 /** Devuelve el desplazamiento vertical 'n' en la ecuación de la recta y = mx + n.
124 * @return Pendiente.
125 */
126 float N() const {return n;}
127
128 /** Establece la coordenada x del primer segmento.
129 * @param _x1 Coordenada x del primer segmento.
130 */
131 void X1(float _x1) {x1 = _x1; RecalcM();}
132
133 /** Establece la coordenada y del primer segmento.
134 * @param _y1 Coordenada y del primer segmento.
135 */
136 void Y1(float _y1) {y1 = _y1; RecalcM();}
137
138 /** Establece la coordenada x del segundo segmento.
139 * @param _x2 Coordenada x del segundo segmento.
140 */
141 void X2(float _x2) {x2 = _x2; RecalcM();}
142
143 /** Establece la coordenada y del segundo segmento.
144 * @param _y2 Coordenada y del segundo segmento.
145 */
146 void Y2(float _y2) {y2 = _y2; RecalcM();}
147
148 /** Establece las coordenadas de los extremos.
149 * @param _x1 Coordenada x del primer segmento.
150 * @param _y1 Coordenada y del primer segmento.
151 * @param _x2 Coordenada x del segundo segmento.
152 * @param _y2 Coordenada y del segundo segmento.
153 */
154 void Pos(float _x1, float _y1, float _x2, float _y2)
155 {X1(_x1); Y1(_y1); X2(_x2); Y2(_y2); RecalcM();}
156
157 /** Devuelve la coordenada x del último punto de corte.
158 * @return Coordenada x del último punto de corte.
159 */
160 float LastX() {return lastX;}
161
162 /** Devuelve la coordenada y del último punto de corte.
163 * @return Coordenada y del último punto de corte.
164 */
165 float LastY() {return lastY;}
166
167 /** Determina si el valor x se encuentra entre min y max, inclusive.
168 * @param x Valor a probar.
169 * @param min Valor mínimo.
170 * @param max Valor máximo.
171 * @return <b>true</b> si x está entre min y max, <b>false</b> si no.
172 */
173 bool Between(float x, float min, float max) const
174 {
175 return (min <= x && x <= max);
176 }
177
178 /** Comprueba si el punto pertenece al segmento.
179 * @param x Coordenada x del punto a probar.
180 * @param y Coordenada y del punto a probar.
181 * @return <b>true</b> si lo contiene, <b>false</b> si no.
182 * @see epsilon.
183 */
184 bool Contains(float x, float y) const
185 {
186 if (vertical)
187 {
188 return x1 == x && (Between(y, y1, y2) || Between(y, y2, y1));
189 }
190
191 return (NearlyEquals(y, ((m * x) + n)) &&
192 (Between(x, x1, x2) ||
193 Between(x, x2, x1)));
194 }
195
196 /** Comprueba si el punto está en el rectángulo formado por el segmento.
197 * @param x Coordenada x del punto a probar.
198 * @param y Coordenada y del punto a probar.
199 * @return <b>true</b> si lo está, <b>false</b> si no.
200 */
201 bool InRect(float x, float y) const
202 {
203 float xMin, xMax, yMin, yMax;
204
205 if (x1 < x2)
206 {
207 xMin = x1;
208 xMax = x2;
209 }
210 else
211 {
212 xMin = x2;
213 xMax = x1;
214 }
215
216 if (y1 < y2)
217 {
218 yMin = y1;
219 yMax = y2;
220 }
221 else
222 {
223 yMin = y2;
224 yMax = y1;
225 }
226
227 return (Between(x, xMin, xMax) && Between(y, yMin, yMax));
228 }
229
230 /** Comprueba si se cortan los segmentos. En caso de cortarse, el punto
231 * de corte se obtiene con LastX() y LastY().
232 * @param other Segmento con el que comprobar el corte.
233 * @return <b>true</b> si se cortan, <b>false</b> si no.
234 */
235 bool Cuts(const J2DSegment &other)
236 {
237 bool cut;
238
239 if (vertical)
240 {
241 // Paralelos
242 if (other.Vertical())
243 {
244 //printf("Paralelos verticales\n");
245 cut = (Contains(lastX = other.X1(), lastY = other.Y1()) ||
246 Contains(lastX = other.X2(), lastY = other.Y2()));
247 }
248 else
249 {
250 // No paralelos
251 //printf("No Paralelos, primero vertical\n");
252 lastX = x1;
253 lastY = (other.M() * x1) + other.N();
254 cut = (Contains(lastX, lastY) &&
255 other.Contains(lastX, lastY));
256 // cut = InRect(lastX, lastY) && other.InRect(lastX, lastY);
257 }
258 }
259 else if (other.Vertical())
260 {
261 // No paralelos
262 //printf("No Paralelos, segundo vertical\n");
263 lastX = other.X1();
264 lastY = (M() * other.X1()) + N();
265 cut = (Contains(lastX, lastY) &&
266 other.Contains(lastX, lastY));
267 // cut = InRect(lastX, lastY) && other.InRect(lastX, lastY);
268 }
269 else
270 // Paralelos
271 if (m == other.M()) // ¡UFFFF!, aunque vienen de enteros, no creo que haya problemas
272 {
273 if ((s32)n != other.N())
274 {
275 //printf("Paralelos no coincidentes n1=%d, n2=%d\n", (s32)n, (s32)other.N());
276 cut = false;
277 }
278 else
279 {
280 //printf("Coincidentes\n");
281 cut = (Contains(lastX = other.X1(), lastY = other.Y1()) ||
282 Contains(lastX = other.X2(), lastY = other.Y2()) ||
283 other.Contains(lastX = X1(), lastY = Y1()) ||
284 other.Contains(lastX = X2(), lastY = Y2()));
285 // cut = InRect(lastX, lastY) && other.InRect(lastX, lastY);
286 }
287 }
288 else
289 {
290 // No Paralelos
291 //printf("No Paralelos\n");
292 lastX = (other.N() - n)/(m - other.M());
293 lastY = n + (m * lastX);
294
295 cut = (Contains(lastX, lastY) &&
296 other.Contains(lastX, lastY));
297 // cut = InRect(lastX, lastY) && other.InRect(lastX, lastY);
298 }
299
300 //if (cut)
301 ////printf("(%d,%d)-(%d,%d) corta a (%d,%d)-(%d,%d) en (%d, %d)\n", (s32)x1, (s32)y1,
302 // (s32)x2, (s32)y2, (s32)other.X1(), (s32)other.Y1(), (s32)other.X2(), (s32)other.Y2(), (s32)lastX, (s32)lastY);
303 return cut;
304 }
305
306 /** Carga el segmento.
307 * @param f Fichero abierto y posicionado para cargar el objeto.
308 * @return 0 si todo fue bien, 1 en caso de error de E/S, 2 en caso
309 * de error de integridad.
310 */
311 u32 Load(JFile &f)
312 {
313 if (0 != f.Read(&x1, sizeof(x1)) &&
314 0 != f.Read(&y1, sizeof(y1)) &&
315 0 != f.Read(&x2, sizeof(x2)) &&
316 0 != f.Read(&y2, sizeof(y2)))
317 {
318 RecalcM();
319
320 return 0;
321 }
322
323 return 1;
324 }
325
326 /** Salva el segmento.
327 * @param f Fichero abierto y posicionado para salvar el objeto.
328 * @return 0 si todo fue bien, 1 en caso de error de E/S, 2 en caso
329 * de error de integridad.
330 */
331 u32 Save(JFile &f)
332 {
333 if (0 != f.Write(&x1, sizeof(x1)) &&
334 0 != f.Write(&y1, sizeof(y1)) &&
335 0 != f.Write(&x2, sizeof(x2)) &&
336 0 != f.Write(&y2, sizeof(y2)))
337 {
338 return 0;
339 }
340
341 return 1;
342 }
343 };
344
345 const float J2DSegment::epsilon = 0.9f;
346
347 #endif // _J2DSEGMENT_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Definición de vector en 2D
23 * @file J2DVector.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 05/01/2004
26 * @version 0.0.1 - 05/01/2004 - Primera versión.
27 */
28
29 #ifndef _J2DVECTOR_INCLUDED
30 #define _J2DVECTOR_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Util/JLoadSave.h>
34 #include <math.h>
35
36 typedef float J2DScalar; /**< Escalar en 2D. */
37
38 /** Encapsula un vector en el plano y las operaciones más comunes.
39 */
40 class J2DVector : public JLoadSave
41 {
42 public:
43 J2DScalar x; /**< Coordenada x. */
44 J2DScalar y; /**< Coordenada y. */
45
46 public:
47 /** Crea un vector en el plano de coordenadas (0,0).
48 */
49 J2DVector() : x(0), y(0) {};
50
51 /** Crea un vector en el plano con las componentes dadas.
52 * @param _x Componente x del vector.
53 * @param _y Componente y del vector.
54 */
55 J2DVector(const J2DScalar& _x, const J2DScalar& _y)
56 : x(_x), y(_y) {};
57
58 /** Crea un vector en el plano apartir del array dado.
59 * @param arr Array con los dos valores x, y, en ese orden.
60 */
61 J2DVector(const J2DScalar *arr)
62 : x(arr[0]), y(arr[1]) {};
63
64 /** Devuelve la coordenada x.
65 * @return Coordenada x.
66 */
67 const J2DScalar& X()
68 {
69 return x;
70 }
71
72 /** Devuelve la coordenada y.
73 * @return Coordenada y.
74 */
75 const J2DScalar& Y()
76 {
77 return y;
78 }
79
80 /** Establece la coordenada x.
81 * @param _x Coordenada x.
82 */
83 void X(const J2DScalar& _x)
84 {
85 x = _x;
86 }
87
88 /** Establece la coordenada y.
89 * @param _y Coordenada y.
90 */
91 void Y(const J2DScalar& _y)
92 {
93 y = _y;
94 }
95
96 /** Comparación de vectores.
97 * @param v vector a comparar.
98 * @return <b>true</b> si son iguales, <b>false</b> si no.
99 */
100 const bool operator == (const J2DVector& v) const
101 {
102 return (v.x==x && v.y==y);
103 }
104
105 /** Comparación de vectores.
106 * @param v vector a comparar.
107 * @return <b>true</b> si son diferentes, <b>false</b> si no.
108 */
109 const bool operator != (const J2DVector& v) const
110 {
111 return (v.x!=x || v.y!=y);
112 }
113
114 /** Devuelve un vector que es la negación de este.
115 * @return Vector negado.
116 */
117 const J2DVector operator - () const
118 {
119 return J2DVector(-x, -y);
120 }
121
122 /** Asignación.
123 * @param v Vector a asignar a este.
124 * @return Este vector.
125 */
126 const J2DVector& operator = (const J2DVector& v)
127 {
128 x = v.x;
129 y = v.y;
130
131 return *this;
132 }
133
134 /** Asignación.
135 * @param xx Nuevo valor de x.
136 * @param yy Nuevo valor de y.
137 */
138 void Pos(J2DScalar xx, J2DScalar yy)
139 {
140 x = xx;
141 y = yy;
142 }
143
144 /** Incremento.
145 * @param v Vector por el que se incrementará el valor de este.
146 * @return Este vector.
147 */
148 const J2DVector& operator += (const J2DVector& v)
149 {
150 x += v.x;
151 y += v.y;
152
153 return *this;
154 }
155
156 /** Decremento.
157 * @param v Vector por el que se decrementará el valor de este.
158 * @return Este vector.
159 */
160 const J2DVector& operator -= (const J2DVector& v)
161 {
162 x -= v.x;
163 y -= v.y;
164
165 return *this;
166 }
167
168 /** Multiplicación por escalar. Multiplica cada componente por el escalar
169 * dado.
170 * @param s Escalar por el que multiplicar.
171 * @return Este vector.
172 */
173 const J2DVector& operator *= (const J2DScalar& s)
174 {
175 x *= s;
176 y *= s;
177
178 return *this;
179 }
180
181 /** División por escalar.Divide cada componente por el escalar dado.
182 * @param s Escalar por el que dividir.
183 * @return Este vector.
184 */
185 const J2DVector& operator /= (const J2DScalar& s)
186 {
187 const J2DScalar r = 1/s;
188 x *= r;
189 y *= r;
190
191 return *this;
192 }
193
194 /** Suma. Devuelve un nuevo vector que es la suma de este y el dado.
195 * @param v Vector a sumar con este.
196 * @return Vector resultado de la suma.
197 */
198 const J2DVector operator + (const J2DVector& v) const
199 {
200 return J2DVector(x + v.x, y + v.y);
201 }
202
203 /** Resta. Devuelve un nuevo vector que es la resta de este y el dado.
204 * @param v Vector a restar de este.
205 * @return Vector resultado de la resta.
206 */
207 const J2DVector operator - (const J2DVector& v) const
208 {
209 return J2DVector(x - v.x, y - v.y);
210 }
211
212 /** Post-multiplicación por escalar.
213 * Es el resultado de hacer v * s, en ese orden.
214 * @param s Escalar por el que multiplicar.
215 * @return Nuevo objeto vector resultado de la multiplicación.
216 */
217 const J2DVector operator * (const J2DScalar& s) const
218 {
219 return J2DVector( x*s, y*s);
220 }
221
222 /** Pre-multiplicación por escalar.
223 * Es el resultado de hacer s * v, en ese orden.
224 * @param s Escalar por el que multiplicar.
225 * @param v Vector.
226 * @return Nuevo objeto vector resultado de la multiplicación.
227 */
228 friend inline const J2DVector operator * (const J2DScalar& s, const J2DVector& v)
229 {
230 return v*s;
231 }
232
233 /** Divide todas las componentes.
234 * Este método no modifica al objeto vector actual.
235 * @param s Escalar por el que dividir.
236 * @return Nuevo objeto vector con el resultado.
237 */
238 const J2DVector operator / (J2DScalar s) const
239 {
240 s = 1/s;
241 return J2DVector(s*x, s*y);
242 }
243
244 /** Realiza el producto escalar por el vector dado.
245 * El producto escalar de dos vectores v1 y v2 se define como
246 * v1 · v2 = (x1*x2) + (y1*y2) + (z1*z2)
247 * @param v Vector con el que calcular el producto escalar.
248 * @return Valor del producto escalar.
249 */
250 const J2DScalar Dot(const J2DVector& v) const
251 {
252 return x*v.x + y*v.y;
253 }
254
255 /** Calcula la longitud (norma)
256 * @return La longitud del vector.
257 */
258 const float Length() const
259 {
260 return (J2DScalar)sqrt((double)this->Dot(*this));
261 }
262
263 /** Calcula y devuelve un vector perpendicular a este.
264 * El vector normal resultado es N=(y, -x), con x e y las componentes de este vector.
265 * @return Vector normal
266 */
267 const J2DVector Normal() const
268 {
269 return J2DVector(y, -x);
270 }
271
272 /** Carga el objeto
273 * @param f Fichero posicionado sobre este objeto
274 */
275 u32 Load(JFile &f)
276 {
277 // Carga las coordenadas de los puntos
278 if (0 != f.Read(&x, sizeof(x)) &&
279 0 != f.Read(&y, sizeof(y)))
280 {
281 return 0;
282 }
283
284 return 1;
285 }
286
287 /** Salva el objeto
288 * @param f Fichero posicionado sobre este objeto
289 */
290 u32 Save(JFile &f)
291 {
292 // Salva las coordenadas de los puntos
293 if (0 != f.Write(&x, sizeof(x)) &&
294 0 != f.Write(&y, sizeof(y)))
295 {
296 return 0;
297 }
298
299 return 1;
300 }
301 };
302
303 typedef J2DVector J2DPoint; // Posición 2D
304
305 #endif // _J2DVECTOR_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Base ortonormal respecto a un padre.
23 * @file JBasis.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 30/04/2003
26 * @version 0.0.1 - 30/04/2003 - Primera versión.
27 */
28
29 #ifndef _JBASIS_INCLUDED
30 #define _JBASIS_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Util/JObject.h>
34
35 /** Base de vectores ortonormales, respecto a un padre.
36 */
37 class JBasis
38 {
39 public:
40 JMatrix R; /**< Vectores base en columnas */
41
42 public:
43 /** Crea una base.
44 */
45 JBasis(){};
46
47 /** Crea una base a partir de sus vectores columna.
48 */
49 JBasis(const JVector& v0,
50 const JVector& v1,
51 const JVector& v2) : R(v0, v1, v2){};
52
53 /** Crea una base a partir de una matriz. Las columnas son los vectores
54 * base.
55 */
56 JBasis(const JMatrix& m) : R(m) {}
57
58 /** Acceso indexado a los vectores columna.
59 * @param i Índice del vector columna a ser recuperado (0, 1 ó 2).
60 * @return Vector columna pedido.
61 */
62 const JVector& operator [] (s32 i) const { return R.C[i]; }
63
64 /** Función de acceso al primer vector columna.
65 * Es equivalente a usar operator [0].
66 * @return Primer vector columna.
67 */
68 const JVector& X() const { return R.C[0]; }
69
70 /** Función de acceso al segundo vector columna.
71 * Es equivalente a usar operator [1].
72 * @return Segundo vector columna.
73 */
74 const JVector& Y() const { return R.C[1]; }
75
76 /** Función de acceso al tercer vector columna.
77 * Es equivalente a usar operator [2].
78 * @return Tercer vector columna.
79 */
80 const JVector& Z() const { return R.C[2]; }
81
82 /** Devuelve la matriz de base. Sus columnas son los vectores que
83 * forman la base.
84 * @return Matriz de base.
85 */
86 const JMatrix& Basis() const { return R; }
87
88 /** Establece la base a partir de sus vectores.
89 * @param v0 Primer vector base.
90 * @param v1 Segundo vector base.
91 * @param v2 Tercer vector base.
92 */
93 void Basis(const JVector& v0, const JVector& v1, const JVector& v2)
94 {
95 this->R[0] = v0;
96 this->R[1] = v1;
97 this->R[2] = v2;
98 }
99
100 /** Rotación de mano derecha en torno al primer vector base (X).
101 * @param a Angulo de rotación en radianes.
102 */
103 void RotateAboutX(const JScalar& a)
104 {
105 if(0 != a) // No se rota 0
106 {
107 JVector b1 = this->Y()*cosf(a) + this->Z()*sinf(a); // Rota X
108 JVector b2 = -this->Y()*sinf(a) + this->Z()*cosf(a); // Rota Z
109
110 // Establece la base
111 this->R[1] = b1;
112 this->R[2] = b2;
113 // X no camia
114 }
115 }
116
117 /** Rotación de mano derecha en torno al segundo vector base (Y).
118 * @param a Angulo de rotación en radianes.
119 */
120 void RotateAboutY(const JScalar& a)
121 {
122 if(0 != a) // No se rota 0
123 {
124 JVector b2 = this->Z()*cosf(a) + this->X()*sinf(a); // Rota Z
125 JVector b0 = -this->Z()*sinf(a) + this->X()*cosf(a); // Rota Y
126
127 // Establece la base
128 this->R[2] = b2;
129 this->R[0] = b0;
130 // Y no camia
131 }
132 }
133
134 /** Rotación de mano derecha en torno al tercer vector base (Z).
135 * @param a Angulo de rotación en radianes.
136 */
137 void RotateAboutZ(const JScalar& a)
138 {
139 if(0 != a) // No se rota 0
140 {
141 // No cambiar la base mientras se hace la operación
142 JVector b0 = this->X()*cosf(a) + this->Y()*sinf(a); // Rota X
143 JVector b1 = -this->X()*sinf(a) + this->Y()*cosf(a); // Rota Y
144
145 // Establece la base
146 this->R[0] = b0;
147 this->R[1] = b1;
148 // Z no cambia
149 }
150 }
151
152 /** Rotación de mano derecha en torno al eje dado.
153 * @param theta Angulo de rotación en radianes.
154 * @param u Vector director del eje de rotación.
155 */
156 void Rotate(const JScalar& theta, const JVector& u)
157 {
158 JBasis ZInv, ZZ, YInv, YY, U;
159 JVector v;
160
161 // Giro hasta el plano YZ
162 v = u;
163 v.x = 0.0f;
164 ZZ.RotateAboutZ(acosf(1.0f - v.Length()));
165 ZInv = ZZ.R.Inverse();
166
167 // Giro hasta el plano XY
168 v = u;
169 v.z = 0.0f;
170 YY.RotateAboutY(acosf(1.0f - v.Length()));
171 YInv = YY.R.Inverse();
172
173 // Giro en eje Z
174 U.R = this->R;
175 U.RotateAboutZ(theta);
176 this->R = ZInv.R * YInv.R * U.R * YY.R * ZZ.R;
177 }
178
179 // Rotación, la longitud 'da' es theta, la dirección unitaria de 'da' es u
180 void Rotate(const JVector& da);
181
182 /** Espresa en coordenadas de esta base el vector dado en coordenadas
183 * de la base padre.
184 * @param v Vector expresado en coordenadas de la base padre.
185 * @return Vector expresado en coordenadas de esta base.
186 */
187 const JVector TransformVectorToLocal(const JVector& v) const
188 {
189 return JVector(R.C[0].Dot(v), R.C[1].Dot(v), R.C[2].Dot(v));
190 }
191
192 /** Espresa en coordenadas de la base padre el vector dado en coordenadas
193 * de esta base.
194 * @param v Vector expresado en coordenadas de esta base.
195 * @return Vector expresado en coordenadas de la base padre.
196 */
197 const JPoint TransformVectorToParent(const JVector& v) const
198 {
199 return R.C[0] * v.x + R.C[1] * v.y + R.C[2] * v.z;
200 }
201 };
202
203 #endif // _JBASIS_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Eje de coordenadas (base + origen)
23 * @file JCoordAxes.h
24 * @author: Juan Carlos Seijo Pérez
25 * @date 30/04/2003
26 * @version 0.0.1 - 30/04/2003 - Primera versión.
27 */
28
29 #ifndef _JCOORDAXES_INCLUDED
30 #define _JCOORDAXES_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33
34 /** Encapsula unos ejes coordenados consistentes en una base definida
35 * por 3 vectores y un punto en el espacio, el origen.
36 */
37 class JCoordAxes : public JBasis
38 {
39 public:
40 JPoint O; /**< Origen de coordenadas relativo al origen del padre. */
41
42 public:
43 /** Crea unos ejes coordenados.
44 */
45 JCoordAxes(){}
46
47 /** Crea unos ejes coordenados a partir de los vectores base y el origen.
48 * @param o Origen de coordenadas.
49 * @param v0 Vector base 0
50 * @param v1 Vector base 1
51 * @param v2 Vector base 2
52 */
53 JCoordAxes(const JPoint& o,
54 const JVector& v0,
55 const JVector& v1,
56 const JVector& v2) : JBasis (v0, v1, v2), O(o){};
57
58 /** Crea unos ejes coordenados a partir de la base y el origen.
59 * @param o Origen de coordenadas.
60 * @param b Base de vectores.
61 */
62 JCoordAxes(const JPoint& o,
63 const JBasis& b) : JBasis (b), O(o) {};
64
65 /** Devuelve el origen de coordenadas.
66 * @return Origen de coordenadas.
67 */
68 const JPoint& Position() const { return O; }
69
70 /** Establece el origen de coordenadas.
71 * @param p Nuevo origen de coordenadas.
72 */
73 void Position(const JPoint& p) { O = p; }
74
75 /** Transforma las coordenadas de un punto a coordenadas locales.
76 * Dado un punto en el sistema de referencia al que se refiere la
77 * base de estos ejes coordenados, devuelve el punto correspondiente
78 * respecto de esta base.
79 * @param p Punto a transformar.
80 * @return Punto referido a la base de estos ejes coordenados.
81 */
82 const JPoint transformPointToLocal(const JPoint& p) const
83 {
84 // Traslada al origen local y luego proyecta en la base local
85 return TransformVectorToLocal(p - O);
86 }
87
88 /** Transforma las coordenadas de un punto a coordenadas del padre.
89 * Dado un punto en este sistema de referencia, devuelve el punto
90 * correspondiente respecto del sistema de referencia en el que están
91 * expresados los vectores de esta base.
92 * @param p Punto a transformar.
93 * @return Punto referido a la base padre de estos ejes coordenados.
94 */
95 const JPoint TransformPointToParent(const JPoint& p) const
96 {
97 // Transforma las coordenadas y traslada este origen
98 return TransformVectorToParent(p) + O;
99 }
100
101 /** Traslada el origen por el vector dado.
102 * @param v Vector de desplazamiento.
103 */
104 void Translate(const JVector& v)
105 {
106 O += v;
107 }
108 };
109
110 #endif // _JCOORDAXES_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Inclusión general para tipos y funciones matemáticas.
23 * @file JMath.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 29/03/2003
26 * @version 0.0.1 - 29/03/2003 - Primera versión.
27 */
28
29 #ifndef _JMATH_INCLUDED
30 #define _JMATH_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <math.h>
34 #include <JLib/Math/JVector.h>
35 #include <JLib/Math/JMatrix.h>
36 #include <JLib/Math/JBasis.h>
37 #include <JLib/Math/JCoordAxes.h>
38
39 #endif // _JMATH_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Matriz 3x3.
23 * @file JMatrix.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 30/04/2003
26 * @version 0.0.1 - 30/04/2003 - Primera versión.
27 */
28
29 #ifndef _JMATRIX_INCLUDED
30 #define _JMATRIX_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33
34 /** Representa una matriz tridimensional mediante 3 vectores en columna.
35 */
36 class JMatrix
37 {
38 public:
39 JVector C[3]; /**< Vectores columna */
40
41 public:
42
43 /** Crea una nueva matriz. La matriz es la matriz identidad.
44 */
45 JMatrix()
46 {
47 // Matriz identidad
48 C[0].x = 1;
49 C[1].y = 1;
50 C[2].z = 1;
51 }
52
53 /** Crea la matriz a partir de tres vectores columna.
54 * @param c0 Vector columna 0.
55 * @param c1 Vector columna 1.
56 * @param c2 Vector columna 2.
57 */
58 JMatrix(const JVector& c0, const JVector& c1, const JVector& c2)
59 {
60 C[0] = c0;
61 C[1] = c1;
62 C[2] = c2;
63 }
64
65 /** Acceso indexado.
66 * @note Si se usa con el del vector el acceso es <b>M[columna][fila]</b>,
67 * (y NO el estándar M[fila][columna]).
68 * @param i Índice del vector columna a recuperar (0, 1 ó 2).
69 */
70 JVector& operator [] (s32 i)
71 {
72 return C[i];
73 }
74
75 /** Comparación de matrices.
76 * @param m Matriz a comparar con esta.
77 * @return <b>true</b> en caso de ser iguales, <b>false</b> si no.
78 */
79 const bool operator == (const JMatrix& m) const
80 {
81 return C[0]==m.C[0] && C[1]==m.C[1] && C[2]==m.C[2];
82 }
83
84 /** Comparación de matrices.
85 * @param m Matriz a comparar con esta.
86 * @return <b>true</b> en caso de ser diferentes, <b>false</b> si no.
87 */
88 const bool operator != (const JMatrix& m) const
89 {
90 return !(m == *this);
91 }
92
93 /** Asigna una matriz a esta.
94 * @param m Matriz a asignar a esta.
95 * @return Este objeto matriz.
96 */
97 const JMatrix& operator = (const JMatrix& m)
98 {
99 C[0] = m.C[0];
100 C[1] = m.C[1];
101 C[2] = m.C[2];
102
103 return *this;
104 }
105
106 /** Incremento. Suma cada elemento de esta matriz con el
107 * correspondiente de la matriz dada.
108 * @param m Matriz a sumar a esta.
109 * @return Este objeto matriz.
110 */
111 const JMatrix& operator +=(const JMatrix& m)
112 {
113 C[0] += m.C[0];
114 C[1] += m.C[1];
115 C[2] += m.C[2];
116
117 return *this;
118 }
119
120 /** Decremento. Resta cada elemento de la matriz dada del
121 * correspondiente de esta matriz.
122 * @param m Matriz a restar de esta.
123 * @return Este objeto matriz.
124 */
125 const JMatrix& operator -=(const JMatrix& m)
126 {
127 C[0] -= m.C[0];
128 C[1] -= m.C[1];
129 C[2] -= m.C[2];
130
131 return *this;
132 }
133
134 /** Multiplica cada elemento de esta matriz por el escalar dado.
135 * Esta operación afecta al objeto matriz actual.
136 * @param s Escalar por el que multiplicar.
137 * @return Este objeto matriz.
138 */
139 const JMatrix& operator *= (const JScalar& s)
140 {
141 C[0] *= s;
142 C[1] *= s;
143 C[2] *= s;
144
145 return *this;
146 }
147
148 /** Multiplica esta matriz por la dada, en ese orden.
149 * Esta operación afecta al objeto matriz actual.
150 * @param m Matriz por la que multiplicar.
151 * @return Este objeto matriz.
152 */
153 const JMatrix& operator *= (const JMatrix& m)
154 {
155 // NOTA: No cambiar las columnas en medio de la operación
156 JMatrix temp = (*this);
157 C[0] = temp * m.C[0];
158 C[1] = temp * m.C[1];
159 C[2] = temp * m.C[2];
160
161 return *this;
162 }
163
164 /** Suma la matriz dada a esta.
165 * Esta operación devuelve un nuevo objeto matriz.
166 * @param m Matriz a sumar a esta.
167 * @return Nuevo objeto matriz resultado de la operación.
168 */
169 const JMatrix operator + (const JMatrix& m) const
170 {
171 return JMatrix(C[0] + m.C[0], C[1] + m.C[1], C[2] + m.C[2]);
172 }
173
174 /** Resta la matriz dada de esta.
175 * Esta operación devuelve un nuevo objeto matriz.
176 * @param m Matriz a restar a esta.
177 * @return Nuevo objeto matriz resultado de la operación.
178 */
179 const JMatrix operator - (const JMatrix& m) const
180 {
181 return JMatrix(C[0] - m.C[0], C[1] - m.C[1], C[2] - m.C[2]);
182 }
183
184 /** Multiplicación copia por un escalar.
185 * Esta operación crea un nuevo objeto matriz.
186 * @param s Escalar por el que multiplicar cada elemento.
187 * @return Nuevo objeto matriz resultado de la operación.
188 */
189 const JMatrix operator * (const JScalar& s) const
190 {
191 return JMatrix(C[0]*s, C[1]*s, C[2]*s);
192 }
193
194 /** Multiplicación propia por un escalar.
195 * Esta operación actúa sobre este objeto.
196 * @param s Escalar por el que multiplicar cada elemento de la matriz.
197 * @param m Matriz a multiplicar.
198 * @return Este objeto matriz resultado de la operación.
199 */
200 friend inline const JMatrix operator * (const JScalar& s, const JMatrix& m)
201 {
202 return m * s;
203 }
204
205 /** Post-Multiplicación copia por un vector (m * v).
206 * @param v Vector por el que multiplicar.
207 * @return Vector resultado de la operación.
208 */
209 const JVector operator * (const JVector& v) const
210 {
211 return(C[0]*v.x + C[1]*v.y + C[2]*v.z);
212 }
213
214 /** Pre-Multiplicación copia por un vector (v * m).
215 * @param v Vector por el que multiplicar.
216 * @param m Matriz a multiplicar.
217 * @return Vector resultado de la operación.
218 */
219 inline friend const JVector operator * (const JVector& v, const JMatrix& m)
220 {
221 return JVector(m.C[0].Dot(v), m.C[1].Dot(v), m.C[2].Dot(v));
222 }
223
224 /** Multiplica esta matriz por la dada en ese orden.
225 * Esta operación crea una nueva matriz.
226 * @param m Matriz a multiplicar.
227 * @return Nuevo objeto matriz resultado de la operación.
228 */
229 const JMatrix operator * (const JMatrix& m) const
230 {
231 return JMatrix((*this) * m.C[0], (*this) * m.C[1], (*this) * m.C[2]);
232 }
233
234 /** Devuelve la matriz traspuesta a esta.
235 * @return Nueva matriz resultado de la trasposición.
236 */
237 JMatrix Transpose() const
238 {
239 return JMatrix(JVector(C[0].x, C[1].x, C[2].x),
240 JVector(C[0].y, C[1].y, C[2].y),
241 JVector(C[0].z, C[1].z, C[2].z));
242 }
243
244 /** Devuelve el determinante de esta matriz.
245 * @return Valor del determinante de esta matriz.
246 */
247 const JScalar Determinant() const
248 {
249 return C[0].Dot(C[1].Cross(C[2]));
250 }
251
252 /** Devuelve una nueva matriz adjunta a esta.
253 * @return Matriz adjunta.
254 */
255 JMatrix Adjoint() const
256 {
257 JMatrix m;
258 m[0][0] = (C[1].y * C[2].z - C[2].y * C[1].z);
259 m[1][0] = -(C[0].y * C[2].z - C[2].y * C[0].z);
260 m[2][0] = (C[0].y * C[1].z - C[1].y * C[0].z);
261
262 m[0][1] = -(C[1].x * C[2].z - C[2].x * C[1].z);
263 m[1][1] = (C[0].x * C[2].z - C[2].x * C[0].z);
264 m[2][1] = -(C[0].x * C[1].z - C[1].x * C[0].z);
265
266 m[0][2] = (C[1].x * C[2].y - C[2].x * C[1].y);
267 m[1][2] = -(C[0].x * C[2].y - C[2].x * C[0].y);
268 m[2][2] = (C[0].x * C[1].y - C[1].x * C[0].y);
269
270 return m;
271 }
272
273 /** Devuelve una nueva matriz, inversa de esta.
274 * @return Matriz inversa a esta.
275 */
276 const JMatrix Inverse() const
277 {
278 JMatrix m;
279 JScalar j = Determinant();
280 if (j != 0)
281 {
282 // La inversa es la matriz adjunta traspuesta dividida por el determinante
283 m = Adjoint();
284 m = m.Transpose();
285 m *= 1.0f/Determinant();
286 }
287
288 return m;
289 }
290 };
291
292 #endif // _JMATRIX_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Vector en 3D.
23 * @file JVector.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 30/04/2003
26 * @version 0.0.1 - 30/04/2003 - Primera versión.
27 */
28
29 #ifndef _JVECTOR_INCLUDED
30 #define _JVECTOR_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Util/JObject.h>
34 #include <math.h>
35
36 typedef float JScalar; /**< Escalar decimal */
37
38 /** Encapsula un vector en el espacio de coordenadas (x, y, z) y
39 * las operaciones más comunes entre vectores.
40 */
41 class JVector
42 {
43 public:
44 JScalar x; // Coordenada x
45 JScalar y; // Coordenada y
46 JScalar z; // Coordenada z
47
48 public:
49 /** Crea un vector.
50 */
51 JVector() : x(0), y(0), z(0) {};
52
53 /** Crea un vector con los valores dados.
54 * @param _x Valor de la componente x
55 * @param _y Valor de la componente y
56 * @param _z Valor de la componente z
57 */
58 JVector(const JScalar& _x, const JScalar& _y, const JScalar& _z)
59 : x(_x), y(_y), z(_z) {};
60
61 /** Crea un vector a partir del array de valores.
62 * El array debe contener al menos 3 elementos que se asignarán,
63 * respectivamente, a las componentes 'x', 'y' y 'z'.
64 */
65 JVector(const JScalar *arr)
66 : x(arr[0]), y(arr[1]), z(arr[2]) {};
67
68 /** Acceso indexado.
69 * @param i Índice de la componente a recuperar (0 para x, 1 para y,
70 * 2 para z).
71 * @return Coordenada pedida.
72 */
73 JScalar& operator [] (const s32 i)
74 {
75 return *((&x) + i);
76 }
77
78 /** Determina si el vector dado es igual a este.
79 * Dos vectores son iguales si todas sus componentes son iguales.
80 * El resultado podría no ser el esperado debido a errores de precisión.
81 * En estos casos se debe usar el método NearlyEquals() para tener en
82 * cuenta esta imprecisión.
83 * @param v Vector a comparar con este.
84 * @return <b>true</b> si son iguales, <b>false</b> si no.
85 */
86 const bool operator == (const JVector& v) const
87 {
88 return (v.x==x && v.y==y && v.z==z);
89 }
90
91 /** Determina si el vector dado es diferente a este.
92 * El resultado podría no ser el esperado debido a errores de precisión.
93 * En estos casos se debe usar el método NearlyEquals() para tener en
94 * cuenta esta imprecisión.
95 * @param v Vector a comparar con este.
96 * @return <b>true</b> si son diferentes, <b>false</b> si no.
97 */
98 const bool operator != (const JVector& v) const
99 {
100 return !(v == *this);
101 }
102
103 /** Devuelve un vector que es la negación de este, es decir,
104 * con todas las coordenadas cambiadas de signo.
105 */
106 const JVector operator - () const
107 {
108 return JVector(-x, -y, -z);
109 }
110
111 /** Asigna otro vector a este.
112 * @param v Vector que se quiere asignar a este.
113 * @return Este objeto.
114 */
115 const JVector& operator = (const JVector& v)
116 {
117 x = v.x;
118 y = v.y;
119 z = v.z;
120
121 return *this;
122 }
123
124 /** Suma un vector dado a este vector. A diferencia del operador
125 * '+', este operador no crea un objeto nuevo.
126 * @param v Vector a sumar a este.
127 * @return Este objeto.
128 */
129 const JVector& operator += (const JVector& v)
130 {
131 x += v.x;
132 y += v.y;
133 z += v.z;
134
135 return *this;
136 }
137
138 /** Resta un vector dado a este vector. A diferencia del operador
139 * '-', este operador no crea un objeto nuevo.
140 * @param v Vector a restar a este.
141 * @return Este objeto.
142 */
143 const JVector& operator -= (const JVector& v)
144 {
145 x -= v.x;
146 y -= v.y;
147 z -= v.z;
148
149 return *this;
150 }
151
152 /** Multiplica cada componente por el escalar dado.
153 * @param s Escalar por el que multiplicar.
154 * @return Este objeto.
155 */
156 const JVector& operator *= (const JScalar& s)
157 {
158 x *= s;
159 y *= s;
160 z *= s;
161
162 return *this;
163 }
164
165 /** Divide cada componente por un escalar.
166 * A diferencia del operador '/' este no crea un nuevo objeto.
167 * @param s Escalar por el que dividir.
168 * @return Este objeto.
169 */
170 const JVector& operator /= (const JScalar& s)
171 {
172 const JScalar r = 1/s;
173 x *= r;
174 y *= r;
175 z *= r;
176
177 return *this;
178 }
179
180 /** Devuelve la suma de este vector y el vector dado.
181 * Este método no modifica el objeto vector actual, devuelve
182 * un nuevo objeto.
183 * @param v Vector a sumar a este.
184 * @return Vector resultado de la suma de este y el vector dado.
185 */
186 const JVector operator + (const JVector& v) const
187 {
188 return JVector(x + v.x, y + v.y, z + v.z);
189 }
190
191 /** Devuelve la resta de este vector y el vector dado.
192 * Este método no modifica el objeto vector actual, devuelve
193 * un nuevo objeto.
194 * @param v Vector a restar a este.
195 * @return Vector resultado de la resta de este y el vector dado.
196 */
197 const JVector operator - (const JVector& v) const
198 {
199 return JVector(x - v.x, y - v.y, z - v.z);
200 }
201
202 /** Post-multiplicación por escalar.
203 * Es el resultado de hacer v * s, en ese orden.
204 * @param s Escalar por el que multiplicar.
205 * @return Nuevo objeto vector resultado de la multiplicación.
206 */
207 const JVector operator * (const JScalar& s) const
208 {
209 return JVector( x*s, y*s, z*s);
210 }
211
212 /** Pre-multiplicación por escalar.
213 * Es el resultado de hacer s * v, en ese orden.
214 * @param s Escalar por el que multiplicar.
215 * @param v Vector.
216 * @return Nuevo objeto vector resultado de la multiplicación.
217 */
218 friend inline const JVector operator * (const JScalar& s, const JVector& v)
219 {
220 return v*s;
221 }
222
223 /** Divide todas las componentes.
224 * Este método no modifica al objeto vector actual.
225 * @param s Escalar por el que dividir.
226 * @return Nuevo objeto vector con el resultado.
227 */
228 const JVector operator / (JScalar s) const
229 {
230 s = 1/s;
231 return JVector(s*x, s*y, s*z);
232 }
233
234 /** Realiza el producto vectorial de este vector por el vector dado,
235 * en ese orden.
236 * @param v Vector con el que realizar el producto vectorial.
237 * @return Nuevo objeto vector con el resultado.
238 */
239 const JVector Cross(const JVector& v) const
240 {
241 return JVector(y*v.z - z*v.y, z*v.x - x*v.z, x*v.y - y*v.x);
242 }
243
244 /** Realiza el producto escalar por el vector dado.
245 * El producto escalar de dos vectores v1 y v2 se define como
246 * v1 · v2 = (x1*x2) + (y1*y2) + (z1*z2)
247 * @param v Vector con el que calcular el producto escalar.
248 * @return Valor del producto escalar.
249 */
250 const JScalar Dot(const JVector& v) const
251 {
252 return x*v.x + y*v.y + z*v.z;
253 }
254
255 /** Determina la longitud (norma) del vector.
256 * @return Longitud del vector.
257 */
258 const JScalar Length() const
259 {
260 return (JScalar)sqrt((double)this->Dot(*this));
261 }
262
263 /** Devuelve un vector unitario en el sentido de este.
264 * Esta operación no modifica a este vector actual.
265 * @return Nuevo vector unitario.
266 */
267 const JVector Unit() const
268 {
269 return (*this) / Length();
270 }
271
272 /** Convierte este vector en vector unitario (longitud 1).
273 */
274 void Normalize()
275 {
276 (*this) /= Length();
277 }
278
279 /** Determina si dos vectores son iguales con un margen de error 'e'.
280 * Esta función se usa en los casos en que a precisión del redondeo decimal
281 * se deba tener en cuenta.
282 * @param v Vector a comparar con este.
283 * @param e Margen de error positivo/negativo en cada componente.
284 * @return <b>true</b> si son iguales dentro del margen dado <b>false</b> si no.
285 */
286 const bool NearlyEquals(const JVector& v, const JScalar e) const
287 {
288 return fabs(x - v.x) < e && fabs(y - v.y) < e && fabs(z - v.z) < e;
289 }
290 };
291
292 typedef JVector JPoint; /**< Posición 3D */
293
294 #endif // _JVECTOR_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Definiciones para controlar el estado de un sólido rígido.
23 * @file JRigidBodyState.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 30/04/2003
26 * @version 0.0.1 - 30/04/2003 - Primera versión.
27 */
28
29 #ifndef _JRIGIDBODYSTATE_INCLUDED
30 #define _JRIGIDBODYSTATE_INCLUDED
31
32 /** Encapsula métodos de cálculo de dinámica de sólido rígido.
33 */
34 class JRigidBodyState : public JCoordAxes
35 {
36 public:
37 JVector V; /**< Velocidad lineal en m/s */
38 JVector W; /**< Velocidad angular en rad/s */
39 JMatrix I; /**< Tensor de inercia en coordenadas de mundo, kg m m */
40 JMatrix I_inv; /**< Inverso del tensor de inercia en coordenadas de mundo */
41
42 public:
43 /** Crea un nuevo controlador de estado de sólido rígido. */
44 JRigidBodyState() {}
45
46 /** Crea un nuevo controlador de estado de sólido rígido
47 * con la velocidad lineal y angular.
48 * @param v Velocidad lineal.
49 * @param w Velocidad angular.
50 */
51 JRigidBodyState(const JVector& v, const JVector& w) : V (v), W (w) {}
52
53 /** Devuelve la velocidad lineal
54 * @return Velocidad lineal del sólido.
55 */
56 const JVector& Velocity() const { return V; }
57
58 /** Establece la velocidad lineal.
59 * @param v Velocidad lineal.
60 */
61 void Velocity(const JVector& v) { V = v; }
62
63 /** Devuelve la velocidad angular
64 * @return Velocidad angular del sólido.
65 */
66 const JVector& AngularVelocity() const { return W; }
67
68 /** Establece la velocidad angular.
69 * @param v Velocidad angular.
70 */
71 void AngularVelocity(const JVector& v) {W = v;}
72
73 /** Devuelve el tensor de inercia.
74 * @return Tensor de inercia del sólido.
75 */
76 const JMatrix& inertiaTensor() const { return I; }
77
78 /** Devuelve el inverso del tensor de inercia.
79 * @return Inverso del tensor de inercia del sólido.
80 */
81 const JMatrix& InverseInertiaTensor() const { return I_inv; }
82
83 /** Calcula el tensor de inercia y su inverso a partir
84 * de la orientacion actual y los momentos de inercia principales.
85 * @param ip Orientación actual.
86 * @todo Implementar.
87 */
88 void CalculateInertiaTensor(const JVector& ip);
89 };
90
91 #endif // _JRIGIDBODYSTATE_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Wrapper C++ para una muestra de audio de SDL_mixer.
23 * @file JChunk.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 25/03/2004
26 * @version 0.0.1 - 25/03/2004 - Primera versión.
27 */
28
29 #ifndef _JCHUNK_INCLUDED
30 #define _JCHUNK_INCLUDED
31
32 #include <SDL_mixer.h>
33
34 /** Encapsula una muestra de audio.
35 */
36 class JChunk
37 {
38 s32 last_channel; /**< Último canal en el que se reprodujo. */
39 Mix_Chunk *chunk; /**< Muestra asociada. */
40
41 public:
42 /** Crea una muestra vacía.
43 */
44 JChunk() : chunk(0)
45 {}
46
47 /** Libera los recursos asociados a esta muestra.
48 */
49 void Destroy()
50 {
51 if (chunk != 0)
52 {
53 // Stop() no se debe liberar en reproducción!
54 Mix_FreeChunk(chunk);
55 chunk = 0;
56 }
57 }
58
59 /** Libera los recursos asociados a esta muestra.
60 */
61 ~JChunk()
62 {
63 Destroy();
64 }
65
66 /** Carga una muestra de audio desde fichero. El archivo puede ser de
67 * tipo WAVE, AIFF, RIFF, OGG o VOC.
68 * @param filename Nombre del fichero de audio a abrir.
69 * @return <b>true</b> si todo fue bien, <b>false</b> en caso contrario.
70 */
71 bool LoadWave(const char *filename)
72 {
73 Destroy();
74 chunk = Mix_LoadWAV(filename);
75
76 return chunk != 0;
77 }
78
79 /** Establece el volumen de esta muestra. El volumen tiene un valor comprendido
80 * entre 0 y MIX_MAX_VOLUME (128 actualmente). Si el valor es negativo el volumen
81 * no cambia, si es mayor que el máximo, se establece al máximo.
82 * @param newVolume Nuevo valor para el volumen.
83 * @return Valor del volumen antiguo.
84 */
85 s32 Volume(s32 newVolume)
86 {
87 return Mix_VolumeChunk(chunk, newVolume);
88 }
89
90 /** Reproduce esta muestra.
91 * @param channel Canal en el que reproducir (o -1 para cualquiera libre).
92 * @param loops Número de veces a reproducir. -1 hace que se repita
93 * todo el tiempo.
94 * @return Canal donde se reproducirá la muestra ó -1 en caso de
95 * error. El error se podría deber a falta de canales libres.
96 */
97 s32 Play(s32 channel = -1, s32 loops = 0)
98 {
99 return (last_channel = Mix_PlayChannel(channel, chunk, loops));
100 }
101
102 /** Reproduce esta muestra con límite de tiempo.
103 * @param msMax Número máximo de milisegundos a reproducir de la muestra.
104 * @param channel Canal en el que reproducir (o -1 para cualquiera libre).
105 * @param loops Número de veces a reproducir. -1 hace que se repita
106 * todo el tiempo.
107 * @return Canal donde se reproducirá la muestra ó -1 en caso de
108 * error. El error se podría deber a falta de canales libres.
109 */
110 s32 PlayTimed(s32 msMax, s32 channel = -1, s32 loops = 0)
111 {
112 return (last_channel = Mix_PlayChannelTimed(channel, chunk, loops, msMax));
113 }
114
115 /** Reproduce esta muestra con un fundido.
116 * @param msFade Milisegundos de duración del efecto fade-in.
117 * @param channel Canal en el que reproducir (o -1 para cualquiera libre).
118 * @param loops Número de veces a reproducir. -1 hace que se repita
119 * todo el tiempo.
120 * @return Canal donde se reproducirá la muestra ó -1 en caso de
121 * error. El error se podría deber a falta de canales libres.
122 */
123 s32 FadeIn(s32 msFade, s32 channel = -1, s32 loops = 0)
124 {
125 return (last_channel = Mix_FadeInChannel(channel, chunk, loops, msFade));
126 }
127
128 /** Reproduce esta muestra con límite tiempo y un fundido.
129 * @param msFade Milisegundos de duración del efecto fade-in.
130 * @param msMax Número máximo de milisegundos a reproducir de la muestra.
131 * @param channel Canal en el que reproducir (o -1 para cualquiera libre).
132 * @param loops Número de veces a reproducir. -1 hace que se repita
133 * todo el tiempo.
134 * @return Canal donde se reproducirá la muestra ó -1 en caso de
135 * error. El error se podría deber a falta de canales libres.
136 */
137 s32 FadeInTimed(s32 msFade, s32 msMax, s32 channel = -1, s32 loops = 0)
138 {
139 return (last_channel = Mix_FadeInChannelTimed(channel, chunk, loops, msFade, msMax));
140 }
141
142
143 /** Pausa la reproducción.
144 * @see Resume(), Halt().
145 */
146 void Pause()
147 {
148 if (Mix_GetChunk(last_channel) == chunk)
149 {
150 Mix_Pause(last_channel);
151 }
152 }
153
154 /** Reanuda la reproducción.
155 * @see Pause(), Halt().
156 */
157 void Resume()
158 {
159 if (Mix_GetChunk(last_channel) == chunk)
160 {
161 Mix_Resume(last_channel);
162 }
163 }
164
165 /** Detiene la reproducción.
166 * @see Resume(), Pause().
167 */
168 void Halt()
169 {
170 if (Mix_GetChunk(last_channel) == chunk)
171 {
172 Mix_HaltChannel(last_channel);
173 }
174 }
175
176 /** Detiene la reproducción con un fundido.
177 * @param ms Milisegundos de fade.
178 */
179 void FadeOut(s32 ms)
180 {
181 if (Mix_GetChunk(last_channel) == chunk)
182 {
183 Mix_FadeOutChannel(last_channel, ms);
184 }
185 }
186
187 /** Determina si está reproduciendo o en pausa.
188 * @return <b>true</b> si se está reproduciendo, <b>false</b> si no.
189 */
190 bool IsPlaying()
191 {
192 if (Mix_GetChunk(last_channel) == chunk)
193 {
194 return 1 == Mix_Playing(last_channel);
195 }
196
197 return false;
198 }
199
200 /** Determina si está en pausa o parado.
201 * @return <b>true</b> si se está en pausa o parado, <b>false</b> si no.
202 */
203 s32 IsPaused()
204 {
205 if (Mix_GetChunk(last_channel) == chunk)
206 {
207 return Mix_Paused(last_channel);
208 }
209
210 return false;
211 }
212
213 /** Determina el estado de fade.
214 * @return MIX_NO_FADING si no hace fade o no está reproduciendo,
215 * MIX_FADING_IN si hace fade-in o MIX_FADING_OUT si hace fade-out.
216 */
217 s32 Fading()
218 {
219 if (Mix_GetChunk(last_channel) == chunk)
220 {
221 return Mix_Fading(last_channel);
222 }
223
224 return MIX_NO_FADING;
225 }
226
227 /** Devuelve el canal en el que se reproduce la muestra.
228 * @return Canal en el que reproduce el sonido o -1 si no se está reproduciendo.
229 */
230 s32 GetChannel()
231 {
232 if (Mix_GetChunk(last_channel) == chunk)
233 {
234 return last_channel;
235 }
236
237 return -1;
238 }
239
240 /** Devuelve si el objeto es válido o no.
241 * @return <b>true</b> si lo es, <b>false</b> si no.
242 */
243 bool Valid() {return chunk != 0;}
244
245 operator Mix_Chunk * () {return chunk;}
246 };
247
248 #endif // _JCHUNK_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Wrapper C++ para SDL_mixer.
23 * @author Juan Carlos Seijo Pérez
24 * @file JMixer.h
25 * @date 06/03/2004
26 * @version 0.0.1 - Primera versión. 06/03/2004.
27 */
28
29 #ifndef _JMIXER_INCLUDED
30 #define _JMIXER_INCLUDED
31
32 #include <SDL_mixer.h>
33 #include <JLib/Util/JTypes.h>
34 #include <JLib/Sound/JChunk.h>
35
36 /** Esta clase permite configurar los parámetros del sonido.
37 */
38 class JMixer
39 {
40 bool valid;
41
42 public:
43 /** Crea el objeto.
44 */
45 JMixer() : valid(false)
46 {}
47
48 /** Determina si el objeto está inicializado o no.
49 * @return <b>true</b> si se puede usar, <b>false</b> si no.
50 */
51 bool Valid() {return valid;}
52
53 /** Recupera la versión de SDL_mixer. El objeto devuelto tiene
54 * tres campos: major, minor y patch, que identifican la versión.
55 * @return La versión de SDL_mixer.
56 */
57 const SDL_version * GetLinkedVersion() {return Mix_Linked_Version();}
58
59 /** Establece los parámetros del audio. Este método reserva además 16 canales para la
60 * reproducción. Este parámetro se puede cambiar por medio de AllocateChannels().
61 * @param freq Frecuencia de muestreo (44.100 Hz, 22050 Hz, etc.) [22050].
62 * @param fmt Formato de la muestra (uno de AUDIO_{U|S}{8|16[LSB|MSB|SYS]}) [AUDIO_S16SYS].
63 * @param chann Número de canales de salida (1 - mono, 2 - stereo) [2].
64 * @param size Bytes por muestra [1024].
65 * @return 0 si todo fue bien, -1 en caso de no poderse inicializar SDL y -2 en caso
66 * de no poder abrir el dispositivo.
67 */
68 s32 Init(s32 freq = MIX_DEFAULT_FREQUENCY, Uint16 fmt = MIX_DEFAULT_FORMAT, s32 chann = 2, s32 size = 1024)
69 {
70 if (!SDL_WasInit(SDL_INIT_AUDIO))
71 {
72 if (SDL_Init(SDL_INIT_AUDIO) == -1)
73 {
74 return -1;
75 }
76 }
77
78 if (Mix_OpenAudio(freq, fmt, chann, size) == -1)
79 {
80 return -2;
81 }
82
83 valid = true;
84
85 AllocateChannels(16);
86
87 return 0;
88 }
89
90 /** Devuelve la cadena de error de SDL_mixer.
91 * @return Cadena del último error producido.
92 */
93 const char * GetError()
94 {
95 return Mix_GetError();
96 }
97
98 /** Recupera los parámetros del dispositivo de audio.
99 * @param freq Variable donde se guardará la frecuencia de muestreo.
100 * @param fmt Variable donde se guardará el formato de la muestra.
101 * @param chann Variable donde se guardará el número de canales.
102 * @return El número de veces que se ha abierto el dispositivo ó 0 (cero)
103 * si se produjo algún error.
104 */
105 s32 QuerySpec(s32 freq, u16 fmt, s32 chann)
106 {
107 return Mix_QuerySpec(&freq, &fmt, &chann);
108 }
109
110 /** Reserva canales de reproducción.
111 * Si el número de canales a reservar es menor que el actual, se paran
112 * los que están en exceso. Si fuese negativo se obtiene el número
113 * total de canales reservados, sin que esto afecte a los existentes.
114 * @param numChannels Número total de canales a reservar.
115 * @return Número de canales reservados en total.
116 */
117 s32 AllocateChannels(s32 numChannels)
118 {
119 return Mix_AllocateChannels(numChannels);
120 }
121
122 /** Establece el nivel de volumen de un canal.
123 * @param channel Canal a modificar (-1 para todos).
124 * @param volume Nuevo volumen del canal.
125 * @return Valor actual del volumen del canal o un promedio de todos si
126 * channel es -1.
127 */
128 s32 Volume(s32 channel = -1, s32 volume = MIX_MAX_VOLUME)
129 {
130 return Mix_Volume(channel, volume);
131 }
132
133 /** Pausa el canal especificado.
134 * @param channel Número de canal.
135 * @see Resume(), Halt().
136 */
137 void Pause(s32 channel = -1)
138 {
139 Mix_Pause(channel);
140 }
141
142 /** Reanuda la reproducción del canal especificado.
143 * @param channel Número de canal.
144 * @see Pause(), Halt().
145 */
146 void Resume(s32 channel = -1)
147 {
148 Mix_Resume(channel);
149 }
150
151 /** Detiene la reproducción del canal especificado.
152 * @param channel Número de canal.
153 * @see Resume(), Pause().
154 */
155 void Halt(s32 channel = -1)
156 {
157 Mix_HaltChannel(channel);
158 }
159
160 /** Detiene el canal con un fundido.
161 * @param ms Milisegundos de fade.
162 * @param channel Canal a detener.
163 * @return Número de canales a detener.
164 */
165 s32 FadeOut(s32 ms, s32 channel = -1)
166 {
167 return Mix_FadeOutChannel(channel, ms);
168 }
169
170 /** Determina si el canal dado está reproduciendo o en pausa.
171 * @param channel Canal a determinar ó -1.
172 * @return 1 si se está reproduciendo, 0 si no o el número de canales
173 * en reproducción o pausa en caso de ser channel = -1.
174 */
175 s32 Playing(s32 channel = -1)
176 {
177 return Mix_Playing(channel);
178 }
179
180 /** Determina si el canal dado está en pausa o parado.
181 * @param channel Canal a determinar ó -1.
182 * @return 1 si está en pausa o parado, 0 si no o el número de canales
183 * en pausa o detenidos en caso de ser channel = -1.
184 */
185 s32 Paused(s32 channel = -1)
186 {
187 return Mix_Paused(channel);
188 }
189
190 /** Determina el estado de fade del canal dado.
191 * @param channel Canal a determinar.
192 * @return MIX_NO_FADING si no hace fade, MIX_FADING_IN si hace fade-in
193 * o MIX_FADING_OUT si hace fade-out.
194 */
195 s32 Fading(s32 channel)
196 {
197 return Mix_Fading(channel);
198 }
199
200 /** Detiene la reproducción del canal especificado en un tiempo dado.
201 * @param ms Milisegundos a esperar antes de detenerlo.
202 * @param channel Número de canal.
203 * @see Halt().
204 */
205 void HaltTimed(s32 ms, s32 channel = -1)
206 {
207 Mix_ExpireChannel(channel, ms);
208 }
209
210 /** Cierra el dispositvo de audio.
211 */
212 void Destroy()
213 {
214 // La especificación no dice que se le puedan pasar ceros a Mix_QuerySpec().
215 s32 freq, chann;
216 u16 fmt;
217
218 // Debe cerrarse tantas veces como haya sido abierto
219 s32 numTimes = Mix_QuerySpec(&freq, &fmt, &chann);
220 for (int i = 0; i < numTimes; ++i)
221 {
222 Mix_CloseAudio();
223 }
224 }
225
226 /** Cierra el dispositvo de audio.
227 */
228 ~JMixer()
229 {
230 Destroy();
231 }
232 };
233
234 #endif // _JMIXER_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Definiciones de una interfaz de usuario.
23 * @file JUI.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 28/07/2004
26 * @version 0.0.1 - 28/07/2004 - Primera versión.
27 */
28
29 #ifndef _JUI_INCLUDED
30 #define _JUI_INCLUDED
31
32 #include <vector>
33 #include <JLib/Util/JTypes.h>
34 #include <JLib/UI/JUIElement.h>
35 #include <JLib/Graphics/JDrawable.h>
36
37 /** Clase de gestión de una interfaz de usuario.
38 * Gestiona los elementos de la interfaz y se encarga de gestionar el foco
39 * dentro de cada uno de ellos en base al estado del teclado y del ratón.
40 * Esta clase se encarga de dibujar cada uno de los elementos visibles de la
41 * interfaz así como de su actualización.
42 */
43 class JUI : public JDrawable
44 {
45 vector<JUIElement> elements; /**< Elementos de esta interfaz. */
46 vector<JUIElement*> visibles; /**< Elementos visibles. */
47 vector<JUIElement*> invisibles; /**< Elementos ocultos. */
48 vector<JUIElement*> focusables; /**< Elementos enfocables. */
49
50 /** Crea una interfaz vacía. Se deben añadir elementos mediante Add() o bien
51 * cargar una interfaz desde fichero con Load().
52 */
53 JUI();
54
55 /** Actualiza la interfaz.
56 */
57 s32 Update();
58
59 /** Dibuja la interfaz.
60 */
61 void Draw();
62
63 /** Destruye la interfaz. Destruye cada elemento del vector de elementos.
64 */
65 void Destroy();
66
67 /** Destructor de la clase.
68 */
69 ~JUI() {Destroy();}
70 };
71
72 #endif // _JUI_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clase para gestión de una ventana gráfica.
23 * @file JApp.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 01/04/2003
26 * @version 0.0.1 - Primera versión - 01/04/2003
27 */
28
29 #include <JLib/Util/JApp.h>
30
31 JApp * JApp::thisApp = 0;
32
33 // Constructor
34 JApp::JApp(const JString &strTitle, s32 w, s32 h, bool fullScr, s32 _depth, u32 otherFlags)
35 : active(true), paused(false), endLoop(false), title(strTitle), width(w), height(h), depth(_depth), fullScreen(fullScr),
36 doInput(true), flags(otherFlags), appPauseTime(0), keys(0), keyMods(KMOD_NONE), numKeys(0), mouseX(0), mouseY(0), mouseBt(0),
37 mouseRelX(0), mouseRelY(0), joyAxisX(0), joyAxisY(0), joyButton(0), fps(25), dumpVideoInfo(false), soundEnabled(false), iconName(0), screen(0), joystick(0)
38 {
39 __OnActive = 0;
40 __OnKeyUp = 0;
41 __OnKeyDown = 0;
42 __OnMouseMove = 0;
43 __OnMouseDown = 0;
44 __OnMouseUp = 0;
45 __OnJoyMove = 0;
46 __OnJoyBall = 0;
47 __OnJoyHat = 0;
48 __OnJoyUp = 0;
49 __OnJoyDown = 0;
50 __OnQuit = 0;
51 __OnSysWM = 0;
52 __OnResize = 0;
53 __OnExpose = 0;
54 __OnUser = 0;
55 thisApp = this;
56 }
57
58 // Inicializa la aplicación
59 bool JApp::Init()
60 {
61 if (-1 == SDL_Init(SDL_INIT_EVERYTHING))
62 {
63 return false;
64 }
65
66 if (dumpVideoInfo)
67 {
68 DumpVideoInfo();
69 }
70
71 if (fullScreen)
72 flags |= SDL_FULLSCREEN;
73
74 // Establecemos el icono
75 if (iconName)
76 {
77 JImage imgIcon;
78 if (!imgIcon.Load(iconName))
79 {
80 fprintf(stderr, "Couldn't load icon!: %s\n", iconName);
81 }
82 else
83 {
84 imgIcon.ColorKey(0, SDL_SRCCOLORKEY);
85 SDL_WM_SetIcon(imgIcon.Surface(), 0);
86 }
87 }
88
89 if ( (screen = SDL_SetVideoMode(width, height, depth, flags)) == 0 )
90 {
91 fprintf(stderr, "Error: Couldn't set video mode %s\n", SDL_GetError());
92 SDL_Delay(2000);
93 SDL_Quit();
94 return false;
95 }
96
97 if(SDL_NumJoysticks() > 0)
98 {
99 SDL_JoystickEventState(SDL_ENABLE);
100 joystick = SDL_JoystickOpen(0);
101
102 if(!joystick)
103 {
104 fprintf(stderr, "Warning: Joystick not initialized: %s\n", SDL_GetError());
105 }
106 }
107 else
108 {
109 joystick = 0;
110 }
111
112 // Initializes the font subsystem
113 if (!JFont::Init())
114 {
115 return false;
116 }
117
118 // Establecemos el título
119 SDL_WM_SetCaption(title, 0);
120
121 // Activamos la repetición de teclas
122 SDL_EnableKeyRepeat(300, 30);
123
124 // Inicializamos el array de teclas
125 keys = SDL_GetKeyState(&numKeys);
126
127 FPS(fps);
128
129 return true; // Todo OK
130 }
131
132 // Comprueba los eventos
133 bool JApp::UpdateEvents()
134 {
135 keys = SDL_GetKeyState(&numKeys);
136 keyMods = SDL_GetModState();
137
138 SDL_Event e;
139 while (SDL_PollEvent(&e))
140 {
141 switch(e.type)
142 {
143 case SDL_ACTIVEEVENT:
144 // Pasamos a estado de pausa
145 switch (e.active.state)
146 {
147 case SDL_APPMOUSEFOCUS:
148 //printf("Mouse focus %s!\n", e.active.gain == 0 ? "LOST" : "GAINED");
149 break;
150 case SDL_APPINPUTFOCUS:
151 //printf("Input focus %s!\n", e.active.gain == 0 ? "LOST" : "GAINED");
152 break;
153 case SDL_APPACTIVE:
154 // Pausa o reanuda la aplicación
155 e.active.gain == 0 ? Pause(true) : Pause(false);
156 break;
157 }
158
159 if (__OnActive)
160 {
161 __OnActive(e.active.gain != 0, (s32)e.active.state);
162 }
163 else
164 {
165 /**< @todo Averiguar por qué da problemas. */
166 //active = (e.active.gain != 1);
167 }
168 break;
169
170 case SDL_KEYDOWN:
171
172 // Actualiza el estado del teclado
173 keys = SDL_GetKeyState(&numKeys);
174 keyMods = SDL_GetModState();
175
176 if (__OnKeyDown)
177 {
178 __OnKeyDown(e.key.keysym);
179 }
180 break;
181
182 case SDL_KEYUP:
183
184 // Actualiza el estado del teclado
185 keys = SDL_GetKeyState(&numKeys);
186 keyMods = SDL_GetModState();
187
188 if (__OnKeyUp)
189 {
190 __OnKeyUp(e.key.keysym);
191 }
192 break;
193
194 case SDL_MOUSEMOTION:
195
196 // Actualiza el estado del ratón
197 SDL_GetMouseState(&mouseX, &mouseY);
198 SDL_GetRelativeMouseState(&mouseRelX, &mouseRelY);
199
200 if (__OnMouseMove)
201 {
202 __OnMouseMove(e.motion.x, e.motion.y, e.motion.state, e.motion.xrel, e.motion.yrel);
203 }
204 break;
205
206 case SDL_MOUSEBUTTONDOWN:
207
208 // Actualiza el estado de los botones del ratón
209 mouseBt = SDL_GetMouseState(&mouseX, &mouseY);
210
211 if (__OnMouseDown)
212 {
213 __OnMouseDown(e.button.button, e.button.x, e.button.y);
214 }
215 break;
216
217 case SDL_MOUSEBUTTONUP:
218
219 // Actualiza el estado de los botones del ratón
220 mouseBt = SDL_GetMouseState(&mouseX, &mouseY);
221
222 if (__OnMouseUp)
223 {
224 __OnMouseUp(e.button.button, e.button.x, e.button.y);
225 }
226 break;
227
228 case SDL_JOYAXISMOTION:
229 switch(e.jaxis.axis)
230 {
231 case 0:
232 joyAxisX = e.jaxis.value;
233 break;
234
235 case 1:
236 joyAxisY = e.jaxis.value;
237 break;
238
239 default:
240 break;
241 }
242
243 if (__OnJoyMove)
244 {
245 __OnJoyMove(e.jaxis.which, e.jaxis.axis, e.jaxis.value);
246 }
247 break;
248
249 case SDL_JOYBALLMOTION:
250 if (__OnJoyBall)
251 {
252 __OnJoyBall(e.jball.which, e.jball.ball, e.jball.xrel, e.jball.yrel);
253 }
254 break;
255
256 case SDL_JOYHATMOTION:
257 if (__OnJoyHat)
258 {
259 __OnJoyHat(e.jhat.which, e.jhat.hat, e.jhat.value);
260 }
261 break;
262
263 case SDL_JOYBUTTONDOWN:
264 joyButton = 1;
265
266 if (__OnJoyDown)
267 {
268 __OnJoyDown(e.jbutton.which, e.jbutton.button);
269 }
270 break;
271
272 case SDL_JOYBUTTONUP:
273 joyButton = 0;
274
275 if (__OnJoyUp)
276 {
277 __OnJoyUp(e.jbutton.which, e.jbutton.button);
278 }
279 break;
280
281 case SDL_QUIT:
282 if (__OnQuit)
283 {
284 __OnQuit();
285 }
286 Exit();
287 break;
288
289 case SDL_SYSWMEVENT:
290 if (__OnSysWM)
291 {
292 __OnSysWM();
293 }
294 break;
295
296 case SDL_VIDEORESIZE:
297
298 if (__OnResize)
299 {
300 __OnResize(e.resize.w, e.resize.h);
301 }
302 else
303 {
304 Resize(e.resize.w, e.resize.h, fullScreen);
305 }
306 break;
307
308 case SDL_VIDEOEXPOSE:
309 if (__OnExpose)
310 {
311 __OnExpose();
312 }
313 break;
314
315 case SDL_USEREVENT:
316 if (__OnUser)
317 {
318 __OnUser(e.user.code, e.user.data1, e.user.data2);
319 }
320 break;
321
322 default:
323 break;
324 }
325 }
326
327 return true;
328 }
329
330
331 // Bucle principal
332 s32 JApp::MainLoop()
333 {
334 while (!endLoop)
335 {
336 UpdateEvents();
337
338 if (active)
339 {
340 if (timer.Changed())
341 {
342 if (Update())
343 {
344 Draw();
345 }
346 else
347 {
348 printf("Error updating the app.\n");
349 }
350 }
351 }
352 else
353 {
354 sleep(1);
355 }
356 }
357
358 return 0;
359 }
360
361 // Pausa la aplicación. Devuelve los ms que lleva en pausa (false) o
362 // los transcurridos desde el inicio de la aplicación (true).
363 u32 JApp::Pause(bool doPause)
364 {
365 paused = doPause;
366 if (paused)
367 {
368 appPauseTime = SDL_GetTicks();
369 }
370 else
371 {
372 appPauseTime = SDL_GetTicks() - appPauseTime;
373 }
374
375 return appPauseTime;
376 }
377
378 // Cambia el tamaño de la ventana
379 void JApp::Resize(s32 w, s32 h, bool _fullScreen)
380 {
381 if ((fullScreen = _fullScreen))
382 flags |= SDL_FULLSCREEN;
383 else
384 flags &= ~SDL_FULLSCREEN;
385
386 SDL_Surface *surf;
387 surf = SDL_SetVideoMode(w, h, depth, flags);
388
389 if (surf)
390 {
391 screen = surf;
392 width = w;
393 height = h;
394 }
395 }
396
397 void JApp::FPS(s32 newFPS)
398 {
399 fps = newFPS;
400
401 if (fps < 0)
402 {
403 fps = 25;
404 }
405
406 timer.Start(1000/fps);
407 }
408
409 int JApp::ParseArg(char *args[], int argc)
410 {
411 if (args[0][0]!='-')
412 return -1; // error
413
414 switch (args[0][1])
415 {
416 // '-f' Fullscreen
417 case 'f':
418 flags |= SDL_FULLSCREEN;
419 return 0; // no arguments used
420
421 // '-w' En ventana
422 case 'w':
423 flags &= ~SDL_FULLSCREEN;
424 return 0; // no arguments used
425
426 // '-i' Muestra información del video
427 case 'i':
428 dumpVideoInfo = true;
429 return 0; // no arguments used
430
431 // '-m' Modo gráfico/tamaño de ventana
432 case 'm':
433 {
434 s32 w, h, bpp;
435 if (3 ==sscanf(args[0] + 2, "%d%*c%d%*c%d", &w, &h, &bpp))
436 {
437 if (w > 0 && h > 0 && bpp > 0)
438 {
439 width = w;
440 height = h;
441 depth = bpp;
442 }
443 }
444 }
445 return 0; // no arguments used
446 case '-':
447 {
448 switch (*(args[0] + 2))
449 {
450 case 'f':
451 if (strcmp((args[0] + 2), "fps") == 0)
452 {
453 if (argc<1) // I need at least 1 more argument
454 return -2;
455 fps = atoi(args[1]);
456 }
457 return 1; // 1 argument used
458 }
459 }
460 }
461 return -1; // error
462 }
463
464 void JApp::PrintUsage(char *program)
465 {
466 fprintf(stderr, "JApp v1.0. (C) Juan Carlos Seijo Pérez / 2002-2004.\n\n");
467 fprintf(stderr, "Usage: %s [-f]ullscreen [-w]indowed [--fps nnn] [-mWxHxBPP] [-i]nfo_of_video\n", program);
468 fprintf(stderr, "\n");
469 exit(0);
470 }
471
472 void JApp::ParseArgs(s32 argc, char **argv)
473 {
474 s32 i = 0;
475
476 while (++i < argc)
477 {
478 switch (*argv[i])
479 {
480 case '-':
481 switch (*(argv[i] + 1))
482 {
483 // '-h' opción: ayuda
484 case 'h':
485 PrintUsage(argv[0]);
486 break;
487
488 default:
489 // TODO: Preguntar a Miriam
490 // int n = ParseArg(argv+i, argc-2);
491 int n = ParseArg(argv+i, argc-i);
492 if (n>=0)
493 i += n;
494 else if (n==-1)
495 fprintf(stderr, "Unknown option: %s. Use -h to get help.\n", argv[i]);
496 else if (n==-2)
497 fprintf(stderr, "Not enough arguments to option: %s. Use -h to get help.\n", argv[i]);
498 else if (n<0)
499 fprintf(stderr, "Error in option option %s. Use -h to get help.\n", argv[i]);
500 break;
501 }
502 break;
503
504 default:
505 // treats it as the file name to load
506 int n = ParseArg(argv+i, argc-i);
507 if (n>=0)
508 i += n;
509 else if (n<0)
510 fprintf(stderr, "Error in parameter: %s. Use -h to get help.\n", argv[i]);
511 break;
512 }
513 }
514 }
515
516 void JApp::DumpVideoInfo()
517 {
518 const SDL_VideoInfo *vi = VideoInfo();
519
520 fprintf(stdout, "hw_available: %s\n", vi->hw_available ? "yes" : "no");
521 fprintf(stdout, "wm_available: %s\n", vi->wm_available ? "yes" : "no");
522 fprintf(stdout, " blit_hw: %s\n", vi->blit_hw ? "yes" : "no");
523 fprintf(stdout, " blit_hw_CC: %s\n", vi->blit_hw_CC ? "yes" : "no");
524 fprintf(stdout, " blit_hw_A: %s\n", vi->blit_hw_A ? "yes" : "no");
525 fprintf(stdout, " blit_sw: %s\n", vi->blit_sw ? "yes" : "no");
526 fprintf(stdout, " blit_sw_CC: %s\n", vi->blit_sw_CC ? "yes" : "no");
527 fprintf(stdout, " blit_sw_A: %s\n", vi->blit_sw_A ? "yes" : "no");
528 fprintf(stdout, " blit_fill: %s\n", vi->blit_fill ? "yes" : "no");
529 fprintf(stdout, "video memory: %d\n\n", vi->video_mem);
530
531 fprintf(stdout, "Current pixel format:\n");
532 fprintf(stdout, " BitsPerPixel: %d\n", vi->vfmt->BitsPerPixel);
533 fprintf(stdout, "BytesPerPixel: %d\n", vi->vfmt->BytesPerPixel);
534 fprintf(stdout,
535 " RGBAmask: R: 0x%08x G: 0x%08x B: 0x%08x A: 0x%08x\n",
536 vi->vfmt->Rmask, vi->vfmt->Gmask, vi->vfmt->Bmask, vi->vfmt->Amask);
537 fprintf(stdout,
538 " RGBAshift: R: 0x%08x G: 0x%08x B: 0x%08x A: 0x%08x\n",
539 vi->vfmt->Rshift, vi->vfmt->Gshift, vi->vfmt->Bshift, vi->vfmt->Ashift);
540 fprintf(stdout,
541 " RGBAloss: R: 0x%08x G: 0x%08x B: 0x%08x A: 0x%08x\n",
542 vi->vfmt->Rloss, vi->vfmt->Gloss, vi->vfmt->Bloss, vi->vfmt->Aloss);
543 fprintf(stdout, " ColorKey: 0x%08x\n", vi->vfmt->colorkey);
544 fprintf(stdout, " Alpha: 0x%02x\n", vi->vfmt->alpha);
545 }
546
547 void JApp::Icon(const char *filename)
548 {
549 free(iconName);
550
551 if (filename)
552 {
553 iconName = strdup(filename);
554 }
555 }
556
557 void JApp::Destroy()
558 {
559 free(iconName);
560 }
561
562 JApp::~JApp()
563 {
564 Destroy();
565 SDL_Quit();
566 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Base application class. Allows to init SDL and the other subsystems as sound.
23 * @file JApp.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 01/04/2003
26 * @version 0.0.1 - First version - 01/04/2003
27 */
28
29 #ifndef _JAPP_INCLUDED
30 #define _JAPP_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Util/JString.h>
34 #include <JLib/Util/JTimer.h>
35 #include <JLib/Graphics/JFont.h>
36 #include <JLib/Sound/JMixer.h>
37 #include <SDL.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40
41 #ifdef _WIN32
42 #else
43 #include <unistd.h>
44 #define _sleep sleep
45 #endif
46
47 /** Application base class. You should inherit from this class and override
48 * the Update and Draw methods to create an application. The following example
49 * creates a 400x300 window and fills the window with a diferent color each frame:
50 * You can try to execute it with the '-h' option to see what standard parameters a JApp
51 * accepts by default.
52 * <pre>
53 *
54 * #include <JLib/Util/JApp.h>
55 * #include <SDL_keysym.h>
56 * #include <stdio.h>
57 *
58 * class MyApp : public JApp
59 * {
60 * int myData;
61 *
62 * public:
63 * MyApp() : JApp("App window title", 400, 300, false, 16), myData(0)
64 * {}
65 *
66 * bool Update()
67 * {
68 * UpdateEvents();
69 *
70 * ++myData;
71 * if (Keys()[SDLK_ESCAPE] != 0)
72 * {
73 * Exit();
74 * }
75 * }
76 *
77 * bool Draw() {SDL_FillRect(screen, 0, myData); Flip();}
78 * };
79 *
80 * int main(int argc, char **argv)
81 * {
82 * MyApp app;
83 *
84 * // Optionally, parses the command line
85 * app.ParseArgs(argc, argv);
86 *
87 * // Initializes SDL.
88 * if (!app.Init())
89 * {
90 * printf("Error initializing app.\n");
91 * return -1;
92 * }
93 *
94 * // The aplication stays here until Exit() is called.
95 * return app.MainLoop();
96 * }
97 *
98 * </pre>
99 */
100 class JApp
101 {
102 protected:
103 bool active; /**< Is the application active (first plane)? */
104 bool paused; /**< Is paused the application? */
105 bool endLoop; /**< Must exit the app? */
106 JString title; /**< Window title */
107 s32 width; /**< Window width */
108 s32 height; /**< Window height */
109 s32 depth; /**< Color depth */
110 bool fullScreen; /**< Fullscreen flag */
111 bool doInput; /**< Must capture events (keyboard, mouse, WM)? */
112 u32 flags; /**< SDL additional flags */
113 u32 appPauseTime; /**< Time at which the application is paused */
114 u8 *keys; /**< Keyboard state */
115 SDLMod keyMods; /**< Key modifiers state (Shift, Ctrl, etc.) */
116 s32 numKeys; /**< Number of keyboard keys */
117 s32 mouseX; /**< Mouse X position */
118 s32 mouseY; /**< Mouse Y position */
119 u8 mouseBt; /**< Mouse button mask */
120 s32 mouseRelX; /**< Mouse X relative increment */
121 s32 mouseRelY; /**< Mouse Y relative increment */
122 s16 joyAxisX; /**< Joystick X offset */
123 s16 joyAxisY; /**< Joystick Y offset */
124 u8 joyButton; /**< Joystick button */
125 JTimer timer; /**< Application timer */
126 s32 fps; /**< Frames per second */
127 bool dumpVideoInfo; /**< Must dump video info at init? */
128
129 JMixer mixer; /**< Audio mixer */
130 bool soundEnabled; /**< Is sound enabled? */
131
132 char *iconName; /**< Application icon filename */
133
134 static JApp* thisApp; /**< Pointer to this application */
135
136 void (*__OnActive)(bool active, s32 state); /**< Active event callback */
137 void (*__OnKeyUp )(SDL_keysym key); /**< Key up event callback */
138 void (*__OnKeyDown)(SDL_keysym key); /**< Key down event callback */
139 void (*__OnMouseMove)(s32 x, s32 y, s32 bt, s32 xRel, s32 yRel); /**< Mouse move event callback */
140 void (*__OnMouseDown)(s32 bt, s32 x, s32 y); /**< Mouse button down event callback */
141 void (*__OnMouseUp)(s32 bt, s32 x, s32 y); /**< Mouse button up event callback */
142 void (*__OnJoyMove)(s32 joyNum, s32 axis, s32 value); /**< Joystick move event callback */
143 void (*__OnJoyBall)(s32 joyNum, s32 ballIndex, s32 xRel, s32 yRel); /**< Joystick ball event callback */
144 void (*__OnJoyHat)(s32 joyNum, s32 hatIndex, s32 value); /**< Joystick hat event callback */
145 void (*__OnJoyUp)(s32 joyNum, s32 btIndex); /**< Joystick button up event callback */
146 void (*__OnJoyDown)(s32 joyNum, s32 btIndex); /**< Joystick button down event callback */
147 void (*__OnQuit)(); /**< Quit event callback */
148 void (*__OnSysWM)(); /**< Window manager event callback */
149 void (*__OnResize)(s32 w, s32 h); /**< Resize event callback */
150 void (*__OnExpose)(); /**< Window exposure (unhide) event callback */
151 void (*__OnUser)(s32 code, void *data1, void *data2); /**< User event callback */
152
153 SDL_Surface *screen; /**< Primary surface as of SDL_GetVideoSurface() */
154 SDL_Joystick *joystick; /**< Joystick device */
155
156 public:
157 /** Creates the application. The audio mixer must be initialized in the child class.
158 * @param strTitle Window title.
159 * @param w Window width.
160 * @param h Window height.
161 * @param fullScr Fullscreen flag.
162 * @param _depth Bits per pixel (color depth, 8, 16, 24, 32, etc.)
163 * @param otherFlags SDL Additional flags
164 */
165 JApp(const JString& strTitle, s32 w = 1024, s32 h = 768, bool fullScr = true, s32 _depth = 16, u32 otherFlags = 0);
166
167 /** Checks for events to process. In case the associated callback is registered, calls it.
168 * @return <b>true</b> if event polling succeded, <b>false</b> if not.
169 */
170 virtual bool UpdateEvents();
171
172 /** Initializes the app. Creates the window with the paraameters given at construction time.
173 * Normally the child application class overrides this method to initialize its objects and calls the parent (this class)
174 * to do the SDL initialization stuff.
175 * @return <b>true</b> if the creation succeded <b>false</b> if not.
176 */
177 virtual bool Init();
178
179 /** Updates the application objects (graphics, sounds, A.I., etc.). Must be implemented in the child class.
180 * JApp will call this method before Draw in the child class (by means of MainLoop().
181 * @return <b>true</b> if success, <b>false</b> else.
182 */
183 virtual bool Update() = 0;
184
185 /** Draws the application. As Update(), must be implemented in the child class.
186 * @return <b>true</b> if ok, <b>false</b> else.
187 */
188 virtual bool Draw() = 0;
189
190 /** Main loop. The default implementation calls Update() and if it succeded then calls Draw. The application remains
191 * here until Exit() is called or Update() or Draw() fail.
192 * @return Application exit code.
193 */
194 virtual s32 MainLoop();
195
196 /** Returns the window width.
197 * @return Window width.
198 */
199 s32 Width() {return width;}
200
201 /** Returns the window height.
202 * @return Window Height.
203 */
204 s32 Height() {return height;}
205
206 /** Changes the window size.
207 * @param w New width.
208 * @param h New height.
209 * @param _fullScreen <b>true</b> if the app must be fullscreen, <b>false</b> if windowed.
210 */
211 void Resize(s32 w, s32 h, bool _fullScreen);
212
213 /** Returns the fullscreen flag.
214 * @return <b>true</b> if fullscreen, <b>false</b> if windowed.
215 */
216 bool IsFullscreen() {return fullScreen;}
217
218 /** Returns the color depth.
219 * @return Color depth in bits (normally 8, 16, 24 or 32).
220 */
221 s32 Depth() {return depth;}
222
223 /** Ends the application, exiting from the main loop.
224 */
225 void Exit() {endLoop = true;}
226
227 /** Returns the active flag.
228 * @return <b>true</b> if the application is active (foreground) <b>false</b> if not.
229 */
230 bool IsActive() {return active;}
231
232 /** Returns the pause state of the application.
233 * @return <b>true</b> if paused <b>false</b> otherwise.
234 */
235 bool IsPaused() {return paused;}
236
237 /** Pauses or resumes the application.
238 * @param doPause <b>true</b> pauses the application, <b>false</b> resumes.
239 * @return if pausing (doPause is <b>true</b>), returns the number
240 * of milliseconds from the start of the application. If resuming,
241 * (doPause <b>false</b>), returns the number of milliseconds
242 * during pause mode.
243 */
244 u32 Pause(bool doPause);
245
246 /** Returns the window title.
247 * @return Window title.
248 */
249 const JString &Title() {return title;}
250
251 /** Sets the window title.
252 * @param newTitle New window title..
253 */
254 void Title(JString &newTitle) {title = newTitle; SDL_WM_SetCaption(title, 0);}
255
256 /** Returns the execution time in milliseconds.
257 * @return Execution time in milliseconds.
258 */
259 u32 AppTime() {return SDL_GetTicks();}
260
261 /** Returns the main SDL surface. The surface is created after Init()
262 * @return SDL main surface.
263 */
264 SDL_Surface * Screen() {return screen;}
265
266 /** Establishes if events must be captured.
267 * @param b <b>true</b> if they must be <b>false</b> otherwise.
268 */
269 void DoInput(bool b) {doInput = b;}
270
271 /** Determines if events must be captured.
272 * @return <b>true</b> if so <b>false</b> if not.
273 */
274 bool DoInput() {return doInput;}
275
276 /** Sets the active event callback.
277 * @param _OnActive Callback.
278 */
279 void SetOnActive (void (*_OnActive)(bool active, s32 state))
280 {__OnActive = _OnActive;}
281
282 /** Sets the kay up event callback.
283 * @param _OnKeyUp Callback.
284 */
285 void SetOnKeyUp (void (*_OnKeyUp )(SDL_keysym key))
286 {__OnKeyUp = _OnKeyUp ;}
287
288 /** Sets the key down event callback.
289 * @param _OnKeyDown Callback.
290 */
291 void SetOnKeyDown (void (*_OnKeyDown)(SDL_keysym key))
292 {__OnKeyDown = _OnKeyDown;}
293
294 /** Sets the mouse move event callback.
295 * @param _OnMouseMove Callback.
296 */
297 void SetOnMouseMove (void (*_OnMouseMove)(s32 x, s32 y, s32 bt, s32 xRel, s32 yRel))
298 {__OnMouseMove = _OnMouseMove;}
299
300 /** Sets the mouse button down event callback.
301 * @param _OnMouseDown Callback.
302 */
303 void SetOnMouseDown (void (*_OnMouseDown)(s32 bt, s32 x, s32 y))
304 {__OnMouseDown = _OnMouseDown;}
305
306 /** Sets the mouse button up event callback.
307 * @param _OnMouseUp Callback.
308 */
309 void SetOnMouseUp (void (*_OnMouseUp)(s32 bt, s32 x, s32 y))
310 {__OnMouseUp = _OnMouseUp;}
311
312 /** Sets the joystick move event callback.
313 * @param _OnJoyMove Callback.
314 */
315 void SetOnJoyMove (void (*_OnJoyMove)(s32 joyNum, s32 axis, s32 value))
316 {__OnJoyMove = _OnJoyMove;}
317
318 /** Sets the joystick ball event callback.
319 * @param _OnJoyBall Callback.
320 */
321 void SetOnJoyBall (void (*_OnJoyBall)(s32 joyNum, s32 ballIndex, s32 xRel, s32 yRel))
322 {__OnJoyBall = _OnJoyBall;}
323
324 /** Sets the joystick hat event callback.
325 * @param _OnJoyHat Callback.
326 */
327 void SetOnJoyHat (void (*_OnJoyHat)(s32 joyNum, s32 hatIndex, s32 value))
328 {__OnJoyHat = _OnJoyHat;}
329
330 /** Sets the joystick button up event callback.
331 * @param _OnJoyUp Callback.
332 */
333 void SetOnJoyUp (void (*_OnJoyUp)(s32 joyNum, s32 btIndex))
334 {__OnJoyUp = _OnJoyUp;}
335
336 /** Sets the joystick button down event callback.
337 * @param _OnJoyDown Callback.
338 */
339 void SetOnJoyDown (void (*_OnJoyDown)(s32 joyNum, s32 btIndex))
340 {__OnJoyDown = _OnJoyDown;}
341
342 /** Sets the quit event callback.
343 * @param _OnQuit Callback.
344 */
345 void SetOnQuit (void (*_OnQuit)())
346 {__OnQuit = _OnQuit;}
347
348 /** Sets the window manager event callback.
349 * @param _OnSysWM Callback.
350 */
351 void SetOnSysWM (void (*_OnSysWM)())
352 {__OnSysWM = _OnSysWM;}
353
354 /** Sets the resize event callback.
355 * @param _OnResize Callback.
356 */
357 void SetOnResize (void (*_OnResize)(s32 w, s32 h))
358 {__OnResize = _OnResize;}
359
360 /** Sets the video expose event callback.
361 * @param _OnExpose Callback.
362 */
363 void SetOnExpose (void (*_OnExpose)())
364 {__OnExpose = _OnExpose;}
365
366 /** Sets the user event callback.
367 * @param _OnUser Callback.
368 */
369 void SetOnUser(void (*_OnUser)(s32 code, void *data1, void *data2))
370 {__OnUser = _OnUser;}
371
372 /** Returns mouse X position.
373 * @return Mouse X position.
374 */
375 s32 MouseX() {return mouseX;}
376
377 /** Returns mouse Y position.
378 * @return Mouse Y position.
379 */
380 s32 MouseY() {return mouseY;}
381
382 /** Returns the relative X mouse position (since the last move).
383 * @return Relative X mouse position.
384 */
385 s32 MouseRelX() {return mouseRelX;}
386
387 /** Returns the relative Y mouse position (since the last move).
388 * @return Relative Y mouse position.
389 */
390 s32 MouseRelY() {return mouseRelY;}
391
392 /** Returns the mouse button press mask.
393 * @return Mouse button state mask.
394 */
395 u8 MouseBt() {return mouseBt;}
396
397 /** Returns the keyboard key state. The state for a certain key is determined
398 * with Keys()[SDLK_XXX], where SDLK_XXX is the key to query.
399 * If the value is 0, the key is not pressed, else, it is pressed.
400 * @return Key state array.
401 */
402 u8 * Keys() {return keys;}
403
404 /** Returns the key modifier mask. The bits of this mask are those for SDL
405 * KMOD_XXX, with XXX=LCTRL, LSHIFT, etc.
406 * @return Key modifiers bit mask.
407 */
408 SDLMod KeyMods() {return keyMods;}
409
410 /** Returns the joystick X axis
411 * @return joystick X axis
412 */
413 s16 JoystickX() {return joyAxisX;}
414
415 /** Returns the joystick Y axis
416 * @return joystick Y axis
417 */
418 s16 JoystickY() {return joyAxisY;}
419
420 /** Returns the joystick buttonstate. Note: It does not differentiate between buttons.
421 * @return joystick button
422 */
423 u8 JoystickButton() {return joyButton;}
424
425 /** Updates the given region of the primary surface. If all parameters are 0,
426 * the whole window is updated. This is simply a wrapper for SDL_UpdateRect(...).
427 * @param x X position of the rectangle to update.
428 * @param y Y position of the rectangle to update.
429 * @param w Width of the rectangle to update.
430 * @param h Height of the rectangle to update..
431 */
432 void UpdateRect(s32 x, s32 y, s32 w, s32 h) {SDL_UpdateRect(screen, x, y, w, h);}
433
434 /** Update the given rects. As UpdateRect() is only a wrapper for SDL_UpdateRects().
435 * @param num Number of rects to update.
436 * @param rc Array with the rects to update.
437 */
438 void UpdateRects(s32 num, SDL_Rect *rc) {SDL_UpdateRects(screen, num, rc);}
439
440 /** Swaps front and back buffer (if SDL_DOUBLEBUF is used as flag during SDL initializacion)
441 * or updates the whole screen. This is a wrapper for SDL_Flip().
442 * @return <b>true</b> if ok, <b>false</b> if an error ocurred..
443 */
444 bool Flip() {return -1 != SDL_Flip(screen);}
445
446 /** Returns the audio mixer. Must be initialized in the child class.
447 * @return Audio mixer.
448 */
449 JMixer & Mixer() {return mixer;}
450
451 /** Returns this application instance.
452 * @return Pointer to this application.
453 */
454 static JApp * App() {return thisApp;}
455
456 /** Sets the number of frames per second (FPS). Its the maximum number of times Draw() is called per second.
457 * @param newFPS New FPS value.
458 */
459 void FPS(s32 newFPS);
460
461 /** Returns the FPS (frames per second). Its the maximum number of times Draw() is called per second.
462 * @return FPS value.
463 */
464 s32 FPS() {return fps;}
465
466 /** Returns a pointer to the current video mode video info. Is Exactly a wrapper for SDL_GetVideoInfo().
467 * If called before Init() or Resize() it contains the 'best' intended video mode.
468 * @return Information about the current video mode or about the video system in general.
469 */
470 const SDL_VideoInfo *VideoInfo() {return SDL_GetVideoInfo();}
471
472 /** Show the video info in the standard output.
473 */
474 void DumpVideoInfo();
475
476 /** Parses the application argument.
477 * @param args Command line arguments.
478 * @param argc Arguments left.
479 * @return Number of parameters used.
480 */
481 virtual int ParseArg(char *args[], int argc);
482
483 /** Shows the usage string. It contains the default arguments a JApp can be passed.
484 * @param program Program's name.
485 */
486 virtual void PrintUsage(char *program);
487
488 /** Parses the application arguments.
489 * @param argc Command line argument count.
490 * @param argv Command line arguments.
491 */
492 void ParseArgs(s32 argc, char **argv);
493
494 /** Enables or disables sound playback.
495 * @param enable <b>true</b> if it must be enabled, <b>false</b> if not.
496 */
497 void SoundEnabled(bool enable) {soundEnabled = (enable && mixer.Valid());}
498
499 /** Shows or hides the mouse cursor.
500 * @param b <b>true</b> to show, <b>false</b> to hide.
501 */
502 void MouseCursor(bool b) {SDL_ShowCursor(b ? SDL_ENABLE : SDL_DISABLE);}
503
504 /** Returns the viewing state of the mouse cursor.
505 * @param b <b>true</b> if showing, <b>false</b> if not.
506 */
507 bool MouseCursor() {return SDL_ENABLE == SDL_ShowCursor(SDL_QUERY);}
508
509 /** Sets the file name of the icon to be used for the window. Must be called before init.
510 * In Windows must have exactly 32x32 pixels.
511 * @param filename Filename of the icon, 0 to use the default icon.
512 */
513 void Icon(const char *filename);
514
515 /** Returns the sound mixer state.
516 * @return <b>true</b> if active, <b>false</b> if not or the mixer couldn't be initialized properly.
517 * @see JMixer::Valid(), Mixer().
518 */
519 bool SoundEnabled() {return soundEnabled;}
520
521 /** Destroys this application, frees resources and quits the SDL subsystems initialized.
522 */
523 void Destroy();
524
525 /** Destroys the object.
526 */
527 virtual ~JApp();
528 };
529
530 #endif // JAPP_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Dynamic array template.
23 * @file JArray.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 23/10/2005
26 * @version 0.0.1 - 23/10/2005 - First version.
27 */
28
29 #ifndef _JARRAY_INCLUDED
30 #define _JARRAY_INCLUDED
31
32 #include <string.h>
33
34 #include <JLib/Util/JObject.h>
35
36 /** This class allows to track the size of a dinamically created array of elements, grow and shrink it.
37 * Basically unloads from the task of keeping a variable with the array size associated to an array.
38 */
39 template<class T, unsigned int max = 128>
40 class JArray
41 {
42 protected:
43 int maxSize; /**< Maximum number of elements this array can store */
44 T *elements; /**< Array with the elements */
45
46 public:
47 /** Creates an empty array. By default the memory is zeroed.
48 */
49 JArray(int sz = max) : maxSize(sz) {elements = new T[maxSize]; Zero();}
50
51 /** Grows by the specified amount (by default, the amount is the max template parameter).
52 * @param amount Amount to grow.
53 */
54 void Grow(unsigned int amount = max)
55 {
56 T *newElements = new T[maxSize + amount];
57 memset(newElements, 0, sizeof(T) * (maxSize + amount));
58 for (int i = 0; i < maxSize; ++i) newElements[i] = elements[i];
59 delete[] elements; elements = newElements; maxSize += amount;
60 }
61
62 /** Shrinks by the specified amount (by default, the amount is the max template parameter)..
63 * If the amount is greater than the maximum size the it shrinks by the max size (making the array 0 sized).
64 * @param amount Amount to shrink.
65 */
66 void Shrink(unsigned int amount = max)
67 {
68 if (amount >= maxSize)
69 {
70 Clear();
71 return;
72 }
73
74 T *newElements = new T[maxSize - amount];
75 memset(newElements, 0, sizeof(T) * (maxSize - amount));
76 for (int i = 0; i < maxSize - amount; ++i) newElements[i] = elements[i];
77 delete[] elements; elements = newElements; maxSize -= amount;
78 }
79
80 /** Fills the array (its memory) with zeros.
81 */
82 void Zero() {memset(elements, 0, sizeof(T) * maxSize);}
83
84 /** Clears the array, shrinking it to 0 capacity.
85 */
86 void Clear() {JDELETE_ARRAY(elements); maxSize = 0;}
87
88 /** Returns the capacity of the array.
89 */
90 int MaxSize() {return maxSize;}
91
92 /** Returns the element at the given index.
93 * @param i Index of the element.
94 * @return Element at that index.
95 */
96 T& operator[](int i) {return elements[i];}
97
98 /** Destroys the array and frees allocated resources.
99 */
100 ~JArray() {JDELETE_ARRAY(elements); maxSize = 0;}
101 };
102
103 #endif // _JARRAY_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Basic linked list class.
23 * @file JBasicList.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 03/11/2005
26 * @version 0.0.1 - 03/11/2005 - First version.
27 */
28
29 #ifndef _JBASICLIST_INCLUDED
30 #define _JBASICLIST_INCLUDED
31
32 #include <assert.h>
33
34 #include <JLib/Util/JTypes.h>
35
36 /** This template provides a doubly-linked list with basic memory management.
37 */
38 template<class T>
39 class JBasicList
40 {
41 public:
42 class Iterator;
43
44 /** List node.
45 */
46 class Node
47 {
48 friend class JBasicList;
49 friend class Iterator;
50 T data; /**< Node data */
51 Node *prev; /**< Previous node */
52 Node *next; /**< Next node */
53
54 public:
55 Node() {}
56 Node(const T& n) {data = n.data; prev = n.prev; next = n.next;}
57 Node(const T &d, Node *p, Node *n) : data(d), prev(p), next(n) {n->prev = p->next = this;}
58 inline Link(const T &d, Node *p, Node *n) {data = d; prev = p; next = n; n->prev = p->next = this;}
59 inline Unlink() {prev->next = next; next->prev = prev;}
60 Node & operator=(const Node &n) {data = n.data; prev = n.prev; next = n.next; return *this;}
61 };
62
63 /** List iterator.
64 */
65 class Iterator
66 {
67 friend class JBasicList;
68 Node *cur; /**< Node this iterator points to */
69
70 public:
71
72 /** Creates an empty iterator (pointing to nowhere).
73 */
74 Iterator() : cur(0) {}
75
76 /** Creates an iterator pointing to the given node.
77 * @param node Node this iterator must point to.
78 */
79 Iterator(Node *node) : cur(node) {}
80
81 /** Assings another iterator to this iterator.
82 * @param other Other iterator.
83 * @return This iterator.
84 */
85 Iterator & operator=(const Iterator &other) {cur = other.cur; return *this;}
86
87 /** Test equality between iterators.
88 * @param other Other iterator.
89 * @return <b>true</b> if they are equal, <b>false</b> otherwise.
90 */
91 bool operator==(const Iterator &other) {return cur == other.cur;}
92
93 /** Test inequality between iterators.
94 * @param other Other iterator.
95 * @return <b>true</b> if they are different, <b>false</b> otherwise.
96 */
97 bool operator!=(const Iterator &other) {return cur != other.cur;}
98
99 /** Goes to the next element.
100 */
101 inline void Next() {if (cur->next == 0) return; cur = cur->next;}
102
103 /** Goes to the next element.
104 */
105 void operator++() {if (cur->next == 0) return; cur = cur->next;}
106
107 /** Goes to the previous element.
108 */
109 inline void Prev() {if (cur->prev == 0) return; cur = cur->prev;}
110
111 /** Goes to the previous element.
112 */
113 void operator--() {if (cur->prev == 0) return; cur = cur->prev;}
114
115 /** Returns the data of the current element.
116 * @return Data of the current element.
117 */
118 inline T& Data() {return cur->data;}
119
120 /** Returns the data of the current element.
121 * @return Data of the current element.
122 */
123 inline T& operator*() {return cur->data;}
124 };
125
126 protected:
127 Node first; /**< First element */
128 Node last; /**< Last element */
129 int size; /**< Current size of the list */
130 Iterator begin; /**< Iterator to first element */
131 Iterator end; /**< Iterator to last element */
132
133 public:
134 /** Creates an empty list.
135 */
136 JBasicList() : size(0)
137 {
138 first.next = &last;
139 last.prev = &first;
140 end.cur = &last;
141 }
142
143 /** Inserts the given data at the front of the list.
144 * @param data Data to be inserted.
145 */
146 inline void PushFront(const T& data)
147 {
148 new Node(data, &first, first.next);
149 ++size;
150 }
151
152 /** Inserts the given data at the back of the list.
153 * @param data Data to be inserted.
154 */
155 inline void PushBack(const T& data)
156 {
157 new Node(data, last.prev, &last);
158 ++size;
159 }
160
161 /** Inserts the given data before the element at the given iterator.
162 * @param data Data to be inserted.
163 * @param it Iterator to the element before which insert.
164 */
165 inline void Insert(const T& data, Iterator &it)
166 {
167 new Node(data, it.cur->prev, it.cur);
168 ++size;
169 }
170
171 /** Removes the element at the back of the list.
172 */
173 inline void PopBack()
174 {
175 if (last.prev != &first)
176 {
177 Node *tmp = last.prev;
178 last.prev->Unlink();
179 delete tmp;
180 --size;
181 }
182 }
183
184 /** Removes the element at the front of the list.
185 */
186 inline void PopFront()
187 {
188 if (first.next != &last)
189 {
190 Node *tmp = first.next;
191 first.next->Unlink();
192 delete tmp;
193 --size;
194 }
195 }
196
197 /** Removes the element at the given position and places the iterator in the next element.
198 * WARNING: this method does not check if the iterator is valid, one must must check it outside if
199 * needed.
200 * @param it Iterator at the element to be removed.
201 */
202 inline void Remove(Iterator &it)
203 {
204 assert(it.cur != &last && it.cur != &first);
205 Node *tmp = it.cur;
206 it.cur = it.cur->next;
207 tmp->Unlink();
208 delete tmp;
209 --size;
210 }
211
212 /** Returns an iterator at the first element of the list.
213 * If the list is empty, this iterator is the same (in the sense of operator=) to that of End().
214 * @return Iterator at the first element or at one past the last element if the list is empty.
215 */
216 inline const Iterator & Begin() {begin.cur = first.next; return begin;}
217
218 /** Returns the data of the first element in the list.
219 * @return data of the first element in the list.
220 */
221 inline const T& Front() {return first.cur->next->data;}
222
223 /** Returns an iterator at one past the last element of the list.
224 * @return Iterator at one past the last element.
225 */
226 inline const Iterator & End() {return end;}
227
228 /** Returns the data of the last element in the list.
229 * @return data of the first element in the list.
230 */
231 inline const T& Back() {return end.cur->prev->data;}
232
233 /** Returns the number of elements in the list.
234 * @return Number of elements in the list.
235 */
236 inline int Size() {return size;}
237
238 /** Destroys the list, frees used resources.
239 */
240 ~JBasicList()
241 {
242 Node *n = first.next, *tmp;
243
244 while (n != &last)
245 {
246 tmp = n->next;
247 delete n;
248 n = tmp;
249 }
250 }
251 };
252
253 #endif // _JBASICLIST_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Definitions for cross-platform compatibility.
23 * @file JCompatibility.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 09/01/2004
26 * @version 0.0.1 - 09/01/2004 - First version.
27 */
28
29 #ifndef _JCOMPATIBILITY_INCLUDED
30 #define _JCOMPATIBILITY_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #ifdef _WIN32
34 #define sleep _sleep
35 #define mode_t u16
36 #ifndef S_IFBLK
37 #define S_IFBLK 0
38 #endif
39 #ifndef S_IFLNK
40 #define S_IFLNK 0
41 #endif
42 #endif
43
44 #endif // _JCOMPATIBILITY_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Utility funtions for FLTK v1.1.4 (www.fltk.org).
23 * @file JFLTK.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 07/01/2004
26 * @version 0.0.1 - 07/01/2004 - First version
27 */
28
29 #ifndef _JFLTK_INCLUDED
30 #define _JFLTK_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33
34 /** Shifts the selected elements in the browser a line up.
35 * @param brw Browser.
36 */
37 void JFLTK_SelectedUp(Fl_Browser *brw)
38 {
39 for (s32 i = 2; i <= brw->size(); ++i)
40 {
41 if (0 != brw->selected(i) &&
42 0 == brw->selected(i - 1))
43 {
44 brw->move(i - 1, i);
45 }
46 }
47 }
48
49 /** Shifts the selected elements in the browser a line down.
50 * @param brw Browser.
51 */
52 void JFLTK_SelectedDown(Fl_Browser *brw)
53 {
54 for (s32 i = brw->size() - 1; i >= 1; --i)
55 {
56 if (0 != brw->selected(i))
57 {
58 if (0 == brw->selected(i + 1))
59 {
60 brw->move(i + 1, i);
61 }
62 }
63 }
64 }
65
66 /** Removes the selected elements in the browser.
67 * @param brw Browser.
68 */
69 void JFLTK_RemoveSelected(Fl_Browser *brw)
70 {
71 // Borra los seleccionados
72 for (s32 i = 1; i <= brw->size(); ++i)
73 {
74 if (0 != brw->selected(i))
75 {
76 brw->remove(i);
77 --i;
78 }
79 }
80 }
81
82 /** Checks if the browser has the string already.
83 * @param brw Browser.
84 * @param text Text to find.
85 * @return The index in the list if it exists already, else 0 (zero).
86 */
87 s32 JFLTK_Contains(Fl_Browser *brw, const s8 *text)
88 {
89 bool exists = false;
90 s32 i = 0;
91 for (i = 1; i <= brw->size() && !exists; ++i)
92 {
93 if (0 == strcmp(brw->text(i), text))
94 exists = true;
95 }
96
97 if (exists)
98 return i - 1;
99
100 return 0;
101 }
102
103 /** Request a name and checks that the name didn't exist in the browser already.
104 * 'filename' is a posible name for the file or the default value.
105 * @param filename Name of the file from which to extract the default value or default value..
106 * @param brw Browser to check coincidences..
107 * @return Choosen name of 0 (zero) if the user cancels the operation.
108 */
109 const s8 * JFLTK_InputName(const s8 *filename, Fl_Browser *brw)
110 {
111 const s8 *name = "";
112 s8 *s;
113
114 if (filename)
115 {
116 // Shows the name of the file without extension by default
117 // Search the first dot from the end
118 if (0 != (s = strrchr(filename, '.')))
119 *s = 0;
120
121 // Searchs the first slash from the end
122 if (0 == (s = strrchr(filename, '/')))
123 name = filename;
124 else
125 name = s + 1;
126 }
127
128 name = fl_input("Nombre", name);
129 while (name != 0 && JFLTK_Contains(brw, name))
130 {
131 fl_ask("El nombre ya existe,\npor favor elija otro.");
132 name = fl_input("Nombre", name);
133 }
134
135 return name;
136 }
137
138 #endif // _JFLTK_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Sistema de ficheros virtual.
23 * @file JFS.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 23/12/2003
26 * @version 0.0.1 - 23/12/2003 - Primera versión.
27 */
28
29 #include <JLib/Util/JFS.h>
30
31 // Carga la cabecera
32 u32 JResourceHeader::Load(JRW &f)
33 {
34 if (0 != f.ReadLE32(&id) &&
35 0 != f.ReadLE32(&pid) &&
36 0 != f.ReadLE32(&type) &&
37 0 != f.ReadLE32(&size) &&
38 0 != f.ReadLE32(&flags))
39 {
40 return 0;
41 }
42
43 return 1;
44 }
45
46 // Salva la cebecera
47 u32 JResourceHeader::Save(JRW &f)
48 {
49 if (0 != f.WriteLE32(&id) &&
50 0 != f.WriteLE32(&pid) &&
51 0 != f.WriteLE32(&type) &&
52 0 != f.WriteLE32(&size) &&
53 0 != f.WriteLE32(&flags))
54 {
55 return 0;
56 }
57
58 return 1;
59 }
60
61 u32 JResource::TypeOf(const char *filename)
62 {
63 const int size = 13;
64 const char *prefix[size] = {".txt",
65 ".c",
66 ".cpp",
67 ".h",
68 ".png",
69 ".tga",
70 ".jpg",
71 ".bmp",
72 ".xpm",
73 ".wav",
74 ".spr",
75 ".ttf",
76 ".jfs"};
77
78
79 u32 types[size] = {JRES_TEXT,
80 JRES_TEXT,
81 JRES_TEXT,
82 JRES_TEXT,
83 JRES_IMAGE,
84 JRES_IMAGE,
85 JRES_IMAGE,
86 JRES_IMAGE,
87 JRES_IMAGE,
88 JRES_SOUND,
89 JRES_IMAGESPRITE,
90 JRES_FONT,
91 JRES_RESOURCEBLOCK};
92
93 for (int i = 0; i < size; ++i)
94 {
95 if (strstr(filename, prefix[i]))
96 {
97 return types[i];
98 }
99 }
100
101 return JRES_BINARY;
102 }
103
104 // Carga el recurso.
105 u32 JResource::Load(JRW &f, JLoadSave *where)
106 {
107 u32 resp = 0;
108
109 if (0 == (resp |= where->Load(f)))
110 {
111 loaded = true;
112 data = where;
113 }
114
115 return resp;
116 }
117
118 bool JFS::ResizeAt(u32 offset, u32 numBytes)
119 {
120 u32 orgPos = resFile.Tell();
121
122 // TODO: Ver si hace falta
123 resFile.Close();
124 //resFile.Destroy();
125
126 JFile f;
127
128 if (!f.Open(resFilename, "r+b"))
129 {
130 perror("JFS::ResizeAt - No se pudo abrir el fichero");
131 return false;
132 }
133
134 // printf("Resizeando en byte %d, %d bytes\n", offset, numBytes);
135 if (!f.ResizeAt(offset, numBytes))
136 {
137 perror("No se pudo cambiar el tamaño del fichero");
138 f.Close();
139
140 // Deja el jrw como estaba
141 resFile.Create(resFilename, "r+b");
142 resFile.Seek(orgPos, SEEK_SET);
143
144 return false;
145 }
146
147 orgPos = f.Pos();
148 f.Close();
149
150 // Deja el jrw listo para escribir
151 if (!resFile.Create(resFilename, "r+b"))
152 {
153 perror("JFS::ResizeAt - No se pudo volver a crear e jrw");
154 return false;
155 }
156
157 resFile.Seek(orgPos, SEEK_SET);
158
159 return true;
160 }
161
162 // Carga la cabecera del fichero
163 s32 JFS::LoadHeader()
164 {
165 resFile.Seek(0, SEEK_SET);
166
167 // Lee la cabecera
168 char ident[9];
169 if (!resFile.Read(ident, 8))
170 {
171 fprintf(stderr, "No se pudo leer la cabecera del fichero %s\n", resFilename.Str());
172 return -1;
173 }
174
175 ident[8] = '\0';
176
177 if (strcmp(ident, JRES_JFS_FILE) != 0)
178 {
179 fprintf(stderr, "%s no es un fichero JFS\n", resFilename.Str());
180 return -2;
181 }
182
183 u8 major, minor;
184 if (!resFile.Read(&major, 1) || !resFile.Read(&minor, 1))
185 {
186 fprintf(stderr, "No se pudo leer la versión de %s\n", resFilename.Str());
187 return -3;
188 }
189
190 fprintf(stderr, "%s versión %d.%d\n", ident, major, minor);
191
192 return 0;
193 }
194
195 // Salva la cabecera del fichero
196 s32 JFS::SaveHeader()
197 {
198 resFile.Seek(0, SEEK_SET);
199
200 // Escribe la cabecera
201 if (!resFile.Write(JRES_JFS_FILE, 8))
202 {
203 fprintf(stderr, "No se pudo leer la cabecera del fichero %s\n", resFilename.Str());
204 return -1;
205 }
206
207 u8 major = JRES_JFS_MAJOR, minor = JRES_JFS_MINOR;
208 if (!resFile.Write(&major, 1) || !resFile.Write(&minor, 1))
209 {
210 fprintf(stderr, "No se pudo leer la versión de %s\n", resFilename.Str());
211 return -3;
212 }
213
214 fprintf(stderr, "Salvado %s, %s versión %d.%d\n", resFilename.Str(), JRES_JFS_FILE, major, minor);
215
216 return 0;
217 }
218
219 // Carga el índice de recursos
220 s32 JFS::LoadIndex()
221 {
222 resFile.Seek(0, SEEK_END);
223 fprintf(stderr, "Fin de fichero en %d\n", resFile.Tell());
224
225 // Lee el índice al final del fichero
226 resFile.Seek(-8, SEEK_END);
227 fprintf(stderr, "Tamaño del índice en %d\n", resFile.Tell());
228
229 u32 indexSize, indexCount;
230 if (!resFile.ReadLE32(&indexSize) || !resFile.ReadLE32(&indexCount))
231 {
232 fprintf(stderr, "No se pudo cargar el índice\n");
233 return -1;
234 }
235
236 resFile.Seek(-indexSize - 8, SEEK_END);
237
238 index.resize(indexCount, 0);
239
240 for (u32 i = 0; i < indexCount; ++i)
241 {
242 index[i] = new JFSIndexEntry;
243 if (!index[i])
244 {
245 // No hay memoria
246 return -2;
247 }
248
249 index[i]->res = new JResource;
250
251 if (!index[i]->res ||
252 !resFile.ReadLE32(&index[i]->offset) ||
253 !fprintf(stderr, "Leo en %d el offset %d\n", resFile.Tell() - 4, index[i]->offset) ||
254 (0 != index[i]->name.Load(resFile)) ||
255 (0 != index[i]->res->Header().Load(resFile)))
256 {
257 // Error al cargar la entrada
258 return -3;
259 }
260 }
261
262 return 0;
263 }
264
265 // Salva el índice de recursos
266 s32 JFS::SaveIndex()
267 {
268 // Escribe el índice a partir del final del último recurso
269 resFile.Seek(index[index.size() - 1]->offset + index[index.size() - 1]->res->Size(), SEEK_SET);
270
271 fprintf(stderr, "index[index.size() - 1]->offset = %d, index[index.size() - 1]->res->Header().size = %d\n", index[index.size() - 1]->offset, index[index.size() - 1]->res->Header().size);
272
273 u32 curPos = resFile.Tell();
274
275 for (u32 i = 0; i < index.size(); ++i)
276 {
277 fprintf(stderr, "Escribo offset %d en %d, ", index[i]->offset, resFile.Tell());
278
279 if (!index[i] || !resFile.WriteLE32(&index[i]->offset) ||
280 (0 != index[i]->name.Save(resFile)) ||
281 (0 != index[i]->res->Header().Save(resFile)))
282 {
283 return -1;
284 }
285
286 fprintf(stderr, "acabo en %d\n", resFile.Tell());
287 }
288
289 u32 indexSize = resFile.Tell() - curPos;
290 u32 indexCount = index.size();
291
292 curPos = resFile.Tell();
293 resFile.Seek(0, SEEK_END);
294 fprintf(stderr, "Fin de fichero está en %d\n", resFile.Tell());
295
296 fprintf(stderr, "Escribo indexSize en %d como %d\n", resFile.Tell(), indexSize);
297
298 if (0 == resFile.WriteLE32(&indexSize) || 0 == resFile.WriteLE32(&indexCount))
299 {
300 fprintf(stderr, "OOops, hubo un fallo gordo no se pudo salvar el tamaño o el count\n");
301 return -2;
302 }
303
304 fprintf(stderr, "Fin de fichero en %d\n", resFile.Tell());
305
306 return 0;
307 }
308
309 // Carga el fichero de recursos
310 s32 JFS::Load()
311 {
312 s32 ret = 0;
313
314 if (0 != (ret = LoadHeader()))
315 {
316 fprintf(stderr, "Error cargando la cabecera\n");
317 return ret;
318 }
319
320 if (0 != (ret = LoadIndex()))
321 {
322 fprintf(stderr, "Error cargando el índice\n");
323 return ret;
324 }
325
326 return 0;
327 }
328
329 // Carga el recurso dado.
330 u32 JFS::Load(u32 id, JLoadSave *where)
331 {
332 if (id < index.size() && where)
333 {
334 if (index[id] && index[id]->res)
335 {
336 if (index[id]->res->data)
337 {
338 // Ya cargado
339 return 1;
340 }
341
342 // Se posiciona para cargar el recurso
343 resFile.Seek(index[id]->offset, SEEK_SET);
344 index[id]->res->data = where;
345
346 return where->Load(resFile);
347 }
348 }
349
350 // Id o lugar de carga no válidos
351 return 2;
352 }
353
354 // Devuelve el recurso pedido
355 JLoadSave * JFS::Get(const JString &_name)
356 {
357 for (u32 i = 0; i < index.size(); ++i)
358 {
359 if (index[i] && index[i]->name == _name)
360 {
361 if (index[i]->res)
362 {
363 return index[i]->res->data;
364 }
365
366 // Encontrado pero no cargado
367 return 0;
368 }
369 }
370
371 return 0;
372 }
373
374 // Devuelve el recurso pedido
375 JLoadSave * JFS::Get(u32 id)
376 {
377 if (id < index.size() && index[id] && index[id]->res)
378 {
379 return index[id]->res->data;
380 }
381
382 return 0;
383 }
384
385 // Borra el recurso dado
386 bool JFS::Delete(JString &_name)
387 {
388 // JResource *res;
389 // bool found = false;
390
391 // for (it->FirstInBranch(); !found && it->HasNext(); it->Next())
392 // {
393 // res = it->Data();
394 // if (res->Type() != JRES_RESOURCEBLOCK && _name == res->Name())
395 // {
396 // found = true;
397 // it->RemoveNode();
398 // }
399 // }
400
401 // if (found)
402 // {
403 // return true;
404 // }
405
406 return false;
407 }
408
409 u32 JFS::AddToIndex(u32 offset, const JString &name, JResource *res)
410 {
411 if (!res || res->header.id > index.size())
412 {
413 // Índice fuera de rango o no hay recurso
414 return 1;
415 }
416
417 JFSIndexEntry *e = new JFSIndexEntry;
418 e->offset = offset;
419 e->name = name;
420 e->res = res;
421
422 if (res->header.id == index.size())
423 {
424 fprintf(stderr, "\n+++ AddToIndex: Al final\n");
425 // caso especial, va al final y no hay que ajustar nada
426 index.push_back(e);
427 return 0;
428 }
429
430 fprintf(stderr, "\n+++ AddToIndex: Entre medias\n");
431
432 std::vector<JFSIndexEntry *>::iterator itt = index.begin();
433 itt += res->header.id;
434 index.insert(itt, e);
435
436 // Actualiza los índices posteriores
437 for (u32 i = res->header.id + 1; i < index.size(); ++i)
438 {
439 fprintf(stderr, "\n+++ AddToIndex: Actualizo el id de %d\n", i);
440 ++index[i]->res->Header().id;
441 }
442
443 return 0;
444 }
445
446 s32 JFS::AddTreeResource(JResource *res)
447 {
448 // Añade el recurso al árbol. Si el nodo actual es un bloque lo hace dentro de él, tras el último nodo;
449 // si es un recurso de otro tipo, lo inserta tras él.
450 if (it->Data())
451 {
452 fprintf(stderr, "\nAddTreeResource: El nodo ya tiene datos!\n");
453 return -1;
454 }
455
456 it->Data(res);
457
458 // Asigna el identificador
459 if (it->node->prev)
460 {
461 if (it->node->prev->child)
462 {
463 // Si el anterior tiene hijos, el id es el próximo al último de la rama
464 JTree<JResource *>::Iterator *itTmp = NewIterator(it->node->prev->child);
465
466 do
467 {
468 itTmp->LastInBranch();
469 } while (itTmp->Child());
470
471 res->Header().id = itTmp->node->data->Header().id + 1;
472 // fprintf(stderr, "Asigno id de hijo del anterior %d %s\n", itTmp->node->data->Header().id + 1, index[itTmp->node->data->Header().id]->name.Str());
473
474 delete itTmp;
475 }
476 else
477 {
478 // fprintf(stderr, "Asigno id de hijo del anterior %d %s\n", it->node->prev->data->Header().id + 1, index[it->node->prev->data->Header().id]->name.Str());
479 res->Header().id = it->node->prev->data->Header().id + 1;
480 }
481 }
482 else
483 {
484 res->Header().id = it->node->parent->data->Header().id + 1;
485 }
486
487 res->Header().pid = it->node->parent->data->Header().id;
488
489 return 0;
490 }
491
492 s32 JFS::AddResource(const char *filename, u32 flags)
493 {
494 JFile importFile;
495
496 if (!importFile.Open(filename, "r+b"))
497 {
498 perror ("No se pudo abrir el fichero a importar");
499 return -1;
500 }
501
502 // Añade un nuevo recurso al árbol, AddTreeResource calcula su id y su pid
503 JResource *res = new JResource;
504
505 if (0 != AddTreeResource(res))
506 {
507 fprintf(stderr, "No se pudo añadir el nodo al árbol.\n");
508 delete res;
509
510 return -2;
511 }
512
513 // Estos valores no los conoce AddTreeResource
514 res->Header().type = JResource::TypeOf(filename);
515 res->Header().flags = flags;
516
517 // El offset es el del elemento con el id anterior
518 u32 offset = index[res->Header().id-1]->offset + index[res->Header().id-1]->res->Size();
519
520 fprintf(stderr, "AddResource: offset anterior %d + size anterior %d + hdr size %d\n", index[res->Header().id-1]->offset, index[res->Header().id-1]->res->Size(), index[res->Header().id-1]->res->header.Size());
521 fprintf(stderr, "AddResource: Por tanto offset %d\n", offset);
522
523 // Carga el buffer con los datos a salvar
524 if (importFile.Size())
525 {
526 u8 *buff = new u8[importFile.Size()];
527
528 if (!buff)
529 {
530 fprintf(stderr, "No hay memoria para importar el fichero\n");
531 return -3;
532 }
533
534 if (0 == importFile.Read(buff, importFile.Size()))
535 {
536 fprintf(stderr, "Error al leer los datos del fichero a importar\n");
537 delete[] buff;
538 return -4;
539 }
540
541 if (JFS_COMPRESSED(res))
542 {
543 // Los datos deben comprimirse. Hay que hacerlo en memoria pues no sabemos a priori
544 // cuánto ocuparán
545 u32 sizeComp, size;
546 unsigned long sizeUL, sizeCompUL;
547 size = importFile.Size();
548 sizeUL = size;
549
550 // Zlib header says it can be computed with compressBounds but if so, it fails to compress2.
551 // ZLib manual says that it must be 0.1% plus 12 bytes larger 8-?
552 sizeComp = compressBound(size);
553 sizeCompUL = sizeComp;
554
555 printf("---> sizeComp es %lu, (uLongf*)&sizeComp es %lu\n", sizeUL, *((uLongf*)&sizeUL));
556
557 unsigned char *buffComp = new unsigned char[sizeComp + 8];
558
559 if (!buffComp)
560 {
561 delete[] buff;
562 return -5;
563 }
564
565 s32 ret;
566 if (Z_OK != (ret = compress2((Bytef*)buffComp, (uLongf*)&sizeCompUL, (Bytef*)buff, sizeUL, compressionLevel)))
567 {
568 printf("ret=%d, Z_MEM_ERROR=%d, Z_BUF_ERROR=%d, Z_STREAM_ERROR=%d\n", ret, Z_MEM_ERROR, Z_BUF_ERROR, Z_STREAM_ERROR);
569 delete[] buff;
570 delete[] buffComp;
571 return -6;
572 }
573
574 sizeComp = (u32)sizeCompUL;
575
576 res->Header().size = sizeof(size) + sizeof(sizeComp) + sizeComp;
577
578 // Hace crecer el fichero de recursos desde la posición posterior al recurso actual.
579 if (!ResizeAt(offset, res->Size()))
580 {
581 delete[] buff;
582 delete[] buffComp;
583 return -7;
584 }
585
586 // Tamaño original + Tamaño comprimido + datos comprimidos
587 // Esto lo guarda en el formato que espera ZRead al cargar
588 if (0 == resFile.WriteLE32(&size) || 0 == resFile.WriteLE32(&sizeComp) ||
589 0 == resFile.Write(buffComp, sizeComp))
590 {
591 delete[] buff;
592 delete[] buffComp;
593 return -8;
594 }
595
596 delete[] buffComp;
597 }
598 else
599 {
600 res->Header().size = importFile.Size();
601
602 if (!ResizeAt(offset, res->Size()))
603 {
604 delete[] buff;
605 return -10;
606 }
607
608 if (0 == resFile.Write(buff, res->Header().size))
609 {
610 delete[] buff;
611 return -11;
612 }
613 }
614
615 delete[] buff;
616 }
617 else
618 {
619 // Fichero vacío
620 res->Header().size = 0;
621 }
622
623 // Añade la entrada nueva al índice y ajusta las entradas por detrás
624 AddToIndex(offset, filename, res);
625
626 return 0;
627 }
628
629 s32 JFS::AddBlock(const char *name)
630 {
631 // Añade el recurso al árbol. Si el nodo actual es un bloque lo hace dentro de él, tras el último nodo;
632 // si es un recurso de otro tipo, lo inserta tras él.
633 JResource *res = new JResource;
634
635 if (0 != AddTreeResource(res))
636 {
637 fprintf(stderr, "Error al añadir un bloque al árbol.\n");
638 delete res;
639
640 return -1;
641 }
642
643 // Esta información no la conoce AddTreeBlock
644 res->header.type = JRES_RESOURCEBLOCK;
645 res->header.flags = JRES_FLAGS_BLOCK_OPENED;
646 res->header.size = 0;
647
648 // El offset es el del elemento con el id anterior
649 u32 offset = index[res->header.id-1]->offset + index[res->header.id-1]->res->Size();
650
651 // Hace crecer el fichero de recursos desde la posición posterior al recurso actual.
652 if (!ResizeAt(offset, res->Size()))
653 {
654 fprintf(stderr, "Error al hacer resize!\n");
655 return -10;
656 }
657
658 fprintf(stderr, "Añado al índice el bloque.\n");
659
660 // Añade la entrada nueva al índice y ajusta las entradas por detrás
661 AddToIndex(offset, name, res);
662
663 return 0;
664 }
665
666 s32 JFS::BuildTree()
667 {
668 if (!index.size())
669 {
670 // No hay índice
671 fprintf(stderr, "BuildTree: No hay un índice cargado!\n");
672 return -1;
673 }
674
675 // Borra todo el árbol
676 it->Root();
677 it->RemoveNode();
678
679 if (it->Data())
680 {
681 delete it->Data();
682 it->Data(0);
683 }
684
685 // Organiza los recursos en forma de árbol
686 u32 i;
687 u32 pid = 0;
688
689 for (i = 0; i < index.size() - 1; ++i)
690 {
691 it->Data(index[i]->res);
692 pid = index[i + 1]->res->Header().pid;
693
694 if (index[i]->res->Header().type == JRES_RESOURCEBLOCK && pid == index[i]->res->Header().id)
695 {
696 // Recurso actual es bloque y tiene hijos
697 it->AddBranchGo(0);
698 }
699 else
700 if (pid == index[i]->res->Header().pid)
701 {
702 // Siguiente recurso al mismo nivel que el actual
703 it->AddNodeGo(0);
704 }
705 else
706 {
707 while (it->Parent() && it->node->data->header.pid != pid)
708 {}
709
710 it->LastInBranch();
711 it->AddNodeGo(0);
712 }
713 }
714
715 it->Data(index[i]->res);
716
717 return 0;
718 }
719
720 s32 JFS::Open(const char *_name, bool edit)
721 {
722 if (!_name || ! JFile::Exists(_name))
723 {
724 // Nombre nulo o no exists el fichero
725 return -1;
726 }
727
728 char str[4096];
729 getcwd(str, sizeof(str));
730
731 resFilename = str;
732 resFilename += "/";
733 resFilename += _name;
734
735 if (!resFile.Create(resFilename, "r+b"))
736 {
737 // No se pudo abrir el fichero
738 return -2;
739 }
740
741 if (0 != Load())
742 {
743 return -3;
744 }
745
746 if (it)
747 {
748 delete it;
749 }
750
751 it = NewIterator();
752 it->Data(0);
753
754 return BuildTree();
755 }
756
757 s32 JFS::Create(const char *_name)
758 {
759 if (!_name)
760 {
761 // Nombre nulo
762 return -1;
763 }
764
765 char str[4096];
766 getcwd(str, sizeof(str));
767
768 resFilename = str;
769 resFilename += "/";
770 resFilename += _name;
771
772 if (!resFile.Create(resFilename, "w+b"))
773 {
774 // No se pudo abrir el fichero
775 return -2;
776 }
777
778 if (0 != SaveHeader())
779 {
780 // No se pudo salvar la cabecera
781 return -3;
782 }
783
784 // Índice vacío inicialmente
785 u32 indexSize = 0, indexCount = 0;
786 if (0 == resFile.WriteLE32(&indexSize) ||
787 0 == resFile.WriteLE32(&indexCount))
788 {
789 return -4;
790 }
791
792 // Adición manual del primer recurso
793 root->data = new JResource;
794 root->data->header.id = 0;
795 root->data->header.pid = 0;
796 root->data->header.type = JRES_RESOURCEBLOCK;
797 root->data->header.flags = JRES_FLAGS_BLOCK_OPENED;
798 root->data->header.size = 0;
799
800 // El offset es el tamaño de la cabecera
801 u32 offset = JRES_JFS_HEADER_SIZE;
802
803 // Hace crecer el fichero de recursos desde la posición posterior al recurso actual.
804 if (!ResizeAt(offset, root->data->Size()))
805 {
806 return -10;
807 }
808
809 AddToIndex(JRES_JFS_HEADER_SIZE, _name, root->data);
810
811 SaveIndex();
812
813 if (it)
814 {
815 delete it;
816 }
817
818 it = NewIterator();
819
820 return 0;
821 }
822
823 s32 JFS::Import(const char *filename, JTree<JResource *>::Node *where, bool after)
824 {
825 static s32 depth = 0;
826 fprintf(stderr, "Recursión %d, size es %d importo %s\n", depth, Size(), filename);
827
828 char str[256];
829 getcwd(str, 256);
830 printf("CWD es %s\n", str);
831
832 if (!filename || resFilename == "")
833 {
834 return -2;
835 }
836
837 if (depth == 0)
838 {
839 if (it)
840 {
841 delete it;
842 }
843
844 // Si nos dan un nodo (se asume que es de este árbol) mueve el iterador interno a esa posición,
845 // si no, se posicionará el iterador al comienzo del árbol
846 it = NewIterator(where);
847 }
848
849 printf("Depth es %d!\n", depth);
850
851 if (JFile::IsDir(filename))
852 {
853 if (depth == 0)
854 {
855 if (JFS_BLOCKOPENED(it->Data()) || it->node == root)
856 {
857 printf("Añado rama inicial!\n");
858
859 // Si es un bloque abierto o root
860 if (it->Child())
861 {
862 // Tiene ya elementos, inserta antes del primero
863 it->AddNodeGo(0, false);
864 }
865 else
866 {
867 // No tiene elementos, añade uno dentro
868 it->AddBranchGo(0);
869 }
870 }
871 else
872 {
873 printf("Añado nodo inicial!\n");
874
875 // Bloque cerrado distinto de root o nodo, lo añade tras éste
876 it->AddNodeGo(0, after);
877 }
878 }
879
880 ++depth;
881
882 AddBlock(filename);
883 fprintf(stderr, "Importando directorio: %*c%s\n", it->node->depth+1, '.', filename);
884
885 s32 n, k;
886
887 // Si es un directorio lo importa recursivamente
888 struct dirent64 **namelist;
889 n = scandir64(filename, &namelist, 0, alphasort);
890
891 if (n < 0)
892 {
893 perror("scandir");
894 it->Parent();
895 --depth;
896 return -1;
897 }
898
899 s32 num = 0;
900
901 if (n > 0)
902 {
903 chdir(filename);
904 getcwd(str, 256);
905 printf("CWD es %s\n", str);
906
907 // Añade una entrada vacía para el primer elemento del directorio
908 printf("Añado rama nueva al directorio!\n");
909 it->AddBranchGo(0);
910
911 // index[itt->node->data->Header().id]->name.Str()
912
913 k = 0;
914 while (k < n)
915 {
916 if (JFile::IsFile(namelist[k]->d_name) || (JFile::IsDir(namelist[k]->d_name) && (0 != strcmp(namelist[k]->d_name, ".") && 0 != strcmp(namelist[k]->d_name, ".."))))
917 {
918 ++num;
919
920 // Procesa recursivamente sus elementos
921 printf("Voy a importar %s\n", namelist[k]->d_name);
922 Import(namelist[k]->d_name);
923 it->AddNodeGo(0);
924 }
925 free(namelist[k]);
926
927 ++k;
928 }
929 printf("No hay más elementos en %s\n", filename);
930
931 // el último nodo (o la rama si el directorio estaba vacío) está vacío, lo borra
932 if (it->Data())
933 {
934 printf("Horror, FALLO!!\n");
935 }
936 else
937 {
938 it->RemoveNode();
939 }
940
941 free(namelist);
942 chdir("..");
943 getcwd(str, 256);
944 printf("CWD es %s\n", str);
945 }
946
947 // printf("it->Parent()\n");
948 if (num)
949 {
950 // Sólo pasa al padre si se importaron elementos del directorio pues si no
951 // ya estamos en el padre tras hacer RemoveNode
952 it->Parent();
953 }
954 }
955 else if (JFile::IsFile(filename))
956 {
957 if (depth == 0)
958 {
959 if (JFS_BLOCKOPENED(it->Data()) || it->node == root)
960 {
961 printf("Añado rama!\n");
962
963 // Si es un bloque abierto o root
964 if (it->Child())
965 {
966 // Tiene ya elementos, inserta antes del primero
967 it->AddNodeGo(0, false);
968 }
969 else
970 {
971 // No tiene elementos, añade uno dentro
972 it->AddBranchGo(0);
973 }
974 }
975 else
976 {
977 printf("Añado nodo!\n");
978
979 // Bloque cerrado distinto de root o nodo, lo añade tras éste
980 it->AddNodeGo(0, after);
981 }
982 }
983
984 ++depth;
985
986 s32 ret = AddResource(filename, defaultFlags);
987
988 fprintf(stderr, "Importando archivo: %s depth=%d, Addresource()=%d\n", filename, it->node->depth, ret);
989 }
990
991 if (!it->Data())
992 {
993 printf("-----> Nodo vacío, lo quito!! <-----\n");
994 it->RemoveNode();
995 }
996
997 --depth;
998
999 if (depth == 0)
1000 {
1001 // tras la última entrada actualiza el índice en disco
1002 return SaveIndex();
1003 }
1004
1005 return 0;
1006 }
1007
1008 s32 JFS::Export()
1009 {
1010 JString dirName;
1011 int i = 1;
1012
1013 // Busca un subdirectorio que no exista para exportar
1014 do
1015 {
1016 dirName.Format("export%d", i++);
1017 } while(JFile::Exists(dirName));
1018
1019 // char str[256];
1020 // getcwd(str, 256);
1021 // printf("Estoy en %s\n", str);
1022 // printf("Creo %s\n", dirName.Str());
1023
1024 #ifndef _WIN32
1025 if (0 != mkdir(dirName, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH))
1026 #else
1027 if (0 != mkdir(dirName))
1028 #endif //_WIN32
1029 {
1030 perror("Error creating export base directory");
1031 return -1;
1032 }
1033
1034 chdir(dirName);
1035
1036 // No exporta el nodo raíz
1037 u32 id, lastPid;
1038 for (id = 1, lastPid = 0; id < index.size(); ++id)
1039 {
1040 // printf("Lastpid es %s, cur.pid es %s\n", index[lastPid]->name.Str(), index[index[id]->res->Header().pid]->name.Str());
1041
1042 while (lastPid && lastPid >= index[id]->res->Header().pid)
1043 {
1044 // Sube un directorio hasta que el padre sea el mismo que el del recurso actual
1045 // getcwd(str, 256);
1046 // printf("Estoy en %s\n", str);
1047 chdir("..");
1048 lastPid = index[lastPid]->res->Header().pid;
1049 //getcwd(str, 256);
1050 //printf("Subo a %s\n", str);
1051 }
1052 //printf("Ahora lastpid es %s, cur.pid es %s\n", index[lastPid]->name.Str(), index[index[id]->res->Header().pid]->name.Str());
1053
1054 if (JFS_IS_BLOCK(index[id]->res))
1055 {
1056 // Bloque, sólo crea un directorio
1057 dirName = index[id]->name;
1058
1059 //printf("Creo %s\n", dirName.Str());
1060
1061 #ifndef _WIN32
1062 if (0 != mkdir(dirName, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH))
1063 #else
1064 if (0 != mkdir(dirName))
1065 #endif //_WIN32
1066 {
1067 perror("Error creating directory");
1068 printf("%s\n", dirName.Str());
1069 return -1;
1070 }
1071
1072 int ret = chdir(dirName);
1073
1074 //getcwd(str, 256);
1075 //printf("Cambio a %s\n", str);
1076
1077 if (ret != 0)
1078 {
1079 perror("chdir falló");
1080 }
1081 else
1082 {
1083 // Cambio de padre
1084 lastPid = index[id]->res->Header().pid;
1085 }
1086 }
1087 else
1088 {
1089 //char str[256];
1090 //getcwd(str, 256);
1091 //printf("Estoy en %s\n", str);
1092
1093 //printf("Creo archivo %s size es %d\n", index[id]->name.Str(), index[id]->res->Header().size);
1094
1095 // Abre el fichero de destino
1096 JFile f;
1097 if (!f.Open(index[id]->name, "w+b"))
1098 {
1099 return -3;
1100 }
1101
1102 // Fichero regular (pronto también links... :)
1103 // Este es el mismo código que para cargar un recurso
1104 resFile.Seek(index[id]->offset, SEEK_SET);
1105
1106 if (index[id]->res->Header().size)
1107 {
1108 u8 *buff;
1109 u32 size;
1110
1111 // Lee los datos desde el formato adecuado
1112 if (JFS_COMPRESSED(index[id]->res))
1113 {
1114 if (0 == (size = resFile.ZRead((void **)&buff)))
1115 {
1116 fprintf(stderr, "JFS::Export - Error reading compressed resource\n");
1117 delete[] buff;
1118
1119 return -4;
1120 }
1121 }
1122 else
1123 {
1124 size = index[id]->res->Header().size;
1125 buff = new u8[size];
1126
1127 if (0 == resFile.Read(buff, size))
1128 {
1129 fprintf(stderr, "JFS::Export - Error reading resource\n");
1130 delete[] buff;
1131
1132 return -5;
1133 }
1134 }
1135
1136
1137 // Escribe el fichero de destino
1138 if (!f.Write(buff, size))
1139 {
1140 delete[] buff;
1141 return -6;
1142 }
1143
1144 delete[] buff;
1145 }
1146 }
1147 }
1148
1149 while (lastPid && lastPid > 0)
1150 {
1151 // Sube un directorio hasta que el padre sea el mismo que el del recurso actual
1152 //getcwd(str, 256);
1153 //printf("FIN: Estoy en %s\n", str);
1154 chdir("..");
1155 lastPid = index[lastPid]->res->Header().pid;
1156 //getcwd(str, 256);
1157 //printf("FIN: Cambio a %s\n", str);
1158 }
1159
1160 chdir("..");
1161 //getcwd(str, 256);
1162 //printf(".. a %s\n", str);
1163 chdir("..");
1164 //getcwd(str, 256);
1165 //printf("2 .. a %s\n", str);
1166
1167 return 0;
1168 }
1169
1170 const JString JFS::FilenameFromId(const char *name)
1171 {
1172 JString ret = name;
1173 ret.Lowercase();
1174 s32 dotPos = ret.FindLast('_');
1175
1176 // Pone el punto de la extensión (esto no funciona en id's que provengan de archivos con espacios sin extensión)
1177 if (dotPos >= 0)
1178 {
1179 ret[dotPos] = '.';
1180 }
1181
1182 return ret;
1183 }
1184
1185 const JString JFS::IdFromFilename(const char *name)
1186 {
1187 JString ret;
1188 if (prefix.Length())
1189 {
1190 ret = prefix + "_" + name;
1191 }
1192 else
1193 {
1194 ret = name;
1195 }
1196
1197 ret.Uppercase();
1198 ret.Replace(' ', '_');
1199 ret.Replace('.', '_');
1200 ret.Replace('-', '_');
1201
1202 return ret;
1203 }
1204
1205 bool JFS::ExportIndex(const char *filename)
1206 {
1207 JTextFile f;
1208 if (!f.Open(filename, "w+b"))
1209 {
1210 perror("JFS::ExportIndex");
1211 return false;
1212 }
1213
1214 if (!f.PrintLine(JRES_JFS_EXPORT_VERSION) ||
1215 !f.PrintLine(JRES_JFS_EXPORT_WARNING) ||
1216 !f.PrintLine(JRES_JFS_EXPORT_BEGIN"\n"))
1217 {
1218 perror("JFS::ExportIndex");
1219 return false;
1220 }
1221
1222 char str[4096];
1223 JString exportName;
1224 s32 j = 0;
1225
1226 for (u32 i = 0; i < index.size(); ++i)
1227 {
1228 exportName = IdFromFilename(index[i]->name.Str());
1229
1230 j = index[i]->res->Header().pid;
1231
1232 while (j > 0)
1233 {
1234 exportName = IdFromFilename(index[j]->name.Str()) + ("_" + exportName);
1235 j = index[j]->res->Header().pid;
1236 }
1237
1238 snprintf(str, sizeof(str), "#define %-40s %d", exportName.Str(), i);
1239 if (!f.PrintLine(str))
1240 {
1241 perror("JFS::ExportIndex");
1242 return false;
1243 }
1244 }
1245
1246 if (!f.PrintLine("\n"JRES_JFS_EXPORT_END))
1247 {
1248 perror("JFS::ExportIndex");
1249 return false;
1250 }
1251
1252 return true;
1253 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Virtual filesystem.
23 * @file JFS.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 23/12/2003
26 * @version 0.0.1 - 23/12/2003 - First version.
27 */
28 #ifndef _JFS_INCLUDED
29 #define _JFS_INCLUDED
30
31 #include <JLib/Util/JTypes.h>
32 #include <JLib/Util/JTree.h>
33 #include <vector>
34 #include <dirent.h>
35 #include <JLib/Util/JObject.h>
36 #include <JLib/Util/JString.h>
37 #include <JLib/Util/JFile.h>
38 #include <JLib/Util/JTextFile.h>
39 #include <JLib/Util/JLoadSave.h>
40 #include <JLib/Graphics/JImage.h>
41 #include <JLib/Graphics/JImageSprite.h>
42
43 /*** Identification string for JFS files */
44 #define JRES_JFS_FILE "JLIBJFS "
45 /*** Major version number */
46 #define JRES_JFS_MAJOR 1
47 /*** Minor version number */
48 #define JRES_JFS_MINOR 0
49 /*** Size of the header */
50 #define JRES_JFS_HEADER_SIZE 10
51 /*** Version of the exporter */
52 #define JRES_JFS_EXPORT_VERSION "///~ JFS V1.0"
53 /*** Begin of export id */
54 #define JRES_JFS_EXPORT_BEGIN "///~ RESOURCES BEGIN"
55 /*** End of export id */
56 #define JRES_JFS_EXPORT_END "///~ RESOURCES END"
57 /*** Export warning label */
58 #define JRES_JFS_EXPORT_WARNING " - DO NOT EDIT THIS FILE MANUALLY. USE JLib's JFSBrowser INSTEAD"
59
60 // Built-in resource identifiers
61
62 /*** Resource block id */
63 #define JRES_RESOURCEBLOCK 0x80000000
64 /*** Resource link id */
65 #define JRES_RESOURCELINK 0x40000000
66 /*** Image file id */
67 #define JRES_IMAGE 0x20000000
68 /*** Sound file id */
69 #define JRES_SOUND 0x10000000
70 /*** Text file id */
71 #define JRES_TEXT 0x08000000
72 /*** Image sprite id */
73 #define JRES_IMAGESPRITE 0x04000000
74 /*** Font file id */
75 #define JRES_FONT 0x02000000
76 /*** Generic data id */
77 #define JRES_BINARY 0x01000000
78
79 // Resource flags
80
81 /*** Compression flag */
82 #define JRES_FLAGS_COMPRESSED 0x00000001
83 /*** Opened block flag (edit mode) */
84 #define JRES_FLAGS_BLOCK_OPENED 0x80000000
85 /** Selected resource flag (edit mode) */
86 #define JRES_FLAGS_SELECTED 0x40000000
87 /** Save pending flag (edit mode) */
88 #define JRES_FLAGS_IMPORTED 0x20000000
89
90 /*** Check if the resource is compressed */
91 #define JFS_COMPRESSED(p) ((p)->Header().flags & JRES_FLAGS_COMPRESSED)
92
93 /** Check if the resource is a block */
94 #define JFS_IS_BLOCK(p) ((p)->Header().type == JRES_RESOURCEBLOCK)
95
96 /** Check if the resource is a link */
97 #define JFS_IS_LINK(p) ((p)->Header().type == JRES_RESOURCELINK)
98
99 /** Checks if the resource is opened (has no sense for other resource than a block) */
100 #define JFS_OPENED(p) ((p)->Header().flags & JRES_FLAGS_BLOCK_OPENED)
101
102 /** Checks if the reosurce is a block and it is opened */
103 #define JFS_BLOCKOPENED(p) (((p)->Header().type == JRES_RESOURCEBLOCK) && ((p)->Header().flags & JRES_FLAGS_BLOCK_OPENED))
104
105 /** Checks if the resource is seleced */
106 #define JFS_SELECTED(p) ((p)->Header().flags & JRES_FLAGS_SELECTED)
107
108 class JFS;
109
110 /** Resource header.
111 */
112 class JResourceHeader : public JLoadSave
113 {
114 public:
115 u32 id; /**< Unique resource id */
116 u32 pid; /**< Parent resource id */
117 u32 type; /**< Resource type */
118 u32 flags; /**< Additional flags */
119 u32 size; /**< Size of the data this resource contains in the file */
120
121 /** Loads the header.
122 * @param f File opened and correctly positioned from which to load the data.
123 * @return 0 if ok, 1 if I/O error, 2 if data integrity error.
124 */
125 virtual u32 Load(JRW &f);
126
127 /** Saves the header.
128 * @param f File opened and correctly positioned where to save the data.
129 * @return 0 if ok, 1 if I/O error, 2 if data integrity error.
130 */
131 virtual u32 Save(JRW &f);
132
133 /** Size of this header in the file.
134 * @return Size of the header in the file.
135 */
136 virtual u32 Size() {return 20;}
137 };
138
139 /** Basic resource.
140 */
141 class JResource : public JLoadSave
142 {
143 friend class JFS;
144
145 private:
146 u32 instanceCount; /**< Number of existing instances of this resource */
147
148 protected:
149 JResourceHeader header; /**< Resource header */
150
151 JLoadSave *data; /**< Unique instance of the data of the object this resource refers to */
152 bool loaded; /**< Indicates whether this resource has benn loaded or not */
153
154 public:
155 /** Creates an empty resource.
156 */
157 JResource() : instanceCount(0), data(0), loaded(false)
158 {}
159
160 /** Returns the data size for this resource.
161 * @return Data size of this resource.
162 */
163 u32 Size() {return header.size;}
164
165 /** Returns the type of resource.
166 * @return Type of this resource as in the header.
167 */
168 u32 Type() const {return header.type;}
169
170 /** Returns this resource's id.
171 * @return Resource id.
172 */
173 u32 Id() const {return header.id;}
174
175 /** Returns the data of this resource.
176 * @return Dta of this resource.
177 */
178 JLoadSave* Data() const {return data;}
179
180 /** Checks if the resource has been loaded already.
181 * @return <b>true</b> if so, <b>false</b> if not.
182 */
183 bool Loaded() {return loaded;}
184
185 /** Destroys the resource, unloads it and frees its allocated memory.
186 */
187 virtual ~JResource() {}
188
189 /** Loads the resource.
190 * @param f File opened and correctly positioned from which to load the resource data.
191 * @param where Pointer to the object in where to load resource data.
192 * @return 0 if ok, 1 if I/O error, 2 if data integrity error.
193 */
194 virtual u32 Load(JRW &f, JLoadSave *where);
195
196 /** Returns this resource's header.
197 * @return Resource header.
198 */
199 JResourceHeader & Header() {return header;}
200
201 /** Returns the resource type based upon the file extension.
202 * @param filename File name (.txt, .png, .tga, .jpg, .bmp, .xpm, .wav, .spr, .jfs).
203 * @return Resource type, one of JRES_XXX.
204 */
205 static u32 TypeOf(const char *filename);
206 };
207
208 /** Resource list iterator.
209 */
210 typedef std::vector<JResource*>::iterator JResIterator;
211
212 /** Resource index entry.
213 */
214 struct JFSIndexEntry
215 {
216 u32 offset; /**< Offset of the resource from the beginning of the file. */
217 JString name; /**< String with the resource id in text form. */
218 JResource *res; /**< Resource. */
219 };
220
221 /** Virtual filesystem.
222 * Consists on a file organized in a hierarchy of blocks.
223 * At least always one block exists, the root block from which the other resources in the file hang.
224 * A resource is identified biunivocally from its id.
225 */
226 class JFS : public JTree<JResource *>
227 {
228 protected:
229 JString resFilename; /**< Name of the file */
230 JString prefix; /**< Export prefix for identifiers at the '.h' export file */
231 JRW resFile; /**< Resource file */
232 JTree<JResource *>::Iterator *it; /**< Auxiliar iterator */
233 std::vector<JFSIndexEntry *> index; /**< Resource offset index */
234 u32 defaultFlags; /**< Default flags when adding a resource */
235 s32 compressionLevel; /**< Compression level */
236
237 /** Chenges the size of the file. Places resFile ready to write.
238 * @param offset Offset at which to change the size.
239 * @param numBytes Number of bytes to increment size.
240 * @return <b>true</b> if ok, <b>false</b> if the operation couldn't be accomplished.
241 */
242 bool ResizeAt(u32 offset, u32 numBytes);
243
244 /** Loads the resource header and checks if it's in the expected format.
245 * @return 0 if ok, 1 if I/O error, 2 if data integrity error.
246 */
247 s32 LoadHeader();
248
249 /** Load the resource offset index.
250 * @return 0 if ok, 1 if I/O error, 2 if data integrity error.
251 */
252 s32 LoadIndex();
253
254 /** Saves the resource header.
255 * @return 0 if ok, 1 if I/O error, 2 if data integrity error.
256 */
257 s32 SaveHeader();
258
259 /** Saves the resource offset index.
260 * @return 0 if ok, 1 if I/O error, 2 if data integrity error.
261 */
262 s32 SaveIndex();
263
264 /** Adds a resource in the current position of the tree's global iterator.
265 * @param res Resource to add.
266 * @return 0 if successful, -1 if not.
267 */
268 s32 AddTreeResource(JResource *res);
269
270 /** Adds an entry to the resource offset index and adjusts the following indices.
271 * @param offset Offset to add.
272 * @param name Name of the resource to add.
273 * @param res Resource to add.
274 * @return 0 if ok, 1 if I/O error, 2 if data integrity error.
275 */
276 u32 AddToIndex(u32 offset, const JString &name, JResource *res);
277
278 /** Checks the resource header and loads the index.
279 * @return 0 if ok, 1 if I/O error, 2 if data integrity error.
280 */
281 s32 Load();
282
283 /** Creates the tree structure based upon the actual index. Destroys any previously existing structure.
284 * @return 0 if ok, -1 if an error ocurred.
285 */
286 s32 BuildTree();
287
288 public:
289 /** Creates an empty virtual resource filesystem. Any of Open or Create must be called before using it.
290 */
291 JFS() : it(0), defaultFlags(0), compressionLevel(9)
292 {}
293
294 /** Adds a file to the current block.
295 * @param filename Name of the file to import.
296 * @param flags Import flags.
297 * @return 0 if ok, <0 if error.
298 */
299 s32 AddResource(const char *filename, u32 flags = 0);
300
301 /** Creates a resource block in the actual block.
302 * @param filename Name of the block to create.
303 * @return 0 if ok, <0 if error.
304 */
305 s32 AddBlock(const char *name);
306
307 /** Opens an existing virtual resource filesystem file.
308 * @param _name Name of the file.
309 * @param edit Edit mode indicator. If not editing, only the index is read and waits for resource queries.
310 * If editing, the tree structure is also created.
311 * @return 0 if it exists and could be loaded, -1 if _name is 0, -2 if the file couldn't be opened, 1 if the file couldn't be loaded.
312 */
313 s32 Open(const char *_name = 0, bool edit = false);
314
315 /** Creates a new JFS file.
316 * @param _name Name of the file.
317 * @return 0 if it could be created, 1 if not.
318 */
319 s32 Create(const char *name = 0);
320
321 /** Imports a file or a directory structure.
322 * The directories are added as blocks containing the files as resources. .png, .tga, .bmp, .jpg, etc. files are added as image resources,
323 * .wav files as sound resource, .spr as image sprites, .txt files as text resources, .jfs files as blocks (if not accompained of a .h
324 * definition file (a file with its same name but extension '.h', in the same directory), unique id's are created for its resources.
325 * The rest of files are treated as binary data (egenric resources).
326 * @param filename File or base directory where to import.
327 * @param where Tree node from which import. If it's a opened block or root imports inside, else imports at the same level and
328 * where 'after' says.
329 * @param after Indicates whether to add before or after the current node.
330 * @return 0 If import succeeded, -1 if not.
331 */
332 s32 Import(const char *filename, JTree<JResource *>::Node *where = 0, bool after = true);
333
334 /** Import from a JFS file.
335 * @param _name Name of the file to import.
336 * @return 0 If import succeeded, -1 if the file didn't exist, -2 if its not a valid JFS file.
337 * -3 if error during import.
338 */
339 s32 ImportJFS(const char *_name);
340
341 /** Loads the given resource.
342 * @param id Resource id of the resource to be loaded.
343 * @param where Pointer to the object where to load the resource.
344 * @return 0 if ok, 1 if I/O error and 2 if data integrity error.
345 */
346 u32 Load(u32 id, JLoadSave *where);
347
348 /** Returns an instance of the resource with the given name. If not loaded, loads it.
349 * @param _name Name of the resource.
350 * @return Requested reosurce or 0 (zero) if it wasn't found or an error occured.
351 */
352 JLoadSave * Get(const JString &_name);
353
354 /** Returns an instance of the resource with the given id.
355 * @param id Resource id.
356 * @return Requested reosurce or 0 (zero) if it wasn't found or an error occured.
357 */
358 JLoadSave * Get(u32 id);
359
360 /** Deletes the requested resource.
361 * @param _name Name of the resource to delete.
362 * @return <b>true</b> if it could be deleted <b>false</b> if not.
363 */
364 bool Delete(JString &_name);
365
366 /** Returns the name of the JFS file.
367 * @return Name of the JFS file.
368 */
369 const JString & Name() {return resFilename;}
370
371 /** Sets the current preffix.
372 * @param p Preffix.
373 */
374 void Prefix(const JString &p) {prefix = p;}
375
376 /** Gets the current preffix.
377 * @return p Current preffix.
378 */
379 const char * Prefix() {return prefix.Str();}
380
381 /** Sets the default flags.
382 * @param p Default flags to set.
383 */
384 void DefaultFlags(u32 flags) {defaultFlags = flags;}
385
386 /** Gets the default flags.
387 * @return Default flags.
388 */
389 u32 DefaultFlags() {return defaultFlags;}
390
391 /** Sets the default compression level.
392 * @param c Default compression level to set.
393 */
394 void CompressionLevel(s32 c) {compressionLevel = c;}
395
396 /** Returns the default compression level.
397 * @return Default compression level.
398 */
399 s32 CompressionLevel() {return compressionLevel;}
400
401 /** Returns a textual resource id based upon a filename and the current preffix.
402 * @param name Name of the file the resource comes from.
403 * @return Id string representation.
404 */
405 const JString IdFromFilename(const char *name);
406
407 /** Returns a file name from a resource id and the current preffix.
408 * @param name Name of the id.
409 * @return Filename.
410 */
411 const JString FilenameFromId(const char *name);
412
413 /** Exports the index in C header format to the given file.
414 * @param filename Name of the file where to export the identifiers.
415 * @return <b>true</b> if export succeeded, <b>false</b> if not.
416 */
417 bool ExportIndex(const char *filename);
418
419 /** Export the resource structure to a directory structure.
420 * @return 0 if ok, <0 if not.
421 */
422 s32 Export();
423
424 /** Destroys this object.
425 */
426 ~JFS() {JDELETE(it);}
427 };
428
429 #endif // _JFS_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 15/06/2003
25 // @description: Clase base de ficheros
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #include <JLib/Util/JObject.h>
29 #include <JLib/Util/JFile.h>
30
31 u32 JFile::MAX_BLOCK_SIZE = JFILE_DEF_MAX_BLOCK_SIZE;
32
33 // Constructor
34 JFile::JFile(const s8 *filename) : file(0), buff(0), name(0), exists(false), size(0), buffSize(0)
35 {
36 if (filename != 0)
37 {
38 name = new s8 [strlen(filename) + 1];
39 strcpy(name, filename);
40
41 Refresh();
42 }
43 }
44
45 // Destructor
46 JFile::~JFile()
47 {
48 Close(); // Quizá no sea necesario, ya que puede hacerlo el programador
49 JDELETE_ARRAY(name);
50 }
51
52 // Vuelve a consultar la información del fichero
53 s32 JFile::Refresh()
54 {
55 if (name)
56 {
57 s32 ret;
58 if (0 != (ret = stat(name, &statInfo)))
59 {
60 if (errno == ENOENT)
61 exists = false;
62 }
63 else
64 {
65 exists = true;
66 }
67
68 return ret;
69 }
70
71 return -2;
72 }
73
74 // Abre el fichero. mode como en open() de C. Si no existe actualiza
75 // el flag de existencia.
76 bool JFile::Open(const s8 *filename, const s8 *mode)
77 {
78 Close();
79
80 if (filename)
81 {
82 JDELETE_ARRAY(name);
83
84 name = new s8 [strlen(filename) + 1];
85 strcpy(name, filename);
86
87 // Refresca la información de fichero 'statInfo'
88 Refresh();
89 }
90
91 if (name != 0)
92 {
93 if (0 != (file = fopen(name, mode)))
94 {
95 return true;
96 }
97 }
98
99 return false;
100 }
101
102 // Lee el fichero. Si no se especifica readsize o es cero, lo lee entero
103 u32 JFile::Read(u32 readSize)
104 {
105 if (!readSize)
106 readSize = statInfo.st_size;
107
108 FreeBuffer();
109
110 buff = new s8[readSize];
111
112 return (buffSize = (u32)fread(buff, sizeof(s8), readSize, file));
113 }
114
115 u32 JFile::ZRead()
116 {
117 FreeBuffer();
118
119 u32 len, lenUncomp;
120
121 // Original & compressed size
122 if (!ReadLE32(&lenUncomp) ||
123 !ReadLE32(&len))
124 {
125 return 0;
126 }
127
128 unsigned char *buffComp = new unsigned char[len];
129
130 if (!buffComp)
131 {
132 return 0;
133 }
134
135 buffSize = lenUncomp;
136 buff = new s8[lenUncomp];
137
138 if (!buff)
139 {
140 delete[] buffComp;
141 return 0;
142 }
143
144 if (0 >= fread(buffComp, len, 1, file) && !feof(file))
145 {
146 delete[] buffComp;
147 delete[] buff;
148 return 0;
149 }
150
151 // For compatibility with zlib
152 unsigned long lenUL, lenUncompUL;
153 lenUncompUL = lenUncomp;
154 lenUL = len;
155
156 if (Z_OK != uncompress((Bytef*)buff, (uLongf*)&lenUncompUL, (Bytef*)buffComp, lenUL))
157 {
158 delete[] buffComp;
159 delete[] buff;
160 return 0;
161 }
162
163 delete[] buffComp;
164
165 return (u32)(lenUncompUL + 8);
166 }
167
168 // Carga todo el fichero. Equivalente a Open() + Read(0).
169 bool JFile::Load(const s8 *filename, const s8 *mode)
170 {
171 if (Open(filename, mode))
172 {
173 return 0 < Read();
174 }
175
176 return false;
177 }
178
179 // Lee del fichero
180 u32 JFile::Read(void *_buff, u32 _size)
181 {
182 return (u32)fread(_buff, sizeof(s8), _size, file);
183 }
184
185 u32 JFile::ReadBool(bool *_buff) {u8 b; if (0 < Read(&b, 1)) {*_buff = (b ? true : false); return 1;} return 0;}
186
187 u32 JFile::Read8(u8 *_buff) {if (0 < Read(_buff, 1)) return 1; return 0;}
188
189 u32 JFile::Read8(s8 *_buff) {if (0 < Read(_buff, 1)) return 1; return 0;}
190
191 u32 JFile::ReadLE16(u16 *_buff) {if (0 < Read(_buff, 2)) {*_buff = SDL_SwapLE16(*_buff); return 2;} return 0;}
192
193 u32 JFile::ReadLE16(s16 *_buff) {if (0 < Read(_buff, 2)) {*_buff = SDL_SwapLE16(*_buff); return 2;} return 0;}
194
195 u32 JFile::ReadBE16(u16 *_buff) {if (0 < Read(_buff, 2)) {*_buff = SDL_SwapBE16(*_buff); return 2;} return 0;}
196
197 u32 JFile::ReadBE16(s16 *_buff) {if (0 < Read(_buff, 2)) {*_buff = SDL_SwapBE16(*_buff); return 2;} return 0;}
198
199 u32 JFile::ReadLE32(u32 *_buff) {if (0 < Read(_buff, 4)) {*_buff = SDL_SwapLE32(*_buff); return 4;} return 0;}
200
201 u32 JFile::ReadLE32(s32 *_buff) {if (0 < Read(_buff, 4)) {*_buff = SDL_SwapLE32(*_buff); return 4;} return 0;}
202
203 u32 JFile::ReadBE32(u32 *_buff) {if (0 < Read(_buff, 4)) {*_buff = SDL_SwapBE32(*_buff); return 4;} return 0;}
204
205 u32 JFile::ReadBE32(s32 *_buff) {if (0 < Read(_buff, 4)) {*_buff = SDL_SwapBE32(*_buff); return 4;} return 0;}
206
207 u32 JFile::ZRead(void * &_buff)
208 {
209 u32 len, lenUncomp;
210
211 // Original & compressed size
212 if (!ReadLE32(&lenUncomp) ||
213 !ReadLE32(&len))
214 {
215 return 0;
216 }
217
218 unsigned char *buffComp = new unsigned char[len];
219
220 if (!buffComp)
221 {
222 return 0;
223 }
224
225 unsigned char *buffUncomp = new unsigned char[lenUncomp];
226
227 if (!buffUncomp)
228 {
229 delete[] buffComp;
230 return 0;
231 }
232
233 if (0 >= fread(buffComp, len, 1, file) && !feof(file))
234 {
235 delete[] buffComp;
236 delete[] buffUncomp;
237 return 0;
238 }
239
240 // For compatibility with zlib
241 unsigned long lenUL, lenUncompUL;
242 lenUncompUL = lenUncomp;
243 lenUL = len;
244
245 if (Z_OK != uncompress((Bytef*)buffUncomp, (uLongf*)&lenUncompUL, (Bytef*)buffComp, lenUL))
246 {
247 delete[] buffComp;
248 delete[] buffUncomp;
249 return 0;
250 }
251
252 delete[] buffComp;
253
254 return (u32)(lenUncompUL);
255 }
256
257 // Lee del fichero al buffer dado y deja el puntero
258 // en su posición original
259 u32 JFile::Peep(void *_buff, u32 _size)
260 {
261 s32 p = Pos();
262 u32 r = (u32)fread(_buff, _size, 1, file);
263 Pos(p);
264
265 return r;
266 }
267
268 u32 JFile::WriteBool(bool *_buff) {u8 b = ((*_buff) ? 1 : 0);return Write(&b, 1);}
269
270 u32 JFile::Write8(u8 *_buff) {return Write(_buff, 1);}
271
272 u32 JFile::Write8(s8 *_buff) {return Write(_buff, 1);}
273
274 u32 JFile::WriteLE16(u16 *_buff) {u16 v = SDL_SwapLE16(*_buff); return Write(&v, 2);}
275
276 u32 JFile::WriteLE16(s16 *_buff) {u16 v = SDL_SwapLE16(*_buff); return Write(&v, 2);}
277
278 u32 JFile::WriteBE16(u16 *_buff) {u16 v = SDL_SwapBE16(*_buff); return Write(&v, 2);}
279
280 u32 JFile::WriteBE16(s16 *_buff) {u16 v = SDL_SwapBE16(*_buff); return Write(&v, 2);}
281
282 u32 JFile::WriteLE32(u32 *_buff) {u32 v = SDL_SwapLE32(*_buff); return Write(&v, 4);}
283
284 u32 JFile::WriteLE32(s32 *_buff) {u32 v = SDL_SwapLE32(*_buff); return Write(&v, 4);}
285
286 u32 JFile::WriteBE32(u32 *_buff) {u32 v = SDL_SwapBE32(*_buff); return Write(&v, 4);}
287
288 u32 JFile::WriteBE32(s32 *_buff) {u32 v = SDL_SwapBE32(*_buff); return Write(&v, 4);}
289
290 // Escribe en el fichero
291 u32 JFile::Write(const void *_buff, u32 _size)
292 {
293 return (u32) fwrite(_buff, sizeof(s8), _size, file);
294 }
295
296 u32 JFile::ZWrite(const void *_buff, u32 _size, s32 level)
297 {
298 u32 sizeComp;
299 sizeComp = compressBound(_size);
300
301 unsigned char *buffComp = new unsigned char[sizeComp + 8];
302
303 if (!buffComp)
304 {
305 return 0;
306 }
307
308 // For compatibility with zlib
309 unsigned long sizeCompUL, sizeUL;
310 sizeCompUL = sizeComp;
311 sizeUL = _size;
312
313 if (Z_OK != compress2((Bytef*)buffComp, (uLongf*)&sizeCompUL, (Bytef*)_buff, sizeUL, level))
314 {
315 delete[] buffComp;
316 return 0;
317 }
318
319 sizeComp = (u32)sizeCompUL;
320
321 // Tamaño original + Tamaño comprimido + datos comprimidos
322 if (0 == WriteLE32(&_size) || 0 == WriteLE32(&sizeComp) ||
323 fwrite(buffComp, sizeComp, 1, file) <= 0)
324 {
325 delete[] buffComp;
326 return 0;
327 }
328
329 delete[] buffComp;
330
331 return sizeComp + 8;
332 }
333
334 // Cierra el fichero. Devuelve true si liberó memoria, false si no lo hizo.
335 bool JFile::Close()
336 {
337 if (!(file || buff))
338 return false;
339
340 if (file)
341 {
342 fclose(file);
343 file = 0;
344 }
345
346 FreeBuffer();
347
348 return true;
349 }
350
351 // Situa el puntero al inicio
352 void JFile::Rewind()
353 {
354 rewind(file);
355 }
356
357 // Libera la memoria del buffer de forma segura
358 void JFile::FreeBuffer()
359 {
360 if (buff)
361 {
362 delete[] buff;
363 buff = 0;
364 }
365 }
366
367 // Determina si existe el fichero
368 bool JFile::Exists(const s8 *name)
369 {
370 if (name != 0)
371 {
372 struct stat s;
373 if (0 != stat(name, &s))
374 {
375 if (errno == ENOENT)
376 {
377 return false;
378 }
379 }
380
381 return true;
382 }
383
384 return false;
385 }
386
387 // Determina si existe el fichero
388 u32 JFile::Size(const s8 *name)
389 {
390 if (name == 0)
391 return 0;
392
393 struct stat s;
394 if (0 == stat(name, &s))
395 {
396 return s.st_size;
397 }
398
399 return 0;
400 }
401
402 // Determina si el fichero dado es del tipo dado
403 bool JFile::IsOfType(const s8 *name, mode_t mode)
404 {
405 if (name == 0)
406 return false;
407
408 struct stat s;
409 if (0 == stat(name, &s))
410 {
411 return 0 != (s.st_mode & mode);
412 }
413
414 return false;
415 }
416
417 // Determina si existe el fichero
418 bool JFile::IsFile(const s8 *name)
419 {
420 return IsOfType(name, S_IFREG);
421 }
422
423 // Determina si existe el fichero
424 bool JFile::IsDir(const s8 *name)
425 {
426 return IsOfType(name, S_IFDIR);
427 }
428
429 // Determina si existe el fichero
430 bool JFile::IsLink(const s8 *name)
431 {
432 return IsOfType(name, S_IFLNK);
433 }
434
435 // Determina si existe el fichero
436 bool JFile::IsCharDev(const s8 *name)
437 {
438 return IsOfType(name, S_IFCHR);
439 }
440
441 // Determina si existe el fichero
442 bool JFile::IsBlockDev(const s8 *name)
443 {
444 return IsOfType(name, S_IFBLK);
445 }
446
447 bool JFile::ResizeBack(u32 numBytes)
448 {
449 if (numBytes == 0)
450 {
451 return false;
452 }
453
454 if (0 != fseek(file, 0, SEEK_END))
455 {
456 return false;
457 }
458
459 u32 pos = ftell(file);
460
461 if (0 != fseek(file, numBytes, SEEK_END) ||
462 0 != fseek(file, pos, SEEK_SET))
463 {
464 return false;
465 }
466
467 return true;
468 }
469
470 bool JFile::ResizeAt(u32 byte, s32 numBytes)
471 {
472 if (numBytes < 0)
473 {
474 return false;
475 }
476
477 if (numBytes == 0)
478 {
479 // Tan solo lo deja preparado para copiar en la zona dada
480 fseek(file, byte, SEEK_SET);
481 return true;
482 }
483
484 if (0 != fseek(file, 0, SEEK_END))
485 {
486 return false;
487 }
488
489 u32 oldEnd = ftell(file);
490
491 if (byte > oldEnd)
492 {
493 byte = oldEnd;
494 }
495
496 u32 remSize = oldEnd - byte; // Espacio restante por desplazar
497 u32 copiedSize = 0; // Espacio ya copiado
498
499 // Establece un tamaño de bloque de copia adecuado
500 u32 blockSize = MAX_BLOCK_SIZE < remSize ? MAX_BLOCK_SIZE : remSize;
501
502 // printf("BlockSize es %d\n", blockSize);
503
504 // Cambia el tamaño del fichero
505 fseek(file, numBytes, SEEK_END);
506 int ret;
507
508 if (!remSize)
509 {
510 fseek(file, 0, SEEK_SET);
511
512 return true;
513 }
514
515 // Guarda la nueva posición de fin
516 u32 newEnd = ftell(file);
517
518 u8 *copyBuff = new u8[blockSize];
519
520 // Desplaza el trozo final
521 while (remSize >= blockSize)
522 {
523 if (0 != fseek(file, oldEnd - copiedSize - blockSize, SEEK_SET))
524 perror("1");
525
526 if (0 > (ret = fread(copyBuff, blockSize, 1, file)) || feof(file))
527 perror("2");
528
529 if (0 != fseek(file, newEnd - copiedSize - blockSize, SEEK_SET))
530 perror("3");
531
532 if (0 >= (ret = fwrite(copyBuff, blockSize, 1, file)))
533 perror("4");
534
535 copiedSize += blockSize;
536 remSize -= blockSize;
537 }
538
539 if (remSize > 0)
540 {
541 // Copia el trozo final, si queda algo
542 blockSize = remSize;
543 if (0 != fseek(file, oldEnd - copiedSize - blockSize, SEEK_SET))
544 perror("1");
545
546 if (0 > (ret = fread(copyBuff, blockSize, 1, file)) || feof(file))
547 perror("2");
548
549 if (0 != fseek(file, newEnd - copiedSize - blockSize, SEEK_SET))
550 perror("3");
551
552 if (0 >= (ret = fwrite(copyBuff, blockSize, 1, file)))
553 perror("4");
554
555 copiedSize += blockSize;
556 remSize -= blockSize;
557 }
558
559 // fprintf(stderr, "Total por copiar %d bytes, copiados %d bytes newEnd es %d\n", remSize, copiedSize, newEnd);
560
561 if (copiedSize != oldEnd - byte)
562 {
563 fprintf(stderr, "No coincide el tamaño copiado (orig era %d, copiados %d)\n", oldEnd - byte, copiedSize);
564 }
565
566 if (remSize != 0)
567 {
568 fprintf(stderr, "Faltan datos por copiar (remSize != 0)\n");
569 }
570
571 // Deja el puntero al comienzo de la zona vacía
572 fseek(file, byte, SEEK_SET);
573
574 fflush(file);
575
576 delete[] copyBuff;
577
578 return true;
579 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** File base class.
23 * @file JFile.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 15/06/2003
26 * @version 0.0.1 - 15/06/2003 - First versio.
27 */
28
29 #ifndef _JFILE_INCLUDED
30 #define _JFILE_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <stdarg.h>
40 #include <SDL_endian.h>
41 #include <zlib.h>
42 #include <JLib/Util/JCompatibility.h>
43
44 /*** Maximum block size by default */
45 #define JFILE_DEF_MAX_BLOCK_SIZE 2097152
46
47 /** Encapsulates a file. Allows to read, write, resize, insert, compress, etc.
48 */
49 class JFile
50 {
51 protected:
52 FILE *file; /**< File pointer */
53 s8 *buff; /**< Auxilliary read buffer */
54 s8 *name; /**< File name */
55 bool exists; /**< Existence flag */
56 struct stat statInfo; /**< File information */
57 u32 size; /**< Size of the file */
58 u32 buffSize; /**< Size of the auxilliary buffer */
59 static u32 MAX_BLOCK_SIZE; /**< Max size of copy block buffer */
60
61 /** Determines if the given file is of the given type.
62 * @param name Name of the file to check.
63 * @param mode Type of file.
64 * @return <b>true</b> if so, <b>false</b> if not.
65 */
66 static bool IsOfType(const s8 *name, mode_t mode);
67
68 public:
69
70 /** Creates an empty file object.
71 * @param filename Name of the file (optional).
72 */
73 JFile(const s8 *filename = 0);
74
75 /** Destroys the object and frees allocated resources.
76 */
77 virtual ~JFile();
78
79 /** Gathers again the file information, (size, permissions, etc.).
80 * @return 0 (zero) if success, -1 if error and -2 if a name was not given.
81 */
82 s32 Refresh();
83
84 /** Opens the file.
85 * @param filename Name of the file to open.
86 * @param mode Opening modes in fopen(): {w|r|a}[+][{b|t}].
87 * by default is "r+b" (read-write, but don't create it if it doesn't exist and binario).
88 */
89 virtual bool Open(const s8 *filename = 0, const s8 *mode = "r+b");
90
91 /** Reads to the internal buffer.
92 * @param readSize Size in bytes to read from the file. If zero, the whole file is read.
93 * @return Number of bytes read or zero if an error occurred.
94 */
95 virtual u32 Read(u32 readSize = 0);
96
97 /** Reads from the file to the internal buffer, uncompressing the read data.
98 * @return Number of bytes of the uncompressed buffer or zero if an error ocurred.
99 */
100 virtual u32 ZRead();
101
102 /** Reads from the file to the given buffer.
103 * @param _buff Buffer to fill with the data read.
104 * @param _size Size in bytes to read. If zero, the whole file is read.
105 * @return Number of bytes read or zero if an error occurred.
106 */
107 virtual u32 Read(void *_buff, u32 _size);
108
109 /** Reads a boolean. WARNING: It is read as a single byte.
110 * @param _buff Variable to store the result.
111 * @return Number of bytes read or zero if an error ocurred.
112 */
113 virtual u32 ReadBool(bool *_buff);
114
115 /** Reads a byte.
116 * @param _buff Variable to store the result.
117 * @return Number of bytes read or zero if an error ocurred.
118 */
119 virtual u32 Read8(u8 *_buff);
120
121 /** Reads a byte.
122 * @param _buff Variable to store the result.
123 * @return Number of bytes read or zero if an error ocurred.
124 */
125 virtual u32 Read8(s8 *_buff);
126
127 /** Reads a data in little-endian format.
128 * @param _buff Variable to store the result in the machine's endianness.
129 * @return Number of bytes read or zero if an error ocurred.
130 */
131 virtual u32 ReadLE16(u16 *_buff);
132
133 /** Reads a data in little-endian format.
134 * @param _buff Variable to store the result in the machine's endianness.
135 * @return Number of bytes read or zero if an error ocurred.
136 */
137 virtual u32 ReadLE16(s16 *_buff);
138
139 /** Reads a data in big-endian format.
140 * @param _buff Variable to store the result in the machine's endianness.
141 * @return Number of bytes read or zero if an error ocurred.
142 */
143 virtual u32 ReadBE16(u16 *_buff);
144
145 /** Reads a data in big-endian format.
146 * @param _buff Variable to store the result in the machine's endianness.
147 * @return Number of bytes read or zero if an error ocurred.
148 */
149 virtual u32 ReadBE16(s16 *_buff);
150
151 /** Reads a data in little-endian format.
152 * @param _buff Variable to store the result in the machine's endianness.
153 * @return Number of bytes read or zero if an error ocurred.
154 */
155 virtual u32 ReadLE32(u32 *_buff);
156
157 /** Reads a data in little-endian format.
158 * @param _buff Variable to store the result in the machine's endianness.
159 * @return Number of bytes read or zero if an error ocurred.
160 */
161 virtual u32 ReadLE32(s32 *_buff);
162
163 /** Reads a data in big-endian format.
164 * @param _buff Variable to store the result in the machine's endianness.
165 * @return Number of bytes read or zero if an error ocurred.
166 */
167 virtual u32 ReadBE32(u32 *_buff);
168
169 /** Reads a data in big-endian format.
170 * @param _buff Variable to store the result in the machine's endianness.
171 * @return Number of bytes read or zero if an error ocurred.
172 */
173 virtual u32 ReadBE32(s32 *_buff);
174
175 /** Reads from the file to the given buffer, uncompressing the data. The first 4 bytes read are
176 * the uncompressed size. The next 4 are the size to read compressed. Then the data comes.
177 * @param _buff Buffer to fill with the uncompressed data. The memory is reserved using operator new from inside,
178 * the caller should delete it after using it.
179 * @return Uncompressed size.
180 */
181 virtual u32 ZRead(void * &_buff);
182
183 /** Reads from the file to the given buffer and leaves the poiter in its original position.
184 * @param _buff Buffer to fill with the data read.
185 * @param _size Size in bytes to read from the file. If zero, reads the whole file.
186 * @return Number of bytes read or zero if an error occurred.
187 */
188 virtual u32 Peep(void *_buff, u32 _size);
189
190 /** Loads the whole file. Is the same as Open() + Read(0).
191 * @param filename Name of the file to load.
192 * @param mode Opening mode as that of fopen(): {w|r|a}[+][{b|t}]. By default, "rb" is used.
193 * @return <b>true</b> if loaded successfuly, <b>false</b> if not.
194 */
195 virtual bool Load(const s8 *filename, const s8 *mode = "rb");
196
197 /** Writes in the file.
198 * @param _buff Buffer with the data to write.
199 * @param _size Size in bytes to write.
200 * @return Number of bytes written or zero if an error occurred.
201 */
202 virtual u32 Write(const void *_buff, u32 _size);
203
204 /** Writes a boolean. It is stored as a single byte.
205 * @param _buff Variable with the value to store.
206 * @return Number of bytes written or zero if an error ocurred.
207 */
208 u32 WriteBool(bool *_buff);
209
210 /** Writes a byte.
211 * @param _buff Variable with the value to store.
212 * @return Number of bytes written or zero if an error ocurred.
213 */
214 u32 Write8(u8 *_buff);
215
216 /** Writes a byte.
217 * @param _buff Variable with the value to store.
218 * @return Number of bytes written or zero if an error ocurred.
219 */
220 u32 Write8(s8 *_buff);
221
222 /** Writes a data in little-endian format.
223 * @param _buff Variable with the value to store in the machine's endianness.
224 * @return Number of bytes written or zero if an error ocurred.
225 */
226 u32 WriteLE16(u16 *_buff);
227
228 /** Writes a data in little-endian format.
229 * @param _buff Variable with the value to store in the machine's endianness.
230 * @return Number of bytes written or zero if an error ocurred.
231 */
232 u32 WriteLE16(s16 *_buff);
233
234 /** Writes a data in big-endian format.
235 * @param _buff Variable with the value to store in the machine's endianness.
236 * @return Number of bytes written or zero if an error ocurred.
237 */
238 u32 WriteBE16(u16 *_buff);
239
240 /** Writes a data in big-endian format.
241 * @param _buff Variable with the value to store in the machine's endianness.
242 * @return Number of bytes written or zero if an error ocurred.
243 */
244 u32 WriteBE16(s16 *_buff);
245
246 /** Writes a data in little-endian format.
247 * @param _buff Variable with the value to store in the machine's endianness.
248 * @return Number of bytes written or zero if an error ocurred.
249 */
250 u32 WriteLE32(u32 *_buff);
251
252 /** Writes a data in little-endian format.
253 * @param _buff Variable with the value to store in the machine's endianness.
254 * @return Number of bytes written or zero if an error ocurred.
255 */
256 u32 WriteLE32(s32 *_buff);
257
258 /** Writes a data in big-endian format.
259 * @param _buff Variable with the value to store in the machine's endianness.
260 * @return Number of bytes written or zero if an error ocurred.
261 */
262 u32 WriteBE32(u32 *_buff);
263
264 /** Writes a data in big-endian format.
265 * @param _buff Variable with the value to store in the machine's endianness.
266 * @return Number of bytes written or zero if an error ocurred.
267 */
268 u32 WriteBE32(s32 *_buff);
269
270 /** Writes compressed to the file. The format is
271 * [size uncompressed][size compressed][compressed data].
272 * @param _buff Buffer with the data to write.
273 * @param _size Size of the data to write.
274 * @param level Compression level, 1 (lowest) to 9 (greatest).
275 * @return Number of bytes written (including the 8 of the header) or zero if an error occurred.
276 */
277 virtual u32 ZWrite(const void *_buff, u32 _size, s32 level = 9);
278
279 /** Returns the internal read buffer.
280 * @return Internal buffer. NEVER must be deleted from outside the class.
281 */
282 virtual s8 *Buffer() {return buff;}
283
284 /** Returns the size of the internal buffer. Its the size of the last Read operation to the internal buffer.
285 * @return Size of the internal buffer.
286 */
287 virtual u32 BufferSize() {return buffSize;}
288
289 /** Returns the size of the file. If the file could have changed its size since its creation,
290 * is necessary a call to Refresh.
291 * @return Size in bytes of the file.
292 */
293 inline u32 FileSize() {return statInfo.st_size;}
294
295 /** Frees the internal buffer.
296 */
297 virtual void FreeBuffer();
298
299 /** Places the file pointer at the beginning of the file.
300 */
301 virtual void Rewind();
302
303 /** Closes the file.
304 * @return <b>true</b> if memory was freed, <b>false</b> if it was not necessary.
305 */
306 virtual bool Close();
307
308 /** Returns the internal file pointer.
309 * @return Internal file pointer.
310 */
311 virtual const FILE * File() {return file;}
312
313 /** Returns the name of the file.
314 * @return Name of the file.
315 */
316 virtual const s8 * Name() {return name;}
317
318 /** Returns the current position in bytes from the beginning of the file.
319 * @return Current position in bytes from the beginning of the file.
320 */
321 virtual s32 Pos() {return ftell(file);}
322
323 /** Sets the current position of the file pointer.
324 * @param pos New position, in bytes.
325 * @return <b>true</b> if the position waswithin the file, <b>false</b> if not.
326 */
327 virtual bool Pos(s32 pos) {return 0 == fseek(file, pos, SEEK_SET);}
328
329 /** Seeks to the given position.
330 * @param pos Position to seek.
331 * @param whence Source of the seeking (SEEK_SET, SEEK_CUR, SEEK_END).
332 * @return <b>true</b> if reached, <b>false</b> if not.
333 */
334 virtual bool Seek(s32 pos, u32 whence) {return 0 == fseek(file, pos, whence);}
335
336 /** Determines if this file exists. If the file has been created from outside the class,
337 * Refresh() must be called.
338 * @return <b>true</b> if it exists, <b>false</b> if not.
339 */
340 virtual bool Exists() {return exists;}
341
342 /** Returns the size of this file in bytes.
343 * @return Size in bytes of the file.
344 */
345 virtual u32 Size() {return statInfo.st_size;}
346
347 /** Determines if this file is a regular file or not (link, directory, etc.)
348 * @return <b>true</b> if so, <b>false</b> if not.
349 */
350 bool IsFile() {return 0 != (statInfo.st_mode & S_IFREG);}
351
352 /** Determines if it's a directory.
353 * @return <b>true</b> if so, <b>false</b> if not.
354 */
355 bool IsDir() {return 0 != (statInfo.st_mode & S_IFDIR);}
356
357 /** Determines if it's a link to another file.
358 * @return <b>true</b> if so, <b>false</b> if not.
359 */
360 bool IsLink() {return 0 != (statInfo.st_mode & S_IFLNK);}
361
362 /** Determines if it's a character device.
363 * @return <b>true</b> if so, <b>false</b> if not.
364 */
365 bool IsCharDev() {return 0 != (statInfo.st_mode & S_IFCHR);}
366
367 /** Determines if it's a block device.
368 * @return <b>true</b> if so, <b>false</b> if not.
369 */
370 bool IsBlockDev() {return 0 != (statInfo.st_mode & S_IFBLK);}
371
372 /** Determines if a file with the given name exists.
373 * @param name Name of the file to test.
374 * @return <b>true</b> if it exists, <b>false</b> if not.
375 */
376 static bool Exists(const s8 *name);
377
378 /** Determines the size of the given file.
379 * @param name Name of the file.
380 * @return Size in bytes of the file. If it does not exist, it returns 0 (zero).
381 */
382 static u32 Size(const s8 *name);
383
384 /** Determines if it's a regular file.
385 * @param name Name of the file.
386 * @return <b>true</b> if so, <b>false</b> if not.
387 */
388 static bool IsFile(const s8 *name);
389
390 /** Determines if it's a directory.
391 * @param name Name of the file.
392 * @return <b>true</b> if so, <b>false</b> if not.
393 */
394 static bool IsDir(const s8 *name);
395
396 /** Determines if it's a link.
397 * @param name Name of the file.
398 * @return <b>true</b> if so, <b>false</b> if not.
399 */
400 static bool IsLink(const s8 *name);
401
402 /** Determines if it's a character device.
403 * @param name Name of the file.
404 * @return <b>true</b> if so, <b>false</b> if not.
405 */
406 static bool IsCharDev(const s8 *name);
407
408 /** Determines if it's a block device.
409 * @param name Name of the file.
410 * @return <b>true</b> if so, <b>false</b> if not.
411 */
412 static bool IsBlockDev(const s8 *name);
413
414 /** Ensures all the data are written in the physical media.
415 * @return <b>true</b> if succeeded, <b>false</b> otherwise.
416 */
417 bool Flush() {return 0 == fflush(file);}
418
419 /** Resizes this file, moving in disk the necessary bytes from the insert position
420 * After it, the file is ready to write in the new region.
421 * The opening mode must be binary and read and write (not only "wb", but "r+b").
422 * @param byte Position of the first byte left blank.
423 * @param numBytes Number of blank bytes to insert.
424 * @return <b>true</b> if it succeeds, <b>false</b> if not.
425 */
426 bool ResizeAt(u32 byte, s32 numBytes);
427
428 /** Resizes this file, moving in disk the necessary bytes from the beginning of the file.
429 * After it, the file is ready to write in the new region.
430 * The opening mode must be binary and read and write (not only "wb", but "r+b").
431 * @param numBytes Number of blank bytes to insert.
432 * @return <b>true</b> if it succeeds, <b>false</b> if not.
433 */
434 bool ResizeFront(u32 numBytes) {return ResizeAt(0, numBytes);}
435
436 /** Changes the size of the file at the end of it (thus, no need to move any bytes).
437 * The opening mode must be binary and read and write (not only "wb", but "r+b").
438 * @param numBytes Number of blank bytes to insert.
439 * @return <b>true</b> if it succeeds, <b>false</b> if not.
440 */
441 bool ResizeBack(u32 numBytes);
442
443 /** Sets the maximum transfer block size for a resize operation like ResizeAt() or ResizeFront().
444 * Its default value is JFILE_DEF_MAX_BLOCK_SIZE (2MB). Ideally this value should be that of the maximum DMA
445 * transfer block in order to obtain the best results (above this value, there are no significant benefits
446 * and furthermore the memory needed must be previously allocated by the class so it can be a penalty).
447 * @param max New New block size (at least 1).
448 */
449 static void MaxBlockSize(u32 max) {MAX_BLOCK_SIZE = (max > 0) ? max : 1;}
450
451 /** Returns the maximum transfer block size for resize operations like ResizeAt() and ResizeFront().
452 * By default this value is JFILE_DEF_MAX_BLOCK_SIZE (2MB).
453 * @return Maximum transfer block size.
454 */
455 static u32 MaxBlockSize() {return MAX_BLOCK_SIZE;}
456 };
457
458 #endif // _JFILE_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clase de aplicación OpenGL.
23 * @file JGLApp.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 01/04/2003
26 * @version 0.0.1 - 01/04/2003 - Primera versión.
27 */
28
29 #include <JLib/Util/JGLApp.h>
30
31 // Constructor
32 JGLApp::JGLApp(const JString &strTitle, s32 w, s32 h, bool fullScr, s32 _depth, u32 otherFlags)
33 : JApp(strTitle, w, h, fullScr, _depth, otherFlags)
34 {
35 }
36
37 // Inicializa la aplicación
38 bool JGLApp::Init()
39 {
40 if (-1 == SDL_Init(SDL_INIT_EVERYTHING))
41 {
42 return false;
43 }
44
45 // Establece los valores de profundidad por canal
46 s32 rd = 5, gd = 6, bd = 5, ad = 0, db = 1;
47
48 switch (depth)
49 {
50 case 24:
51 rd = gd = bd = ad = 8;
52 break;
53
54 case 32:
55 rd = gd = bd = ad = 8;
56 break;
57
58 default:
59 break;
60 }
61
62 SDL_GL_SetAttribute( SDL_GL_RED_SIZE, rd );
63 SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, gd );
64 SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, bd );
65 SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, ad );
66 SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, depth );
67 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, db );
68
69 flags |= SDL_OPENGL | SDL_OPENGLBLIT;
70 if (fullScreen)
71 flags |= SDL_FULLSCREEN;
72
73 if ( (screen = SDL_SetVideoMode(width, height, depth, flags)) == 0 )
74 {
75 fprintf(stderr, "No se pudo establecer el modo OpenGL: %s\n", SDL_GetError());
76 SDL_Quit();
77 return false;
78 }
79
80 SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &rd );
81 SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, &gd );
82 SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, &bd );
83 SDL_GL_GetAttribute( SDL_GL_ALPHA_SIZE, &ad );
84 SDL_GL_GetAttribute( SDL_GL_DOUBLEBUFFER, &db );
85
86 fprintf(stderr, "Setvideomode(): \n");
87 fprintf(stderr, "W=%d H=%d BPP=%d\n", screen->w, screen->h, screen->format->BitsPerPixel);
88 fprintf(stderr, "OpenGL: %s\n", screen->flags & SDL_OPENGL ? "YES" : "NO");
89 fprintf(stderr, "OpenGL blitting: %s\n", screen->flags & SDL_OPENGLBLIT ? "YES" : "NO");
90 fprintf(stderr, "FullScreen: %s\n", screen->flags & SDL_FULLSCREEN ? "YES" : "NO");
91 fprintf(stderr, "R:%d G:%d B:%d A:%d D-Buffer:%d\n", rd, gd, bd, ad, db);
92 fprintf(stderr, "\n");
93
94 glViewport(0, 0, width, height);
95
96 glMatrixMode(GL_PROJECTION);
97 glLoadIdentity();
98 gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 10000.0f);
99
100 glMatrixMode(GL_MODELVIEW);
101 glLoadIdentity();
102
103 glClearColor(0.0f, 0.2f, 0.2f, 1.0f);
104 glClearDepth(1.0f);
105 glEnable(GL_DEPTH_TEST);
106 glDepthFunc(GL_LEQUAL);
107
108 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
109 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
110 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
111 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
112
113 // Establecemos el título
114 SDL_WM_SetCaption(title, 0);
115
116 // Activamos la repetición de teclas
117 SDL_EnableKeyRepeat(300, 30);
118
119 // Inicializamos el array de teclas
120 keys = SDL_GetKeyState(&numKeys);
121
122 return true; // Todo OK
123 }
124
125 // Destructor
126 JGLApp::~JGLApp()
127 {
128 SDL_Quit();
129 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** OpenGL application base class.
23 * @file JGLApp.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 01/04/2003
26 * @version 0.0.1 - 01/04/2003 - First version.
27 */
28
29 #ifndef _JGLAPP_INCLUDED
30 #define _JGLAPP_INCLUDED
31
32 #ifdef WIN32
33 #include <windows.h>
34 #endif
35
36 #include <JLib/Util/JApp.h>
37 #include <SDL.h>
38 #include <GL/gl.h>
39 #include <GL/glu.h>
40 #include <stdio.h>
41
42 class JGLApp : public JApp
43 {
44 public:
45 /** Creates the app.
46 * @param strTitle Window title.
47 * @param w Window width.
48 * @param h Window height.
49 * @param fullScr Fullscreen mode flag.
50 * @param _depth Color depth.
51 * @param otherFlags SDL additional flags. By default SDL_OPENGL | SDL_OPENGLBLIT are used.
52 */
53 JGLApp(const JString &strTitle, s32 w = 640, s32 h = 480, bool fullScr = false, s32 _depth = 16, u32 otherFlags = 0);
54
55 /** Ends the application. The base class (JApp) quits SDL.
56 */
57 virtual ~JGLApp();
58
59 /** Inits the app.
60 * @return <b>true</b> if succeeded, <b>false</b> if not.
61 */
62 virtual bool Init();
63
64 /** Swaps front and back buffer if dowblu buffered, else simply updates the screen.
65 */
66 void SwapBuffers() {SDL_GL_SwapBuffers();}
67 };
68
69 #endif // JGLAPP_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Linked list class
23 * @file JList.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 23/10/2005
26 * @version 0.0.1 - 23/10/2005 - First version.
27 */
28
29 #ifndef _JLIST_INCLUDED
30 #define _JLIST_INCLUDED
31
32 #include <assert.h>
33
34 #include <JLib/Util/JTypes.h>
35 #include <JLib/Util/JStack.h>
36
37 /** This template provides a doubly-linked list.
38 */
39 template<class T, unsigned int growBy=128>
40 class JList
41 {
42 public:
43 class Iterator;
44
45 /** List node.
46 */
47 class Node
48 {
49 friend class JList;
50 friend class Iterator;
51 T data; /**< Node data */
52 Node *prev; /**< Previous node */
53 Node *next; /**< Next node */
54
55 public:
56 Node() {}
57 Node(const T& n) {data = n.data; prev = n.prev; next = n.next;}
58 Node(const T &d, Node *p, Node *n) : data(d), prev(0), next(0) {}
59 Link(const T &d, Node *p, Node *n) {data = d; prev = p; next = n; n->prev = this; p->next = this;}
60 Unlink() {prev->next = next; next->prev = prev;}
61 Node & operator=(const Node &n) {data = n.data; prev = n.prev; next = n.next; return *this;}
62 };
63
64 /** List iterator.
65 */
66 class Iterator
67 {
68 friend class JList;
69 Node *cur; /**< Node this iterator points to */
70
71 public:
72
73 /** Creates an empty iterator (pointing to nowhere).
74 */
75 Iterator() : cur(0) {}
76
77 /** Creates an iterator pointing to the given node.
78 * @param node Node this iterator must point to.
79 */
80 Iterator(Node *node) : cur(node) {}
81
82 /** Assings another iterator to this iterator.
83 * @param other Other iterator.
84 * @return This iterator.
85 */
86 Iterator & operator=(const Iterator &other) {cur = other.cur; return *this;}
87
88 /** Test equality between iterators.
89 * @param other Other iterator.
90 * @return <b>true</b> if they are equal, <b>false</b> otherwise.
91 */
92 bool operator==(const Iterator &other) {return cur == other.cur;}
93
94 /** Test inequality between iterators.
95 * @param other Other iterator.
96 * @return <b>true</b> if they are different, <b>false</b> otherwise.
97 */
98 bool operator!=(const Iterator &other) {return cur != other.cur;}
99
100 /** Goes to the next element.
101 */
102 void Next() {if (cur->next == 0) return; cur = cur->next;}
103
104 /** Goes to the next element.
105 */
106 void operator++() {if (cur->next == 0) return; cur = cur->next;}
107
108 /** Goes to the previous element.
109 */
110 void Prev() {if (cur->prev == 0) return; cur = cur->prev;}
111
112 /** Goes to the previous element.
113 */
114 void operator--() {if (cur->prev == 0) return; cur = cur->prev;}
115
116 /** Returns the data of the current element.
117 * @return Data of the current element.
118 */
119 T& Data() {return cur->data;}
120
121 /** Returns the data of the current element.
122 * @return Data of the current element.
123 */
124 T& operator*() {return cur->data;}
125 };
126
127 protected:
128 Node first; /**< First element */
129 Node last; /**< Last element */
130 int grow; /**< Growing amount */
131 int size; /**< Current size of the list */
132 int nextFree; /**< Next free node */
133 JStack<Node *> mem; /**< Memory allocator */
134 Iterator begin; /**< Iterator to first element */
135 Iterator end; /**< Iterator to last element */
136
137 public:
138 /** Creates an empty list.
139 * @param growBy Grow amount, i.e. the initial capacity of the list before grow is necessary and the
140 * memory steps of the grow phase. Note that the underlying memory allocator is a JStack so the growing
141 * takes place first as the growBy, then at 2*growBy, then at 4*growBy, and so on. The value affects
142 * considerably the insertion of new elements, as a rule of thumb select a value that is close to your
143 * needs (if known, of course). If not known, the default (128) is conservative and gives good speed results.
144 */
145 JList(unsigned int _growBy = growBy) : grow(_growBy), size(0), nextFree(0), mem(1)
146 {
147 mem.Push(new Node[grow]);
148 first.next = &last;
149 last.prev = &first;
150 end.cur = &last;
151 }
152
153 /** Inserts the given data at the front of the list.
154 * @param data Data to be inserted.
155 */
156 void PushFront(const T& data)
157 {
158 if (nextFree >= grow)
159 {
160 nextFree = 0;
161 mem.Push(new Node[grow]);
162 //printf("mem has now %d max items\n", mem.MaxSize());
163 }
164
165 mem.Top()[nextFree].Link(data, &first, first.next);
166 ++nextFree;
167 ++size;
168 }
169
170 /** Inserts the given data at the back of the list.
171 * @param data Data to be inserted.
172 */
173 void PushBack(const T& data)
174 {
175 if (nextFree >= grow)
176 {
177 nextFree = 0;
178 mem.Push(new Node[grow]);
179 //printf("mem has now %d max items\n", mem.MaxSize());
180 }
181
182 mem.Top()[nextFree].Link(data, last.prev, &last);
183 ++nextFree;
184 ++size;
185 }
186
187 /** Inserts the given data before the element at the given iterator.
188 * @param data Data to be inserted.
189 * @param it Iterator to the element before which insert.
190 */
191 void Insert(const T& data, Iterator &it)
192 {
193 if (nextFree >= grow)
194 {
195 nextFree = 0;
196 mem.Push(new Node[grow]);
197 //printf("mem has now %d max items\n", mem.MaxSize());
198 }
199
200 mem.Top()[nextFree].Link(data, it.cur->prev, it.cur);
201 ++nextFree;
202 ++size;
203 }
204
205 /** Removes the element at the back of the list. WARNING: This method doesn't check for
206 * existing elements in the list, one must check it if necessary from outside.
207 */
208 void PopBack()
209 {
210 assert(nextFree != 0 || printf("JList PopBack with no elements!\n"));
211
212 // DBG ///////////
213 // printf(" Están así : FIRST-");
214 // Node *n = first.next;
215 // int jj = 0;
216 // while (n != &last || jj++ > 5)
217 // {
218 // if (n->data)
219 // {
220 // printf("%s-", n->data);
221 // }
222 // n = n->next;
223 // }
224 // printf("LAST\n");
225 // DBG ///////////
226
227 if (last.prev != &(mem.Top()[nextFree - 1]))
228 {
229 // Not at the top of the stack, replaces that element with this one
230 Node n(*last.prev);
231 *last.prev = mem.Top()[nextFree - 1];
232 n.Unlink();
233 }
234 else
235 {
236 last.prev->Unlink();
237 }
238
239 // DBG ///////////
240 // printf(" Tras Unlink(): FIRST-");
241 // n = first.next;
242 // jj = 0;
243 // while (n != &last || jj++ > 5)
244 // {
245 // if (n->data)
246 // {
247 // printf("%s-", n->data);
248 // }
249 // n = n->next;
250 // }
251 // printf("LAST\n\n");
252 // DBG ///////////
253
254 if (--nextFree == 0)
255 {
256 nextFree = grow;
257 mem.Pop();
258 }
259
260 --size;
261 }
262
263 /** Removes the element at the front of the list. WARNING: This method doesn't check for
264 * existing elements in the list, one must check it if necessary from outside.
265 */
266 void PopFront()
267 {
268 assert(nextFree != 0 || printf("JList PopBack with no elements!\n"));
269
270 if (first.next != &(mem.Top()[nextFree - 1]))
271 {
272 // Not at the top of the stack, replaces that element with this one
273 Node n(*first.next);
274 *first.next = mem.Top()[nextFree - 1];
275 n.Unlink();
276 }
277 else
278 {
279 first.next->Unlink();
280 }
281
282 if (--nextFree == 0)
283 {
284 nextFree = grow;
285 mem.Pop();
286 }
287
288 --size;
289 }
290
291 /** Removes the element at the given position and places the iterator in the next element.
292 * WARNING: this method does not check if the iterator is valid, one must must check it outside if
293 * needed.
294 * @param it Iterator at the element to be removed.
295 */
296 void Remove(Iterator &it)
297 {
298 assert(nextFree != 0 || printf("JList PopBack with no elements!\n"));
299
300 if (it.cur != &(mem.Top()[nextFree - 1]))
301 {
302 // Not at the top of the stack, replaces that element with this one
303 Node n(*it.cur);
304 *it.cur = mem.Top()[nextFree - 1];
305 n.Unlink();
306 it.cur = n.next;
307 }
308 else
309 {
310 it.cur->Unlink();
311 it.cur = it.cur->next;
312 }
313
314 if (--nextFree == 0)
315 {
316 nextFree = grow;
317 mem.Pop();
318 }
319
320 --size;
321 }
322
323 /** Returns an iterator at the first element of the list.
324 * If the list is empty, this iterator is the same (in the sense of operator=) to that of End().
325 * @return Iterator at the first element or at one past the last element if the list is empty.
326 */
327 const Iterator & Begin() {begin.cur = first.next; return begin;}
328
329 /** Returns an iterator at one past the last element of the list.
330 * @return Iterator at one past the last element.
331 */
332 const Iterator & End() {return end;}
333
334 /** Returns the number of elements in the list.
335 * @return Number of elements in the list.
336 */
337 int Size() {return size;}
338
339 /** Returns the maximum number of elements that fit in the list.
340 * @return Maximum number of elements that fit in the list before growing is necessary.
341 */
342 int MaxSize() {return mem.MaxSize();}
343
344 /** Destroys the list, frees used resources.
345 */
346 ~JList()
347 {
348 while (!mem.Empty())
349 {
350 delete[] mem.Top();
351 mem.Pop();
352 }
353 }
354 };
355
356 #endif // _JLIST_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Interface for the objects to be loaded from and saved to a JRW object.
23 * @file JLoadSave.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 24/12/2003
26 * @version 0.0.1 - 24/12/2003 - First version.
27 */
28
29 #ifndef _JLOADSAVE_INCLUDED
30 #define _JLOADSAVE_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Util/JObject.h>
34 #include <JLib/Util/JFile.h>
35 #include <JLib/Util/JRW.h>
36
37 /** Interface for the objects to be loaded from and saved to a JRW object.
38 * Has methods to be implemented in the child classes to save and load from a JRW source.
39 */
40 class JLoadSave
41 {
42 public:
43 /** Loads the object from the actual position of the given source.
44 * @param jrw JRW object correctly positioned.
45 * @return 0 if ok, 1 if I/O error, 2 if data integrity error.
46 */
47 virtual u32 Load(JRW &jrw){return 0;};
48
49 /** Saves the object to the actual position of the given source.
50 * @param jrw JRW object correctly positioned.
51 * @return 0 if ok, 1 if I/O error, 2 if data integrity error.
52 */
53 virtual u32 Save(JRW &jrw){return 0;};
54
55 /** Loads an array of objects in the given source's actual position.
56 * The format is: [numObjects (4bytes)][obj_1]...[obj_numObjects]
57 * @param numObjects Number of objects in the array.
58 * @param ls JLoadSave object array.
59 * @param f JRW object correctly positioned.
60 * @return 0 if ok, 1 if I/O error, 2 if data integrity error.
61 */
62 virtual u32 LoadList(u32 *numObjects, JLoadSave *ls, JRW &f) {return 0;}
63
64 /** Saves an array of objects in the given source's actual position.
65 * The format is: [numObjects (4bytes)][obj_1]...[obj_numObjects]
66 * @param numObjects Number of objects in the array.
67 * @param ls JLoadSave object array.
68 * @param f JRW object correctly positioned.
69 * @return 0 if ok, 1 if I/O error, 2 if data integrity error.
70 */
71 virtual u32 SaveList(u32 numObjects, JLoadSave *ls, JRW &f) {return 0;}
72
73 /** Destroys the object.
74 */
75 virtual ~JLoadSave() {}
76 };
77
78 #endif // _JLOADSAVE_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Linked list class
23 * @file JNeuralNetwork.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 23/10/2005
26 * @version 0.0.1 - 23/10/2005 - First version.
27 */
28
29 #ifndef _JNEURALNETWORK_INCLUDED
30 #define _JNEURALNETWORK_INCLUDED
31
32 #include <assert.h>
33
34 #include <JLib/Util/JTypes.h>
35 #include <vector>
36 #include <list>
37
38 /** This template provides a neural network.
39 */
40 template<class T>
41 class JNeuralNetwork
42 {
43 public:
44 class Iterator;
45
46 /** Network node.
47 */
48 class Node
49 {
50 friend class JNeuralNetwork;
51 friend class Iterator;
52 T data; /**< Node data */
53 std::vector<Node *> links; /**< Vector of links. */
54
55 Node(const Node& n) {}
56
57 public:
58 Node() {}
59 Node(const T &d) : data(d) {}
60 void Link(Node *n) {links.push_back(n);}
61 void DLink(Node *n) {links.push_back(n); n->links.push_back(this);}
62 bool Linked(Node *n) {for (s32 i = 0; i < links.size(); ++i) if (links[i] == n) return true; return false;}
63 bool DLinked(Node *n) {return Linked(n) && n->Linked(this);}
64 void Unlink(Node *n) {for (s32 i = 0; i < links.size(); ++i) if (links[i] == n) {links.erase(links.begin() + i); return;}}
65 void DUnlink(Node *n) {Unlink(n); n->Unlink(this);}
66 void Isolate() {links.clear();}
67 s32 NumLinks() {return links.size();}
68 Node * NodeAt(s32 index) {return links[index];}
69 T& Data() {return data;}
70 Node & operator=(const Node &n) {data = n.data; links.clear(); links.insert(n.links); return *this;}
71 ~Node() {links.clear();}
72 };
73
74 /** List iterator.
75 */
76 class Iterator
77 {
78 friend class JNeuralNetwork;
79 Node *cur; /**< Node this iterator points to */
80
81 public:
82
83 /** Creates an empty iterator (pointing to nowhere).
84 */
85 Iterator() : cur(0) {}
86
87 /** Creates an iterator pointing to the given node.
88 * @param node Node this iterator must point to.
89 */
90 Iterator(Node *node) : cur(node) {}
91
92 /** Assings another iterator to this iterator.
93 * @param other Other iterator.
94 * @return This iterator.
95 */
96 Iterator & operator=(const Iterator &other) {cur = other.cur; return *this;}
97
98 /** Test equality between iterators.
99 * @param other Other iterator.
100 * @return <b>true</b> if they are equal, <b>false</b> otherwise.
101 */
102 bool operator==(const Iterator &other) {return cur == other.cur;}
103
104 /** Test inequality between iterators.
105 * @param other Other iterator.
106 * @return <b>true</b> if they are different, <b>false</b> otherwise.
107 */
108 bool operator!=(const Iterator &other) {return cur != other.cur;}
109
110 /** Goes to the element linked by the given path.
111 */
112 void Move(s32 pathNum) {if (pathNum >= cur->NumLinks()) return; cur = cur->links[pathNum];}
113
114 /** Returns the number of links in the current node.
115 */
116 s32 NumLinks() {return cur->links.size();}
117
118 void Unlink(s32 i) {if (cur->links.size() > i) erase(cur->links.begin() + i);}
119 void DUnlink(s32 i) {if (cur->links.size() > i) {erase(cur->links.begin() + i); cur->links[i]->Unlink(cur);}}
120
121 void Link(Node *n) {cur->links.push_back(n);}
122 void DLink(Node *n) {cur->links.push_back(n); n.links.push_back(cur);}
123 bool Linked(Node *n) {for (s32 i = 0; i < cur->links.size(); ++i) if (cur->links[i] == n) return true; return false;}
124 bool DLinked(Node *n) {return cur->Linked(n) && n->Linked(cur);}
125 void Unlink(Node *n) {for (s32 i = 0; i < cur->links.size(); ++i) if (cur->links[i] == n) {erase(cur->links.begin() + i); return;}}
126 void DUnlink(Node *n) {cur->Unlink(n); n->Unlink(cur);}
127 void Isolate() {for (s32 i = 0; i < cur->links.size(); ++i) links[i]->Unlink(this); cur->links.clear();}
128
129 /** Gives the node at the given link number.
130 */
131 Node * NodeAt(s32 index) {return cur->links[index];}
132
133 /** Returns the current node.
134 * @return Current node.
135 */
136 const Node* GetNode() {return cur;}
137
138 /** Returns the data of the current element.
139 * @return Data of the current element.
140 */
141 T& Data() {return cur->data;}
142
143 /** Returns the data of the current element.
144 * @return Data of the current element.
145 */
146 T& operator*() {return cur->data;}
147 };
148
149 protected:
150 std::vector<Node *> nodes; /**< List of network nodes. */
151 Iterator begin; /**< Iterator to the first element. */
152 Iterator end; /**< Iterator to one past the last element. */
153
154 public:
155 /** Creates an empty network.
156 */
157 JNeuralNetwork()
158 {}
159
160 /** Creates and adds a node to the network.
161 * @param data Data of the node to be added.
162 * @return Created node.
163 */
164 Node * New(const T& data)
165 {
166 Node *n = new Node(data);
167 nodes.push_back(n);
168 return n;
169 }
170
171 /** Adds a node to the network.
172 * @param data Data of the node to be added.
173 */
174 void Add(Node *n)
175 {
176 nodes.push_back(n);
177 }
178
179 /** Removes the given element.
180 */
181 void Del(Node *n)
182 {
183 if (n)
184 {
185 n->Isolate();
186 for (s32 i = 0; i < nodes.size(); ++i)
187 {
188 if (nodes[i] == n)
189 {
190 delete nodes[i];
191 nodes.erase(nodes.begin() + i);
192 return;
193 }
194 }
195 }
196 }
197
198 /** Returns the first node with the given data.
199 * @return First node containing the given data or null if it isn't found.
200 */
201 Node * Get(const T &data)
202 {
203 for (s32 i = 0; i < nodes.size(); ++i)
204 {
205 if (*nodes[i] == data)
206 {
207 return nodes[i];
208 }
209 }
210
211 return 0;
212 }
213
214 /** Returns the first node with the given data.
215 * @return First node containing the given data or null if it isn't found.
216 */
217 Node * Find(const T &data)
218 {
219 for (s32 i = 0; i < nodes.size(); ++i)
220 {
221 if (*nodes[i] == data)
222 {
223 return nodes[i];
224 }
225 }
226
227 return 0;
228 }
229
230 /** Returns a logical iterator to the first element of the network.
231 * If the list is empty, this iterator is the same (in the sense of operator=) to that of End().
232 * @return Iterator at the first element or at one past the last element if the list is empty.
233 */
234 const Iterator & Begin() {begin.cur = nodes.begin(); return begin;}
235
236 /** Returns an iterator to one past the last element of the list.
237 * @return Iterator at one past the last element.
238 */
239 const Iterator & End() {end.cur = nodes.end(); return end;}
240
241 /* /\** Returns an iterator to the first element of the internal list. */
242 /* * @return Iterator at the first element. */
243 /* *\/ */
244 /* const std::vector<Node *>::iterator & GBegin() {return nodes.begin();} */
245
246 /* /\** Returns an iterator to one past the last element of the list. */
247 /* * @return Iterator at one past the last element. */
248 /* *\/ */
249 /* const std::vector<Node *>::iterator & GEnd() {return nodes.end();} */
250
251 /** Returns the list of nodes.
252 * @return List of nodes.
253 */
254 std::vector<Node *>& Nodes() {return nodes;}
255
256 /** Returns the number of nodes in the network.
257 * @return Number of nodes in the network.
258 */
259 int Size() {return nodes.size();}
260
261 /** Destroys the list, frees used resources.
262 */
263 ~JNeuralNetwork()
264 {
265 for (s32 i = 0; i < nodes.size(); ++i)
266 {
267 delete nodes[i];
268 }
269 }
270 };
271
272 #endif // _JNEURALNETWORK_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clase base de todos los objetos.
23 * @file JObject.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 15/11/2003
26 * @version 0.0.1 - 15/11/2003 - Primera versión
27 */
28
29 #include <JLib/Util/JObject.h>
30
31 #ifdef _JLIB_DEBUG
32 #include <SDL/SDL.h>
33 #include <stdio.h>
34
35 s32 JObject::instanceCount;
36 s32 JObject::instanceID;
37 std::vector<JObject *> JObject::objects;
38
39 JObject::JObject()
40 {
41 objects.push_back(this);
42 ++instanceCount;
43 instanceNum = ++instanceID;
44 fprintf(stderr, "#%d Created: 0x%x. JObjects: %d.\n", instanceNum, this, instanceCount);
45 }
46
47 JObject::~JObject()
48 {
49 --instanceCount;
50 fprintf(stderr,
51 "#%d Destroyed: 0x%x. Remaining JObjects: %d - %s",
52 instanceNum, this, instanceCount, instanceCount == 0 ? "NO LEAKS!" : "");
53
54 s32 first = 0, last;
55 first = (*objects.begin())->instanceNum;
56 last = first + 1;
57
58 for (std::vector<JObject *>::iterator it = objects.begin(); it != objects.end(); ++it)
59 {
60 if (*it == this)
61 {
62 fprintf(stderr, "*** %d *** ", (*it)->instanceNum);
63 objects.erase(it);
64 --it;
65 }
66 else
67 {
68 // Calculates ranges of instance numbers so the output is not too big
69 if (last == (*it)->instanceNum)
70 {
71 // Correlatives: only increments the range
72 ++last;
73 }
74 else
75 {
76 // Not correlatives, prints the range and jumps to the next
77 fprintf(stderr, "[%d-%d] ", first, last - 1);
78 first = (*it)->instanceNum;
79 last = first + 1;
80 }
81 }
82 }
83
84 if (first != last - 1)
85 fprintf(stderr, "[%d-%d] ", first, last - 1);
86
87 fprintf(stderr, "\n");
88 }
89
90 #endif // _JLIB_DEBUG
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clase base de todos los objetos.
23 * @file JObject.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 15/11/2003
26 * @version 0.0.1 - 15/11/2003 - Primera versión
27 */
28
29 #ifndef _JOBJECT_INCLUDED
30 #define _JOBJECT_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33
34 #ifdef WIN32
35 #include <windows.h>
36 #endif
37
38 #ifdef _JLIB_DEBUG
39 #include <vector>
40 #endif
41
42 /** Borra el puntero si no es nulo */
43 #define JDELETE(p) if (p){delete p;p = 0;}
44
45 /** Borra el array si no es nulo */
46 #define JDELETE_ARRAY(p) if(p){delete[] p;p = 0;}
47
48 /** Borra el array y cada uno de sus punteros si no son nulos ni él mismo es nulo */
49 #define JDELETE_POINTER_ARRAY(p, sz) if(p){for (s32 __i___ = 0; __i___ < sz; ++__i___) JDELETE((p)[__i___]); delete[] (p); (p) = 0;}
50
51 /** Borra el array y cada uno de sus arrays si no son nulos ni él mismo es nulo */
52 #define JDELETE_ARRAY_ARRAY(p, sz) if(p){for (s32 __i___ = 0; __i___ < sz; ++__i___) JDELETE_ARRAY((p)[__i___]); delete[] (p); (p) = 0;}
53
54 /** Clase base de todos los objetos.
55 */
56 class JObject
57 {
58 #ifdef _JLIB_DEBUG
59 protected:
60 static std::vector<JObject *> objects;
61 static s32 instanceCount;
62 static s32 instanceID;
63 s32 instanceNum;
64
65 public:
66 /** Crea un nuevo objeto.
67 */
68 JObject();
69
70 /** Destruye el objeto.
71 */
72 virtual ~JObject();
73
74 #else // NOT _JLIB_DEBUG
75
76 public:
77 /** Destruye el objeto.
78 */
79 virtual ~JObject(){}
80
81 #endif // _JLIB_DEBUG
82
83 };
84
85 #endif // _JOBJECT_INCLUDED
0 /** Wrapper de SDL_RWops
1 * @file JRW.cpp
2 * @author Juan Carlos Seijo Pérez
3 * @date 23/Mar/2005
4 * @version 0.0.1 - 23/Mar/2005 - Primera versión.
5 */
6
7 #include <JLib/Util/JRW.h>
8
9 u32 JRW::ZRead(void **buff)
10 {
11 u32 len, lenUncomp;
12
13 // Original & compressed size
14 if (!ReadLE32(&lenUncomp) ||
15 !ReadLE32(&len))
16 {
17 // perror("ZRead - Error 1");
18 return 0;
19 }
20
21 // printf("ZRead: lenUncomp %d, len %d\n", lenUncomp, len);
22
23 u8 *buffComp = new u8[len];
24
25 if (!buffComp)
26 {
27 // perror("ZRead - Error 2");
28 return 0;
29 }
30
31 u8 *buff_out = new u8[lenUncomp];
32
33 if (!buff_out)
34 {
35 // perror("ZRead - Error 3");
36 delete[] buffComp;
37 return 0;
38 }
39
40 if (0 >= SDL_RWread(rwops, buffComp, len, 1))
41 {
42 // perror("ZRead - Error 4");
43 delete[] buffComp;
44 delete[] buff_out;
45 return 0;
46 }
47
48 // For compatibility with zlib
49 unsigned long lenUL, lenUncompUL;
50 lenUncompUL = lenUncomp;
51 lenUL = len;
52
53 if (Z_OK != uncompress((Bytef*)buff_out, (uLongf*)&lenUncompUL, (Bytef*)buffComp, lenUL))
54 {
55 // perror("ZRead - Error 5");
56 delete[] buffComp;
57 delete[] buff_out;
58 return 0;
59 }
60
61 delete[] buffComp;
62 *buff = buff_out;
63
64 // perror("Todo ok");
65
66 return (u32)lenUncompUL;
67 }
68
69 u32 JRW::Import(const char *filename)
70 {
71 JRW f;
72
73 if (!f.Create(filename, "rb"))
74 {
75 return 0;
76 }
77
78 u32 size = f.Seek(0, SEEK_END);
79 f.Seek(0, SEEK_SET);
80
81 u8 *buff = new u8[size];
82
83 if (!buff)
84 {
85 return 0;
86 }
87
88 u32 ret;
89 ret = f.Read(buff, size, 1);
90
91 if (!ret)
92 {
93 delete[] buff;
94 return 0;
95 }
96
97 Create(buff, size);
98
99 return ret;
100 }
101
102 u32 JRW::ZWrite(const void *buff, u32 size, s32 level)
103 {
104 u32 sizeComp;
105 sizeComp = compressBound(size);
106
107 unsigned char *buffComp = new unsigned char[sizeComp + 8];
108
109 if (!buffComp)
110 {
111 return 0;
112 }
113
114 // For compatibility with zlib
115 unsigned long sizeCompUL, sizeUL;
116 sizeCompUL = sizeComp;
117 sizeUL = size;
118
119 if (Z_OK != compress2((Bytef*)buffComp, (uLongf*)&sizeComp, (Bytef*)buff, size, level))
120 {
121 delete[] buffComp;
122 return 0;
123 }
124
125 sizeComp = (u32)sizeCompUL;
126
127 // Tamaño original + Tamaño comprimido + datos comprimidos
128 if (0 == WriteLE32(&size) || 0 == WriteLE32(&sizeComp) ||
129 SDL_RWwrite(rwops, buffComp, sizeComp, 1) <= 0)
130 {
131 delete[] buffComp;
132 return 0;
133 }
134
135 delete[] buffComp;
136
137 return sizeComp;
138 }
139
140 u32 JRW::Export(const char *filename, u32 size)
141 {
142 JRW f;
143
144 if (!f.Create(filename, "wb"))
145 {
146 return 0;
147 }
148
149 u8 *buff = new u8[size];
150
151 if (!buff)
152 {
153 return 0;
154 }
155
156 u32 ret;
157 ret = Read(buff, size, 1);
158
159 if (!ret)
160 {
161 delete[] buff;
162 return 0;
163 }
164
165 ret = f.Write(buff, size, 1);
166 delete[] buff;
167
168 return ret;
169 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** SDL_RWops wrapper.
23 * @file JRW.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 23/Mar/2005
26 * @version 0.0.1 - 23/03/2005 - First version.
27 */
28
29 #ifndef _JRW_INCLUDED
30 #define _JRW_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Util/JObject.h>
34 #include <zlib.h>
35 #include <SDL.h>
36 #include <SDL_endian.h>
37
38 /** Encapsulates a SDL_RWops object. It's a simple wrapper.
39 */
40 class JRW : public JObject
41 {
42 public:
43 SDL_RWops *rwops; /**< Pointer to the SDL_RWops object. */
44
45 /** Creates an empty object. One of the Create methods must be called in order to use it.
46 */
47 JRW() : rwops(0)
48 {}
49
50 /** Creates (and destroys any existing) SDL_RWops structure to access a file.
51 * @param file Name of the file.
52 * @param mode Open mode (as fopen() of stdio.h)
53 * @return <b>true</b> if it succeeds, <b>false</b> if not.
54 */
55 bool Create(const char *file, const char *mode)
56 {
57 Destroy();
58
59 return (0 != (rwops = SDL_RWFromFile(file, mode)));
60 }
61
62 /** Creates (and destroys any existing) SDL_RWops structure to access a file.
63 * @param fp File pointer.
64 * @param autoclose Close flag when destroyed.
65 * @return <b>true</b> if it succeeds, <b>false</b> if not.
66 */
67 bool Create(FILE *fp, int autoclose = 0)
68 {
69 Destroy();
70
71 return (0 != (rwops = SDL_RWFromFP(fp, autoclose)));
72 }
73
74 /** Creates (and destroys any existing) SDL_RWops structure to access a memory block.
75 * @param mem Pointer to the memory block.
76 * @param size Size in bytes of the block.
77 * @return <b>true</b> if it succeeds, <b>false</b> if not.
78 */
79 bool Create(void *mem, int size)
80 {
81 Destroy();
82
83 return (0 != (rwops = SDL_RWFromMem(mem, size)));
84 }
85
86 /** Creates (and destroys any existing) SDL_RWops structure to access a memory block.
87 * @param mem Pointer to the memory block.
88 * @param size Size in bytes of the block.
89 * @return <b>true</b> if it succeeds, <b>false</b> if not.
90 */
91 bool Create(const void *mem, int size)
92 {
93 Destroy();
94
95 return (0 != (rwops = SDL_RWFromConstMem(mem, size)));
96 }
97
98 /** Destroys the object and frees the allocated resources.
99 */
100 void Destroy()
101 {
102 if (rwops)
103 {
104 SDL_RWclose(rwops);
105 rwops = 0;
106 }
107 }
108
109 /** Destroys the object.
110 */
111 virtual ~JRW()
112 {
113 Destroy();
114 }
115
116 /** Seeks to the given offset.
117 * @param offset Bytes to seek.
118 * @param whence Position from where to start counting (SEEK_SET, SEEK_CUR, SEEK_END)
119 * @return Reached offset (note that could be less than the requested one).
120 */
121 s32 Seek(s32 offset, s32 whence) {return SDL_RWseek(rwops, offset, whence);}
122
123 /** Reurns the given position.
124 * @return Position (offset) from the beginning of the object.
125 */
126 s32 Tell() {return SDL_RWtell(rwops);}
127
128 /** Reads data.
129 * @param ptr Read destination.
130 * @param size Number of bytes to read.
131 * @param maxnum Number of times to read size bytes (by default 1)
132 * @return Number of read objects or -1 if failed.
133 */
134 s32 Read(void *ptr, int size, int maxnum = 1) {return SDL_RWread(rwops, ptr, size, maxnum);}
135
136 /** Reads from the source to the given pointer, uncompressing the data. The first 4 bytes read are
137 * the uncompressed size. The next 4 bytes are the compressed size to read. Then comes the compressed data.
138 * @param buff Buffer to fill with the read data uncompressed.
139 * @return Uncompressed size of the data.
140 */
141 u32 ZRead(void **buff);
142
143 /** Reads a bool data. The bool is stored as a single byte.
144 * @param buff Variable with the result.
145 * @return Number of bytes read or 0 (zero) if an error occured.
146 */
147 u32 ReadBool(bool *buff) {u8 b; if (0 < SDL_RWread(rwops, &b, 1, 1)) {*buff = (b != 0) ? true:false; return 1;} return 0;}
148
149 /** Reads a bool data. The bool is stored as a single byte.
150 * @param buff Variable with the result.
151 * @return Number of bytes read or 0 (zero) if an error occured.
152 */
153 u32 Read8(u8 *buff) {if (0 < SDL_RWread(rwops, buff, 1, 1)) return 1; return 0;}
154
155 /** Reads a bool data. The bool is stored as a single byte.
156 * @param buff Variable with the result.
157 * @return Number of bytes read or 0 (zero) if an error occured.
158 */
159 u32 Read8(s8 *buff) {if (0 < SDL_RWread(rwops, buff, 1, 1)) return 1; return 0;}
160
161 /** Reads a 16-bit unsigned data in little-endian format.
162 * @param buff Variable with the result in the machine weight.
163 * @return Number of bytes read or 0 (zero) if an error occured.
164 */
165 u32 ReadLE16(u16 *buff) {if (0 < SDL_RWread(rwops, buff, 2, 1)) {*buff = SDL_SwapLE16(*buff); return 2;} return 0;}
166
167 /** Reads a 16-bit signed data in little-endian format.
168 * @param buff Variable with the result in the machine weight.
169 * @return Number of bytes read or 0 (zero) if an error occured.
170 */
171 u32 ReadLE16(s16 *buff) {if (0 < SDL_RWread(rwops, buff, 2, 1)) {*buff = SDL_SwapLE16(*buff); return 2;} return 0;}
172
173 /** Reads a 16-bit unsigned data in big-endian format.
174 * @param buff Variable with the result in the machine weight.
175 * @return Number of bytes read or 0 (zero) if an error occured.
176 */
177 u32 ReadBE16(u16 *buff) {if (0 < SDL_RWread(rwops, buff, 2, 1)) {*buff = SDL_SwapBE16(*buff); return 2;} return 0;}
178
179 /** Reads a 16-bit signed data in big-endian format.
180 * @param buff Variable with the result in the machine weight.
181 * @return Number of bytes read or 0 (zero) if an error occured.
182 */
183 u32 ReadBE16(s16 *buff) {if (0 < SDL_RWread(rwops, buff, 2, 1)) {*buff = SDL_SwapBE16(*buff); return 2;} return 0;}
184
185 /** Reads a 32-bit unsigned data in little-endian format.
186 * @param buff Variable with the result in the machine weight.
187 * @return Number of bytes read or 0 (zero) if an error occured.
188 */
189 u32 ReadLE32(u32 *buff) {if (0 < SDL_RWread(rwops, buff, 4, 1)) {*buff = SDL_SwapLE32(*buff); return 4;} return 0;}
190
191 /** Reads a 32-bit signed data in little- endian format.
192 * @param buff Variable with the result in the machine weight.
193 * @return Number of bytes read or 0 (zero) if an error occured.
194 */
195 u32 ReadLE32(s32 *buff) {if (0 < SDL_RWread(rwops, buff, 4, 1)) {*buff = SDL_SwapLE32(*buff); return 4;} return 0;}
196
197 /** Reads a 32-bit unsigned data in big-endian format.
198 * @param buff Variable with the result in the machine weight.
199 * @return Number of bytes read or 0 (zero) if an error occured.
200 */
201 u32 ReadBE32(u32 *buff) {if (0 < SDL_RWread(rwops, buff, 4, 1)) {*buff = SDL_SwapBE32(*buff); return 4;} return 0;}
202
203 /** Reads a 32-bit signed data in big-endian format.
204 * @param buff Variable with the result in the machine weight.
205 * @return Number of bytes read or 0 (zero) if an error occured.
206 */
207 u32 ReadBE32(s32 *buff) {if (0 < SDL_RWread(rwops, buff, 4, 1)) {*buff = SDL_SwapBE32(*buff); return 4;} return 0;}
208
209 /** Imports from a file.
210 * @param filename Name of the file to import.
211 * @return Number of bytes imported or 0 (zero) if an error occured.
212 */
213 u32 Import(const char *filename);
214
215 /** Writes data to the source.
216 * @param ptr Pointer to the data to be written.
217 * @param size Number of bytes to write.
218 * @param maxnum Number of times to write size bytes (1 by default)
219 * @return maxnum or -1 if failed.
220 */
221 s32 Write(const void *ptr, int size, int maxnum = 1) {return SDL_RWwrite(rwops, ptr, size, maxnum);}
222
223 /** Writes in the file, compressing the data. The format is:
224 * [size uncompressed][size compressed][compressed data].
225 * @param buff Pointer to the data to be written compressed.
226 * @param size Size in bytes of the data to write.
227 * @param level Compression level, from 1 (less compression) to 9 (best compression).
228 * @return Number of bytes written or 0 if an error occured.
229 */
230 u32 ZWrite(const void *buff, u32 size, s32 level);
231
232 /** Writes a bool data. The bool is stored as a single byte.
233 * @param buff Variable with the data.
234 * @return Number of bytes written or 0 (zero) if an error occured.
235 */
236 u32 WriteBool(bool *buff) {u8 b = (*buff)? 1 : 0; return SDL_RWwrite(rwops, &b, 1, 1);}
237
238 /** Writes a byte.
239 * @param buff Variable with the data.
240 * @return Number of bytes written or 0 (zero) if an error occured.
241 */
242 u32 Write8(u8 *buff) {return SDL_RWwrite(rwops, buff, 1, 1);}
243
244 /** Writes a byte.
245 * @param buff Variable with the data.
246 * @return Number of bytes written or 0 (zero) if an error occured.
247 */
248 u32 Write8(s8 *buff) {return SDL_RWwrite(rwops, buff, 1, 1);}
249
250 /** Writes a 16-bit unsigned data in little-endian format.
251 * @param buff Variable with the data in the machine weight.
252 * @return Number of bytes written or 0 (zero) if an error occured.
253 */
254 u32 WriteLE16(u16 *buff) {u16 v = SDL_SwapLE16(*buff); return SDL_RWwrite(rwops, &v, 2, 1);}
255
256 /** Writes a 16-bit signed data in little-endian format.
257 * @param buff Variable with the data in the machine weight.
258 * @return Number of bytes written or 0 (zero) if an error occured.
259 */
260 u32 WriteLE16(s16 *buff) {s16 v = SDL_SwapLE16(*buff); return SDL_RWwrite(rwops, &v, 2, 1);}
261
262 /** Writes a 16-bit unsigned data in big-endian format.
263 * @param buff Variable with the data in the machine weight.
264 * @return Number of bytes written or 0 (zero) if an error occured.
265 */
266 u32 WriteBE16(u16 *buff) {u16 v = SDL_SwapBE16(*buff); return SDL_RWwrite(rwops, &v, 2, 1);}
267
268 /** Writes a 16-bit signed data in big-endian format.
269 * @param buff Variable with the data in the machine weight.
270 * @return Number of bytes written or 0 (zero) if an error occured.
271 */
272 u32 WriteBE16(s16 *buff) {s16 v = SDL_SwapBE16(*buff); return SDL_RWwrite(rwops, &v, 2, 1);}
273
274 /** Writes a 32-bit unsigned data in little-endian format.
275 * @param buff Variable with the data in the machine weight.
276 * @return Number of bytes written or 0 (zero) if an error occured.
277 */
278 u32 WriteLE32(u32 *buff) {u32 v = SDL_SwapLE32(*buff); return SDL_RWwrite(rwops, &v, 4, 1);}
279
280 /** Writes a 32-bit signed data in little-endian format.
281 * @param buff Variable with the data in the machine weight.
282 * @return Number of bytes written or 0 (zero) if an error occured.
283 */
284 u32 WriteLE32(s32 *buff) {s32 v = SDL_SwapLE32(*buff); return SDL_RWwrite(rwops, &v, 4, 1);}
285
286 /** Writes a 32-bit unsigned data in big-endian format.
287 * @param buff Variable with the data in the machine weight.
288 * @return Number of bytes written or 0 (zero) if an error occured.
289 */
290 u32 WriteBE32(u32 *buff) {u32 v = SDL_SwapBE32(*buff); return SDL_RWwrite(rwops, &v, 4, 1);}
291
292 /** Writes a 32-bit signed data in big-endian format.
293 * @param buff Variable with the data in the machine weight.
294 * @return Number of bytes written or 0 (zero) if an error occured.
295 */
296 u32 WriteBE32(s32 *buff) {s32 v = SDL_SwapBE32(*buff); return SDL_RWwrite(rwops, &v, 4, 1);}
297
298 /** Export to file.
299 * @param filename Name of the file to export to.
300 * @param size Size of the data to export.
301 * @return Number of bytes written, 0 (zero) if an error occured.
302 */
303 u32 Export(const char *filename, u32 size);
304
305 /** Close the file. Only for a JRW created from a file.
306 */
307 s32 Close() {s32 ret = SDL_RWclose(rwops); rwops = 0; return ret;}
308 };
309
310 #endif // _JRW_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Stack template
23 * @file JStack.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 23/10/2005
26 * @version 0.0.1 - 23/10/2005 - First version.
27 */
28
29 #ifndef _JSTACK_INCLUDED
30 #define _JSTACK_INCLUDED
31
32 #include <JLib/Util/JObject.h>
33 #include <JLib/Util/JTypes.h>
34 #include <assert.h>
35
36 /** This class encapsulates a stack.
37 */
38 template<class T, unsigned int max = 64>
39 class JStack
40 {
41 protected:
42 int maxSize; /**< Current maximum size of the stack */
43 int size; /**< Number of elements in the stack */
44 int grow; /**< Grow amount of the stack */
45 T *elements; /**< Elements in the stack */
46
47 public:
48
49 /** Creates an empty stack.
50 * @param sz Initial capacity of the stack. If needed, the stack will grow its capacity
51 * to allow more elements to be added.
52 */
53 JStack(int sz = max) : maxSize(sz), size(0), grow(sz) {elements = new T[maxSize];}
54
55 /** Places an element at the top of the stack.
56 * @param element Element to push.
57 */
58 void Push(const T& element)
59 {
60 if (size == maxSize)
61 {
62 T *newElements = new T[maxSize*2];
63 for (int i = 0; i < size; ++i) newElements[i] = elements[i];
64 delete[] elements; elements = newElements; maxSize *= 2;
65 }
66 elements[size] = element; ++size;
67 }
68
69 /** Removes the element at the top of the stack. If Size() is MaxSize()/2, shrinks the stack memory.
70 */
71 void Pop()
72 {
73 if (size > 0)
74 {
75 --size;
76
77 if (size <= (maxSize/2) && (maxSize > (grow*2)))
78 {
79 T *newElements = new T[(maxSize/2) + grow];
80 for (int i = 0; i < size; ++i) newElements[i] = elements[i];
81 delete[] elements; elements = newElements; maxSize = (maxSize/2) + grow;
82 }
83 }
84 }
85
86 /** Returns the number of elements in the stack.
87 * @return Number of elements in the stack.
88 */
89 int Size() {return size;}
90
91 /** Checks if this stack is empty.
92 * @return <b>true</b> if it's empty, <b>false</b> otherwise.
93 */
94 bool Empty() {return size <= 0;}
95
96 /** Returns the current capacity of this stack (total number of elements that can be
97 * pushed before growing the stack is necessary).
98 * @return Current capacity of the stack.
99 */
100 int MaxSize() {return maxSize;}
101
102 /** Returns the element at the top of the stack.
103 * @return Element at the top of the stack.
104 */
105 T& Top() {assert(size > 0 || printf("JStack: size = 0 and Top() invoked!\n")); return elements[size - 1];}
106
107 /** Returns the element at the given position of the stack. WARNING: this method does not check bound so one
108 * must ensure the index is inside the range of the stack.
109 * @param i Index to retrieve.
110 * @return Element at the given index.
111 */
112 T& operator[](int i) {assert(i < size || printf("JStack: operator[%d], size = %d!\n", i, size)); return elements[i];}
113
114 /** Destroys the stack and frees allocated resources.
115 */
116 ~JStack() {JDELETE_ARRAY(elements); size = 0;}
117 };
118
119 #endif // _JSTACK_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Text string class.
23 * @file JString.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 19/04/2003
26 * @version 0.0.1 - 19/04/2003 - First version.
27 */
28
29 #ifndef _JSTRING_INCLUDED
30 #define _JSTRING_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <stdio.h>
34 #include <stdarg.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <JLib/Util/JLoadSave.h>
38
39 class JString : public JLoadSave
40 {
41 friend bool operator==(const char *s1, const JString& s2);
42 friend bool operator==(const JString& s1, const char *s2);
43 friend bool operator!=(const char *s1, const JString& s2);
44 friend bool operator!=(const JString& s1, const char *s2);
45 friend bool operator>(const char *s1, const JString& s2);
46 friend bool operator<(const char *s1, const JString& s2);
47 friend bool operator>=(const char *s1, const JString& s2);
48 friend bool operator<=(const char *s1, const JString& s2);
49 //friend const JString operator+(const char *s1, const JString &s2);
50 friend const JString operator+(const JString &s1, const char *s2);
51 friend const JString operator+(const JString &s1, const JString &s2);
52
53 protected:
54 char *data; // Caracteres
55 u32 length; // Longitud
56
57 public:
58
59 /** Creates an empty string.
60 */
61 inline JString();
62
63 /** Creates a string that is a copy of the given string.
64 * @param s String to be copied.
65 */
66 inline JString(const char *s);
67
68 /** Creates a string from a substring of the given string.
69 * @param s String.
70 * @param start Start of the substring.
71 * @param end Of the substring, -1 for the string length.
72 */
73 inline JString(const JString& s, u32 start, u32 end = (u32)-1);
74
75 /** Creates a string from a substring of the given string.
76 * @param s String.
77 * @param start Start of the substring.
78 * @param end Of the substring, -1 for the string length.
79 */
80 inline JString(const char *s, u32 start, u32 end = (u32)-1);
81
82 /** Creates a string that is a copy of the given string.
83 * @param s String to be copied.
84 */
85 inline JString(const JString& s);
86
87 /** Destroys this string and frees the allocated resources.
88 */
89 inline virtual ~JString();
90
91 /** Clears the string.
92 */
93 inline void Clear();
94
95 /** Compares this string to another one.
96 * @param s Another string.
97 * @return <b>true</b> if they are equal, <b>false</b> otherwise.
98 */
99 inline bool Equals(const JString& s) const;
100
101 /** Compares this string to another one.
102 * @param s Another string.
103 * @return <b>true</b> if they are equal, <b>false</b> otherwise.
104 */
105 inline bool operator==(const JString& s) const;
106
107 /** Compares this string to another one.
108 * @param s Another string.
109 * @return 0 i they are equal, >0 if this string is ASCII-greater than the given, <0 if its ASCII-lower.
110 */
111 inline s32 CompareTo(const JString& s) const;
112
113 /** Compares this string to another one.
114 * @param s Another string.
115 * @return 0 i they are equal, >0 if this string is ASCII-greater than the given, <0 if its ASCII-lower.
116 */
117 inline s32 CompareTo(const char *s) const;
118
119 /** Test if this string is ASCII-greater than another.
120 * @param s Another string.
121 * @return <b>true</b> if so, <b>false</b> otherwise.
122 */
123 inline bool operator>(const JString& s) const;
124
125 /** Test if this string is ASCII-lower than another.
126 * @param s Another string.
127 * @return <b>true</b> if so, <b>false</b> otherwise.
128 */
129 inline bool operator<(const JString& s) const;
130
131 /** Test if this string is ASCII-greater or equal than another.
132 * @param s Another string.
133 * @return <b>true</b> if so, <b>false</b> otherwise.
134 */
135 inline bool operator>=(const JString& s) const;
136
137 /** Test if this string is ASCII-lower or equal than another.
138 * @param s Another string.
139 * @return <b>true</b> if so, <b>false</b> otherwise.
140 */
141 inline bool operator<=(const JString& s) const;
142
143 /** Compares this string to another one.
144 * @param s Another string.
145 * @return <b>true</b> if they are different, <b>false</b> otherwise.
146 */
147 inline bool operator!=(const JString& s) const;
148
149 /** Returns the char at the given pos.
150 * @param pos Index of the character to be retrieved.
151 */
152 inline char& operator[](s32 pos);
153
154 /** Assigns a copy of the given string to this one.
155 * @param s Another string.
156 */
157 inline void operator=(const char *s);
158
159 /** Assigns a copy of the given string to this one.
160 * @param s Another string.
161 */
162 inline void operator=(const JString &s);
163
164 /** Returns the internal character array.
165 * @return internal character array.
166 */
167 inline const char* Str() const;
168
169
170 /** Appends the given string to this one.
171 * @param s Another string.
172 */
173 inline void Append(const JString& s);
174
175 /** Appends the given string to this one.
176 * @param s Another string.
177 */
178 inline void Append(const char * s);
179
180 /** Appends the given string to this one.
181 * @param s Another string.
182 */
183 inline void operator+=(const JString& s);
184
185 /** Appends the given string to this one.
186 * @param s Another string.
187 */
188 inline void operator+=(const char *s);
189
190 /** Appends the given char to this string.
191 * @param c Character to append.
192 */
193 inline void Append(char c);
194
195 /** Appends the given char to this string.
196 * @param c Character to append.
197 */
198 inline void operator+=(char c);
199
200 /** Creates a string from a format string (as printf uses).
201 * @param fmt Format string.
202 * @param ... Format parameters.
203 * @return <b>true</b> if it could be formatted, <b>false</b> otherwise.
204 */
205 inline bool Format(const char *fmt, ...);
206
207 /** Converts this string to uppercase.
208 */
209 inline void Uppercase();
210
211 /** Converts this string to lowercase.
212 */
213 inline void Lowercase();
214
215 /** Searchs for the given character from the given position within the string.
216 * @param c Character to be found.
217 * @param from Index within the string where to start the search (inclusive).
218 * @return index of the character searched or -1 if it wasn't found.
219 */
220 inline s32 Find(char c, u32 from = 0);
221
222 /** Searchs for the last index of the given character from the given position within the string.
223 * @param c Character to be found.
224 * @param from Index within the string where to start the search (inclusive).
225 * @return index of the character searched or -1 if it wasn't found.
226 */
227 inline s32 FindLast(char c, u32 from = 0);
228
229 /** Searchs for the index of the given string from the given position within this string.
230 * @param str String to be found.
231 * @param from Index within the string where to start the search (inclusive).
232 * @return index of the character searched or -1 if it wasn't found.
233 */
234 inline s32 Find(const char *str, u32 from = 0);
235
236 /** Searchs for the last index of the given string from the given position within this string.
237 * @param str String to be found.
238 * @param from Index within the string where to start the search (inclusive).
239 * @return index of the character searched or -1 if it wasn't found.
240 */
241 inline s32 FindLast(const char *str, u32 from = 0);
242
243 /** Replaces pat with rep from the given index, max number of times within this string.
244 * @param pat Character to look for.
245 * @param rep Character to replace pat with.
246 * @param from Start index within the string where to start the search (inclusive).
247 * @param max Maximum number of replacements to be made.
248 * @return Number of replacements doen.
249 */
250 inline s32 Replace(const char pat, const char rep, u32 from = 0, u32 max = 0);
251
252 /** Replaces pat with rep from the given index, max number of times within this string.
253 * @param pat String pattern to look for.
254 * @param rep String replacement to replace pat with.
255 * @param from Start index within the string where to start the search (inclusive).
256 * @param max Maximum number of replacements to be made.
257 * @return Number of replacements doen.
258 */
259 inline s32 Replace(const char *pat, const char *rep, u32 from = 0, u32 max = 0);
260
261 /** Returns a string that is a substring of this string.
262 * @param start Substring start position.
263 * @param end Substring end position.
264 * @return Substring.
265 */
266 inline const JString Substring(u32 start, u32 end = (u32)-1);
267
268
269 /** Cast to const char * type.
270 * @return const char * string.
271 */
272 inline operator const char *() const {return data;} // Cast a cadena
273
274
275 /** Returns the length of this string.
276 * @return Length of this string.
277 */
278 inline u32 Length() const {return length;} // Devuelve la longitud
279
280 // Lee la cadena de un fichero (longitud + cadena)
281
282 /** Reads a string from a JRW object (length in four bytes + characters)
283 * @param f JRW object.
284 * @return 0 if succeeded, 1 if I/O error, 2 if data integrity error.
285 */
286 inline u32 Load(JRW &f);
287
288 // Escribe la cadena a un fichero (longitud + cadena)
289
290 /** Writes a string to a JRW object (length in four bytes + characters)
291 * @param f JRW object.
292 * @return 0 if succeeded, 1 if I/O error, 2 if data integrity error.
293 */
294 inline u32 Save(JRW &f);
295 };
296
297 /** Test the equality of two strings.
298 * @param s1 First string.
299 * @param s1 Second string.
300 * @return <b>true</b> if they are equal, <b>false</b> otherwise.
301 */
302 inline bool operator==(const char *s1, const JString& s2)
303 {
304 return (strcmp(s1, s2.data) == 0);
305 }
306
307 /** Test the equality of two strings.
308 * @param s1 First string.
309 * @param s1 Second string.
310 * @return <b>true</b> if they are equal, <b>false</b> otherwise.
311 */
312 inline bool operator==(const JString& s1, const char *s2)
313 {
314 return (strcmp(s1.data, s2) == 0);
315 }
316
317 /** Test if the given strings are different.
318 * @param s1 First string.
319 * @param s1 Second string.
320 * @return <b>true</b> if so, <b>false</b> otherwise.
321 */
322 inline bool operator!=(const char *s1, const JString& s2)
323 {
324 return (strcmp(s1, s2.data) != 0);
325 }
326
327 /** Test if the given strings are different.
328 * @param s1 First string.
329 * @param s1 Second string.
330 * @return <b>true</b> if so, <b>false</b> otherwise.
331 */
332 inline bool operator!=(const JString& s1, const char *s2)
333 {
334 return (strcmp(s1.data, s2) != 0);
335 }
336
337 /** Test if the first string is ASCII-greater than the second.
338 * @param s1 First string.
339 * @param s1 Second string.
340 * @return <b>true</b> if so, <b>false</b> otherwise.
341 */
342 inline bool operator>(const char *s1, const JString& s2)
343 {
344 return (strcmp(s1, s2.data) > 0);
345 }
346
347 /** Test if the first string is ASCII-lower than the second.
348 * @param s1 First string.
349 * @param s1 Second string.
350 * @return <b>true</b> if so, <b>false</b> otherwise.
351 */
352 inline bool operator<(const char *s1, const JString& s2)
353 {
354 return (strcmp(s1, s2.data) < 0);
355 }
356
357 /** Test if the first string is ASCII-greater or equal than the second.
358 * @param s1 First string.
359 * @param s1 Second string.
360 * @return <b>true</b> if so, <b>false</b> otherwise.
361 */
362 inline bool operator>=(const char *s1, const JString& s2)
363 {
364 return (strcmp(s1, s2.data) >= 0);
365 }
366
367 /** Test if the first string is ASCII-lower or equal than the second.
368 * @param s1 First string.
369 * @param s1 Second string.
370 * @return <b>true</b> if so, <b>false</b> otherwise.
371 */
372 inline bool operator<=(const char *s1, const JString& s2)
373 {
374 return (strcmp(s1, s2.data) <= 0);
375 }
376
377 // Constructor
378 JString::JString() : length(0)
379 {
380 data = new char[1];
381 data [0] = '\0';
382 }
383
384 // Constructor
385 JString::JString(const char *s)
386 {
387 if (s)
388 {
389 length = (u32)strlen(s);
390 data = new char[length + 1];
391 strcpy(data, s);
392 }
393 else
394 {
395 data = new char[1];
396 data [0] = '\0';
397 length = 0;
398 }
399 }
400
401 // Constructor de subcadena
402 inline JString::JString(const JString& s, u32 start, u32 end)
403 {
404 if (end == (u32)-1)
405 end = s.Length();
406
407 if (start >= 0 && start < s.Length() && end > start && end <= s.Length())
408 {
409 length = end - start;
410 data = new char[length + 1];
411 strncpy(data, s.data + start, length);
412 data[length] = '\0';
413 }
414 else
415 {
416 data = new char[1];
417 data [0] = '\0';
418 length = 0;
419 }
420 }
421
422 // Constructor de subcadena
423 inline JString::JString(const char *s, u32 start, u32 end)
424 {
425 if (s)
426 {
427 u32 len = (u32)strlen(s);
428 if (end == (u32)-1)
429 end = len;
430
431 if (start >= 0 && start < len && end > start && end <= len)
432 {
433 length = end - start;
434 data = new char[length + 1];
435 strncpy(data, s + start, length);
436 data[length] = '\0';
437 }
438 else
439 {
440 data = new char[1];
441 data [0] = '\0';
442 length = 0;
443 }
444 }
445 else
446 {
447 data = new char[1];
448 data [0] = '\0';
449 length = 0;
450 }
451 }
452
453 // Constructor copia
454 JString::JString(const JString &s)
455 {
456 length = s.length;
457 data = new char[length + 1];
458 strcpy(data, s.data);
459 }
460
461 // Destructor
462 JString::~JString()
463 {
464 delete[] data;
465 }
466
467 // Borra la cadena
468 inline void JString::Clear()
469 {
470 delete[] data;
471 data = new char[1];
472
473 // La cadena no tiene estado 'nulo', como mucho estará vacía
474 data [0] = '\0';
475 length = 0;
476 }
477
478 // ¿Son iguales?
479 inline bool JString::Equals(const JString& s) const
480 {
481 return (strcmp(data, s.data) == 0);
482 }
483
484 // ¿Son iguales?
485 inline bool JString::operator==(const JString& s) const
486 {
487 return (strcmp(data, s.data) == 0);
488 }
489
490 // Comparación de cadenas
491 inline s32 JString::CompareTo(const JString &s) const
492 {
493 return (strcmp(data, s.data));
494 }
495
496 // Comparación de cadenas
497 inline s32 JString::CompareTo(const char *s) const
498 {
499 return (strcmp(data, s));
500 }
501
502 // ¿Es la primera mayor?
503 inline bool JString::operator>(const JString& s) const
504 {
505 return (strcmp(data, s.data) > 0);
506 }
507
508 // ¿Es la primera menor?
509 inline bool JString::operator<(const JString& s) const
510 {
511 return (strcmp(data, s.data) < 0);
512 }
513
514 // ¿Es la primera mayor o igual?
515 inline bool JString::operator>=(const JString& s) const
516 {
517 return (strcmp(data, s.data) >= 0);
518 }
519
520 // ¿Es la primera menor o igual?
521 inline bool JString::operator<=(const JString& s) const
522 {
523 return (strcmp(data, s.data) <= 0);
524 }
525
526 // ¿Son diferentes?
527 inline bool JString::operator!=(const JString& s) const
528 {
529 return (strcmp(data, s.data) != 0);
530 }
531
532 // Devuelve el caracter en la posición dada
533 inline char& JString::operator[](s32 pos)
534 {
535 return data[pos];
536 }
537
538 // Asignación
539 inline void JString::operator=(const char *s)
540 {
541 if (s)
542 {
543 u32 len;
544
545 len = (u32)strlen(s);
546 if (len > length)
547 {
548 delete[] data;
549 data = new char[len + 1];
550 }
551
552 length = len;
553 strcpy(data, s);
554 }
555 else
556 {
557 delete[] data;
558 data = new char[1];
559 data[0] = '\0';
560 length = 0;
561 }
562 }
563
564 // Asignación
565 inline void JString::operator=(const JString &s)
566 {
567 if (s.Length() > length)
568 {
569 delete[] data;
570 data = new char[s.length + 1];
571 }
572 length = s.length;
573 strcpy(data, s.data);
574 }
575
576 // Devuelve el array de caracteres
577 inline const char* JString::Str() const
578 {
579 return ((const char*)data);
580 }
581
582 // Concatenación de cadenas
583 inline void JString::Append(const JString& s)
584 {
585 if (s.length)
586 {
587 u32 len;
588 len = s.length;
589
590 char *strAux = new char[length + len + 1];
591 strAux[0] = 0;
592
593 strcpy(strAux, data);
594 delete[] data;
595
596 // Evita contar los caracteres en strcat(), ya que sabemos la longitud
597 strcpy(strAux + length, s.data);
598
599 data = strAux;
600 length += len;
601 }
602 }
603
604 // Concatenación de cadenas
605 inline void JString::Append(const char *s)
606 {
607 u32 len = (u32)strlen(s);
608
609 if (len)
610 {
611 char *strAux = new char[length + len + 1];
612 strAux[0] = 0;
613
614 strcpy(strAux, data);
615 delete[] data;
616
617 // Evita contar los caracteres en strcat(), ya que sabemos la longitud
618 strcpy(strAux + length, s);
619
620 data = strAux;
621 length += len;
622 }
623 }
624
625 // Concatenación de cadenas
626 inline void JString::operator+=(const JString& s)
627 {
628 if (s.length)
629 {
630 u32 len;
631 len = s.length;
632
633 char *strAux = new char[length + len + 1];
634 strAux[0] = 0;
635
636 strcpy(strAux, data);
637
638 // Evita contar los caracteres en strcat(), ya que sabemos la longitud
639 strcpy(strAux + length, s.data);
640
641 delete[] data;
642 data = strAux;
643 length += len;
644 }
645 }
646
647 // Concatenación de cadenas
648 inline void JString::operator+=(const char *s)
649 {
650 u32 len = (u32)strlen(s);
651
652 if (len)
653 {
654 char *strAux = new char[length + len + 1];
655 strAux[0] = 0;
656
657 strcpy(strAux, data);
658 delete[] data;
659
660 // Evita contar los caracteres en strcat(), ya que sabemos la longitud
661 strcpy(strAux + length, s);
662
663 data = strAux;
664 length += len;
665 }
666 }
667
668 // Concatena la cadena
669 inline const JString operator+(const JString &s1, const char *s2)
670 {
671 JString s(s1);
672 s.Append(s2);
673 return s;
674 }
675
676 inline const JString operator+(const JString &s1, const JString &s2)
677 {
678 JString s(s1);
679 s.Append(s2);
680 return s;
681 }
682
683 inline const JString operator+(const char *s1, const JString& s2)
684 {
685 JString s(s1);
686 s.Append(s2);
687 return s;
688 }
689
690 // Concatena un caracter
691 inline void JString::Append(char c)
692 {
693 if (c)
694 {
695 char *strAux = new char[length + 2];
696 strAux[0] = 0;
697
698 if (data)
699 {
700 strcpy(strAux, data);
701 delete[] data;
702 }
703
704 strAux[length] = c;
705 data = strAux;
706 length += 1;
707 strAux[length] = 0;
708 }
709 }
710
711 // Concatena un caracter
712 inline void JString::operator+=(char c)
713 {
714 if (c)
715 {
716 char *strAux = new char[length + 2];
717 strAux[0] = 0;
718
719 if (data)
720 {
721 strcpy(strAux, data);
722 delete[] data;
723 }
724
725 strAux[length] = c;
726 data = strAux;
727 length += 1;
728 strAux[length] = 0;
729 }
730 }
731
732 // Formatea la cadena tipo printf
733 inline bool JString::Format(const char *fmt, ...)
734 {
735 int n, size = 0;
736 char *p = 0;
737
738 va_list ap;
739
740 while (1)
741 {
742 // Intenta escribir hasta que la escritura tenga éxito
743 va_start(ap, fmt);
744 n = vsnprintf (p, size, fmt, ap);
745 va_end(ap);
746
747 // Si tiene éxito, sale del bucle para asignar la nueva cadena
748 if (n > -1 && n < size)
749 break;
750
751 // Si no, intenta determinar el espacio necesario
752 if (n > -1) // Esto ocurre con glibc >= 2.1
753 {
754 // Justo lo necesario
755 size = n+1;
756 }
757 else // Esto ocurre con glibc < 2.1
758 {
759 // Incrementa el tamaño
760 size += (64 + size);
761 }
762
763 if (p)
764 {
765 delete[] p;
766 }
767
768 if ((p = new char[size]) == 0)
769 {
770 // No hay memoria
771 return false;
772 }
773 }
774
775 delete[] data;
776 data = p;
777 length = size - 1;
778
779 return true;
780 }
781
782 // Convierte a mayúsculas
783 void JString::Uppercase()
784 {
785 char *p = data;
786 while (*p)
787 {
788 *p = toupper(*p);
789 ++p;
790 }
791 }
792
793 // Convierte a minúsculas
794 void JString::Lowercase()
795 {
796 char *p = data;
797 while (*p)
798 {
799 *p = tolower(*p);
800 ++p;
801 }
802 }
803
804 // Devuelve la posición del primer carácter c desde el comienzo de la cadena
805 s32 JString::Find(char c, u32 from)
806 {
807 if (from >= length)
808 {
809 return -1;
810 }
811
812 char *p;
813 if ((p = strchr(data + from, c)))
814 {
815 if (p > data)
816 return p - data;
817 else
818 return data - p;
819 }
820
821 return -1;
822 }
823
824 // Devuelve la posición del último carácter c desde el comienzo de la cadena
825 s32 JString::FindLast(char c, u32 from)
826 {
827 if (from >= length)
828 {
829 return -1;
830 }
831
832 char *p;
833 if ((p = strrchr(data + from, c)))
834 {
835 if (p > data)
836 return p - data;
837 else
838 return data - p;
839 }
840
841 return -1;
842 }
843
844 // Devuelve la posición de la cadena str desde el comienzo de la cadena
845 s32 JString::Find(const char *str, u32 from)
846 {
847 if (from >= length)
848 {
849 return -1;
850 }
851
852 char *p;
853 if ((p = strstr(data + from, str)))
854 {
855 if (p > data)
856 return p - data;
857 else
858 return data - p;
859 }
860
861 return -1;
862 }
863
864 // Reemplaza las ocurrencias 'pat' con 'rep' desde 'from', hasta 'max' veces
865 s32 JString::Replace(const char pat, const char rep, u32 from, u32 max)
866 {
867 s32 i, num = 0;
868
869 while ((i = Find(pat, from)) > -1)
870 {
871 data[i] = rep;
872 ++num;
873 }
874
875 return num;
876 }
877
878 // Reemplaza las ocurrencias 'pat' con 'rep' desde 'from', hasta 'max' veces
879 s32 JString::Replace(const char *pat, const char *rep, u32 from, u32 max)
880 {
881 s32 cur, patLen, repLen, num = 0;
882
883 patLen = strlen(pat);
884 repLen = strlen(rep);
885
886 if (patLen == repLen)
887 {
888 // Caso especial, esto se hace más rápido
889 while ((cur = Find(pat, from)) > -1)
890 {
891 strncpy(data + cur, rep, repLen);
892 ++num;
893 from = cur + patLen;
894 }
895
896 return num;
897 }
898
899 JString str(*this, 0, from);
900
901 while ((cur = Find(pat, from)) > -1)
902 {
903 str += Substring(from, cur);
904 str += rep;
905 ++num;
906 from = cur + patLen;
907 }
908
909 str += Substring(from);
910 *this = str;
911
912 return num;
913 }
914
915 // Devuelve una subcadena de esta cadena
916 inline const JString JString::Substring(u32 start, u32 end)
917 {
918 return JString(*this, start, end);
919 }
920
921 // Lee la cadena de un fichero (longitud + cadena)
922 inline u32 JString::Load(JRW &f)
923 {
924 f.ReadLE32(&length);
925 delete[] data;
926 data = new char[length + 1];
927 f.Read(data, length);
928 data[length] = 0;
929
930 return 0;
931 }
932
933 // Escribe la cadena a un fichero (longitud + cadena)
934 inline u32 JString::Save(JRW &f)
935 {
936 f.WriteLE32(&length);
937 f.Write(data, length);
938
939 return 0;
940 }
941
942 #endif // _JSTRING_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clase para manejo de ficheros de texto.
23 * @file JTextFile.cpp.
24 * @author Juan Carlos Seijo Pérez
25 * @date 15/06/2003
26 * @version 0.0.1 - 15/06/2003 - Primera versión.
27 */
28
29 #include <JLib/Util/JTextFile.h>
30
31 s8 JTextFile::line = '\n';
32
33 // Constructor
34 JTextFile::JTextFile(const s8 *_name) : JFile(_name), ptr(0)
35 {
36 }
37
38 // Destructor
39 JTextFile::~JTextFile()
40 {
41 JFile::Close();
42 }
43
44 // Develve el puntero a la posición actual
45 s8 * JTextFile::GetPos()
46 {
47 return ptr;
48 }
49
50 // Establece el puntero a la posición actual
51 bool JTextFile::SetPos(s8 *_ptr)
52 {
53 if (_ptr >= buff && _ptr < buff + buffSize)
54 {
55 ptr = _ptr;
56
57 return true;
58 }
59
60 return false;
61 }
62
63 // Lee el fichero como en la clase base pero asigna el puntero de desplazamiento.
64 u32 JTextFile::Read(u32 readSize)
65 {
66 u32 sz;
67 sz = JFile::Read(readSize);
68 ptr = buff;
69
70 return sz;
71 }
72
73 // Carga todo el fichero como en la clase base pero asigna el puntero de desplazamiento y
74 // añade un cero al final
75 bool JTextFile::Load(const char *filename, const char *mode)
76 {
77 if (!Open(filename, mode))
78 {
79 return false;
80 }
81
82 u32 ret;
83
84 FreeBuffer();
85 buff = new char[statInfo.st_size + 1];
86
87 if (!buff)
88 {
89 return false;
90 }
91
92 ret = fread(buff, sizeof(char), statInfo.st_size, file);
93
94 if (ret < 0)
95 {
96 return false;
97 }
98
99 ptr = buff;
100
101 buffSize = ret + 1;
102 buff[buffSize - 1] = '\0';
103
104 return true;
105 }
106
107 // Lee el próximo número decimal. Salta todos los caracteres que no sean números.
108 bool JTextFile::ReadFloat(float *f)
109 {
110 //while (isspace(*ptr)) ++ptr;
111
112 s8 str[16];
113 if (ReadWord(str))
114 {
115 *f = (float)atof(str);
116
117 return true;
118 }
119
120 return false;
121 }
122
123 // Lee el próximo número entero. Salta todos los caracteres que no sean números.
124 bool JTextFile::ReadInteger(s32 *i)
125 {
126 //while (isspace(*ptr)) ++ptr;
127
128 s8 str[16];
129 if (ReadWord(str))
130 {
131 *i = atoi(str);
132
133 return true;
134 }
135
136 return false;
137 }
138
139 // Avanza hasta el comienzo de la cadena dada. Comienza desde el principio si jump
140 // es true y se alcanza el final del fichero (hasta que se alcanza la posición de inicio).
141 bool JTextFile::FindNext(const s8 *str, bool jump)
142 {
143 s8 *tmp;
144
145 tmp = strstr(ptr, str);
146
147 if (tmp > 0)
148 ptr = tmp;
149 else
150 {
151 if (jump)
152 {
153 tmp = strstr(buff, str);
154
155 if (tmp > 0)
156 ptr = tmp;
157 else
158 return false;
159 }
160 else
161 return false;
162 }
163
164 return true;
165 }
166
167 u32 JTextFile::CountString(const s8 *str, s8* init, s8* end)
168 {
169 u32 count = 0;
170 s8 *pos = GetPos();
171
172 if (init == 0)
173 {
174 init = pos;
175 }
176
177 if (end == 0)
178 {
179 end = buff + buffSize - 1;
180 }
181
182 if (!SetPos(init) || !SetPos(end))
183 {
184 // Posición no válida
185 return 0;
186 }
187
188 SetPos(init);
189
190 while (FindNext(str) && ptr < end)
191 {
192 ++count;
193 ++ptr;
194 }
195
196 SetPos(pos);
197
198 return count;
199 }
200
201 // Lee y avanza el puntero
202 bool JTextFile::ReadWord(s8 *str)
203 {
204 s8 *ptrEnd = buff + buffSize + 1;
205 s32 i = 0;
206
207 while (isspace(*ptr) && ptr < ptrEnd) ++ptr;
208 while (!isspace(*ptr) && ptr < ptrEnd)
209 {
210 str[i++] = *ptr;
211 ++ptr;
212 }
213 str[i] = 0;
214
215 return i > 0;
216 }
217
218 bool JTextFile::ReadQuotedWord(s8 *str)
219 {
220 s8 *org = ptr, *end;
221 s32 i = 0;
222
223 while (isspace(*ptr)) ++ptr;
224
225 if (*ptr != '"')
226 {
227 // No hay comillas de inicio
228 ptr = org;
229 return false;
230 }
231
232 ++ptr;
233 end = ptr;
234
235 if (0 >= (end = strstr(ptr, "\"")))
236 {
237 // No hay comillas de cierre
238 ptr = org;
239 return false;
240 }
241
242 while (*ptr != '"')
243 {
244 str[i++] = *ptr;
245 ++ptr;
246 }
247 ++ptr;
248 str[i] = 0;
249
250 return true;
251 }
252
253 // Salta la siguiente palabra y avanza el puntero
254 bool JTextFile::SkipNextWord()
255 {
256 while (isspace(*ptr)) ++ptr;
257 while (!isspace(*ptr)) ++ptr;
258 while (isspace(*ptr)) ++ptr;
259
260 return true;
261 }
262
263 // Mueve el puntero al comienzo del documento
264 void JTextFile::StartOfDocument()
265 {
266 ptr = buff;
267 }
268
269 // Mueve el puntero al comienzo de la siguiente línea con texto.
270 bool JTextFile::NextLine()
271 {
272 s8 *ptrOrg = ptr, *ptrEnd = buff + buffSize - 1;
273
274 while (*ptr != line && ptr < ptrEnd)
275 {
276 ++ptr;
277 }
278
279 if (ptr == ptrEnd)
280 return false;
281
282 while (isspace(*ptr))
283 {
284 ++ptr;
285 }
286
287 return ptrOrg != ptr;
288 }
289
290 // Lee una línea del fichero desde la posición actual (sin contar espacios).
291 bool JTextFile::ReadLine(s8 *str)
292 {
293 s8 *orgPtr = ptr;
294
295 // Se salta los blancos
296 while (isspace(*ptr)) ++ptr;
297 s8 *tmp = ptr;
298
299 if (NextLine())
300 {
301 --ptr;
302
303 // Vuelve atrás el número de blancos saltados
304 while (isspace(*ptr)) --ptr;
305 ++ptr;
306
307 strncpy(str, tmp, ptr - tmp);
308 str[ptr - tmp] = '\0';
309
310 return true;
311 }
312
313 ptr = orgPtr;
314
315 return false;
316 }
317
318 // Escribe en el fichero sin salto de línea
319 u32 JTextFile::Print(const s8 *str)
320 {
321 if (!file)
322 return 0;
323
324 return(fputs(str, file));
325 }
326
327 // Escribe en el fichero con salto de línea
328 u32 JTextFile::PrintLine(const s8 *str)
329 {
330 if (!file)
331 return 0;
332
333 fputs(str, file);
334
335 return(fputc(line, file));
336 }
337
338 // Escribe en el fichero con formato y sin salto de línea
339 u32 JTextFile::Printf(const s8 *fmt, ... )
340 {
341 if (!file)
342 return 0;
343
344 va_list vlist;
345 s8 str[MAX_LINE_LENGTH];
346
347 va_start(vlist, fmt);
348 vsprintf(str, fmt, vlist);
349 va_end(vlist);
350
351 return(fputs(str, file));
352 }
353
354 // Lectura tipo scanf
355 s32 JTextFile::Scanf(const char *format, ...)
356 {
357 va_list vlist;
358 s32 ret;
359
360 u32 strSize = buffSize - (ptr - buff);
361 if (strSize == 0)
362 {
363 return 0;
364 }
365
366 char *str = new char[strSize + 1];
367 memcpy(str, ptr, strSize);
368 str[strSize] = '\0';
369
370 va_start(vlist, format);
371 ret = vsscanf(str, format, vlist);
372 va_end(vlist);
373
374 delete[] str;
375
376 return ret;
377 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Class to manipulate text files.
23 * @file JTextFile.h.
24 * @author Juan Carlos Seijo Pérez
25 * @date 15/06/2003
26 * @version 0.0.1 - 15/06/2003 - First version.
27 */
28
29 #ifndef _JTEXTFILE_INCLUDED
30 #define _JTEXTFILE_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Util/JFile.h>
34 #include <stdarg.h>
35 #include <ctype.h>
36 #include <stdlib.h>
37
38 /** Max line length.
39 */
40 #define MAX_LINE_LENGTH 1024
41
42 /** This class allows to manipulate text files. Contains methods to load, save, write formatted strings,
43 * and search words among others.
44 */
45 class JTextFile : public JFile
46 {
47 protected:
48 s8 *ptr; /**< Seek pointer */
49 static s8 line; /**< End of line character */
50
51 public:
52
53 /** Creates a new file with the given name.
54 * @param _name Name of the file.
55 */
56 JTextFile(const s8 *_name = 0);
57
58 /** Frees allocated resources and closes the file.
59 */
60 ~JTextFile();
61
62 /** Seeks to the first character of the next occurrence of the given string.
63 * @param str String to look for.
64 * @param jump Indicates whether it must jump to the beginning of the file if the end of the file is reached.
65 * @return <b>true</b> if the word was found, <b>false</b> if not.
66 */
67 bool FindNext(const s8 *str, bool jump = false);
68
69 /** Reads the file as in the base class but assigns the seek pointer also.
70 * @param readSize Size to read or zeor to read the whole file.
71 * @return Number of bytes read or 0 (zero) if an error occurred.
72 */
73 virtual u32 Read(u32 readSize = 0);
74
75 /** Loads the whole file as in the base class but assigns the seek pointer.
76 * @param filename Name of the file to load.
77 * @param mode Open mode as in fopen() (like {w|r|a}[+][{b|t}]).
78 * by default is "rb" (read, binary).
79 * @return <b>true</b> if succeeded, <b>false</b> otherwise.
80 */
81 virtual bool Load(const char *filename, const char *mode = "rb");
82
83 /** Advances the seek pointer to the next word.
84 * @return <b>true</b> if another word existed, <b>false</b> if not.
85 */
86 bool SkipNextWord();
87
88 /** Reads the next word and moves the pointer.
89 * @param str Buffer where to put the read word.
90 * @return <b>true</b> if another word existed, <b>false</b> if not.
91 */
92 bool ReadWord(s8 *str);
93
94 /** Reads the next double-quoted word and moves the pointer.
95 * @param str Buffer where to put the read double-quoted word.
96 * @return <b>true</b> if another word existed, <b>false</b> if not.
97 */
98 bool ReadQuotedWord(s8 *str);
99
100 /** Reads the next decimal number. Skips all characters that are not numbers (or the decimal dot or a sign).
101 * @param f Variable to store the result.
102 * @return <b>true</b> if there was a number, <b>false</b> if not.
103 */
104 bool ReadFloat(float *f);
105
106 /** Reads the next integer. Skips all characters that are not numbers (or signs).
107 * @param i Variable to store the result.
108 * @return <b>true</b> if there was a number, <b>false</b> if not.
109 */
110 bool ReadInteger(s32 *i);
111
112 /** Advances the pointer to the next line.
113 * @return <b>true</b> if there was next line, <b>false</b> if not.
114 */
115 bool NextLine();
116
117 /** Moves the pointer to the start of the document.
118 */
119 void StartOfDocument();
120
121 /** Reads the line under the actual position.
122 * @param str Variable to store the result.
123 * @return <b>true</b> if there was next line, <b>false</b> if not.
124 */
125 bool ReadLine(s8 *str);
126
127 /** Returns the pointer to the current position.
128 * @return Pointer to the current position.
129 */
130 s8 * GetPos();
131
132 /** Sets the current position.
133 * @param _ptr New current position.
134 * @return <b>true</b> if the position existed, <b>false</b> if not.
135 */
136 bool SetPos(s8 *_ptr);
137
138 /** Writes in the file without line-feed.
139 * @param str String to write.
140 * @return Number of characters written.
141 */
142 u32 Print(const s8 *str);
143
144 /** Writes in the file with line-feed.
145 * @param str String to write.
146 * @return Number of characters written.
147 */
148 u32 PrintLine(const s8 *str);
149
150 /** Writes in the file with format and without line-feed.
151 * @param fmt Format string, printf-like.
152 * @return Number of characters written.
153 */
154 u32 Printf(const s8 *fmt, ... );
155
156 /** Counts the number of occurrences of the given string among the file.
157 * @param str String to search.
158 * @param init Start position.
159 * @param end End position.
160 * @return Number of coincidences.
161 */
162 u32 CountString(const s8 *str, s8* init = 0, s8* end = 0);
163
164 /** Reads like scanf.
165 * @param format Format string.
166 * @param format Format parameters.
167 * @return Number of parameters read successfuly.
168 */
169 s32 Scanf(const char *format, ...);
170 };
171
172 #endif // _JTEXTFILE_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 24/05/2003
25 // @description: Funciones de manejo de texto de windows
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #include <JLib/Util/JTextUtil.h>
29
30 // Crea una superficie en formato RGBA de 32 bits con un mapa de caracteres en
31 // 16 filas y 16 columnas para el formato de fuente especificado.
32 // NOTA: Es responsabilidad del llamador liberar la memoria del buffer devuelto
33 // por esta función.
34 //u32* GetFontSurface(JFontFormat format)
35 //{
36 // HDC hDCSurf, hDCScr;
37 // hDCScr = GetDC(0);
38 // hDCSurf = CreateCompatibleDC(hDCScr);
39 //
40 // // Crea la fuente a partir de las de windows
41 // HFONT font = CreateFont(-format.fontSize,
42 // 0,
43 // 0,
44 // 0,
45 // format.fontWeight,
46 // format.cursive,
47 // format.underscore,
48 // 0,
49 // ANSI_CHARSET,
50 // OUT_DEFAULT_PRECIS,
51 // CLIP_DEFAULT_PRECIS,
52 // ANTIALIASED_QUALITY,
53 // DEFAULT_PITCH | FF_SWISS,
54 // format.fontName);
55 //
56 // // Dibuja el texto en memoria
57 // HBITMAP hBMP, hBMPOld;
58 // BITMAPINFO bi;
59 //
60 // RECT rc;
61 // s8 str[272]; // 255 caracteres + 15 saltos de línea \n\r + 1 '/0'
62 // for (s32 i = 0, cnt = 0; i < 271; ++i)
63 // {
64 // if (i > 0 && i < 271 && i % 16 == 0)
65 // {
66 // // cr + lf
67 // str[i] = '\n';
68 // str[++i] = '\r';
69 // ++i;
70 // }
71 //
72 // str[i] = cnt++;
73 // }
74 //
75 // str[271] = 0;
76 //
77 //
78 // // Calcula el tamaño del rectángulo con la fuente escogida
79 // SIZE sz;
80 // HFONT oldFont = (HFONT)SelectObject(hDCSurf, font);
81 // GetTextExtentPoint32(hDCScr, str, (s32)strlen(str), &sz);
82 // rc.top = 0;
83 // rc.left = 0;
84 // rc.right = sz.cx;
85 // rc.bottom = sz.cy;
86 //
87 // // Pinta sobre la superficie en memoria
88 // bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
89 // bi.bmiHeader.biBitCount = 32;
90 // bi.bmiHeader.biCompression = BI_RGB;
91 // bi.bmiHeader.biPlanes = 1;
92 // bi.bmiHeader.biWidth = rc.right;
93 // bi.bmiHeader.biHeight = rc.bottom;
94 // bi.bmiHeader.biSizeImage = 0;
95 //
96 // void *bits, *surf;
97 // hBMP = CreateDIBSection(hDCSurf, &bi, DIB_RGB_COLORS, &bits, 0, 0x0);
98 // hBMPOld = (HBITMAP)SelectObject(hDCSurf, hBMP);
99 //
100 // // Establece el color de fuente
101 // SetBkColor(hDCSurf, RGB(0, 0, 0));
102 // SetTextColor(hDCSurf, RGB(format.b, format.g, format.r));
103 // TextOut(hDCSurf, 0, 0, str, (s32)strlen(str));
104 //
105 // // Optimizar para MMX
106 // surf = (void *)new u32[rc.right * rc.bottom];
107 // CopyMemory(surf, bits, rc.right * rc.bottom * 4);
108 //
109 // // Asigna valores alfa para la superficie en función de la
110 // // proximidad de los pixels al texto
111 // u32 val;
112 // u32 color = RGB(format.b, format.g, format.r);
113 // u8 alpha;
114 //
115 // for (u32 i = 0; i < (u32)bi.bmiHeader.biWidth * bi.bmiHeader.biHeight; ++i)
116 // {
117 // val = *(((u32 *)surf) + i);
118 //
119 // if (val > 0)
120 // val = val;
121 //
122 // // Asignamos un valor al canal alfa inversamente proporcional al valor del color
123 // alpha = (u8)(255 * ((double)val/(double)color));
124 //
125 // if (alpha > 0)
126 // alpha = alpha;
127 //
128 // *(((u32*)surf) + i) |= ((u32)alpha) << 24;
129 // }
130 //
131 // SelectObject(hDCSurf, hBMPOld);
132 // SelectObject(hDCSurf, oldFont);
133 // DeleteDC(hDCSurf);
134 // ReleaseDC(0, hDCScr);
135 //
136 // return (u32 *)surf;
137 //}
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // @author: Juan Carlos Seijo Pérez
24 // @date: 24/05/2003
25 // @description: Funciones de manejo de texto de windows
26 ///////////////////////////////////////////////////////////////////////////////
27
28 #ifndef _JTEXTUTIL_INCLUDED
29 #define _JTEXTUTIL_INCLUDED
30
31 #include <JLib/Util/JTypes.h>
32 #include <SDL.h>
33 //#include <JLib/Graphics/JText.h>
34
35 // Crea una superficie en formato RGBA de 32 bits con los caracteres en
36 // 16 filas y 16 columnas para el formato de fuente especificado.
37 // NOTA: Es responsabilidad del llamador liberar la memoria del buffer devuelto
38 // por esta función.
39 //u32* GetFontSurface(JFontFormat format);
40
41 #endif // _JTEXTUTIL_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Clase base para threads.
23 * @file JThread.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 18/04/2004
26 * @version 0.0.1 - 18/04/2004 - Primera versión.
27 */
28
29 #include <JLib/Util/JThread.h>
30
31 JThread::JThread(int (* func)(void *), void *data)
32 : valid(false), paused(false), terminate(false), thread(0), id(0)
33 {
34 if (func)
35 {
36 s32 ret;
37 if (0 == (ret = SDL_WasInit(SDL_INIT_EVENTTHREAD)))
38 {
39 ret = SDL_Init(SDL_INIT_EVENTTHREAD);
40 }
41
42 if (ret == 0)
43 {
44 // Si no se dan datos asociados, se pasará este objeto a la función
45 if (data == 0)
46 {
47 data = this;
48 }
49
50 thread = SDL_CreateThread(func, data);
51 id = SDL_GetThreadID(thread);
52
53 fprintf(stderr, "Nuevo thread: 0x%x", id);
54 }
55 else
56 {
57 fprintf(stderr, "No se pudo iniciar el sistema de threads.");
58 }
59 }
60 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Base class for threads.
23 * @file JThread.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 18/04/2004
26 * @version 0.0.1 - 18/04/2004 - First version.
27 */
28
29 #ifndef _JTHREAD_INCLUDED
30 #define _JTHREAD_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <SDL.h>
34 #include <SDL_thread.h>
35
36 /** Base class for threads.
37 */
38 class JThread
39 {
40 protected:
41 bool valid; /**< Validity flag for this thread */
42 bool paused; /**< Pause flag of this thread */
43 bool terminate; /**< Termination flag of this thread */
44 SDL_Thread *thread; /**< SDL thread id for this thread */
45 u32 id; /**< Thread id */
46
47 public:
48 /** Creates a new thread that will execute the given function.
49 * A method can be implemented in a child class and the be passed as the execution function
50 * if it is defined as 'static int Func(void *data)' or any other name instead of Func
51 * and using the constructor as JThread(&Func, data).
52 * A sample of the way Func could be implemented is:
53 * <pre>
54 * while (!terminate)
55 * {
56 * while (paused)
57 * sleep(0);
58 *
59 * // Code to execute
60 * }
61 * </pre>
62 * @param func Function to execute. If zero, the thread is not launched.
63 * @param data Additional data to pass to the function.
64 */
65 JThread(int (* func)(void *), void *data = 0);
66
67 /** Returns the thread id for this thread.
68 * @return Thread id of this thread.
69 */
70 u32 GetId() {return id;}
71
72 /** Checks if this thread must terminate.
73 * @return <b>true</b> if so, <b>false</b> if not.
74 */
75 bool MustTerminate() {return terminate;}
76
77 /** Signals this thread to end. This does not guarantee that it ends,
78 * because it depends on the implementation to use MustTerminate()
79 * as end condition.
80 */
81 void Terminate() {terminate = true; paused = false; valid = false; SDL_WaitThread(thread, 0);}
82
83 /** Checks if this thread is paused.
84 * @return <b>true</b> if so, <b>false</b> if not.
85 */
86 bool Paused() {return paused;}
87
88 /** Pauses this thread.
89 */
90 void Pause() {paused = true;}
91
92 /** Resumes this thread.
93 */
94 void Continue() {paused = false;}
95
96 /** Kills this thread. This aproximation must be avoided, is better to implement
97 * an exit mechanism in the child class as:
98 * <pre>
99 * while (!terminate)
100 * {
101 * while (paused)
102 * sleep(0);
103 *
104 * // Code to execute
105 * }
106 * </pre>
107 */
108 void Kill() {SDL_KillThread(thread);}
109
110 /** Determines if this thread is valid..
111 * @return <b>true</b> if so, <b>false</b> if not.
112 */
113 bool Valid() {return valid;}
114 };
115
116 #endif // _JTHREAD_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Timer.
23 * @file JTimer.cpp.
24 * @author Juan Carlos Seijo Pérez.
25 * @date 21/04/2003.
26 * @version 0.0.1 - 21/04/2003 - Primera versión.
27 */
28
29 #include <JLib/Util/JTimer.h>
30
31 // Construye e inicializa un nuevo timer de baja resolución
32 JTimer::JTimer(u32 millis) : pause(0), last(0), cur(0), lastQueryCycle(0)
33 {
34 if (millis == 0L)
35 millis = 1L;
36
37 cycleTime = millis;
38 start = SDL_GetTicks();
39 }
40
41 // Comenzar
42 void JTimer::Start(u32 millis)
43 {
44 if (millis != 0L)
45 cycleTime = millis;
46
47 start = SDL_GetTicks();
48 last = 0;
49 cur = 0;
50 lastQueryCycle = 0;
51 pause = 0;
52 }
53
54 // Pausar
55 void JTimer::Pause()
56 {
57 if (!pause)
58 {
59 pause = SDL_GetTicks();
60 cur = pause; // Para la consulta durante la pausa
61 }
62 }
63
64 // Continuar tras pausa
65 void JTimer::Continue()
66 {
67 if (pause)
68 {
69 start += SDL_GetTicks() - pause;
70 pause = 0;
71 }
72 }
73
74 // Consulta el número de ms ocurridos desde el comienzo del último ciclo
75 u32 JTimer::Lap()
76 {
77 if (!pause)
78 cur = SDL_GetTicks();
79
80 return(cur - start);
81 }
82
83 // Consulta el número de ms que faltan para terminar el ciclo actual
84 u32 JTimer::Rem()
85 {
86 return(SDL_GetTicks() - start)%cycleTime;
87 }
88
89 // Consulta el tiempo transcurrido entre llamadas a Tick()
90 u32 JTimer::Tick()
91 {
92 u32 ret = last;
93
94 if (!pause)
95 cur = SDL_GetTicks();
96
97 ret = cur - last;
98 last = cur;
99
100 return ret;
101 }
102
103 // Consulta el número de ciclos desde el comienzo
104 u32 JTimer::Cycles()
105 {
106 if (!pause)
107 cur = SDL_GetTicks();
108
109 return ((cur - start) / cycleTime);
110 }
111
112 // Consulta si hemos pasado a otro ciclo desde la última consulta
113 // y devuelve el número de ciclos transcurridos
114 u32 JTimer::Changed()
115 {
116 if (!pause)
117 cur = SDL_GetTicks();
118
119 u32 ret;
120 ret = ((cur - start) / cycleTime) - lastQueryCycle; // Ciclo actual - último consultado
121 lastQueryCycle += ret;
122
123 return (ret);
124 }
125
126 // Consulta el número de ms ocurridos desde el comienzo
127 u32 JTimer::TotalLap()
128 {
129 if (!pause)
130 cur = SDL_GetTicks();
131
132 return (cur - start);
133 }
134
135 // Espera a que se complete el ciclo
136 void JTimer::WaitCycle()
137 {
138 u32 val;
139
140 if (!pause)
141 {
142 do
143 {
144 cur = SDL_GetTicks();
145 val = (cur - start) / cycleTime;
146 }
147 while (!(val - lastQueryCycle));
148
149 lastQueryCycle = val;
150 }
151 }
152
153 /** Devuelve el nº de segundos de la época (00:00h del 01/01/1970). */
154 time_t JTimer::CurS()
155 {
156 return time(0);
157 }
158
159 /** Devuelve el nº de milisegundos del segundo actual. */
160 u16 JTimer::CurMs()
161 {
162 #ifdef WIN32
163 timeb t;
164 ftime(&t);
165 return t.millitm;
166 #else
167 timeval tv;
168 gettimeofday(&tv, 0);
169 return tv.tv_usec/1000;
170 #endif // WIN32
171 }
172
173 /** Devuelve el timestamp como cadena de texto. */
174 const s8 * JTimer::StrTime()
175 {
176 time_t t;
177 time(&t);
178 return (ctime(&t));
179 }
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Timer.
23 * @file JTimer.h.
24 * @author Juan Carlos Seijo Pérez.
25 * @date 21/04/2003.
26 * @version 0.0.1 - 21/04/2003 - First version.
27 */
28
29 #ifndef _JTIMER_INCLUDED
30 #define _JTIMER_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Util/JObject.h>
34 #include <SDL.h>
35 #include <time.h>
36
37 #ifdef WIN32
38 #include <sys/timeb.h>
39 #else
40 #include <sys/time.h>
41 #include <unistd.h>
42 #endif // WIN32
43
44 /** Generic timer. Includes functions to count fixed periods of milliseconds (ms), time between calls, etc.
45 */
46 class JTimer
47 {
48 protected:
49 u32 start; /**< First measure (cycle 0) */
50 u32 pause; /**< Pause measure (millis) */
51 u32 last; /**< Last measure (millis) */
52
53 u32 cycleTime; /**< Cycle period (millis) */
54
55 u32 cur; /**< Current measure (millis) */
56
57 u32 lastQueryCycle; /**< Cycle of the last query */
58
59 public:
60 /** Creates and initializes the timer.
61 * @param millis Milliseconds per cycle.
62 */
63 JTimer(u32 millis = 1L);
64
65 /** Starts the timer.
66 * @param millis Milliseconds per cycle (0 to use the value given at creation time, by default is zero).
67 */
68 void Start(u32 millis = 0L);
69
70 /** Pauses this timer.
71 */
72 void Pause();
73
74 /** Resumes this timer.
75 */
76 void Continue();
77
78 /** Queries the number of ms since the start of the last cycle.
79 * @return Number of ms since the start of the last cycle.
80 */
81 u32 Lap();
82
83 /** Queries the number of ms to end the current cycle.
84 * @return Number of ms to end the current cycle.
85 */
86 u32 Rem();
87
88 /** Queries the time in ms between calls to Tick().
89 * @return Time in ms between calls to Tick().
90 */
91 u32 Tick();
92
93 /** Queries the number of cycles since Start().
94 * @return Number of cycles since Start().
95 */
96 u32 Cycles();
97
98 /** Queries if the cycle has changed since the last call to Lap(), Rem() or Start()..
99 * @return 0 if not, different if so.
100 */
101 u32 Changed();
102
103 /** Queries the number of ms since Start() was called.
104 * @return Number of ms since Start() was called.
105 */
106 u32 TotalLap();
107
108 /** Waits for the cycle to complete.
109 */
110 void WaitCycle();
111
112 /** Returns the number of seconds since the epoch (00:00h, 01/01/1970).
113 * @return Number of seconds since the epoch (00:00h, 01/01/1970).
114 */
115 static time_t CurS();
116
117 /** Returns the number of milliseconds since the current second started.
118 * @return Number of milliseconds since the current second started.
119 */
120 static u16 CurMs();
121
122 /** Returns the timestamp as a string.
123 * @return Timestamp as a string.
124 */
125 static const s8 * StrTime();
126
127 /** Returns the cycle period in ms.
128 * @return Cycle period in ms.
129 */
130 u32 CycleTime() {return cycleTime;}
131 };
132
133 #endif // _JTIMER_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Simple recursive tree.
23 * <pre>
24 * The tree is organized as:
25 *
26 *(parent of cur and root of the whole tree)
27 * | (cur, iterator here)
28 * | |
29 * v v
30 * O===O===O <-- (child)
31 * |
32 * O <-- (next)
33 * |
34 * O===O
35 * | |
36 * O O
37 * |
38 * O===O===O
39 * ^
40 * |
41 * (branch)
42 * </pre>
43 *
44 * @file JTree.h.
45 * @author Juan Carlos Seijo Pérez
46 * @date 26/10/2003
47 * @version 0.0.1 - 26/10/2003 - First version.
48 */
49
50 #ifndef _JTREE_INCLUDED
51 #define _JTREE_INCLUDED
52
53 #include <JLib/Util/JTypes.h>
54 #include <JLib/Util/JObject.h>
55 #include <list>
56
57 /** Simple recursive tree. The type must have a default constructor.
58 */
59 template <typename T>
60 class JTree : public JObject
61 {
62 public:
63 /** Tree node.
64 */
65 class Node
66 {
67 public:
68 T data; /**< Node data */
69 Node *prev; /**< Previous node */
70 Node *next; /**< Next node */
71 Node *child; /**< Child node */
72 Node *parent; /**< Parent node */
73 u32 depth; /**< This node's depth */
74
75 /** Creates a new node. The type T requires a default constructor.
76 */
77 Node() : prev(0), next(0), child(0), parent(0)
78 {
79 if (parent)
80 depth = parent->depth + 1;
81 else
82 depth = 0;
83 }
84
85 /** Creates a new node.
86 * @param _data Node data.
87 * @param _prev Previous node.
88 * @param _next Next node.
89 * @param _parent Parent node.
90 */
91 Node(T _data, Node *_prev = 0, Node *_next = 0, Node *_parent = 0, Node *_gPrev = 0, Node *_gNext = 0)
92 : data(_data), prev(_prev), next(_next), child(0), parent(_parent)
93 {
94 if (parent)
95 depth = parent->depth + 1;
96 else
97 depth = 0;
98 }
99 };
100
101 Node* root; /**< Root node. Its the parent of the first node */
102 Node* end; /**< Is the next of the last of each branch */
103 std::list<Node *> nodes; /**< All the nodes as a list. */
104 typename std::list<Node *>::iterator itG; /**< Global node iterator. */
105
106 /** Creates an empty tree.
107 */
108 JTree<T>()
109 {
110 root = new Node;
111 root->parent = root;
112 nodes.push_back(root);
113 }
114
115 /** Destroys the tree. Deletes created nodes (BUT NOT its contents if they are pointers)
116 */
117 ~JTree<T>()
118 {
119 nodes.clear();
120 }
121
122 /** Tree iterator.
123 */
124 class Iterator
125 {
126 public:
127 JTree *tree; /**< Tree this iterator belongs to. */
128 Node *node; /**< Actual node. */
129
130 /** Creates an iterator from a tree.
131 */
132 Iterator(JTree &t)
133 {
134 tree = &t;
135 node = *(tree->nodes.begin());
136 if (node->child)
137 {
138 // Skips root to be at the first element
139 node = node->child;
140 }
141 }
142
143 /** Creates an iterator froam a tree and a node belonging to it.
144 * @param t Tree.
145 * @param n Node of the tree.
146 */
147 Iterator(JTree &t, Node *n)
148 {
149 tree = &t;
150 node = n ? n : *(tree->nodes.begin());
151 }
152
153 /** Assigns the data of the current node.
154 * @param data New data.
155 */
156 void Data(T data)
157 {
158 node->data = data;
159 }
160
161 /** Returns the data of the current node.
162 * @return Current node data.
163 */
164 T& Data()
165 {
166 return node->data;
167 }
168
169 /** Goes to the next node.
170 * @return <b>true</b> if it exists, <b>false</b> if not.
171 */
172 bool Next()
173 {
174 if (node->next)
175 {
176 node = node->next;
177 return true;
178 }
179
180 return false;
181 }
182
183 /** Goes to the previous node.
184 * @return <b>true</b> if it exists, <b>false</b> if not.
185 */
186 bool Prev()
187 {
188 if (node->prev)
189 {
190 node = node->prev;
191 return true;
192 }
193
194 return false;
195 }
196
197 /** Goes to the parent node.
198 * @return <b>true</b> if it exists, <b>false</b> if not.
199 */
200 bool Parent()
201 {
202 if (node->parent != tree->root)
203 {
204 node = node->parent;
205 return true;
206 }
207
208 return false;
209 }
210
211 /** Goes to the child node.
212 * @return <b>true</b> if it exists, <b>false</b> if not.
213 */
214 bool Child()
215 {
216 if (node->child)
217 {
218 node = node->child;
219 return true;
220 }
221
222 return false;
223 }
224
225 /** Adds a node.
226 * @param nodeData Data for the new node.
227 * @param after <b>true</b> to put it after the current node,
228 * <b>false</b> to put it before.
229 */
230 void AddNode(T nodeData, bool after = true)
231 {
232 if (after)
233 {
234 node->next = new Node(nodeData, node, node->next, node->parent);
235 tree->nodes.push_back(node->next);
236 }
237 else
238 {
239 node->prev = new Node(nodeData, node->prev, node, node->parent);
240 tree->nodes.push_back(node->prev);
241 }
242 }
243
244 /** Adds a node and places the iterator there.
245 * @param nodeData Node data.
246 * @param after <b>true</b> to put it after the current node,
247 * <b>false</b> to put it before.
248 */
249 void AddNodeGo(T nodeData, bool after = true)
250 {
251 if (after)
252 {
253 node->next = new Node(nodeData, node, node->next, node->parent);
254 node = node->next;
255 }
256 else
257 {
258 node->prev = new Node(nodeData, node->prev, node, node->parent);
259 node = node->prev;
260 }
261
262 tree->nodes.push_back(node);
263 }
264
265 /** Adds a child node if it didn't exist yet.
266 * @param nodeData Data of the child node.
267 */
268 void AddBranch(T nodeData)
269 {
270 if (!node->child)
271 {
272 node->child = new Node(nodeData, 0, 0, node);
273 tree->nodes.push_back(node->child);
274 }
275 }
276
277 /** Adds a child node if it didn't exist yet and places the iterator there.
278 * @param nodeData Data of the child node.
279 */
280 void AddBranchGo(T nodeData)
281 {
282 if (!node->child)
283 {
284 node->child = new Node(nodeData, 0, 0, node);
285 node = node->child;
286 tree->nodes.push_back(node);
287 }
288 }
289
290 /** Removes a node and its childs. The iterator after this operation is placed
291 * in th eprevious node or in th eparent node if it doesn't exist.
292 */
293 void RemoveNode()
294 {
295 if (node != tree->root)
296 {
297 // Places the iterator in the previous node or int the parent node
298 Node *n = (node->prev) ? node->prev : node->parent;
299
300 if (node->next)
301 node->next->prev = node->prev;
302
303 if (node->prev)
304 node->prev->next = node->next;
305
306 // Tell the father this node was unique
307 if (!node->next && !node->prev && node->parent)
308 node->parent->child = 0;
309
310 tree->nodes.remove(node);
311 JDELETE(node);
312
313 node = n;
314 }
315 }
316
317 /** Goes to the first node in branch.
318 */
319 void FirstInBranch()
320 {
321 while (Prev());
322 }
323
324 /** Goes to the last node in branch.
325 * @see Root()
326 */
327 void LastInBranch()
328 {
329 while (Next());
330 }
331
332 /** Goes to the first node in the tree.
333 */
334 void FirstInTree()
335 {
336 while (Parent())
337 {}
338
339 FirstInBranch();
340 }
341
342 /** Goes to the first node in the tree.
343 * @see FirstInTree()
344 */
345 void Root()
346 {
347 FirstInTree();
348 }
349
350 /** Checks if the current node has childs.
351 * @return <b>true</b> if so, <b>false</b> if not.
352 */
353 bool HasChilds()
354 {
355 return (0 != node->child);
356 }
357
358 /** Checks if the current node has previous.
359 * @return <b>true</b> if so, <b>false</b> if not.
360 */
361 bool HasPrev()
362 {
363 return (0 != node->prev);
364 }
365
366 /** Checks if the current node has next.
367 * @return <b>true</b> if so, <b>false</b> if not.
368 */
369 bool HasNext()
370 {
371 return (0 != node->next);
372 }
373 };
374
375 /** Returns a new iterator. The caller must delete (with operator delete) the object after using it.
376 * @return Iterator at the root node.
377 */
378 Iterator * NewIterator() {return new Iterator(*this);}
379
380 /** Returns a new iterator in the given node.
381 * The caller must delete (with operator delete) the object after using it.
382 * @param n Node at which the iterator must be placed.
383 * @return Iterator at the given node.
384 */
385 Iterator * NewIterator(Node *n) {return new Iterator(*this, n);}
386
387 /** Goes to the begin of the global node list.
388 */
389 void Begin() {itG = nodes.begin();}
390
391 /** Check if it's at the end of the global node list.
392 * @return <b>true</b> if so, <b>false</b> if not.
393 */
394 bool End() {return itG == nodes.end();}
395
396 /** Returns the object at the current position in the global list of nodes.
397 * @return Object at the current position in the global list of nodes.
398 */
399 T& Cur() {return (*itG)->data;}
400
401 /** Goes to the previous node in the global list of nodes.
402 */
403 void Prev() {--itG;}
404
405 /** Goes to the next node in the global list of nodes.
406 */
407 void Next() {++itG;}
408
409 /** Returns the number of elements in the tree.
410 * @return Total number of elements in the tree.
411 */
412 s32 Size() {return nodes.size();}
413
414 /** Clear the whole tree (BUT not its contents if they were pointers).
415 */
416 void Clear() {nodes.clear();}
417
418 friend class Iterator;
419 };
420
421 #endif // _JTREE_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** JLib's types definition file.
23 * @file JTypes.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 01/04/2003
26 * @version 0.0.1 - 01/04/2003 - First version.
27 */
28 #ifndef _JTYPES_INCLUDED
29 #define _JTYPES_INCLUDED
30
31 #include <limits.h>
32
33 #ifdef _WIN32
34 /** Macro para los tipos de 64 bits en constante para windows. */
35 #define S64(X) X##i64
36 /** Macro para los tipos de 64 bits en constante para windows. */
37 #define U64(X) X##ui64
38 #else
39 /** Macro para los tipos de 64 bits en constante para no-windows. */
40 #define S64(X) X##LL
41 /** Macro para los tipos de 64 bits en constante para no-windows. */
42 #define U64(X) X##ULL
43 #endif
44
45 typedef char s8;
46 typedef unsigned char u8;
47 typedef short s16;
48 typedef unsigned short u16;
49 typedef int s32;
50 typedef unsigned int u32;
51
52 #ifdef _WIN32
53 typedef __int64 s64;
54 typedef unsigned __int64 u64;
55 #else
56 typedef long long int s64;
57 typedef unsigned long long int u64;
58 #endif
59
60 #define S8_MIN ((s8)(0x80))
61 #define S8_MAX ((s8)(0x7F))
62 #define U8_MIN ((u8)(0x00))
63 #define U8_MAX ((u8)(0xFF))
64 #define S16_MIN ((s16)(0x8000))
65 #define S16_MAX ((s16)(0x7FFF))
66 #define U16_MIN ((u16)(0x0000))
67 #define U16_MAX ((u16)(0xFFFF))
68 #define S32_MIN ((s32)(0x80000000))
69 #define S32_MAX ((s32)(0x7FFFFFFF))
70 #define U32_MIN ((u32)(0x00000000))
71 #define U32_MAX ((u32)(0xFFFFFFFF))
72 #define S64_MIN (S64(0x8000000000000000))
73 #define S64_MAX (S64(0x7FFFFFFFFFFFFFFF))
74 #define U64_MIN (U64(0x0000000000000000))
75 #define U64_MAX (U64(0xFFFFFFFFFFFFFFFF))
76
77 // Casts to and from void * avoiding compiler warnings
78 // This is absolutely tricky and a different approach should be used if possible
79 // It's intended to be used when you want to pass a void* that contain a value instead
80 // of and address (i.e. as parameter of callback functions that accept a void* as additional data).
81 // Be aware of the fact that YOU CAN ONLY USE THE MACROS WITH A NUMBER LOWER OR EQUAL TO THE
82 // BITS OF THE UNDERLYING ARCHITECTURE YOU COMPILE FOR. That is, if you intend to compile only for a 32-bits
83 // architecture, you can use all of them. If your target architecture is 16-bit based, you could only
84 // use the 8bit and 16bit macros listed here, and using any of the 32-bit macros in this case could
85 // translate in a segmentation fault during execution. Notice that he 'double' and 'long' types are normally
86 // twice the size of the architecture
87 #define JCAST_8_TO_VOIDPTR(val) ((void *)size_t(*((u8 *)&(val))))
88 #define JCAST_16_TO_VOIDPTR(val) ((void *)size_t(*((u16 *)&(val))))
89 #define JCAST_32_TO_VOIDPTR(val) ((void *)size_t(*((u32 *)&(val))))
90 #define JCAST_64_TO_VOIDPTR(val) ((void *)size_t(*((u64 *)&(val))))
91
92 #define JCAST_S8_TO_VOIDPTR(val) JCAST_8_TO_VOIDPTR((val))
93 #define JCAST_U8_TO_VOIDPTR(val) JCAST_8_TO_VOIDPTR((val))
94 #define JCAST_S16_TO_VOIDPTR(val) JCAST_16_TO_VOIDPTR((val))
95 #define JCAST_U16_TO_VOIDPTR(val) JCAST_16_TO_VOIDPTR((val))
96 #define JCAST_S32_TO_VOIDPTR(val) JCAST_32_TO_VOIDPTR((val))
97 #define JCAST_U32_TO_VOIDPTR(val) JCAST_32_TO_VOIDPTR((val))
98 #define JCAST_FLOAT_TO_VOIDPTR(val) JCAST_32_TO_VOIDPTR((val))
99 #define JCAST_S64_TO_VOIDPTR(val) JCAST_64_TO_VOIDPTR((val))
100 #define JCAST_U64_TO_VOIDPTR(val) JCAST_64_TO_VOIDPTR((val))
101 #define JCAST_DOUBLE_TO_VOIDPTR(val) JCAST_64_TO_VOIDPTR((val))
102
103 #define JCAST_VOIDPTR_TO_TYPE(p, type) (*((type *)&(p)))
104 #define JCAST_VOIDPTR_TO_S8(p) JCAST_VOIDPTR_TO_TYPE(p, s8)
105 #define JCAST_VOIDPTR_TO_U8(p) JCAST_VOIDPTR_TO_TYPE(p, u8)
106 #define JCAST_VOIDPTR_TO_S16(p) JCAST_VOIDPTR_TO_TYPE(p, s16)
107 #define JCAST_VOIDPTR_TO_U16(p) JCAST_VOIDPTR_TO_TYPE(p, u16)
108 #define JCAST_VOIDPTR_TO_S32(p) JCAST_VOIDPTR_TO_TYPE(p, s32)
109 #define JCAST_VOIDPTR_TO_U32(p) JCAST_VOIDPTR_TO_TYPE(p, u32)
110 #define JCAST_VOIDPTR_TO_S64(p) JCAST_VOIDPTR_TO_TYPE(p, s64)
111 #define JCAST_VOIDPTR_TO_U64(p) JCAST_VOIDPTR_TO_TYPE(p, u64)
112 #define JCAST_VOIDPTR_TO_FLOAT(p) JCAST_VOIDPTR_TO_TYPE(p, float)
113 #define JCAST_VOIDPTR_TO_DOUBLE(p) JCAST_VOIDPTR_TO_TYPE(p, double)
114
115 #endif // _JTYPES_INCLUDED
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Macros y funciones de utilidad diversa.
23 * @file JUtil.cpp.
24 * @author Juan Carlos Seijo Pérez
25 * @date 16/10/2003
26 * @version 0.0.1 - 16/10/2003 - Primera versión.
27 */
28
29 #include <JLib/Util/JUtil.h>
30
31 // Carga una fuente de un fichero Targa, con caracteres de 8x8 píxels,
32 // 16 filas y 16 columnas (256).
33 void JDumpTGAFontBits(const JString &TGAFileName, const JString &outFileName)
34 {
35 JImage img;
36 if (!img.Load(TGAFileName))
37 return;
38
39 u8 *chars[256];
40 u8 *ptr;
41 u32 rowSize;
42 s32 ind, imgInd;
43
44 rowSize = (u32)(img.Line(1) - img.Line(0));
45
46 for (s32 j = 0; j < 16; ++j)
47 {
48 // Avanza al primer caracter de la siguiente fila
49 ptr = img.Line(j * 8);
50
51 for (s32 i = 0; i < 16; ++i)
52 {
53 ind = ((15 - j) * 16) + i; // = (row * nCharsRow) + col
54
55 // Reservamos 8 bytes para cada caracter
56 chars[ind] = new u8[8];
57 memset(chars[ind], 0, 8 * sizeof(s8));
58
59 for (s32 y = 0; y < 8; ++y)
60 {
61 imgInd = (y * rowSize);
62
63 for (s32 x = 0; x < 8; ++x)
64 {
65 if (0xFF & *(ptr + imgInd))
66 {
67 // 7 - y empieza a rellenar por abajo, ya que en memoria está invertido
68 chars[ind][y] |= 0x80 >> x;
69 }
70
71 imgInd += 4;
72 }
73 }
74
75 // Avanza al siguiente caracter de la fila
76 ptr += 32;
77 }
78 }
79
80 // Vuelca en formato de array los datos de la fuente al fichero dado
81 JTextFile outFile(outFileName);
82 if (outFile.Open())
83 {
84 outFile.Printf("const u8 font[256][] = {\n");
85 for (s32 row = 0; row < 16; ++row)
86 {
87 for (s32 col = 0; col < 16; ++col)
88 {
89 outFile.Printf("{");
90 for (s32 idx = 0; idx < 8; ++idx)
91 {
92 outFile.Printf("0x%02x,", chars[(row * 16) + col][idx]);
93 }
94 outFile.Printf("},\n");
95 }
96 }
97
98 outFile.Printf("};\n");
99 }
100 else
101 {
102 printf("DumpTGAFontBits: Error al abrir el archivo.\n");
103 }
104
105 for (s32 i = 0; i < 256; ++i)
106 delete[] chars[i];
107 }
108
109 JVideoMode * JListVideoModes(s32 *count, s32 depth)
110 {
111 bool uninit = false;
112 s32 bpps[] = {32, 24, 16, 8};
113
114 s32 *pBpps = bpps, nBpps = 4;
115
116 if (depth != 0)
117 {
118 pBpps = &depth;
119 nBpps = 1;
120 }
121
122 if (SDL_WasInit(SDL_INIT_VIDEO) == 0)
123 {
124 // Video no inicializado, lo inicializa
125 if (-1 == SDL_Init(SDL_INIT_VIDEO))
126 {
127 // No se puede iniciar el video
128 return 0;
129 }
130
131 // Deinicializar SDL al final
132 uninit = true;
133 }
134
135 std::vector<JVideoMode*> modes;
136 SDL_Rect **modeList = 0;
137 JVideoMode *mode;
138
139 // Busca los modos de vídeo sin aceleración para la profundidad actual y comprueba para el resto de profundidades
140 modeList = SDL_ListModes(0, SDL_FULLSCREEN);
141 if ((long)modeList == 0 || (long)modeList == -1)
142 {
143 return 0;
144 }
145
146 s32 rec;
147
148 for (s32 k = 0; k < nBpps; ++k)
149 {
150 for (s32 j = 0; modeList[j] != 0; ++j)
151 {
152 if (0 != (rec = SDL_VideoModeOK(modeList[j]->w, modeList[j]->h, pBpps[k], SDL_HWSURFACE | SDL_FULLSCREEN))
153 && (j == 0 || (modeList[j]->w != modeList[j - 1]->w || modeList[j]->h != modeList[j - 1]->h)))
154 {
155 mode = new JVideoMode;
156 mode->w = modeList[j]->w;
157 mode->h = modeList[j]->h;
158 mode->bpp = pBpps[k];
159 mode->hw = true;
160 modes.push_back(mode);
161 }
162 }
163 }
164
165 JVideoMode *result = 0;
166
167 if (modes.size() == 0)
168 {
169 result = 0;
170 }
171 else
172 {
173 if (count)
174 *count = modes.size();
175
176 result = new JVideoMode [modes.size() + 1];
177 for (u32 i = 0; i < modes.size(); ++i)
178 {
179 memcpy(&result[i], modes[i], sizeof(JVideoMode));
180 delete modes[i];
181 }
182
183 // Último elemento
184 result[modes.size()].w = result[modes.size()].h = -1;
185 modes.clear();
186 }
187
188 if (uninit)
189 {
190 SDL_QuitSubSystem(SDL_INIT_VIDEO);
191 }
192
193 return result;
194 }
195
196 void JDumpImage(JImage *img, s32 n)
197 {
198 SDL_Surface *s = img->Surface();
199 SDL_PixelFormat *fmt = s->format;
200
201 if (0 != SDL_LockSurface(s))
202 {
203 return;
204 }
205
206 fprintf(stderr,
207 "%dx%d@%d CKEY: %08x ALPHA: %d SRCALPHA: %s SRCCOLORKEY: %s RLE: %s\n",
208 s->w, s->h, fmt->BitsPerPixel, fmt->colorkey, fmt->alpha,
209 s->flags & SDL_SRCALPHA ? "yes" : "no",
210 s->flags & SDL_SRCCOLORKEY ? "yes" : "no",
211 s->flags & SDL_RLEACCEL ? "yes" : "no",
212 s->flags & SDL_RLEACCEL ? "yes" : "no");
213 fprintf(stderr,
214 "RGBAmask: R: 0x%08x G: 0x%08x B: 0x%08x A: 0x%08x\n",
215 fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask);
216 fprintf(stderr,
217 "RGBAshift: R: 0x%08x G: 0x%08x B: 0x%08x A: 0x%08x\n",
218 fmt->Rshift, fmt->Gshift, fmt->Bshift, fmt->Ashift);
219 fprintf(stderr,
220 "RGBAloss: R: 0x%08x G: 0x%08x B: 0x%08x A: 0x%08x\n",
221 fmt->Rloss, fmt->Gloss, fmt->Bloss, fmt->Aloss);
222
223 // Muestra el valor de algunos píxeles
224 if (n != 0)
225 {
226 fprintf(stderr, "First %d pixels:\n", n);
227 for (s32 j = 0, count = 1; count <= n && j < s->h; ++j)
228 {
229 for (s32 i = 0; count <= n && i < s->w; ++i)
230 {
231 fprintf(stderr, "%08x ", img->GetPixel(i, j));
232
233 if (count % 10 == 0)
234 fprintf(stderr, "\n");
235
236 ++count;
237 }
238 }
239
240 fprintf(stderr, "First %d pixels != CKEY:\n", n);
241 for (s32 j = 0, count = 1; count <= n && j < s->h; ++j)
242 {
243 for (s32 i = 0; count <= n && i < s->w; ++i)
244 {
245 if (img->GetPixel(i, j) != fmt->colorkey)
246 {
247 fprintf(stderr, "%08x ", img->GetPixel(i, j));
248
249 if (count % 10 == 0)
250 fprintf(stderr, "\n");
251
252 ++count;
253 }
254 }
255 }
256
257 fprintf(stderr, "\n");
258 }
259
260 SDL_UnlockSurface(s);
261 }
262
0 /*
1 * JLib - Jacob's Library.
2 * Copyright (C) 2003, 2004 Juan Carlos Seijo Pérez
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Macros y funciones de utilidad diversa.
23 * @file JUtil.h.
24 * @author Juan Carlos Seijo Pérez
25 * @date 16/10/2003
26 * @version 0.0.1 - 16/10/2003 - Primera versión.
27 */
28
29 #ifndef _JUTIL_INCLUDED
30 #define _JUTIL_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Graphics/JImage.h>
34 #include <JLib/Util/JString.h>
35 #include <JLib/Util/JTextFile.h>
36 #include <vector>
37
38 class JImage;
39
40 /** Devuelve la palabra (32) menos significativa */
41 #define JLOWORD(x) ((x) & 0x0000FFFF)
42
43 /** Devuelve la palabra más significativa */
44 #define JHIWORD(x) ((x) & 0xFFFF0000)
45
46 /** Devuelve el byte menos significativo */
47 #define JLOBYTE(x) ((x) & 0x00FF)
48
49 /** Devuelve el byte más significativo */
50 #define JHIBYTE(x) ((x) & 0xFF00)
51
52 /** Devuelve el mínimo entre dos números.
53 * @param a Primer número.
54 * @param b Segundo número.
55 * @return Menor de los dos números.
56 */
57 inline float JMin(float a, float b)
58 {
59 return a < b ? a : b;
60 }
61
62 /** Devuelve el máximo entre dos números.
63 * @param a Primer número.
64 * @param b Segundo número.
65 * @return Mayor de los dos números.
66 */
67 inline float JMax(float a, float b)
68 {
69 return a > b ? a : b;
70 }
71
72 /** Recorta el valor por arriba y por abajo para que no sobrepase min y max.
73 * @param v Valor a recortar.
74 * @param min Valor mínimo que puede tomar.
75 * @param max Valor máximo que puede tomar.
76 */
77 inline void JClamp(s8& v, s8 min, s8 max)
78 {
79 if (v < min) {v = min; return;} if (v > max) {v = max; return;}
80 }
81
82 /** Recorta el valor por arriba y por abajo para que no sobrepase min y max.
83 * @param v Valor a recortar.
84 * @param min Valor mínimo que puede tomar.
85 * @param max Valor máximo que puede tomar.
86 */
87 inline void JClamp(u8& v, u8 min, u8 max)
88 {
89 if (v < min) {v = min; return;} if (v > max) {v = max; return;}
90 }
91
92 /** Recorta el valor por arriba y por abajo para que no sobrepase min y max.
93 * @param v Valor a recortar.
94 * @param min Valor mínimo que puede tomar.
95 * @param max Valor máximo que puede tomar.
96 */
97 inline void JClamp(s16& v, s16 min, s16 max)
98 {
99 if (v < min) {v = min; return;} if (v > max) {v = max; return;}
100 }
101
102 /** Recorta el valor por arriba y por abajo para que no sobrepase min y max.
103 * @param v Valor a recortar.
104 * @param min Valor mínimo que puede tomar.
105 * @param max Valor máximo que puede tomar.
106 */
107 inline void JClamp(u16& v, u16 min, u16 max)
108 {
109 if (v < min) {v = min; return;} if (v > max) {v = max; return;}
110 }
111
112 /** Recorta el valor por arriba y por abajo para que no sobrepase min y max.
113 * @param v Valor a recortar.
114 * @param min Valor mínimo que puede tomar.
115 * @param max Valor máximo que puede tomar.
116 */
117 inline void JClamp(s32& v, s32 min, s32 max)
118 {
119 if (v < min) {v = min; return;} if (v > max) {v = max; return;}
120 }
121
122 /** Recorta el valor por arriba y por abajo para que no sobrepase min y max.
123 * @param v Valor a recortar.
124 * @param min Valor mínimo que puede tomar.
125 * @param max Valor máximo que puede tomar.
126 */
127 inline void JClamp(u32& v, u32 min, u32 max)
128 {
129 if (v < min) {v = min; return;} if (v > max) {v = max; return;}
130 }
131
132 /** Recorta el valor por arriba y por abajo para que no sobrepase min y max.
133 * @param v Valor a recortar.
134 * @param min Valor mínimo que puede tomar.
135 * @param max Valor máximo que puede tomar.
136 */
137 inline void JClamp(float& v, float min, float max)
138 {
139 if (v < min) {v = min; return;} if (v > max) {v = max; return;}
140 }
141
142 /** Escribe un fichero raw con los bits de la fuente del fichero TGA dado.
143 * @param TGAFileName Nombre del fichero targa con la fuente ordenada.
144 * deben ser caracteres de 8x8 organizados en 16 filas por 16 columnas.
145 * @param outFileName Nombre del fichero de salida.
146 */
147 void JDumpTGAFontBits(const s8 *TGAFileName, const s8 *outFileName);
148
149 /** Modo gráfico.
150 */
151 struct JVideoMode
152 {
153 s32 w; /**< Anchura del modo. */
154 s32 h; /**< Altura del modo. */
155 s32 bpp; /**< Profundidad de color en bits del modo. */
156 bool hw; /**< Indicador de aceleración hardware. */
157 };
158
159 /** Devuelve un puntero a una tabla con los modos gráficos disponibles. Es necesario
160 * borrar con JDELETE_ARRAY() el array resultante.
161 * @param depth Profundidad para la que se quieren obtener los modos.
162 * @param count Salida con el número de modos encontrados.
163 * @return Lista de modos disponibles en pantalla completa tanto acelerados como no acelerados por HW.
164 * El último elemento del array tiene anchura y altura -1.
165 * Si devuelve 0 es que no existe ningún modo.
166 */
167 JVideoMode * JListVideoModes(s32 *count, s32 depth = 0);
168
169 /** Muestra en stderr las propiedades de una imagen, los n primeros
170 * píxeles y los n primeros píxeles diferentes de la CKEY.
171 * @param img Imagen a examinar.
172 * @param n Número de píxeles a mostrar.
173 */
174 void JDumpImage(JImage *img, s32 n = 10);
175
176 #endif // _JUTIL_INCLUDED
0 # Makefile para JLib.
1 # (C) Juan Carlos Seijo Pérez - 2003.
2
3 GRAPHICS=JLib/Graphics
4 UTIL=JLib/Util
5 MATH=JLib/Math
6 SOUND=JLib/Sound
7 PHYSICS=JLib/Physics
8
9 JLIB_OBJS=$(GRAPHICS)/JControl.o $(GRAPHICS)/JUI.o $(GRAPHICS)/JGLAxes.o $(GRAPHICS)/JGLCamera.o $(GRAPHICS)/JGLConsole.o\
10 $(GRAPHICS)/JGLGrid.o $(GRAPHICS)/JGLLight.o $(GRAPHICS)/JGLTexture.o $(GRAPHICS)/JGLVector.o \
11 $(GRAPHICS)/JControlImage.o $(GRAPHICS)/JImage.o $(GRAPHICS)/JImageSprite.o $(GRAPHICS)/JSprite.o $(GRAPHICS)/JFont.o\
12 $(GRAPHICS)/JTextMenu.o $(GRAPHICS)/JImageMenu.o $(GRAPHICS)/JGLMesh.o $(GRAPHICS)/JGLImage.o $(UTIL)/JFile.o\
13 $(UTIL)/JGLApp.o $(UTIL)/JObject.o $(UTIL)/JTextFile.o $(UTIL)/JTextUtil.o $(UTIL)/JTimer.o $(UTIL)/JUtil.o\
14 $(UTIL)/JApp.o $(UTIL)/JFS.o $(UTIL)/JThread.o $(UTIL)/JRW.o $(MATH)/J2DPolygon.o
15
16 ifndef SDL_CONFIG
17 SDL_CONFIG = sdl-config
18 endif
19
20 # Define -D_JLIB_DEBUG to debug JLib. Compile the app to debug also with this flag
21 CFLAGS=-I. -I/usr/local/include/SDL -O3 -ffast-math -fPIC -Wall -Wshadow `$(SDL_CONFIG) --cflags`
22
23 # Sample LDFLAGS for applications
24 # LDFLAGS=-L. -ffast-math -lSDL_image -lSDL_ttf -lSDL_mixer `$(SDL_CONFIG) --libs`
25
26 all: libJLib
27
28 # JLib
29 libJLib: $(JLIB_OBJS)
30 g++-4.1 -shared -L/usr/lib -fPIC -o $@.so $? \
31 && ar rvus $@.a $? \
32
33 $(GRAPHICS)/%.o: $(GRAPHICS)/%.cpp
34 g++-4.1 $(CFLAGS) -c -o $@ $<
35 $(UTIL)/%.o: $(UTIL)/%.cpp
36 g++-4.1 $(CFLAGS) -c -o $@ $<
37 $(MATH)/%.o: $(MATH)/%.cpp
38 g++-4.1 $(CFLAGS) -c -o $@ $<
39
40 .PHONY: install
41 install:
42 cp libJLib* /usr/local/lib/.; \
43 find . -name *.h -exec 'cp' '--parents' '{}' '/usr/local/include/' ';' ; \
44 ldconfig;
45
46 .PHONY: clean
47 clean:
48 rm -rf JLib/*/*\.o libJLib.a libJLib.so
0 # Makefile para JLib/Win32.
1 # (C) Juan Carlos Seijo Pérez - 2003.
2
3 GRAPHICS=JLib/Graphics
4 UTIL=JLib/Util
5 MATH=JLib/Math
6 SOUND=JLib/Sound
7 PHYSICS=JLib/Physics
8
9 JLIB_OBJS=$(GRAPHICS)/JControl.o $(GRAPHICS)/JUI.o $(GRAPHICS)/JGLAxes.o $(GRAPHICS)/JGLCamera.o $(GRAPHICS)/JGLConsole.o \
10 $(GRAPHICS)/JGLGrid.o $(GRAPHICS)/JGLLight.o $(GRAPHICS)/JGLTexture.o $(GRAPHICS)/JGLVector.o \
11 $(GRAPHICS)/JControlImage.o $(GRAPHICS)/JImage.o $(GRAPHICS)/JImageSprite.o $(GRAPHICS)/JSprite.o $(GRAPHICS)/JFont.o \
12 $(GRAPHICS)/JTextMenu.o $(GRAPHICS)/JImageMenu.o $(GRAPHICS)/JGLMesh.o $(GRAPHICS)/JGLImage.o $(UTIL)/JFile.o \
13 $(UTIL)/JGLApp.o $(UTIL)/JObject.o $(UTIL)/JTextFile.o $(UTIL)/JTextUtil.o $(UTIL)/JTimer.o $(UTIL)/JUtil.o \
14 $(UTIL)/JApp.o $(UTIL)/JThread.o $(MATH)/J2DPolygon.o
15
16 # Definir -D_JLIB_DEBUG para hacer debug de JLib. Compilar el programa a debugear también con este flag
17 CFLAGS=-I. -I/mingw/include/SDL -O3 -ffast-math -I/mingw/include
18 #LDFLAGS=-L. -ffast-math -lwinsock32 -luser32.lib -lgdi32.lib -lwinmm.lib -lcomdlg32.lib -lcomctl32.lib -lSDLmain -lSDL -lSDL_image -lSDL_ttf -lSDL_mixer -lJLib
19
20 all: libJLib
21
22 # JLib
23 libJLib: $(JLIB_OBJS)
24 ar rvus $@.a $?
25
26 $(GRAPHICS)/%.o: $(GRAPHICS)/%.cpp
27 g++ $(CFLAGS) -c -o $@ $<
28 $(UTIL)/%.o: $(UTIL)/%.cpp
29 g++ $(CFLAGS) -c -o $@ $<
30 $(MATH)/%.o: $(MATH)/%.cpp
31 g++ $(CFLAGS) -c -o $@ $<
32
33 .PHONY: install
34 install:
35 cp libJLib* /mingw/lib/.; \
36 find . -name *.h -exec 'cp' '--parents' '{}' '/mingw/include/' ';' ; \
37
38 .PHONY: clean
39 clean:
40 rm JLib/Graphics/*.o
41 rm JLib/Util/*.o
42 rm JLib/Math/*.o
43 rm libJLib.a
0 The GNU General Public License (GPL)
1 Version 2, June 1991
2
3 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
4 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5
6 Everyone is permitted to copy and distribute verbatim copies
7 of this license document, but changing it is not allowed.
8
9 Preamble
10
11 The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.
12
13 When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
14
15 To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
16
17 For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
18
19 We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
20
21 Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
22
23 Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
24
25 The precise terms and conditions for copying, distribution and modification follow.
26
27 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
28
29 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".
30
31 Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
32
33 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
34
35 You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
36
37 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
38
39 a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
40
41 b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
42
43 c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
44
45 These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
46
47 Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
48
49 In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
50
51 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
52
53 a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
54
55 b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
56
57 c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
58
59 The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
60
61 If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
62
63 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
64
65 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
66
67 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
68
69 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
70
71 If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
72
73 It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
74
75 This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
76
77 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
78
79 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
80
81 Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
82
83 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
84
85 NO WARRANTY
86
87 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
88
89 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
90
91 END OF TERMS AND CONDITIONS
0 # Makefile Para Holotz's Castle. (C) Juan Carlos Seijo Pérez - 2004.
1 # Makefile for Holotz's Castle.
2
3 HC_VERSION=1.3.14
4
5 all:
6 $(MAKE) -C src
7
8 distro-src:
9 find . -iname "*~" -exec 'rm' '{}' ';';
10 $(MAKE) clean;
11 rm -rf _DISTRO/SRC;
12 mkdir -p _DISTRO/SRC/holotz-castle-$(HC_VERSION)-src;\
13 cp -RL [^_h]* _DISTRO/SRC/holotz-castle-$(HC_VERSION)-src &&\
14 cd _DISTRO/SRC &&\
15 tar -czvf holotz-castle-$(HC_VERSION)-src.tar.gz holotz-castle-$(HC_VERSION)-src &&\
16 cd ../.. &&\
17 rm -rf _DISTRO/SRC/holotz-castle-$(HC_VERSION)-src\
18
19 distro-i486:
20 find . -iname "*~" -exec 'rm' '{}' ';';
21 $(MAKE) I486_BUILD=1 CPU_OPTS="-march=i486" &&\
22 rm -rf _DISTRO/I486;
23 mkdir -p _DISTRO/I486/holotz-castle-$(HC_VERSION)-linux-i486;
24 cp -RL holotz-castle holotz-castle-editor res HCedHome doc LICENSE.txt man _DISTRO/I486/holotz-castle-$(HC_VERSION)-linux-i486 &&\
25 cd _DISTRO/I486 &&\
26 tar -czvf holotz-castle-$(HC_VERSION)-linux-i486.tar.gz holotz-castle-$(HC_VERSION)-linux-i486;
27 rm -rf _DISTRO/I486/holotz-castle-$(HC_VERSION)-linux-i486;
28
29 distro-win32:
30 find . -iname "*~" -exec 'rm' '{}' ';';
31 rm -rf _DISTRO/WIN32;
32 mkdir -p _DISTRO/WIN32/HC;
33 cp -RL _WIN32_DLLS/* holotz-castle.exe holotz-castle-editor.exe res HCedHome LICENSE.txt doc _DISTRO/WIN32/HC &&\
34 cd _DISTRO/WIN32 &&\
35 zip -r HC HC;
36 mv _DISTRO/WIN32/HC.zip _DISTRO/WIN32/holotz-castle-$(HC_VERSION)-win32.zip;
37 rm -rf _DISTRO/WIN32/HC;
38
39 install:
40 $(MAKE) -C src install
41
42 uninstall:
43 $(MAKE) -C src uninstall;
44
45 .PHONY: clean
46 clean:
47 $(MAKE) -C src clean
0 # Makefile Para Holotz's Castle. (C) Juan Carlos Seijo Pérez - 2004.
1 # Makefile for Holotz's Castle.
2
3 all: HC
4
5 .PHONY: HC
6 HC:
7 make -C src -f Makefile.win32
8
9 .PHONY: clean
10 clean:
11 make -C src -f Makefile.win32 clean
0 Holotz's Castle - Manual
1 ------------------------
2
3 HISTORY:
4 08/02/2005 - Second edition.
5 24/10/2004 - First edition.
6
7 1. Quick Start
8
9 1.1. Windows
10
11 1. Unzip HC_win32-1.3.zip
12 2. After the extraction process, a folder named HC appears.
13 3. Explore into that folder.
14 4. Double click holotz-castle.exe
15 5. Enjoy!
16
17 NOTA: To create an application short cut is necessary to fill the field 'Run in' the
18 full path to the HC folder, in the short cut properties dialog.
19
20 1.2. Linux (source code)
21
22 1. Do 'tar -zxf HC_JLib_Linux_Win32-1.3.tar.gz' (without quotes)
23 2. Follow the instructions in the file README.txt under the directory 'HC_JLib_Linux_Win32-1.3'.
24 3. Do 'cd Games/HolotzCastle'
25 4. Do './holotz-castle'
26 5. Enjoy!
27
28 2. Walk-around
29
30 To show the help in the main menu or playing, press F1. Th ehelp is not available during the dialog
31 scenes.
32
33 The first two scenes you see when you select 'New game' in the main menu is a dialog between Ybelle and
34 Ludar, the main characters of the game.
35
36 You can skip the dialog balloons by pressing space. You can skip the entire scene by pressing enter.
37
38 You can switch to the main menu whenever you want while playing but then if you select the option 'Continue game'
39 you will start at the beginning of the last level played.
40 Said this, as a rule of thumb: if you want to save, do it when you just entered a new level.
41
42 To pause a game and relax, press 'p'. Pressing 'p' again gets you back to the game.
43
44 At the third level you can control Ybelle. Try moving it with the arrow keys. Try jumping with the space bar.
45 The more you keep pressed it the more you can jump.
46
47 The remaining time to complete a level is displayed in the top left corner of the screen.
48
49 The remaining objects to unlock the exit of a level are displayed in the top right corner of the screen.
50
51 When you collect all the objects, the exit activates (it moves faster) you have to move toward it and when you
52 are bellow, jump to exit the level.
53
54 If you find too hard or too easy the levels, try to adjust the difficulty in the main menu (Options > Difficulty).
55
56 3. HCed
57
58 HCed is the level editor for Holotz's Castle.
59
60 To launch it:
61 - In Linux, run './holotz-castle-editor'
62
63 - In Windows, double click over the icon holotz-castle-editor.exe
64
65 Main window:
66
67 The title of the window contains the file being used when you save the current level.
68
69 In the left side are shown the icons:
70
71 - Normal floor
72 - Continuous floor
73 - Ladder
74 - Bar
75 - Breakable floor
76 - Object
77 - Rope
78 - Start position
79 - End position
80 - Enemies
81 - Save
82 - Load/Create story
83 - Exit
84
85 Under those, there are these indicators:
86
87 - Level time.
88 - Gravity.
89 - X Speed.
90 - Y Speed.
91 - Jump amount.
92 - Map size (rows x columns)
93
94 Mouse:
95
96 Left button: Draws the current object in the map.
97 Central button or left & right buttons at the same time: Deletes the object under the pointer.
98
99 Keys:
100
101 c : adds blank column to the right
102 Shift + c : removes column to the right
103 Ctrl + c : adds blank column to the left
104 Ctrl + Mayús + c : removes column to the left
105 r : adds blank row bellow
106 Shift + r : removes row bellow
107 Ctrl + r : adds blank row upside
108 Ctrl + Mayús + r : removes row upside
109 + : increase time (based upon hardest difficulty level)
110 - : decrease time
111 g : increase gravity
112 Shift + g: decrease gravity
113 x : increase x speed
114 Shift + x: decrease x speed
115 y : increase y speed
116 Shift + y: decrease y speed
117 j : increase jump amount
118 Shift + j : decrease jump amount
119
120 With object/rope/start pos./enemy:
121 Ctrl - Adjusts to map.
122
123 Adding ropes:
124 Select rope icon.
125 Position rope in map.
126 Without realeasing the left mouse button, press 'Alt'.
127 Mover updown mouse to set rope length.
128 Without realeasing the left mouse button, press 'Shift' to adjust the rope period.
129
130 4. FAQ
131
132 Q. I double-click on HC.exe but nothing happens!
133 A. Open the file called stderr.txt in the same folder (or check the console messages under Linux).
134 The last lines tell the problem initializing the game. Find a solution in the rest of the FAQ
135 for your problem.
136
137 Q. The game runs slowly what can I do?
138 A. Select a lower resolution video mode in the main menu:
139 Options > Video > Size > [mode]
140 Maybe your graphics card supports 320x200 mode, that's a chance to
141 revive the feelings of the old-fashined video games.
142
143 Q. I'm running Linux with ALSA but don't hear any sound.
144 A. By default ALSA mutes the sound. Try to check the volume with alsamixer or aumix or kmix.
145 If another application is using the the sound device you will not be able to hear sounds
146 until you close it.
147
148 Q. Sound under Windows is fake!
149 A. Despite the fact that the soundtrack is not very audible by itself :D, maybe the problem is
150 in the drivers of your soundcard. Get the last version of them and try again.
151
152 Q. In 8 bpp mode some parts of the level are black at all!
153 A. That error is fixed in v1.2 on higher, check the web (www.mainreactor.net) for the last release.
154
155 Q. I didn't find an answer to my problem in this FAQ, what should I do?
156 A. You can e-mail me to the direction bellow. Don't forget to attach the file called stderr.txt which is
157 in the same folder as the executable (HC.exe). It contains information about your graphics card and
158 the problem with the game.
159
160 Q. I'm an artist/musician/programmer/producer/90-60-90-model and I want to contribute to the cause. What can I do?
161 A. Oh, you can e-mail me at the direction bellow (if you are model we have to have a personal date first :) )
162
163
164 Juan Carlos Seijo Pérez (jacob@mainreactor.net)
0 Holotz's Castle - Manual
1 ------------------------
2
3 HISTORIA:
4 08/02/2005 - Segunda edición.
5 24/10/2004 - Primera edición.
6
7 1. Comienzo rápido.
8
9 1.1. Windows
10
11 1. Descomprime HC_win32-1.3.zip
12 2. Cuando termine de descomprimirse, una carpeta llamada HC apparece.
13 3. Abre la carpeta.
14 4. Haz doble click en holotz-castle.exe.
15 5. ¡Pásalo bien!
16
17 NOTA: Para crear un acceso directo es necesario poner en la casilla 'Ejecutar en' la
18 ruta completa de la carpeta HC, en las propiedades del acceso directo.
19
20 1.2. Linux (código fuente)
21
22 1. Haz 'tar -zxf HC_JLib_Linux_Win32-1.3.tar.gz' (sin comillas)
23 2. Sigue las instrucciones del fichero LEEME.txt en el directorio 'HC_JLib_Linux_Win32-1.3'.
24 3. Haz 'cd Games/HolotzCastle'
25 4. Haz './holotz-castle'
26 5. ¡Pásalo bien!
27
28 2. Un primer recorrido por el juego.
29
30 Para mostrar la ayuda mientras estás jugando, pulsa 'F1'. La ayuda no está disponible durante
31 las escenas de diálogo.
32
33 Las primeras dos escenas que ves cuando seleccionas 'Nueva Partida' en el menú principal es
34 un diálogo entre Ybelle y Ludar, los protagonistas del juego.
35
36 Puedes saltarte los globos de texto pulsando espacio. Puedes saltarte todo un diálogo con la tecla intro.
37
38 Puedes pasar al menú principal siempre que quieras durante el juego pero si luego quieres continuar
39 tendrás que empezar de nuevo el nivel desde el que saliste. Si vas a salvar, lo mejor es que lo hagas al
40 principio del nivel.
41
42 Para pausar el juego y tomarte un respiro pulsa 'p'. Pulsando 'p' de nuevo te lleva otra vez al juego.
43
44 En el tercer nivel puedes manejar a Ybelle. Intenta moverlo con las teclas de dirección. Intenta saltar con la
45 barra de espacio. Cuanto más la mantengas pulsada, más alto llegarás.
46
47 El tiempo restante para completar el nivel se muestra en la esquina superior izquierda.
48
49 El número de llaves objectos que faltan por recoger se muestra en la parte superior derecha.
50
51 Cuando has recogido todas los objetos, la salida del nivel se activa (se mueve más rápido). Tienes que conseguir
52 llegar a ella en tiempo y una vez debajo saltar para salir del nivel.
53
54 Si los niveles te parecen demasiado fáciles o difíciles, intenta ajustar el nivel de dificultad en el menú
55 principal (Opciones > Dificultad).
56
57 3. HCed
58
59 HCed es el editor de niveles de Holotz's Castle.
60
61 Para ejecutarlo:
62 - En Linux, ejecuta './holotz-castle-editor'
63
64 - En Windows, haz docle click sobre 'holotz-castle-editor.exe'
65
66 Ventana:
67
68 El título de la ventana muestra el fichero usado al salvar el nivel actual.
69
70 En la parte izquierda se muestran los iconos del editor:
71
72 - Suelo normal
73 - Suelo continuo
74 - Escalera
75 - Barra
76 - Suelo rompible
77 - Objeto
78 - Cuerda
79 - Posición de comienzo
80 - Posición de fin
81 - Enemigos
82 - Salvar
83 - Cargar/Crear historia
84 - Salir
85
86 Debajo de esto iconos están los indicadores:
87
88 - Tiempo del nivel.
89 - Gravedad.
90 - Velocidad x.
91 - Velocidad y.
92 - Potencia de salto.
93 - Tamaño del mapa (filas x columnas)
94
95 Ratón:
96
97 Botón izquierdo: Dibuja en el mapa el objeto actual.
98 Botón central o ambos botones a la vez pulsados: Borra el objeto bajo el
99 puntero.
100
101 Teclas:
102
103 c : añade columna en blanco por la derecha
104 Mayús + c : borra columna por la derecha
105 Ctrl + c : añade columna en blanco por la derecha
106 Ctrl + Mayús + c : borra columna por la derecha
107 + : aumenta tiempo (el tiempo es el del nivel de dificultad difícil)
108 - : disminuye tiempo
109 g : aumenta gravedad
110 Mayús g: disminuye gravedad
111 x : aumenta velocidad x
112 Mayús x: disminuye velocidad x
113 y : aumenta velocidad y
114 Mayús y: disminuye velocidad y
115 j : aumenta nº de unidades verticales de salto
116 Mayús + j : disminuye nº de unidades verticales de salto
117
118 Con objeto/cuerda/pos. comienzo/enemigo:
119 Ctrl - Ajusta la posición al mapa.
120
121 Añadir cuerdas:
122 Seleccionar el icono de cuerda.
123 Posicionar la cuerda en el mapa.
124 Sin soltar el botón izquierdo, pulsar la tecla 'Alt'.
125 Mover el ratón en vertical para ajustar la longitud de la cuerda.
126 Sin soltar 'Alt', pulsar 'Mayús' para ajustar la amplitud del movimiento.
127
128 4. Preguntas frecuentes.
129
130 P. ¡Hago doble click en HC.exe pero no pasa nada!
131 R. Abre el fichero llamado stderr.txt en la misma carpeta (o comprueba los mensajes de la consola si estás en Linux).
132 Las últimas líneas muestran el error que se produjo. Eso te puede dar una pista para encontrar la solución en el
133 resto de preguntas de esta lista.
134
135 P. El juego va muy despacio, ¿Qué puedo hacer?
136 R. Selecciona una resolución menor en el menú principal:
137 Opciones > Video > Tamaño > [WWWxHHH] (escoge un valor bajo para WWW y HHH)
138 Quizá tu tarjeta gráfica soporta el modo 320x200, esa es una buena oportunidad para
139 hacer que el juego se parezca más a los primeros juegos de plataformas.
140
141 P. Uso Linux con ALSA pero no oigo ningún sonido.
142 R. Por defecto ALSA enmudece el sonido completamente. Comprueba el valor del volumen por medio de algún
143 programa como alsamixer, aumix o kmix. Si otra aplicación está usando el sonido, no podrás oir nada hasta que
144 la aplicación se cierre.
145
146 P. ¡El sonido en Windows en penoso!
147 R. Dejando de un lado el hecho de que la banda sonora no es una maravilla en sí misma :D, quizá el problema
148 esté en los drivers de la tarjeta de sonido. Comprueba que tienes una versión actualizada de los mismos y si no
149 la tienes, actualizala y prueba de nuevo.
150
151 P. ¡En 8 bpp algunas partes del nivel aparecen en negro!
152 R. Sí, hay un pequeño problema con el modo de 8 bits por pixel. Esos bloques negros corresponden al suelo contínuo.
153 Quizá en la versión 2.0 esté ya solucionado :D
154
155 P. No he encontrado una respuesta a mi problema en esta lista, ¿Qué puedo hacer?
156 R. Puedes enviarme un correo describiéndome el problema a la dirección de correo que aparece más abajo. No
157 olvides adjuntar el fichero stderr.txt que está en la carpeta del juego. Contiene información sobre tu tarjeta
158 gráfica y el problema con el juego.
159
160 P. Soy dibujante/músico/programador/productor/modelo-90-60-90 y quiero contribuir a la causa. ¿Que puedo hacer?
161 R. Oh, puedes mandarme un e-mail a la dirección de correo de abajo (si eres una modelo, es imprescindible que tengamos
162 antes una cita personal :) ).
163
164
165 Juan Carlos Seijo Pérez (jacob@mainreactor.net)
0 Holotz's Castle - Eskuliburua
1 -----------------------------
2
3 HISTORIA:
4 08/02/2005 - Bigarren edizioa.
5 24/10/2004 - Lehen edizioa.
6
7 1. Hasiera bizkorra.
8
9 1.1. Windows
10
11 1. Atera HC_win32-1.3.zip artxiboko fitxategiak.
12 2. Ateratzen bukatzean, HC izeneko karpeta bat agertuko da.
13 3. Ireki karpeta.
14 4. Klik bikoitza egin holotz-castle.exe fitxategian.
15 5. Gozatu jokuaz!
16
17 OHARRA: Lasterbide bat sortzeko beharrezkoa da 'Hasi hemen:' dioen hutsunean
18 HC karpetaren bide osoa jartzea, lasterbidearen ezaugarrietan.
19
20 1.2. Linux (iturburu kodea)
21
22 1. Egin 'tar -zxf HC_JLib_Linux_Win32-1.3.tar.gz' (kakotx gabe)
23 2. Jarraitu 'HC_JLib_Linux_Win32-1.3' karpetako IRAKURRI.txt fitxategiko urratsak.
24 3. Egin 'cd Games/HolotzCastle'
25 4. Egin './holotz-castle'
26 5. Gozatu jokuaz!
27
28 2. Aurreneko ibilaldia jokuan zehar.
29
30 Jokatzen ari zarenean laguntza ikusteko, sakatu 'F1'. Elkarrizketetan ezin da laguntza
31 ikusi.
32
33 Hautesleihoan 'Jokaldi Berria' hautatzean agertzen diren lehen bi eszenak Ybelle eta Ludar,
34 jokuko protagonisten arteko elkarrizketak dira.
35
36 Elkarrizketa globoak ken ditzakezu Hutsunea sakatuz. Elkarrizketa osoa kentzeko sakatu Sartu.
37
38 Jokatzen zabiltzan bitartean edozein unetan joan zaitezke hautesleiho nagusira, baina gero utzitako
39 tokian jarraitzea ezinezkoa da, maila hori berriz hasi beharko duzu. Jokua gorde nahi baduzu, onena
40 mailaren hasieran egitea da.
41
42 Jokua gelditu eta atsedena hartzeko sakatu 'p'. Berriro 'p' zapalduz jokura itzuliko zara.
43
44 Hirugarren mailan Ybelle maneia dezakezu. Mugi ezazu norantza geziekin. Egin jauzi hutsune
45 barrarekin. Zenbat eta denbora gehiago eduki sakatuta, orduan eta gorago helduko zara.
46
47 Maila burutzeko duzun astia goi-ezkerraldeko ertzean ageri da.
48
49 Jasotzeko dituzun giltza edo harrien kopurua goi-eskumaldeko ertzean ageri da.
50
51 Objektu guztiak jasotzean, mailaren irteerako ataria irekitzen da (bizkorrago mugitzen da). Bertara
52 denboraz heltzea lortu behar duzu, eta behin honen azpian zaudela jauzi egin mailatik irteteko.
53
54 Maila errazegiak edo zailegiak iruditzen bazaizkizu, zailtasun maila aldatu hautesleiho nagusian (Aukerak > Zailtasuna).
55
56 3. HCed
57
58 HCed Holotz's Castle-ren maila-sorgailua da.
59
60 Abiarazteko:
61 - Linuxpean, egin './holotz-castle-editor'.
62
63 - Windowspean, egin klik bikoitza 'holotz-castle-editor.exe' fitxategian.
64
65 Leihoa:
66
67 Leihoaren izenburua uneko maila gordetzeko erabiliko den fitxategiaren izena da.
68
69 Ezkerraldean sorgailuaren ikurrak ageri dira:
70
71 - Zoru arrunta
72 - Zoru jarraia
73 - Eskailera
74 - Barra
75 - Zoru hauskorra
76 - Objektua
77 - Soka
78 - Hasierako lekua
79 - Amaierako lekua
80 - Aurkariak
81 - Gorde
82 - Istorioa Eskuratu/Sortu
83 - Irten
84
85 Ikur hauen azpian informazio hau dago:
86
87 - Mailako denbora.
88 - Grabitatea.
89 - X abiadura.
90 - Y abiadura.
91 - Jauzien potentzia.
92 - Maparen neurria (lerroak x zutabeak)
93
94 Sagua:
95
96 Ezkerreko botoia: Uneko objektua mapan margotzen du.
97 Erdiko botoia edo bi botoiak batera sakatuta: Erakuslearen azpian dagoen
98 objektua ezabatzen du.
99
100 Teklak:
101
102 c : eskuman zutabe huts bat gehitzen du
103 Maius + c : eskumako lehen zutabea ezabatzen du
104 Ktrl + c : eskuman zutabe huts bat gehitzen du
105 Ktrl + Maius + c : eskumako lehen zutabea ezabatzen du
106 + : maila burutzeko denbora tartea handitzen du (zailtasun zailean)
107 - : denbora tartea txikitzen du
108 g : grabitatea handitzen du
109 Maius g: grabitatea txikitzen du
110 x : x abiadura handitzen du
111 Maius x: x abiadura txikitzen du
112 y : y abiadura handitzen du
113 Maius y: y abiadura txikitzen du
114 j : jauziko unitate bertikalen kopurua handitzen du
115 Maius + j : jauziko unitate bertikalen kopurua txikitzen du
116
117
118 Objektu, soka, hasierako leku eta aurkariekin:
119 Ktrl - Kokalekua mapara egokitzen du.
120
121 Sokak gehitzeko:
122 Sokaren ikurra hautatu.
123 Soka mapan kokatu.
124 Ezkerreko botoia sakatuta duzula, 'Alt' tekla zapaldu.
125 Sagua goitik behera eraman sokaren luzeera zehazteko.
126 'Alt' sakatzeari utzi gabe, zapaldu 'Maius' balantza-mugimenduaren anplitudea zehazteko.
127
128 4. Ohiko galderak.
129
130 G. HC.exe-n klik bikoitza egiten dut eta ez da ezer gertatzen!
131 E. Ireki karpeta bereko stderr.txt fitxategia (edo frogatu kontsolako mezuak Linux badarabilzu).
132 Azken lerroek gertaturiko akatsa azaltzen dute. Honek konponbidea aurkitzen lagun zaitzake, agian zerrendako beste
133 galderetan dago bilatzen ari zaren erantzuna.
134
135 G. Jokua oso motel dabil, zer egin dezaket?
136 E. Hautesleiho nagusian bereizmen txikiagoa aukeratu:
137 Aukerak > Irudia > Neurria > [WWWxHHH] (hautatu balio txiki bat WWW eta HHHrentzat)
138 Agian zure irudi-txartelak 320x200 era onartzen du, honakoa aukera bikaina da jokuari
139 aspaldiko plataforma jokuen antza emateko.
140
141 G. Linuxekin ALSA erabiltzen dut, baina ez da soinurik entzuten.
142 E. ALSAk, berez, soinu guztiak isilarazten ditu. Frogatu soinuen ozentasun maila alsamixer, aumix edo kmix
143 bezalako programa batekin. Beste aplikazioren bat soinua erabiltzen ari bada, ezingo duzu ezer entzun programa
144 hori itxi arte.
145
146 G. Windowseko soinua kakazahar bat da!
147 E. Soinu Banda beste mundu batekoa ez dela jakinda :D, baliteke arazoa beste bat izatea, soinu-txartelaren
148 driverrena. Frogatu driverren bertsio eguneratu bat daukazula eta hala ez bada, eguneratu eta saiatu berriro.
149
150 G. 8 bit/piksel eran mailaren zati batzuk beltzez ageri dira!
151 E. Bai, 8 bit/piksel erarekin arazo txiki bat dugu. Lauki beltz horiek zoru jarraiari dagozkio.
152 Agian 2.0 bertsioan arazoa konponduta egongo da :D
153
154 G. Zerrenda honetan ez dut nire arazoaren konponbidea aurkitu, zer egin dezaket?
155 E. Postel bat bidali diezadakezu arazoa azalduz beherago ageri den helbide elektronikora. Ez ahaztu
156 stderr.txt fitxategia gehitzea (jokuaren karpetan dago). Zure irudi-txartelaren eta jokuko arazoaren
157 informazioa dauka.
158
159 G. Marrazkilaria/musikaria/programatzailea/ekoizlea/90-60-90-modeloa naiz eta egitasmoan lagundu nahi dut. Zer egin dezaket?
160 E. Hara, beheko helbidera postel bat bidali diezadakezu (modeloa bazara, aurrena zita bat edukitzea ezinbestekoa da :) ).
161
162
163 Juan Carlos Seijo Pérez (jacob@mainreactor.net)
0 Holotz's Castle - Manuel
1 ------------------------
2
3 1. Démarrage Rapide
4
5 Tapez:
6
7 ./holotz-castle
8
9 ...et amusez-vous!
10
11
12 1.1 Si ça ne fonctionne pas, vous aurez probablement besoin des dernières versions
13 des librairies:
14 - SDL (www.libsdl.org)
15 - SDL_image, SDL_ttf, SDL_mixer (www.libsdl.org, section librairies)
16
17 2. Brève présentaion du jeu
18
19 Pour afficher l'aide dans le menu principal ou pendant le jeu, appuyez sur F1. L'aide n'est pas disponible pendant les scènes de dialogues.
20
21 Les deux premières scènes que vous verrez en sélectionnant 'Nouvelle partie' dans le menu principal sont un dialogue entre Ybelle et Ludar, les deux héros du jeu.
22
23 Vous pouvez sauter les bulles de dialogues en appuyant sur la barre d'espace. Vous pouvez sauter une scène entière en appuyant sur Entrée.
24
25 Vous pouvez revenir au menu principal à n'importe quel moment du jeu en pressant Echap mais, ensuite, si vous sélectionnez l'option 'Continuer la partie' vous reprendrez le jeu au début du dernier niveau joué.
26 Un conseil: Si vous voulez enregistrer la partie, faites-le quand vous venez de commencer un niveau.
27
28 Pour mettre le jeu en pause et vous reposer, appuyez sur 'p'. Pressez 'p' une seconde fois pour revenir dans le jeu.
29
30 À partir du troisième niveau, vous pourrez contrôler Ybelle. Vous pourrez le faire bouger en utilisant les flèches directionnelles et le faire sauter en appuyant sur la barre d'espace.
31 Plus vous appuierez longtemps, plus vous pourrez sauter haut.
32
33 Le temps disponible pour finir le niveau est visible dans le coin supérieur gauche de l'écran.
34
35 Les objets restants à trouver pour débloquer la sortie du niveau sont affichés dans le coin supérieur droit de l'écran.
36
37 Quand vous aurez collecté tous les objets, la sortie sera activée (cela bougera plus vite) et vous devrez aller jusqu'à elle et sauter quand vous serez en dessous pour sortir du niveau.
38
39 Si vous trouvez les niveaux trop difficiles ou trop faciles, essayez d'ajuster le niveau de difficulté dans le menu principal (Options > Difficulté).
40
41 3. HCed
42
43 HCed est l'éditeur de niveau de Holotz's Castle.
44
45 Pour le lancer:
46 - Sous Linux, tapez './holotz-castle-editor'
47
48 - Sous Windows, double-cliquez sur l'icône holotz-castle-editor.exe
49
50 Fenêtre principale:
51
52 Le titre de la fenêtre contient le nom du fichier qui sera utilisé quand vous enregistrerez le niveau courant.
53
54 Sur le côté gauche, on peut voir les icônes suivantes:
55
56 - Sol normal
57 - Sol continu
58 - Échelle
59 - Barre
60 - Sol cassable
61 - Objet
62 - Corde
63 - Point de départ
64 - Sortie
65 - Ennemis
66 - Sauvegarde
67 - Charger/Créer une histoire
68 - Quitter
69
70 En dessous, il y a les indicateurs suivants:
71
72 - Temps du niveau.
73 - Gravité.
74 - Vitesse en X.
75 - Vitesse en Y.
76 - Puissance de saut.
77 - Taille de la carte (lignes x colonnes)
78
79 Souris:
80
81 Bouton gauche: Place l'objet choisi dans la carte.
82 Bouton du mileu ou boutons gauche & droit simultanément: Supprime l'objet sous le pointeur.
83
84 Clavier:
85
86 c : Ajoute une colonne vide sur la droite
87 Shift + c : Supprime une colonne sur la droite
88 Ctrl + c : Ajoute une colonne vide sur la gauche
89 Ctrl + Shift + c : Supprime une colonne sur la gauche
90 r : Ajoute une ligne vide en bas
91 Shift + r : Supprime une ligne en bas
92 Ctrl + r : Ajoute une ligne vide en haut
93 Ctrl + Mayús + r : Supprime une ligne en haut
94 + : Augmenter le temps (le temps sera celui du niveau en mode difficile)
95 - : Diminuer le temps
96 g : Augmenter la gravité
97 Shift + g: Diminuer la gravité
98 x : Augmenter la vitesse en x
99 Shift + x: Diminuer la vitesse en x
100 y : Augmenter la vitesse en y
101 Shift + y: Diminuer la vitesse en y
102 j : Augmenter la puissance de saut
103 Shift + j : Diminuer la puissance de saut
104
105 Avec les objets/cordes/point de départ/ennemis:
106 Ctrl - Déplacer l'objet.
107
108 Ajouter une corde:
109 Choisir l'icône de corde.
110 Positionner la corde sur la carte.
111 Sans relâcher le bouton gauche de la souris, appuyer sur 'Alt'.
112 Bouger la souris vers le haut ou le bas pour choisir la longueur de la corde.
113 Sans relâcher le bouton gauche de la souris, appuyer sur 'Shift' pour choisir la période de balancement de la corde.
114
115 4. FAQ
116
117 Q. Je double-clique sur HC.exe mais rien ne se passe!
118 A. Ouvez le fichier nommé stderr.txt dans le même dossier (ou regardez les messages
119 de la console sous Linux).
120 Les dernières lignes indiquent le problème. Cherchez une solution dans la suite de
121 cette FAQ
122
123 Q. Le jeu est lent que puis-je faire?
124 A. Choisissez une résolution plus faible dans le menu principal:
125 Options > Vidéo > Taille > [mode]
126 Peut-être que votre carte graphique supporte le mode 320x200, vous avez la chance de
127 revivre les sensations des jeux vidéos à l'ancienne.
128
129 Q. Je suis sous Linux mais ALSA ne laisse entendre aucun son.
130 A. Par défaut ALSA coupe le son. Essayez de vérifier le volume avec alsamixer ou aumix
131 ou kmix.
132 Si une autre application utilise le son, vous ne pourrez pas entendre de son avant
133 de l'avoir fermer.
134
135 Q. Le son sous Windows est médiocre!
136 A. Malgré le fait que la bande son elle même n'est pas terrible :D, peut-être que le
137 problème provient des pilotes de la carte son. Récupérez la dernière version
138 de ceux-ci et réessayez.
139
140 Q. En mode 8 bpp mode des parties du niveau sont toutes noires!
141 A. Cette erreur est corrigée dans les version 1.2 et plus, récupérez la
142 dernière version sur Internet (www.mainreactor.net).
143
144 Q. Je n'ai pas trouvé de réponses à mon problème dans cette FAQ, que puis-je faire?
145 A. Vous pouvez m'envoyer à l'adresse qui est à la fin de cette FAQ. N'oubliez pas
146 de joindre le fichier nommé stderr.txt qui est dans le même dossier que
147 l'éxécutable (HC.exe). Il contient toutes les informations à propos de votre
148 carte graphqiue et le problème avec le jeu.
149
150 Q. Je suis un artiste/musicien/programmeur/producteur/modèle-90-60-90 et je veux
151 contribuer à la cause. Que puis-je faire?
152 A. Oh, vous pouvez pouvez me contacter à l'adresse en dessous (si vous êtes mannequin,
153 nous prendrons un rendez-vous personnel avant :) )
154
155
156 Juan Carlos Seijo Pérez (jacob@mainreactor.net)
0 Il castello di Holotz - Manuale
1 ------------------------
2
3 STORICO DELLE EDIZIONI:
4 08/02/2005 - Seconda edizione
5 24/10/2004 - Prima editione
6
7 1. Guida volece
8
9 1.1. Windows
10
11 1. Decomprimi HC_win32-1.3.zip
12 2. Dopo l'estrazione troverari una cartella 'HC'.
13 3. Entra in quella cartella.
14 4. Fai doppio click su holotz-castle.exe
15 5. Divertiti!
16
17 NOTA: Per creare un collegamento al programma è necessario riempire la casella "Esegui in"
18 con il percorso completo della cartella del gioco.
19
20 1.2. GNU/Linux (da codice sorgente)
21
22 1. Esegui 'tar -zxf HC_JLib_Linux_Win32-1.3.tar.gz' (senza gli apici) da terminale
23 2. Segui le istruzioni nel file README.txt nella directory 'HC_JLib_Linux_Win32-1.3'.
24 3. Scrivi 'cd Games/HolotzCastle' da terminale
25 4. Esegui './holotz-castle'
26 5. Divertiti!
27
28 2. Introduzione
29
30 Per vedere la schermata di aiuto nel menù principale o mentre stai giocando premi F1. L'aiuto non è disponibile
31 durante i dialoghi.
32
33 Le prime due scene che vedrai appena dopo avere selezionato 'Nuova partita' dal menù principale è un dialogo tra
34 Ybelle e Ludar, i personaggi principali del gioco.
35
36 Puoi saltare le singole battute dei dialoghi prementi 'spazio'; per saltare dialoghi interi premi 'invio'.
37
38 In ogni momento puoi tornare al menù principale e da lì, premendo 'Continua partita' ricomincerai da dove hai interrotto
39 la partita. È buona regola salvare una partita subito dopo essere entrato in un nuovo livello.
40
41 Per mettere il gioco in pausa ed andare a fare due passi premi 'p'. Ripremi 'p' quando vuoi ricominciare
42 a giocare.
43
44 Al terzo livello potrai controllare Ybelle. Puoi muoverlo con i tasti 'freccia' e farlo saltare con il tasto 'spazio'.
45 Più tieni premuto il tasto 'spazio' e più alto sarà il salto.
46
47 Il tempo disponibile per completare il livello è sempre visibile nell'angolo in alto a sinistra dello schermo.
48
49 Gli oggetti ancora da raccogliere per poter uscire dal livello sono mostrati nell'angolo in alto a destra dello
50 schermo.
51
52 Quando avrai raccolto tutti gli oggetti si attiverà l'uscita. Dovrai spostarti verso di essa e quando ci sarai sotto
53 salta e passerai al quadro successivo.
54
55 Se trovi uno o più livelli troppo difficili puoi regolare la difficoltà dal menù principale (Opzioni > Difficoltà).
56
57 3. HCed
58
59 HCed è l'editor di livelli per "Holotz's Castle".
60
61 Per eseguirlo:
62 - In GNU/Linux, lancia './holotz-castle-editor' da terminale
63
64 - In Windows, fai doppio-click sull'icona holotz-castle-editor.exe
65
66 Finestra principale:
67
68 Nel titolo della finestra ci sarà il nome del file in cui sarà salvato il livello.
69
70 Nella parte sinistra della finestra ci sono le seguenti icone:
71
72 (Non trodotto)
73 - Normal floor
74 - Continuous floor
75 - Ladder
76 - Bar
77 - Breakable floor
78 - Object
79 - Rope
80 - Start position
81 - End position
82 - Enemies
83 - Save
84 - Load/Create story
85 - Exit
86
87 Al di sotto ci sono questi indicatori:
88
89 (Non trodatto)
90 - Level time.
91 - Gravity.
92 - X Speed.
93 - Y Speed.
94 - Jump amount.
95 - Map size (rows x columns)
96
97 Mouse:
98
99 Tasto sinistro: disegna l'oggetto selezionato sulla mappa.
100 Tasto centrale (o tasto destro e sinistro premuti insieme): cancella l'oggetto sotto il puntatore.
101
102 Tasti:
103
104 (non tradotto)
105 c : adds blank column to the right
106 Shift + c : removes column to the right
107 Ctrl + c : adds blank column to the left
108 Ctrl + Mayús + c : removes column to the left
109 r : adds blank row bellow
110 Shift + r : removes row bellow
111 Ctrl + r : adds blank row upside
112 Ctrl + Mayús + r : removes row upside
113 + : increase time (based upon hardest difficulty level)
114 - : decrease time
115 g : increase gravity
116 Shift + g: decrease gravity
117 x : increase x speed
118 Shift + x: decrease x speed
119 y : increase y speed
120 Shift + y: decrease y speed
121 j : increase jump amount
122 Shift + j : decrease jump amount
123
124 With object/rope/start pos./enemy:
125 Ctrl - Adjusts to map.
126
127 Per aggiungere corde:
128 Seleziona l'icona della corda.
129 Posiziona la corda nella mappa.
130 *Senza* rilasciare il tasto sinistro del mouse premi il tasto 'Alt'
131 Muovi in sù o in giù il mouse per allungare o accorciare la corda.
132 *Senza* rilasciare il tasto sinistro del mouse premi 'Shift'
133 per selezionare il periodo d'oscillazione della corda.
134
135 4. FAQ -- Domande più frequenti
136
137 D. Faccio doppio-click su HC.exe ma non succede nulla!
138 R. Apri file 'stderr.txt' nella cartella del gioco (o controlla i messaggi sulla console in GNU/Linux).
139 L'ultima riga ti dirà il problema; cerca la soluzione in questo documento.
140
141 D. Il gioco è lento. Cosa posso fare?
142 R. Scegli una risoluzione video più bassa dal menù principale:
143 Opzioni > Video > Dimensioni > [modo]
144 Forse la tua scheda grafica supporta la modalità 320x200. È un'occasione
145 per rivivere le senzazioni dei grandi giochi del passato :).
146
147 D. Sono sotto GNU/Linux ed uso ALSA ma non sento nessun suono.
148 R. Per impostazioni predefinite ALSA azzera il suono. Prova a controllare il livello dei volumi
149 con i comandi 'alsamixer', 'aumix' oppure 'kmix'. Se un'altra applicazione sta usando la scheda audio
150 non potrai ascoltare i suoni de 'Il castello di Holotz' finchè non chiuderai quel programma.
151
152 D. I suoni sotto Windows sono orribili!
153 R. A parte il fatto che la colonna sonora del gioco non è tutto sto granchè :D, potrebbe essere un problema
154 di driver. Controlla di avere l'ultima versione disponibile dei driver.
155
156 D. Nella modalità ad 8bpp alcune zone del livello sono totalmente nere!
157 R. Questo errore è stato corretto nelle versioni 1.2 e superiori, controlla il sito del gioco (www.mainreactor.net)
158 per avere l'ultima versione disponibile.
159
160 D. Non trovato risposta alle mie domande, cosa dovrei fare?
161 R. Puoi mandarmi una mail all'indirizzo scritto sotto. Non dimenticarti di allegare il file 'stderr.txt' che si
162 trova nella stessa cartella del gioco. Il file contiene informazioni sulla tua scheda grafica e sul tuo problema.
163
164 D. Sono un artista/musicita/programmatore/produttore/modella-90-60-90 e vorrei contribuire alla causa. Come posso farlo?
165 R. Oh, puoi inviarmi una mail all'indirizzo qui sotto (se sei una modella dovremmo prima avere un appuntamento :) )
166
167 Juan Carlos Seijo Pérez (jacob@mainreactor.net)
168
169 -- Traduzione in italiano: Federico 'hs1' Tolomei hardskinone chiocciola autistici punto org
0 Holotz's Castle - Руководство
1 ------------------------
2
3 1. Быстрый запуск
4
5 Выполните команду:
6
7 ./holotz-castle
8
9 ...и наслаждайтесь!
10
11
12 1.1 Если это не работает, то, возможно, потребуется установить более новые версии библиотек:
13 - SDL (www.libsdl.org)
14 - SDL_image, SDL_ttf, SDL_mixer (www.libsdl.org, libraries section)
15
16 2. Игра
17
18 Чтобы получить справку, нажмите F1 во время игры или в главном меню. Во время диалогов справка недоступна.
19
20 Первые две сцены, которые вы увидите, начав новую игру - разговор Ивонны и Людара, главных героев игры.
21
22 Реплики в диалоге можно пропускать, нажимая клавишу "Пробел". Пропустить целую сцену можно нажав на "Ввод".
23
24 В любой момент игры можно выйти в главное меню и вернуться к игре с помощью команды 'Продолжить игру'. Игра продолжится с начала текущего уровня. Поэтому, лучше сохранять игру сразу после перехода на новый уровень.
25
26 Чтобы прервать игру и передохнуть, нажмите 'p'. Если нажать 'p' снова, игра продолжится.
27
28 На третьем уровне вы можете управлять Ивонной. Используйте стрелки для движения и "пробел" для прыжков. Чем дольше нажатие на "пробел", тем выше прыжок.
29
30 Оставшееся на прохождение уровня время отображается в верхнем-левом углу экрана.
31
32 Необходимые для переход на следующий уровень предметы отображаются в верхнем-правом углу экрана.
33
34 Когда все предметы собраны, открывается выход. Пдойдите к нему и подпрыгните, чтобы покаинуть уровень.
35
36 Если уровни кажутся вам слишком трудными или слишком простыми, изменить уровень сложности в главном меню (Настройки > Сложность).
37
38 3. HCed
39
40 HCed - редактор уровней для игры Holotz's Castle.
41
42 Для запуска:
43 - В ОС Linux, запустите './holotz-castle-editor'
44
45 - В ОС Windows, дважды щелкните значок holotz-castle-editor.exe
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 - Скорость по оси X.
72 - Скорость по оси Y.
73 - Сила прыжка.
74 - Размер уровня (рядов x колонок)
75
76 Мышь:
77
78 Левая кнопка: Помещает текущий объект на карту.
79 Средняя или правая и левая кнопки вместе: Удалить объект.
80
81 Клавиатура:
82
83 c : добавить пустую колонку справа
84 Shift + c : удалить колонку справа
85 Ctrl + c : добавить пустую колонку слева
86 Ctrl + Shift + c : удалить колонку слева
87 r : добавить пустой ряд снизу
88 Shift + r : удалить ряд снизу
89 Ctrl + r : добавить пустой ряд сверху
90 Ctrl + Shift + r : удалить ряд сверху
91 + : увеличить время (на основе самого высокого уровня сложности)
92 - : уменьшить время
93 g : увеличить притяжение
94 Shift + g: уменьшить притяжение
95 x : увеличить скорость по оси x
96 Shift + x: уменьшить x speed
97 y : увеличить скорость по оси y
98 Shift + y: уменьшить y speed
99 j : увеличить силу прыжка
100 Shift + j : уменьшить силу прыжка
101
102 Для объектов/верёвок/нач. позиций/врагов:
103 Ctrl - Подгонка к карте.
104
105 Добавление верёвок:
106 Выберите значок верёвки.
107 Расположите верёвку на карте.
108 Нажмите 'Alt', не отпуская левой кнопки мыши.
109 Двигая курсором мыши задайте длину верёвки.
110 Не отпуская левой кнопки мыши нажмите 'Shift', чтобы отрегулировать период качания верёвки.
111
112 4. ЧаВо
113
114 Q. Я дважды щёлкаю значок HC, но ничего не происходит!
115 A. Откройте файл stderr.txt в том же каталоге (или прочтите сообщения в консоли Linux).
116 В последних строках должно быть описание проблемы. Прочтите раздел ЧаВо, чтобы найти
117 решение.
118
119 Q. Игра работает слишком медленно?
120 A. Выберите видеорежим с меньшим разрешением:
121 Настройка > Изображение > Размер > [режим]
122 Возможно, ваша видеокарта пожерживает режим 320x200. Он позволит вам
123 вспомнить времена старинных видеоигр.
124
125 Q. Я использую Linux с драйверами ALSA, не не слышу звука.
126 A. По умолчанию ALSA заглушает звук. Проверьте громкость с помощью alsamixer, aumix или gmix.
127 Если устройтво вывода звука заблокировано другой программой, то звук появится только после её
128 закрытия.
129
130 Q. Неправильный звук в Windows!
131 A. Хотя звуки в игре не очень хорошо слышны сами по себе :D, проблема может заключаться в
132 драйверах вашей звуковой карты. Поставтьте самую новую версию.
133
134 Q. В режиме 8-битного цвета некоторые части уровней выглядят чёрными!
135 A. Эта ошибка исправлена, начиная с версии v1.2, загрузите новую версию со страницы (www.mainreactor.net).
136
137 Q. здесь нет ответа на мой вопрос. Что делать?
138 A. Напишите мне по адресу внизу. Не забудьте приложить файл stderr.txt, который находится в той же
139 папке, где и исполняемый файл (HC.exe). В нём содержится информация о вашей видеокарте и возникшей проблеме.
140
141 Q. Я художник/музыкант/программист/продюсер/фотомодель 90-60-90 и хочу помочь. Что делать?
142 A. Напишите мне по адресу внизу.(Если вы модель, то надо сначала встретиться :) )
143
144
145 Хуан Карлос Сейжо Перес (jacob@mainreactor.net)
0 Holotz's Castle - Manual
1 ------------------------
2
3 HISTORIA:
4 24/10/2004 - Första utgåvan.
5 08/02/2005 - Andra utgåvan.
6
7 1. Snabbstart
8
9 1.1. Windows
10
11 1. Extrahera HC_win32-1.3.zip
12 2. Efter extraheringen skapas en mapp med namnet HC.
13 3. Öppna och utforska mappen.
14 4. Dubbelklicka på filen holotz-castle.exe
15 5. Njut!
16
17 NOTERING: To create an application short cut is necessary to fill the field 'Run in' the
18 full path to the HC folder, in the short cut properties dialog.
19
20 1.2. Linux (källkod)
21
22 1. Gör 'tar -zxf HC_JLib_Linux_Win32-1.3.tar.gz' (utan citationstecken)
23 2. Följ instruktionerna i filen README.txt i katalogen 'HC_JLib_Linux_Win32-1.3'.
24 3. Gör 'cd Games/HolotzCastle'
25 4. Gör './holotz-castle'
26 5. Njut!
27
28 2. Spelinstruktioner
29
30 Tryck F1 i huvudmenyn eller under spelets gång för att visa hjälprutan. Den är dock inte tillgänglig vid dialoger.
31
32
33 Efter att du tryckt på 'Nytt spel' får du se de första två scenerna där huvudkaraktärerna Ybelle och Ludar för en dialog med varandra.
34
35 Du kan hoppa över pratbubblorna genom att trycka mellanslag. Du kan hoppa över hela scenen genom att trycka enter.
36
37 Under spelets gång kan du när som helst växla till huvudmenyn, men ifall du sedan trycker på 'Fortsätt spel' kommer du starta
38 i början av den senast spelade banan.
39 Med detta sagt är en tumregel: om du vill spara, gör det precis efter att du påbörjat en ny bana.
40
41 Tryck 'p' för att pausa spelet och vila. Tryck 'p' igen för att återgå till spelet.
42
43 På tredje banan kan du styra Ybelle. Försöka styra honom med piltangenterna. Försök hoppa med mellanslag.
44 Ju längre du håller ned mellanslag, desto högre kommer karaktären att hoppa.
45
46 I skärmens översta vänstra hörn syns den tid som återstår för att klara banan.
47
48 I skärmens översta högra hörn syns det antal objekt som återstår för att låsa upp banans utgång.
49
50 När du samlat alla objekt aktiveras utgången (den rör sig fortare). Ställ dig under den och hoppa för att avsluta banan.
51
52 Om du tycker att banorna är för lätta eller svåra kan du ändra svårighetsgraden i huvudmenyn (Inställningar > Svårighetsgrad).
53
54 3. HCed
55
56 HCed heter Holotz Castles banredigerare.
57
58 För att starta den:
59 - I Linux, kör './holotz-castle-editor'
60
61 - I Windows, dubbelklicka på ikonen holotz-castle-editor.exe
62
63 Huvudfönstret:
64
65 Fönstrets titel innehåller filen som används då du sparar den aktuella banan.
66
67 På vänster sida syns ikonerna:
68
69 - Normal floor
70 - Continuous floor
71 - Stege
72 - Bar
73 - Breakable floor
74 - Objekt
75 - Rep
76 - Startposition
77 - Slutposition
78 - Fiender
79 - Spara
80 - Ladda/Skapa handling
81 - Avsluta
82
83 Under dessa syns följande skyltar:
84
85 - Level time.
86 - Gravitation.
87 - X-hastighet.
88 - Y-hastighet.
89 - Jump amount.
90 - Map size (rader x kolumner)
91
92 Mus:
93
94 Vänster knapp: Draws the current object in the map.
95 Central button or left & right buttons at the same time: Deletes the object under the pointer.
96
97 Tangentknappar:
98
99 c : adds blank column to the right
100 Shift + c : removes column to the right
101 Ctrl + c : adds blank column to the left
102 Ctrl + Mayús + c : removes column to the left
103 r : adds blank row bellow
104 Shift + r : removes row bellow
105 Ctrl + r : adds blank row upside
106 Ctrl + Mayús + r : removes row upside
107 + : increase time (based upon hardest difficulty level)
108 - : decrease time
109 g : increase gravity
110 Shift + g: decrease gravity
111 x : increase x speed
112 Shift + x: decrease x speed
113 y : increase y speed
114 Shift + y: decrease y speed
115 j : increase jump amount
116 Shift + j : decrease jump amount
117
118 With object/rope/start pos./enemy:
119 Ctrl - Adjusts to map.
120
121 Att lägga till rep:
122 Select rope icon.
123 Position rope in map.
124 Without realeasing the left mouse button, press 'Alt'.
125 Mover updown mouse to set rope length.
126 Without realeasing the left mouse button, press 'Shift' to adjust the rope period.
127
128 4. Frågor och svar
129
130 F. Jag dubbelklickar på HC.exe men ingenting sker!
131 S. Öppna filen kallad stderr.txt i samma mapp (eller kontrollera terminalmeddelanden i Linux).
132 De sista raderna talar om varför spelet hade problem att starta. Hitta en lösning till ditt
133 problem bland de återstående frågorna och svaren.
134
135 F. Spelet går segt. Lösning?
136 S. Välj en lägre skärmupplösning i huvudmenyn:
137 Inställningar > Skärm > Upplösning > [storlek].
138 Ditt grafikkort kanske stöder upplösningen 320x200. Se det som ett
139 tillfälle att återuppliva känslor från de gammalmodiga tv-spelen.
140
141 F. Jag kör Linux med ALSA men kan inte höra något ljud. Vad göra?
142 S. Av standard tystar ALSA ned ljudet. Testa att kontrollera volymen med alsamixer, aumix eller kmix.
143 Om ett annat program använder ljudenheten kommer du inte kunna höra annat ljud förrän du stänger
144 ned det programmet.
145
146 F. Ljudet i Windows är fejkat!
147 S. Trots det faktum att ljudspåret i sig självt inte är särskilt hörbart :D kan problemet orsakas av
148 drivrutinerna till ditt ljudkort. Uppdatera dem och försök igen.
149
150 F. Ifall jag spelar med 8 bitars färgdjup är delar av banan helt svarta!
151 S. Det där felet har blivit åtgärdat sedan version 1.2, gå till spelets webbplats (www.mainreactor.net) för att hämta hem den senaste utgåvan.
152
153 F. Jag hittade inget svar till mitt problem bland dessa frågor och svar, vad ska jag göra?
154 S. Du kan skicka ett e-brev till e-postadressen nedanför. Glöm inte att vidhäfta filen kallad
155 stderr.txt vilken finns i samma mapp som den binära filen (HC.exe). Den innehåller information
156 om ditt grafikkort och problemet med spelet.
157
158 F. Jag är en konstnär/musiker/programmerare/producent/90-60-90-modell och jag vill bidra till detta spel. Vad kan jag göra?
159 S. Oh, Du kan skicka ett e-brev till e-postadressen nedanför (om du är modell måste vi dejta först :) )
160
161
162 Juan Carlos Seijo Pérez (jacob@mainreactor.net)
0 Holotz's Castle - Руководство
1 ------------------------
2
3 1. Швидкий запуск
4
5 Виконайте команду:
6
7 ./holotz-castle
8
9 ...и насолоджуйтеся!
10
11
12 1.1 Якщо це не працює, то, можливо, необхідно встановити більш нові версії бібліотек:
13 - SDL (www.libsdl.org)
14 - SDL_image, SDL_ttf, SDL_mixer (www.libsdl.org, libraries section)
15
16 2. Гра
17
18 Щоб отримати довідку, натисніть F1 під час гри або в головному меню. Під час діалогів довідка недоступна.
19
20 Перші две сцени, які ви побачите, зпочатком нової гри - ррозмова Івонни в Людара, головних героїв гри.
21
22 Репліки в диалозі можна пропускати, натискаючи клавішу "Пробіл". Пропустити цілу сцену можна нанатискаючи на "Введення".
23
24 В будь-який момент гри можна вийти в головне меню и повернутися до гри з допомогою команди 'Продовжити гру'. Гра продовжиться з початку поточного рівня. Тому, краще зберігати гру відразу після переходу на новий рівень.
25
26 Щоб перервати гру та перепочити, натисніть 'p'. Якщо натиснути 'p' снову, гра продовжиться.
27
28 На третьому рівні ви можете управляти Івонною. Використовуйте стрілки для руху і "пробіл" для прижків. Чим довше натискання на "пробіл", тим вище прижок.
29
30 Час, який залишається для проходження рівня відображується у верхньому-лівому кутку екрана.
31
32 Необхідні для переходу на наступний рівень предмети відображаються у верхньому-правому кутку екрана.
33
34 Коли всі предмети зібрано, відкривається вихід. Підійдіть до нього та підпригніть, щоб покинути рівень.
35
36 Якщо рівні здаються вам занадто важкими або занадто простими, змінити рівень складності в головному меню (Налаштування > Складність).
37
38 3. HCed
39
40 HCed - редактор рівней для гри Holotz's Castle.
41
42 Для запуску:
43 - В ОС Linux, запустіть './holotz-castle-editor'
44
45 - В ОС Windows, зробіть подвійне клацання на значку holotz-castle-editor.exe
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 - Швидкість по осі X.
72 - Швидкість по осі Y.
73 - Сила прижка.
74 - Розмір рівня (рядів x колонок)
75
76 Миша:
77
78 Ліва кнопка: Переміщує поточний об'єкт на карту.
79 Середня або права та ліва кнопки разом: Видалити об'єкт.
80
81 Клавіатура:
82
83 c : добавити пусту колонку справа
84 Shift + c : видалити колонку справа
85 Ctrl + c : добавити пусту колонку зліва
86 Ctrl + Shift + c : видалити колонку зліва
87 r : добавити пустий ряд знизу
88 Shift + r : видалити ряд знизу
89 Ctrl + r : добавити пустий ряд зверху
90 Ctrl + Shift + r : видалити ряд зверху
91 + : збільшити час (на основі найвищого рівня складності)
92 - : зменьшити час
93 g : збільшити тяжіння
94 Shift + g: зменьшити тяжіння
95 x : збільшити швидкість по осі x
96 Shift + x: зменьшити x speed
97 y : збільшити швидкість по оси y
98 Shift + y: зменьшити y speed
99 j : збільшити силу прижка
100 Shift + j : зменьшити силу прижка
101
102 Для об'єктів/мотузок/поч. позицій/ворогів:
103 Ctrl - Підрівнювання к карте.
104
105 Добавлення мотузок:
106 Виберіть значок мотузки.
107 Розташуйте мотузку на карте.
108 Натисніть 'Alt', не відпускаючи лівої кнопки миші.
109 Двигаючи курсором миші задайте довжину мотузки.
110 Не відпускаючи лівої кнопки миші натисніть 'Shift', щоб відрегулювати період качання мотузки.
111
112 4. ЧаПи
113
114 Q. Я роблю подвійне клацання на значок HC, але нічого не відбувається!
115 A. Відкрийте файл stderr.txt в тому ж каталозі (або прочитайте повідомлення в консолі Linux).
116 В останніх рядках повинен бути опис проблеми. Прочитайте розділ ЧаПи, щоб нзайти
117 рішення.
118
119 Q. Гра працює занадто повільно?
120 A. Виберіть відеорежим з меньшою роздільною здатністю:
121 Налаштування > Зображення > Розмір > [режим]
122 Можливо ваша відеокарта підтримує режим 320x200. Він дозволить вам
123 пригадати часи перших відеоігр.
124
125 Q. Я використовую Linux з драйверами ALSA, але не чую звука.
126 A. Типово ALSA заглушує звук. Перевірте гучність з допомогою alsamixer, aumix або gmix.
127 Якщо пристрій виводу звука заблоковано іншою программою, то звук з'явиться тільки після її
128 завершення.
129
130 Q. Невірний звук у Windows!
131 A. Хоча звуки у грі не досить добре чутно і так :D, проблема може заключатися в
132 драйверах вашої звукової карти. Поставте найновішу версію.
133
134 Q. В режимі 8-бітного кольору деякі частини рівнів виглядають чорними!
135 A. Ця помилка виправлена починаючи з версії v1.2, завантажте нову версію зі сторінки (www.mainreactor.net).
136
137 Q. Тут не має відповіді на моє запитання. Що робити?
138 A. Напишіть мені за адресою знизу. Не забудьте додати файл stderr.txt, який знаходиться в тому ж
139 каталозі, де й програмний файл (HC.exe). В ньому є інформація про вашу відеокарту та виникші проблеми.
140
141 Q. Я художник/музикант/програміст/продюсер/фотомодель 90-60-90 та хочу допомогти. Що робити?
142 A. Напишіть мені за адресою знизу.(Якщо ви модель, то потрібно спочатку зустрітися :) )
143
144
145 Хуан Карлос Сейжо Перес (jacob@mainreactor.net)
0 .TH "Holotz's Castle Editor" "6" "28.01.2005" "Miriam Ruiz" ""
1 .SH "NAME"
2 holotz\-castle\-editor \- editor for holotz\-castle game
3 .SH "SYNOPSIS"
4 .B holotz\-castle\-editor [\fI\-f\fR] [\fI\-w\fR] [\fI\-\-fps nn\fR] [\fI\-mWWxHHxBPP\fR] [\fI\-r RR\fR] [\fI\-c CC\fR] [\fI\-t theme\fR] \fI<story> <nr>\fR
5 .SH "DESCRIPTION"
6 A great mistery is hidden beyond the walls of Holotz's Castle. ¿Will you be able to help Ybelle and Ludar to scape alive from the castle?
7
8 Use the editor to design new levels for this game!
9 .SH "USAGE"
10 You can use the following keys while working with the editor:
11
12 \- Page Down: Next level in the story (or a new one if it doesn't exist).
13 \- Page Up: Previous level in the story.
14 \- 'c': Increase the number of columns from the right.
15 \- CTRL\-'c': Increase the number of columns from the left
16 \- SHIFT\-'c': Decrease the number of columns from the right.
17 \- SHIFT\-CTRL\-'c': Decrease the number of columns from the left.
18 \- 'r': Increase the number of rows from below.
19 \- CTRL\-'r': Increase the number of rows from above.
20 \- SHIFT\-'r': Decrease the number of rows from below.
21 \- SHIFT\-CTRL\-r: Decrease the number of rows from Above.
22 \- '+': Increase level time.
23 \- '\-': Decrease level time.
24 \- '1': Select 'floor' tool.
25 \- '2': Select 'continuous floor' tool.
26 \- '3': Select 'stairs' tool.
27 \- '4': Select 'bar' tool.
28 \- '5': Select 'breakable floor' tool.
29 \- '6': Select 'key' tool.
30 \- '7': Select 'rope' tool
31 \- '8': Select 'starting character's position' tool.
32 \- '9': Select 'exit position' tool.
33 \- '0': Select 'enemy' tool.
34 \- 's': Save.
35 \- CTRL\-'q': Quit editor.
36 \- Arrow keys: Move around in the map.
37 \- 'g': Increase gravity strength.
38 \- SHIFT\-'g': Decrease gravity strength.
39 \- 'x': Increase main character's speed in axis.
40 \- SHIFT\-'x': Decrease main character's speed in X axis.
41 \- 'y': Increase main character's speed in Y axis.
42 \- SHIFT\-'y': Decrease main character's speed in Y axis.
43 \- 'j': Increase the number of cells that the player can jump vertically.
44 \- SHIFT\-'j': Decrease the number of cells that the player can jump vertically.
45
46 Other features:
47 \- When adding an item to the map, if you press CTRL key it is adjusted to a cell.
48 \- To adjust a rope's lenght, you select it and, while still pressing mouse button, press ALT key and drag the mouse vertically until getting the desired length.
49 \- To adjust a rope's oscillation amplitude, you must select it and, keeping mouse button pressed, press SHIFT key. Real time amplitude is not shown, as it is determined taking into account the distance in vertical to the rope when releasing mouse button.
50
51 .SH "OPTIONS"
52 These command line options are available:
53 \-f Full Screen.
54 \-w Windowed.
55 \-\-fps nn Run the game at nn frames per second (fps).
56 \-mWWxHHxBPP Run in video mode set by WW pixels of width, HH pixels of height and BPP bits per pixel (eg. \-m640x480x16).
57 \-r RR Crete map with RR rows of height.
58 \-c CC Crete map with CC columns of width.
59 \-t theme Use theme named 'theme'.
60 <story> <nr> Load level nr of the story called 'story'.
61 .SH "AUTHOR"
62 This manual page was written for the Debian GNU/Linux system by Miriam Ruiz
63 <little_miry@yahoo.es> (but may be used by others, of course)
0 .TH "Holotz's Castle" "6" "28.01.2005" "Miriam Ruiz" ""
1 .SH "NAME"
2 holotz\-castle \- platform game with high dosis of mistery
3
4 .SH "SYNOPSIS"
5 .B holotz\-castle [\fI\-f\fR] [\fI\-w\fR] [\fI\-\-fps nn\fR] [\fI\-mWWxHHxBPP\fR]
6 .SH "DESCRIPTION"
7 A great mistery is hidden beyond the walls of Holotz's Castle. ¿Will you be able to help Ybelle and Ludar to scape alive from the castle?
8
9 Test your dexterity with this tremendously exciting platform game!
10 .SH "USAGE"
11 You'll get an options' menu as soon as the game starts, with the following options:
12
13 \- Continue Game: You can continue playing the game if you have interrupted it with escape key.
14 \- New Game: You can start playing the game right from the beginning.
15 \- Help: You get a general help text on the game. You can use escape key for leaving that screen.
16 \- Options: You'll get a new menu from which you can set video, sound, dificulty and language options. You can leave each menu by using the escape key.
17 \- Load: You can continue playing the game from a previously saved adventure.
18 \- Save: With this option you can save the current adventure.
19 \- Exit: Leave the game.
20
21 During the game, you can use the following keys:
22
23 \- Arrow keys: Move character
24 \- Space key: Jump / Skip dialog
25 \- Enter/Return key: Skip dialog sequence
26 \- F1: Display help text while playing
27 \- Escape key: Hides help screen.
28
29 Aside from that the game easy to play, no need for a manual!
30
31 .SH "OPTIONS"
32 These command line options are available:
33 \-f Full Screen.
34 \-w Windowed.
35 \-\-fps nn Run the game at nn frames per second (fps).
36 \-mWWxHHxBPP Run in video mode set by WW pixels of width, HH pixels of height and BPP bits per pixel (eg. \-m640x480x16).
37 .SH "AUTHOR"
38 This manual page was written for the Debian GNU/Linux system by Miriam Ruiz
39 <little_miry@yahoo.es> (but may be used by others, of course)
0 This is the resource directory for Holotz's Castle.
1
2
3 1. English
4 -------
5
6 1.1 playlist.txt
7 ----------------
8
9 Play list of stories. Each line contains the name of the directory with the next story to play.
10
11
12 1.2 preferences.txt
13 -------------------
14
15 This file contains the default preferences for the game. It's generated automatically when
16 the user changes the game settings or the game is run for the first time.
17 The file is organized in lines:
18
19 1st line - abbreviated name of the language ('es', 'en', 'fr', etc.).
20 2nd line - video mode to use(widthXheightXbpp)
21 3rd line - windowed/fullscreen
22 4th line - audio on/off
23
24 Example of preferences file:
25
26 language=es
27 video=5
28 mode=fullscreen
29 audio=on
30
31
32 2. Español
33 ----------
34
35 2.1 playlist.txt
36 ----------------
37
38 Lista de historias a reproducir. Cada línea del fichero contiene el nombre del directorio con
39 la siguiente historia a reproducir.
40
41 2.2 preferences.txt
42 -------------------
43
44 Este fichero contiene las preferencias por defecto para el juego. Se genera automáticamente cuando
45 el usuario cambia la configuración del juego o el juego se ejecuta por primera vez.
46 El fichero se organiza en líneas como sigue:
47
48 1ª línea - Nombre abreviado del idioma ('es', 'en', 'fr', etc.).
49 2ª línea - Modo de vídeo (anchuraXalturaXbpp)
50 3ª línea - Audio activado/desactivado
51 4ª línea - En ventana/pantalla completa
52
53 Ejemplo:
54
55 language=es
56 video=5
57 mode=fullscreen
58 audio=on
59
60
61 3. Русский
62 -------
63
64 1.1 playlist.txt
65 ----------------
66
67 Список сценариев. Каждая строчка содержит путь к каталогу со следующим сценарием.
68
69
70 1.2 preferences.txt
71 -------------------
72
73 Настройки игры по умолчанию. Этот файл автоматически содаётся, когда
74 изменяет настройки, или игра запускается в первый раз.
75 Файл состоит из следующих строк:
76
77 1-я строка - сокращенное обозначение языка ('es', 'en', 'fr', 'ru' и т.д.).
78 2-я строка - видеорежим(ширинаXвысотаXцветность)
79 3-я строка - в окне/на весь экран
80 4-я строка - включить/выключить звук
81
82 Пример файла настроек:
83
84 language=ru
85 video=5
86 mode=fullscreen
87 audio=on
88
89 4. Українська
90 -------
91
92 4.1 playlist.txt
93 ----------------
94
95 Список сценаріїв. Кожен рядок вміщує шлях до каталогу з наступним сценарієм.
96
97
98 4.2 preferences.txt
99 -------------------
100
101 Типові налаштування гри. Цей файл автоматично створюється, коли
102 змінюються налаштування, або гра запускається в перший раз.
103 Файл складається з наступних рядків:
104
105 1-й рядок - скорочене позначення мови ('es', 'en', 'fr', 'ua' и т.д.).
106 2-й рядок - відеорежим(ширинаXвисотаXколір)
107 3-й рядок - у вікні/на весь екран
108 4-й рядок - включити/виключити звук
109
110 Приклад файлу налаштувань:
111
112 language=ua
113 video=5
114 mode=fullscreen
115 audio=on
116
117
118 5. Euskaraz
119 ----------
120
121 5.1 playlist.txt
122 ----------------
123
124 Aukeratu daitezkeen istorioen zerrenda. Zerrendako lerro bakoitzak hurrengo hasi behar den
125 istorioaren karpetaren izena darama.
126
127 5.2 preferences.txt
128 -------------------
129
130 Fitxategi honek jokuaren berezko ezarpenak ditu. Erabiltzaileak jokuaren ezarpenak
131 aldatzen dituenero edo lehen aldiz abiarazten denean sortzen da bere kasa.
132 Fitxategiko lerroak hauek dira:
133
134 1. lerroa - Hizkuntzaren laburdura ('eu', 'en', 'fr', etab.).
135 2. lerroa - Irudien ezarpenak (zabaleraXgaraieraXbit/piksel)
136 3. lerroa - Leihoan/Guztizko ikuskera
137 4. lerroa - Soinua gaituta/ezgaituta
138
139 Adibidez:
140
141 language=eu
142 video=5
143 mode=fullscreen
144 audio=on
145
146 6. Português
147 ----------
148
149 6.1 playlist.txt
150 ----------------
151
152 Lista de histórias a reproduzir. Cada linha do ficheiro contém o nome do directório com
153 a próxima história a reproduzir.
154
155 2.2 preferences.txt
156 -------------------
157
158 Este ficheiro contém as preferências por omissão para o jogo. Gera-se automáticamente quando
159 o utilizador muda a configuracão do jogo ou o jogo se executa pela primeira vez.
160 O ficheiro organiza-se em linhas da seguinte forma:
161
162 1ª linha - Nome abreviado do idioma ('es', 'en', 'fr', etc).
163 2ª linha - Modo de vídeo (larguraXalturaXbpp)
164 3ª linha - Áudio activado/desactivado
165 4ª linha - Em janela/ecrã completo
166
167 Exemplo:
168
169 language=es
170 video=5
171 mode=fullscreen
172 audio=on
Binary diff not shown
Binary diff not shown
Binary diff not shown
Binary diff not shown
Binary diff not shown
Binary diff not shown
Binary diff not shown
Binary diff not shown
Binary diff not shown
Binary diff not shown
0 Ybelle a Ludar se objevili v tajemnem hrade.
1 Musi vzdy sebrat vsechny magicke predmety
2 v mistnosti, aby mohli postoupit do dalsi.
3
4 Ovladani:
5
6 Kurzorove sipky - Pohyb
7 Mezernik - Skok / Preskoceni vety dialogu
8 Enter - Preskoceni celeho dialogu
9 F1 (pri hre) - Zobrazi tuto napovedu
10 ESC - Skryje tuto napovedu
0 Ybelle und Ludar sind in einem geheimisvollen
1 Schloss angekommen. Sie müssen alle
2 magischen Gegenstände in einem Raum sammeln,
3 um in den nächsten zu kommen...
4
5 Tasten:
6
7 Pfeile - Bewegt die Spielfigur
8 Leertaste - Überspringt den einzelnen Dialog
9 Enter - Überspringt die ganze Dialog-Folge
10 F1 (während des Spiels) - Zeigt diese Hilfe an
11 ESC - Versteckt diese Hilfe
0 Ybelle and Ludar have appeared in a
1 misterious castle. They must pick up
2 all the magical objects in a room to go
3 to the next one.
4
5 Controls:
6
7 Arrows - Move character
8 Space - Jump / Skip single dialog
9 Enter - Skip dialog sequence
10 F1 (playing) - Displays this help
11 ESC - Hide this help
0 Ybelle y Ludar han aparecido en un
1 misterioso castillo. Deberán recoger
2 los objetos mágicos en cada sala para
3 poder pasar a la siguiente.
4
5 Controles:
6
7 Flechas - Mover al personaje
8 Barra de espacio - Saltar / Pasar diálogo
9 Intro - Saltar diálogo entero
10 F1 (jugando) - Mostrar la ayuda
11 ESC - Ocultar la ayuda
0 Ybelle eta Ludar gaztelu misteriotsu
1 batean agertu dira. Gela bakoitzeko
2 objektu majikoak bildu beharko dituzte
3 hurrengo gelara joan ahal izateko.
4
5 Teklak:
6
7 Geziak - Pertsonaia mugitzeko
8 Hutsunea - Jauzi egin / Elkarrizketa moztu
9 Sartu - Elkarrizketa kendu
10 F1 (jolastean) - Laguntza erakutsi
11 IHES - Laguntza ezkutatu
0 Ybelle et Ludar sont apparus dans un
1 mystérieux château. Ils doivent récupérer
2 tous les ojets magiques d'une pièce
3 pour passer à la suivante.
4
5 Contrôles:
6
7 Flèches - Déplacer le personnage
8 Espace - Sauter / Passer un dialogue
9 Entrée - Passer une série de dialogues
10 F1 (pendant le jeu) - Afficher cet écran
11 ESC - Masquer cet écran
0 Ybelle e Ludare sono apparsi in un
1 misterioso castello. Devono prendere
2 tutti gli oggetti magici in una stanza
3 per poter entrare nella successiva.
4
5 Controlli:
6
7 Frecce - Muovi il personaggio
8 Spazio - Salto/Ignora una battuta
9 Invio - Ignora un intero dialogo
10 F1 (in gioco) - Mostra questo menu
11 ESC - Nascondi questo menu
0 Ybelle en Ludar zijn verschenen in een
1 mysterieus kasteel. Ze moeten alle
2 magische objecten in een kamer
3 verzamelen om naar de volgende kamer
4 te mogen gaan.
5
6 Besturing:
7
8 Pijltjestoetsen - Beweeg het spelkarakter
9 Spatie - Springen / Sla een enkel dialoog over
10 Enter - Sla een heel dialoog over
11 F1 (tijdens het spelen) - Laat deze help zien
12 ESC - Verberg deze help
0 Ybelle e Ludar apareceram num
1 misterioso castelo. Deverão recolher
2 os objetos mágicos em cada sala para
3 poder passar à sala seguinte.
4
5 Controlos:
6
7 Setas - Mover a personagem
8 Barra de espaço - Saltar / Passar diálogo
9 Return - Saltar diálogo inteiro
10 F1 (a jogar) - Mostrar ajuda
11 ESC - Ocultar ajuda
0 Ивонна и Людар очутились в загадочном
1 волшебном замке. Теперь им нужно собирать
2 все магические предметы в комнате, чтобы
3 пройти далее.
4
5 Управление:
6
7 Стрелки - Движение
8 Пробел - Прыжок / Пропустить реплику
9 Ввод - Пропустить диалог
10 F1 (во время игры) - Показать справку
11 ESC - Закрыть страницу справки
0 Ибела и Лудар су се појавили у
1 тајанственом замку. Сад морају да покупе
2 све чаробне предмете у соби да би прешли
3 у следећу.
4
5 Управљање:
6
7 Стрелице - Померај лика
8 Размак - Скочи / Прескочи говор
9 Ентер - Прескочи цео разговор
10 F1 (у току игре) - Приказује ову помоћ
11 ESC - Сакрива ову помоћ
0 Ybelle och Ludar befinner sig i ett
1 mystiskt slott. De maste samla ihop
2 alla magiska objekt i ett rum for
3 att kunna ga vidare till nasta.
4
5 Kontroller:
6
7 Piltangenter - Forflytta karaktar
8 Mellanslag - Hoppa / Hoppa over singeldialog
9 Enter - Hoppa over dialogsekvens
10 F1 (under spelets gang) - Visa denna hjalp
11 ESC - Dolj denna hjalp
0 Ybelle och Ludar befinner sig i ett
1 mystiskt slott. De måste samla ihop
2 alla magiska objekt i ett rum för
3 att kunna gå vidare till nästa.
4
5 Kontroller:
6
7 Piltangenter - Förflytta karaktär
8 Mellanslag - Hoppa / Hoppa över singeldialog
9 Enter - Hoppa över dialogsekvens
10 F1 (under spelets gång) - Visa denna hjälp
11 ESC - Dölj denna hjälp
0 Івонна та Дюдар опинилися в загадковому
1 чарівному замку. Тепер їм необхідно збирати
2 всі магічні предмети в кімнаті, щоб
3 пройти далі
4
5 Управління:
6
7 Стрілки - Рух героєм
8 Пробіл - Стрибок / Пропустити репліку
9 Введення - Пропустити діалог
10 F1 (під час гри) - Показати довідку
11 ESC - Закрити сторінку довідки
Binary diff not shown
0 PRÄSENTIERT
0 MAINREACTORREK_AURKEZTURIK
Binary diff not shown
Binary diff not shown
0 APRESENTA
0 ПРЕДСТАВЛЯЕТ
0 ПРЕДСТАВЉА
0 ПРЕДСТАВЛЯЄ
0 ENGLISH;en
1 ESPAÑOL;es
2 DEUTSCH;de
3 FRANÇAIS;fr
4 РУССКИЙ;ru
5 УКРАÏНСЬКА;ua
6 EUSKARA;eu
7 CESKY;cs
8 PORTUGUÊS;pt
9 ITALIANO;it
10 NEDERLANDS;nl
11 SVENSKA;sv
12 СРПСКИ;sr
Binary diff not shown
0 Making of "HOLOTZ'S CASTLE" main title.
1
2 The image was made with the Gimp.
3
4 - Dynamic Text > 150 pt > write "HOLOTZ'S CASTLE"
5 - Script-fu > Alfa to logo > Stella > Select color and ~28 for intensity.
6
7
8 (C) 2004 - Juan Carlos Seijo Pérez.
0 POKRACOVAT VE HRE
1 NOVA HRA
2 POMOC
3 NASTAVENI
4 VIDEO
5 ROZLISENI
6 BAREVNA HLOUBKA
7 V OKNE / CELA OBRAZOVKA
8 V OKNE
9 CELA OBRAZOVKA
10 STANDARTNI
11 ZVUK
12 ZAPNUT
13 VYPNUT
14 OBTIZNOST
15 HRACKA
16 LEHKA
17 STREDNI
18 TEZKA
19 JAZYK
20 NACIST
21 ULOZIT
22 ZASLUHY
23 KONEC
0 WEITERSPIELEN
1 NEUES SPIEL
2 HILFE
3 OPTIONEN
4 VIDEO
5 GRÖSSE
6 BPP
7 BILDSCHRIM
8 FENSTER
9 VOLLBILD
10 STANDARD
11 AUDIO
12 AN
13 AUS
14 SCHWIERIGKEIT
15 SPIELZEUG
16 EINFACH
17 MITTEL
18 SCHWER
19 SPRACHE
20 LADEN
21 SPEICHERN
22 ABSPANN
23 ENDE
0 CONTINUE GAME
1 NEW GAME
2 HELP
3 OPTIONS
4 VIDEO
5 SIZE
6 BPP
7 WINDOW
8 WINDOWED
9 FULL SCREEN
10 DEFAULTS
11 SOUND
12 ON
13 OFF
14 DIFFICULTY
15 TOY
16 EASY
17 MEDIUM
18 HARD
19 LANGUAGE
20 LOAD
21 SAVE
22 CREDITS
23 EXIT
0 CONTINUAR PARTIDA
1 NUEVA PARTIDA
2 AYUDA
3 OPCIONES
4 VIDEO
5 TAMAÑO
6 BPP
7 VENTANA
8 EN VENTANA
9 PANTALLA COMPLETA
10 VALORES POR DEFECTO
11 SONIDO
12 ACTIVAR
13 DESACTIVAR
14 DIFICULTAD
15 JUGUETE
16 BAJA
17 MEDIA
18 ALTA
19 IDIOMA
20 CARGAR
21 SALVAR
22 CREDITOS
23 SALIR
0 JOKALDIA JARRAITU
1 JOKALDI BERRIA
2 LAGUNTZA
3 AUKERAK
4 IRUDIA
5 NEURRIA
6 BIT/PIKSEL
7 IKUSKERA
8 LEIHOAN
9 GUZTIZKO IKUSKERA
10 BEREZKO BALIOAK
11 SOINUA
12 GAITU
13 EZGAITU
14 ZAILTASUNA
15 JOSTAILU
16 TXIKIA
17 OHIKOA
18 HANDIA
19 HIZKUNTZA
20 ESKURATU
21 GORDE
22 EGILEAK
23 IRTEN
0 CONTINUER LA PARTIE
1 NOUVELLE PARTIE
2 AIDE
3 OPTIONS
4 VIDEO
5 TAILLE
6 BPP
7 FENETRE
8 FENETRE
9 PLEIN ECRAN
10 DEFAUT
11 SON
12 ACTIVE
13 DESACTIVE
14 DIFFICULTE
15 JOUET
16 FACILE
17 MOYEN
18 DIFFICLE
19 LANGUE
20 CHARGER
21 SAUVEGARDER
22 CREDITS
23 QUITTER
0 CONTINUA PARTITA
1 NUOVA PARTITA
2 AIUTO
3 OPZIONI
4 VIDEO
5 RISOLUZIONE
6 COLORI
7 FINESTRA
8 IN FINESTRA
9 SCHERMO INTERO
10 PREDEFINITI
11 SOUONO
12 ACCESO
13 SPENTO
14 DIFFICOLTÀ
15 GIOCATTOLO
16 FACILE
17 MEDIO
18 DIFFICILE
19 LINGUE
20 CARICA
21 SALVA
22 CREDITI
23 ESCI
0 HERVAT SPEL
1 NIEUW SPEL
2 HELP
3 OPTIES
4 BEELD
5 GROOTTE
6 BPP
7 VENSTER
8 IN VENSTER
9 VOLLEDIG SCHERM
10 STANDAARDWAARDES
11 GELUID
12 AAN
13 UIT
14 MOEILIJKHEIDSGRAAD
15 TOY
16 MAKKELIJK
17 GEMIDDELD
18 MOEILIJK
19 TAAL
20 LADEN
21 OPSLAAN
22 CREDITS
23 VERLAAT SPEL
0 CONTINUAR JOGO
1 NOVO JOGO
2 AJUDA
3 OPÇÕES
4 VÍDEO
5 TAMANHO
6 BPP
7 JANELA
8 EM JANELA
9 ECRÃ COMPLETO
10 VALORES POR OMISSÃO
11 SOM
12 ACTIVAR
13 DESACTIVAR
14 DIFICULDADE
15 BRINQUEDO
16 BAIXA
17 MÉDIA
18 ALTA
19 IDIOMA
20 CARREGAR
21 GUARDAR
22 CRÉDITOS
23 SAIR
0 ПРОДОЛЖИТЬ ИГРУ
1 НОВАЯ ИГРА
2 ПОМОЩЬ
3 НАСТРОЙКА
4 ИЗОБРАЖЕНИЕ
5 РАЗМЕР
6 ЧИСЛО БИТ НА ТОЧКУ
7 РЕЖИМ ПОКАЗА
8 В ОКНЕ
9 НА ВЕСЬ ЭКРАН
10 СТАНДАРТНЫЕ НАСТРОЙКИ
11 ЗВУК
12 ВКЛ
13 ВЫКЛ
14 СЛОЖНОСТЬ
15 ИГРЧШКА
16 ЛЕГКО
17 В САМЫЙ РАЗ
18 ТЯЖЕЛО
19 ЯЗЫК
20 ПРОЧИТАТЬ
21 СОХРАНИТЬ
22 АВТОРЫ
23 ВЫХОД
0 НАСТАВИ ИГРУ
1 НОВА ИГРА
2 ПОМОЋ
3 ПОДЕШАВАЊА
4 ГРАФИКА
5 ВЕЛИЧИНА
6 БПП
7 ПРОЗОР
8 УПРОЗОРЕН
9 ПУН ЕКРАН
10 ВРАТИ ОСНОВНА ПОДЕШАВАЊА
11 ЗВУК
12 УКЉУЧЕН
13 ИСКЉУЧЕН
14 ТЕЖИНА
15 ДЕЧИЈА ИГРА
16 ЛАКА
17 СРЕДЊА
18 ТЕШКА
19 ЈЕЗИК
20 УЧИТАЈ
21 СНИМИ
22 ЗАХВАЛНИЦЕ
23 ИЗЛАЗ
0 FORTSÄTT SPEL
1 NYTT SPEL
2 HJÄLP
3 INSTÄLLNINGAR
4 SKÄRM
5 UPPLÖSNING
6 FÄRGDJUP
7 FÖNSTER
8 FÖNSTERLÄGE
9 HELSKÄRMSLÄGE
10 STANDARD
11 LJUD
12
13 AV
14 SVÅRIGHETSGRAD
15 LEKSAK
16 LÄTT
17 MEDIUM
18 SVÅRT
19 SPRÅK
20 LADDA
21 SPARA
22 UPPHOVSMÄN
23 AVSLUTA
0 ПРОДОВЖИТИ ГРУ
1 НОВА ГРА
2 ДОПОМОГА
3 НАЛАШТУВАННЯ
4 ЗОБРАЖЕННЯ
5 РОЗМІР
6 ЧИСЛО БІТ НА ТОЧКУ
7 РЕЖИМ ПОКАЗУ
8 У ВІКНІ
9 НА ПОВНИЙ ЕКРАН
10 СТАНДАРТНІ НАЛАШТУВАННЯ
11 ЗВУК
12 ВКЛ
13 ВИКЛ
14 СКЛАДНІСТЬ
15 ІГРАШКА
16 ЛЕГКО
17 ТЕ ЩО ТРЕБА
18 ВАЖКО
19 МОВА
20 ВІДНОВИТИ
21 ЗБЕРЕГТИ
22 АВТОРИ
23 ВИХІД
0 Game Over
1 ... ZzZzZz ...
0 Aus und vorbei
1 Schnarch...
0 Game Over
1 Paused
0 Game Over
1 ... ZzZzZz ...
0 Game Over
1 ... ZzZzZz ...
0 Game Over
1 ...zzZzzZzz...
0 Einde Spel
1 Gepauzeerd
0 Game Over
1 ... ZzZzZz ...
0 Игра је готова
1 Пауза
0 Spelet är slut
1 Pausat
0 Game Over
1 ... ZzZzZz ...
0 holotzcastle
1 milanb
(New empty file)
Binary diff not shown
Binary diff not shown
Binary diff not shown
Binary diff not shown
Binary diff not shown
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle and Ludar arrive to the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
8 }
9
10 {
11 [ NARRATIVE text="Ludar a Ybelle" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
12 }
13
14 {
15 [ DIALOG main(0) text="Co se stalo?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=6 amount=2 ]
17 [ MOVE enemy(0) dir=6 amount=3 ]
18 }
19
20 {
21 [ DIALOG enemy(0) text="Rikal jsem ti,
22 abys na ten kamen nesahal!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Mlc uz..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
27 }
28
29 {
30 [ DIALOG main(0) text="Jak jsem to mohl tusit?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
31 }
32
33 {
34 [ DIALOG main(0) text="A kde to vubec jsme?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
35 }
36
37 {
38 [ DIALOG enemy(0) text="Ha! To se
39 pta ten pravy." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
40 }
41
42 {
43 [ DIALOG enemy(0) text="Kdybys nesahal,
44 na co jsi nemel..." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
45 }
46
47 {
48 [ DIALOG main(0) text="Pitomec..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
49 [ DIALOG enemy(0) text="Idiot..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
50 }
51
52 {
53 [ DIALOG main(0) text="Musime najit cestu
54 zpatky domu." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
55 }
56
57 {
58 [ DIALOG main(0) text="Nasleduj me, Ludare." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
59 }
60
61 {
62 [ DIALOG enemy(0) text="Ani ne... Vzdycky me dostanes
63 do nejakeho prusvihu." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
64 }
65
66 {
67 [ DIALOG enemy(0) text="Tentokrat nas
68 povedu ja." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
69 }
70
71 {
72 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
73 }
74
75 {
76 [ DIALOG main(0) text="Ok, jdi si sam." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
77 [ MOVE main(0) dir=6 amount=5 ]
78 }
79
80 {
81 [ DIALOG enemy(0) text="???" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
82 [ MOVE main(0) dir=8 amount=3 ]
83 }
84
85 {
86 [ MOVE enemy(0) dir=6 amount=3 ]
87 [ DIALOG enemy(0) text="Err... Ybelle,
88 pockej na me!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
89 }
90
91 {
92 [ MOVE main(0) dir=6 amount=3 ]
93 }
0 ##########################################
1 # Holotz's Castle story - Level 2
2 # Ybelle enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Nee!" txtAlign=4 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 }
7
8 {
9 [ DIALOG main(0) text="To bolelo!" txtAlign=4 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
10 }
11
12 {
13 [ DIALOG main(0) text="Ludare!" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
14 }
15
16 {
17 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=1 ]
18 }
19
20 {
21 [ DIALOG main(0) text="...vypada to,
22 ze me neslysi." txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Dobre..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
27 [ MOVE main(0) dir=6 amount=1 ]
28 }
29
30 {
31 [ MOVE main(0) dir=4 amount=1 ]
32 [ DIALOG main(0) text="Co tu k sakru delaji
33 vsechny tyhle klice?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]}
0 ##########################################
1 # Holotz's Castle story - Level 7
2 # Ludar enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Err... Ybelle,
6 pockej na me!" txtAlign=4 speed=2 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ MOVE main(0) dir=6 amount=2 ]
8 }
9
10 {
11 [ MOVE main(0) dir=6 amount=1 ]
12 [ DIALOG main(0) text="Ale ne!" txtAlign=4 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
13 }
14
15 {
16 [ DIALOG main(0) text="Kde se tady
17 vzala ta dira?" txtAlign=4 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
18 }
19
20 {
21 [ DIALOG main(0) text="Ybelle!" txtAlign=5 speed=1 size=3 align=0 r=20 g=200 b=20 subtype=0 ]
22 }
23
24 {
25 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
26 }
27
28 {
29 [ DIALOG main(0) text="Palicak jeden..." txtAlign=5 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
30 }
31
32 {
33 [ DIALOG main(0) text="A hele." txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=4 amount=1 ]
35 }
36
37 {
38 [ DIALOG main(0) text="Tyhle kameny jsou
39 podobne tomu, co na
40 nej sahl Ybelle." txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
41 [ MOVE main(0) dir=4 amount=1 ]
42 }
43
44 {
45 [ DIALOG main(0) text="Co je tohle za divne misto?" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
46 }
0 ##########################################
1 # Holotz's Castle story - Level 14
2 # Ybelle finds the shoe maker
3 ##########################################
4
5 {[ DIALOG main(0) text="?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Co je tohle za divne misto?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
9
10 {[ NARRATIVE text="Obuvnictvi" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
11 [ MOVE main(0) dir=6 amount=1 ]}
12
13 {[ MOVE main(0) dir=2 amount=3 ]}
14
15 {[ MOVE main(0) dir=6 amount=2 ]}
16
17 {[ MOVE main(0) dir=9 amount=2 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]}
20
21 {[ MOVE main(0) dir=9 amount=1 ]
22 [ DIALOG enemy(0) text="Ooh,
23 navstevnik!" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=1 ]}
24
25 {[ MOVE main(0) dir=9 amount=2 ]}
26
27 {[ DIALOG main(0) text="Co je to za
28 podivina..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
29 [ DIALOG enemy(0) text="Co je to za
30 podivina..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=1 ]
31 }
32
33 {[ DIALOG main(0) text="Err... A-hoj?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
34
35 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
36
37 {[ DIALOG enemy(0) text="Nevypadas..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
38
39 {[ DIALOG enemy(0) text="...ze jsi odsud." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
40
41 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
42 [ DIALOG main(0) text="Vypada, jako by
43 se chystal kazdou
44 chvili usnout!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
45
46 {[ DIALOG enemy(0) text="Vstoupil jsi
47 novy..." txtAlign=5 speed=1 size=0 align=0 r=200 g=130 b=20 subtype=0 ]}
48
49 {[ DIALOG enemy(0) text="...pred..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
50
51 {[ DIALOG enemy(0) text="...kratkou dobou?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
52
53 {[ DIALOG main(0) text="Podivej...
54 Novy, rikas??" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
55
56 {[ DIALOG main(0) text="Oh, ano,
57 samozrejme." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
58
59 {[ DIALOG main(0) text="Kdo jsi?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
60
61 {[ DIALOG enemy(0) text="Jsem..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
62
63 {[ DIALOG enemy(0) text="...Pan bot." txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="Predpokladam..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
66
67 {[ DIALOG enemy(0) text="...ze sis prisel..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
68
69 {[ DIALOG enemy(0) text="...pro novy par..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
70
71 {[ DIALOG enemy(0) text="...Spravne?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
72
73 {[ DIALOG enemy(0) text="Vem si..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
74 [ DIALOG main(0) text="Ja..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
75
76 {[ DIALOG enemy(0) text="...tyhle." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
77
78 {[ MOVE main(0) dir=6 amount=2 ]}
79 {[ MOVE main(0) dir=4 amount=2 ]}
80
81 {[ DIALOG enemy(0) text="Samozrejme..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
82
83 {[ DIALOG enemy(0) text="...se s nimi budes..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
84
85 {[ DIALOG enemy(0) text="...pohybovat rychleji..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
86
87 {[ DIALOG main(0) text="Nevis, jak se
88 odsud dostat?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
89
90 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
91
92 {[ DIALOG enemy(0) text="...ne." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
93
94 {[ DIALOG enemy(0) text="...Jen Holotz..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
95
96 {[ DIALOG enemy(0) text="...vi." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
97
98 {[ DIALOG main(0) text="Holotz?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
99
100 {[ DIALOG enemy(0) text="Ano..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
101
102 {[ DIALOG enemy(0) text="To on vytvoril..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
103
104 {[ DIALOG enemy(0) text="...tenhle hrad." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
105
106 {[ DIALOG main(0) text="Kde ho najdu?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
107
108 {[ DIALOG enemy(0) text="...To nejde." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
109
110 {[ DIALOG enemy(0) text="On..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
111
112 {[ DIALOG enemy(0) text="...najde tebe." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
113
114 {[ DIALOG enemy(0) text="Nyni se musim..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
115
116 {[ DIALOG enemy(0) text="...vratit..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
117
118 {[ DIALOG enemy(0) text="...ke sve praci." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
119
120 {[ DIALOG main(0) text="A-ale...!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
121 [ DIALOG enemy(0) text="Nyni se musim..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
122
123 {[ DIALOG main(0) text="To nic,
124 nech to plavat." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
125
126 {[ DIALOG main(0) text="Tedy, ja jdu...
127 Diky za boty." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
128 [ MOVE main(0) dir=7 amount=2 ]}
129
130 {[ MOVE main(0) dir=7 amount=2 ]}
131
132 {[ DIALOG main(0) text="Ale kam
133 vlastne pujdu?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
134
135 {[ DIALOG main(0) text="No, vzdyt je to docela jedno..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
136 [ MOVE main(0) dir=4 amount=1 ]}
137
138 {[ MOVE main(0) dir=2 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 16
2 # Ludar talks to the two flames
3 ##########################################
4
5 {[ DIALOG main(0) text="Oops..." txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_UltraSlow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Hele, dalsi kamen!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
9 [ MOVE main(0) dir=6 amount=1 ]}
10
11 {[ NARRATIVE text="Dva plameny" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
12 [ MOVE main(0) dir=6 amount=4 ]
13 [ DIALOG main(0) text="A dalsi!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
14
15 {[ DIALOG enemy(0) text="Ani hnout!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
16
17 {[ DIALOG main(0) text="???" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
18 [ MOVE main(0) dir=4 amount=1 ]}
19
20 {[ DIALOG main(0) text="Co to bylo?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
21 [ MOVE main(0) dir=6 amount=4 ]}
22
23 {[ DIALOG enemy(0) text="Povidam:
24 Ani hnout!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
25
26 {[ MOVE main(0) dir=4 amount=4 ]
27 [ DIALOG main(0) text="Oh, povidajici plamen!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]}
28
29 {[ DIALOG enemy(0) text="Nejsem povidajici plamen!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]
30 [ DIALOG main(0) text="Oh!" txtAlign=5 speed=4 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
31 [ MOVE main(0) dir=6 amount=2 ]}
32
33 {[ DIALOG enemy(0) text="Jsem mluvici plamen!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
34
35 {[ DIALOG main(0) text="Jak jsi vedel,
36 na co myslim?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
37
38 {[ DIALOG enemy(0) text="Ja vim vsechno!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
39
40 {[ DIALOG enemy(1) text="Ahem..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
41
42 {[ DIALOG enemy(0) text="Teda, skoro vsechno." txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
43
44 {[ DIALOG enemy(1) text="On cte myslenky..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
45
46 {[ DIALOG enemy(1) text="...a ja ctu..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
47
48 {[ DIALOG enemy(1) text="...knihy." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
49
50 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]
51 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]
52 [ DIALOG main(0) text="??!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
53
54 {[ DIALOG enemy(1) text="Jak ses sem dostal?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
55
56 {[ DIALOG enemy(0) text="Ja vim..." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
57
58 {[ DIALOG main(0) text="Oh, chysta se mi
59 precist myslenky!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]}
60
61 {[ DIALOG enemy(0) text="Kouzelnym portalem!" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
62
63 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
64 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=3 align=0 r=20 g=20 b=180 subtype=0 ]
65 [ DIALOG main(0) text="hmpfxs#@!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
66 [ MOVE main(0) dir=6 amount=4 ]}
67
68 {[ DIALOG enemy(1) text="Pockej, neodchazej." txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
69 [ MOVE main(0) dir=4 amount=5 ]}
70
71 {[ DIALOG main(0) text="Nemam cas na forky!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
72 [ MOVE main(0) dir=6 amount=2 ]}
73
74 {[ DIALOG enemy(0) text="Co potrebujes?" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]
75 [ MOVE main(0) dir=4 amount=3 ]}
76
77 {[ DIALOG main(0) text="Musim najit Ybelle." txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
78
79 {[ DIALOG main(0) text="Musime se vratit
80 do rise Lizarno." txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
81
82 {[ DIALOG enemy(0) text="Hmmm... Lizarnit, zajimave." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=1 ]}
83
84 {[ DIALOG enemy(1) text="Odted dale bude hrad" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
85
86 {[ DIALOG enemy(1) text="nebezpecnejsi" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
87
88 {[ DIALOG enemy(1) text="a ty nemas dost
89 magicke sily," txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
90
91 {[ DIALOG enemy(1) text="abys dosahl
92 nejvyssi urovne." txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
93
94 {[ DIALOG enemy(0) text="Ano, potrebujes..." txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
95
96 {[ DIALOG enemy(1) text="Boty!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
97 [ DIALOG enemy(0) text="Boty!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
98
99 {[ DIALOG main(0) text="Hele, nechte
100 toho vtipkovani!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
101 [ MOVE main(0) dir=4 amount=2 ]}
102
103 {[ DIALOG enemy(0) text="Ale muzes je
104 ziskat pouze od" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
105
106 {[ DIALOG enemy(0) text="Pana bot." txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
107
108 {[ DIALOG main(0) text="Neni zadny jiny
109 zpusob, jak je ziskat?" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
110 [ MOVE main(0) dir=6 amount=2 ]}
111
112 {[ DIALOG enemy(1) text="Ano, muzes je
113 dostat v" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=60 subtype=0 ]}
114
115 {[ DIALOG enemy(1) text="Obuvnictvi!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=60 subtype=0 ]
116 [ DIALOG enemy(0) text="Obuvnictvi!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]}
117
118 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
119 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]
120 [ DIALOG main(0) text="Zacinaji me stvat!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
121 [ MOVE main(0) dir=6 amount=4 ]}
122
123 {[ DIALOG enemy(1) text="Pockej." txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
124 [ MOVE main(0) dir=4 amount=2 ]}
125
126 {[ DIALOG enemy(1) text="Boty muzes taky najit" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
127
128 {[ DIALOG enemy(1) text="v mistnosti za timto
129 mystickym portalem." txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
130
131 {[ DIALOG enemy(0) text="Ale mel bys vedet," txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
132
133 {[ DIALOG enemy(0) text="ze z nej nikdy
134 nikdo nevysel zivy." txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
135
136 {[ DIALOG main(0) text="Oh!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
137 [ MOVE main(0) dir=6 amount=2 ]}
138
139 {[ DIALOG main(0) text="Hmm... Presto
140 to musim zkusit." txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
141 [ MOVE main(0) dir=4 amount=2 ]}
142
143 {[ DIALOG main(0) text="Oh, ale ja ten
144 portal nemuzu otevrit." txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
145 [ MOVE main(0) dir=4 amount=2 ]}
146
147 {[ DIALOG main(0) text="Posledni kamen je
148 prilis vysoko!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
149
150 {[ DIALOG enemy(1) text="Tak pouzij tenhle zebrik." txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 19
2 # Ybelle is captured
3 ##########################################
4
5 {[ DIALOG main(0) text="Aaah!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_Fast.wav" loops=0 waitToEnd=0 ]}
7
8 {[ MOVE enemy(0) dir=8 amount=4 ]
9 [ MOVE enemy(1) dir=8 amount=4 ]
10 [ MOVE enemy(2) dir=4 amount=2 ]
11 [ MOVE enemy(3) dir=6 amount=2 ]
12 [ MOVE enemy(4) dir=4 amount=5 ]
13 [ MOVE enemy(5) dir=6 amount=5 ]
14 [ DIALOG main(0) text="Oh, oh..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
15 [ DIALOG enemy(2) text="!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=1 ]
16 [ DIALOG enemy(3) text="!" txtAlign=5 speed=1 size=2 align=0 r=220 g=20 b=20 subtype=1 ]}
17
18 {[ NARRATIVE text="
19 POKRACOVANI PRISTE...
20 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
21 [ DIALOG main(0) text="??!" txtAlign=5 speed=3 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=5 amount=1 ]}
23
24 {[ DIALOG main(0) text="Eeeh!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
25 [ MOVE main(0) dir=5 amount=2 ]}
26
27 {[ DIALOG main(0) text="Nenechavejte me tady!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
28 [ MOVE main(0) dir=5 amount=2 ]}
29
30 {[ WAIT millis=3000]}
0 ##########################################
1 # Holotz's Castle story - Level 20
2 # Ybelle is captured (continued)
3 ##########################################
4
5 {[ MOVE enemy(0) dir=8 amount=0 ]
6 [ MOVE enemy(1) dir=8 amount=0 ]
7 [ MOVE enemy(2) dir=4 amount=0 ]
8 [ MOVE enemy(3) dir=6 amount=0 ]
9 [ MOVE enemy(4) dir=4 amount=0 ]
10 [ MOVE enemy(5) dir=6 amount=0 ]}
11
12 {[ WAIT millis=1000]}
13
14 {[ DIALOG main(0) text="Ani hnout!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
15 [ MOVE main(0) dir=4 amount=1 ]}
16
17 {[ DIALOG enemy(0) text="Je je" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]
18 [ DIALOG enemy(1) text="Hmmm" txtAlign=5 speed=5 size=3 align=0 r=200 g=20 b=20 subtype=0 ]}
19
20 {[ DIALOG main(0) text="Varuju vas,
21 jsem nebezpecny!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=6 amount=2 ]}
23
24 {[ MOVE enemy(1) dir=4 amount=3 ]
25 [ DIALOG enemy(1) text="Podivej..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
26
27 {[ MOVE enemy(1) dir=4 amount=1 ]
28 [ DIALOG enemy(5) text="Co?" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
29
30 {[ DIALOG enemy(1) text="On ma boty." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
31
32 {[ DIALOG enemy(5) text="Hmmm... Holotzovi
33 se to nebude libit." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
34
35 {[ DIALOG main(0) text="Co chces?" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
36
37 {[ MOVE enemy(5) dir=6 amount=4 ]
38 [ MOVE main(0) dir=6 amount=1 ]
39 [ DIALOG enemy(5) text="Otazka zni..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
40
41 {[ DIALOG enemy(5) text="Co tu delas?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
42
43 {[ DIALOG main(0) text="Sebral jsem kamen a..." txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
44
45 {[ DIALOG enemy(5) text="A otevrel se mysticky
46 portal, ano?." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
47
48 {[ DIALOG main(0) text="Jo, presne!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
49
50 {[ DIALOG enemy(5) text="Vypada to, ze
51 Holotzovy experimenty" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
52
53 {[ DIALOG enemy(5) text="neuspely." txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
54
55 {[ DIALOG enemy(5) text="Udivuje mne, ze se
56 ti podarilo dostat
57 takhle daleko..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
58
59 {[ DIALOG enemy(4) text="Co s nim udelame?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
60
61 {[ DIALOG enemy(5) text="Jak naridil Holotz..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
62
63 {[ DIALOG enemy(5) text="...vezmeme jej do
64 Labyrintu Froj." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
65
66 {[ DIALOG enemy(5) text="Zustane tam,
67 nez Holotz rozhodne,
68 co s nim..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
69
70 {[ DIALOG enemy(5) text="...Jestli jej teda
71 driv nenajdou
72 4 sileni bratri." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
73
74 {[ DIALOG enemy(1) text="Har, har!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=20 subtype=0 ]
75 [ DIALOG enemy(2) text="Hur, hur, hur!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 25
2 # Holotz appears
3 ##########################################
4
5 {
6 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
7 [ NARRATIVE text="Holotz" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
8 }
9
10 {[ MOVE enemy(0) dir=9 amount=2 ]}
11
12 {[ MOVE main(0) dir=4 amount=2 ]
13 [ DIALOG main(0) text="Silou Hutazina!..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
14
15 {[ MOVE enemy(0) dir=9 amount=1 ]}
16 {[ MOVE enemy(0) dir=9 amount=1 ]}
17
18 {[ MOVE main(0) dir=6 amount=3 ]
19 [ DIALOG main(0) text="Elementalni portale,
20 otevri se!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
21
22 {[ MOVE enemy(0) dir=9 amount=1 ]}
23
24 {[ WAIT millis=3000 ]}
25
26 {[ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
27
28 {[ MOVE main(0) dir=5 amount=1 ]
29 [ DIALOG main(0) text="Opet selhal!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
30
31 {[ MOVE main(0) dir=4 amount=2 ]
32 [ MOVE enemy(0) dir=9 amount=1 ]
33 [ DIALOG main(0) text="Ty!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
34
35 {[ DIALOG main(0) text="Kde je Lizarnit?" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
36
37 {[ DIALOG enemy(0) text="Hodili jsme jej
38 do Labyrintu Froj,
39 jak jste nakazal." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
40
41 {[ DIALOG main(0) text="Vyborne." txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
42
43 {[ DIALOG enemy(0) text="Ale mel byste vedet," txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
44
45 {[ DIALOG enemy(0) text="ze mel boty, pane." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
46
47 {[ DIALOG main(0) text="Idiote!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
48
49 {[ DIALOG main(0) text="Idiote!
50 Proc jsi mi o tom nerekl?" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
51
52 {[ DIALOG enemy(0) text="Ja..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
53
54 {[ DIALOG main(0) text="S takovou rychlosti
55 uz urcite dosahli veze." txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
56
57 {[ DIALOG main(0) text="Vypustte vsechny bestie!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
58
59 {[ DIALOG enemy(0) text="Ano, pane." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
60
61 {[ MOVE enemy(0) dir=7 amount=2 ]}
62
63 {[ MOVE enemy(0) dir=7 amount=3 ]
64 [ DIALOG main(0) text="Posleme tem Lizarnitum
65 male prekvapeni..." txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 30
2 # Ybelle and Ludar met again
3 ##########################################
4
5 {[ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
6
7 {[ MOVE main(0) dir=8 amount=6 ]
8 [ MOVE enemy(0) dir=8 amount=6 ]
9 [ MOVE enemy(1) dir=8 amount=6 ]
10 [ MOVE enemy(2) dir=8 amount=6 ]}
11
12 {[ MOVE main(0) dir=6 amount=3 ]
13 [ MOVE enemy(0) dir=4 amount=3 ]
14 [ MOVE enemy(1) dir=8 amount=4 ]
15 [ MOVE enemy(2) dir=8 amount=4 ]}
16
17 {[ MOVE main(0) dir=6 amount=4 ]
18 [ MOVE enemy(0) dir=4 amount=4 ]
19 [ MOVE enemy(1) dir=4 amount=3 ]
20 [ MOVE enemy(2) dir=6 amount=3 ]}
21
22 {[ DIALOG main(0) text="Ludare!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
23 [ DIALOG enemy(0) text="Ybelle!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
24
25 {[ DIALOG main(0) text="Ty zijes!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
26 [ DIALOG enemy(0) text="Ty nejsi mrtvy!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
27
28 {[ DIALOG enemy(0) text="Skvele, muzeme
29 pokracovat spolu." txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]}
30
31 {[ DIALOG enemy(0) text="Na zebrik, jdeme!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
32
33 {[ MOVE main(0) dir=8 amount=3 ]
34 [ MOVE enemy(0) dir=8 amount=3 ]}
0 ##########################################
1 # Holotz's Castle story - Level 32
2 # Return to the land of Lizarno
3 ##########################################
4
5 {[ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCCredits.wav" loops=-1 waitToEnd=0 ]}
8
9 {[ DIALOG main(0) text="To je Lizarno!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
10
11 {[ DIALOG enemy(0) text="Jsme zpatky!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
12
13 {[ DIALOG main(0) text="Eh, podivej, ten kamen!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
14 [ MOVE main(0) dir=4 amount=2 ]}
15
16 {[ DIALOG enemy(0) text="Nedotykej se ho!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
17
18 {[ MOVE main(0) dir=4 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 33
2 # The end
3 ##########################################
4
5 {[ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
7
8 {
9 [ NARRATIVE text="
10 KONEC
11 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
12 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle and Ludar arrive to the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
8 }
9
10 {
11 [ NARRATIVE text="Ybelle und Ludar." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
12 }
13
14 {
15 [ DIALOG main(0) text="Was war das?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=6 amount=2 ]
17 [ MOVE enemy(0) dir=6 amount=3 ]
18 }
19
20 {
21 [ DIALOG enemy(0) text="Und ich sage noch:
22 FASS DEN STEIN NICHT AN!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Ja ja, ist ja gut..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
27 }
28
29 {
30 [ DIALOG main(0) text="Woher soll ich denn ahnen,
31 was dann passiert?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
32 }
33
34 {
35 [ DIALOG main(0) text="Wo sind wir eigentlich?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
36 }
37
38 {
39 [ DIALOG enemy(0) text="Ha! Woher soll ich
40 das denn wissen?" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
41 }
42
43 {
44 [ DIALOG enemy(0) text="Wenn du nicht das
45 angefasst hättest,
46 was du nicht hättest
47 anfassen sollen..." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
48 }
49
50 {
51 [ DIALOG main(0) text="Trampel..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
52 [ DIALOG enemy(0) text="Trottel..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
53 }
54
55 {
56 [ DIALOG main(0) text="Wir müssen wieder
57 einen Weg nach
58 Hause finden." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
59 }
60
61 {
62 [ DIALOG main(0) text="Folge mir, Ludar!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
63 }
64
65 {
66 [ DIALOG enemy(0) text="Nein! Du bringst
67 mich ständig
68 in Schwierigkeiten!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
69 }
70
71 {
72 [ DIALOG enemy(0) text="Diesmal machen
73 wir, was ich sage!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
74 }
75
76 {
77 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
78 }
79
80 {
81 [ DIALOG main(0) text="Gut, dann gehe
82 ich eben alleine..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
83 [ MOVE main(0) dir=6 amount=5 ]
84 }
85
86 {
87 [ DIALOG enemy(0) text="???" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
88 [ MOVE main(0) dir=8 amount=3 ]
89 }
90
91 {
92 [ MOVE enemy(0) dir=6 amount=3 ]
93 [ DIALOG enemy(0) text="Ähm... Ybelle!
94 Warte auf mich!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
95 }
96
97 {
98 [ MOVE main(0) dir=6 amount=3 ]
99 }
0 ##########################################
1 # Holotz's Castle story - Level 2
2 # Ybelle enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Nein!" txtAlign=4 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
6 }
7
8 {
9 [ DIALOG main(0) text="Das tat weh!" txtAlign=4 speed=2 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
10 }
11
12 {
13 [ DIALOG main(0) text="LUDAR!" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
14 }
15
16 {
17 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=1 ]
18 }
19
20 {
21 [ DIALOG main(0) text="...scheint so, als
22 könnte er mich nicht hören." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Nun..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
27 [ MOVE main(0) dir=6 amount=1 ]
28 }
29
30 {
31 [ MOVE main(0) dir=4 amount=1 ]
32 [ DIALOG main(0) text="Wieso liegen hier
33 nur so viele
34 Schlüssel rum?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]}
0 ##########################################
1 # Holotz's Castle story - Level 7
2 # Ludar enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Ähm... Ybelle,
6 Warte auf mich!" txtAlign=4 speed=2 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ MOVE main(0) dir=6 amount=2 ]
8 }
9
10 {
11 [ MOVE main(0) dir=6 amount=1 ]
12 [ DIALOG main(0) text="Oh, nein!" txtAlign=4 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
13 }
14
15 {
16 [ DIALOG main(0) text="Wo kam denn
17 dieses Loch her?" txtAlign=4 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
18 }
19
20 {
21 [ DIALOG main(0) text="Ybelle!" txtAlign=5 speed=1 size=3 align=0 r=20 g=200 b=20 subtype=0 ]
22 }
23
24 {
25 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
26 }
27
28 {
29 [ DIALOG main(0) text="Das ist dumm!" txtAlign=5 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
30 }
31
32 {
33 [ DIALOG main(0) text="Oh, schau!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=4 amount=1 ]
35 }
36
37 {
38 [ DIALOG main(0) text="Diese Steine sehen
39 so aus wie der, den
40 Ybelle angefasst hat." txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
41 [ MOVE main(0) dir=4 amount=1 ]
42 }
43
44 {
45 [ DIALOG main(0) text="Was ist das hier für ein seltsamer Ort?" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
46 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle finds the shoe maker
3 ##########################################
4
5 {[ DIALOG main(0) text="?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Was ist das für ein Ort?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
9
10 {[ NARRATIVE text="Schuhmachers" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
11 [ MOVE main(0) dir=6 amount=1 ]}
12
13 {[ MOVE main(0) dir=2 amount=3 ]}
14
15 {[ MOVE main(0) dir=6 amount=2 ]}
16
17 {[ MOVE main(0) dir=9 amount=2 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]}
20
21 {[ MOVE main(0) dir=9 amount=1 ]
22 [ DIALOG enemy(0) text="Ooh, ein
23 Besucher!" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=1 ]}
24
25 {[ MOVE main(0) dir=9 amount=2 ]}
26
27 {[ DIALOG main(0) text="Was für eine
28 seltsame Gestalt!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
29 [ DIALOG enemy(0) text="Was für eine
30 seltsame Gestalt!" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=1 ]
31 }
32
33 {[ DIALOG main(0) text="Ähm... Hallo?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
34
35 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
36
37 {[ DIALOG enemy(0) text="Du scheinst
38 nicht..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="...von hier
41 zu sein." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
44 [ DIALOG main(0) text="Sieht aus,
45 als ob er im Begriff
46 ist einzuschlafen!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
47
48 {[ DIALOG enemy(0) text="Du bist
49 neu hier,..." txtAlign=5 speed=1 size=0 align=0 r=200 g=130 b=20 subtype=0 ]}
50
51 {[ DIALOG enemy(0) text="...gerade..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
52
53 {[ DIALOG enemy(0) text="...angekommen?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
54
55 {[ DIALOG main(0) text="Verstehe...
56 neu hier, sagst du?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
57
58 {[ DIALOG main(0) text="Oh, ja,
59 vielleicht" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
60
61 {[ DIALOG main(0) text="Wer bist
62 du?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
63
64 {[ DIALOG enemy(0) text="Ich bin..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
65
66 {[ DIALOG enemy(0) text="...der Herr
67 der Schuhe" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=0 ]}
68
69 {[ DIALOG enemy(0) text="Ich gehe davon aus..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
70
71 {[ DIALOG enemy(0) text="...du
72 kommst..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
73
74 {[ DIALOG enemy(0) text="...wegen ein
75 Paar neuer Schuhe..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
76
77 {[ DIALOG enemy(0) text="...richtig?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
78
79 {[ DIALOG enemy(0) text="Nimm..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
80 [ DIALOG main(0) text="Bekomme ich..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
81
82 {[ DIALOG enemy(0) text="...diese" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
83
84 {[ MOVE main(0) dir=6 amount=2 ]}
85 {[ MOVE main(0) dir=4 amount=2 ]}
86
87 {[ DIALOG enemy(0) text="Bestimmt..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
88
89 {[ DIALOG enemy(0) text="...bewegst
90 du dich..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
91
92 {[ DIALOG enemy(0) text="...sicherer
93 mit ihnen..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
94
95 {[ DIALOG main(0) text="Weisst du
96 einen Weg, wie
97 man hier raus kommt?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
98
99 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
100
101 {[ DIALOG enemy(0) text="...nein" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
102
103 {[ DIALOG enemy(0) text="...nur
104 Holotz..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
105
106 {[ DIALOG enemy(0) text="...weiss es" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
107
108 {[ DIALOG main(0) text="Holotz?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
109
110 {[ DIALOG enemy(0) text="Ja..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
111
112 {[ DIALOG enemy(0) text="Er erbaute..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
113
114 {[ DIALOG enemy(0) text="...dieses
115 Schloss" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
116
117 {[ DIALOG main(0) text="Wo kann ich
118 ihn finden?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
119
120 {[ DIALOG enemy(0) text="...du kannst
121 es nicht" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
122
123 {[ DIALOG enemy(0) text="Er..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
124
125 {[ DIALOG enemy(0) text="...wird dich finden" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
126
127 {[ DIALOG enemy(0) text="Nun
128 muss..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
129
130 {[ DIALOG enemy(0) text="...ich" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
131
132 {[ DIALOG enemy(0) text="...weiterarbeiten" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
133
134 {[ DIALOG main(0) text="A-aber...!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
135 [ DIALOG enemy(0) text="Nun
136 muss ich..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
137
138 {[ DIALOG main(0) text="Lass es,
139 es ist Unsinn." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
140
141 {[ DIALOG main(0) text="Nun, ich gehe...
142 Danke für
143 die Schuhe!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
144 [ MOVE main(0) dir=7 amount=2 ]}
145
146 {[ MOVE main(0) dir=7 amount=2 ]}
147
148 {[ DIALOG main(0) text="Und, wie geht's
149 nun weiter?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
150
151 {[ DIALOG main(0) text="Ach, wen interessiert's..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
152 [ MOVE main(0) dir=4 amount=1 ]}
153
154 {[ MOVE main(0) dir=2 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ludar talks to the two flames
3 ##########################################
4
5 {[ DIALOG main(0) text="Uups!" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_UltraSlow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Oh, noch
9 ein Stein!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
10 [ MOVE main(0) dir=6 amount=1 ]}
11
12 {[ NARRATIVE text="Die zwei Flammen" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=4 ]
14 [ DIALOG main(0) text="Noch einer!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
15
16 {[ DIALOG enemy(0) text="Halt!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
17
18 {[ DIALOG main(0) text="???" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
19 [ MOVE main(0) dir=4 amount=1 ]}
20
21 {[ DIALOG main(0) text="Ist da jemand?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
22 [ MOVE main(0) dir=6 amount=4 ]}
23
24 {[ DIALOG enemy(0) text="Ich sagte
25 HALT!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
26
27 {[ MOVE main(0) dir=4 amount=4 ]
28 [ DIALOG main(0) text="Oh, eine sprechende
29 Flamme!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]}
30
31 {[ DIALOG enemy(0) text="Ich bin keine
32 sprechende Flamme!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]
33 [ DIALOG main(0) text="Oh!" txtAlign=5 speed=4 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=6 amount=2 ]}
35
36 {[ DIALOG enemy(0) text="Ich bin eine
37 redende Flamme!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
38
39 {[ DIALOG main(0) text="Woher weißt
40 du, was ich denke?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
41
42 {[ DIALOG enemy(0) text="Ich weiß
43 alles!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
44
45 {[ DIALOG enemy(1) text="Ähm..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
46
47 {[ DIALOG enemy(0) text="Nun, fast
48 alles" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
49
50 {[ DIALOG enemy(1) text="Wir lesen
51 Gedanken..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
52
53 {[ DIALOG enemy(1) text="Und ich lese..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
54
55 {[ DIALOG enemy(1) text="...Bücher" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
56
57 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]
58 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]
59 [ DIALOG main(0) text="??!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
60
61 {[ DIALOG enemy(1) text="Wie bist du
62 hierher gekommen?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
63
64 {[ DIALOG enemy(0) text="Ich weiß..." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
65
66 {[ DIALOG main(0) text="Oh, Du liest
67 gerade meine Gedanken!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]}
68
69 {[ DIALOG enemy(0) text="Beim
70 mystischen
71 Portal!" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
72
73 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
74 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=3 align=0 r=20 g=20 b=180 subtype=0 ]
75 [ DIALOG main(0) text="hmpfxs#@!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
76 [ MOVE main(0) dir=6 amount=4 ]}
77
78 {[ DIALOG enemy(1) text="Warte, gehe
79 nicht" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
80 [ MOVE main(0) dir=4 amount=5 ]}
81
82 {[ DIALOG main(0) text="Ich habe
83 keine Zeit
84 für Witze!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
85 [ MOVE main(0) dir=6 amount=2 ]}
86
87 {[ DIALOG enemy(0) text="Was
88 willst du?" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]
89 [ MOVE main(0) dir=4 amount=3 ]}
90
91 {[ DIALOG main(0) text="Ich will
92 Ybelle finden" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
93
94 {[ DIALOG main(0) text="Wir müssen
95 ins Land von
96 Lizarno
97 zurückkehren" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
98
99 {[ DIALOG enemy(0) text="Hmmm...ein Lizarnit,
100 wie interessant" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=1 ]}
101
102 {[ DIALOG enemy(1) text="Von nun an
103 dreht sich
104 das Schloss" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
105
106 {[ DIALOG enemy(1) text="viel gefährlicher" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
107
108 {[ DIALOG enemy(1) text="aber du
109 hast nicht genug
110 magische Energie" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
111
112 {[ DIALOG enemy(1) text="um die höchste
113 Ebene zu erreichen" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
114
115 {[ DIALOG enemy(0) text="Ja, was du
116 brauchst ist..." txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
117
118 {[ DIALOG enemy(1) text="ein paar
119 Schuhe!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
120 [ DIALOG enemy(0) text="Ein paar
121 Schuhe!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
122
123 {[ DIALOG main(0) text="Oh, veralber
124 mich nicht!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
125 [ MOVE main(0) dir=4 amount=2 ]}
126
127 {[ DIALOG enemy(0) text="Aber du bekommst
128 sie nur beim" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
129
130 {[ DIALOG enemy(0) text="Herr der
131 der Schuhe" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
132
133 {[ DIALOG main(0) text="Gibt es keinen
134 anderen Weg, um an
135 ein Paar Schuhe zu kommen?" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
136 [ MOVE main(0) dir=6 amount=2 ]}
137
138 {[ DIALOG enemy(1) text="Ja, du kannst
139 sie im" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=60 subtype=0 ]}
140
141 {[ DIALOG enemy(1) text="Schuhladen kaufen!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=60 subtype=0 ]
142 [ DIALOG enemy(0) text="Schuhladen kaufen!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]}
143
144 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
145 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]
146 [ DIALOG main(0) text="Das ist schier
147 zum verzweifeln!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
148 [ MOVE main(0) dir=6 amount=4 ]}
149
150 {[ DIALOG enemy(1) text="Warte!" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
151 [ MOVE main(0) dir=4 amount=2 ]}
152
153 {[ DIALOG enemy(1) text="Du kannst welche
154 im Raum" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
155
156 {[ DIALOG enemy(1) text="hinter dem
157 mystischen Portal
158 bekommen." txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
159
160 {[ DIALOG enemy(0) text="Aber du musst
161 wissen," txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
162
163 {[ DIALOG enemy(0) text="dass niemand dort wieder
164 lebend heraus gekommen ist!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
165
166 {[ DIALOG main(0) text="Oh!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
167 [ MOVE main(0) dir=6 amount=2 ]}
168
169 {[ DIALOG main(0) text="Hmm... Egal,
170 ich muss es probieren" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
171 [ MOVE main(0) dir=4 amount=2 ]}
172
173 {[ DIALOG main(0) text="Oh!, ich kann
174 das Portal
175 nicht öffnen" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
176 [ MOVE main(0) dir=4 amount=2 ]}
177
178 {[ DIALOG main(0) text="Dieser Stein
179 ist zu hoch!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
180
181 {[ DIALOG enemy(1) text="Nun, warum benutzt
182 du nicht diese Leiter?" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 19
2 # Ybelle is captured
3 ##########################################
4
5 {[ DIALOG main(0) text="AAAH!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_Fast.wav" loops=0 waitToEnd=0 ]}
7
8 {[ MOVE enemy(0) dir=8 amount=4 ]
9 [ MOVE enemy(1) dir=8 amount=4 ]
10 [ MOVE enemy(2) dir=4 amount=2 ]
11 [ MOVE enemy(3) dir=6 amount=2 ]
12 [ MOVE enemy(4) dir=4 amount=5 ]
13 [ MOVE enemy(5) dir=6 amount=5 ]
14 [ DIALOG main(0) text="Oh, oh" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
15 [ DIALOG enemy(2) text="!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=1 ]
16 [ DIALOG enemy(3) text="!" txtAlign=5 speed=1 size=2 align=0 r=220 g=20 b=20 subtype=1 ]}
17
18 {[ NARRATIVE text="
19 Fortsetzung folgt...
20 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
21 [ DIALOG main(0) text="??!" txtAlign=5 speed=3 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=5 amount=1 ]}
23
24 {[ DIALOG main(0) text="Iiih!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
25 [ MOVE main(0) dir=5 amount=2 ]}
26
27 {[ DIALOG main(0) text="Lass mich nicht hier!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
28 [ MOVE main(0) dir=5 amount=2 ]}
29
30 {[ WAIT millis=3000]}
0 ##########################################
1 # Holotz's Castle story - Level 20
2 # Ybelle is captured (continued)
3 ##########################################
4
5 {[ MOVE enemy(0) dir=8 amount=0 ]
6 [ MOVE enemy(1) dir=8 amount=0 ]
7 [ MOVE enemy(2) dir=4 amount=0 ]
8 [ MOVE enemy(3) dir=6 amount=0 ]
9 [ MOVE enemy(4) dir=4 amount=0 ]
10 [ MOVE enemy(5) dir=6 amount=0 ]}
11
12 {[ WAIT millis=1000]}
13
14 {[ DIALOG main(0) text="Halt, keine
15 Bewegung!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=4 amount=1 ]}
17
18 {[ DIALOG enemy(0) text="Je je" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]
19 [ DIALOG enemy(1) text="Hmmm" txtAlign=5 speed=5 size=3 align=0 r=200 g=20 b=20 subtype=0 ]}
20
21 {[ DIALOG main(0) text="Ich warne dich,
22 ich bin gefährlich!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
23 [ MOVE main(0) dir=6 amount=2 ]}
24
25 {[ MOVE enemy(1) dir=4 amount=3 ]
26 [ DIALOG enemy(1) text="Schau..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
27
28 {[ MOVE enemy(1) dir=4 amount=1 ]
29 [ DIALOG enemy(5) text="Was?" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
30
31 {[ DIALOG enemy(1) text="Er hat Schuhe." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
32
33 {[ DIALOG enemy(5) text="Hmmm...
34 Holotz wird nicht
35 erfreut sein." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
36
37 {[ DIALOG main(0) text="Was willst Du?" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
38
39 {[ MOVE enemy(5) dir=6 amount=4 ]
40 [ MOVE main(0) dir=6 amount=1 ]
41 [ DIALOG enemy(5) text="Die Frage ist..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(5) text="Wie kommst
44 du hierher?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
45
46 {[ DIALOG main(0) text="Ich nahm einen
47 Stein und..." txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
48
49 {[ DIALOG enemy(5) text="und ein mystisches Portal
50 öffnete sich, richtig?." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
51
52 {[ DIALOG main(0) text="Ja, genau so!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
53
54 {[ DIALOG enemy(5) text="Sieht aus, wie eins
55 von Holotz's Experimenten." txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
56
57 {[ DIALOG enemy(5) text="Unvollendet." txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
58
59 {[ DIALOG enemy(5) text="Ich finde es lustig,
60 das du so weit
61 gegangen bist..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
62
63 {[ DIALOG enemy(4) text="Was wollen wir mit
64 ihm machen?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
65
66 {[ DIALOG enemy(5) text="Wie Holotz
67 gesagt hat..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
68
69 {[ DIALOG enemy(5) text="...wir bringen ihn
70 ins Labyrinth
71 von Froj." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
72
73 {[ DIALOG enemy(5) text="Er bleibt dort,
74 bis Holotz entscheidet,
75 was mit ihm zu tun ist..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
76
77 {[ DIALOG enemy(5) text="...wenn die vier
78 verrückten Brüder ihn nicht
79 vorher finden." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
80
81 {[ DIALOG enemy(1) text="Har, har!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=20 subtype=0 ]
82 [ DIALOG enemy(2) text="Hur, hur, hur!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 25
2 # Holotz appears
3 ##########################################
4
5 {
6 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
7 [ NARRATIVE text="Holotz." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
8 }
9
10 {[ MOVE enemy(0) dir=9 amount=2 ]}
11
12 {[ MOVE main(0) dir=4 amount=2 ]
13 [ DIALOG main(0) text="Bei der Macht
14 von Hutazin!..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
15
16 {[ MOVE enemy(0) dir=9 amount=1 ]}
17 {[ MOVE enemy(0) dir=9 amount=1 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]
20 [ DIALOG main(0) text="Elementares Portal,
21 öffene dich!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
22
23 {[ MOVE enemy(0) dir=9 amount=1 ]}
24
25 {[ WAIT millis=3000 ]}
26
27 {[ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
28
29 {[ MOVE main(0) dir=5 amount=1 ]
30 [ DIALOG main(0) text="Es hat wieder
31 nicht geklappt!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
32
33 {[ MOVE main(0) dir=4 amount=2 ]
34 [ MOVE enemy(0) dir=9 amount=1 ]
35 [ DIALOG main(0) text="Du!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
36
37 {[ DIALOG main(0) text="Wo ist der
38 Lizarnit?" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="Wir haben ihn ins
41 Labyrinth von Froj gebracht,
42 wir ihr es uns sagtet." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
43
44 {[ DIALOG main(0) text="Gut gemacht!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
45
46 {[ DIALOG enemy(0) text="Aber ihr müsst wissen," txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="dass er Schuhe
49 hatte, Herr!" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
50
51 {[ DIALOG main(0) text="Trottel!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
52
53 {[ DIALOG main(0) text="Trottel!
54 Wieso hast du das
55 mir nicht mitgeteilt!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
56
57 {[ DIALOG enemy(0) text="Ich..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
58
59 {[ DIALOG main(0) text="Bei der Geschwindigkeit
60 werden sie den Turm erreicht haben!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
61
62 {[ DIALOG main(0) text="Holt all
63 die Monster!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="Ja, Herr!" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
66
67 {[ MOVE enemy(0) dir=7 amount=2 ]}
68
69 {[ MOVE enemy(0) dir=7 amount=3 ]
70 [ DIALOG main(0) text="Diesen Lizarniten
71 werden wir eine schöne
72 Überraschung bereiten!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 30
2 # Ybelle and Ludar met again
3 ##########################################
4
5 {[ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
6
7 {[ MOVE main(0) dir=8 amount=6 ]
8 [ MOVE enemy(0) dir=8 amount=6 ]
9 [ MOVE enemy(1) dir=8 amount=6 ]
10 [ MOVE enemy(2) dir=8 amount=6 ]}
11
12 {[ MOVE main(0) dir=6 amount=3 ]
13 [ MOVE enemy(0) dir=4 amount=3 ]
14 [ MOVE enemy(1) dir=8 amount=4 ]
15 [ MOVE enemy(2) dir=8 amount=4 ]}
16
17 {[ MOVE main(0) dir=6 amount=4 ]
18 [ MOVE enemy(0) dir=4 amount=4 ]
19 [ MOVE enemy(1) dir=4 amount=3 ]
20 [ MOVE enemy(2) dir=6 amount=3 ]}
21
22 {[ DIALOG main(0) text="Ludar!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
23 [ DIALOG enemy(0) text="Ybelle!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
24
25 {[ DIALOG main(0) text="Du lebst!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
26 [ DIALOG enemy(0) text="Du bist nicht tot!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
27
28 {[ DIALOG enemy(0) text="Nun, dann können wir
29 zusammen weitermachen!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]}
30
31 {[ DIALOG enemy(0) text="Zur Leiter,
32 folge mir!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
33
34 {[ MOVE main(0) dir=8 amount=3 ]
35 [ MOVE enemy(0) dir=8 amount=3 ]}
0 ##########################################
1 # Holotz's Castle story - Level 32
2 # Return to the land of Lizarno
3 ##########################################
4
5 {[ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCCredits.wav" loops=-1 waitToEnd=0 ]}
8
9 {[ DIALOG main(0) text="Es ist Lizarno!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
10
11 {[ DIALOG enemy(0) text="Wir sind zurück!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
12
13 {[ DIALOG main(0) text="Eh, schau dir
14 diesen Stein an!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
15 [ MOVE main(0) dir=4 amount=2 ]}
16
17 {[ DIALOG enemy(0) text="Fass ihn nicht an!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
18
19 {[ MOVE main(0) dir=4 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 33
2 # The end
3 ##########################################
4
5 {[ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
7
8 {
9 [ NARRATIVE text="
10 THE END
11 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
12 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle and Ludar arrive to the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
8 }
9
10 {
11 [ NARRATIVE text="Ybelle and Ludar." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
12 }
13
14 {
15 [ DIALOG main(0) text="Whoa! What happened?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=6 amount=2 ]
17 [ MOVE enemy(0) dir=6 amount=3 ]
18 }
19
20 {
21 [ DIALOG enemy(0) text="I told you
22 not to touch
23 that stone!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
24 }
25
26 {
27 [ DIALOG main(0) text="Oh, be quiet..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
28 }
29
30 {
31 [ DIALOG main(0) text="How was I
32 to know?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
33 }
34
35 {
36 [ DIALOG main(0) text="Where are we?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
37 }
38
39 {
40 [ DIALOG enemy(0) text="HA! You
41 tell me!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
42 }
43
44 {
45 [ DIALOG enemy(0) text="If you had just
46 kept your hands off..." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
47 }
48
49 {
50 [ DIALOG main(0) text="Lump..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
51 [ DIALOG enemy(0) text="Nincompoop..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
52 }
53
54 {
55 [ DIALOG main(0) text="We have to find
56 a way to
57 return home" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
58 }
59
60 {
61 [ DIALOG main(0) text="Follow me, Ludar" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
62 }
63
64 {
65 [ DIALOG enemy(0) text="No way, José! You're
66 always getting me
67 into trouble" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
68 }
69
70 {
71 [ DIALOG enemy(0) text="This time we'll
72 do what I say" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
73 }
74
75 {
76 [ DIALOG main(0) text="Well..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
77 }
78
79 {
80 [ DIALOG main(0) text="I guess I'll
81 go alone" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
82 [ MOVE main(0) dir=6 amount=5 ]
83 }
84
85 {
86 [ DIALOG enemy(0) text="???" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
87 [ MOVE main(0) dir=8 amount=3 ]
88 }
89
90 {
91 [ MOVE enemy(0) dir=6 amount=3 ]
92 [ DIALOG enemy(0) text="err... Ybelle,
93 Wait up!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
94 }
95
96 {
97 [ MOVE main(0) dir=6 amount=3 ]
98 }
0 ##########################################
1 # Holotz's Castle story - Level 2
2 # Ybelle enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Noooo!" txtAlign=4 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 }
7
8 {
9 [ DIALOG main(0) text="That hurt!" txtAlign=4 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
10 }
11
12 {
13 [ DIALOG main(0) text="LUDAR!" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
14 }
15
16 {
17 [ DIALOG main(0) text="?" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=1 ]
18 }
19
20 {
21 [ DIALOG main(0) text="Maybe he
22 can't hear me." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="What the...?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
27 [ MOVE main(0) dir=6 amount=1 ]
28 }
29
30 {
31 [ MOVE main(0) dir=4 amount=1 ]
32 [ DIALOG main(0) text="What's with all
33 the keys?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
34
35 }
36
37 # REMIND USER THAT THIS IS YBELLE.
38 # TEACH THE USER THAT SPACE IS JUMP.
39 # MAKE SURE THEY KNOW WHAT A "MAGIC PORTAL" IS, TO SET UP THE JOKE IN LEVEL 16.
40 {
41 [ NARRATIVE text="Press space to make Ybelle
42 jump into the magic portal" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
43 }
0 ##########################################
1 # Holotz's Castle story - Level 7
2 # Ludar enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="err... Ybelle,
6 Wait for me!" txtAlign=4 speed=2 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ MOVE main(0) dir=6 amount=2 ]
8 }
9
10 {
11 [ MOVE main(0) dir=6 amount=1 ]
12 [ DIALOG main(0) text="Oh, no!" txtAlign=4 speed=5 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
13 }
14
15
16 {
17 [ DIALOG main(0) text="Who put that
18 hole there?" txtAlign=4 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
19 }
20
21 {
22 [ DIALOG main(0) text="Help! Ybelle!" txtAlign=5 speed=1 size=3 align=0 r=20 g=200 b=20 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Why won't
27 he answer?" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
28 }
29
30 {
31 [ DIALOG main(0) text="You stubborn fool!" txtAlign=5 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
32 }
33
34 {
35 [ DIALOG main(0) text="Oh, hey!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
36 [ MOVE main(0) dir=4 amount=1 ]
37 }
38
39 {
40 [ DIALOG main(0) text="Those stones are
41 similar to the one
42 Ybelle took" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
43 [ MOVE main(0) dir=4 amount=1 ]
44 }
45
46 {
47 # EXPLAIN WHY YBELLE IS GRABBING STONES AFTER HE TOLD LUDAR NOT TO
48 [ DIALOG main(0) text="Could they be
49 the way out of here?" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
50 [ MOVE main(0) dir=4 amount=1 ]
51 }
52
53 {
54 # SHOULD GIVE USER A HINT THAT GAME IS STARTING AS LUDAR
55 [ DIALOG main(0) text="I guess it's my turn
56 to take a risk" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
57 }
58
59 # MORE HINTS FOR THE USER AND A REMINDER THAT THIS GUY IS LUDAR
60 {
61 [ NARRATIVE text="Holding space makes Ludar jump higher" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
62 }
0 ##########################################
1 # Holotz's Castle story - Level 14
2 # Ybelle finds the shoe maker
3 ##########################################
4
5 {[ DIALOG main(0) text="Whew!
6 I'm glad to be
7 out of there" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
8 [ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
9
10 {[ DIALOG main(0) text="But, what's this place?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
11
12 {[ NARRATIVE text="Ybelle in The Shoemaker's Workshop" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=1 ]}
14
15 {[ MOVE main(0) dir=2 amount=3 ]}
16
17 {[ MOVE main(0) dir=6 amount=2 ]}
18
19 {[ MOVE main(0) dir=9 amount=2 ]}
20
21 {[ MOVE main(0) dir=6 amount=3 ]}
22
23 {[ MOVE main(0) dir=9 amount=1 ]
24 [ DIALOG enemy(0) text="A visitor!" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=1 ]}
25
26 {[ MOVE main(0) dir=9 amount=2 ]}
27
28 {[ DIALOG main(0) text="What a
29 strange guy!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
30 [ DIALOG enemy(0) text="What a
31 strange guy!" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=1 ]
32 }
33
34 {[ DIALOG main(0) text="Err.. Hello?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
35
36 {[ DIALOG enemy(0) text="You..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
37
38 {[ DIALOG enemy(0) text="seem..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="not..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
41 [ DIALOG main(0) text="?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
42
43
44 {[ DIALOG enemy(0) text="to..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
45
46 {[ DIALOG enemy(0) text="be..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="from..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
49
50 {[ DIALOG enemy(0) text="here" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
51
52 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
53 [ DIALOG main(0) text="Looks like
54 he was going
55 to fall asleep!!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
56
57 {[ DIALOG enemy(0) text="Are...
58 you...
59 the..." txtAlign=5 speed=1 size=0 align=1 r=200 g=130 b=20 subtype=0 ]}
60
61 {[ DIALOG main(0) text="Look... Oh" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
62 [ DIALOG enemy(0) text="new..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
63
64 {[ DIALOG main(0) text="New, you say?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
65
66 {[ DIALOG main(0) text="Why, yes,
67 I am new here" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
68
69 {[ DIALOG main(0) text="Who are you?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
70
71 {[ DIALOG enemy(0) text="I... am..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
72
73 {[ DIALOG enemy(0) text="The Lord of
74 The Shoes" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=0 ]}
75
76 {[ DIALOG enemy(0) text="You've...
77 come...
78 for..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
79
80 {[ DIALOG enemy(0) text="a...
81 new...
82 pair..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
83
84 {[ DIALOG enemy(0) text="...Right?" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
85 [ DIALOG main(0) text="Well,
86 actually" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
87
88 {[ DIALOG enemy(0) text="Take..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
89 [ DIALOG main(0) text="I..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
90
91 {[ DIALOG enemy(0) text="...these" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
92
93
94
95 {[ MOVE main(0) dir=6 amount=2 ]}
96 {[ MOVE main(0) dir=4 amount=2 ]}
97
98 {[ DIALOG enemy(0) text="Your...
99 jumps...
100 will..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
101
102 {[ DIALOG enemy(0) text="be..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
103 [ DIALOG main(0) text="Do you know
104 how to get
105 out of here?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
106 }
107
108 {[ DIALOG enemy(0) text="Let...
109 me...
110 think..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
111
112 {[ DIALOG enemy(0) text="No" txtAlign=5 speed=1 size=2 align=1 r=200 g=130 b=20 subtype=0 ]}
113
114 {[ DIALOG enemy(0) text="Only...
115 Holotz..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
116
117 {[ DIALOG enemy(0) text="knows..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
118 [ DIALOG main(0) text="Holotz?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
119
120 {[ DIALOG enemy(0) text="Yes..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
121 {[ DIALOG enemy(0) text="He...
122 created..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
123
124 {[ DIALOG enemy(0) text="this..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
125 [ DIALOG main(0) text="Where can
126 I find him?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
127
128 {[ DIALOG enemy(0) text="You...
129 can't..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
130
131 {[ DIALOG enemy(0) text="He'll...
132 find...
133 you" txtAlign=5 speed=1 size=2 align=1 r=200 g=130 b=20 subtype=0 ]}
134 {[ DIALOG main(0) text="!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
135
136
137 {[ DIALOG enemy(0) text="Now...
138 I...
139 must..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
140
141 {[ DIALOG enemy(0) text="return...
142 to...
143 work" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
144
145 {[ DIALOG main(0) text="B-but...!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
146 [ DIALOG enemy(0) text="Now...
147 I...
148 must..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
149
150 {[ DIALOG main(0) text="Oh, forget
151 this nonsense!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
152
153 {[ DIALOG main(0) text="Well, I'm going...
154 thanks for
155 the shoes" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
156 [ MOVE main(0) dir=7 amount=2 ]}
157
158 {[ MOVE main(0) dir=7 amount=2 ]}
159
160 {[ DIALOG main(0) text="But, where do
161 I go now?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
162
163 {[ DIALOG main(0) text="Oh well." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
164
165 {[ DIALOG main(0) text="When you're lost" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
166 [ MOVE main(0) dir=4 amount=1 ]}
167
168 {[ DIALOG main(0) text="any direction
169 is forward" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
170 {[ MOVE main(0) dir=2 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 16
2 # Ludar talks to the two flames
3 ##########################################
4
5 {[ DIALOG main(0) text="Oops" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_UltraSlow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Oh, another
9 stone!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
10 [ MOVE main(0) dir=6 amount=1 ]}
11
12 {[ NARRATIVE text="Ludar and the Two Flames" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=4 ]
14 [ DIALOG main(0) text="...and another!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
15
16 {[ DIALOG enemy(0) text="Halt!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
17
18 {[ DIALOG main(0) text="???" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
19 [ MOVE main(0) dir=4 amount=1 ]}
20
21 {[ DIALOG main(0) text="Who's here?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
22 [ MOVE main(0) dir=6 amount=4 ]}
23
24 {[ DIALOG enemy(0) text="I said
25 HALT!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
26
27 {[ MOVE main(0) dir=4 amount=4 ]
28 [ DIALOG main(0) text="Oh, a speaking
29 flame!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]}
30
31 {[ DIALOG enemy(0) text="I'm not a
32 speaking flame!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]
33 [ DIALOG main(0) text="Oh!" txtAlign=5 speed=4 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=6 amount=2 ]}
35
36 {[ DIALOG enemy(0) text="I'm a talking
37 flame!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
38
39 {[ DIALOG main(0) text="How did
40 you know
41 my thoughts?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(0) text="I know
44 everything!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
45
46 {[ DIALOG enemy(1) text="Ahem..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="Well, almost
49 everything" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
50
51 {[ DIALOG enemy(1) text="She reads
52 the mind..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
53
54 {[ DIALOG enemy(1) text="And I read..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
55
56 {[ DIALOG enemy(1) text="...Books" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
57
58 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]
59 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]
60 [ DIALOG main(0) text="??!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
61
62 {[ DIALOG enemy(1) text="How did you
63 get here?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="I know..." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
66
67 {[ DIALOG main(0) text="Oh, She's going
68 to read my mind!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]}
69
70 {[ DIALOG enemy(0) text="By the
71 mystic
72 portal!!" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
73
74 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
75 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=3 align=0 r=20 g=20 b=180 subtype=0 ]
76 [ DIALOG main(0) text="hmpfxs#@!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
77 [ MOVE main(0) dir=6 amount=4 ]}
78
79 {[ DIALOG enemy(1) text="Wait, don't
80 leave" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
81 [ MOVE main(0) dir=4 amount=5 ]}
82
83 {[ DIALOG main(0) text="I don't have
84 time for
85 jokes!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
86 [ MOVE main(0) dir=6 amount=2 ]}
87
88 {[ DIALOG enemy(0) text="What do
89 you need?" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]
90 [ MOVE main(0) dir=4 amount=3 ]}
91
92 {[ DIALOG main(0) text="I have to
93 find Ybelle" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
94
95 {[ DIALOG main(0) text="We have
96 to return
97 to the Land of
98 Lizarno" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
99
100 {[ DIALOG enemy(0) text="Hmmm...a Lizarnite,
101 how interesting" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=1 ]}
102
103 {[ DIALOG enemy(1) text="From here the
104 castle turns more
105 dangerous" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
106
107 {[ DIALOG enemy(1) text="But you lack
108 magical power" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
109
110 {[ DIALOG enemy(1) text="and cannot
111 reach the
112 highest level" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
113
114 {[ DIALOG enemy(0) text="Yes, what you
115 need is..." txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
116
117 {[ DIALOG enemy(1) text="A pair
118 of shoes!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
119 [ DIALOG enemy(0) text="A pair
120 of shoes!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
121
122 {[ DIALOG main(0) text="Oh, stop
123 joking!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
124 [ MOVE main(0) dir=4 amount=2 ]}
125
126 {[ DIALOG enemy(0) text="But you can only
127 obtain them from" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
128
129 {[ DIALOG enemy(0) text="The Lord of
130 The Shoes" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
131
132 {[ DIALOG main(0) text="Isn't there any
133 other way to get
134 a pair of shoes?" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
135 [ MOVE main(0) dir=6 amount=2 ]}
136
137 {[ DIALOG enemy(1) text="Yes, you can
138 obtain them in" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=60 subtype=0 ]}
139
140 {[ DIALOG enemy(1) text="The shoe store!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=60 subtype=0 ]
141 [ DIALOG enemy(0) text="The shoe store!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]}
142
143 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
144 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]
145 [ DIALOG main(0) text="This is
146 exasperating!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
147 [ MOVE main(0) dir=6 amount=4 ]}
148
149 {[ DIALOG enemy(1) text="Wait" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
150 [ MOVE main(0) dir=4 amount=2 ]}
151
152 {[ DIALOG enemy(1) text="You can find
153 a pair" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
154
155 {[ DIALOG enemy(1) text="in the room
156 beyond this
157 mystic portal" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
158
159 {[ DIALOG enemy(0) text="But you must
160 know" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
161
162 {[ DIALOG enemy(0) text="that nobody has
163 left it alive" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
164
165 {[ DIALOG main(0) text="Oh!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
166 [ MOVE main(0) dir=6 amount=2 ]}
167
168 {[ DIALOG main(0) text="Hmm... Well,
169 I must try" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
170 [ MOVE main(0) dir=4 amount=2 ]}
171
172 {[ DIALOG main(0) text="Oh! But I
173 can't open
174 the portal" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
175 [ MOVE main(0) dir=4 amount=2 ]}
176
177 {[ DIALOG main(0) text="That stone is
178 too high!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
179
180 {[ DIALOG enemy(1) text="Well, then
181 use this ladder" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 19
2 # Ybelle is captured
3 ##########################################
4
5 {[ DIALOG main(0) text="AAAH!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_Fast.wav" loops=0 waitToEnd=0 ]}
7
8 {[ MOVE enemy(0) dir=8 amount=4 ]
9 [ MOVE enemy(1) dir=8 amount=4 ]
10 [ MOVE enemy(2) dir=4 amount=2 ]
11 [ MOVE enemy(3) dir=6 amount=2 ]
12 [ MOVE enemy(4) dir=4 amount=5 ]
13 [ MOVE enemy(5) dir=6 amount=5 ]
14 [ DIALOG main(0) text="Uh oh" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
15 [ DIALOG enemy(2) text="!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=1 ]
16 [ DIALOG enemy(3) text="!" txtAlign=5 speed=1 size=2 align=0 r=220 g=20 b=20 subtype=1 ]}
17
18 {[ NARRATIVE text="
19 TO BE CONTINUED...
20 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
21 [ DIALOG main(0) text="??!" txtAlign=5 speed=3 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=5 amount=1 ]}
23
24 {[ DIALOG main(0) text="Eeeh!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
25 [ MOVE main(0) dir=5 amount=2 ]}
26
27 {[ DIALOG main(0) text="Don't leave me here!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
28 [ MOVE main(0) dir=5 amount=2 ]}
29
30 {[ WAIT millis=3000]}
0 ##########################################
1 # Holotz's Castle story - Level 20
2 # Ybelle is captured (continued)
3 ##########################################
4
5 {[ MOVE enemy(0) dir=8 amount=0 ]
6 [ MOVE enemy(1) dir=8 amount=0 ]
7 [ MOVE enemy(2) dir=4 amount=0 ]
8 [ MOVE enemy(3) dir=6 amount=0 ]
9 [ MOVE enemy(4) dir=4 amount=0 ]
10 [ MOVE enemy(5) dir=6 amount=0 ]}
11
12 {[ WAIT millis=1000]}
13
14 {[ DIALOG main(0) text="Halt, don't
15 move!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=4 amount=1 ]}
17
18 {[ DIALOG enemy(0) text="Hee hee" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]
19 [ DIALOG enemy(1) text="Huh?" txtAlign=5 speed=5 size=3 align=0 r=200 g=20 b=20 subtype=0 ]}
20
21 {[ DIALOG main(0) text="Don't make me
22 bust out my Kung Fu!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
23 [ MOVE main(0) dir=6 amount=2 ]}
24
25 {[ MOVE enemy(1) dir=4 amount=3 ]
26 [ DIALOG enemy(1) text="Look!" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
27
28 {[ MOVE enemy(1) dir=4 amount=1 ]
29 [ DIALOG enemy(5) text="What?" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
30
31 {[ DIALOG enemy(1) text="He has... shoes" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
32
33 {[ DIALOG enemy(5) text="Oh ho!
34 Holotz won't
35 like that" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
36
37 {[ DIALOG main(0) text="What do you want?" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
38
39 {[ MOVE enemy(5) dir=6 amount=4 ]
40 [ MOVE main(0) dir=6 amount=1 ]
41 [ DIALOG enemy(5) text="The question is..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(5) text="What are you
44 doing here?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
45
46 {[ DIALOG main(0) text="I took a
47 stone and..." txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
48
49 {[ DIALOG enemy(5) text="And a mystic portal
50 opened. Right?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
51
52 {[ DIALOG main(0) text="Yes, exactly!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
53
54 {[ DIALOG enemy(5) text="Seems that
55 Holotz's experiments
56 haven't succeeded" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
57
58 {[ DIALOG enemy(5) text="I'm amused
59 you have gotten
60 this far..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
61
62 {[ DIALOG enemy(4) text="What do we
63 do with him?" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=0 ]}
64
65 {[ DIALOG enemy(5) text="We do as
66 Holotz said..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
67
68 {[ DIALOG enemy(5) text="...we take him
69 to the Labyrinth
70 of Froj" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
71
72 {[ DIALOG enemy(5) text="There he'll stay
73 until Holotz decides
74 his fate..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
75
76 {[ DIALOG enemy(5) text="...if the four
77 crazy brothers
78 don't find him first!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
79
80 {[ DIALOG enemy(1) text="Har, har!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=20 subtype=0 ]
81 [ DIALOG enemy(2) text="Hur, hur, hur!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ] }
82
83 {[ DIALOG main(0) text="Gulp!" txtAlign=5 speed=5 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
84
85
86 # LET USER KNOW THEY'RE SWITCHING BACK TO LUDAR.
87 {[ DIALOG main(0) text="I hope
88 Ludar's okay..." txtAlign=5 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=1 ]}
89
90 {
91 [ NARRATIVE text="You can change Ludar's direction mid-jump." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
92 }
0 ##########################################
1 # Holotz's Castle story - Level 25
2 # Holotz appears
3 ##########################################
4
5
6 # This jump is just to scroll the screen up so the text is visible.
7 # A better fix would be to redesign the level so Holotz isn't so high up.
8 {[ MOVE main(0) dir=5 amount=1 ]}
9
10 {
11 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
12 [ NARRATIVE text="Holotz." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 }
14 {[ MOVE enemy(0) dir=9 amount=2 ]}
15
16 {[ MOVE main(0) dir=4 amount=2 ]
17 [ DIALOG main(0) text="By the power
18 of Hutazin!..." txtAlign=5 speed=5 size=2 align=1 r=80 g=80 b=200 subtype=0 ]}
19
20 {[ MOVE enemy(0) dir=9 amount=1 ]}
21 {[ MOVE enemy(0) dir=9 amount=1 ]}
22
23 {[ MOVE main(0) dir=6 amount=3 ]
24 [ DIALOG main(0) text="Elemental Portal,
25 open!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
26
27 {[ MOVE enemy(0) dir=9 amount=1 ]}
28
29 {[ WAIT millis=3000 ]}
30
31 {[ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=5 size=1 align=1 r=80 g=80 b=200 subtype=0 ]}
32
33 {[ MOVE main(0) dir=5 amount=1 ]
34 [ DIALOG main(0) text="It failed
35 again!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
36
37 {[ MOVE main(0) dir=4 amount=2 ]
38 [ MOVE enemy(0) dir=9 amount=1 ]
39 [ DIALOG main(0) text="You!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
40
41 {[ DIALOG main(0) text="Where's the
42 prisoner?" txtAlign=5 speed=5 size=2 align=1 r=80 g=80 b=200 subtype=0 ]}
43
44 {[ DIALOG enemy(0) text="We took him to
45 the Labyrinth of Froj
46 as you told us" txtAlign=5 speed=5 size=1 align=1 r=200 g=20 b=20 subtype=0 ]}
47
48 {[ DIALOG main(0) text="Well done" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
49
50 {[ DIALOG enemy(0) text="But you must know" txtAlign=5 speed=5 size=1 align=1 r=200 g=20 b=20 subtype=0 ]}
51
52 {[ DIALOG enemy(0) text="that he had
53 shoes, sir" txtAlign=5 speed=5 size=1 align=1 r=200 g=20 b=20 subtype=0 ]}
54
55 {[ DIALOG main(0) text="Dolt! Wait, I mean..." txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
56 [ MOVE enemy(0) dir=4 amount=1 ]}
57
58 # When Holotz yells, the demon falls back one stair step
59 {[ DIALOG main(0) text="You utterly
60 peabrained half-wit!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
61 [ MOVE main(0) dir=4 amount=1 ]
62 [ MOVE enemy(0) dir=4 amount=1 ]}
63
64 {[ DIALOG main(0) text="Why didn't you
65 tell me!" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
66
67 {[ DIALOG enemy(0) text="I..." txtAlign=5 speed=5 size=1 align=0 r=200 g=20 b=20 subtype=0 ]}
68
69 {[ DIALOG main(0) text="They'll have reached
70 the tower by now" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
71
72 {[ DIALOG main(0) text="Summon all
73 the beasts!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
74
75 {[ DIALOG enemy(0) text="Yes, sir" txtAlign=5 speed=5 size=2 align=0 r=200 g=20 b=20 subtype=0 ]}
76
77 {[ MOVE enemy(0) dir=7 amount=2 ]}
78
79 {[ MOVE enemy(0) dir=7 amount=2 ]
80 [ DIALOG main(0) text="We're going to give
81 those Lizarnites
82 a surprise" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 30
2 # Ybelle and Ludar meet again
3 ##########################################
4
5 {[ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
6
7 {[ MOVE main(0) dir=8 amount=6 ]
8 [ MOVE enemy(0) dir=8 amount=6 ]
9 [ MOVE enemy(1) dir=8 amount=6 ]
10 [ MOVE enemy(2) dir=8 amount=6 ]}
11
12 {[ MOVE main(0) dir=6 amount=3 ]
13 [ MOVE enemy(0) dir=4 amount=3 ]
14 [ MOVE enemy(1) dir=8 amount=4 ]
15 [ MOVE enemy(2) dir=8 amount=4 ]}
16
17 {[ MOVE main(0) dir=6 amount=4 ]
18 [ MOVE enemy(0) dir=4 amount=4 ]
19 [ MOVE enemy(1) dir=4 amount=3 ]
20 [ MOVE enemy(2) dir=6 amount=3 ]}
21
22 {[ DIALOG main(0) text="Ludar!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
23 [ DIALOG enemy(0) text="Ybelle!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]
24 [ MOVE main(0) dir=4 amount=1 ]
25 [ MOVE enemy(0) dir=6 amount=1 ]}
26
27 {[ DIALOG main(0) text="You're alive!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
28 [ DIALOG enemy(0) text="You're not dead!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]
29 [ MOVE main(0) dir=6 amount=1 ]
30 [ MOVE enemy(0) dir=4 amount=1 ]}
31
32 {[ DIALOG main(0) text="Nice shoes" txtAlign=5 speed=5 size=2 align=0 r=130 g=30 b=180 subtype=0 ]}
33
34 {[ DIALOG enemy(0) text="We do better
35 as a team" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
36
37 {[ DIALOG enemy(0) text="Follow me!" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
38
39 {[ DIALOG main(0) text="Hmm..." txtAlign=5 speed=5 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
40 [ MOVE main(0) dir=4 amount=1 ]}
41
42 {[ DIALOG enemy(0) text="How about
43 together?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
44
45 {[ DIALOG main(0) text="Together." txtAlign=5 speed=5 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
46 [ MOVE main(0) dir=6 amount=1 ]}
47
48 {[ MOVE main(0) dir=8 amount=3 ]
49 [ MOVE enemy(0) dir=8 amount=3 ]}
0 ##########################################
1 # Holotz's Castle story - Level 32
2 # Return to the land of Lizarno
3 ##########################################
4
5 {[ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCCredits.wav" loops=-1 waitToEnd=0 ]}
8
9 {[ DIALOG main(0) text="We're in Lizarno!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
10
11 {[ DIALOG enemy(0) text="We're home!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
12
13 {[ DIALOG main(0) text="Hey, look at
14 that stone!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
15 [ MOVE main(0) dir=4 amount=2 ]}
16
17 {[ DIALOG enemy(0) text="Don't touch it!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
18
19 {[ MOVE main(0) dir=4 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 33
2 # The end
3 ##########################################
4
5 {[ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
7
8 {
9 [ NARRATIVE text="
10 THE END
11 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
12 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle and Ludar arrive to the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="¡Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="¡Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
8 }
9
10 {
11 [ NARRATIVE text="Ybelle y Ludar." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
12 }
13
14 {
15 [ DIALOG main(0) text="¿Qué ha pasado?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=6 amount=2 ]
17 [ MOVE enemy(0) dir=6 amount=3 ]
18 }
19
20 {
21 [ DIALOG enemy(0) text="¡Te dije que
22 no tocaras
23 ese pedrusco!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
24 }
25
26 {
27 [ DIALOG main(0) text="Oh, calla ya..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
28 }
29
30 {
31 [ DIALOG main(0) text="¿Qué iba a
32 saber yo?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
33 }
34
35 {
36 [ DIALOG main(0) text="¿Dónde estamos?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
37 }
38
39 {
40 [ DIALOG enemy(0) text="¡JA! ¿Cómo quieres
41 que lo sepa?" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
42 }
43
44 {
45 [ DIALOG enemy(0) text="Si no tocaras
46 lo que no debes..." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
47 }
48
49 {
50 [ DIALOG main(0) text="Pesado..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
51 [ DIALOG enemy(0) text="Imbécil..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
52 }
53
54 {
55 [ DIALOG main(0) text="Hay que buscar
56 una forma de
57 volver a casa" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
58 }
59
60 {
61 [ DIALOG main(0) text="Sígueme, Ludar" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
62 }
63
64 {
65 [ DIALOG enemy(0) text="Ni lo sueñes...
66 siempre me metes
67 en algún lio" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
68 }
69
70 {
71 [ DIALOG enemy(0) text="Esta vez se
72 hará lo que
73 yo diga" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
74 }
75
76 {
77 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
78 }
79
80 {
81 [ DIALOG main(0) text="Bien, entonces me
82 voy yo solo" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
83 [ MOVE main(0) dir=6 amount=5 ]
84 }
85
86 {
87 [ DIALOG enemy(0) text="???" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
88 [ MOVE main(0) dir=8 amount=3 ]
89 }
90
91 {
92 [ MOVE enemy(0) dir=6 amount=3 ]
93 [ DIALOG enemy(0) text="err... Ybelle,
94 ¡Espérame!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
95 }
96
97 {
98 [ MOVE main(0) dir=6 amount=3 ]
99 }
0 ##########################################
1 # Holotz's Castle story - Level 2
2 # Ybelle enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="¡NoO!" txtAlign=4 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 }
7
8 {
9 [ DIALOG main(0) text="¡Eso dolió!" txtAlign=4 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
10 }
11
12 {
13 [ DIALOG main(0) text="¡LUDAR!" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
14 }
15
16 {
17 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=1 ]
18 }
19
20 {
21 [ DIALOG main(0) text="...parece que
22 no me oye" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="En fin..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
27 [ MOVE main(0) dir=6 amount=1 ]
28 }
29
30 {
31 [ MOVE main(0) dir=4 amount=1 ]
32 [ DIALOG main(0) text="¿Qué demonios
33 hacen aquí todas
34 estas llaves?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
35 }
0 ##########################################
1 # Holotz's Castle story - Level 7
2 # Ludar enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="err... Ybelle,
6 espera" txtAlign=4 speed=2 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ MOVE main(0) dir=6 amount=2 ]
8 }
9
10 {
11 [ MOVE main(0) dir=6 amount=1 ]
12 [ DIALOG main(0) text="¡Oh, no!" txtAlign=4 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
13 }
14
15 {
16 [ DIALOG main(0) text="¡Quién ha puesto ese
17 agujero ahí!" txtAlign=4 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
18 }
19
20 {
21 [ DIALOG main(0) text="¡Ybelle!" txtAlign=5 speed=1 size=3 align=0 r=20 g=200 b=20 subtype=0 ]
22 }
23
24 {
25 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
26 }
27
28 {
29 [ DIALOG main(0) text="¡Ese cabezota!" txtAlign=5 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
30 }
31
32 {
33 [ DIALOG main(0) text="Oh, fíjate" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=4 amount=1 ]
35 }
36
37 {
38 [ DIALOG main(0) text="Esas piedras se
39 parecen a la que
40 Ybelle cogió" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
41 [ MOVE main(0) dir=4 amount=1 ]
42 }
43
44 {
45 [ DIALOG main(0) text="¿Qué es este sitio?" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
46 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle finds the shoe maker
3 ##########################################
4
5 {[ DIALOG main(0) text="?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="¿Qué es este sitio?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
9
10 {[ NARRATIVE text="La Zapatería" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
11 [ MOVE main(0) dir=6 amount=1 ]}
12
13 {[ MOVE main(0) dir=2 amount=3 ]}
14
15 {[ MOVE main(0) dir=6 amount=2 ]}
16
17 {[ MOVE main(0) dir=9 amount=2 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]}
20
21 {[ MOVE main(0) dir=9 amount=1 ]
22 [ DIALOG enemy(0) text="Ooh, ¡Una
23 visita!" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=1 ]}
24
25 {[ MOVE main(0) dir=9 amount=2 ]}
26
27 {[ DIALOG main(0) text="¡Vaya un
28 tipo raro!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
29 [ DIALOG enemy(0) text="!Vaya un
30 tipo raro!" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=1 ]
31 }
32
33 {[ DIALOG main(0) text="Err.. ¿Hola?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
34
35 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
36
37 {[ DIALOG enemy(0) text="No pareces..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
38
39 {[ DIALOG enemy(0) text="De por
40 aquí..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
41
42 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
43 [ DIALOG main(0) text="¡¡Parece que
44 se va a dormir!!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
45
46 {[ DIALOG enemy(0) text="¿Has entrado
47 nuevo..." txtAlign=5 speed=1 size=0 align=0 r=200 g=130 b=20 subtype=0 ]}
48
49 {[ DIALOG enemy(0) text="...hace..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
50
51 {[ DIALOG enemy(0) text="...poco?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
52
53 {[ DIALOG main(0) text="Esto...
54 ¿Nuevo, dices?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
55
56 {[ DIALOG main(0) text="Oh, sí,
57 claro" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
58
59 {[ DIALOG main(0) text="¿Quién
60 eres tú?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
61
62 {[ DIALOG enemy(0) text="Yo soy..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
63
64 {[ DIALOG enemy(0) text="...El Señor de
65 Los Zapatos" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=0 ]}
66
67 {[ DIALOG enemy(0) text="Supongo..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
68
69 {[ DIALOG enemy(0) text="...que vienes..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
70
71 {[ DIALOG enemy(0) text="...a por unos
72 zapatos nuevos..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
73
74 {[ DIALOG enemy(0) text="...¿No?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
75
76 {[ DIALOG enemy(0) text="Coge..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
77 [ DIALOG main(0) text="Yo..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
78
79 {[ DIALOG enemy(0) text="...estos" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
80
81 {[ MOVE main(0) dir=6 amount=2 ]}
82 {[ MOVE main(0) dir=4 amount=2 ]}
83
84 {[ DIALOG enemy(0) text="Seguro..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
85
86 {[ DIALOG enemy(0) text="... que te
87 moverás..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
88
89 {[ DIALOG enemy(0) text="...mejor con
90 ellos..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
91
92 {[ DIALOG main(0) text="¿Sabes cómo
93 salir de
94 aquí?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
95
96 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
97
98 {[ DIALOG enemy(0) text="...no" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
99
100 {[ DIALOG enemy(0) text="...sólo
101 Holotz..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
102
103 {[ DIALOG enemy(0) text="...sabe eso" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
104
105 {[ DIALOG main(0) text="¿Holotz?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
106
107 {[ DIALOG enemy(0) text="Sí..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
108
109 {[ DIALOG enemy(0) text="Él creó..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
110
111 {[ DIALOG enemy(0) text="...este
112 castillo" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
113
114 {[ DIALOG main(0) text="¿Dónde
115 puedo
116 encontrarle?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
117
118 {[ DIALOG enemy(0) text="...no
119 puedes" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
120
121 {[ DIALOG enemy(0) text="Él te..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
122
123 {[ DIALOG enemy(0) text="...encontrará" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
124
125 {[ DIALOG enemy(0) text="Ahora
126 debo..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
127
128 {[ DIALOG enemy(0) text="...seguir" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
129
130 {[ DIALOG enemy(0) text="...trabajando" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
131
132 {[ DIALOG main(0) text="¡Pero...!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
133 [ DIALOG enemy(0) text="Ahora
134 debo..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
135
136 {[ DIALOG main(0) text="Déjalo,
137 es inútil" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
138
139 {[ DIALOG main(0) text="Bien, me voy...
140 y gracias por
141 los zapatos" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
142 [ MOVE main(0) dir=7 amount=2 ]}
143
144 {[ MOVE main(0) dir=7 amount=2 ]}
145
146 {[ DIALOG main(0) text="¿Y ahora por
147 dónde voy?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
148
149 {[ DIALOG main(0) text="Oh, es igual" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
150 [ MOVE main(0) dir=4 amount=1 ]}
151
152 {[ MOVE main(0) dir=2 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ludar talks to the two flames
3 ##########################################
4
5 {[ DIALOG main(0) text="Oops" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_UltraSlow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="¡Oh, otra
9 piedra!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
10 [ MOVE main(0) dir=6 amount=1 ]}
11
12 {[ NARRATIVE text="Las Dos Llamas" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=4 ]
14 [ DIALOG main(0) text="¡Y Otra!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
15
16 {[ DIALOG enemy(0) text="¡Alto ahí!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
17
18 {[ DIALOG main(0) text="???" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
19 [ MOVE main(0) dir=4 amount=1 ]}
20
21 {[ DIALOG main(0) text="¿Hay alguien
22 aquí?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
23 [ MOVE main(0) dir=6 amount=4 ]}
24
25 {[ DIALOG enemy(0) text="¡He dicho
26 alto ahí!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
27
28 {[ MOVE main(0) dir=4 amount=4 ]
29 [ DIALOG main(0) text="¡Oh, Una llama
30 oradora!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]}
31
32 {[ DIALOG enemy(0) text="¡No soy una
33 llama oradora!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]
34 [ DIALOG main(0) text="¡Oh!" txtAlign=5 speed=4 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
35 [ MOVE main(0) dir=6 amount=2 ]}
36
37 {[ DIALOG enemy(0) text="¡Soy una
38 llama habladora!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
39
40 {[ DIALOG main(0) text="¿Cómo has
41 sabido lo
42 que pensaba?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
43
44 {[ DIALOG enemy(0) text="¡Yo lo
45 sé todo!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
46
47 {[ DIALOG enemy(1) text="Ejem..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
48
49 {[ DIALOG enemy(0) text="Bueno, casi
50 todo" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
51
52 {[ DIALOG enemy(1) text="Ella lee la
53 mente..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
54
55 {[ DIALOG enemy(1) text="Yo leo..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
56
57 {[ DIALOG enemy(1) text="...Libros" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
58
59 {[ DIALOG enemy(1) text="¡Jar, jar, jar!" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]
60 [ DIALOG enemy(0) text="¡Jur, jur, jur!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]
61 [ DIALOG main(0) text="??!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
62
63 {[ DIALOG enemy(1) text="¿Cómo has
64 entrado aquí?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
65
66 {[ DIALOG enemy(0) text="Yo lo sé..." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
67
68 {[ DIALOG main(0) text="Oh, ¡Va a leer
69 mi mente!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]}
70
71 {[ DIALOG enemy(0) text="¡¡Por el
72 portal
73 místico!!" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
74
75 {[ DIALOG enemy(1) text="¡Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
76 [ DIALOG enemy(0) text="¡Jur, jur, jur!" txtAlign=5 speed=1 size=3 align=0 r=20 g=20 b=180 subtype=0 ]
77 [ DIALOG main(0) text="hmpfxs#@!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
78 [ MOVE main(0) dir=6 amount=4 ]}
79
80 {[ DIALOG enemy(1) text="Espera, no
81 te vayas" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
82 [ MOVE main(0) dir=4 amount=5 ]}
83
84 {[ DIALOG main(0) text="¡No tengo
85 tiempo para
86 bromas!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
87 [ MOVE main(0) dir=6 amount=2 ]}
88
89 {[ DIALOG enemy(0) text="¿Qué
90 necesitas?" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]
91 [ MOVE main(0) dir=4 amount=3 ]}
92
93 {[ DIALOG main(0) text="Tengo que
94 encontrar
95 a Ybelle" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
96
97 {[ DIALOG main(0) text="Debemos
98 regresar a
99 la Tierra de
100 Lizarno" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
101
102 {[ DIALOG enemy(0) text="Hmmm...un Lizarnita,
103 qué interesante" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=1 ]}
104
105 {[ DIALOG enemy(1) text="En adelante
106 el castillo
107 se vuelve" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
108
109 {[ DIALOG enemy(1) text="más peligroso" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
110
111 {[ DIALOG enemy(1) text="pero tú no
112 tienes suficiente
113 poder mágico" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
114
115 {[ DIALOG enemy(1) text="para llegar al
116 nivel superior" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
117
118 {[ DIALOG enemy(0) text="Sí, lo que
119 necesitas
120 es..." txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
121
122 {[ DIALOG enemy(1) text="¡Unos
123 zapatos!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
124 [ DIALOG enemy(0) text="¡Unos
125 zapatos!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
126
127 {[ DIALOG main(0) text="Oh, dejaos
128 de bromas!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
129 [ MOVE main(0) dir=4 amount=2 ]}
130
131 {[ DIALOG enemy(0) text="Pero sólo
132 puede dártelos" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
133
134 {[ DIALOG enemy(0) text="El Señor de
135 Los Zapatos" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
136
137 {[ DIALOG main(0) text="¿No existe otra
138 forma de conseguir
139 unos zapatos?" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
140 [ MOVE main(0) dir=6 amount=2 ]}
141
142 {[ DIALOG enemy(1) text="Sí, puedes
143 conseguirlos en" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=60 subtype=0 ]}
144
145 {[ DIALOG enemy(1) text="¡La zapatería!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=60 subtype=0 ]
146 [ DIALOG enemy(0) text="¡La zapatería!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]}
147
148 {[ DIALOG enemy(1) text="¡Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
149 [ DIALOG enemy(0) text="¡Jur, jur, jur!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]
150 [ DIALOG main(0) text="¡Esto es
151 demasiado!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
152 [ MOVE main(0) dir=6 amount=4 ]}
153
154 {[ DIALOG enemy(1) text="Espera" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
155 [ MOVE main(0) dir=4 amount=2 ]}
156
157 {[ DIALOG enemy(1) text="Puedes conseguir
158 unos zapatos" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
159
160 {[ DIALOG enemy(1) text="tras este portal
161 místico" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
162
163 {[ DIALOG enemy(0) text="Pero debes
164 saber" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
165
166 {[ DIALOG enemy(0) text="que nadie
167 ha salido con
168 vida de allí" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
169
170 {[ DIALOG main(0) text="¡Oh!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
171 [ MOVE main(0) dir=6 amount=2 ]}
172
173 {[ DIALOG main(0) text="Hmm... Bueno,
174 debo intentarlo" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
175 [ MOVE main(0) dir=4 amount=2 ]}
176
177 {[ DIALOG main(0) text="¡Oh!, pero no
178 puedo abrir
179 el portal" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
180 [ MOVE main(0) dir=4 amount=2 ]}
181
182 {[ DIALOG main(0) text="Esa piedra está
183 demasiado alto" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
184
185 {[ DIALOG enemy(1) text="Bien, entonces
186 usa esta escalera" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 19
2 # Ybelle is captured
3 ##########################################
4
5 {[ DIALOG main(0) text="¡AAAH!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_Fast.wav" loops=0 waitToEnd=0 ]}
7
8 {[ MOVE enemy(0) dir=8 amount=4 ]
9 [ MOVE enemy(1) dir=8 amount=4 ]
10 [ MOVE enemy(2) dir=4 amount=2 ]
11 [ MOVE enemy(3) dir=6 amount=2 ]
12 [ MOVE enemy(4) dir=4 amount=5 ]
13 [ MOVE enemy(5) dir=6 amount=5 ]
14 [ DIALOG main(0) text="Oh, oh" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
15 [ DIALOG enemy(2) text="!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=1 ]
16 [ DIALOG enemy(3) text="!" txtAlign=5 speed=1 size=2 align=0 r=220 g=20 b=20 subtype=1 ]}
17
18 {[ NARRATIVE text="
19 CONTINUARÁ...
20 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
21 [ DIALOG main(0) text="??!" txtAlign=5 speed=3 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=5 amount=1 ]}
23
24 {[ DIALOG main(0) text="¡Eeeh!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
25 [ MOVE main(0) dir=5 amount=2 ]}
26
27 {[ DIALOG main(0) text="¡No me dejéis aquí!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
28 [ MOVE main(0) dir=5 amount=2 ]}
29
30 {[ WAIT millis=3000]}
0 ##########################################
1 # Holotz's Castle story - Level 20
2 # Ybelle is captured (continued)
3 ##########################################
4
5 {[ MOVE enemy(0) dir=8 amount=0 ]
6 [ MOVE enemy(1) dir=8 amount=0 ]
7 [ MOVE enemy(2) dir=4 amount=0 ]
8 [ MOVE enemy(3) dir=6 amount=0 ]
9 [ MOVE enemy(4) dir=4 amount=0 ]
10 [ MOVE enemy(5) dir=6 amount=0 ]}
11
12 {[ WAIT millis=1000]}
13
14 {[ DIALOG main(0) text="¡Alto, ni un
15 paso más!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=4 amount=1 ]}
17
18 {[ DIALOG enemy(0) text="Je je" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]
19 [ DIALOG enemy(1) text="Hmmm" txtAlign=5 speed=5 size=3 align=0 r=200 g=20 b=20 subtype=0 ]}
20
21 {[ DIALOG main(0) text="¡Os lo advierto,
22 soy peligroso!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
23 [ MOVE main(0) dir=6 amount=2 ]}
24
25 {[ MOVE enemy(1) dir=4 amount=3 ]
26 [ DIALOG enemy(1) text="Fíjate..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
27
28 {[ MOVE enemy(1) dir=4 amount=1 ]
29 [ DIALOG enemy(5) text="¿Qué pasa?" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
30
31 {[ DIALOG enemy(1) text="Lleva zapatos" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
32
33 {[ DIALOG enemy(5) text="Hmmm... a
34 Holotz no le
35 va a gustar" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
36
37 {[ DIALOG main(0) text="¿Qué queréis?" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
38
39 {[ MOVE enemy(5) dir=6 amount=4 ]
40 [ MOVE main(0) dir=6 amount=1 ]
41 [ DIALOG enemy(5) text="La cuestión es..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(5) text="¿Qué haces
44 tú aquí?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
45
46 {[ DIALOG main(0) text="Cogí una
47 piedra y..." txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
48
49 {[ DIALOG enemy(5) text="Y se abrió un
50 portal, ¿Verdad?." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
51
52 {[ DIALOG main(0) text="¡Sí, exacto!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
53
54 {[ DIALOG enemy(5) text="Parece que
55 los experimentos
56 de Holotz" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
57
58 {[ DIALOG enemy(5) text="No han tenido
59 mucho éxito" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
60
61 {[ DIALOG enemy(5) text="Me sorprende que
62 hayas llegado
63 tan lejos..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
64
65 {[ DIALOG enemy(4) text="¿Qué haremos
66 con él?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
67
68 {[ DIALOG enemy(5) text="Tal y como
69 dijo Holotz..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
70
71 {[ DIALOG enemy(5) text="...lo llevaremos
72 al laberinto
73 de Froj" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
74
75 {[ DIALOG enemy(5) text="Allí se quedará
76 hasta que Holotz
77 decida qué hacer
78 con él..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
79
80 {[ DIALOG enemy(5) text="... si los 4
81 hermanos locos no
82 lo encuentran antes" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
83
84 {[ DIALOG enemy(1) text="Jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=20 subtype=0 ]
85 [ DIALOG enemy(2) text="Jur, jur, jur!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 25
2 # Holotz appears
3 ##########################################
4
5 {
6 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
7 [ NARRATIVE text="Holotz." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
8 }
9
10 {[ MOVE enemy(0) dir=9 amount=2 ]}
11
12 {[ MOVE main(0) dir=4 amount=2 ]
13 [ DIALOG main(0) text="¡Por el poder
14 de Hutazin!..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
15
16 {[ MOVE enemy(0) dir=9 amount=1 ]}
17 {[ MOVE enemy(0) dir=9 amount=1 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]
20 [ DIALOG main(0) text="¡Portal elemental,
21 ábrete!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
22
23 {[ MOVE enemy(0) dir=9 amount=1 ]}
24
25 {[ WAIT millis=3000 ]}
26
27 {[ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
28
29 {[ MOVE main(0) dir=5 amount=1 ]
30 [ DIALOG main(0) text="¡Falló
31 otra vez!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
32
33 {[ MOVE main(0) dir=4 amount=2 ]
34 [ MOVE enemy(0) dir=9 amount=1 ]
35 [ DIALOG main(0) text="¡Tú!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
36
37 {[ DIALOG main(0) text="¿Dónde está
38 el lizarnita?" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="Lo metimos en
41 el laberinto de
42 Froj como nos dijo" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
43
44 {[ DIALOG main(0) text="Bien hecho" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
45
46 {[ DIALOG enemy(0) text="Pero debe saber" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="que llevaba
49 zapatos, señor" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
50
51 {[ DIALOG main(0) text="¡Estúpido!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
52
53 {[ DIALOG main(0) text="¡Estúpido!
54 ¡Cómo no me
55 lo dijiste!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
56
57 {[ DIALOG enemy(0) text="Yo..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
58
59 {[ DIALOG main(0) text="A este paso habrán
60 llegado a la torre" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
61
62 {[ DIALOG main(0) text="¡Reúne a todas
63 las bestias!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="Sí, señor" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
66
67 {[ MOVE enemy(0) dir=7 amount=2 ]}
68
69 {[ MOVE enemy(0) dir=7 amount=3 ]
70 [ DIALOG main(0) text="Vamos a dar una
71 sorpresa a esos
72 lizarnitas" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 30
2 # Ybelle and Ludar met again
3 ##########################################
4
5 {[ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
6
7 {[ MOVE main(0) dir=8 amount=6 ]
8 [ MOVE enemy(0) dir=8 amount=6 ]
9 [ MOVE enemy(1) dir=8 amount=6 ]
10 [ MOVE enemy(2) dir=8 amount=6 ]}
11
12 {[ MOVE main(0) dir=6 amount=3 ]
13 [ MOVE enemy(0) dir=4 amount=3 ]
14 [ MOVE enemy(1) dir=8 amount=4 ]
15 [ MOVE enemy(2) dir=8 amount=4 ]}
16
17 {[ MOVE main(0) dir=6 amount=4 ]
18 [ MOVE enemy(0) dir=4 amount=4 ]
19 [ MOVE enemy(1) dir=4 amount=3 ]
20 [ MOVE enemy(2) dir=6 amount=3 ]}
21
22 {[ DIALOG main(0) text="¡Ludar!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
23 [ DIALOG enemy(0) text="¡Ybelle!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
24
25 {[ DIALOG main(0) text="¡Estás vivo!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
26 [ DIALOG enemy(0) text="¡No estás muerto!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
27
28 {[ DIALOG enemy(0) text="Bueno, ahora podremos
29 continuar juntos" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]}
30
31 {[ DIALOG enemy(0) text="¡Por la escalera,
32 sígueme!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
33
34 {[ MOVE main(0) dir=8 amount=3 ]
35 [ MOVE enemy(0) dir=8 amount=3 ]}
0 ##########################################
1 # Holotz's Castle story - Level 32
2 # Return to the land of Lizarno
3 ##########################################
4
5 {[ DIALOG main(0) text="¡Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="¡Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCCredits.wav" loops=-1 waitToEnd=0 ]}
8
9 {[ DIALOG main(0) text="¡Es Lizarno!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
10
11 {[ DIALOG enemy(0) text="¡Hemos vuelto!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
12
13 {[ DIALOG main(0) text="¡Eh, mira
14 esa piedra!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
15 [ MOVE main(0) dir=4 amount=2 ]}
16
17 {[ DIALOG enemy(0) text="¡No la toques!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
18
19 {[ MOVE main(0) dir=4 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 33
2 # The end
3 ##########################################
4
5 {[ DIALOG enemy(0) text="¡Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ DIALOG main(0) text="¡Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
7
8 {
9 [ NARRATIVE text="
10 FIN
11 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
12 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle and Ludar arrive to the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
8 }
9
10 {
11 [ NARRATIVE text="Ybelle eta Ludar." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
12 }
13
14 {
15 [ DIALOG main(0) text="Zer gertatu da?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=6 amount=2 ]
17 [ MOVE enemy(0) dir=6 amount=3 ]
18 }
19
20 {
21 [ DIALOG enemy(0) text="Esan nizun
22 harritzar hura
23 ez ukitzeko!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
24 }
25
26 {
27 [ DIALOG main(0) text="Oh, isil zaitez..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
28 }
29
30 {
31 [ DIALOG main(0) text="Eta zer
32 nekien nik?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
33 }
34
35 {
36 [ DIALOG main(0) text="Non gaude?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
37 }
38
39 {
40 [ DIALOG enemy(0) text="JA! Nola nahi
41 duzu nik jakitea?" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
42 }
43
44 {
45 [ DIALOG enemy(0) text="Ez bazenu
46 behar ez dena ukituko..." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
47 }
48
49 {
50 [ DIALOG main(0) text="Gogaikarri hori..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
51 [ DIALOG enemy(0) text="Tentel hori..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
52 }
53
54 {
55 [ DIALOG main(0) text="Etxera itzultzeko
56 bideren bat
57 aurkitu behar dugu" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
58 }
59
60 {
61 [ DIALOG main(0) text="Jarrai nazazu, Ludar" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
62 }
63
64 {
65 [ DIALOG enemy(0) text="Ezta pentsatu ere...
66 nahaspiletan sartu
67 baizik ez nauzu egiten" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
68 }
69
70 {
71 [ DIALOG enemy(0) text="Oraingo honetan
72 nik esandakoa
73 egingo dugu" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
74 }
75
76 {
77 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
78 }
79
80 {
81 [ DIALOG main(0) text="Ados, orduan
82 bakarrik joango naiz" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
83 [ MOVE main(0) dir=6 amount=5 ]
84 }
85
86 {
87 [ DIALOG enemy(0) text="???" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
88 [ MOVE main(0) dir=8 amount=3 ]
89 }
90
91 {
92 [ MOVE enemy(0) dir=6 amount=3 ]
93 [ DIALOG enemy(0) text="err... Ybelle,
94 itxaron!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
95 }
96
97 {
98 [ MOVE main(0) dir=6 amount=3 ]
99 }
0 ##########################################
1 # Holotz's Castle story - Level 2
2 # Ybelle enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Eeeeez!" txtAlign=4 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 }
7
8 {
9 [ DIALOG main(0) text="Hau kolpea!" txtAlign=4 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
10 }
11
12 {
13 [ DIALOG main(0) text="LUDAR!" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
14 }
15
16 {
17 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=1 ]
18 }
19
20 {
21 [ DIALOG main(0) text="...dirudienez
22 ez nau entzuten" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Tira..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
27 [ MOVE main(0) dir=6 amount=1 ]
28 }
29
30 {
31 [ MOVE main(0) dir=4 amount=1 ]
32 [ DIALOG main(0) text="Ze demonio
33 egiten dute hemen
34 giltza guzti hauek?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
35 }
0 ##########################################
1 # Holotz's Castle story - Level 7
2 # Ludar enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="err... Ybelle,
6 itxaron" txtAlign=4 speed=2 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ MOVE main(0) dir=6 amount=2 ]
8 }
9
10 {
11 [ MOVE main(0) dir=6 amount=1 ]
12 [ DIALOG main(0) text="Oh, ez!" txtAlign=4 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
13 }
14
15 {
16 [ DIALOG main(0) text="Nork jarri du
17 hor zulo hori!" txtAlign=4 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
18 }
19
20 {
21 [ DIALOG main(0) text="Ybelle!" txtAlign=5 speed=1 size=3 align=0 r=20 g=200 b=20 subtype=0 ]
22 }
23
24 {
25 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
26 }
27
28 {
29 [ DIALOG main(0) text="Burugogor halakoa!" txtAlign=5 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
30 }
31
32 {
33 [ DIALOG main(0) text="Hara..." txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=4 amount=1 ]
35 }
36
37 {
38 [ DIALOG main(0) text="Harri horiek
39 Ybellek harturikoaren
40 antza dute" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
41 [ MOVE main(0) dir=4 amount=1 ]
42 }
43
44 {
45 [ DIALOG main(0) text="Zer da toki hau?" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
46 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle finds the shoe maker
3 ##########################################
4
5 {[ DIALOG main(0) text="?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Non nago?
9 Zer da hau?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
10
11 {[ NARRATIVE text="Zapatadenda" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
12 [ MOVE main(0) dir=6 amount=1 ]}
13
14 {[ MOVE main(0) dir=2 amount=3 ]}
15
16 {[ MOVE main(0) dir=6 amount=2 ]}
17
18 {[ MOVE main(0) dir=9 amount=2 ]}
19
20 {[ MOVE main(0) dir=6 amount=3 ]}
21
22 {[ MOVE main(0) dir=9 amount=1 ]
23 [ DIALOG enemy(0) text="Ooh,
24 bisita bat!" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=1 ]}
25
26 {[ MOVE main(0) dir=9 amount=2 ]}
27
28 {[ DIALOG main(0) text="Ze tipo
29 bitxia!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
30 [ DIALOG enemy(0) text="Ze tipo
31 bitxia!" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=1 ]
32 }
33
34 {[ DIALOG main(0) text="Err.. Kaixo?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
35
36 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
37
38 {[ DIALOG enemy(0) text="Ez dirudizu..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="Inguru
41 honetakoa..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
44 [ DIALOG main(0) text="Loak hartuko
45 duela dirudi!!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
46
47 {[ DIALOG enemy(0) text="Orain
48 dela gutxi..." txtAlign=5 speed=1 size=0 align=0 r=200 g=130 b=20 subtype=0 ]}
49
50 {[ DIALOG enemy(0) text="...sartu zara,..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
51
52 {[ DIALOG enemy(0) text="...berria?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
53
54 {[ DIALOG main(0) text="Baaa...
55 Berria, diozu?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
56
57 {[ DIALOG main(0) text="Oh, bai,
58 noski" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
59
60 {[ DIALOG main(0) text="Nor
61 zara zu?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
62
63 {[ DIALOG enemy(0) text="Ni..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="...Zapaten
66 Jauna naiz" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=0 ]}
67
68 {[ DIALOG enemy(0) text="Zapata..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
69
70 {[ DIALOG enemy(0) text="...berri batzuen bila..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
71
72 {[ DIALOG enemy(0) text="...etorriko
73 zara..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
74
75 {[ DIALOG enemy(0) text="...Ezta?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
76
77 {[ DIALOG enemy(0) text="Tori..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
78 [ DIALOG main(0) text="Zera..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
79
80 {[ DIALOG enemy(0) text="...hauek" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
81
82 {[ MOVE main(0) dir=6 amount=2 ]}
83 {[ MOVE main(0) dir=4 amount=2 ]}
84
85 {[ DIALOG enemy(0) text="Ziur..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
86
87 {[ DIALOG enemy(0) text="...hauekin
88 arinago..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
89
90 {[ DIALOG enemy(0) text="...ibiliko
91 zarela..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
92
93 {[ DIALOG main(0) text="Ba al dakizu
94 nola irteten den
95 hemendik?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
96
97 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
98
99 {[ DIALOG enemy(0) text="...ez" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
100
101 {[ DIALOG enemy(0) text="...hori
102 Holotzek..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
103
104 {[ DIALOG enemy(0) text="...baino ez daki" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
105
106 {[ DIALOG main(0) text="Holotzek?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
107
108 {[ DIALOG enemy(0) text="Bai..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
109
110 {[ DIALOG enemy(0) text="Berak sortu zuen..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
111
112 {[ DIALOG enemy(0) text="...gaztelu
113 hau" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
114
115 {[ DIALOG main(0) text="Eta non
116 aurki
117 dezaket?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
118
119 {[ DIALOG enemy(0) text="...ezin
120 zenezake" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
121
122 {[ DIALOG enemy(0) text="Berak..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
123
124 {[ DIALOG enemy(0) text="...aurkituko
125 zaitu" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
126
127 {[ DIALOG enemy(0) text="Orain
128 lanean..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
129
130 {[ DIALOG enemy(0) text="...jarraitu" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
131
132 {[ DIALOG enemy(0) text="...beharra dut" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
133
134 {[ DIALOG main(0) text="Baina...!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
135 [ DIALOG enemy(0) text="Orain
136 lanean..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
137
138 {[ DIALOG main(0) text="Uztak Ybelle,
139 eztuk ezer lortuko" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
140
141 {[ DIALOG main(0) text="Bikain, ni banoa...
142 eta eskerrik asko
143 oinetakoengatik!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
144 [ MOVE main(0) dir=7 amount=2 ]}
145
146 {[ MOVE main(0) dir=7 amount=2 ]}
147
148 {[ DIALOG main(0) text="Eta nondik joango
149 naiz ni orain?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
150
151 {[ DIALOG main(0) text="Oh, berdin dio" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
152 [ MOVE main(0) dir=4 amount=1 ]}
153
154 {[ MOVE main(0) dir=2 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ludar talks to the two flames
3 ##########################################
4
5 {[ DIALOG main(0) text="Oops" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_UltraSlow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Hara, beste
9 harri bat!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
10 [ MOVE main(0) dir=6 amount=1 ]}
11
12 {[ NARRATIVE text="Bi Sugarrak" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=4 ]
14 [ DIALOG main(0) text="Eta beste bat!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
15
16 {[ DIALOG enemy(0) text="Geldi hor!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
17
18 {[ DIALOG main(0) text="???" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
19 [ MOVE main(0) dir=4 amount=1 ]}
20
21 {[ DIALOG main(0) text="Nor dabil
22 hor?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
23 [ MOVE main(0) dir=6 amount=4 ]}
24
25 {[ DIALOG enemy(0) text="Gelditzeko
26 esan dut!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
27
28 {[ MOVE main(0) dir=4 amount=4 ]
29 [ DIALOG main(0) text="Oh, sugar bat
30 berriketan!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]}
31
32 {[ DIALOG enemy(0) text="Ez naiz
33 berriketan ari den
34 sugar bat!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]
35 [ DIALOG main(0) text="Oh!" txtAlign=5 speed=4 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
36 [ MOVE main(0) dir=6 amount=2 ]}
37
38 {[ DIALOG enemy(0) text="Hizketan
39 ari den sugar
40 bat naiz!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
41
42 {[ DIALOG main(0) text="Nola jakin
43 duzu zer narabilen
44 buruan?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
45
46 {[ DIALOG enemy(0) text="Nik
47 dena dakit!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
48
49 {[ DIALOG enemy(1) text="Ejem..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
50
51 {[ DIALOG enemy(0) text="Tira, ia
52 dena" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
53
54 {[ DIALOG enemy(1) text="Zure pentsamenduak
55 irakurtzen ditu..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
56
57 {[ DIALOG enemy(1) text="Nik irakurtzen ditudanak..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
58
59 {[ DIALOG enemy(1) text="...liburuak dira" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
60
61 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]
62 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]
63 [ DIALOG main(0) text="??!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
64
65 {[ DIALOG enemy(1) text="Nola sartu
66 zara hemen?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
67
68 {[ DIALOG enemy(0) text="Nik badakit..." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
69
70 {[ DIALOG main(0) text="Oh, nire pentsamenduak
71 irakurtzera doa!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]}
72
73 {[ DIALOG enemy(0) text="Atari
74 mistikotik!!" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
75
76 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
77 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=3 align=0 r=20 g=20 b=180 subtype=0 ]
78 [ DIALOG main(0) text="hmpfxs#@!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
79 [ MOVE main(0) dir=6 amount=4 ]}
80
81 {[ DIALOG enemy(1) text="Itxaron, ez
82 ezazu alde egin" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
83 [ MOVE main(0) dir=4 amount=5 ]}
84
85 {[ DIALOG main(0) text="Ez dut
86 txantxetarako
87 astirik!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
88 [ MOVE main(0) dir=6 amount=2 ]}
89
90 {[ DIALOG enemy(0) text="Zer
91 behar duzu?" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]
92 [ MOVE main(0) dir=4 amount=3 ]}
93
94 {[ DIALOG main(0) text="Ybelle
95 aurkitu
96 beharra dut" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
97
98 {[ DIALOG main(0) text="Lizarnoko
99 lurretara
100 itzuli beharra
101 dugu" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
102
103 {[ DIALOG enemy(0) text="Hmmm...Lizarnoar bat,
104 bikain..." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=1 ]}
105
106 {[ DIALOG enemy(1) text="Hemendik
107 aurrera,
108 gaztelua" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
109
110 {[ DIALOG enemy(1) text="arriskutsuagoa bilakatzen da" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
111
112 {[ DIALOG enemy(1) text="baina zuk ez
113 duzu behar beste
114 indar majiko" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
115
116 {[ DIALOG enemy(1) text="azken mailara
117 iritsi ahal izateko" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
118
119 {[ DIALOG enemy(0) text="Bai, behar
120 duzuna
121 da..." txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
122
123 {[ DIALOG enemy(1) text="Oinetako
124 parea!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
125 [ DIALOG enemy(0) text="Oinetako
126 parea!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
127
128 {[ DIALOG main(0) text="Oh, utzi
129 txantxak egiteari!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
130 [ MOVE main(0) dir=4 amount=2 ]}
131
132 {[ DIALOG enemy(0) text="Baina bakar
133 batek eman diezazkizuke:" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
134
135 {[ DIALOG enemy(0) text="Zapaten
136 Jaunak" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
137
138 {[ DIALOG main(0) text="Ez dago
139 zapata horiek lortzeko
140 beste biderik?" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
141 [ MOVE main(0) dir=6 amount=2 ]}
142
143 {[ DIALOG enemy(1) text="Bai, bada zapatak
144 lortzeko toki bat:" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=60 subtype=0 ]}
145
146 {[ DIALOG enemy(1) text="Oinetako denda!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=60 subtype=0 ]
147 [ DIALOG enemy(0) text="Oinetako denda!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]}
148
149 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
150 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]
151 [ DIALOG main(0) text="Aski da!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
152 [ MOVE main(0) dir=6 amount=4 ]}
153
154 {[ DIALOG enemy(1) text="Zaude" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
155 [ MOVE main(0) dir=4 amount=2 ]}
156
157 {[ DIALOG enemy(1) text="Oinetakoak
158 atari mistiko" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
159
160 {[ DIALOG enemy(1) text="honen ostean ere
161 lor ditzakezu" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
162
163 {[ DIALOG enemy(0) text="Baina jakin
164 beharko zenuke" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
165
166 {[ DIALOG enemy(0) text="inoiz inor
167 ez dela handik
168 bizirik irten" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
169
170 {[ DIALOG main(0) text="Oh!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
171 [ MOVE main(0) dir=6 amount=2 ]}
172
173 {[ DIALOG main(0) text="Hmm... Tira,
174 saiatu beharra dut" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
175 [ MOVE main(0) dir=4 amount=2 ]}
176
177 {[ DIALOG main(0) text="Oh!, baina
178 ezin dut
179 ataria ireki!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
180 [ MOVE main(0) dir=4 amount=2 ]}
181
182 {[ DIALOG main(0) text="Harri hura
183 garaiegi dago" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
184
185 {[ DIALOG enemy(1) text="Ados, orduan
186 erabili eskailera hau" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 19
2 # Ybelle is captured
3 ##########################################
4
5 {[ DIALOG main(0) text="AAAH!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_Fast.wav" loops=0 waitToEnd=0 ]}
7
8 {[ MOVE enemy(0) dir=8 amount=4 ]
9 [ MOVE enemy(1) dir=8 amount=4 ]
10 [ MOVE enemy(2) dir=4 amount=2 ]
11 [ MOVE enemy(3) dir=6 amount=2 ]
12 [ MOVE enemy(4) dir=4 amount=5 ]
13 [ MOVE enemy(5) dir=6 amount=5 ]
14 [ DIALOG main(0) text="Oh, oh" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
15 [ DIALOG enemy(2) text="!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=1 ]
16 [ DIALOG enemy(3) text="!" txtAlign=5 speed=1 size=2 align=0 r=220 g=20 b=20 subtype=1 ]}
17
18 {[ NARRATIVE text="
19 JARRAITUKO DU...
20 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
21 [ DIALOG main(0) text="??!" txtAlign=5 speed=3 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=5 amount=1 ]}
23
24 {[ DIALOG main(0) text="Eeeh!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
25 [ MOVE main(0) dir=5 amount=2 ]}
26
27 {[ DIALOG main(0) text="Ez nazazue hemen utzi!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
28 [ MOVE main(0) dir=5 amount=2 ]}
29
30 {[ WAIT millis=3000]}
0 ##########################################
1 # Holotz's Castle story - Level 20
2 # Ybelle is captured (continued)
3 ##########################################
4
5 {[ MOVE enemy(0) dir=8 amount=0 ]
6 [ MOVE enemy(1) dir=8 amount=0 ]
7 [ MOVE enemy(2) dir=4 amount=0 ]
8 [ MOVE enemy(3) dir=6 amount=0 ]
9 [ MOVE enemy(4) dir=4 amount=0 ]
10 [ MOVE enemy(5) dir=6 amount=0 ]}
11
12 {[ WAIT millis=1000]}
13
14 {[ DIALOG main(0) text="Geldi, ezta urrats
15 bat gehiago ere!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=4 amount=1 ]}
17
18 {[ DIALOG enemy(0) text="Je je" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]
19 [ DIALOG enemy(1) text="Hmmm" txtAlign=5 speed=5 size=3 align=0 r=200 g=20 b=20 subtype=0 ]}
20
21 {[ DIALOG main(0) text="Ohartarazi beharrean nago,
22 oso arriskutsua naiz!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
23 [ MOVE main(0) dir=6 amount=2 ]}
24
25 {[ MOVE enemy(1) dir=4 amount=3 ]
26 [ DIALOG enemy(1) text="Begira..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
27
28 {[ MOVE enemy(1) dir=4 amount=1 ]
29 [ DIALOG enemy(5) text="Zer da?" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
30
31 {[ DIALOG enemy(1) text="Oinetakoak daramatza" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
32
33 {[ DIALOG enemy(5) text="Hmmm...
34 Holotzi ez zaio
35 gustatuko" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
36
37 {[ DIALOG main(0) text="Zer da nahi duzuena?" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
38
39 {[ MOVE enemy(5) dir=6 amount=4 ]
40 [ MOVE main(0) dir=6 amount=1 ]
41 [ DIALOG enemy(5) text="Kontua da..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(5) text="Zer egiten duzu
44 zuk hemen?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
45
46 {[ DIALOG main(0) text="Harri bat
47 hartu nuen, eta..." txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
48
49 {[ DIALOG enemy(5) text="Eta atari bat
50 ireki zen, ezta?." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
51
52 {[ DIALOG main(0) text="Bai, hala da!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
53
54 {[ DIALOG enemy(5) text="Badirudi
55 Holotzen
56 esperimentuek" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
57
58 {[ DIALOG enemy(5) text="ez dutela
59 arrakastarik izan" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
60
61 {[ DIALOG enemy(5) text="Harrigarria da
62 honen urrun
63 heldu izana..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
64
65 {[ DIALOG enemy(4) text="Zer egingo dugu
66 honekin?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
67
68 {[ DIALOG enemy(5) text="Holotzek
69 agindu bezala..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
70
71 {[ DIALOG enemy(5) text="...Frojen
72 labirintoan
73 utziko dugu" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
74
75 {[ DIALOG enemy(5) text="Bertan geldituko
76 da Holotzek berekin
77 zer egin erabaki
78 arte..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
79
80 {[ DIALOG enemy(5) text="... 4 anai
81 eroek lehenago
82 aurkitzen ez badute" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
83
84 {[ DIALOG enemy(1) text="Jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=20 subtype=0 ]
85 [ DIALOG enemy(2) text="Jur, jur, jur!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 25
2 # Holotz appears
3 ##########################################
4
5 {
6 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
7 [ NARRATIVE text="Holotz." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
8 }
9
10 {[ MOVE enemy(0) dir=9 amount=2 ]}
11
12 {[ MOVE main(0) dir=4 amount=2 ]
13 [ DIALOG main(0) text="Hutazinen
14 indarragatik!..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
15
16 {[ MOVE enemy(0) dir=9 amount=1 ]}
17 {[ MOVE enemy(0) dir=9 amount=1 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]
20 [ DIALOG main(0) text="Oinarrizko ataria,
21 ireki!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
22
23 {[ MOVE enemy(0) dir=9 amount=1 ]}
24
25 {[ WAIT millis=3000 ]}
26
27 {[ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
28
29 {[ MOVE main(0) dir=5 amount=1 ]
30 [ DIALOG main(0) text="Berriro
31 huts egin du!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
32
33 {[ MOVE main(0) dir=4 amount=2 ]
34 [ MOVE enemy(0) dir=9 amount=1 ]
35 [ DIALOG main(0) text="Zu!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
36
37 {[ DIALOG main(0) text="Non dago
38 lizarnoarra?" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="Frojen labirintoan
41 sartu genuen
42 berorrek agindu bezala" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
43
44 {[ DIALOG main(0) text="Ongi egina" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
45
46 {[ DIALOG enemy(0) text="Baina jakin behar du" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="oinetakoak
49 zeramatzala, Jauna" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
50
51 {[ DIALOG main(0) text="Ergela!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
52
53 {[ DIALOG main(0) text="Ergela!
54 Nolatan ez
55 didazu ezer esan!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
56
57 {[ DIALOG enemy(0) text="Ni..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
58
59 {[ DIALOG main(0) text="Honezkero dorrera
60 iritsiko ziren" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
61
62 {[ DIALOG main(0) text="Bil itzazu
63 munstro guztiak!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="Bai, Jauna" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
66
67 {[ MOVE enemy(0) dir=7 amount=2 ]}
68
69 {[ MOVE enemy(0) dir=7 amount=3 ]
70 [ DIALOG main(0) text="Lizarnoar horiei
71 ezusteko bat eman
72 behar diegu" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 30
2 # Ybelle and Ludar met again
3 ##########################################
4
5 {[ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
6
7 {[ MOVE main(0) dir=8 amount=6 ]
8 [ MOVE enemy(0) dir=8 amount=6 ]
9 [ MOVE enemy(1) dir=8 amount=6 ]
10 [ MOVE enemy(2) dir=8 amount=6 ]}
11
12 {[ MOVE main(0) dir=6 amount=3 ]
13 [ MOVE enemy(0) dir=4 amount=3 ]
14 [ MOVE enemy(1) dir=8 amount=4 ]
15 [ MOVE enemy(2) dir=8 amount=4 ]}
16
17 {[ MOVE main(0) dir=6 amount=4 ]
18 [ MOVE enemy(0) dir=4 amount=4 ]
19 [ MOVE enemy(1) dir=4 amount=3 ]
20 [ MOVE enemy(2) dir=6 amount=3 ]}
21
22 {[ DIALOG main(0) text="Ludar!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
23 [ DIALOG enemy(0) text="Ybelle!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
24
25 {[ DIALOG main(0) text="Bizirik zaude!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
26 [ DIALOG enemy(0) text="Ez zaude hilik!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
27
28 {[ DIALOG enemy(0) text="Tira, orain biok
29 batera jarrai genezake" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]}
30
31 {[ DIALOG enemy(0) text="Eskaileratik,
32 jarraitu niri!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
33
34 {[ MOVE main(0) dir=8 amount=3 ]
35 [ MOVE enemy(0) dir=8 amount=3 ]}
0 ##########################################
1 # Holotz's Castle story - Level 32
2 # Return to the land of Lizarno
3 ##########################################
4
5 {[ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCCredits.wav" loops=-1 waitToEnd=0 ]}
8
9 {[ DIALOG main(0) text="Lizarno da!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
10
11 {[ DIALOG enemy(0) text="Itzuli gara!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
12
13 {[ DIALOG main(0) text="Ei, ikusten
14 harri hori?!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
15 [ MOVE main(0) dir=4 amount=2 ]}
16
17 {[ DIALOG enemy(0) text="Ez ezazu ukitu!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
18
19 {[ MOVE main(0) dir=4 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 33
2 # The end
3 ##########################################
4
5 {[ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
7
8 {
9 [ NARRATIVE text="
10 AMAIERA
11 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
12 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle and Ludar arrive to the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
8 }
9
10 {
11 [ NARRATIVE text="Ybelle et Ludar." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
12 }
13
14 {
15 [ DIALOG main(0) text="Qu'est-ce qui s'est passé?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=6 amount=2 ]
17 [ MOVE enemy(0) dir=6 amount=3 ]
18 }
19
20 {
21 [ DIALOG enemy(0) text="Je t'avais dit de ne pas
22 toucher à cette pierre!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Oh, la ferme..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
27 }
28
29 {
30 [ DIALOG main(0) text="Je ne pouvais pas savoir..." txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
31 }
32
33 {
34 [ DIALOG main(0) text="Où sommes-nous?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
35 }
36
37 {
38 [ DIALOG enemy(0) text="HA! Qu'est-ce que j'en sais, moi?" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
39 }
40
41 {
42 [ DIALOG enemy(0) text="Si tu ne touchais par ce que
43 tu ne dois pas toucher..." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
44 }
45
46 {
47 [ DIALOG main(0) text="Abruti..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
48 [ DIALOG enemy(0) text="Idiot..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
49 }
50
51 {
52 [ DIALOG main(0) text="On doit trouver comment
53 rentrer chez nous" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
54 }
55
56 {
57 [ DIALOG main(0) text="Suis-moi, Ludar" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
58 }
59
60 {
61 [ DIALOG enemy(0) text="Non... Tu m'attires
62 toujours des ennuis" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
63 }
64
65 {
66 [ DIALOG enemy(0) text="Cette fois-ci,
67 on fera ce que je dis" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
68 }
69
70 {
71 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
72 }
73
74 {
75 [ DIALOG main(0) text="Ok, alors j'y vais tout seul" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
76 [ MOVE main(0) dir=6 amount=5 ]
77 }
78
79 {
80 [ DIALOG enemy(0) text="???" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
81 [ MOVE main(0) dir=8 amount=3 ]
82 }
83
84 {
85 [ MOVE enemy(0) dir=6 amount=3 ]
86 [ DIALOG enemy(0) text="Hé... Ybelle,
87 Attends moi!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
88 }
89
90 {
91 [ MOVE main(0) dir=6 amount=3 ]
92 }
0 ##########################################
1 # Holotz's Castle story - Level 2
2 # Ybelle enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="noN!" txtAlign=4 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 }
7
8 {
9 [ DIALOG main(0) text="Et mince!" txtAlign=4 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
10 }
11
12 {
13 [ DIALOG main(0) text="LUDAR!" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
14 }
15
16 {
17 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=1 ]
18 }
19
20 {
21 [ DIALOG main(0) text="...il n'a pas l'air de m'entendre" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
22 }
23
24 {
25 [ DIALOG main(0) text="Bon..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
26 [ MOVE main(0) dir=6 amount=1 ]
27 }
28
29 {
30 [ MOVE main(0) dir=4 amount=1 ]
31 [ DIALOG main(0) text="Que font toutes ces clés ici?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]}
0 ##########################################
1 # Holotz's Castle story - Level 7
2 # Ludar enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Hé... Ybelle,
6 Attends moi!" txtAlign=4 speed=2 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ MOVE main(0) dir=6 amount=2 ]
8 }
9
10 {
11 [ MOVE main(0) dir=6 amount=1 ]
12 [ DIALOG main(0) text="Oh, non!" txtAlign=4 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
13 }
14
15 {
16 [ DIALOG main(0) text="Qui a mis un trou ici?" txtAlign=4 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
17 }
18
19 {
20 [ DIALOG main(0) text="Ybelle!" txtAlign=5 speed=1 size=3 align=0 r=20 g=200 b=20 subtype=0 ]
21 }
22
23 {
24 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
25 }
26
27 {
28 [ DIALOG main(0) text="Quel têtu!" txtAlign=5 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
29 }
30
31 {
32 [ DIALOG main(0) text="Oh, regarde" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
33 [ MOVE main(0) dir=4 amount=1 ]
34 }
35
36 {
37 [ DIALOG main(0) text="Ces pierres sont semblables à
38 celle que Ybelle a touché" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
39 [ MOVE main(0) dir=4 amount=1 ]
40 }
41
42 {
43 [ DIALOG main(0) text="Quel est cet endroit?" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
44 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle finds the shoe maker
3 ##########################################
4
5 {[ DIALOG main(0) text="?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Quel est cet endroit?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
9
10 {[ NARRATIVE text="Frabicant de chaussures" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
11 [ MOVE main(0) dir=6 amount=1 ]}
12
13 {[ MOVE main(0) dir=2 amount=3 ]}
14
15 {[ MOVE main(0) dir=6 amount=2 ]}
16
17 {[ MOVE main(0) dir=9 amount=2 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]}
20
21 {[ MOVE main(0) dir=9 amount=1 ]
22 [ DIALOG enemy(0) text="Tiens, un
23 visiteur!" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=1 ]}
24
25 {[ MOVE main(0) dir=9 amount=2 ]}
26
27 {[ DIALOG main(0) text="Quel type
28 étrange!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
29 [ DIALOG enemy(0) text="Quel type
30 étrange!" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=1 ]
31 }
32
33 {[ DIALOG main(0) text="Euh.. Bonjour?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
34
35 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
36
37 {[ DIALOG enemy(0) text="Tu n'as pas
38 l'air d'être..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="...du
41 coin" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
44 [ DIALOG main(0) text="Il donne
45 l'impression qu'il
46 va s'endormir!!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
47
48 {[ DIALOG enemy(0) text="Est-tu nouveau
49 ici..." txtAlign=5 speed=1 size=0 align=0 r=200 g=130 b=20 subtype=0 ]}
50
51 {[ DIALOG enemy(0) text="...depuis..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
52
53 {[ DIALOG enemy(0) text="...longtemps?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
54
55 {[ DIALOG main(0) text="Je vois...
56 Nouveau, tu as dit?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
57
58 {[ DIALOG main(0) text="Ah, oui,
59 d'accord" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
60
61 {[ DIALOG main(0) text="Qui est
62 tu?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
63
64 {[ DIALOG enemy(0) text="Je suis..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
65
66 {[ DIALOG enemy(0) text="...Le Prince de
67 la Chaussure" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=0 ]}
68
69 {[ DIALOG enemy(0) text="Je suppose..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
70
71 {[ DIALOG enemy(0) text="...que tu
72 viens..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
73
74 {[ DIALOG enemy(0) text="...pour une
75 nouvelle paire..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
76
77 {[ DIALOG enemy(0) text="...N'est-ce pas?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
78
79 {[ DIALOG enemy(0) text="Prends..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
80 [ DIALOG main(0) text="Je..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
81
82 {[ DIALOG enemy(0) text="...celles là" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
83
84 {[ MOVE main(0) dir=6 amount=2 ]}
85 {[ MOVE main(0) dir=4 amount=2 ]}
86
87 {[ DIALOG enemy(0) text="Je suis sûr..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
88
89 {[ DIALOG enemy(0) text="... que tu
90 te déplaceras..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
91
92 {[ DIALOG enemy(0) text="...mieux
93 avec..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
94
95 {[ DIALOG main(0) text="Sais-tu
96 comment
97 sortir d'ici?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
98
99 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
100
101 {[ DIALOG enemy(0) text="...non" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
102
103 {[ DIALOG enemy(0) text="...seul
104 Holotz..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
105
106 {[ DIALOG enemy(0) text="...le sait" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
107
108 {[ DIALOG main(0) text="Holotz?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
109
110 {[ DIALOG enemy(0) text="Oui..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
111
112 {[ DIALOG enemy(0) text="Il a créÂé..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
113
114 {[ DIALOG enemy(0) text="...ce
115 château" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
116
117 {[ DIALOG main(0) text="Où puis-je
118 le trouver?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
119
120 {[ DIALOG enemy(0) text="...Tu ne
121 peux pas" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
122
123 {[ DIALOG enemy(0) text="Il..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
124
125 {[ DIALOG enemy(0) text="...te trouveras" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
126
127 {[ DIALOG enemy(0) text="A présent
128 je dois..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
129
130 {[ DIALOG enemy(0) text="...retourner" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
131
132 {[ DIALOG enemy(0) text="...travailler" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
133
134 {[ DIALOG main(0) text="M-mais...!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
135 [ DIALOG enemy(0) text="A présent
136 je dois..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
137
138 {[ DIALOG main(0) text="Laissons-le,
139 il délire" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
140
141 {[ DIALOG main(0) text="Bon, J'y vais...
142 Merci pour
143 les chaussures" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
144 [ MOVE main(0) dir=7 amount=2 ]}
145
146 {[ MOVE main(0) dir=7 amount=2 ]}
147
148 {[ DIALOG main(0) text="Et, où je vais
149 maintenant?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
150
151 {[ DIALOG main(0) text="Oh, Pourquoi
152 pas par là ?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
153 [ MOVE main(0) dir=4 amount=1 ]}
154
155 {[ MOVE main(0) dir=2 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ludar talks to the two flames
3 ##########################################
4
5 {[ DIALOG main(0) text="Oups" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_UltraSlow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Oh, une autre
9 pierre!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
10 [ MOVE main(0) dir=6 amount=1 ]}
11
12 {[ NARRATIVE text="Les Deux Flammes" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=4 ]
14 [ DIALOG main(0) text="Encore une!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
15
16 {[ DIALOG enemy(0) text="Stop!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
17
18 {[ DIALOG main(0) text="???" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
19 [ MOVE main(0) dir=4 amount=1 ]}
20
21 {[ DIALOG main(0) text="Il y a quelqu'un?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
22 [ MOVE main(0) dir=6 amount=4 ]}
23
24 {[ DIALOG enemy(0) text="J'ai dit
25 STOP!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
26
27 {[ MOVE main(0) dir=4 amount=4 ]
28 [ DIALOG main(0) text="Oh, une flamme
29 qui peut parler!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]}
30
31 {[ DIALOG enemy(0) text="Je ne suis pas
32 une flamme qui
33 peut parler!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]
34 [ DIALOG main(0) text="Oh!" txtAlign=5 speed=4 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
35 [ MOVE main(0) dir=6 amount=2 ]}
36
37 {[ DIALOG enemy(0) text="Je suis une
38 flamme qui parle!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
39
40 {[ DIALOG main(0) text="Comment
41 as-tu su ce
42 que je pensais?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
43
44 {[ DIALOG enemy(0) text="Je sais
45 tout!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
46
47 {[ DIALOG enemy(1) text="Ahem..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
48
49 {[ DIALOG enemy(0) text="Bon, presque
50 tout" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
51
52 {[ DIALOG enemy(1) text="Elle lit dans
53 tes pensées..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
54
55 {[ DIALOG enemy(1) text="Et je lis..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
56
57 {[ DIALOG enemy(1) text="...des livres" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
58
59 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]
60 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]
61 [ DIALOG main(0) text="??!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
62
63 {[ DIALOG enemy(1) text="Comment est-tu
64 entré ici?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
65
66 {[ DIALOG enemy(0) text="Je sais..." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
67
68 {[ DIALOG main(0) text="Oh, Elle lit
69 dans mes pensées!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]}
70
71 {[ DIALOG enemy(0) text="Par le portail
72 mystique!!" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
73
74 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
75 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=3 align=0 r=20 g=20 b=180 subtype=0 ]
76 [ DIALOG main(0) text="hmpfxs#@!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
77 [ MOVE main(0) dir=6 amount=4 ]}
78
79 {[ DIALOG enemy(1) text="Attends, ne t'en
80 va pas" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
81 [ MOVE main(0) dir=4 amount=5 ]}
82
83 {[ DIALOG main(0) text="Je n'ai pas le
84 temps de
85 rire!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
86 [ MOVE main(0) dir=6 amount=2 ]}
87
88 {[ DIALOG enemy(0) text="De quoi as-tu
89 besoin?" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]
90 [ MOVE main(0) dir=4 amount=3 ]}
91
92 {[ DIALOG main(0) text="Je dois retrouver
93 Ybelle" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
94
95 {[ DIALOG main(0) text="Nous devons
96 retourner
97 dans le Pays de
98 Lizarno" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
99
100 {[ DIALOG enemy(0) text="Hmmm...un Lizarnite,
101 intéressant" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=1 ]}
102
103 {[ DIALOG enemy(1) text="Maitenant,
104 le château
105 devient" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
106
107 {[ DIALOG enemy(1) text="dangereux" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
108
109 {[ DIALOG enemy(1) text="et tu n'as
110 pas assez
111 d'énergie magique" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
112
113 {[ DIALOG enemy(1) text="pour atteindre
114 le dernier niveau" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
115
116 {[ DIALOG enemy(0) text="Oui, tu as
117 besoin d'une..." txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
118
119 {[ DIALOG enemy(1) text="Paire de
120 chaussures!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
121 [ DIALOG enemy(0) text="Paire de
122 chaussures!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
123
124 {[ DIALOG main(0) text="Oh, arrétez de
125 vous moquer de moi!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
126 [ MOVE main(0) dir=4 amount=2 ]}
127
128 {[ DIALOG enemy(0) text="Mais tu ne peux
129 les avoir que chez" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
130
131 {[ DIALOG enemy(0) text="Le Prince de
132 La Chaussure" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
133
134 {[ DIALOG main(0) text="Il n'y a pas
135 d'autre moyen d'avoir
136 une paire de chaussures?" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
137 [ MOVE main(0) dir=6 amount=2 ]}
138
139 {[ DIALOG enemy(1) text="Si, tu peux en
140 avoir une au..." txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=60 subtype=0 ]}
141
142 {[ DIALOG enemy(1) text="Magasin de chaussures!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=60 subtype=0 ]
143 [ DIALOG enemy(0) text="Magasin de chaussures!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]}
144
145 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
146 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]
147 [ DIALOG main(0) text="C'est
148 exaspérant!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
149 [ MOVE main(0) dir=6 amount=4 ]}
150
151 {[ DIALOG enemy(1) text="Attends" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
152 [ MOVE main(0) dir=4 amount=2 ]}
153
154 {[ DIALOG enemy(1) text="Tu peux avoir
155 une paire" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
156
157 {[ DIALOG enemy(1) text="dans la pièce
158 derrière ce
159 portail mystique" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
160
161 {[ DIALOG enemy(0) text="Mais tu dois
162 savoir" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
163
164 {[ DIALOG enemy(0) text="que personne n'en est
165 ressorti vivant" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
166
167 {[ DIALOG main(0) text="Oh!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
168 [ MOVE main(0) dir=6 amount=2 ]}
169
170 {[ DIALOG main(0) text="Hmm... Tant pis,
171 je dois essayer" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
172 [ MOVE main(0) dir=4 amount=2 ]}
173
174 {[ DIALOG main(0) text="Oh!, mais je
175 ne peut pas ouvrir
176 le portail" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
177 [ MOVE main(0) dir=4 amount=2 ]}
178
179 {[ DIALOG main(0) text="Cette pierre est
180 trop haute!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
181
182 {[ DIALOG enemy(1) text="Et bien, alors
183 utilise cette échelle" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 19
2 # Ybelle is captured
3 ##########################################
4
5 {[ DIALOG main(0) text="AAAH!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_Fast.wav" loops=0 waitToEnd=0 ]}
7
8 {[ MOVE enemy(0) dir=8 amount=4 ]
9 [ MOVE enemy(1) dir=8 amount=4 ]
10 [ MOVE enemy(2) dir=4 amount=2 ]
11 [ MOVE enemy(3) dir=6 amount=2 ]
12 [ MOVE enemy(4) dir=4 amount=5 ]
13 [ MOVE enemy(5) dir=6 amount=5 ]
14 [ DIALOG main(0) text="Oh, oh" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
15 [ DIALOG enemy(2) text="!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=1 ]
16 [ DIALOG enemy(3) text="!" txtAlign=5 speed=1 size=2 align=0 r=220 g=20 b=20 subtype=1 ]}
17
18 {[ NARRATIVE text="
19 A SUIVRE...
20 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
21 [ DIALOG main(0) text="??!" txtAlign=5 speed=3 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=5 amount=1 ]}
23
24 {[ DIALOG main(0) text="Hééé!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
25 [ MOVE main(0) dir=5 amount=2 ]}
26
27 {[ DIALOG main(0) text="Ne me laissez pas là!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
28 [ MOVE main(0) dir=5 amount=2 ]}
29
30 {[ WAIT millis=3000]}
0 ##########################################
1 # Holotz's Castle story - Level 20
2 # Ybelle is captured (continued)
3 ##########################################
4
5 {[ MOVE enemy(0) dir=8 amount=0 ]
6 [ MOVE enemy(1) dir=8 amount=0 ]
7 [ MOVE enemy(2) dir=4 amount=0 ]
8 [ MOVE enemy(3) dir=6 amount=0 ]
9 [ MOVE enemy(4) dir=4 amount=0 ]
10 [ MOVE enemy(5) dir=6 amount=0 ]}
11
12 {[ WAIT millis=1000]}
13
14 {[ DIALOG main(0) text="Stop, ne
15 bougez plus!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=4 amount=1 ]}
17
18 {[ DIALOG enemy(0) text="Je je" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]
19 [ DIALOG enemy(1) text="Hmmm" txtAlign=5 speed=5 size=3 align=0 r=200 g=20 b=20 subtype=0 ]}
20
21 {[ DIALOG main(0) text="Je vous préviens,
22 Je suis dangereux!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
23 [ MOVE main(0) dir=6 amount=2 ]}
24
25 {[ MOVE enemy(1) dir=4 amount=3 ]
26 [ DIALOG enemy(1) text="Regardes..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
27
28 {[ MOVE enemy(1) dir=4 amount=1 ]
29 [ DIALOG enemy(5) text="Quoi?" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
30
31 {[ DIALOG enemy(1) text="Il a des chaussures" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
32
33 {[ DIALOG enemy(5) text="Hmmm...
34 Holotz ne va
35 pas aimer ça" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
36
37 {[ DIALOG main(0) text="Que voulez-vous?" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
38
39 {[ MOVE enemy(5) dir=6 amount=4 ]
40 [ MOVE main(0) dir=6 amount=1 ]
41 [ DIALOG enemy(5) text="La question est..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(5) text="Que fais-tu ici?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
44
45 {[ DIALOG main(0) text="J'ai touché une
46 pierre et..." txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
47
48 {[ DIALOG enemy(5) text="Et un portail mystique
49 s'est ouvert, c'est ça?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
50
51 {[ DIALOG main(0) text="Oui, tout à fait!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
52
53 {[ DIALOG enemy(5) text="Apparement les
54 expériences de Holotz" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
55
56 {[ DIALOG enemy(5) text="n'ont pas réussi" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
57
58 {[ DIALOG enemy(5) text="C'est amusant
59 que tu sois arrivé
60 jusqu'ici..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
61
62 {[ DIALOG enemy(4) text="Que va-t'on
63 faire de lui?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
64
65 {[ DIALOG enemy(5) text="Comme l'a dit
66 Holotz..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
67
68 {[ DIALOG enemy(5) text="...nous allons l'abandonner
69 dans le Labyrinthe
70 de Froj" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
71
72 {[ DIALOG enemy(5) text="Il y restera
73 jusqu'à ce que Holotz
74 décide de son sort..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
75
76 {[ DIALOG enemy(5) text="...si les 4 frères
77 fous ne le trouve
78 pas avant" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
79
80 {[ DIALOG enemy(1) text="Har, har!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=20 subtype=0 ]
81 [ DIALOG enemy(2) text="Hur, hur, hur!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 25
2 # Holotz appears
3 ##########################################
4
5 {
6 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
7 [ NARRATIVE text="Holotz." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
8 }
9
10 {[ MOVE enemy(0) dir=9 amount=2 ]}
11
12 {[ MOVE main(0) dir=4 amount=2 ]
13 [ DIALOG main(0) text="Par le pouvoir
14 de Hutazin!..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
15
16 {[ MOVE enemy(0) dir=9 amount=1 ]}
17 {[ MOVE enemy(0) dir=9 amount=1 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]
20 [ DIALOG main(0) text="Portail Élementaire,
21 ouvre toi!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
22
23 {[ MOVE enemy(0) dir=9 amount=1 ]}
24
25 {[ WAIT millis=3000 ]}
26
27 {[ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
28
29 {[ MOVE main(0) dir=5 amount=1 ]
30 [ DIALOG main(0) text="Encore
31 raté!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
32
33 {[ MOVE main(0) dir=4 amount=2 ]
34 [ MOVE enemy(0) dir=9 amount=1 ]
35 [ DIALOG main(0) text="Toi!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
36
37 {[ DIALOG main(0) text="Où est le
38 lizarnite?" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="On l'a enfermé
41 dans le Labyrinthe
42 de Froj
43 comme vous nous
44 aviez demandé" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
45
46 {[ DIALOG main(0) text="Très bien" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="Mais vous devez savoir" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
49
50 {[ DIALOG enemy(0) text="qu'il a des
51 chaussures, maître" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
52
53 {[ DIALOG main(0) text="Idiot!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
54
55 {[ DIALOG main(0) text="Idiot!
56 Pourquoi tu ne me l'as
57 pas dit plus tôt?" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
58
59 {[ DIALOG enemy(0) text="Je..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
60
61 {[ DIALOG main(0) text="À cette vitesse, ils doivent
62 avoir atteint la tour" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
63
64 {[ DIALOG main(0) text="Amène les
65 bêtes!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
66
67 {[ DIALOG enemy(0) text="Oui, maître" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
68
69 {[ MOVE enemy(0) dir=7 amount=2 ]}
70
71 {[ MOVE enemy(0) dir=7 amount=3 ]
72 [ DIALOG main(0) text="On va faire une
73 surprise à ces
74 deux lizarnites" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 30
2 # Ybelle and Ludar met again
3 ##########################################
4
5 {[ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
6
7 {[ MOVE main(0) dir=8 amount=6 ]
8 [ MOVE enemy(0) dir=8 amount=6 ]
9 [ MOVE enemy(1) dir=8 amount=6 ]
10 [ MOVE enemy(2) dir=8 amount=6 ]}
11
12 {[ MOVE main(0) dir=6 amount=3 ]
13 [ MOVE enemy(0) dir=4 amount=3 ]
14 [ MOVE enemy(1) dir=8 amount=4 ]
15 [ MOVE enemy(2) dir=8 amount=4 ]}
16
17 {[ MOVE main(0) dir=6 amount=4 ]
18 [ MOVE enemy(0) dir=4 amount=4 ]
19 [ MOVE enemy(1) dir=4 amount=3 ]
20 [ MOVE enemy(2) dir=6 amount=3 ]}
21
22 {[ DIALOG main(0) text="Ludar!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
23 [ DIALOG enemy(0) text="Ybelle!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
24
25 {[ DIALOG main(0) text="Tu es vivant!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
26 [ DIALOG enemy(0) text="Tu n'es pas mort!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
27
28 {[ DIALOG enemy(0) text="Bien, maintenant
29 nous pouvons
30 continuer ensemble" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]}
31
32 {[ DIALOG enemy(0) text="Prenons l'échelle,
33 suis moi!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
34
35 {[ MOVE main(0) dir=8 amount=3 ]
36 [ MOVE enemy(0) dir=8 amount=3 ]}
0 ##########################################
1 # Holotz's Castle story - Level 32
2 # Return to the land of Lizarno
3 ##########################################
4
5 {[ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCCredits.wav" loops=-1 waitToEnd=0 ]}
8
9 {[ DIALOG main(0) text="C'est Lizarno!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
10
11 {[ DIALOG enemy(0) text="Nous sommes arrivé!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
12
13 {[ DIALOG main(0) text="Eh, regardes
14 cette pierre!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
15 [ MOVE main(0) dir=4 amount=2 ]}
16
17 {[ DIALOG enemy(0) text="N'y touches pas!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
18
19 {[ MOVE main(0) dir=4 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 33
2 # The end
3 ##########################################
4
5 {[ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
7
8 {
9 [ NARRATIVE text="
10 FIN
11 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
12 }
0 ##########################################
1 # Storia de "Il castello di Holotz" - Livello 1
2 # Ybelle e Ludar arrivano al castello
3 ##########################################
4 {
5 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
8 }
9
10 {
11 [ NARRATIVE text="Ybelle e Ludar." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
12 }
13
14 {
15 [ DIALOG main(0) text="Cosa è successo?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=6 amount=2 ]
17 [ MOVE enemy(0) dir=6 amount=3 ]
18 }
19
20 {
21 [ DIALOG enemy(0) text="Lo avevo detto io
22 di non toccare
23 quella pietra!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
24 }
25
26 {
27 [ DIALOG main(0) text="Oh, taci..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
28 }
29
30 {
31 [ DIALOG main(0) text="E io come
32 potevo saperlo?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
33 }
34
35 {
36 [ DIALOG main(0) text="Dove siamo finiti?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
37 }
38
39 {
40 [ DIALOG enemy(0) text="HA! E che ne so?" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
41 }
42
43 {
44 [ DIALOG enemy(0) text="Se solo tu
45 avessi toccato quello
46 che non dovevi..." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
47 }
48
49 {
50 [ DIALOG main(0) text="Che stupido..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
51 [ DIALOG enemy(0) text="Che stupido..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
52 }
53
54 {
55 [ DIALOG main(0) text="Dobbiamo trovare
56 il modo per tornarcene a casa" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
57 }
58
59 {
60 [ DIALOG main(0) text="Seguimi, Ludar" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
61 }
62
63 {
64 [ DIALOG enemy(0) text="Noo... con te
65 ci si mette sempre
66 nei guai" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
67 }
68
69 {
70 [ DIALOG enemy(0) text="Questa volta sarò io
71 a dire cosa fare" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
72 }
73
74 {
75 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
76 }
77
78 {
79 [ DIALOG main(0) text="Ok, allora
80 andrò da solo!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
81 [ MOVE main(0) dir=6 amount=5 ]
82 }
83
84 {
85 [ DIALOG enemy(0) text="???" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
86 [ MOVE main(0) dir=8 amount=3 ]
87 }
88
89 {
90 [ MOVE enemy(0) dir=6 amount=3 ]
91 [ DIALOG enemy(0) text="eeh... Ybelle,
92 Aspettami!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
93 }
94
95 {
96 [ MOVE main(0) dir=6 amount=3 ]
97 }
0 ##########################################
1 # Storia de "Il castello di Holotz" - Levello 2
2 # Ybelle entra nel castello
3 ##########################################
4 {
5 [ DIALOG main(0) text="noO!" txtAlign=4 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 }
7
8 {
9 [ DIALOG main(0) text="Che male!" txtAlign=4 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
10 }
11
12 {
13 [ DIALOG main(0) text="LUDAR!" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
14 }
15
16 {
17 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=1 ]
18 }
19
20 {
21 [ DIALOG main(0) text="...sembra non possa sentirmi" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
22 }
23
24 {
25 [ DIALOG main(0) text="Bene..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
26 [ MOVE main(0) dir=6 amount=1 ]
27 }
28
29 {
30 [ MOVE main(0) dir=4 amount=1 ]
31 [ DIALOG main(0) text="Che ci fanno
32 tutte queste chiavi?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]}
0 ##########################################
1 # Storia de "Il castello di Holotz" - Levello 7
2 # Ludar entra nel castello
3 ##########################################
4 {
5 [ DIALOG main(0) text="err... Ybelle,
6 Aspettami!" txtAlign=4 speed=2 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ MOVE main(0) dir=6 amount=2 ]
8 }
9
10 {
11 [ MOVE main(0) dir=6 amount=1 ]
12 [ DIALOG main(0) text="Oh, no!" txtAlign=4 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
13 }
14
15 {
16 [ DIALOG main(0) text="Chi ha messo
17 un buco qui?!" txtAlign=4 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
18 }
19
20 {
21 [ DIALOG main(0) text="Ybelle!" txtAlign=5 speed=1 size=3 align=0 r=20 g=200 b=20 subtype=0 ]
22 }
23
24 {
25 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
26 }
27
28 {
29 [ DIALOG main(0) text="Che testardo!" txtAlign=5 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
30 }
31
32 {
33 [ DIALOG main(0) text="Oh, guarda!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=4 amount=1 ]
35 }
36
37 {
38 [ DIALOG main(0) text="Queste pietre
39 sono simili a quella
40 che ha preso Ybelle" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
41 [ MOVE main(0) dir=4 amount=1 ]
42 }
43
44 {
45 [ DIALOG main(0) text="Ma cos'è questo posto?!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
46 }
0 ##########################################
1 # Storia de "Il castello di Holotz" - Levello 1
2 # Ybelle trova il fabbricante di scarpe
3 ##########################################
4
5 {[ DIALOG main(0) text="?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Cos'è questo posto?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
9
10 {[ NARRATIVE text="Il fabbricante di Scarpe" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
11 [ MOVE main(0) dir=6 amount=1 ]}
12
13 {[ MOVE main(0) dir=2 amount=3 ]}
14
15 {[ MOVE main(0) dir=6 amount=2 ]}
16
17 {[ MOVE main(0) dir=9 amount=2 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]}
20
21 {[ MOVE main(0) dir=9 amount=1 ]
22 [ DIALOG enemy(0) text="Ooh, c'è
23 qualcuno!" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=1 ]}
24
25 {[ MOVE main(0) dir=9 amount=2 ]}
26
27 {[ DIALOG main(0) text="Che tipo
28 strano!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
29 [ DIALOG enemy(0) text="Che tipo
30 strano!" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=1 ]
31 }
32
33 {[ DIALOG main(0) text="Err.. Ciao" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
34
35 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
36
37 {[ DIALOG enemy(0) text="Tu non
38 sembri essere..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="...di queste
41 parti" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
44 [ DIALOG main(0) text="Sembra
45 stia per
46 addormentarsi!!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
47
48 {[ DIALOG enemy(0) text="Sei
49 entrato..." txtAlign=5 speed=1 size=0 align=0 r=200 g=130 b=20 subtype=0 ]}
50
51 {[ DIALOG enemy(0) text="...poco..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
52
53 {[ DIALOG enemy(0) text="...tempo fa?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
54
55 {[ DIALOG main(0) text="Vediamo...
56 Nuovo, hai detto?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
57
58 {[ DIALOG main(0) text="Oh, sì,
59 certo..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
60
61 {[ DIALOG main(0) text="Chi sei
62 tu?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
63
64 {[ DIALOG enemy(0) text="Io sono..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
65
66 {[ DIALOG enemy(0) text="...il Signore
67 delle Scarpe" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=0 ]}
68
69 {[ DIALOG enemy(0) text="Suppongo..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
70
71 {[ DIALOG enemy(0) text="...tu sia
72 venuto..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
73
74 {[ DIALOG enemy(0) text="...per un
75 nuovo paio..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
76
77 {[ DIALOG enemy(0) text="...vero?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
78
79 {[ DIALOG enemy(0) text="Prendi..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
80 [ DIALOG main(0) text="Io..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
81
82 {[ DIALOG enemy(0) text="...queste" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
83
84 {[ MOVE main(0) dir=6 amount=2 ]}
85 {[ MOVE main(0) dir=4 amount=2 ]}
86
87 {[ DIALOG enemy(0) text="Tranquillo..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
88
89 {[ DIALOG enemy(0) text="... ti
90 muoverai..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
91
92 {[ DIALOG enemy(0) text="...meglio
93 con esse..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
94
95 {[ DIALOG main(0) text="Tu sai
96 come uscire
97 da qui?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
98
99 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
100
101 {[ DIALOG enemy(0) text="...no" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
102
103 {[ DIALOG enemy(0) text="...solo
104 Holotz..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
105
106 {[ DIALOG enemy(0) text="...lo sa" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
107
108 {[ DIALOG main(0) text="Holotz?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
109
110 {[ DIALOG enemy(0) text="Sì..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
111
112 {[ DIALOG enemy(0) text="Lui ha creato..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
113
114 {[ DIALOG enemy(0) text="...questo
115 castello" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
116
117 {[ DIALOG main(0) text="Dove posso
118 trovarlo?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
119
120 {[ DIALOG enemy(0) text="...non
121 puoi" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
122
123 {[ DIALOG enemy(0) text="Sarà lui..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
124
125 {[ DIALOG enemy(0) text="...a trovare te" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
126
127 {[ DIALOG enemy(0) text="Ora
128 devo..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
129
130 {[ DIALOG enemy(0) text="...tornare" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
131
132 {[ DIALOG enemy(0) text="...al lavoro" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
133
134 {[ DIALOG main(0) text="M-ma...!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
135 [ DIALOG enemy(0) text="Ora
136 devo..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
137
138 {[ DIALOG main(0) text="Meglio lasciarlo,
139 è senza senso" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
140
141 {[ DIALOG main(0) text="Beh, vado...
142 grazie per
143 le Scarpe" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
144 [ MOVE main(0) dir=7 amount=2 ]}
145
146 {[ MOVE main(0) dir=7 amount=2 ]}
147
148 {[ DIALOG main(0) text="Ma dove andrò
149 ora?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
150
151 {[ DIALOG main(0) text="Oh, ma che importa ormai..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
152 [ MOVE main(0) dir=4 amount=1 ]}
153
154 {[ MOVE main(0) dir=2 amount=2 ]}
0 ##########################################
1 # Storia de "Il castello di Holotz" - Levello 16
2 # Ludar parla hai due Fuochi
3 ##########################################
4
5 {[ DIALOG main(0) text="Oops" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_UltraSlow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Oh, un'altra
9 pietra!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
10 [ MOVE main(0) dir=6 amount=1 ]}
11
12 {[ NARRATIVE text="I due Fuochi" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=4 ]
14 [ DIALOG main(0) text="Un'altra ancora!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
15
16 {[ DIALOG enemy(0) text="Fermati!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
17
18 {[ DIALOG main(0) text="???" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
19 [ MOVE main(0) dir=4 amount=1 ]}
20
21 {[ DIALOG main(0) text="C'è qualcuno?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
22 [ MOVE main(0) dir=6 amount=4 ]}
23
24 {[ DIALOG enemy(0) text="Ho detto
25 FERMATI!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
26
27 {[ MOVE main(0) dir=4 amount=4 ]
28 [ DIALOG main(0) text="Oh, una fiamma
29 parlante!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]}
30
31 {[ DIALOG enemy(0) text="Io non sono una
32 fiamma parlante!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]
33 [ DIALOG main(0) text="Oh!" txtAlign=5 speed=4 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=6 amount=2 ]}
35
36 {[ DIALOG enemy(0) text="Io sono una fiamma
37 magica!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
38
39 {[ DIALOG main(0) text="Come fai
40 a sapere quello
41 che penso" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(0) text="Io so
44 Tutto!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
45
46 {[ DIALOG enemy(1) text="Ahem..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="Beh, diciamo
49 quasi tutto" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
50
51 {[ DIALOG enemy(1) text="Lei legge
52 la mente..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
53
54 {[ DIALOG enemy(1) text="Ed io leggo..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
55
56 {[ DIALOG enemy(1) text="...i libri" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
57
58 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]
59 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]
60 [ DIALOG main(0) text="??!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
61
62 {[ DIALOG enemy(1) text="Come sei
63 entrato qui?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="Io lo so..." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
66
67 {[ DIALOG main(0) text="Oh, le basterà leggere
68 la mia mente." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]}
69
70 {[ DIALOG enemy(0) text="con il
71 portale
72 magico!!" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
73
74 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
75 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=3 align=0 r=20 g=20 b=180 subtype=0 ]
76 [ DIALOG main(0) text="hmpfxs#@!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
77 [ MOVE main(0) dir=6 amount=4 ]}
78
79 {[ DIALOG enemy(1) text="Aspetta, non
80 andartene!" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
81 [ MOVE main(0) dir=4 amount=5 ]}
82
83 {[ DIALOG main(0) text="Non ho
84 tempo per
85 scherzare!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
86 [ MOVE main(0) dir=6 amount=2 ]}
87
88 {[ DIALOG enemy(0) text="Di cosa hai
89 bisogno?" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]
90 [ MOVE main(0) dir=4 amount=3 ]}
91
92 {[ DIALOG main(0) text="Voglio trovare
93 Ybelle..." txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
94
95 {[ DIALOG main(0) text="Dobbiamo
96 ritornare
97 nella Terra di
98 Lizarno" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
99
100 {[ DIALOG enemy(0) text="Hmmm...un Lizarnita,
101 interessante..." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=1 ]}
102
103 {[ DIALOG enemy(1) text="Da questo
104 punto in avanti
105 il castello..." txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
106
107 {[ DIALOG enemy(1) text="...si farà più pericoloso..." txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
108
109 {[ DIALOG enemy(1) text="...e tu non hai
110 abbastanza
111 forza magica..." txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
112
113 {[ DIALOG enemy(1) text="...per raggiungere
114 il livello più alto." txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
115
116 {[ DIALOG enemy(0) text="Sì, ciò che
117 ti serve è..." txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
118
119 {[ DIALOG enemy(1) text="...un paio
120 di scarpe!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
121 [ DIALOG enemy(0) text="...un paio
122 di scarpe!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
123
124 {[ DIALOG main(0) text="Oh, basta
125 scherzare!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
126 [ MOVE main(0) dir=4 amount=2 ]}
127
128 {[ DIALOG enemy(0) text="Ma potrai averle
129 solamente dal.." txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
130
131 {[ DIALOG enemy(0) text="...Signore
132 delle Scarpe" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
133
134 {[ DIALOG main(0) text="Non c'è nessun
135 altro modo per avere
136 un paio di Scarpe?" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
137 [ MOVE main(0) dir=6 amount=2 ]}
138
139 {[ DIALOG enemy(1) text="Sì, puoi averle
140 andando..." txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=60 subtype=0 ]}
141
142 {[ DIALOG enemy(1) text="...in un negozio di scarpe!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=60 subtype=0 ]
143 [ DIALOG enemy(0) text="...in un negozio di scarpe!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]}
144
145 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
146 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]
147 [ DIALOG main(0) text="Sto perdendo
148 la pazienza!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
149 [ MOVE main(0) dir=6 amount=4 ]}
150
151 {[ DIALOG enemy(1) text="Calma" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
152 [ MOVE main(0) dir=4 amount=2 ]}
153
154 {[ DIALOG enemy(1) text="Ne troverai
155 un paio.." txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
156
157 {[ DIALOG enemy(1) text="...nella stanza
158 oltre questo
159 portale magico..." txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
160
161 {[ DIALOG enemy(0) text="...ma devi
162 sapere" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
163
164 {[ DIALOG enemy(0) text="...che nessuno
165 è mai tornato indietro." txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
166
167 {[ DIALOG main(0) text="Oh!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
168 [ MOVE main(0) dir=6 amount=2 ]}
169
170 {[ DIALOG main(0) text="Hmm... Comunque,
171 devo provare!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
172 [ MOVE main(0) dir=4 amount=2 ]}
173
174 {[ DIALOG main(0) text="Oh!, ma non
175 posso aprire
176 il portale..." txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
177 [ MOVE main(0) dir=4 amount=2 ]}
178
179 {[ DIALOG main(0) text="...quella pietra
180 è troppo alta!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
181
182 {[ DIALOG enemy(1) text="Allora... usa
183 questa scala!" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
0 ##########################################
1 # Storia de "Il castello di Holotz" - Level 19
2 # Ybelle viene catturato (parte I)
3 ##########################################
4
5 {[ DIALOG main(0) text="AAAH!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_Fast.wav" loops=0 waitToEnd=0 ]}
7
8 {[ MOVE enemy(0) dir=8 amount=4 ]
9 [ MOVE enemy(1) dir=8 amount=4 ]
10 [ MOVE enemy(2) dir=4 amount=2 ]
11 [ MOVE enemy(3) dir=6 amount=2 ]
12 [ MOVE enemy(4) dir=4 amount=5 ]
13 [ MOVE enemy(5) dir=6 amount=5 ]
14 [ DIALOG main(0) text="Oh, oh" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
15 [ DIALOG enemy(2) text="!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=1 ]
16 [ DIALOG enemy(3) text="!" txtAlign=5 speed=1 size=2 align=0 r=220 g=20 b=20 subtype=1 ]}
17
18 {[ NARRATIVE text="
19 CONTINUA...
20 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
21 [ DIALOG main(0) text="??!" txtAlign=5 speed=3 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=5 amount=1 ]}
23
24 {[ DIALOG main(0) text="Eeeh!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
25 [ MOVE main(0) dir=5 amount=2 ]}
26
27 {[ DIALOG main(0) text="Non lasciarmi qui!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
28 [ MOVE main(0) dir=5 amount=2 ]}
29
30 {[ WAIT millis=3000]}
0 ##########################################
1 # Storia de "Il castello di Holotz" - Levello 20
2 # Ybelle viene catturato (parte II)
3 ##########################################
4
5 {[ MOVE enemy(0) dir=8 amount=0 ]
6 [ MOVE enemy(1) dir=8 amount=0 ]
7 [ MOVE enemy(2) dir=4 amount=0 ]
8 [ MOVE enemy(3) dir=6 amount=0 ]
9 [ MOVE enemy(4) dir=4 amount=0 ]
10 [ MOVE enemy(5) dir=6 amount=0 ]}
11
12 {[ WAIT millis=1000]}
13
14 {[ DIALOG main(0) text="Fermi, non
15 una mossa!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=4 amount=1 ]}
17
18 {[ DIALOG enemy(0) text="Je je" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]
19 [ DIALOG enemy(1) text="Hmmm" txtAlign=5 speed=5 size=3 align=0 r=200 g=20 b=20 subtype=0 ]}
20
21 {[ DIALOG main(0) text="Vi avviso,
22 sono pericoloso!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
23 [ MOVE main(0) dir=6 amount=2 ]}
24
25 {[ MOVE enemy(1) dir=4 amount=3 ]
26 [ DIALOG enemy(1) text="Guardate..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
27
28 {[ MOVE enemy(1) dir=4 amount=1 ]
29 [ DIALOG enemy(5) text="Cosa?" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
30
31 {[ DIALOG enemy(1) text="Lui ha le... Scarpe!" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
32
33 {[ DIALOG enemy(5) text="Hmmm...
34 Ad Holotz
35 non piacerà" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
36
37 {[ DIALOG main(0) text="Cosa volete?" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
38
39 {[ MOVE enemy(5) dir=6 amount=4 ]
40 [ MOVE main(0) dir=6 amount=1 ]
41 [ DIALOG enemy(5) text="La domanda è..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(5) text="Che cosa fai
44 tu qui?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
45
46 {[ DIALOG main(0) text="Ho preso
47 una pietra e..." txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
48
49 {[ DIALOG enemy(5) text="..e un portale magico
50 si è aperto, giusto?." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
51
52 {[ DIALOG main(0) text="Sì, esatto!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
53
54 {[ DIALOG enemy(5) text="Sembra proprio uno
55 degli esperimenti di Holotz..." txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
56
57 {[ DIALOG enemy(5) text="...senza successo" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
58
59 {[ DIALOG enemy(5) text="Mi stupisce
60 che tu sia arrivato
61 fino a qui..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
62
63 {[ DIALOG enemy(4) text="Che cosa
64 ne facciamo?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
65
66 {[ DIALOG enemy(5) text="Come Holotz
67 ha ordinato..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
68
69 {[ DIALOG enemy(5) text="...lo porteremo
70 al Labirinto
71 di Froj" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
72
73 {[ DIALOG enemy(5) text="Starà lì
74 finchè Holotz non deciderà
75 cosa farne..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
76
77 {[ DIALOG enemy(5) text="...sempre che i Quattro
78 Fratelli Folli non
79 lo trovino prima..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
80
81 {[ DIALOG enemy(1) text="Har, har!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=20 subtype=0 ]
82 [ DIALOG enemy(2) text="Hur, hur, hur!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
0 ##########################################
1 # Storia de "Il castello di Holotz" - Levello 25
2 # L'apparizione di Holotz
3 ##########################################
4
5 {
6 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
7 [ NARRATIVE text="Holotz." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
8 }
9
10 {[ MOVE enemy(0) dir=9 amount=2 ]}
11
12 {[ MOVE main(0) dir=4 amount=2 ]
13 [ DIALOG main(0) text="Per il potere
14 di Hutazin!..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
15
16 {[ MOVE enemy(0) dir=9 amount=1 ]}
17 {[ MOVE enemy(0) dir=9 amount=1 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]
20 [ DIALOG main(0) text="Portale Elementale,
21 apriti!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
22
23 {[ MOVE enemy(0) dir=9 amount=1 ]}
24
25 {[ WAIT millis=3000 ]}
26
27 {[ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
28
29 {[ MOVE main(0) dir=5 amount=1 ]
30 [ DIALOG main(0) text="Si è chiuso
31 di nuovo!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
32
33 {[ MOVE main(0) dir=4 amount=2 ]
34 [ MOVE enemy(0) dir=9 amount=1 ]
35 [ DIALOG main(0) text="Tu!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
36
37 {[ DIALOG main(0) text="Dove si trova il
38 lizarnita?" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="Lo abbiamo portato
41 al Labirinto di Froj,
42 come hai ordinato..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
43
44 {[ DIALOG main(0) text="Bene" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
45
46 {[ DIALOG enemy(0) text="Devi sapere, signore..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="che ha trovato...
49 le Scarpe." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
50
51 {[ DIALOG main(0) text="Idiota!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
52
53 {[ DIALOG main(0) text="Inetto!
54 Perchè non me lo
55 hai detto subito?!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
56
57 {[ DIALOG enemy(0) text="Io..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
58
59 {[ DIALOG main(0) text="Di questo passo
60 raggiungerà la torre" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
61
62 {[ DIALOG main(0) text="Portate
63 le bestie!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="Sì, mio signore" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
66
67 {[ MOVE enemy(0) dir=7 amount=2 ]}
68
69 {[ MOVE enemy(0) dir=7 amount=3 ]
70 [ DIALOG main(0) text="Faremo ai
71 lizarniti una
72 bella sorpresa!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
0 ##########################################
1 # Storia de "Il castello di Holotz" - Levello 30
2 # Ybelle e Ludar si incontrano
3 ##########################################
4
5 {[ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
6
7 {[ MOVE main(0) dir=8 amount=6 ]
8 [ MOVE enemy(0) dir=8 amount=6 ]
9 [ MOVE enemy(1) dir=8 amount=6 ]
10 [ MOVE enemy(2) dir=8 amount=6 ]}
11
12 {[ MOVE main(0) dir=6 amount=3 ]
13 [ MOVE enemy(0) dir=4 amount=3 ]
14 [ MOVE enemy(1) dir=8 amount=4 ]
15 [ MOVE enemy(2) dir=8 amount=4 ]}
16
17 {[ MOVE main(0) dir=6 amount=4 ]
18 [ MOVE enemy(0) dir=4 amount=4 ]
19 [ MOVE enemy(1) dir=4 amount=3 ]
20 [ MOVE enemy(2) dir=6 amount=3 ]}
21
22 {[ DIALOG main(0) text="Ludar!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
23 [ DIALOG enemy(0) text="Ybelle!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
24
25 {[ DIALOG main(0) text="Sei vivo!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
26 [ DIALOG enemy(0) text="Non sei morto!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
27
28 {[ DIALOG enemy(0) text="Bene, ora potremo
29 continuare insieme!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]}
30
31 {[ DIALOG enemy(0) text="Alla scala,
32 seguimi!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
33
34 {[ MOVE main(0) dir=8 amount=3 ]
35 [ MOVE enemy(0) dir=8 amount=3 ]}
0 ##########################################
1 # Storia de "Il castello di Holotz" - Levello 32
2 # Ritorno alla terra di Lizarno
3 ##########################################
4
5 {[ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCCredits.wav" loops=-1 waitToEnd=0 ]}
8
9 {[ DIALOG main(0) text="È Lizarno!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
10
11 {[ DIALOG enemy(0) text="Siamo tornati!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
12
13 {[ DIALOG main(0) text="Ehi, guarda che
14 bella quella pietra!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
15 [ MOVE main(0) dir=4 amount=2 ]}
16
17 {[ DIALOG enemy(0) text="Non toccarla!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
18
19 {[ MOVE main(0) dir=4 amount=2 ]}
0 ##########################################
1 # Storia de "Il castello di Holotz" - Levello 33
2 # Fine
3 ##########################################
4
5 {[ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
7
8 {
9 [ NARRATIVE text="
10 FINE
11 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
12 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle and Ludar arrive to the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
8 }
9
10 {
11 [ NARRATIVE text="Ybelle en Ludar." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
12 }
13
14 {
15 [ DIALOG main(0) text="Wow! Wat is er net gebeurd?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=6 amount=2 ]
17 [ MOVE enemy(0) dir=6 amount=3 ]
18 }
19
20 {
21 [ DIALOG enemy(0) text="Ik zei toch
22 dat je die steen
23 niet moest aanraken!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
24 }
25
26 {
27 [ DIALOG main(0) text="Oh, hou je kop..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
28 }
29
30 {
31 [ DIALOG main(0) text="Hoe kon ik
32 dat nou weten?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
33 }
34
35 {
36 [ DIALOG main(0) text="Waar zijn we?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
37 }
38
39 {
40 [ DIALOG enemy(0) text="HA! Vertel JIJ mij
41 dat maar!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
42 }
43
44 {
45 [ DIALOG enemy(0) text="Als je er nou gewoon vanaf gebleven was..." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
46 }
47
48 {
49 [ DIALOG main(0) text="Domkop..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
50 [ DIALOG enemy(0) text="Drol..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
51 }
52
53 {
54 [ DIALOG main(0) text="We moeten een weg
55 terug naar huis vinden" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
56 }
57
58 {
59 [ DIALOG main(0) text="Volg mij, Ludar" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
60 }
61
62 {
63 [ DIALOG enemy(0) text="Mooi niet! Door jou
64 kom ik steeds
65 maar weer in
66 de problemen." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
67 }
68
69 {
70 [ DIALOG enemy(0) text="Deze keer doen
71 we het op mijn manier" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
72 }
73
74 {
75 [ DIALOG main(0) text="Nou..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
76 }
77
78 {
79 [ DIALOG main(0) text="Ik denk dat
80 ik maar alleen ga" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
81 [ MOVE main(0) dir=6 amount=5 ]
82 }
83
84 {
85 [ DIALOG enemy(0) text="???" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
86 [ MOVE main(0) dir=8 amount=3 ]
87 }
88
89 {
90 [ MOVE enemy(0) dir=6 amount=3 ]
91 [ DIALOG enemy(0) text="eh... Ybelle,
92 Wacht op mij!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
93 }
94
95 {
96 [ MOVE main(0) dir=6 amount=3 ]
97 }
0 ##########################################
1 # Holotz's Castle story - Level 2
2 # Ybelle enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Neeee!" txtAlign=4 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 }
7
8 {
9 [ DIALOG main(0) text="Dat deed pijn!" txtAlign=4 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
10 }
11
12 {
13 [ DIALOG main(0) text="LUDAR!" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
14 }
15
16 {
17 [ DIALOG main(0) text="?" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=1 ]
18 }
19
20 {
21 [ DIALOG main(0) text="Misschien kan
22 hij mij niet horen." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Wat...?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
27 [ MOVE main(0) dir=6 amount=1 ]
28 }
29
30 {
31 [ MOVE main(0) dir=4 amount=1 ]
32 [ DIALOG main(0) text="Wat is de bedoeling
33 van al die sleutels?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
34
35 }
36
37 # REMIND USER THAT THIS IS YBELLE.
38 # TEACH THE USER THAT SPACE IS JUMP.
39 # MAKE SURE THEY KNOW WHAT A "MAGIC PORTAL" IS, TO SET UP THE JOKE IN LEVEL 16.
40 {
41 [ NARRATIVE text="Druk op spatie om Ybelle in de
42 magische poort te laten springen" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
43 }
0 ##########################################
1 # Holotz's Castle story - Level 7
2 # Ludar enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="eh... Ybelle,
6 Wacht op mij!" txtAlign=4 speed=2 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ MOVE main(0) dir=6 amount=2 ]
8 }
9
10 {
11 [ MOVE main(0) dir=6 amount=1 ]
12 [ DIALOG main(0) text="Oh nee!" txtAlign=4 speed=5 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
13 }
14
15
16 {
17 [ DIALOG main(0) text="Wie heeft dat gat
18 hier gemaakt?" txtAlign=4 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
19 }
20
21 {
22 [ DIALOG main(0) text="Help! Ybelle!" txtAlign=5 speed=1 size=3 align=0 r=20 g=200 b=20 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Waarom geeft hij
27 geen antwoord?" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
28 }
29
30 {
31 [ DIALOG main(0) text="Eigenwijze pummel!" txtAlign=5 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
32 }
33
34 {
35 [ DIALOG main(0) text="Oh, hey!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
36 [ MOVE main(0) dir=4 amount=1 ]
37 }
38
39 {
40 [ DIALOG main(0) text="Die stenen lijken
41 veel op degenen die
42 Ybelle meenam" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
43 [ MOVE main(0) dir=4 amount=1 ]
44 }
45
46 {
47 # EXPLAIN WHY YBELLE IS GRABBING STONES AFTER HE TOLD LUDAR NOT TO
48 [ DIALOG main(0) text="Zou er hier
49 een uitweg zijn?" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
50 [ MOVE main(0) dir=4 amount=1 ]
51 }
52
53 {
54 # SHOULD GIVE USER A HINT THAT GAME IS STARTING AS LUDAR
55 [ DIALOG main(0) text="Zo te zien is het mijn beurt
56 om een poging te doen" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
57 }
58
59 # MORE HINTS FOR THE USER AND A REMINDER THAT THIS GUY IS LUDAR
60 {
61 [ NARRATIVE text="Spatie ingedrukt houden laat Ludar hoger springen" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
62 }
0 ##########################################
1 # Holotz's Castle story - Level 14
2 # Ybelle finds the shoe maker
3 ##########################################
4
5 {[ DIALOG main(0) text="Pfff!
6 Gelukkig ben
7 ik eruit" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
8 [ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
9
10 {[ DIALOG main(0) text="Maar, wat is dit voor een plek?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
11
12 {[ NARRATIVE text="Ybelle in De Werkplaats van de Schoenenmaker" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=1 ]}
14
15 {[ MOVE main(0) dir=2 amount=3 ]}
16
17 {[ MOVE main(0) dir=6 amount=2 ]}
18
19 {[ MOVE main(0) dir=9 amount=2 ]}
20
21 {[ MOVE main(0) dir=6 amount=3 ]}
22
23 {[ MOVE main(0) dir=9 amount=1 ]
24 [ DIALOG enemy(0) text="Een bezoeker!" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=1 ]}
25
26 {[ MOVE main(0) dir=9 amount=2 ]}
27
28 {[ DIALOG main(0) text="Wat een
29 vreemde gozer!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
30 [ DIALOG enemy(0) text="Wat een
31 vreemde gozer!" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=1 ]
32 }
33
34 {[ DIALOG main(0) text="Eh.. Hallo?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
35
36 {[ DIALOG enemy(0) text="Jij..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
37
38 {[ DIALOG enemy(0) text="lijkt..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="niet..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
41 [ DIALOG main(0) text="?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
42
43
44 {[ DIALOG enemy(0) text="uit..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
45
46 {[ DIALOG enemy(0) text="deze..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="buurt..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
49
50 {[ DIALOG enemy(0) text="te..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
51
52 {[ DIALOG enemy(0) text="komen" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
53
54 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
55 [ DIALOG main(0) text="Het leek erop
56 dat hij in slaap
57 zou vallen!!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
58
59 {[ DIALOG enemy(0) text="Ben...
60 jij...
61 de..." txtAlign=5 speed=1 size=0 align=1 r=200 g=130 b=20 subtype=0 ]}
62
63 {[ DIALOG main(0) text="Luister... Oh" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
64 [ DIALOG enemy(0) text="nieuwe..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
65
66 {[ DIALOG main(0) text="Nieuw, zei je?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
67
68 {[ DIALOG main(0) text="Nou, ja,
69 Ik ben hier nieuw" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
70
71 {[ DIALOG main(0) text="Wie ben jij?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
72
73 {[ DIALOG enemy(0) text="Ik... ben..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
74
75 {[ DIALOG enemy(0) text="De Heer van
76 De Schoenen" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=0 ]}
77
78 {[ DIALOG enemy(0) text="Je bent...
79 gekomen...
80 voor..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
81
82 {[ DIALOG enemy(0) text="een...
83 nieuw...
84 paar..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
85
86 {[ DIALOG enemy(0) text="...Nietwaar?" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
87 [ DIALOG main(0) text="Nou,
88 eigenlijk" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
89
90 {[ DIALOG enemy(0) text="Neem..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
91 [ DIALOG main(0) text="Ik..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
92
93 {[ DIALOG enemy(0) text="...deze" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
94
95
96
97 {[ MOVE main(0) dir=6 amount=2 ]}
98 {[ MOVE main(0) dir=4 amount=2 ]}
99
100 {[ DIALOG enemy(0) text="Je...
101 sprongen...
102 zullen..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
103
104 {[ DIALOG enemy(0) text="..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
105 [ DIALOG main(0) text="Weet u
106 een weg
107 hiervandaan?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
108 }
109
110 {[ DIALOG enemy(0) text="Even...
111 denken..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
112
113 {[ DIALOG enemy(0) text="Nee" txtAlign=5 speed=1 size=2 align=1 r=200 g=130 b=20 subtype=0 ]}
114
115 {[ DIALOG enemy(0) text="Alleen...
116 Holotz..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
117
118 {[ DIALOG enemy(0) text="weet dat..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
119 [ DIALOG main(0) text="Holotz?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
120
121 {[ DIALOG enemy(0) text="Ja..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
122 {[ DIALOG enemy(0) text="Hij...
123 maakte..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
124
125 {[ DIALOG enemy(0) text="dit alles..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
126 [ DIALOG main(0) text="Waar kan
127 ik hem vinden?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
128
129 {[ DIALOG enemy(0) text="Dat kan...
130 je niet..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
131
132 {[ DIALOG enemy(0) text="Hij zal...
133 jou...
134 vinden" txtAlign=5 speed=1 size=2 align=1 r=200 g=130 b=20 subtype=0 ]}
135 {[ DIALOG main(0) text="!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
136
137
138 {[ DIALOG enemy(0) text="Nu...
139 moet...
140 ik..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
141
142 {[ DIALOG enemy(0) text="terug...
143 aan...
144 het...
145 werk" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
146
147 {[ DIALOG main(0) text="M-maar...!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
148 [ DIALOG enemy(0) text="Nu...
149 moet...
150 ik..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
151
152 {[ DIALOG main(0) text="Oh, laat deze
153 onzin maar zitten!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
154
155 {[ DIALOG main(0) text="Nu ja, Ik ga...
156 bedankt voor
157 de schoenen" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
158 [ MOVE main(0) dir=7 amount=2 ]}
159
160 {[ MOVE main(0) dir=7 amount=2 ]}
161
162 {[ DIALOG main(0) text="Maar, waar moet
163 ik nu heen?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
164
165 {[ DIALOG main(0) text="Nu ja." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
166
167 {[ DIALOG main(0) text="Wanneer je verdwaalt bent" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
168 [ MOVE main(0) dir=4 amount=1 ]}
169
170 {[ DIALOG main(0) text="dan is elke richting
171 de goede" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
172 {[ MOVE main(0) dir=2 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 16
2 # Ludar talks to the two flames
3 ##########################################
4
5 {[ DIALOG main(0) text="Oeps" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_UltraSlow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Oeh, nog een
9 steen!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
10 [ MOVE main(0) dir=6 amount=1 ]}
11
12 {[ NARRATIVE text="Ludar en de Twee Vlammen" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=4 ]
14 [ DIALOG main(0) text="...en nog een!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
15
16 {[ DIALOG enemy(0) text="Halt!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
17
18 {[ DIALOG main(0) text="???" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
19 [ MOVE main(0) dir=4 amount=1 ]}
20
21 {[ DIALOG main(0) text="Wie is daar?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
22 [ MOVE main(0) dir=6 amount=4 ]}
23
24 {[ DIALOG enemy(0) text="Ik zei
25 HALT!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
26
27 {[ MOVE main(0) dir=4 amount=4 ]
28 [ DIALOG main(0) text="Oh, een pratende
29 vlam!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]}
30
31 {[ DIALOG enemy(0) text="Ik ben geen
32 pratende vlam!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]
33 [ DIALOG main(0) text="Oh!" txtAlign=5 speed=4 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=6 amount=2 ]}
35
36 {[ DIALOG enemy(0) text="Ik ben een sprekende
37 vlam!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
38
39 {[ DIALOG main(0) text="Hoe wist
40 je wat
41 ik dacht?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(0) text="Ik weet
44 alles!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
45
46 {[ DIALOG enemy(1) text="Ahem..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="Nou ja, bijna
49 alles" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
50
51 {[ DIALOG enemy(1) text="Ze leest
52 gedachten..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
53
54 {[ DIALOG enemy(1) text="En ik lees..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
55
56 {[ DIALOG enemy(1) text="...Boeken" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
57
58 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]
59 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]
60 [ DIALOG main(0) text="??!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
61
62 {[ DIALOG enemy(1) text="Hoe ben je
63 hier gekomen?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="Ik weet het..." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
66
67 {[ DIALOG main(0) text="Oh, Ze gaat mijn
68 gedachten lezen!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]}
69
70 {[ DIALOG enemy(0) text="Via de
71 mystieke
72 poort!!" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
73
74 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
75 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=3 align=0 r=20 g=20 b=180 subtype=0 ]
76 [ DIALOG main(0) text="hmpfxs#@!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
77 [ MOVE main(0) dir=6 amount=4 ]}
78
79 {[ DIALOG enemy(1) text="Wacht, ga
80 niet weg" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
81 [ MOVE main(0) dir=4 amount=5 ]}
82
83 {[ DIALOG main(0) text="Ik heb geen
84 tijd voor
85 grapjes!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
86 [ MOVE main(0) dir=6 amount=2 ]}
87
88 {[ DIALOG enemy(0) text="Wat heb
89 je nodig?" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]
90 [ MOVE main(0) dir=4 amount=3 ]}
91
92 {[ DIALOG main(0) text="Ik moet
93 Ybelle vinden" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
94
95 {[ DIALOG main(0) text="We moeten
96 terug naar
97 het Land van
98 Lizarno" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
99
100 {[ DIALOG enemy(0) text="Hmmm...een Lizarniet,
101 Interessant" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=1 ]}
102
103 {[ DIALOG enemy(1) text="Vanaf hier wordt
104 het kasteel veel
105 gevaarlijker" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
106
107 {[ DIALOG enemy(1) text="Maar jij mist
108 magische krachten" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
109
110 {[ DIALOG enemy(1) text="en je kunt
111 het hoogste nivo
112 niet bereiken" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
113
114 {[ DIALOG enemy(0) text="Ja, wat jij
115 nodig hebt, is..." txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
116
117 {[ DIALOG enemy(1) text="Een paar
118 schoenen!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
119 [ DIALOG enemy(0) text="Een paar
120 schoenen!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
121
122 {[ DIALOG main(0) text="Oh, houd op met
123 grapjes maken!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
124 [ MOVE main(0) dir=4 amount=2 ]}
125
126 {[ DIALOG enemy(0) text="Maar je kunt ze
127 alleen krijgen van" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
128
129 {[ DIALOG enemy(0) text="De Heer van
130 De Schoenen" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
131
132 {[ DIALOG main(0) text="Is er geen andere
133 manier om een paar
134 schoenen te krijgen?" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
135 [ MOVE main(0) dir=6 amount=2 ]}
136
137 {[ DIALOG enemy(1) text="Ja, je kunt
138 ze krijgen in" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=60 subtype=0 ]}
139
140 {[ DIALOG enemy(1) text="De schoenenwinkel!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=60 subtype=0 ]
141 [ DIALOG enemy(0) text="De schoenenwinkel!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]}
142
143 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
144 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]
145 [ DIALOG main(0) text="Dit is erg
146 vermoeiend!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
147 [ MOVE main(0) dir=6 amount=4 ]}
148
149 {[ DIALOG enemy(1) text="Wacht" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
150 [ MOVE main(0) dir=4 amount=2 ]}
151
152 {[ DIALOG enemy(1) text="Je kunt een
153 paar vinden" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
154
155 {[ DIALOG enemy(1) text="in de kamer
156 achter deze
157 mystieke poort" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
158
159 {[ DIALOG enemy(0) text="Maar je moet
160 weten" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
161
162 {[ DIALOG enemy(0) text="dat nog niemand die
163 levend verlaten heeft" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
164
165 {[ DIALOG main(0) text="Oh!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
166 [ MOVE main(0) dir=6 amount=2 ]}
167
168 {[ DIALOG main(0) text="Hmm... Nu ja,
169 Ik moet het proberen" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
170 [ MOVE main(0) dir=4 amount=2 ]}
171
172 {[ DIALOG main(0) text="Oh! Maar ik
173 kan de poort
174 niet openen" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
175 [ MOVE main(0) dir=4 amount=2 ]}
176
177 {[ DIALOG main(0) text="Die steen is
178 te hoog!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
179
180 {[ DIALOG enemy(1) text="Nou, gebruik deze
181 trap dan" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 19
2 # Ybelle is captured
3 ##########################################
4
5 {[ DIALOG main(0) text="AAAH!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_Fast.wav" loops=0 waitToEnd=0 ]}
7
8 {[ MOVE enemy(0) dir=8 amount=4 ]
9 [ MOVE enemy(1) dir=8 amount=4 ]
10 [ MOVE enemy(2) dir=4 amount=2 ]
11 [ MOVE enemy(3) dir=6 amount=2 ]
12 [ MOVE enemy(4) dir=4 amount=5 ]
13 [ MOVE enemy(5) dir=6 amount=5 ]
14 [ DIALOG main(0) text="Uh oh" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
15 [ DIALOG enemy(2) text="!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=1 ]
16 [ DIALOG enemy(3) text="!" txtAlign=5 speed=1 size=2 align=0 r=220 g=20 b=20 subtype=1 ]}
17
18 {[ NARRATIVE text="
19 WORDT VERVOLGD...
20 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
21 [ DIALOG main(0) text="??!" txtAlign=5 speed=3 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=5 amount=1 ]}
23
24 {[ DIALOG main(0) text="Eeeh!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
25 [ MOVE main(0) dir=5 amount=2 ]}
26
27 {[ DIALOG main(0) text="Laat mij niet alleen achter!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
28 [ MOVE main(0) dir=5 amount=2 ]}
29
30 {[ WAIT millis=3000]}
0 ##########################################
1 # Holotz's Castle story - Level 20
2 # Ybelle is captured (continued)
3 ##########################################
4
5 {[ MOVE enemy(0) dir=8 amount=0 ]
6 [ MOVE enemy(1) dir=8 amount=0 ]
7 [ MOVE enemy(2) dir=4 amount=0 ]
8 [ MOVE enemy(3) dir=6 amount=0 ]
9 [ MOVE enemy(4) dir=4 amount=0 ]
10 [ MOVE enemy(5) dir=6 amount=0 ]}
11
12 {[ WAIT millis=1000]}
13
14 {[ DIALOG main(0) text="Halt, niet
15 bewegen!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=4 amount=1 ]}
17
18 {[ DIALOG enemy(0) text="Hee hee" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]
19 [ DIALOG enemy(1) text="Huh?" txtAlign=5 speed=5 size=3 align=0 r=200 g=20 b=20 subtype=0 ]}
20
21 {[ DIALOG main(0) text="Pas op anders moet ik
22 mijn Kung Fu op jullie toepassen!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
23 [ MOVE main(0) dir=6 amount=2 ]}
24
25 {[ MOVE enemy(1) dir=4 amount=3 ]
26 [ DIALOG enemy(1) text="Kijk!" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
27
28 {[ MOVE enemy(1) dir=4 amount=1 ]
29 [ DIALOG enemy(5) text="What?" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
30
31 {[ DIALOG enemy(1) text="Hij heeft... schoenen" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
32
33 {[ DIALOG enemy(5) text="Oh ho!
34 Holotz zal dat
35 niet leuk vinden" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
36
37 {[ DIALOG main(0) text="Wat willen jullie?" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
38
39 {[ MOVE enemy(5) dir=6 amount=4 ]
40 [ MOVE main(0) dir=6 amount=1 ]
41 [ DIALOG enemy(5) text="De vraag is..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(5) text="Wat doe JIJ hier?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
44
45 {[ DIALOG main(0) text="Ik pakte een
46 steen op en..." txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
47
48 {[ DIALOG enemy(5) text="En er opende een mystieke
49 poor. Toch?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
50
51 {[ DIALOG main(0) text="Ja, precies!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
52
53 {[ DIALOG enemy(5) text="Het lijkt erop
54 dat Holotz's experimenten
55 niet gelukt zijn" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
56
57 {[ DIALOG enemy(5) text="Ik vind het grappig
58 dat je het tot zover
59 heb weten te brengen..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
60
61 {[ DIALOG enemy(4) text="Wat doen we
62 met hem?" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=0 ]}
63
64 {[ DIALOG enemy(5) text="We doen wat
65 Holotz zegt..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
66
67 {[ DIALOG enemy(5) text="...we brengen hem
68 naar het Labyrint
69 van Froj" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
70
71 {[ DIALOG enemy(5) text="Daar zal hij blijven
72 tot Holotz over zijn lot
73 beslist heeft..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
74
75 {[ DIALOG enemy(5) text="...Tenzij de vier
76 gestoorde broers
77 hem eerst vinden!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
78
79 {[ DIALOG enemy(1) text="Har, har!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=20 subtype=0 ]
80 [ DIALOG enemy(2) text="Hur, hur, hur!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ] }
81
82 {[ DIALOG main(0) text="Slik!" txtAlign=5 speed=5 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
83
84
85 # LET USER KNOW THEY'RE SWITCHING BACK TO LUDAR.
86 {[ DIALOG main(0) text="Ik hoop dat het goed
87 gaat met Ludar..." txtAlign=5 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=1 ]}
88
89 {
90 [ NARRATIVE text="Je Ludar van richting laten veranderen tijdens een sprong." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
91 }
0 ##########################################
1 # Holotz's Castle story - Level 25
2 # Holotz appears
3 ##########################################
4
5
6 # This jump is just to scroll the screen up so the text is visible.
7 # A better fix would be to redesign the level so Holotz isn't so high up.
8 {[ MOVE main(0) dir=5 amount=1 ]}
9
10 {
11 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
12 [ NARRATIVE text="Holotz." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 }
14 {[ MOVE enemy(0) dir=9 amount=2 ]}
15
16 {[ MOVE main(0) dir=4 amount=2 ]
17 [ DIALOG main(0) text="Bij de kracht
18 van Hutazin!..." txtAlign=5 speed=5 size=2 align=1 r=80 g=80 b=200 subtype=0 ]}
19
20 {[ MOVE enemy(0) dir=9 amount=1 ]}
21 {[ MOVE enemy(0) dir=9 amount=1 ]}
22
23 {[ MOVE main(0) dir=6 amount=3 ]
24 [ DIALOG main(0) text="Elementaire Poort,
25 opent u!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
26
27 {[ MOVE enemy(0) dir=9 amount=1 ]}
28
29 {[ WAIT millis=3000 ]}
30
31 {[ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=5 size=1 align=1 r=80 g=80 b=200 subtype=0 ]}
32
33 {[ MOVE main(0) dir=5 amount=1 ]
34 [ DIALOG main(0) text="Het is weer
35 mislukt!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
36
37 {[ MOVE main(0) dir=4 amount=2 ]
38 [ MOVE enemy(0) dir=9 amount=1 ]
39 [ DIALOG main(0) text="Jij daar!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
40
41 {[ DIALOG main(0) text="Waar is de
42 gevangene?" txtAlign=5 speed=5 size=2 align=1 r=80 g=80 b=200 subtype=0 ]}
43
44 {[ DIALOG enemy(0) text="We hebben hem naar
45 het Labyrint van Froj gebracht,
46 zoals u zei" txtAlign=5 speed=5 size=1 align=1 r=200 g=20 b=20 subtype=0 ]}
47
48 {[ DIALOG main(0) text="Goed gedaan" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
49
50 {[ DIALOG enemy(0) text="Maar u moet wel weten" txtAlign=5 speed=5 size=1 align=1 r=200 g=20 b=20 subtype=0 ]}
51
52 {[ DIALOG enemy(0) text="dat hij schoenen
53 had, meneer" txtAlign=5 speed=5 size=1 align=1 r=200 g=20 b=20 subtype=0 ]}
54
55 {[ DIALOG main(0) text="Idioot! Wacht, I bedoel..." txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
56 [ MOVE enemy(0) dir=4 amount=1 ]}
57
58 # When Holotz yells, the demon falls back one stair step
59 {[ DIALOG main(0) text="Jij ongelovelijk
60 achterlijke domkop!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
61 [ MOVE main(0) dir=4 amount=1 ]
62 [ MOVE enemy(0) dir=4 amount=1 ]}
63
64 {[ DIALOG main(0) text="Waarom zei je
65 me dat niet!" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
66
67 {[ DIALOG enemy(0) text="Ik..." txtAlign=5 speed=5 size=1 align=0 r=200 g=20 b=20 subtype=0 ]}
68
69 {[ DIALOG main(0) text="Ze zullen ondertussen de
70 toren wel al bereikt hebben" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
71
72 {[ DIALOG main(0) text="Roep alle
73 beesten op!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
74
75 {[ DIALOG enemy(0) text="Ja, meneer" txtAlign=5 speed=5 size=2 align=0 r=200 g=20 b=20 subtype=0 ]}
76
77 {[ MOVE enemy(0) dir=7 amount=2 ]}
78
79 {[ MOVE enemy(0) dir=7 amount=2 ]
80 [ DIALOG main(0) text="We zullen die
81 Lizarnites eens
82 verassen" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 30
2 # Ybelle and Ludar meet again
3 ##########################################
4
5 {[ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
6
7 {[ MOVE main(0) dir=8 amount=6 ]
8 [ MOVE enemy(0) dir=8 amount=6 ]
9 [ MOVE enemy(1) dir=8 amount=6 ]
10 [ MOVE enemy(2) dir=8 amount=6 ]}
11
12 {[ MOVE main(0) dir=6 amount=3 ]
13 [ MOVE enemy(0) dir=4 amount=3 ]
14 [ MOVE enemy(1) dir=8 amount=4 ]
15 [ MOVE enemy(2) dir=8 amount=4 ]}
16
17 {[ MOVE main(0) dir=6 amount=4 ]
18 [ MOVE enemy(0) dir=4 amount=4 ]
19 [ MOVE enemy(1) dir=4 amount=3 ]
20 [ MOVE enemy(2) dir=6 amount=3 ]}
21
22 {[ DIALOG main(0) text="Ludar!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
23 [ DIALOG enemy(0) text="Ybelle!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]
24 [ MOVE main(0) dir=4 amount=1 ]
25 [ MOVE enemy(0) dir=6 amount=1 ]}
26
27 {[ DIALOG main(0) text="Je leeft nog!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
28 [ DIALOG enemy(0) text="Jij bent nog niet dood!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]
29 [ MOVE main(0) dir=6 amount=1 ]
30 [ MOVE enemy(0) dir=4 amount=1 ]}
31
32 {[ DIALOG main(0) text="Mooie schoenen" txtAlign=5 speed=5 size=2 align=0 r=130 g=30 b=180 subtype=0 ]}
33
34 {[ DIALOG enemy(0) text="Wij werken beter
35 als team" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
36
37 {[ DIALOG enemy(0) text="Volg me!" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
38
39 {[ DIALOG main(0) text="Hmm..." txtAlign=5 speed=5 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
40 [ MOVE main(0) dir=4 amount=1 ]}
41
42 {[ DIALOG enemy(0) text="Wat dacht je van
43 samen?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
44
45 {[ DIALOG main(0) text="Samen." txtAlign=5 speed=5 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
46 [ MOVE main(0) dir=6 amount=1 ]}
47
48 {[ MOVE main(0) dir=8 amount=3 ]
49 [ MOVE enemy(0) dir=8 amount=3 ]}
0 ##########################################
1 # Holotz's Castle story - Level 32
2 # Return to the land of Lizarno
3 ##########################################
4
5 {[ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCCredits.wav" loops=-1 waitToEnd=0 ]}
8
9 {[ DIALOG main(0) text="We zijn in Lizarno!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
10
11 {[ DIALOG enemy(0) text="We zijn thuis!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
12
13 {[ DIALOG main(0) text="Hey, kijk
14 die steen!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
15 [ MOVE main(0) dir=4 amount=2 ]}
16
17 {[ DIALOG enemy(0) text="Niet aanraken!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
18
19 {[ MOVE main(0) dir=4 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 33
2 # The end
3 ##########################################
4
5 {[ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
7
8 {
9 [ NARRATIVE text="
10 EINDE
11 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
12 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle and Ludar arrive to the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
8 }
9
10 {
11 [ NARRATIVE text="Ybelle e Ludar." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
12 }
13
14 {
15 [ DIALOG main(0) text="Que aconteceu?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=6 amount=2 ]
17 [ MOVE enemy(0) dir=6 amount=3 ]
18 }
19
20 {
21 [ DIALOG enemy(0) text="Eu disse-te
22 para não tocares
23 naquela pedra!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
24 }
25
26 {
27 [ DIALOG main(0) text="Oh, cala-te..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
28 }
29
30 {
31 [ DIALOG main(0) text="Como é que
32 eu ia saber?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
33 }
34
35 {
36 [ DIALOG main(0) text="Onde estamos?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
37 }
38
39 {
40 [ DIALOG enemy(0) text="Ah! Como queres
41 que saiba?" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
42 }
43
44 {
45 [ DIALOG enemy(0) text="Se não tocasses
46 no que não devias..." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
47 }
48
49 {
50 [ DIALOG main(0) text="Idiota..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
51 [ DIALOG enemy(0) text="Imbecil..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
52 }
53
54 {
55 [ DIALOG main(0) text="Temos de arranjar
56 uma forma de
57 voltar para casa" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
58 }
59
60 {
61 [ DIALOG main(0) text="Segue-me Ludar" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
62 }
63
64 {
65 [ DIALOG enemy(0) text="Nem sonhes...
66 metes-me sempre
67 em confusões" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
68 }
69
70 {
71 [ DIALOG enemy(0) text="Desta vez
72 faremos o que
73 eu disser" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
74 }
75
76 {
77 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
78 }
79
80 {
81 [ DIALOG main(0) text="Bom, então
82 eu vou sozinho" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
83 [ MOVE main(0) dir=6 amount=5 ]
84 }
85
86 {
87 [ DIALOG enemy(0) text="???" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
88 [ MOVE main(0) dir=8 amount=3 ]
89 }
90
91 {
92 [ MOVE enemy(0) dir=6 amount=3 ]
93 [ DIALOG enemy(0) text="ermm... Ybelle,
94 Espera por mim!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
95 }
96
97 {
98 [ MOVE main(0) dir=6 amount=3 ]
99 }
0 ##########################################
1 # Holotz's Castle story - Level 2
2 # Ybelle enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Não!" txtAlign=4 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 }
7
8 {
9 [ DIALOG main(0) text="Isso doeu!" txtAlign=4 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
10 }
11
12 {
13 [ DIALOG main(0) text="LUDAR!" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
14 }
15
16 {
17 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=1 ]
18 }
19
20 {
21 [ DIALOG main(0) text="...parece que
22 não me ouve" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Enfim..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
27 [ MOVE main(0) dir=6 amount=1 ]
28 }
29
30 {
31 [ MOVE main(0) dir=4 amount=1 ]
32 [ DIALOG main(0) text="Que diabos
33 fazem aqui todas
34 estas chaves?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
35 }
0 ##########################################
1 # Holotz's Castle story - Level 7
2 # Ludar enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="ermm... Ybelle,
6 espera" txtAlign=4 speed=2 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ MOVE main(0) dir=6 amount=2 ]
8 }
9
10 {
11 [ MOVE main(0) dir=6 amount=1 ]
12 [ DIALOG main(0) text="Oh não!" txtAlign=4 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
13 }
14
15 {
16 [ DIALOG main(0) text="Quem pôs aquele
17 buraco ali!?" txtAlign=4 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
18 }
19
20 {
21 [ DIALOG main(0) text="Ybelle!" txtAlign=5 speed=1 size=3 align=0 r=20 g=200 b=20 subtype=0 ]
22 }
23
24 {
25 [ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
26 }
27
28 {
29 [ DIALOG main(0) text="Aquele teimoso!" txtAlign=5 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
30 }
31
32 {
33 [ DIALOG main(0) text="Oh, olha" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=4 amount=1 ]
35 }
36
37 {
38 [ DIALOG main(0) text="Estas pedras
39 parecem-se com a que
40 Ybelle pegou" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
41 [ MOVE main(0) dir=4 amount=1 ]
42 }
43
44 {
45 [ DIALOG main(0) text="Que sítio é este?" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
46 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle finds the shoe maker
3 ##########################################
4
5 {[ DIALOG main(0) text="?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Que sítio é este?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
9
10 {[ NARRATIVE text="A Sapataria" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
11 [ MOVE main(0) dir=6 amount=1 ]}
12
13 {[ MOVE main(0) dir=2 amount=3 ]}
14
15 {[ MOVE main(0) dir=6 amount=2 ]}
16
17 {[ MOVE main(0) dir=9 amount=2 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]}
20
21 {[ MOVE main(0) dir=9 amount=1 ]
22 [ DIALOG enemy(0) text="Oh, um
23 visitante!" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=1 ]}
24
25 {[ MOVE main(0) dir=9 amount=2 ]}
26
27 {[ DIALOG main(0) text="Que tipo
28 estranho!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
29 [ DIALOG enemy(0) text="Que tipo
30 estranho!" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=1 ]
31 }
32
33 {[ DIALOG main(0) text="Ermm.. Olá?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
34
35 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
36
37 {[ DIALOG enemy(0) text="Não pareces..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
38
39 {[ DIALOG enemy(0) text="Ser
40 daqui..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
41
42 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
43 [ DIALOG main(0) text="Parece que
44 vai adormecer!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
45
46 {[ DIALOG enemy(0) text="És novo
47 aqui..." txtAlign=5 speed=1 size=0 align=0 r=200 g=130 b=20 subtype=0 ]}
48
49 {[ DIALOG enemy(0) text="...há..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
50
51 {[ DIALOG enemy(0) text="...pouco?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
52
53 {[ DIALOG main(0) text="Sim...
54 Novo, dizes?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
55
56 {[ DIALOG main(0) text="Oh sim,
57 claro" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
58
59 {[ DIALOG main(0) text="Quem
60 és tu?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
61
62 {[ DIALOG enemy(0) text="Eu sou..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
63
64 {[ DIALOG enemy(0) text="...O Senhor
65 dos Sapatos" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=0 ]}
66
67 {[ DIALOG enemy(0) text="Suponho..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
68
69 {[ DIALOG enemy(0) text="...que vens..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
70
71 {[ DIALOG enemy(0) text="...por uns
72 sapatos novos..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
73
74 {[ DIALOG enemy(0) text="...Certo?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
75
76 {[ DIALOG enemy(0) text="Pega..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
77 [ DIALOG main(0) text="Eu..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
78
79 {[ DIALOG enemy(0) text="...nestes" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
80
81 {[ MOVE main(0) dir=6 amount=2 ]}
82 {[ MOVE main(0) dir=4 amount=2 ]}
83
84 {[ DIALOG enemy(0) text="De certeza..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
85
86 {[ DIALOG enemy(0) text="... que te
87 moverás..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
88
89 {[ DIALOG enemy(0) text="...melhor com
90 eles..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
91
92 {[ DIALOG main(0) text="Sabes como
93 sair
94 daqui?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
95
96 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
97
98 {[ DIALOG enemy(0) text="...não" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
99
100 {[ DIALOG enemy(0) text="...só
101 Holotz..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
102
103 {[ DIALOG enemy(0) text="...sabe isso" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
104
105 {[ DIALOG main(0) text="Holotz?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
106
107 {[ DIALOG enemy(0) text="Sim..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
108
109 {[ DIALOG enemy(0) text="Ele criou..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
110
111 {[ DIALOG enemy(0) text="...este
112 castelo" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
113
114 {[ DIALOG main(0) text="Onde
115 posso
116 encontrá-lo?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
117
118 {[ DIALOG enemy(0) text="...não
119 podes" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
120
121 {[ DIALOG enemy(0) text="Ele vai-te..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
122
123 {[ DIALOG enemy(0) text="...encontrar" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
124
125 {[ DIALOG enemy(0) text="Agora
126 tenho..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
127
128 {[ DIALOG enemy(0) text="...de continuar" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
129
130 {[ DIALOG enemy(0) text="...a trabalhar" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
131
132 {[ DIALOG main(0) text="Mas...!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
133 [ DIALOG enemy(0) text="Agora
134 tenho..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
135
136 {[ DIALOG main(0) text="Deixa-o,
137 é inútil" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
138
139 {[ DIALOG main(0) text="Bom, vou-me...
140 obrigado por
141 os sapatos" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
142 [ MOVE main(0) dir=7 amount=2 ]}
143
144 {[ MOVE main(0) dir=7 amount=2 ]}
145
146 {[ DIALOG main(0) text="E agora para
147 onde vou?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
148
149 {[ DIALOG main(0) text="Oh, tanto faz" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
150 [ MOVE main(0) dir=4 amount=1 ]}
151
152 {[ MOVE main(0) dir=2 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ludar talks to the two flames
3 ##########################################
4
5 {[ DIALOG main(0) text="Oops" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_UltraSlow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Oh, outra
9 pedra!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
10 [ MOVE main(0) dir=6 amount=1 ]}
11
12 {[ NARRATIVE text="As Duas Chamas" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=4 ]
14 [ DIALOG main(0) text="Outra!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
15
16 {[ DIALOG enemy(0) text="Alto!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
17
18 {[ DIALOG main(0) text="???" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
19 [ MOVE main(0) dir=4 amount=1 ]}
20
21 {[ DIALOG main(0) text="Está alguém
22 aqui?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
23 [ MOVE main(0) dir=6 amount=4 ]}
24
25 {[ DIALOG enemy(0) text="Eu disse
26 alto!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
27
28 {[ MOVE main(0) dir=4 amount=4 ]
29 [ DIALOG main(0) text="Oh, uma chama
30 oradora!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]}
31
32 {[ DIALOG enemy(0) text="Não sou uma
33 chama oradora!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]
34 [ DIALOG main(0) text="¡Oh!" txtAlign=5 speed=4 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
35 [ MOVE main(0) dir=6 amount=2 ]}
36
37 {[ DIALOG enemy(0) text="Sou uma
38 chama faladora!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
39
40 {[ DIALOG main(0) text="Como soubeste
41 o que pensava?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(0) text="Eu sei
44 tudo!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
45
46 {[ DIALOG enemy(1) text="Ahem..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="Bom, quase
49 tudo" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
50
51 {[ DIALOG enemy(1) text="Ela lê a
52 mente..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
53
54 {[ DIALOG enemy(1) text="Eu leio..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
55
56 {[ DIALOG enemy(1) text="...Livros" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
57
58 {[ DIALOG enemy(1) text="Ah, ah, ah!" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]
59 [ DIALOG enemy(0) text="Uh, uh, uh!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]
60 [ DIALOG main(0) text="?!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
61
62 {[ DIALOG enemy(1) text="Como
63 entraste aqui?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="Eu sei..." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
66
67 {[ DIALOG main(0) text="Oh, ela vai ler
68 a minha mente!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]}
69
70 {[ DIALOG enemy(0) text="Através
71 do portal
72 místico!!" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
73
74 {[ DIALOG enemy(1) text="Ah, ah, ah!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
75 [ DIALOG enemy(0) text="Uh, uh, uh!" txtAlign=5 speed=1 size=3 align=0 r=20 g=20 b=180 subtype=0 ]
76 [ DIALOG main(0) text="hmpfxs#@!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
77 [ MOVE main(0) dir=6 amount=4 ]}
78
79 {[ DIALOG enemy(1) text="Espera, não
80 te vás" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
81 [ MOVE main(0) dir=4 amount=5 ]}
82
83 {[ DIALOG main(0) text="Não tenho
84 tempo para
85 piadas!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
86 [ MOVE main(0) dir=6 amount=2 ]}
87
88 {[ DIALOG enemy(0) text="Que
89 precisas?" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]
90 [ MOVE main(0) dir=4 amount=3 ]}
91
92 {[ DIALOG main(0) text="Tenho que
93 encontrar Ybelle" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
94
95 {[ DIALOG main(0) text="Temos de
96 regressar à
97 Terra de
98 Lizarno" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
99
100 {[ DIALOG enemy(0) text="Hmmm...um Lizarnita,
101 que interessante" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=1 ]}
102
103 {[ DIALOG enemy(1) text="Daqui em diante
104 o castelo
105 torna-se" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
106
107 {[ DIALOG enemy(1) text="mais perigoso" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
108
109 {[ DIALOG enemy(1) text="mas tu não
110 tens suficiente
111 poder mágico" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
112
113 {[ DIALOG enemy(1) text="para chegar ao
114 nível superior" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
115
116 {[ DIALOG enemy(0) text="Sim, o que
117 precisas é de..." txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
118
119 {[ DIALOG enemy(1) text="Uns
120 sapatos!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
121 [ DIALOG enemy(0) text="Uns
122 sapatos!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
123
124 {[ DIALOG main(0) text="Oh, deixem-se
125 de piadas!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
126 [ MOVE main(0) dir=4 amount=2 ]}
127
128 {[ DIALOG enemy(0) text="Mas só os
129 pode dar-te" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
130
131 {[ DIALOG enemy(0) text="O Senhor dos
132 Sapatos" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
133
134 {[ DIALOG main(0) text="Não existe outra
135 forma de conseguir
136 uns sapatos?" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
137 [ MOVE main(0) dir=6 amount=2 ]}
138
139 {[ DIALOG enemy(1) text="Sim, podes
140 consegui-los na" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=60 subtype=0 ]}
141
142 {[ DIALOG enemy(1) text="Sapataria!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=60 subtype=0 ]
143 [ DIALOG enemy(0) text="Sapataria!!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]}
144
145 {[ DIALOG enemy(1) text="Ah, ah, ah!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
146 [ DIALOG enemy(0) text="Uh, uh, uh!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]
147 [ DIALOG main(0) text="Isto é
148 demais!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
149 [ MOVE main(0) dir=6 amount=4 ]}
150
151 {[ DIALOG enemy(1) text="Espera" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
152 [ MOVE main(0) dir=4 amount=2 ]}
153
154 {[ DIALOG enemy(1) text="Podes conseguir
155 uns sapatos" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
156
157 {[ DIALOG enemy(1) text="Por trás deste
158 portal místico" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
159
160 {[ DIALOG enemy(0) text="Mas deves
161 saber" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
162
163 {[ DIALOG enemy(0) text="que ninguém
164 saiu com
165 vida dali" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
166
167 {[ DIALOG main(0) text="Oh!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
168 [ MOVE main(0) dir=6 amount=2 ]}
169
170 {[ DIALOG main(0) text="Hmm... Bom,
171 tenho que tentar" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
172 [ MOVE main(0) dir=4 amount=2 ]}
173
174 {[ DIALOG main(0) text="Oh!, mas não
175 consigo abrir
176 o portal" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
177 [ MOVE main(0) dir=4 amount=2 ]}
178
179 {[ DIALOG main(0) text="Aquela pedra está
180 demasiado alta" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
181
182 {[ DIALOG enemy(1) text="Bom, então
183 usa esta escada" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 19
2 # Ybelle is captured
3 ##########################################
4
5 {[ DIALOG main(0) text="AAAH!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_Fast.wav" loops=0 waitToEnd=0 ]}
7
8 {[ MOVE enemy(0) dir=8 amount=4 ]
9 [ MOVE enemy(1) dir=8 amount=4 ]
10 [ MOVE enemy(2) dir=4 amount=2 ]
11 [ MOVE enemy(3) dir=6 amount=2 ]
12 [ MOVE enemy(4) dir=4 amount=5 ]
13 [ MOVE enemy(5) dir=6 amount=5 ]
14 [ DIALOG main(0) text="Oh, oh" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
15 [ DIALOG enemy(2) text="!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=1 ]
16 [ DIALOG enemy(3) text="!" txtAlign=5 speed=1 size=2 align=0 r=220 g=20 b=20 subtype=1 ]}
17
18 {[ NARRATIVE text="
19 CONTINUA...
20 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
21 [ DIALOG main(0) text="??!" txtAlign=5 speed=3 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=5 amount=1 ]}
23
24 {[ DIALOG main(0) text="Eeeh!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
25 [ MOVE main(0) dir=5 amount=2 ]}
26
27 {[ DIALOG main(0) text="Não me deixem aqui!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
28 [ MOVE main(0) dir=5 amount=2 ]}
29
30 {[ WAIT millis=3000]}
0 ##########################################
1 # Holotz's Castle story - Level 20
2 # Ybelle is captured (continued)
3 ##########################################
4
5 {[ MOVE enemy(0) dir=8 amount=0 ]
6 [ MOVE enemy(1) dir=8 amount=0 ]
7 [ MOVE enemy(2) dir=4 amount=0 ]
8 [ MOVE enemy(3) dir=6 amount=0 ]
9 [ MOVE enemy(4) dir=4 amount=0 ]
10 [ MOVE enemy(5) dir=6 amount=0 ]}
11
12 {[ WAIT millis=1000]}
13
14 {[ DIALOG main(0) text="Alto, não
15 te mexas!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=4 amount=1 ]}
17
18 {[ DIALOG enemy(0) text="He he" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]
19 [ DIALOG enemy(1) text="Hmmm" txtAlign=5 speed=5 size=3 align=0 r=200 g=20 b=20 subtype=0 ]}
20
21 {[ DIALOG main(0) text="Advirto-vos,
22 sou perigoso!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
23 [ MOVE main(0) dir=6 amount=2 ]}
24
25 {[ MOVE enemy(1) dir=4 amount=3 ]
26 [ DIALOG enemy(1) text="Olha..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
27
28 {[ MOVE enemy(1) dir=4 amount=1 ]
29 [ DIALOG enemy(5) text="O quê?" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
30
31 {[ DIALOG enemy(1) text="Ele tem sapatos" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
32
33 {[ DIALOG enemy(5) text="Hmmm...
34 Holotz não
35 vai gostar" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
36
37 {[ DIALOG main(0) text="Que queres?" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
38
39 {[ MOVE enemy(5) dir=6 amount=4 ]
40 [ MOVE main(0) dir=6 amount=1 ]
41 [ DIALOG enemy(5) text="A questão é..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(5) text="Que fazes
44 tu aqui?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
45
46 {[ DIALOG main(0) text="Peguei numa
47 pedra e..." txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
48
49 {[ DIALOG enemy(5) text="E abriu-se um
50 portal, certo?." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
51
52 {[ DIALOG main(0) text="Sim, exacto!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
53
54 {[ DIALOG enemy(5) text="Parece que
55 as experiências
56 de Holotz" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
57
58 {[ DIALOG enemy(5) text="Não tiveram
59 muito sucesso" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
60
61 {[ DIALOG enemy(5) text="Surpreende-me
62 que tenham chegado
63 tão longe..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
64
65 {[ DIALOG enemy(4) text="Que fazemos
66 com ele?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
67
68 {[ DIALOG enemy(5) text="Tal como
69 disse Holotz..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
70
71 {[ DIALOG enemy(5) text="...vamos levá-lo
72 ao labirinto
73 de Froj" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
74
75 {[ DIALOG enemy(5) text="Ali ficará
76 até que Holotz
77 decida o que fazer
78 com ele..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
79
80 {[ DIALOG enemy(5) text="...se os 4
81 irmãos loucos não
82 o encontrarem antes" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
83
84 {[ DIALOG enemy(1) text="Ah, ah!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=20 subtype=0 ]
85 [ DIALOG enemy(2) text="Uh, uh, uh!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 25
2 # Holotz appears
3 ##########################################
4
5 {
6 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
7 [ NARRATIVE text="Holotz." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
8 }
9
10 {[ MOVE enemy(0) dir=9 amount=2 ]}
11
12 {[ MOVE main(0) dir=4 amount=2 ]
13 [ DIALOG main(0) text="Pelo poder
14 de Hutazin!..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
15
16 {[ MOVE enemy(0) dir=9 amount=1 ]}
17 {[ MOVE enemy(0) dir=9 amount=1 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]
20 [ DIALOG main(0) text="Portal elemental,
21 abre-te!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
22
23 {[ MOVE enemy(0) dir=9 amount=1 ]}
24
25 {[ WAIT millis=3000 ]}
26
27 {[ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
28
29 {[ MOVE main(0) dir=5 amount=1 ]
30 [ DIALOG main(0) text="Falhou
31 outra vez!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
32
33 {[ MOVE main(0) dir=4 amount=2 ]
34 [ MOVE enemy(0) dir=9 amount=1 ]
35 [ DIALOG main(0) text="Tu!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
36
37 {[ DIALOG main(0) text="Onde está
38 o lizarnita?" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="Levamo-lo para
41 o labirinto de
42 Froj como nos disseste" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
43
44 {[ DIALOG main(0) text="Bem feito" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
45
46 {[ DIALOG enemy(0) text="Mas deves saber" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="que calçava
49 sapatos, senhor" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
50
51 {[ DIALOG main(0) text="Estúpido!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
52
53 {[ DIALOG main(0) text="Estúpido!
54 Porque que não
55 me disseste!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
56
57 {[ DIALOG enemy(0) text="Eu..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
58
59 {[ DIALOG main(0) text="A este passo devem
60 ter chegado à torre" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
61
62 {[ DIALOG main(0) text="Reúne todas
63 as bestas!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="Sim, senhor" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
66
67 {[ MOVE enemy(0) dir=7 amount=2 ]}
68
69 {[ MOVE enemy(0) dir=7 amount=3 ]
70 [ DIALOG main(0) text="Vamos fazer uma
71 supresa a esses
72 lizarnitas" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 30
2 # Ybelle and Ludar met again
3 ##########################################
4
5 {[ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
6
7 {[ MOVE main(0) dir=8 amount=6 ]
8 [ MOVE enemy(0) dir=8 amount=6 ]
9 [ MOVE enemy(1) dir=8 amount=6 ]
10 [ MOVE enemy(2) dir=8 amount=6 ]}
11
12 {[ MOVE main(0) dir=6 amount=3 ]
13 [ MOVE enemy(0) dir=4 amount=3 ]
14 [ MOVE enemy(1) dir=8 amount=4 ]
15 [ MOVE enemy(2) dir=8 amount=4 ]}
16
17 {[ MOVE main(0) dir=6 amount=4 ]
18 [ MOVE enemy(0) dir=4 amount=4 ]
19 [ MOVE enemy(1) dir=4 amount=3 ]
20 [ MOVE enemy(2) dir=6 amount=3 ]}
21
22 {[ DIALOG main(0) text="Ludar!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
23 [ DIALOG enemy(0) text="Ybelle!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
24
25 {[ DIALOG main(0) text="Estás vivo!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
26 [ DIALOG enemy(0) text="Não estás morto!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
27
28 {[ DIALOG enemy(0) text="Bem, agora podemos
29 continuar juntos" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]}
30
31 {[ DIALOG enemy(0) text="Pela escada,
32 segue-me!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
33
34 {[ MOVE main(0) dir=8 amount=3 ]
35 [ MOVE enemy(0) dir=8 amount=3 ]}
0 ##########################################
1 # Holotz's Castle story - Level 32
2 # Return to the land of Lizarno
3 ##########################################
4
5 {[ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCCredits.wav" loops=-1 waitToEnd=0 ]}
8
9 {[ DIALOG main(0) text="É Lizarno!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
10
11 {[ DIALOG enemy(0) text="Voltamos!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
12
13 {[ DIALOG main(0) text="Eh, olha
14 essa pedra!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
15 [ MOVE main(0) dir=4 amount=2 ]}
16
17 {[ DIALOG enemy(0) text="Não lhe toques!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
18
19 {[ MOVE main(0) dir=4 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 33
2 # The end
3 ##########################################
4
5 {[ DIALOG enemy(0) text="¡Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ DIALOG main(0) text="¡Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
7
8 {
9 [ NARRATIVE text="
10 FIM
11 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
12 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle and Ludar arrive to the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Aaa!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Ааа!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
8 }
9
10 {
11 [ NARRATIVE text="Ивонна и Людар." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
12 }
13
14 {
15 [ DIALOG main(0) text="Что случилось?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=6 amount=2 ]
17 [ MOVE enemy(0) dir=6 amount=3 ]
18 }
19
20 {
21 [ DIALOG enemy(0) text="Я же тебе говорил
22 не трогать тот
23 странный камень!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
24 }
25
26 {
27 [ DIALOG main(0) text="Заткнись..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
28 }
29
30 {
31 [ DIALOG main(0) text="Откуда мне
32 было знать?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
33 }
34
35 {
36 [ DIALOG main(0) text="А где мы?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
37 }
38
39 {
40 [ DIALOG enemy(0) text="Ха-ха! Откуда
41 ей было знать?" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
42 }
43
44 {
45 [ DIALOG enemy(0) text="Если-б ты не
46 влезла, то ничего бы
47 не случилось..." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
48 }
49
50 {
51 [ DIALOG main(0) text="Придурок..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
52 [ DIALOG enemy(0) text="Тупица..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
53 }
54
55 {
56 [ DIALOG main(0) text="Придётся
57 искать дорогу
58 домой" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
59 }
60
61 {
62 [ DIALOG main(0) text="Пошли за мной, Людар" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
63 }
64
65 {
66 [ DIALOG enemy(0) text="Ну уж нет... ты всегда
67 ввязываешся во всякие
68 неприятности" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
69 }
70
71 {
72 [ DIALOG enemy(0) text="Теперь ты слушай
73 меня!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
74 }
75
76 {
77 [ DIALOG main(0) text="Что на него нашло?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
78 }
79
80 {
81 [ DIALOG main(0) text="Ну и ладно! Обойдусь
82 без тебя." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
83 [ MOVE main(0) dir=6 amount=5 ]
84 }
85
86 {
87 [ DIALOG enemy(0) text="???" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
88 [ MOVE main(0) dir=8 amount=3 ]
89 }
90
91 {
92 [ MOVE enemy(0) dir=6 amount=3 ]
93 [ DIALOG enemy(0) text="э-ээ... Ивонна,
94 Подожди!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
95 }
96
97 {
98 [ MOVE main(0) dir=6 amount=3 ]
99 }
0 ##########################################
1 # Holotz's Castle story - Level 2
2 # Ybelle enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Ой!" txtAlign=4 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 }
7
8 {
9 [ DIALOG main(0) text="Больно!" txtAlign=4 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
10 }
11
12 {
13 [ DIALOG main(0) text="ЛЮДАР!" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
14 }
15
16 {
17 [ DIALOG main(0) text="Гм..." txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=1 ]
18 }
19
20 {
21 [ DIALOG main(0) text="...похоже,
22 не слышит" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Ну хорошо..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
27 [ MOVE main(0) dir=6 amount=1 ]
28 }
29
30 {
31 [ MOVE main(0) dir=4 amount=1 ]
32 [ DIALOG main(0) text="Для чего
33 могут быть все
34 эти ключи?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]}
0 ##########################################
1 # Holotz's Castle story - Level 7
2 # Ludar enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="... Ивонна!
6 Подожди!" txtAlign=4 speed=2 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ MOVE main(0) dir=6 amount=2 ]
8 }
9
10 {
11 [ MOVE main(0) dir=6 amount=1 ]
12 [ DIALOG main(0) text="Чёрт!" txtAlign=4 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
13 }
14
15 {
16 [ DIALOG main(0) text="Ну кто выкопал
17 эту яму!" txtAlign=4 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
18 }
19
20 {
21 [ DIALOG main(0) text="Ивонна!" txtAlign=5 speed=1 size=3 align=0 r=20 g=200 b=20 subtype=0 ]
22 }
23
24 {
25 [ DIALOG main(0) text="У-уу..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
26 }
27
28 {
29 [ DIALOG main(0) text="Осёл!" txtAlign=5 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
30 }
31
32 {
33 [ DIALOG main(0) text="Ого!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=4 amount=1 ]
35 }
36
37 {
38 [ DIALOG main(0) text="Эти камни
39 похожи на тот,
40 что взяла Ивонна" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
41 [ MOVE main(0) dir=4 amount=1 ]
42 }
43
44 {
45 [ DIALOG main(0) text="Что это за место?" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
46 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle finds the shoe maker
3 ##########################################
4
5 {[ DIALOG main(0) text="?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Куда я попала?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
9
10 {[ NARRATIVE text="Сапожник" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
11 [ MOVE main(0) dir=6 amount=1 ]}
12
13 {[ MOVE main(0) dir=2 amount=3 ]}
14
15 {[ MOVE main(0) dir=6 amount=2 ]}
16
17 {[ MOVE main(0) dir=9 amount=2 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]}
20
21 {[ MOVE main(0) dir=9 amount=1 ]
22 [ DIALOG enemy(0) text="О!
23 Посетитель!" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=1 ]}
24
25 {[ MOVE main(0) dir=9 amount=2 ]}
26
27 {[ DIALOG main(0) text="Какой
28 странный тип!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
29 [ DIALOG enemy(0) text="Таких гостей у меня
30 ещё не бывало!" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=1 ]
31 }
32
33 {[ DIALOG main(0) text="... Здравствуйте?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
34
35 {[ DIALOG enemy(0) text="Ммм..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
36
37 {[ DIALOG enemy(0) text="Вы, наверно,
38 прибыли..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="...
41 издалека" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(0) text="Гм..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
44 [ DIALOG main(0) text="Кажется
45 он собирается
46 заснуть!!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
47
48 {[ DIALOG enemy(0) text="Вы вошли
49 в новый..." txtAlign=5 speed=1 size=0 align=0 r=200 g=130 b=20 subtype=0 ]}
50
51 {[ DIALOG enemy(0) text="...совсем..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
52
53 {[ DIALOG enemy(0) text="...недавно?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
54
55 {[ DIALOG main(0) text="...
56 Вы говорите новый?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
57
58 {[ DIALOG main(0) text="О да,
59 конечно" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
60
61 {[ DIALOG main(0) text="Кто вы?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
62
63 {[ DIALOG enemy(0) text="Я..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="...Господин
66 сапог и туфель!" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=0 ]}
67
68 {[ DIALOG enemy(0) text="Полагаю,..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
69
70 {[ DIALOG enemy(0) text="...вы
71 пришли..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
72
73 {[ DIALOG enemy(0) text="...за новой
74 парой..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
75
76 {[ DIALOG enemy(0) text="...так, ведь?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
77
78 {[ DIALOG enemy(0) text="Возьмите..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
79 [ DIALOG main(0) text="Я..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
80
81 {[ DIALOG enemy(0) text="...эти" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
82
83 {[ MOVE main(0) dir=6 amount=2 ]}
84 {[ MOVE main(0) dir=4 amount=2 ]}
85
86 {[ DIALOG enemy(0) text="Конечно..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
87
88 {[ DIALOG enemy(0) text="... в них
89 будет..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
90
91 {[ DIALOG enemy(0) text="...легче
92 бегать..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
93
94 {[ DIALOG main(0) text="Как
95 отсюда
96 выбраться?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
97
98 {[ DIALOG enemy(0) text="Гм..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
99
100 {[ DIALOG enemy(0) text="...нет" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
101
102 {[ DIALOG enemy(0) text="...только
103 Холоц..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
104
105 {[ DIALOG enemy(0) text="...знает" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
106
107 {[ DIALOG main(0) text="Холоц?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
108
109 {[ DIALOG enemy(0) text="Да..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
110
111 {[ DIALOG enemy(0) text="Он построил..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
112
113 {[ DIALOG enemy(0) text="...весь
114 этот замок" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
115
116 {[ DIALOG main(0) text="А где его
117 найти?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
118
119 {[ DIALOG enemy(0) text="...это
120 невозможно" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
121
122 {[ DIALOG enemy(0) text="Он..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
123
124 {[ DIALOG enemy(0) text="...сам найдёт тебя" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
125
126 {[ DIALOG enemy(0) text="А теперь
127 пора мне..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
128
129 {[ DIALOG enemy(0) text="...вернуться" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
130
131 {[ DIALOG enemy(0) text="...к работе" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
132
133 {[ DIALOG main(0) text="Но,... но!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
134 [ DIALOG enemy(0) text="Надо
135 работать..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
136
137 {[ DIALOG main(0) text="Бесполезно" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
138
139 {[ DIALOG main(0) text="Ну ладно, я пойду...
140 Спасибо за
141 сапоги!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
142 [ MOVE main(0) dir=7 amount=2 ]}
143
144 {[ MOVE main(0) dir=7 amount=2 ]}
145
146 {[ DIALOG main(0) text="Куда же мне
147 идти теперь?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
148
149 {[ DIALOG main(0) text="Да какая разница" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
150 [ MOVE main(0) dir=4 amount=1 ]}
151
152 {[ MOVE main(0) dir=2 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ludar talks to the two flames
3 ##########################################
4
5 {[ DIALOG main(0) text="Ой!" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_UltraSlow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="О! Ещё один
9 камень!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
10 [ MOVE main(0) dir=6 amount=1 ]}
11
12 {[ NARRATIVE text="Два Огня" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=4 ]
14 [ DIALOG main(0) text="Ещё один!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
15
16 {[ DIALOG enemy(0) text="Стой!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
17
18 {[ DIALOG main(0) text="???" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
19 [ MOVE main(0) dir=4 amount=1 ]}
20
21 {[ DIALOG main(0) text="Кто там?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
22 [ MOVE main(0) dir=6 amount=4 ]}
23
24 {[ DIALOG enemy(0) text="Я сказал
25 СТОЙ!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
26
27 {[ MOVE main(0) dir=4 amount=4 ]
28 [ DIALOG main(0) text="Ого, говорящий
29 огонёк!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]}
30
31 {[ DIALOG enemy(0) text="Я не говорящий
32 огонёк!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]
33 [ DIALOG main(0) text="Ой!" txtAlign=5 speed=4 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=6 amount=2 ]}
35
36 {[ DIALOG enemy(0) text="Я глаголящее
37 пламя!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
38
39 {[ DIALOG main(0) text="Откуда
40 ты знаешь, что
41 я думаю?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(0) text="Я знаю
44 всё!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
45
46 {[ DIALOG enemy(1) text="Хм..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="Ну или почти
49 всё" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
50
51 {[ DIALOG enemy(1) text="Он
52 читает мысли..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
53
54 {[ DIALOG enemy(1) text="и книги..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
55
56 {[ DIALOG enemy(1) text="...книги" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
57
58 {[ DIALOG enemy(1) text="Буль, буль, буль!" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]
59 [ DIALOG enemy(0) text="Муль, муль, муль!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]
60 [ DIALOG main(0) text="??!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
61
62 {[ DIALOG enemy(1) text="Как ты сюда
63 попал?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="Я не знаю..." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
66
67 {[ DIALOG main(0) text="Оно собирается
68 прочесть мои мысли!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]}
69
70 {[ DIALOG enemy(0) text="Через
71 волшебные
72 врата!!" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
73
74 {[ DIALOG enemy(1) text="Буль, буль, буль!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
75 [ DIALOG enemy(0) text="Муль, муль, муль!" txtAlign=5 speed=1 size=3 align=0 r=20 g=20 b=180 subtype=0 ]
76 [ DIALOG main(0) text="Чёрт побери!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
77 [ MOVE main(0) dir=6 amount=4 ]}
78
79 {[ DIALOG enemy(1) text="Погоди, не
80 уходи" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
81 [ MOVE main(0) dir=4 amount=5 ]}
82
83 {[ DIALOG main(0) text="Мне
84 некогда
85 шутить!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
86 [ MOVE main(0) dir=6 amount=2 ]}
87
88 {[ DIALOG enemy(0) text="Что тебе
89 надо?" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]
90 [ MOVE main(0) dir=4 amount=3 ]}
91
92 {[ DIALOG main(0) text="Я хочу найти
93 Ивонну" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
94
95 {[ DIALOG main(0) text="Мы должны
96 вернуться в
97 страну
98 Лизарнию" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
99
100 {[ DIALOG enemy(0) text="А... лизарнийцы,...
101 как интересно" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=1 ]}
102
103 {[ DIALOG enemy(1) text="Теперь
104 замок
105 станет" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
106
107 {[ DIALOG enemy(1) text="опаснее" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
108
109 {[ DIALOG enemy(1) text="а у тебя не
110 хватит волшебной
111 силы" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
112
113 {[ DIALOG enemy(1) text="чтобы добраться
114 до самого верха" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
115
116 {[ DIALOG enemy(0) text="Точно! Тебе
117 нужна..." txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
118
119 {[ DIALOG enemy(1) text="пара
120 сапог!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
121 [ DIALOG enemy(0) text="пара
122 сапог!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
123
124 {[ DIALOG main(0) text="Хватит
125 смеяться!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
126 [ MOVE main(0) dir=4 amount=2 ]}
127
128 {[ DIALOG enemy(0) text="Но получить их ты
129 можешь только от" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
130
131 {[ DIALOG enemy(0) text="господина
132 сапожника" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
133
134 {[ DIALOG main(0) text="А есть ещё какой-нибудь
135 способ раздобыть эти
136 ваши сапоги?" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
137 [ MOVE main(0) dir=6 amount=2 ]}
138
139 {[ DIALOG enemy(1) text="Есть. Их ещё
140 можно достать в" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=60 subtype=0 ]}
141
142 {[ DIALOG enemy(1) text="Лавке!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=60 subtype=0 ]
143 [ DIALOG enemy(0) text="Лавке!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]}
144
145 {[ DIALOG enemy(1) text="Буль, буль, буль!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
146 [ DIALOG enemy(0) text="Муль, муль, муль!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]
147 [ DIALOG main(0) text="Это уже совершенно
148 невыносимо!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
149 [ MOVE main(0) dir=6 amount=4 ]}
150
151 {[ DIALOG enemy(1) text="Подожди" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
152 [ MOVE main(0) dir=4 amount=2 ]}
153
154 {[ DIALOG enemy(1) text="Ты можешь
155 найти сапоги" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
156
157 {[ DIALOG enemy(1) text="в комнате
158 за этими
159 волшебными вратамиl" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
160
161 {[ DIALOG enemy(0) text="Но знай," txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
162
163 {[ DIALOG enemy(0) text="что ещё никто
164 не уходил оттуда живым" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
165
166 {[ DIALOG main(0) text="Ого!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
167 [ MOVE main(0) dir=6 amount=2 ]}
168
169 {[ DIALOG main(0) text="Гм... Я всё-равно
170 должен попробовать" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
171 [ MOVE main(0) dir=4 amount=2 ]}
172
173 {[ DIALOG main(0) text="Но я же
174 не могу открыть
175 врата" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
176 [ MOVE main(0) dir=4 amount=2 ]}
177
178 {[ DIALOG main(0) text="Этот камень
179 слишком высоко!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
180
181 {[ DIALOG enemy(1) text="Хорошо, возьми
182 эту лестницу." txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 19
2 # Ybelle is captured
3 ##########################################
4
5 {[ DIALOG main(0) text="Ааа!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_Fast.wav" loops=0 waitToEnd=0 ]}
7
8 {[ MOVE enemy(0) dir=8 amount=4 ]
9 [ MOVE enemy(1) dir=8 amount=4 ]
10 [ MOVE enemy(2) dir=4 amount=2 ]
11 [ MOVE enemy(3) dir=6 amount=2 ]
12 [ MOVE enemy(4) dir=4 amount=5 ]
13 [ MOVE enemy(5) dir=6 amount=5 ]
14 [ DIALOG main(0) text="Ой, ой" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
15 [ DIALOG enemy(2) text="!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=1 ]
16 [ DIALOG enemy(3) text="!" txtAlign=5 speed=1 size=2 align=0 r=220 g=20 b=20 subtype=1 ]}
17
18 {[ NARRATIVE text="
19 ПРОДОЛЖЕНИЕ СЛЕДУЕТ...
20 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
21 [ DIALOG main(0) text="??!" txtAlign=5 speed=3 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=5 amount=1 ]}
23
24 {[ DIALOG main(0) text="Ааа!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
25 [ MOVE main(0) dir=5 amount=2 ]}
26
27 {[ DIALOG main(0) text="Не бросай меня!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
28 [ MOVE main(0) dir=5 amount=2 ]}
29
30 {[ WAIT millis=3000]}
0 ##########################################
1 # Holotz's Castle story - Level 20
2 # Ybelle is captured (continued)
3 ##########################################
4
5 {[ MOVE enemy(0) dir=8 amount=0 ]
6 [ MOVE enemy(1) dir=8 amount=0 ]
7 [ MOVE enemy(2) dir=4 amount=0 ]
8 [ MOVE enemy(3) dir=6 amount=0 ]
9 [ MOVE enemy(4) dir=4 amount=0 ]
10 [ MOVE enemy(5) dir=6 amount=0 ]}
11
12 {[ WAIT millis=1000]}
13
14 {[ DIALOG main(0) text="Стоять!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
15 [ MOVE main(0) dir=4 amount=1 ]}
16
17 {[ DIALOG enemy(0) text="Угх Угх" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]
18 [ DIALOG enemy(1) text="Мммм" txtAlign=5 speed=5 size=3 align=0 r=200 g=20 b=20 subtype=0 ]}
19
20 {[ DIALOG main(0) text="Предупреждаю,
21 я опасна!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=6 amount=2 ]}
23
24 {[ MOVE enemy(1) dir=4 amount=3 ]
25 [ DIALOG enemy(1) text="Гляди..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
26
27 {[ MOVE enemy(1) dir=4 amount=1 ]
28 [ DIALOG enemy(5) text="Чего?" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
29
30 {[ DIALOG enemy(1) text="У неё сапоги" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
31
32 {[ DIALOG enemy(5) text="Гм...
33 Холоцу это бы
34 не понравилось" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
35
36 {[ DIALOG main(0) text="Чего вы хотите?" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
37
38 {[ MOVE enemy(5) dir=6 amount=4 ]
39 [ MOVE main(0) dir=6 amount=1 ]
40 [ DIALOG enemy(5) text="Отвечай!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
41
42 {[ DIALOG enemy(5) text="Что ты тут
43 делаешь?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
44
45 {[ DIALOG main(0) text="Я взяла
46 камень и..." txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
47
48 {[ DIALOG enemy(5) text="И открылись волшебные
49 врата, так?." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
50
51 {[ DIALOG main(0) text="Да, точно!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
52
53 {[ DIALOG enemy(5) text="Похоже, что
54 очередной опыт Холоца" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
55
56 {[ DIALOG enemy(5) text="не удался" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
57
58 {[ DIALOG enemy(5) text="Удивительно
59 как ты сюда
60 пробралась..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
61
62 {[ DIALOG enemy(4) text="Что будем с
63 ней делать?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
64
65 {[ DIALOG enemy(5) text="Как сказал Лорд
66 Холоц..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
67
68 {[ DIALOG enemy(5) text="...отправим в
69 лабиринт
70 Фроя" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
71
72 {[ DIALOG enemy(5) text="Посидит там,
73 пока Хозяин не решит,
74 что с ней сделать..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
75
76 {[ DIALOG enemy(5) text="...если четыре
77 сумасшедших брата
78 не найдут её раньше" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
79
80 {[ DIALOG enemy(1) text="Ха-ха-ха!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=20 subtype=0 ]
81 [ DIALOG enemy(2) text="Хи-хи-хи-хи!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 25
2 # Holotz appears
3 ##########################################
4
5 {
6 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
7 [ NARRATIVE text="Лорд Холоц" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
8 }
9
10 {[ MOVE enemy(0) dir=9 amount=2 ]}
11
12 {[ MOVE main(0) dir=4 amount=2 ]
13 [ DIALOG main(0) text="Именем
14 Хутазина!..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
15
16 {[ MOVE enemy(0) dir=9 amount=1 ]}
17 {[ MOVE enemy(0) dir=9 amount=1 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]
20 [ DIALOG main(0) text="Врата стихий,
21 отворитесь!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
22
23 {[ MOVE enemy(0) dir=9 amount=1 ]}
24
25 {[ WAIT millis=3000 ]}
26
27 {[ DIALOG main(0) text="..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
28
29 {[ MOVE main(0) dir=5 amount=1 ]
30 [ DIALOG main(0) text="Опять не
31 сработало!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
32
33 {[ MOVE main(0) dir=4 amount=2 ]
34 [ MOVE enemy(0) dir=9 amount=1 ]
35 [ DIALOG main(0) text="Ты!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
36
37 {[ DIALOG main(0) text="Где
38 лизарнитка?" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="Мы её отправили
41 в лабиринт Фроя,
42 как вы приказали" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
43
44 {[ DIALOG main(0) text="Отлично" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
45
46 {[ DIALOG enemy(0) text="Но знайте, господин," txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="что у неё были
49 сапоги" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
50
51 {[ DIALOG main(0) text="Идиот!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
52
53 {[ DIALOG main(0) text="Подлец!
54 Как ты посмел
55 скрывать это!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
56
57 {[ DIALOG enemy(0) text="Я..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
58
59 {[ DIALOG main(0) text="С такой прытью она уже
60 могла достичь башни!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
61
62 {[ DIALOG main(0) text="Выпустить всех
63 чудовищ!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="Слушаю и повинуюсь" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
66
67 {[ MOVE enemy(0) dir=7 amount=2 ]}
68
69 {[ MOVE enemy(0) dir=7 amount=3 ]
70 [ DIALOG main(0) text="Сейчас мы устроим
71 этим лизарнийцам
72 сюрприз" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 30
2 # Ybelle and Ludar met again
3 ##########################################
4
5 {[ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
6
7 {[ MOVE main(0) dir=8 amount=6 ]
8 [ MOVE enemy(0) dir=8 amount=6 ]
9 [ MOVE enemy(1) dir=8 amount=6 ]
10 [ MOVE enemy(2) dir=8 amount=6 ]}
11
12 {[ MOVE main(0) dir=6 amount=3 ]
13 [ MOVE enemy(0) dir=4 amount=3 ]
14 [ MOVE enemy(1) dir=8 amount=4 ]
15 [ MOVE enemy(2) dir=8 amount=4 ]}
16
17 {[ MOVE main(0) dir=6 amount=4 ]
18 [ MOVE enemy(0) dir=4 amount=4 ]
19 [ MOVE enemy(1) dir=4 amount=3 ]
20 [ MOVE enemy(2) dir=6 amount=3 ]}
21
22 {[ DIALOG main(0) text="Людар!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
23 [ DIALOG enemy(0) text="Ивонна!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
24
25 {[ DIALOG main(0) text="Ты жива!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
26 [ DIALOG enemy(0) text="И ты цел!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
27
28 {[ DIALOG enemy(0) text="Теперь мы
29 будем вместе!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]}
30
31 {[ DIALOG enemy(0) text="К лестнице,
32 давай за мной!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
33
34 {[ MOVE main(0) dir=8 amount=3 ]
35 [ MOVE enemy(0) dir=8 amount=3 ]}
0 ##########################################
1 # Holotz's Castle story - Level 32
2 # Return to the land of Lizarno
3 ##########################################
4
5 {[ DIALOG main(0) text="А-аа!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Ааа!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCCredits.wav" loops=-1 waitToEnd=0 ]}
8
9 {[ DIALOG main(0) text="Это же наша Лизарния!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
10
11 {[ DIALOG enemy(0) text="Мы дома!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
12
13 {[ DIALOG main(0) text="Глянь-ка,
14 ещё камень!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
15 [ MOVE main(0) dir=4 amount=2 ]}
16
17 {[ DIALOG enemy(0) text="Не тронь!!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
18
19 {[ MOVE main(0) dir=4 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 33
2 # The end
3 ##########################################
4
5 {[ DIALOG enemy(0) text="Ааа!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ DIALOG main(0) text="Ой!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
7
8 {
9 [ NARRATIVE text="
10 КОНЕЦ
11 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
12 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle and Ludar arrive to the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Ааах!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Аах!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
8 }
9
10 {
11 [ NARRATIVE text="Ибела и Лудар." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
12 }
13
14 {
15 [ DIALOG main(0) text="Ух! Шта се десило?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=6 amount=2 ]
17 [ MOVE enemy(0) dir=6 amount=3 ]
18 }
19
20 {
21 [ DIALOG enemy(0) text="Рекао сам ти
22 да не дираш
23 тај камен!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
24 }
25
26 {
27 [ DIALOG main(0) text="Ма, ућути..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
28 }
29
30 {
31 [ DIALOG main(0) text="Како сам могла
32 да знам?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
33 }
34
35 {
36 [ DIALOG main(0) text="Где смо?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
37 }
38
39 {
40 [ DIALOG enemy(0) text="ХА! То ми
41 ти кажи!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
42 }
43
44 {
45 [ DIALOG enemy(0) text="Да си само
46 држала своје руке к себи..." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
47 }
48
49 {
50 [ DIALOG main(0) text="Тупсон..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
51 [ DIALOG enemy(0) text="Глупачица..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
52 }
53
54 {
55 [ DIALOG main(0) text="Морамо наћи
56 начин да се
57 вратимо кући" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
58 }
59
60 {
61 [ DIALOG main(0) text="Прати ме, Лударе" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
62 }
63
64 {
65 [ DIALOG enemy(0) text="Нема шансе! Увек
66 ме уваљујеш
67 у невоље" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
68 }
69
70 {
71 [ DIALOG enemy(0) text="Овај пут ћемо
72 радити како ја кажем" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
73 }
74
75 {
76 [ DIALOG main(0) text="Па..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
77 }
78
79 {
80 [ DIALOG main(0) text="Онда ћу
81 ићи сама" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
82 [ MOVE main(0) dir=6 amount=5 ]
83 }
84
85 {
86 [ DIALOG enemy(0) text="???" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
87 [ MOVE main(0) dir=8 amount=3 ]
88 }
89
90 {
91 [ MOVE enemy(0) dir=6 amount=3 ]
92 [ DIALOG enemy(0) text="ехеј... Ибело,
93 чекај!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
94 }
95
96 {
97 [ MOVE main(0) dir=6 amount=3 ]
98 }
0 ##########################################
1 # Holotz's Castle story - Level 2
2 # Ybelle enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Нееее!" txtAlign=4 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 }
7
8 {
9 [ DIALOG main(0) text="Ово боли!" txtAlign=4 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
10 }
11
12 {
13 [ DIALOG main(0) text="ЛУДАРЕ!" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
14 }
15
16 {
17 [ DIALOG main(0) text="?" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=1 ]
18 }
19
20 {
21 [ DIALOG main(0) text="Можда
22 не може да ме чује." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Шта бре...?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
27 [ MOVE main(0) dir=6 amount=1 ]
28 }
29
30 {
31 [ MOVE main(0) dir=4 amount=1 ]
32 [ DIALOG main(0) text="Шта су сви ови
33 кључеви?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
34
35 }
36
37 # REMIND USER THAT THIS IS YBELLE.
38 # TEACH THE USER THAT SPACE IS JUMP.
39 # MAKE SURE THEY KNOW WHAT A "MAGIC PORTAL" IS, TO SET UP THE JOKE IN LEVEL 16.
40 {
41 [ NARRATIVE text="Притисни размак да би Ибела
42 скочила у чаробни пролаз" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
43 }
0 ##########################################
1 # Holotz's Castle story - Level 7
2 # Ludar enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="ехеј... Ибело,
6 чекај ме!" txtAlign=4 speed=2 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ MOVE main(0) dir=6 amount=2 ]
8 }
9
10 {
11 [ MOVE main(0) dir=6 amount=1 ]
12 [ DIALOG main(0) text="О, не!" txtAlign=4 speed=5 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
13 }
14
15
16 {
17 [ DIALOG main(0) text="Ко је ставио ову
18 рупу овде?" txtAlign=4 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
19 }
20
21 {
22 [ DIALOG main(0) text="Упомоћ! Ибело!" txtAlign=5 speed=1 size=3 align=0 r=20 g=200 b=20 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Зашто неће
27 да ми одговори?" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
28 }
29
30 {
31 [ DIALOG main(0) text="Луда тврдоглава!" txtAlign=5 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
32 }
33
34 {
35 [ DIALOG main(0) text="Ох, хеј!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
36 [ MOVE main(0) dir=4 amount=1 ]
37 }
38
39 {
40 [ DIALOG main(0) text="Ови каменови су
41 слични оном који је
42 Ибела узела" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
43 [ MOVE main(0) dir=4 amount=1 ]
44 }
45
46 {
47 # EXPLAIN WHY YBELLE IS GRABBING STONES AFTER HE TOLD LUDAR NOT TO
48 [ DIALOG main(0) text="Да ли би они могли бити
49 пут за излазак одавде?" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
50 [ MOVE main(0) dir=4 amount=1 ]
51 }
52
53 {
54 # SHOULD GIVE USER A HINT THAT GAME IS STARTING AS LUDAR
55 [ DIALOG main(0) text="Претпостављам да је на мене ред
56 да преузмем ризик" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
57 }
58
59 # MORE HINTS FOR THE USER AND A REMINDER THAT THIS GUY IS LUDAR
60 {
61 [ NARRATIVE text="Држањем размака Лудар скаче више" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
62 }
0 ##########################################
1 # Holotz's Castle story - Level 14
2 # Ybelle finds the shoe maker
3 ##########################################
4
5 {[ DIALOG main(0) text="Уф!
6 Драго ми је што сам
7 отишла оданде" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
8 [ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
9
10 {[ DIALOG main(0) text="Бре, шта је ово место?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
11
12 {[ NARRATIVE text="Ибела у обућаревој радионици" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=1 ]}
14
15 {[ MOVE main(0) dir=2 amount=3 ]}
16
17 {[ MOVE main(0) dir=6 amount=2 ]}
18
19 {[ MOVE main(0) dir=9 amount=2 ]}
20
21 {[ MOVE main(0) dir=6 amount=3 ]}
22
23 {[ MOVE main(0) dir=9 amount=1 ]
24 [ DIALOG enemy(0) text="Посетилац!" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=1 ]}
25
26 {[ MOVE main(0) dir=9 amount=2 ]}
27
28 {[ DIALOG main(0) text="Како
29 чудан лик!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
30 [ DIALOG enemy(0) text="Како
31 чудан лик!" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=1 ]
32 }
33
34 {[ DIALOG main(0) text="Овај.. Здраво?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
35
36 {[ DIALOG enemy(0) text="Ти..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
37
38 {[ DIALOG enemy(0) text="како..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="ми..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
41 [ DIALOG main(0) text="?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
42
43
44 {[ DIALOG enemy(0) text="се..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
45
46 {[ DIALOG enemy(0) text="чини..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="ниси..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
49
50 {[ DIALOG enemy(0) text="одавде" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
51
52 {[ DIALOG enemy(0) text="Хммм..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
53 [ DIALOG main(0) text="Изгледа као
54 да је хтео
55 да заспи!!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
56
57 {[ DIALOG enemy(0) text="Јеси...
58 ли..." txtAlign=5 speed=1 size=0 align=1 r=200 g=130 b=20 subtype=0 ]}
59
60 {[ DIALOG main(0) text="Види... овај" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
61 [ DIALOG enemy(0) text="нов..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
62
63 {[ DIALOG main(0) text="Нов, кажеш?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
64
65 {[ DIALOG main(0) text="О, да,
66 ја сам нова овде" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
67
68 {[ DIALOG main(0) text="Ко си ти?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
69
70 {[ DIALOG enemy(0) text="Ја... сам..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
71
72 {[ DIALOG enemy(0) text="Господар
73 ципела" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=0 ]}
74
75 {[ DIALOG enemy(0) text="Дошао...
76 си...
77 по..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
78
79 {[ DIALOG enemy(0) text="нови...
80 пар..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
81
82 {[ DIALOG enemy(0) text="...зар не?" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
83 [ DIALOG main(0) text="Па,
84 у ствари" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
85
86 {[ DIALOG enemy(0) text="Узми..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
87 [ DIALOG main(0) text="ја..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
88
89 {[ DIALOG enemy(0) text="...ове" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
90
91
92
93 {[ MOVE main(0) dir=6 amount=2 ]}
94 {[ MOVE main(0) dir=4 amount=2 ]}
95
96 {[ DIALOG enemy(0) text="Твоји...
97 ће...
98 скокови..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
99
100 {[ DIALOG enemy(0) text="бити..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
101 [ DIALOG main(0) text="Да ли знаш
102 како да
103 изађем одавде?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
104 }
105
106 {[ DIALOG enemy(0) text="Да...
107 размислим..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
108
109 {[ DIALOG enemy(0) text="Не" txtAlign=5 speed=1 size=2 align=1 r=200 g=130 b=20 subtype=0 ]}
110
111 {[ DIALOG enemy(0) text="Само...
112 Холоц..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
113
114 {[ DIALOG enemy(0) text="зна..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
115 [ DIALOG main(0) text="Холоц?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
116
117 {[ DIALOG enemy(0) text="Да..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
118 {[ DIALOG enemy(0) text="Он...
119 је...
120 направио..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
121
122 {[ DIALOG enemy(0) text="ово..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
123 [ DIALOG main(0) text="Где га могу
124 наћи?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
125
126 {[ DIALOG enemy(0) text="Не...
127 можеш..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
128
129 {[ DIALOG enemy(0) text="Он ће...
130 наћи...
131 тебе" txtAlign=5 speed=1 size=2 align=1 r=200 g=130 b=20 subtype=0 ]}
132 {[ DIALOG main(0) text="!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
133
134
135 {[ DIALOG enemy(0) text="Сада...
136 морам...
137 да..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
138
139 {[ DIALOG enemy(0) text="се...
140 вратим...
141 на посао..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
142
143 {[ DIALOG main(0) text="А-али...!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
144 [ DIALOG enemy(0) text="Сада...
145 морам...
146 да..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
147
148 {[ DIALOG main(0) text="Ма, заборави
149 на све ово!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
150
151 {[ DIALOG main(0) text="Па, одлазим...
152 хвала на
153 ципелама" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
154 [ MOVE main(0) dir=7 amount=2 ]}
155
156 {[ MOVE main(0) dir=7 amount=2 ]}
157
158 {[ DIALOG main(0) text="Али, куда ћу
159 сада?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
160
161 {[ DIALOG main(0) text="Па добро." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
162
163 {[ DIALOG main(0) text="Кад си изгубљен" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
164 [ MOVE main(0) dir=4 amount=1 ]}
165
166 {[ DIALOG main(0) text="сваки смер
167 је напред" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
168 {[ MOVE main(0) dir=2 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 16
2 # Ludar talks to the two flames
3 ##########################################
4
5 {[ DIALOG main(0) text="Опа" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_UltraSlow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Гле, још један
9 камен!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
10 [ MOVE main(0) dir=6 amount=1 ]}
11
12 {[ NARRATIVE text="Лудар и два пламена" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=4 ]
14 [ DIALOG main(0) text="...и још један!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
15
16 {[ DIALOG enemy(0) text="Стој!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
17
18 {[ DIALOG main(0) text="???" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
19 [ MOVE main(0) dir=4 amount=1 ]}
20
21 {[ DIALOG main(0) text="Ко је то?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
22 [ MOVE main(0) dir=6 amount=4 ]}
23
24 {[ DIALOG enemy(0) text="Рекох
25 СТОЈ!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
26
27 {[ MOVE main(0) dir=4 amount=4 ]
28 [ DIALOG main(0) text="Гле,
29 пламен који говори!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]}
30
31 {[ DIALOG enemy(0) text="Ја нисам
32 пламен који говори!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]
33 [ DIALOG main(0) text="Не?" txtAlign=5 speed=4 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=6 amount=2 ]}
35
36 {[ DIALOG enemy(0) text="Ја сам
37 пламен који прича!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
38
39 {[ DIALOG main(0) text="Како си
40 знао
41 моје мисли?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(0) text="Ја знам
44 све!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
45
46 {[ DIALOG enemy(1) text="Хммм..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="Па, скоро
49 све" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
50
51 {[ DIALOG enemy(1) text="Она чита
52 мисли..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
53
54 {[ DIALOG enemy(1) text="А ја читам..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
55
56 {[ DIALOG enemy(1) text="...књиге" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
57
58 {[ DIALOG enemy(1) text="Хар, хар, хар!" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]
59 [ DIALOG enemy(0) text="Хур, хур, хур!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]
60 [ DIALOG main(0) text="??!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
61
62 {[ DIALOG enemy(1) text="Како си
63 доспео овде?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="Знам..." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
66
67 {[ DIALOG main(0) text="Ух, сад ће да ми
68 прочита мисли!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]}
69
70 {[ DIALOG enemy(0) text="Кроз
71 чаробни
72 пролаз!!!" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
73
74 {[ DIALOG enemy(1) text="Хар, хар, хар!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
75 [ DIALOG enemy(0) text="Хур, хур, хур!" txtAlign=5 speed=1 size=3 align=0 r=20 g=20 b=180 subtype=0 ]
76 [ DIALOG main(0) text="хрмпф#@!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
77 [ MOVE main(0) dir=6 amount=4 ]}
78
79 {[ DIALOG enemy(1) text="Чекај, не
80 одлази" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
81 [ MOVE main(0) dir=4 amount=5 ]}
82
83 {[ DIALOG main(0) text="Немам
84 времена за
85 шале!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
86 [ MOVE main(0) dir=6 amount=2 ]}
87
88 {[ DIALOG enemy(0) text="Шта ти
89 је потребно?" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]
90 [ MOVE main(0) dir=4 amount=3 ]}
91
92 {[ DIALOG main(0) text="Морам да
93 нађем Ибелу" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
94
95 {[ DIALOG main(0) text="Ми морамо
96 да се вратимо
97 у земљу
98 Лизарно" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
99
100 {[ DIALOG enemy(0) text="Хммм... Лизарнићанин,
101 како занимљиво" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=1 ]}
102
103 {[ DIALOG enemy(1) text="Одавде
104 замак постаје
105 све опаснији" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
106
107 {[ DIALOG enemy(1) text="Али ти немаш
108 чаробне моћи" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
109
110 {[ DIALOG enemy(1) text="и не можеш
111 досећи
112 највиши ниво" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
113
114 {[ DIALOG enemy(0) text="Да, оно што ти
115 треба је..." txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
116
117 {[ DIALOG enemy(1) text="Пар
118 ципела!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
119 [ DIALOG enemy(0) text="Пар
120 ципела!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
121
122 {[ DIALOG main(0) text="Ама, престаните
123 да се шалите!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
124 [ MOVE main(0) dir=4 amount=2 ]}
125
126 {[ DIALOG enemy(0) text="Али, њих ти може
127 дати једино" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
128
129 {[ DIALOG enemy(0) text="Господар
130 ципела" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
131
132 {[ DIALOG main(0) text="Зар не постоји неки
133 други начин да добијем
134 пар ципела?" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
135 [ MOVE main(0) dir=6 amount=2 ]}
136
137 {[ DIALOG enemy(1) text="Да, можеш их
138 набавити у" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=60 subtype=0 ]}
139
140 {[ DIALOG enemy(1) text="продавници ципела!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=60 subtype=0 ]
141 [ DIALOG enemy(0) text="продавници ципела!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]}
142
143 {[ DIALOG enemy(1) text="Хар, хар, хар!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
144 [ DIALOG enemy(0) text="Хур, хур, хур!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]
145 [ DIALOG main(0) text="Ово је
146 излуђујуће!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
147 [ MOVE main(0) dir=6 amount=4 ]}
148
149 {[ DIALOG enemy(1) text="Чекај" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
150 [ MOVE main(0) dir=4 amount=2 ]}
151
152 {[ DIALOG enemy(1) text="Можеш наћи
153 један пар" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
154
155 {[ DIALOG enemy(1) text="у соби
156 иза овог
157 чаробног пролаза" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
158
159 {[ DIALOG enemy(0) text="Али мораш
160 знати" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
161
162 {[ DIALOG enemy(0) text="да је још нико није
163 напустио жив" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
164
165 {[ DIALOG main(0) text="Ух!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
166 [ MOVE main(0) dir=6 amount=2 ]}
167
168 {[ DIALOG main(0) text="Хмм... Па,
169 морам да покушам" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
170 [ MOVE main(0) dir=4 amount=2 ]}
171
172 {[ DIALOG main(0) text="Ух! Али
173 не могу да отворим
174 пролаз" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
175 [ MOVE main(0) dir=4 amount=2 ]}
176
177 {[ DIALOG main(0) text="Овај камен је
178 превисоко!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
179
180 {[ DIALOG enemy(1) text="Па, онда
181 употреби ове мердевине" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 19
2 # Ybelle is captured
3 ##########################################
4
5 {[ DIALOG main(0) text="АААХ!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_Fast.wav" loops=0 waitToEnd=0 ]}
7
8 {[ MOVE enemy(0) dir=8 amount=4 ]
9 [ MOVE enemy(1) dir=8 amount=4 ]
10 [ MOVE enemy(2) dir=4 amount=2 ]
11 [ MOVE enemy(3) dir=6 amount=2 ]
12 [ MOVE enemy(4) dir=4 amount=5 ]
13 [ MOVE enemy(5) dir=6 amount=5 ]
14 [ DIALOG main(0) text="Ух ох" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
15 [ DIALOG enemy(2) text="!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=1 ]
16 [ DIALOG enemy(3) text="!" txtAlign=5 speed=1 size=2 align=0 r=220 g=20 b=20 subtype=1 ]}
17
18 {[ NARRATIVE text="
19 НАСТАВИЋЕ СЕ...
20 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
21 [ DIALOG main(0) text="??!" txtAlign=5 speed=3 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=5 amount=1 ]}
23
24 {[ DIALOG main(0) text="Ееех!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
25 [ MOVE main(0) dir=5 amount=2 ]}
26
27 {[ DIALOG main(0) text="Не остављај ме овде!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
28 [ MOVE main(0) dir=5 amount=2 ]}
29
30 {[ WAIT millis=3000]}
0 ##########################################
1 # Holotz's Castle story - Level 20
2 # Ybelle is captured (continued)
3 ##########################################
4
5 {[ MOVE enemy(0) dir=8 amount=0 ]
6 [ MOVE enemy(1) dir=8 amount=0 ]
7 [ MOVE enemy(2) dir=4 amount=0 ]
8 [ MOVE enemy(3) dir=6 amount=0 ]
9 [ MOVE enemy(4) dir=4 amount=0 ]
10 [ MOVE enemy(5) dir=6 amount=0 ]}
11
12 {[ WAIT millis=1000]}
13
14 {[ DIALOG main(0) text="Стој,
15 не мрдај!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=4 amount=1 ]}
17
18 {[ DIALOG enemy(0) text="Хее хее" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]
19 [ DIALOG enemy(1) text="Ух?" txtAlign=5 speed=5 size=3 align=0 r=200 g=20 b=20 subtype=0 ]}
20
21 {[ DIALOG main(0) text="Не терајте ме
22 да употребим свој кунг фу!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
23 [ MOVE main(0) dir=6 amount=2 ]}
24
25 {[ MOVE enemy(1) dir=4 amount=3 ]
26 [ DIALOG enemy(1) text="Видите!" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
27
28 {[ MOVE enemy(1) dir=4 amount=1 ]
29 [ DIALOG enemy(5) text="Шта?" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
30
31 {[ DIALOG enemy(1) text="Она има... ципеле" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
32
33 {[ DIALOG enemy(5) text="Уху!
34 Холоцу се ово
35 неће свидети" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
36
37 {[ DIALOG main(0) text="Шта желите?" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
38
39 {[ MOVE enemy(5) dir=6 amount=4 ]
40 [ MOVE main(0) dir=6 amount=1 ]
41 [ DIALOG enemy(5) text="Питање је..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(5) text="Шта ти
44 тражиш овде?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
45
46 {[ DIALOG main(0) text="Узела сам
47 камен и..." txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
48
49 {[ DIALOG enemy(5) text="И мистични пролаз
50 се отворио. Зар не?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
51
52 {[ DIALOG main(0) text="Управо тако!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
53
54 {[ DIALOG enemy(5) text="Изгледа да
55 Холоцови експерименти
56 нису успели" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
57
58 {[ DIALOG enemy(5) text="Забавља ме
59 то што си стигла
60 овако далеко..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
61
62 {[ DIALOG enemy(4) text="Шта да
63 радимо са њом?" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=0 ]}
64
65 {[ DIALOG enemy(5) text="Ми радимо како
66 Холоц каже..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
67
68 {[ DIALOG enemy(5) text="...одвешћемо је
69 у Фрохов лавиринт" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
70
71 {[ DIALOG enemy(5) text="Тамо ће остати
72 док Холоц не одлучи
73 њену судбину..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
74
75 {[ DIALOG enemy(5) text="...ако је четворица
76 браће лудака
77 не нађу прво!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
78
79 {[ DIALOG enemy(1) text="Хар, хар!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=20 subtype=0 ]
80 [ DIALOG enemy(2) text="Хур, хур, хур!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ] }
81
82 {[ DIALOG main(0) text="Гулп!" txtAlign=5 speed=5 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
83
84
85 # LET USER KNOW THEY'RE SWITCHING BACK TO LUDAR.
86 {[ DIALOG main(0) text="Надам се
87 да је Лудар добро..." txtAlign=5 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=1 ]}
88
89 {
90 [ NARRATIVE text="Можеш променити Лударов смер усред скока." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
91 }
0 ##########################################
1 # Holotz's Castle story - Level 25
2 # Holotz appears
3 ##########################################
4
5
6 # This jump is just to scroll the screen up so the text is visible.
7 # A better fix would be to redesign the level so Holotz isn't so high up.
8 {[ MOVE main(0) dir=5 amount=1 ]}
9
10 {
11 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
12 [ NARRATIVE text="Холоц." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 }
14 {[ MOVE enemy(0) dir=9 amount=2 ]}
15
16 {[ MOVE main(0) dir=4 amount=2 ]
17 [ DIALOG main(0) text="Тако ми моћи
18 Хутазина!..." txtAlign=5 speed=5 size=2 align=1 r=80 g=80 b=200 subtype=0 ]}
19
20 {[ MOVE enemy(0) dir=9 amount=1 ]}
21 {[ MOVE enemy(0) dir=9 amount=1 ]}
22
23 {[ MOVE main(0) dir=6 amount=3 ]
24 [ DIALOG main(0) text="Пролазу елемената,
25 отвори се!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
26
27 {[ MOVE enemy(0) dir=9 amount=1 ]}
28
29 {[ WAIT millis=3000 ]}
30
31 {[ DIALOG main(0) text="Хммм..." txtAlign=5 speed=5 size=1 align=1 r=80 g=80 b=200 subtype=0 ]}
32
33 {[ MOVE main(0) dir=5 amount=1 ]
34 [ DIALOG main(0) text="Опет није
35 успело!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
36
37 {[ MOVE main(0) dir=4 amount=2 ]
38 [ MOVE enemy(0) dir=9 amount=1 ]
39 [ DIALOG main(0) text="Ти!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
40
41 {[ DIALOG main(0) text="Где је
42 затвореник?" txtAlign=5 speed=5 size=2 align=1 r=80 g=80 b=200 subtype=0 ]}
43
44 {[ DIALOG enemy(0) text="Овели смо га у
45 Фрохов лавиринт
46 како сте нам рекли" txtAlign=5 speed=5 size=1 align=1 r=200 g=20 b=20 subtype=0 ]}
47
48 {[ DIALOG main(0) text="Одлично" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
49
50 {[ DIALOG enemy(0) text="Али морате знати" txtAlign=5 speed=5 size=1 align=1 r=200 g=20 b=20 subtype=0 ]}
51
52 {[ DIALOG enemy(0) text="да је имао
53 ципеле, господине" txtAlign=5 speed=5 size=1 align=1 r=200 g=20 b=20 subtype=0 ]}
54
55 {[ DIALOG main(0) text="Глупане! Чекај, хоћу да кажем..." txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
56 [ MOVE enemy(0) dir=4 amount=1 ]}
57
58 # When Holotz yells, the demon falls back one stair step
59 {[ DIALOG main(0) text="Ти потпуно
60 безмозговни идиоте!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
61 [ MOVE main(0) dir=4 amount=1 ]
62 [ MOVE enemy(0) dir=4 amount=1 ]}
63
64 {[ DIALOG main(0) text="Зашто ми ниси
65 рекао!" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
66
67 {[ DIALOG enemy(0) text="Ја..." txtAlign=5 speed=5 size=1 align=0 r=200 g=20 b=20 subtype=0 ]}
68
69 {[ DIALOG main(0) text="До сада су већ стигли
70 до куле" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
71
72 {[ DIALOG main(0) text="Призови све
73 звери!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
74
75 {[ DIALOG enemy(0) text="Да, господине" txtAlign=5 speed=5 size=2 align=0 r=200 g=20 b=20 subtype=0 ]}
76
77 {[ MOVE enemy(0) dir=7 amount=2 ]}
78
79 {[ MOVE enemy(0) dir=7 amount=2 ]
80 [ DIALOG main(0) text="Приредићемо
81 тим Лизарнићанима
82 изненађење" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 30
2 # Ybelle and Ludar meet again
3 ##########################################
4
5 {[ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
6
7 {[ MOVE main(0) dir=8 amount=6 ]
8 [ MOVE enemy(0) dir=8 amount=6 ]
9 [ MOVE enemy(1) dir=8 amount=6 ]
10 [ MOVE enemy(2) dir=8 amount=6 ]}
11
12 {[ MOVE main(0) dir=6 amount=3 ]
13 [ MOVE enemy(0) dir=4 amount=3 ]
14 [ MOVE enemy(1) dir=8 amount=4 ]
15 [ MOVE enemy(2) dir=8 amount=4 ]}
16
17 {[ MOVE main(0) dir=6 amount=4 ]
18 [ MOVE enemy(0) dir=4 amount=4 ]
19 [ MOVE enemy(1) dir=4 amount=3 ]
20 [ MOVE enemy(2) dir=6 amount=3 ]}
21
22 {[ DIALOG main(0) text="Лударе!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
23 [ DIALOG enemy(0) text="Ибело!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]
24 [ MOVE main(0) dir=4 amount=1 ]
25 [ MOVE enemy(0) dir=6 amount=1 ]}
26
27 {[ DIALOG main(0) text="Жив си!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
28 [ DIALOG enemy(0) text="Ти ниси мртва!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]
29 [ MOVE main(0) dir=6 amount=1 ]
30 [ MOVE enemy(0) dir=4 amount=1 ]}
31
32 {[ DIALOG enemy(0) text="Лепе ципеле" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
33
34 {[ DIALOG main(0) text="Бољи смо
35 заједно" txtAlign=5 speed=5 size=2 align=0 r=130 g=30 b=180 subtype=0 ]}
36
37 {[ DIALOG enemy(0) text="Прати ме!" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
38
39 {[ DIALOG main(0) text="Хмм..." txtAlign=5 speed=5 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
40 [ MOVE main(0) dir=4 amount=1 ]}
41
42 {[ DIALOG enemy(0) text="А да идемо
43 заједно?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
44
45 {[ DIALOG main(0) text="Заједно." txtAlign=5 speed=5 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
46 [ MOVE main(0) dir=6 amount=1 ]}
47
48 {[ MOVE main(0) dir=8 amount=3 ]
49 [ MOVE enemy(0) dir=8 amount=3 ]}
0 ##########################################
1 # Holotz's Castle story - Level 32
2 # Return to the land of Lizarno
3 ##########################################
4
5 {[ DIALOG main(0) text="Ааах!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Аах!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCCredits.wav" loops=-1 waitToEnd=0 ]}
8
9 {[ DIALOG main(0) text="Ми смо у Лизарну!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
10
11 {[ DIALOG enemy(0) text="Ми смо кући!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
12
13 {[ DIALOG main(0) text="Хеј, види
14 овај камен!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
15 [ MOVE main(0) dir=4 amount=2 ]}
16
17 {[ DIALOG enemy(0) text="Не додируј га!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
18
19 {[ MOVE main(0) dir=4 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 33
2 # The end
3 ##########################################
4
5 {[ DIALOG enemy(0) text="Аах!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ DIALOG main(0) text="Ааах!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
7
8 {
9 [ NARRATIVE text="
10 КРАЈ
11 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
12 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle and Ludar arrive to the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
8 }
9
10 {
11 [ NARRATIVE text="Ybelle och Ludar." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
12 }
13
14 {
15 [ DIALOG main(0) text="Whoa! Vad hände?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=6 amount=2 ]
17 [ MOVE enemy(0) dir=6 amount=3 ]
18 }
19
20 {
21 [ DIALOG enemy(0) text="Jag sade åt
22 dig att inte
23 röra den där stenen!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
24 }
25
26 {
27 [ DIALOG main(0) text="Oh, tyst..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
28 }
29
30 {
31 [ DIALOG main(0) text="Hur skulle jag
32 kunna vetat?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
33 }
34
35 {
36 [ DIALOG main(0) text="Var är vi?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
37 }
38
39 {
40 [ DIALOG enemy(0) text="HA! Säg det!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
41 }
42
43 {
44 [ DIALOG enemy(0) text="Om du bara hade
45 hållit dina fingrar borta..." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
46 }
47
48 {
49 [ DIALOG main(0) text="Lump..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
50 [ DIALOG enemy(0) text="Nincompoop..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
51 }
52
53 {
54 [ DIALOG main(0) text="Vi måste hitta
55 en väg så vi
56 kan återvända hem" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
57 }
58
59 {
60 [ DIALOG main(0) text="Följ mig, Ludar" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
61 }
62
63 {
64 [ DIALOG enemy(0) text="Aldrig i livet! Du gör
65 alltid så att jag
66 hamnar i trubbel" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
67 }
68
69 {
70 [ DIALOG enemy(0) text="Den här gången
71 gör vi som jag säger" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
72 }
73
74 {
75 [ DIALOG main(0) text="Tja..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
76 }
77
78 {
79 [ DIALOG main(0) text="Jag antar att jag
80 får fortsätta ensam" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
81 [ MOVE main(0) dir=6 amount=5 ]
82 }
83
84 {
85 [ DIALOG enemy(0) text="???" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
86 [ MOVE main(0) dir=8 amount=3 ]
87 }
88
89 {
90 [ MOVE enemy(0) dir=6 amount=3 ]
91 [ DIALOG enemy(0) text="err... Ybelle,
92 Vänta!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
93 }
94
95 {
96 [ MOVE main(0) dir=6 amount=3 ]
97 }
0 ##########################################
1 # Holotz's Castle story - Level 2
2 # Ybelle enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Neeeej!" txtAlign=4 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 }
7
8 {
9 [ DIALOG main(0) text="Det där gjorde ont!" txtAlign=4 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
10 }
11
12 {
13 [ DIALOG main(0) text="LUDAR!" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
14 }
15
16 {
17 [ DIALOG main(0) text="?" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=1 ]
18 }
19
20 {
21 [ DIALOG main(0) text="Han kanske
22 inte kan höra mig." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Vad i...?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
27 [ MOVE main(0) dir=6 amount=1 ]
28 }
29
30 {
31 [ MOVE main(0) dir=4 amount=1 ]
32 [ DIALOG main(0) text="Vad är det med
33 alla dessa nycklar?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
34
35 }
36
37 # REMIND USER THAT THIS IS YBELLE.
38 # TEACH THE USER THAT SPACE IS JUMP.
39 # MAKE SURE THEY KNOW WHAT A "MAGIC PORTAL" IS, TO SET UP THE JOKE IN LEVEL 16.
40 {
41 [ NARRATIVE text="Tryck mellanslag för att få Ybelle
42 att hoppa in i den magiska portalen" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
43 }
0 ##########################################
1 # Holotz's Castle story - Level 7
2 # Ludar enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="err... Ybelle,
6 Vänta på mig!" txtAlign=4 speed=2 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ MOVE main(0) dir=6 amount=2 ]
8 }
9
10 {
11 [ MOVE main(0) dir=6 amount=1 ]
12 [ DIALOG main(0) text="Oh, nej!" txtAlign=4 speed=5 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
13 }
14
15
16 {
17 [ DIALOG main(0) text="Vem gjorde det
18 där hålet där?" txtAlign=4 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
19 }
20
21 {
22 [ DIALOG main(0) text="Hjälp! Ybelle!" txtAlign=5 speed=1 size=3 align=0 r=20 g=200 b=20 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Varför svarar
27 han inte?" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
28 }
29
30 {
31 [ DIALOG main(0) text="Din envisna dåre!" txtAlign=5 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
32 }
33
34 {
35 [ DIALOG main(0) text="Oh, hey!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
36 [ MOVE main(0) dir=4 amount=1 ]
37 }
38
39 {
40 [ DIALOG main(0) text="De här stenarna
41 liknar den som
42 Ybelle tog" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
43 [ MOVE main(0) dir=4 amount=1 ]
44 }
45
46 {
47 # EXPLAIN WHY YBELLE IS GRABBING STONES AFTER HE TOLD LUDAR NOT TO
48 [ DIALOG main(0) text="Kan de leda till
49 vägen ut härifrån?" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
50 [ MOVE main(0) dir=4 amount=1 ]
51 }
52
53 {
54 # SHOULD GIVE USER A HINT THAT GAME IS STARTING AS LUDAR
55 [ DIALOG main(0) text="Jag antar att det är min tur
56 att ta vissa risker" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
57 }
58
59 # MORE HINTS FOR THE USER AND A REMINDER THAT THIS GUY IS LUDAR
60 {
61 [ NARRATIVE text="Genom att hålla ned mellanslag kan Ludar hoppa högre" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
62 }
0 ##########################################
1 # Holotz's Castle story - Level 14
2 # Ybelle finds the shoe maker
3 ##########################################
4
5 {[ DIALOG main(0) text="Whew!
6 Vad skönt att få
7 komma ut därifrån" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
8 [ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
9
10 {[ DIALOG main(0) text="Men, vad är det här för ställe?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
11
12 {[ NARRATIVE text="Ybelle i skomakarens verkstad" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=1 ]}
14
15 {[ MOVE main(0) dir=2 amount=3 ]}
16
17 {[ MOVE main(0) dir=6 amount=2 ]}
18
19 {[ MOVE main(0) dir=9 amount=2 ]}
20
21 {[ MOVE main(0) dir=6 amount=3 ]}
22
23 {[ MOVE main(0) dir=9 amount=1 ]
24 [ DIALOG enemy(0) text="En besökare!" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=1 ]}
25
26 {[ MOVE main(0) dir=9 amount=2 ]}
27
28 {[ DIALOG main(0) text="Vilken
29 konstig snubbe!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
30 [ DIALOG enemy(0) text="Vilken
31 konstig snubbe!" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=1 ]
32 }
33
34 {[ DIALOG main(0) text="Err.. Hallå?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
35
36 {[ DIALOG enemy(0) text="Du..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
37
38 {[ DIALOG enemy(0) text="ser..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="inte ut..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
41 [ DIALOG main(0) text="?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
42
43
44 {[ DIALOG enemy(0) text="att..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
45
46 {[ DIALOG enemy(0) text="vara..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="här-..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
49
50 {[ DIALOG enemy(0) text="ifrån" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
51
52 {[ DIALOG enemy(0) text="Hmmm..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
53 [ DIALOG main(0) text="Det verkar som
54 om han var
55 på väg att somna!!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
56
57 {[ DIALOG enemy(0) text="Är...
58 du...
59 den..." txtAlign=5 speed=1 size=0 align=1 r=200 g=130 b=20 subtype=0 ]}
60
61 {[ DIALOG main(0) text="Ser... Oh" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
62 [ DIALOG enemy(0) text="ny..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
63
64 {[ DIALOG main(0) text="Ny, säger du?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
65
66 {[ DIALOG main(0) text="Ja, jag är ny här,
67 varför undrar du?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
68
69 {[ DIALOG main(0) text="Vem är du?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
70
71 {[ DIALOG enemy(0) text="Jag... är..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
72
73 {[ DIALOG enemy(0) text="skornas
74 herre" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=0 ]}
75
76 {[ DIALOG enemy(0) text="Du har...
77 kommit...
78 för..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
79
80 {[ DIALOG enemy(0) text="ett...
81 par...
82 nya..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
83
84 {[ DIALOG enemy(0) text="...visst?" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
85 [ DIALOG main(0) text="Tja,
86 egentligen" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
87
88 {[ DIALOG enemy(0) text="Ta..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
89 [ DIALOG main(0) text="Jag..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
90
91 {[ DIALOG enemy(0) text="...de här" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
92
93
94
95 {[ MOVE main(0) dir=6 amount=2 ]}
96 {[ MOVE main(0) dir=4 amount=2 ]}
97
98 {[ DIALOG enemy(0) text="Du...
99 kommer...
100 att..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
101
102 {[ DIALOG enemy(0) text="hoppa..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
103 [ DIALOG main(0) text="Vet du
104 hur man tar
105 sig ut härifrån?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
106 }
107
108 {[ DIALOG enemy(0) text="Låt...
109 mig...
110 tänka..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
111
112 {[ DIALOG enemy(0) text="Nej" txtAlign=5 speed=1 size=2 align=1 r=200 g=130 b=20 subtype=0 ]}
113
114 {[ DIALOG enemy(0) text="Endast...
115 Holotz..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
116
117 {[ DIALOG enemy(0) text="vet..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
118 [ DIALOG main(0) text="Holotz?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
119
120 {[ DIALOG enemy(0) text="Ja..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
121 {[ DIALOG enemy(0) text="Han...
122 skapade..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
123
124 {[ DIALOG enemy(0) text="det..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
125 [ DIALOG main(0) text="Var kan
126 jag hitta honom?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
127
128 {[ DIALOG enemy(0) text="Du...
129 kan inte..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
130
131 {[ DIALOG enemy(0) text="Han kommer...
132 hitta...
133 dig" txtAlign=5 speed=1 size=2 align=1 r=200 g=130 b=20 subtype=0 ]}
134 {[ DIALOG main(0) text="!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
135
136
137 {[ DIALOG enemy(0) text="Nu...
138 måste...
139 jag..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
140
141 {[ DIALOG enemy(0) text="återgå...
142 till...
143 arbete" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
144
145 {[ DIALOG main(0) text="M-men...!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
146 [ DIALOG enemy(0) text="Nu...
147 måste...
148 jag..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
149
150 {[ DIALOG main(0) text="Oh, glöm
151 det här tramset!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
152
153 {[ DIALOG main(0) text="Nåja, jag sticker...
154 tack för
155 skorna" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
156 [ MOVE main(0) dir=7 amount=2 ]}
157
158 {[ MOVE main(0) dir=7 amount=2 ]}
159
160 {[ DIALOG main(0) text="Men, vart ska jag
161 gå nu?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
162
163 {[ DIALOG main(0) text="Jaja." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
164
165 {[ DIALOG main(0) text="När man är vilse" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
166 [ MOVE main(0) dir=4 amount=1 ]}
167
168 {[ DIALOG main(0) text="spelar det ingen
169 roll åt vilket håll man går" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
170 {[ MOVE main(0) dir=2 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 16
2 # Ludar talks to the two flames
3 ##########################################
4
5 {[ DIALOG main(0) text="Oops" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_UltraSlow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Oh, ytterligare
9 en sten!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
10 [ MOVE main(0) dir=6 amount=1 ]}
11
12 {[ NARRATIVE text="Ludar och de två lågorna" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=4 ]
14 [ DIALOG main(0) text="...och en till!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
15
16 {[ DIALOG enemy(0) text="Stanna!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
17
18 {[ DIALOG main(0) text="???" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
19 [ MOVE main(0) dir=4 amount=1 ]}
20
21 {[ DIALOG main(0) text="Vem här?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
22 [ MOVE main(0) dir=6 amount=4 ]}
23
24 {[ DIALOG enemy(0) text="Jag sade
25 STANNA!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
26
27 {[ MOVE main(0) dir=4 amount=4 ]
28 [ DIALOG main(0) text="Oh, en talande
29 låga!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]}
30
31 {[ DIALOG enemy(0) text="Jag är inte
32 en talande låga!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]
33 [ DIALOG main(0) text="Oh!" txtAlign=5 speed=4 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=6 amount=2 ]}
35
36 {[ DIALOG enemy(0) text="Jag är en pratande
37 låga!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
38
39 {[ DIALOG main(0) text="Hur visste
40 du vad
41 jag tänkte?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(0) text="Jag vet
44 allting!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
45
46 {[ DIALOG enemy(1) text="Ahem..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="Tja, nästan
49 allting" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
50
51 {[ DIALOG enemy(1) text="Hon läser
52 ens tankar..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
53
54 {[ DIALOG enemy(1) text="Och jag läser..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
55
56 {[ DIALOG enemy(1) text="...böcker" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
57
58 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]
59 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]
60 [ DIALOG main(0) text="??!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
61
62 {[ DIALOG enemy(1) text="Hur kom du
63 hit?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text=Jag vet..." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
66
67 {[ DIALOG main(0) text="Oh, hon tänker
68 läsa mina tankar!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]}
69
70 {[ DIALOG enemy(0) text="Genom den
71 mystiska
72 portalen!!" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
73
74 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
75 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=3 align=0 r=20 g=20 b=180 subtype=0 ]
76 [ DIALOG main(0) text="hmpfxs#@!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
77 [ MOVE main(0) dir=6 amount=4 ]}
78
79 {[ DIALOG enemy(1) text="Vänta, gå
80 inte" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
81 [ MOVE main(0) dir=4 amount=5 ]}
82
83 {[ DIALOG main(0) text="Jag har inte
84 tid med
85 skämt!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
86 [ MOVE main(0) dir=6 amount=2 ]}
87
88 {[ DIALOG enemy(0) text="Vad behöver
89 du?" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]
90 [ MOVE main(0) dir=4 amount=3 ]}
91
92 {[ DIALOG main(0) text="Jag måste
93 finna Ybelle" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
94
95 {[ DIALOG main(0) text="Vi måste
96 återvända till
97 Land of
98 Lizarno" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
99
100 {[ DIALOG enemy(0) text="Hmmm...en lizarnite,
101 så intressant" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=1 ]}
102
103 {[ DIALOG enemy(1) text="Från och med här
104 förvandlas slottet till
105 en mer farligare plats" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
106
107 {[ DIALOG enemy(1) text="Du saknar dock
108 magisk styrka" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
109
110 {[ DIALOG enemy(1) text="och kan inte
111 nå den
112 högsta nivån" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
113
114 {[ DIALOG enemy(0) text="Ja, det du
115 behöver är..." txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
116
117 {[ DIALOG enemy(1) text="Ett par
118 skor!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
119 [ DIALOG enemy(0) text="Ett par
120 skor!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
121
122 {[ DIALOG main(0) text="Oh, sluta
123 skoja!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
124 [ MOVE main(0) dir=4 amount=2 ]}
125
126 {[ DIALOG enemy(0) text="Men du kan bara
127 skaffa dem av" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
128
129 {[ DIALOG enemy(0) text="skornas
130 herre" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
131
132 {[ DIALOG main(0) text="Finns det inte
133 ett annat sätt att
134 få tag i ett par skor?" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
135 [ MOVE main(0) dir=6 amount=2 ]}
136
137 {[ DIALOG enemy(1) text="Jo, du kan
138 få tag i dem i" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=60 subtype=0 ]}
139
140 {[ DIALOG enemy(1) text="Skoaffären!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=60 subtype=0 ]
141 [ DIALOG enemy(0) text="Skoaffären!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]}
142
143 {[ DIALOG enemy(1) text="Jar, jar, jar!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
144 [ DIALOG enemy(0) text="Jur, jur, jur!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]
145 [ DIALOG main(0) text="Det här är
146 irriterande!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
147 [ MOVE main(0) dir=6 amount=4 ]}
148
149 {[ DIALOG enemy(1) text="Vänta" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
150 [ MOVE main(0) dir=4 amount=2 ]}
151
152 {[ DIALOG enemy(1) text="Du kan hitta
153 ett par" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
154
155 {[ DIALOG enemy(1) text="i rummet
156 bortom den här
157 mystiska portalen" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
158
159 {[ DIALOG enemy(0) text="Men du måste
160 känna till" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
161
162 {[ DIALOG enemy(0) text="att ingen har
163 lämnat det levande" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
164
165 {[ DIALOG main(0) text="Oh!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
166 [ MOVE main(0) dir=6 amount=2 ]}
167
168 {[ DIALOG main(0) text="Hmm... nåja,
169 Jag måste försöka" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
170 [ MOVE main(0) dir=4 amount=2 ]}
171
172 {[ DIALOG main(0) text="Oh! Men jag
173 kan inte öppna
174 portalen" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
175 [ MOVE main(0) dir=4 amount=2 ]}
176
177 {[ DIALOG main(0) text="Den där stenen
178 sitter för högt!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
179
180 {[ DIALOG enemy(1) text="Tja, använd då
181 den här stegen" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 19
2 # Ybelle is captured
3 ##########################################
4
5 {[ DIALOG main(0) text="AAAH!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_Fast.wav" loops=0 waitToEnd=0 ]}
7
8 {[ MOVE enemy(0) dir=8 amount=4 ]
9 [ MOVE enemy(1) dir=8 amount=4 ]
10 [ MOVE enemy(2) dir=4 amount=2 ]
11 [ MOVE enemy(3) dir=6 amount=2 ]
12 [ MOVE enemy(4) dir=4 amount=5 ]
13 [ MOVE enemy(5) dir=6 amount=5 ]
14 [ DIALOG main(0) text="Uh oh" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
15 [ DIALOG enemy(2) text="!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=1 ]
16 [ DIALOG enemy(3) text="!" txtAlign=5 speed=1 size=2 align=0 r=220 g=20 b=20 subtype=1 ]}
17
18 {[ NARRATIVE text="
19 FORTSÄTTNING FÖLJER...
20 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
21 [ DIALOG main(0) text="??!" txtAlign=5 speed=3 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=5 amount=1 ]}
23
24 {[ DIALOG main(0) text="Eeeh!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
25 [ MOVE main(0) dir=5 amount=2 ]}
26
27 {[ DIALOG main(0) text="Lämna mig inte här!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
28 [ MOVE main(0) dir=5 amount=2 ]}
29
30 {[ WAIT millis=3000]}
0 ##########################################
1 # Holotz's Castle story - Level 20
2 # Ybelle is captured (continued)
3 ##########################################
4
5 {[ MOVE enemy(0) dir=8 amount=0 ]
6 [ MOVE enemy(1) dir=8 amount=0 ]
7 [ MOVE enemy(2) dir=4 amount=0 ]
8 [ MOVE enemy(3) dir=6 amount=0 ]
9 [ MOVE enemy(4) dir=4 amount=0 ]
10 [ MOVE enemy(5) dir=6 amount=0 ]}
11
12 {[ WAIT millis=1000]}
13
14 {[ DIALOG main(0) text="Stanna, stå
15 still!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=4 amount=1 ]}
17
18 {[ DIALOG enemy(0) text="Hee hee" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]
19 [ DIALOG enemy(1) text="Huh?" txtAlign=5 speed=5 size=3 align=0 r=200 g=20 b=20 subtype=0 ]}
20
21 {[ DIALOG main(0) text="Tvinga mig inte att
22 använda mina Kung Fu-kunskaper!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
23 [ MOVE main(0) dir=6 amount=2 ]}
24
25 {[ MOVE enemy(1) dir=4 amount=3 ]
26 [ DIALOG enemy(1) text="Titta!" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
27
28 {[ MOVE enemy(1) dir=4 amount=1 ]
29 [ DIALOG enemy(5) text="Vad?" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
30
31 {[ DIALOG enemy(1) text="Han har... skor" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
32
33 {[ DIALOG enemy(5) text="Oh ho!
34 Holotz kommer inte
35 tycka om det där" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
36
37 {[ DIALOG main(0) text="Vad vill ni?" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
38
39 {[ MOVE enemy(5) dir=6 amount=4 ]
40 [ MOVE main(0) dir=6 amount=1 ]
41 [ DIALOG enemy(5) text="Frågan är..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(5) text="Vad gör
44 du här?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
45
46 {[ DIALOG main(0) text="Jag tog en
47 sten och..." txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
48
49 {[ DIALOG enemy(5) text="Och en mystisk portal
50 öppnade. Eller?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
51
52 {[ DIALOG main(0) text="Ja, precis!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
53
54 {[ DIALOG enemy(5) text="Det förefaller som om
55 Holotz experiment
56 inte har varit så framgångsrika" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
57
58 {[ DIALOG enemy(5) text="Det roar mig att
59 du har kommit
60 så här långt..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
61
62 {[ DIALOG enemy(4) text="Vad ska vi
63 göra med honom?" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=0 ]}
64
65 {[ DIALOG enemy(5) text="Vi gör som
66 Holotz sade..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
67
68 {[ DIALOG enemy(5) text="...vi för honom
69 till Labyrinth
70 of Froj" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
71
72 {[ DIALOG enemy(5) text="Där kommer han stanna
73 tills Holotz beslutar
74 vad som ska hända honom..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
75
76 {[ DIALOG enemy(5) text="...om inte de fyra
77 galna bröderna
78 hittar honom först!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
79
80 {[ DIALOG enemy(1) text="Har, har!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=20 subtype=0 ]
81 [ DIALOG enemy(2) text="Hur, hur, hur!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ] }
82
83 {[ DIALOG main(0) text="Gulp!" txtAlign=5 speed=5 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
84
85
86 # LET USER KNOW THEY'RE SWITCHING BACK TO LUDAR.
87 {[ DIALOG main(0) text="Jag hoppas
88 Ludar mår bra..." txtAlign=5 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=1 ]}
89
90 {
91 [ NARRATIVE text="Du kan ändra Ludars riktning när han är halvvägs upp i luften." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
92 }
0 ##########################################
1 # Holotz's Castle story - Level 25
2 # Holotz appears
3 ##########################################
4
5
6 # This jump is just to scroll the screen up so the text is visible.
7 # A better fix would be to redesign the level so Holotz isn't so high up.
8 {[ MOVE main(0) dir=5 amount=1 ]}
9
10 {
11 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
12 [ NARRATIVE text="Holotz." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 }
14 {[ MOVE enemy(0) dir=9 amount=2 ]}
15
16 {[ MOVE main(0) dir=4 amount=2 ]
17 [ DIALOG main(0) text="Med Hutazins
18 krafter!..." txtAlign=5 speed=5 size=2 align=1 r=80 g=80 b=200 subtype=0 ]}
19
20 {[ MOVE enemy(0) dir=9 amount=1 ]}
21 {[ MOVE enemy(0) dir=9 amount=1 ]}
22
23 {[ MOVE main(0) dir=6 amount=3 ]
24 [ DIALOG main(0) text="Öppna,
25 elementärportal!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
26
27 {[ MOVE enemy(0) dir=9 amount=1 ]}
28
29 {[ WAIT millis=3000 ]}
30
31 {[ DIALOG main(0) text="Hmmm..." txtAlign=5 speed=5 size=1 align=1 r=80 g=80 b=200 subtype=0 ]}
32
33 {[ MOVE main(0) dir=5 amount=1 ]
34 [ DIALOG main(0) text="Det misslyckades
35 igen!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
36
37 {[ MOVE main(0) dir=4 amount=2 ]
38 [ MOVE enemy(0) dir=9 amount=1 ]
39 [ DIALOG main(0) text="Du!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
40
41 {[ DIALOG main(0) text="Var är
42 fången?" txtAlign=5 speed=5 size=2 align=1 r=80 g=80 b=200 subtype=0 ]}
43
44 {[ DIALOG enemy(0) text="Vi förde honom till
45 Labyrinth of Froj
46 som du sade åt oss" txtAlign=5 speed=5 size=1 align=1 r=200 g=20 b=20 subtype=0 ]}
47
48 {[ DIALOG main(0) text="Bra gjort" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
49
50 {[ DIALOG enemy(0) text="Men, herre, du måste veta" txtAlign=5 speed=5 size=1 align=1 r=200 g=20 b=20 subtype=0 ]}
51
52 {[ DIALOG enemy(0) text="att han hade
53 skor" txtAlign=5 speed=5 size=1 align=1 r=200 g=20 b=20 subtype=0 ]}
54
55 {[ DIALOG main(0) text="Dolt! Vänta, jag menar..." txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
56 [ MOVE enemy(0) dir=4 amount=1 ]}
57
58 # When Holotz yells, the demon falls back one stair step
59 {[ DIALOG main(0) text="Din dumma
60 ärthjärna!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
61 [ MOVE main(0) dir=4 amount=1 ]
62 [ MOVE enemy(0) dir=4 amount=1 ]}
63
64 {[ DIALOG main(0) text="Varför sade
65 du ingenting!" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
66
67 {[ DIALOG enemy(0) text="Jag..." txtAlign=5 speed=5 size=1 align=0 r=200 g=20 b=20 subtype=0 ]}
68
69 {[ DIALOG main(0) text="Nu har de säkert
70 nått tornet" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
71
72 {[ DIALOG main(0) text="Sammankalla alla
73 odjur!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
74
75 {[ DIALOG enemy(0) text="Ja, herre" txtAlign=5 speed=5 size=2 align=0 r=200 g=20 b=20 subtype=0 ]}
76
77 {[ MOVE enemy(0) dir=7 amount=2 ]}
78
79 {[ MOVE enemy(0) dir=7 amount=2 ]
80 [ DIALOG main(0) text="Vi tänker
81 överraska de här
82 lizarnites" txtAlign=5 speed=5 size=2 align=1 r=130 g=30 b=180 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 30
2 # Ybelle and Ludar meet again
3 ##########################################
4
5 {[ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
6
7 {[ MOVE main(0) dir=8 amount=6 ]
8 [ MOVE enemy(0) dir=8 amount=6 ]
9 [ MOVE enemy(1) dir=8 amount=6 ]
10 [ MOVE enemy(2) dir=8 amount=6 ]}
11
12 {[ MOVE main(0) dir=6 amount=3 ]
13 [ MOVE enemy(0) dir=4 amount=3 ]
14 [ MOVE enemy(1) dir=8 amount=4 ]
15 [ MOVE enemy(2) dir=8 amount=4 ]}
16
17 {[ MOVE main(0) dir=6 amount=4 ]
18 [ MOVE enemy(0) dir=4 amount=4 ]
19 [ MOVE enemy(1) dir=4 amount=3 ]
20 [ MOVE enemy(2) dir=6 amount=3 ]}
21
22 {[ DIALOG main(0) text="Ludar!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
23 [ DIALOG enemy(0) text="Ybelle!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]
24 [ MOVE main(0) dir=4 amount=1 ]
25 [ MOVE enemy(0) dir=6 amount=1 ]}
26
27 {[ DIALOG main(0) text="Du lever!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
28 [ DIALOG enemy(0) text="Du är inte död!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]
29 [ MOVE main(0) dir=6 amount=1 ]
30 [ MOVE enemy(0) dir=4 amount=1 ]}
31
32 {[ DIALOG main(0) text="Snygga skor" txtAlign=5 speed=5 size=2 align=0 r=130 g=30 b=180 subtype=0 ]}
33
34 {[ DIALOG enemy(0) text="Vi fungerar bättre
35 som ett lag" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
36
37 {[ DIALOG enemy(0) text="Följ mig!" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
38
39 {[ DIALOG main(0) text="Hmm..." txtAlign=5 speed=5 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
40 [ MOVE main(0) dir=4 amount=1 ]}
41
42 {[ DIALOG enemy(0) text="Ska vi göra
43 göra det tillsammans?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
44
45 {[ DIALOG main(0) text="Tillsammans." txtAlign=5 speed=5 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
46 [ MOVE main(0) dir=6 amount=1 ]}
47
48 {[ MOVE main(0) dir=8 amount=3 ]
49 [ MOVE enemy(0) dir=8 amount=3 ]}
0 ##########################################
1 # Holotz's Castle story - Level 32
2 # Return to the land of Lizarno
3 ##########################################
4
5 {[ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCCredits.wav" loops=-1 waitToEnd=0 ]}
8
9 {[ DIALOG main(0) text="Vi är i Lizarno!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
10
11 {[ DIALOG enemy(0) text="Vi är hemma!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
12
13 {[ DIALOG main(0) text="Hey, se på
14 den där stenen!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
15 [ MOVE main(0) dir=4 amount=2 ]}
16
17 {[ DIALOG enemy(0) text="Rör den inte!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
18
19 {[ MOVE main(0) dir=4 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 33
2 # The end
3 ##########################################
4
5 {[ DIALOG enemy(0) text="Aah!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ DIALOG main(0) text="Aaah!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
7
8 {
9 [ NARRATIVE text="
10 SLUT
11 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
12 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle and Ludar arrive to the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Aaa!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Ааа!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
8 }
9
10 {
11 [ NARRATIVE text="Івонна та Людар." txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
12 }
13
14 {
15 [ DIALOG main(0) text="Що трапилося?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
16 [ MOVE main(0) dir=6 amount=2 ]
17 [ MOVE enemy(0) dir=6 amount=3 ]
18 }
19
20 {
21 [ DIALOG enemy(0) text="Я ж тобі говорив
22 не чіпати той
23 дивний камінь!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
24 }
25
26 {
27 [ DIALOG main(0) text="Замовкни..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
28 }
29
30 {
31 [ DIALOG main(0) text="Звідкіля мені
32 було знати?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
33 }
34
35 {
36 [ DIALOG main(0) text="А де ми є?" txtAlign=5 speed=1 size=2 align=0 r=130 g=30 b=180 subtype=0 ]
37 }
38
39 {
40 [ DIALOG enemy(0) text="Ха-ха! Звідкіля
41 їй було знати?" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
42 }
43
44 {
45 [ DIALOG enemy(0) text="Якби ти не
46 влізла, то нічого б
47 не трапилося..." txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
48 }
49
50 {
51 [ DIALOG main(0) text="Бовдур..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
52 [ DIALOG enemy(0) text="Дурепа..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
53 }
54
55 {
56 [ DIALOG main(0) text="Доведеться
57 шукати дорогу
58 додому" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
59 }
60
61 {
62 [ DIALOG main(0) text="Пішли за мною, Людар" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
63 }
64
65 {
66 [ DIALOG enemy(0) text="Оце вже дзуськи... ти завжди
67 ввязуєшся у всілякі
68 негаразди" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
69 }
70
71 {
72 [ DIALOG enemy(0) text="Тепер ти слухай
73 мене!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
74 }
75
76 {
77 [ DIALOG main(0) text="Що на нього найшло?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
78 }
79
80 {
81 [ DIALOG main(0) text="Ну и добре! Обійдуся
82 без тебе." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
83 [ MOVE main(0) dir=6 amount=5 ]
84 }
85
86 {
87 [ DIALOG enemy(0) text="???" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
88 [ MOVE main(0) dir=8 amount=3 ]
89 }
90
91 {
92 [ MOVE enemy(0) dir=6 amount=3 ]
93 [ DIALOG enemy(0) text="е-ее... Івонна,
94 Зачекай!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
95 }
96
97 {
98 [ MOVE main(0) dir=6 amount=3 ]
99 }
0 ##########################################
1 # Holotz's Castle story - Level 2
2 # Ybelle enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="Ой!" txtAlign=4 speed=5 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 }
7
8 {
9 [ DIALOG main(0) text="Боляче!" txtAlign=4 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
10 }
11
12 {
13 [ DIALOG main(0) text="ЛЮДАР!" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
14 }
15
16 {
17 [ DIALOG main(0) text="Гм..." txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=1 ]
18 }
19
20 {
21 [ DIALOG main(0) text="...схоже,
22 не чує" txtAlign=5 speed=1 size=2 align=1 r=130 g=30 b=180 subtype=0 ]
23 }
24
25 {
26 [ DIALOG main(0) text="Ну добре..." txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
27 [ MOVE main(0) dir=6 amount=1 ]
28 }
29
30 {
31 [ MOVE main(0) dir=4 amount=1 ]
32 [ DIALOG main(0) text="Для чого
33 можуть бути всі
34 ці ключі?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]}
0 ##########################################
1 # Holotz's Castle story - Level 7
2 # Ludar enters the castle
3 ##########################################
4 {
5 [ DIALOG main(0) text="... Івонна!
6 Зачекай!" txtAlign=4 speed=2 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ MOVE main(0) dir=6 amount=2 ]
8 }
9
10 {
11 [ MOVE main(0) dir=6 amount=1 ]
12 [ DIALOG main(0) text="А бодай тобі!" txtAlign=4 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
13 }
14
15 {
16 [ DIALOG main(0) text="Ну хто викопав
17 цю яму!" txtAlign=4 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
18 }
19
20 {
21 [ DIALOG main(0) text="Івонна!" txtAlign=5 speed=1 size=3 align=0 r=20 g=200 b=20 subtype=0 ]
22 }
23
24 {
25 [ DIALOG main(0) text="У-уу..." txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]
26 }
27
28 {
29 [ DIALOG main(0) text="Віслюк!" txtAlign=5 speed=1 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
30 }
31
32 {
33 [ DIALOG main(0) text="Ого!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=4 amount=1 ]
35 }
36
37 {
38 [ DIALOG main(0) text="Ці камни
39 схожі на той,
40 що взяла Івонна" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
41 [ MOVE main(0) dir=4 amount=1 ]
42 }
43
44 {
45 [ DIALOG main(0) text="Що це за місце?" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
46 }
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ybelle finds the shoe maker
3 ##########################################
4
5 {[ DIALOG main(0) text="?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="Куди я попала?" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
9
10 {[ NARRATIVE text="Чоботар" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
11 [ MOVE main(0) dir=6 amount=1 ]}
12
13 {[ MOVE main(0) dir=2 amount=3 ]}
14
15 {[ MOVE main(0) dir=6 amount=2 ]}
16
17 {[ MOVE main(0) dir=9 amount=2 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]}
20
21 {[ MOVE main(0) dir=9 amount=1 ]
22 [ DIALOG enemy(0) text="О!
23 Гості!" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=1 ]}
24
25 {[ MOVE main(0) dir=9 amount=2 ]}
26
27 {[ DIALOG main(0) text="Який
28 дивний тип!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
29 [ DIALOG enemy(0) text="Таких гостей у мене
30 ще не було!" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=1 ]
31 }
32
33 {[ DIALOG main(0) text="... Доброго дня?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
34
35 {[ DIALOG enemy(0) text="Ммм..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
36
37 {[ DIALOG enemy(0) text="Ви, мабуть,
38 прибули..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="...
41 здалеку" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(0) text="Гм..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
44 [ DIALOG main(0) text="Здається
45 він збирається
46 заснути!!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
47
48 {[ DIALOG enemy(0) text="Ви ввійшли
49 в новий..." txtAlign=5 speed=1 size=0 align=0 r=200 g=130 b=20 subtype=0 ]}
50
51 {[ DIALOG enemy(0) text="...зовсім..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
52
53 {[ DIALOG enemy(0) text="...недавно?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
54
55 {[ DIALOG main(0) text="...
56 Ви кажете новий?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
57
58 {[ DIALOG main(0) text="О так,
59 звичайно" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
60
61 {[ DIALOG main(0) text="Хто ви?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
62
63 {[ DIALOG enemy(0) text="Я..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="...Володар
66 чобіт і черевиків!" txtAlign=5 speed=1 size=2 align=0 r=200 g=130 b=20 subtype=0 ]}
67
68 {[ DIALOG enemy(0) text="Гадаю,..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
69
70 {[ DIALOG enemy(0) text="...ви
71 прийшли..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
72
73 {[ DIALOG enemy(0) text="...за новою
74 парою..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
75
76 {[ DIALOG enemy(0) text="...аджеж, так?" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
77
78 {[ DIALOG enemy(0) text="Візьміть..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]
79 [ DIALOG main(0) text="Я..." txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
80
81 {[ DIALOG enemy(0) text="...ці" txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
82
83 {[ MOVE main(0) dir=6 amount=2 ]}
84 {[ MOVE main(0) dir=4 amount=2 ]}
85
86 {[ DIALOG enemy(0) text="Звичайно..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
87
88 {[ DIALOG enemy(0) text="... в них
89 буде..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
90
91 {[ DIALOG enemy(0) text="...легче
92 бігати..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
93
94 {[ DIALOG main(0) text="Як
95 звідси
96 вибратися?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
97
98 {[ DIALOG enemy(0) text="Гм..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
99
100 {[ DIALOG enemy(0) text="...ні" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
101
102 {[ DIALOG enemy(0) text="...тільки
103 Холоц..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
104
105 {[ DIALOG enemy(0) text="...знає" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
106
107 {[ DIALOG main(0) text="Холоц?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
108
109 {[ DIALOG enemy(0) text="Да..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
110
111 {[ DIALOG enemy(0) text="Он побудував..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
112
113 {[ DIALOG enemy(0) text="...весь
114 цей замок" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
115
116 {[ DIALOG main(0) text="А де його
117 знайти?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]}
118
119 {[ DIALOG enemy(0) text="...це
120 неможливо" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
121
122 {[ DIALOG enemy(0) text="Він..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
123
124 {[ DIALOG enemy(0) text="...сам знайде тебе" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
125
126 {[ DIALOG enemy(0) text="А теперь
127 пора мені..." txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
128
129 {[ DIALOG enemy(0) text="...повернутися" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
130
131 {[ DIALOG enemy(0) text="...до роботи" txtAlign=5 speed=1 size=1 align=0 r=200 g=130 b=20 subtype=0 ]}
132
133 {[ DIALOG main(0) text="Але,... але!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
134 [ DIALOG enemy(0) text="Потрібно
135 працювати..." txtAlign=5 speed=1 size=1 align=1 r=200 g=130 b=20 subtype=0 ]}
136
137 {[ DIALOG main(0) text="Все даремно" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
138
139 {[ DIALOG main(0) text="Ну добре, я піду...
140 Спасибі за
141 черевички!" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=0 ]
142 [ MOVE main(0) dir=7 amount=2 ]}
143
144 {[ MOVE main(0) dir=7 amount=2 ]}
145
146 {[ DIALOG main(0) text="Куди ж мені
147 тепер іти?" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]}
148
149 {[ DIALOG main(0) text="Да яка різниця" txtAlign=5 speed=1 size=1 align=0 r=130 g=30 b=180 subtype=1 ]
150 [ MOVE main(0) dir=4 amount=1 ]}
151
152 {[ MOVE main(0) dir=2 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 1
2 # Ludar talks to the two flames
3 ##########################################
4
5 {[ DIALOG main(0) text="Ой!" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_UltraSlow.wav" loops=-1 waitToEnd=0 ]}
7
8 {[ DIALOG main(0) text="О! Ще один
9 камінь!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]
10 [ MOVE main(0) dir=6 amount=1 ]}
11
12 {[ NARRATIVE text="Два Вогні" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
13 [ MOVE main(0) dir=6 amount=4 ]
14 [ DIALOG main(0) text="Ще один!" txtAlign=5 speed=1 size=1 align=1 r=20 g=200 b=20 subtype=0 ]}
15
16 {[ DIALOG enemy(0) text="Стій!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
17
18 {[ DIALOG main(0) text="???" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=1 ]
19 [ MOVE main(0) dir=4 amount=1 ]}
20
21 {[ DIALOG main(0) text="Хто там?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
22 [ MOVE main(0) dir=6 amount=4 ]}
23
24 {[ DIALOG enemy(0) text="Я сказав
25 СТІЙ!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
26
27 {[ MOVE main(0) dir=4 amount=4 ]
28 [ DIALOG main(0) text="Ого, балакаючий
29 вогник!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=1 ]}
30
31 {[ DIALOG enemy(0) text="Я не балакаючий
32 вогник!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]
33 [ DIALOG main(0) text="Ой!" txtAlign=5 speed=4 size=2 align=0 r=20 g=200 b=20 subtype=0 ]
34 [ MOVE main(0) dir=6 amount=2 ]}
35
36 {[ DIALOG enemy(0) text="Я глаголяще
37 полум'я!" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
38
39 {[ DIALOG main(0) text="Звідки
40 ти знаєшь, що
41 я думаю?" txtAlign=5 speed=5 size=2 align=1 r=20 g=200 b=20 subtype=0 ]}
42
43 {[ DIALOG enemy(0) text="Я знаю
44 все!" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
45
46 {[ DIALOG enemy(1) text="Хм..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="Ну або майже
49 все" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
50
51 {[ DIALOG enemy(1) text="Він
52 читає думки..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
53
54 {[ DIALOG enemy(1) text="і книги..." txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
55
56 {[ DIALOG enemy(1) text="...книги" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
57
58 {[ DIALOG enemy(1) text="Буль, буль, буль!" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]
59 [ DIALOG enemy(0) text="Муль, муль, муль!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]
60 [ DIALOG main(0) text="??!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
61
62 {[ DIALOG enemy(1) text="Як ти сюди
63 потрапив?" txtAlign=5 speed=1 size=3 align=1 r=200 g=20 b=60 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="Я не знаю..." txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
66
67 {[ DIALOG main(0) text="Воно збирається
68 прочитати мої думки!" txtAlign=5 speed=1 size=1 align=0 r=20 g=200 b=20 subtype=1 ]}
69
70 {[ DIALOG enemy(0) text="Через
71 магічну
72 браму!!" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=0 ]}
73
74 {[ DIALOG enemy(1) text="Буль, буль, буль!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
75 [ DIALOG enemy(0) text="Муль, муль, муль!" txtAlign=5 speed=1 size=3 align=0 r=20 g=20 b=180 subtype=0 ]
76 [ DIALOG main(0) text="Біс його побери!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
77 [ MOVE main(0) dir=6 amount=4 ]}
78
79 {[ DIALOG enemy(1) text="Чекай, не
80 йди" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
81 [ MOVE main(0) dir=4 amount=5 ]}
82
83 {[ DIALOG main(0) text="Мені
84 не до
85 жартів!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
86 [ MOVE main(0) dir=6 amount=2 ]}
87
88 {[ DIALOG enemy(0) text="Що тобі
89 потрібно?" txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]
90 [ MOVE main(0) dir=4 amount=3 ]}
91
92 {[ DIALOG main(0) text="Я хочу знайти
93 Івонну" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
94
95 {[ DIALOG main(0) text="Ми повинні
96 повернутися в
97 країнуну
98 Лізарнію" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
99
100 {[ DIALOG enemy(0) text="А... лізарнійці,...
101 як цікаво" txtAlign=5 speed=1 size=1 align=1 r=20 g=20 b=180 subtype=1 ]}
102
103 {[ DIALOG enemy(1) text="Тепер
104 замок
105 стане" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
106
107 {[ DIALOG enemy(1) text="небезпечніше" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
108
109 {[ DIALOG enemy(1) text="а в тебв не
110 вистачить магічної
111 сили" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
112
113 {[ DIALOG enemy(1) text="щоб дістатися
114 до самого верху" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
115
116 {[ DIALOG enemy(0) text="Точно! Тобі
117 потрібна..." txtAlign=5 speed=1 size=3 align=1 r=20 g=20 b=180 subtype=0 ]}
118
119 {[ DIALOG enemy(1) text="пара
120 чобіт!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
121 [ DIALOG enemy(0) text="пара
122 чобіт!" txtAlign=5 speed=1 size=1 align=0 r=20 g=20 b=180 subtype=0 ]}
123
124 {[ DIALOG main(0) text="Досить
125 насміхатися!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
126 [ MOVE main(0) dir=4 amount=2 ]}
127
128 {[ DIALOG enemy(0) text="Але отримати їх ти
129 можешь тільки від" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
130
131 {[ DIALOG enemy(0) text="Пана
132 чоботаря" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
133
134 {[ DIALOG main(0) text="А є ще якийсь
135 спосіб дістати ці
136 ваші чоботи?" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
137 [ MOVE main(0) dir=6 amount=2 ]}
138
139 {[ DIALOG enemy(1) text="Є. Ïх ще
140 можливо дістати в" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=60 subtype=0 ]}
141
142 {[ DIALOG enemy(1) text="Лавці!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=60 subtype=0 ]
143 [ DIALOG enemy(0) text="Лавці!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]}
144
145 {[ DIALOG enemy(1) text="Буль, буль, буль!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=60 subtype=0 ]
146 [ DIALOG enemy(0) text="Муль, муль, муль!" txtAlign=5 speed=1 size=2 align=0 r=20 g=20 b=180 subtype=0 ]
147 [ DIALOG main(0) text="Це вже зовсім
148 нестерпно!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
149 [ MOVE main(0) dir=6 amount=4 ]}
150
151 {[ DIALOG enemy(1) text="Зачекай" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]
152 [ MOVE main(0) dir=4 amount=2 ]}
153
154 {[ DIALOG enemy(1) text="Ти можеш
155 знайти чоботи" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
156
157 {[ DIALOG enemy(1) text="в кімнаті
158 за цими
159 магічними воротами!" txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
160
161 {[ DIALOG enemy(0) text="Але знай," txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
162
163 {[ DIALOG enemy(0) text="що ще ніхто
164 не повертався звідти живим" txtAlign=5 speed=1 size=2 align=1 r=20 g=20 b=180 subtype=0 ]}
165
166 {[ DIALOG main(0) text="Ого!" txtAlign=5 speed=5 size=1 align=1 r=20 g=200 b=20 subtype=1 ]
167 [ MOVE main(0) dir=6 amount=2 ]}
168
169 {[ DIALOG main(0) text="Гм... Я все-таки
170 повинен спробувати" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
171 [ MOVE main(0) dir=4 amount=2 ]}
172
173 {[ DIALOG main(0) text="Але я ж
174 не можу відкрити
175 ворота" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]
176 [ MOVE main(0) dir=4 amount=2 ]}
177
178 {[ DIALOG main(0) text="Цей камінь
179 занадто високо!" txtAlign=5 speed=5 size=1 align=0 r=20 g=200 b=20 subtype=0 ]}
180
181 {[ DIALOG enemy(1) text="Добре, візьми
182 цю драбину." txtAlign=5 speed=1 size=1 align=0 r=200 g=20 b=60 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 19
2 # Ybelle is captured
3 ##########################################
4
5 {[ DIALOG main(0) text="Ааа!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ SOUND file="sound/HCMainTitle_Fast.wav" loops=0 waitToEnd=0 ]}
7
8 {[ MOVE enemy(0) dir=8 amount=4 ]
9 [ MOVE enemy(1) dir=8 amount=4 ]
10 [ MOVE enemy(2) dir=4 amount=2 ]
11 [ MOVE enemy(3) dir=6 amount=2 ]
12 [ MOVE enemy(4) dir=4 amount=5 ]
13 [ MOVE enemy(5) dir=6 amount=5 ]
14 [ DIALOG main(0) text="Ой, ой" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=1 ]
15 [ DIALOG enemy(2) text="!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=1 ]
16 [ DIALOG enemy(3) text="!" txtAlign=5 speed=1 size=2 align=0 r=220 g=20 b=20 subtype=1 ]}
17
18 {[ NARRATIVE text="
19 ДАЛІ БУДЕ...
20 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
21 [ DIALOG main(0) text="??!" txtAlign=5 speed=3 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=5 amount=1 ]}
23
24 {[ DIALOG main(0) text="Ааа!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
25 [ MOVE main(0) dir=5 amount=2 ]}
26
27 {[ DIALOG main(0) text="Не залишай мене!" txtAlign=5 speed=1 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
28 [ MOVE main(0) dir=5 amount=2 ]}
29
30 {[ WAIT millis=3000]}
0 ##########################################
1 # Holotz's Castle story - Level 20
2 # Ybelle is captured (continued)
3 ##########################################
4
5 {[ MOVE enemy(0) dir=8 amount=0 ]
6 [ MOVE enemy(1) dir=8 amount=0 ]
7 [ MOVE enemy(2) dir=4 amount=0 ]
8 [ MOVE enemy(3) dir=6 amount=0 ]
9 [ MOVE enemy(4) dir=4 amount=0 ]
10 [ MOVE enemy(5) dir=6 amount=0 ]}
11
12 {[ WAIT millis=1000]}
13
14 {[ DIALOG main(0) text="Ані руш!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
15 [ MOVE main(0) dir=4 amount=1 ]}
16
17 {[ DIALOG enemy(0) text="Угх Угх" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]
18 [ DIALOG enemy(1) text="Мммм" txtAlign=5 speed=5 size=3 align=0 r=200 g=20 b=20 subtype=0 ]}
19
20 {[ DIALOG main(0) text="Попереджаю,
21 я небезпечна!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]
22 [ MOVE main(0) dir=6 amount=2 ]}
23
24 {[ MOVE enemy(1) dir=4 amount=3 ]
25 [ DIALOG enemy(1) text="Дивися..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
26
27 {[ MOVE enemy(1) dir=4 amount=1 ]
28 [ DIALOG enemy(5) text="Що?" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
29
30 {[ DIALOG enemy(1) text="В неї чобітки" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
31
32 {[ DIALOG enemy(5) text="Гм...
33 Холоцу це б
34 не сподобалося" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
35
36 {[ DIALOG main(0) text="Чого вам треба?" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
37
38 {[ MOVE enemy(5) dir=6 amount=4 ]
39 [ MOVE main(0) dir=6 amount=1 ]
40 [ DIALOG enemy(5) text="Відповідай!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
41
42 {[ DIALOG enemy(5) text="Що ти тут
43 робиш?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
44
45 {[ DIALOG main(0) text="Я взяла
46 камінь і..." txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
47
48 {[ DIALOG enemy(5) text="І відкрилася магічна
49 брама, так?." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
50
51 {[ DIALOG main(0) text="Да, точно!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
52
53 {[ DIALOG enemy(5) text="Схоже, що
54 черговий дослід Холоца" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
55
56 {[ DIALOG enemy(5) text="не вдався" txtAlign=5 speed=1 size=2 align=0 r=200 g=20 b=20 subtype=1 ]}
57
58 {[ DIALOG enemy(5) text="Дивно
59 як ти сюди
60 пробралася..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
61
62 {[ DIALOG enemy(4) text="Що будемо з
63 нею робити?" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
64
65 {[ DIALOG enemy(5) text="Як сказав Лорд
66 Холоц..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
67
68 {[ DIALOG enemy(5) text="...відправимо до
69 лабиринту
70 Фроя" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
71
72 {[ DIALOG enemy(5) text="Посидить там,
73 доки Господар не вирішить,
74 що з нею робити..." txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
75
76 {[ DIALOG enemy(5) text="...якщо чотири
77 божевільний брата
78 не знайдуть її раніше" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
79
80 {[ DIALOG enemy(1) text="Ха-ха-ха!" txtAlign=5 speed=1 size=1 align=1 r=200 g=20 b=20 subtype=0 ]
81 [ DIALOG enemy(2) text="Хи-хи-хи-хи!" txtAlign=5 speed=1 size=2 align=1 r=200 g=20 b=20 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 25
2 # Holotz appears
3 ##########################################
4
5 {
6 [ SOUND file="sound/HCMainTitle_Slow.wav" loops=-1 waitToEnd=0 ]
7 [ NARRATIVE text="Лорд Холоц" txtAlign=5 speed=1 size=3 align=7 r=128 g=20 b=20 subtype=0 ]
8 }
9
10 {[ MOVE enemy(0) dir=9 amount=2 ]}
11
12 {[ MOVE main(0) dir=4 amount=2 ]
13 [ DIALOG main(0) text="Ім'ям
14 Хутазина!..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
15
16 {[ MOVE enemy(0) dir=9 amount=1 ]}
17 {[ MOVE enemy(0) dir=9 amount=1 ]}
18
19 {[ MOVE main(0) dir=6 amount=3 ]
20 [ DIALOG main(0) text="Ворота стихій,
21 відчиніться!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
22
23 {[ MOVE enemy(0) dir=9 amount=1 ]}
24
25 {[ WAIT millis=3000 ]}
26
27 {[ DIALOG main(0) text="..." txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
28
29 {[ MOVE main(0) dir=5 amount=1 ]
30 [ DIALOG main(0) text="Знову не
31 спрацювало!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
32
33 {[ MOVE main(0) dir=4 amount=2 ]
34 [ MOVE enemy(0) dir=9 amount=1 ]
35 [ DIALOG main(0) text="Тиы!" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
36
37 {[ DIALOG main(0) text="Де
38 лізарнітка?" txtAlign=5 speed=5 size=3 align=1 r=80 g=80 b=200 subtype=0 ]}
39
40 {[ DIALOG enemy(0) text="Ми її відправили
41 до лабіринту Фроя,
42 як ви наказали" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
43
44 {[ DIALOG main(0) text="Добре" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
45
46 {[ DIALOG enemy(0) text="Але знайте, господарю," txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
47
48 {[ DIALOG enemy(0) text="що у неї були
49 чобітки" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
50
51 {[ DIALOG main(0) text="Ідиот!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
52
53 {[ DIALOG main(0) text="Холоп!
54 Як ти посмів
55 приховувати це!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
56
57 {[ DIALOG enemy(0) text="Я..." txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
58
59 {[ DIALOG main(0) text="З такою жвавістю вона вже
60 могла досягнути вежі!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
61
62 {[ DIALOG main(0) text="Випустити всіх
63 монстрів!" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
64
65 {[ DIALOG enemy(0) text="Слухаю і підкоряюсь" txtAlign=5 speed=5 size=3 align=1 r=200 g=20 b=20 subtype=0 ]}
66
67 {[ MOVE enemy(0) dir=7 amount=2 ]}
68
69 {[ MOVE enemy(0) dir=7 amount=3 ]
70 [ DIALOG main(0) text="Зараз ми зробимо
71 цим лізарнійцям
72 сюрприз" txtAlign=5 speed=5 size=3 align=1 r=130 g=30 b=180 subtype=0 ]}
0 ##########################################
1 # Holotz's Castle story - Level 30
2 # Ybelle and Ludar met again
3 ##########################################
4
5 {[ SOUND file="sound/HCCredits_Slow.wav" loops=-1 waitToEnd=0 ]}
6
7 {[ MOVE main(0) dir=8 amount=6 ]
8 [ MOVE enemy(0) dir=8 amount=6 ]
9 [ MOVE enemy(1) dir=8 amount=6 ]
10 [ MOVE enemy(2) dir=8 amount=6 ]}
11
12 {[ MOVE main(0) dir=6 amount=3 ]
13 [ MOVE enemy(0) dir=4 amount=3 ]
14 [ MOVE enemy(1) dir=8 amount=4 ]
15 [ MOVE enemy(2) dir=8 amount=4 ]}
16
17 {[ MOVE main(0) dir=6 amount=4 ]
18 [ MOVE enemy(0) dir=4 amount=4 ]
19 [ MOVE enemy(1) dir=4 amount=3 ]
20 [ MOVE enemy(2) dir=6 amount=3 ]}
21
22 {[ DIALOG main(0) text="Людар!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
23 [ DIALOG enemy(0) text="Івонна!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
24
25 {[ DIALOG main(0) text="Ти жива!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]
26 [ DIALOG enemy(0) text="І ти цілий!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
27
28 {[ DIALOG enemy(0) text="Тепер ми
29 будемо разом!" txtAlign=5 speed=5 size=3 align=0 r=130 g=30 b=180 subtype=0 ]}
30
31 {[ DIALOG enemy(0) text="До сходів,
32 давай за мною!" txtAlign=5 speed=5 size=3 align=1 r=20 g=200 b=20 subtype=0 ]}
33
34 {[ MOVE main(0) dir=8 amount=3 ]
35 [ MOVE enemy(0) dir=8 amount=3 ]}
0 ##########################################
1 # Holotz's Castle story - Level 32
2 # Return to the land of Lizarno
3 ##########################################
4
5 {[ DIALOG main(0) text="А-аа!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
6 [ DIALOG enemy(0) text="Ааа!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
7 [ SOUND file="sound/HCCredits.wav" loops=-1 waitToEnd=0 ]}
8
9 {[ DIALOG main(0) text="Це ж наша Лізарнія!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
10
11 {[ DIALOG enemy(0) text="Ми дома!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
12
13 {[ DIALOG main(0) text="Дивись-но,
14 ще камінь!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]
15 [ MOVE main(0) dir=4 amount=2 ]}
16
17 {[ DIALOG enemy(0) text="Не чіпай!!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
18
19 {[ MOVE main(0) dir=4 amount=2 ]}
0 ##########################################
1 # Holotz's Castle story - Level 33
2 # The end
3 ##########################################
4
5 {[ DIALOG enemy(0) text="Ааа!" txtAlign=5 speed=1 size=2 align=1 r=20 g=200 b=20 subtype=0 ]
6 [ DIALOG main(0) text="Ой!" txtAlign=5 speed=1 size=1 align=1 r=130 g=30 b=180 subtype=0 ]}
7
8 {
9 [ NARRATIVE text="
10 КОНЕЦ
11 " txtAlign=5 speed=1 size=3 align=5 r=128 g=20 b=20 subtype=0 ]
12 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Break floor definition file.
23 * @file HCBreak.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 30/04/2004
26 * @version 0.0.1 - 30/04/2004 - First version.
27 */
28
29 #include <HCBreak.h>
30
31 s32 HCBreak::Update()
32 {
33 switch (state)
34 {
35 case HCBREAKSTATE_NORMAL:
36 normal.Update();
37 return 0;
38
39 case HCBREAKSTATE_BREAKING:
40 if (-1 == breaking.Update())
41 {
42 // If the breaking state has ended, places it in a non-drawable state
43 state = HCBREAKSTATE_BROKEN;
44
45 // and let the characters fall through it
46 actionMask |= HCACTION_FALL | HCACTION_LEFT | HCACTION_RIGHT;
47 }
48 return 1;
49
50 case HCBREAKSTATE_BROKEN:
51 default:
52 // Finished with this break
53 return -1;
54 }
55 }
56
57 void HCBreak::Draw()
58 {
59 switch (state)
60 {
61 case HCBREAKSTATE_NORMAL:
62 normal.Draw();
63 break;
64
65 case HCBREAKSTATE_BREAKING:
66 breaking.Draw();
67 break;
68
69 default:
70 break;
71 }
72 }
73
74 void HCBreak::Break()
75 {
76 state = HCBREAKSTATE_BREAKING;
77 breaking.Pos(pos.x, pos.y);
78
79 if (prev && prev->State() == HCBREAKSTATE_NORMAL)
80 {
81 prev->Break();
82 }
83
84 if (next && next->State() == HCBREAKSTATE_NORMAL)
85 {
86 next->Break();
87 }
88 }
89
90 void HCBreak::Pos(float xPos, float yPos)
91 {
92 pos.x = xPos;
93 pos.y = yPos;
94 switch (state)
95 {
96 case HCBREAKSTATE_NORMAL:
97 normal.Pos(xPos, yPos);
98 break;
99
100 case HCBREAKSTATE_BREAKING:
101 breaking.Pos(xPos, yPos);
102 break;
103
104 case HCBREAKSTATE_BROKEN:
105 default:
106 broken.Pos(xPos, yPos);
107 break;
108 }
109 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Break Floor floor definition file.
23 * @file HCBreak.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 30/04/2004
26 * @version 0.0.1 - 30/04/2004 - First version.
27 */
28
29 #ifndef _HCBREAK_INCLUDED
30 #define _HCBREAK_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Graphics/JImageSprite.h>
34 #include <HCCell.h>
35
36 /** Object state.
37 */
38 typedef enum
39 {
40 HCBREAKSTATE_NORMAL = 0, /**< Normal, visible state. */
41 HCBREAKSTATE_BREAKING, /**< Breaking, visible state. */
42 HCBREAKSTATE_BROKEN, /**< Non visible state. */
43 } HCBreakState;
44
45 /** Break Floor class. Defines an break floor of the game and its behaviour.
46 */
47 class HCBreak : public HCCell
48 {
49 protected:
50 HCBreakState state; /**< Break Floor state. */
51 JImageSprite *cur; /**< Current sprite for this break floor. */
52 JImageSprite normal; /**< Normal sprite to show for the break. */
53 JImageSprite breaking; /**< Sprite to show when the floor is breaking. */
54 JImageSprite broken; /**< Sprite to show when the floor is broken. */
55 HCBreak *prev; /**< Previous break floor, 0 if no more. */
56 HCBreak *next; /**< Next break floor, 0 if no more. */
57
58 public:
59 /** Creates a new break floor in the HCBREAKSTATE_NORMAL state.
60 */
61 HCBreak(JImageSprite *states, HCBreak *_prev = 0)
62 :
63 HCCell(HCCELLTYPE_BREAK, 0), state(HCBREAKSTATE_NORMAL), cur(0), prev(_prev), next(0)
64 {
65 normal.Ref(states[HCBREAKSTATE_NORMAL]);
66 breaking.Ref(states[HCBREAKSTATE_BREAKING]);
67 broken.Ref(states[HCBREAKSTATE_BROKEN]);
68
69 if (prev)
70 {
71 prev->next = this;
72 }
73
74 cur = &normal;
75 }
76
77 /** Updates the break floor.
78 * @return 0 If it's in HCBREAKSTATE_NORMAL, 1 if in HCBREAKSTATE_BREAKING,
79 * -1 if in HCBREAKSTATE_NONE state, which means that the break floor has been broken.
80 */
81 virtual s32 Update();
82
83 /** Draws the break floor.
84 */
85 virtual void Draw();
86
87 /** Places this break floor in the breaking state.
88 */
89 void Break();
90
91 /** Positions this cell.
92 * @param xPos New x coordinate.
93 * @param yPos New y coordinate.
94 */
95 virtual void Pos(float xPos, float yPos);
96
97 /** Returns the state of this break floor.
98 * @return The state of this break floor.
99 */
100 HCBreakState State() {return state;}
101
102 /** Destroys the break.
103 */
104 virtual ~HCBreak()
105 {}
106 };
107
108 #endif // _HCBREAK_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Cell definition file.
23 * @file HCCell.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 30/04/2004
26 * @version 0.0.1 - 30/04/2004 - First version.
27 */
28
29 #ifndef _HCCELL_INCLUDED
30 #define _HCCELL_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Graphics/JDrawable.h>
34 #include <JLib/Graphics/JImage.h>
35 #include <JLib/Graphics/JImageSprite.h>
36
37 /** Cell types.
38 */
39 typedef enum
40 {
41 HCCELLTYPE_BLANK = 0, /**< Blank cell. */
42 HCCELLTYPE_FLOOR, /**< Floor cell. */
43 HCCELLTYPE_CONTFLOOR, /**< Continuous floor cell. */
44 HCCELLTYPE_LADDER, /**< Ladder cell. */
45 HCCELLTYPE_BAR, /**< Firefighter bar cell. */
46 HCCELLTYPE_BREAK, /**< Breakable floor cell. */
47 } HCCellType;
48
49 /** Actions allowed in a cell.
50 */
51 typedef enum
52 {
53 HCACTION_UP = 1, /**< Go up. */
54 HCACTION_DOWN = 2, /**< Go down. */
55 HCACTION_LEFT = 4, /**< Go left. */
56 HCACTION_RIGHT = 8, /**< Go right. */
57 HCACTION_FALL = 16, /**< Fall. */
58 HCACTION_SLIDE = 32, /**< Slide. */
59 } HCAction;
60
61 /** Generic 2D blank cell.
62 */
63 class HCCell : public JDrawable
64 {
65 protected:
66 HCCellType type; /**< Type of this cell. */
67 s32 subtype; /**< Subtype of this cell. */
68 u32 actionMask; /**< Mask of allowed actions within this cell. */
69
70 public:
71 /** Creates an empty cell of type HCCELLTYPE_BLANK by default and
72 * movement to the sides, down and falling as actions allowed.
73 */
74 HCCell(HCCellType t = HCCELLTYPE_BLANK, u32 actions = HCACTION_FALL | HCACTION_LEFT | HCACTION_RIGHT)
75 : type(t), subtype(0), actionMask(actions)
76 {}
77
78 /** Returns the mask of allowed actions for this cell.
79 * @return the mask of allowed actions for this cell.
80 */
81 u32 Actions()
82 {
83 return actionMask;
84 }
85
86 /** Enables the specified actions over this cell.
87 * @param actions OR'ed combination of the actions to allow for this cell.
88 */
89 void Enable(u32 actions)
90 {
91 actionMask |= actions;
92 }
93
94 /**Disables the specified actions over this cell.
95 * @param actions OR'ed combination of the actions to allow for this cell.
96 */
97 void Disable(u32 actions)
98 {
99 actionMask &= ~(actions);
100 }
101
102 /** Gets the type of this cell.
103 * @return Type of this cell.
104 */
105 const HCCellType & Type() {return type;}
106
107 /** Sets the type of this cell.
108 * @param newType New type of this cell.
109 */
110 void Type(const HCCellType &newType) {type = newType;}
111
112 /** Gets the subtype of this cell.
113 * @return Subtype of this cell.
114 */
115 s32 Subtype() {return subtype;}
116
117 /** Sets the subtype of this cell.
118 * @param newSubtype New type of this cell.
119 */
120 void Subtype(s32 newSubtype) {subtype = newSubtype;}
121
122 /** Destroys the object.
123 */
124 virtual ~HCCell()
125 {}
126 };
127
128 class HCDrawableCell : public HCCell
129 {
130 protected:
131 JImage drawable; /**< Graphical representation of the cell. */
132
133 public:
134 /** Creates the cell.
135 */
136 HCDrawableCell(HCCellType t, JImage *d, u32 actions = HCACTION_LEFT | HCACTION_RIGHT) : HCCell(t, actions)
137 {
138 if (d)
139 drawable.Ref(*d);
140 }
141
142 /** Draws the cell.
143 */
144 virtual void Draw() {drawable.Draw();}
145
146 /** Positions this cell.
147 * @param xPos New x coordinate.
148 * @param yPos New y coordinate.
149 */
150 virtual void Pos(float xPos, float yPos)
151 {pos.x = xPos; pos.y = yPos; drawable.Pos(xPos, yPos);}
152
153 /** Destroys the cell.
154 */
155 virtual ~HCDrawableCell()
156 {}
157 };
158
159 /** Represents a simple floor or wall
160 */
161 class HCFloorCell : public HCDrawableCell
162 {
163 public:
164 HCFloorCell(JImage *d, u32 actions = 0) : HCDrawableCell(HCCELLTYPE_FLOOR, d, actions)
165 {}
166
167 virtual ~HCFloorCell() {}
168 };
169
170 /** Represents a bar
171 */
172 class HCBarCell : public HCDrawableCell
173 {
174 public:
175 HCBarCell(JImage *d, u32 actions = HCACTION_SLIDE | HCACTION_DOWN | HCACTION_LEFT | HCACTION_RIGHT) : HCDrawableCell(HCCELLTYPE_BAR, d, actions)
176 {}
177
178 virtual ~HCBarCell() {}
179 };
180
181 /** Represents a ladder
182 */
183 class HCLadderCell : public HCDrawableCell
184 {
185 public:
186 HCLadderCell(JImage *d, u32 actions = HCACTION_UP | HCACTION_DOWN | HCACTION_LEFT | HCACTION_RIGHT) : HCDrawableCell(HCCELLTYPE_LADDER, d, actions)
187 {}
188
189 virtual ~HCLadderCell() {}
190 };
191
192 #endif // _HCCELL_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Holotz's Castle main character definition file.
23 * @file HCCharacter.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 30/04/2004
26 * @version 0.0.1 - 30/04/2004 - First version.
27 */
28
29 #include <HCCharacter.h>
30
31 HCCharacter::HCCharacter()
32 {
33 state = HCCS_STOP;
34 actions = 0;
35 lastAction = 0;
36 maxFallRows = 2;
37 startJumpRow = -1;
38 maxJumpRows = 0;
39 maxJumpCols = 0;
40 v.x = v.y = 0.0f;
41 a.x = a.y = 0.0f;
42 vMax.x = 5.0f;
43 vMax.y = 9.0f;
44 vJumpMax.x = vMax.x;
45 vJumpMax.y = 0.0f;
46 aMax.x = vMax.x;
47 aMax.y = vMax.y;
48
49 breakRow = -1;
50 trackRope = 0;
51 dialog = 0;
52 subtype = 0;
53 }
54
55 bool HCCharacter::Init(JImageSprite *sprites, HCMap *_map, HCRope **_ropes, s32 nRopes)
56 {
57 if (0 == sprites)
58 {
59 fprintf(stderr, "No sprites for character.\n");
60
61 return false;
62 }
63
64 if (0 == _map)
65 {
66 fprintf(stderr, "No map for character.\n");
67
68 return false;
69 }
70
71 // References the themes' sprites
72 for (s32 i = 0; i < HCCS_COUNT; ++i)
73 {
74 states[i].Ref(sprites[i]);
75 }
76
77 a.x = v.x = a.y = v.y = 0.0f;
78 map = _map;
79 ropes = _ropes;
80 numRopes = nRopes;
81
82 // Sets the number of rows for jump and computes the jump velocitty
83 MaxJumpRows(maxJumpRows);
84
85 // Sets hanging parameters depending on the largest frame of the jump left sprites
86 // Sets the hang hotspot at the middle of the largest frame, the width and height
87 // are half the maximun of either the width or the height
88 s32 max = 0;
89 for (u32 i = 0; i < sprites[HCCS_JUMPLEFT].NumFrames(); ++i)
90 {
91 max = (s32)JMax(max, ((JImage *)sprites[HCCS_JUMPLEFT].Frame(i))->Width());
92 max = (s32)JMax(max, ((JImage *)sprites[HCCS_JUMPLEFT].Frame(i))->Height());
93 }
94
95 hangCheckYOffset = max/2;
96 hangCheckSize = max/2;
97
98 return true;
99 }
100
101 void HCCharacter::MaxJumpRows(s32 newMaxJumpRows)
102 {
103 maxJumpRows = newMaxJumpRows;
104 JClamp(maxJumpRows, 0, map->Rows());
105
106 // Simulates a jump to determine the veloccity in Y.
107 s32 curJumpRows = 0;
108 vJumpMax.y = 0.0f;
109 float vx = vJumpMax.x, x = 0.0f, firstVy = 0.0f, lastVy = 0.0f, dy = float(map->CellHeight())/200.0f;
110 bool first = true;
111
112 while (curJumpRows <= maxJumpRows)
113 {
114 vJumpMax.y += dy;
115 float vy = -vJumpMax.y, y = 0.0f;
116 vx = vJumpMax.x;
117 x = 0.0f;
118 maxJumpCols = curJumpRows = 0;
119
120 while (y <= 0.0f)
121 {
122 vy += map->Gravity();
123
124 if (vy > vJumpMax.y)
125 {
126 vy = vJumpMax.y;
127 }
128
129 x += vx;
130 y += vy;
131 curJumpRows = (s32)JMax(curJumpRows, -y/map->CellHeight());
132 }
133
134 // Check the first and last v.y's that allow a vertical jump of maxJumpRows cells.
135 if (curJumpRows == maxJumpRows)
136 {
137 if (first)
138 {
139 first = false;
140 firstVy = vJumpMax.y;
141 }
142
143 lastVy = vJumpMax.y;
144 }
145 }
146
147 vJumpMax.y = firstVy + ((lastVy - firstVy)/2.0f);
148
149 // This is only informative for, perhaps, the child classes but includes it also
150 maxJumpCols = (s32)x/map->CellWidth();
151
152 // This is the maximum number of rows before starting to fall (and before the player
153 // has no control over the character, except if it hangs to a rope during the fall).
154 // If falling and the floor is reached, the character dies.
155 maxFallRows = maxJumpCols * 2;
156 }
157
158 void HCCharacter::Draw()
159 {
160 states[state].Draw();
161
162 if (dialog != 0)
163 {
164 dialog->Draw();
165 }
166
167 // SDL_Rect rc;
168 // rc.x = map->ToX(map->ToCol((s32)pos.x)) - 1;
169 // rc.y = map->ToY(map->ToRow((s32)pos.y)) - (map->CellHeight()/2 - 1);
170 // rc.w = 3;
171 // rc.h = 3;
172
173 // SDL_FillRect(SDL_GetVideoSurface(), &rc, 0xffffffff);
174 }
175
176 s32 HCCharacter::Update()
177 {
178 states[state].Update();
179
180 if (state == HCCS_HANG)
181 {
182 UpdateHang();
183 }
184 else
185 {
186 UpdateVeloccity();
187 CheckHang();
188 }
189
190 // Collisions
191 UpdateCollisions();
192 CheckBrokenFloor();
193
194 Pos(pos.x + v.x, pos.y + v.y);
195
196 // Updates dialogs
197 UpdateDialog();
198
199 return 0;
200 }
201
202 void HCCharacter::UpdateVeloccity()
203 {
204 v.x += a.x;
205 v.y += a.y + map->Gravity();
206
207 if (v.x > vMax.x)
208 {
209 v.x = vMax.x;
210 }
211 else
212 if (v.x < -vMax.x)
213 {
214 v.x = -vMax.x;
215 }
216
217 switch (state)
218 {
219 case HCCS_JUMPLEFT:
220 case HCCS_JUMPRIGHT:
221 case HCCS_JUMP:
222 // Falling veloccity limited to the cell height - 1
223 if (v.y > 0.0f)
224 {
225 if (v.y > map->CellHeight() - 1)
226 {
227 v.y = map->CellHeight() - 1;
228 }
229 }
230 else
231 if (v.y < -vJumpMax.y)
232 {
233 v.y = -vJumpMax.y;
234 }
235 break;
236
237 case HCCS_DIE:
238 v.x = a.x = 0.0f;
239 if (v.y > vMax.y)
240 {
241 v.y = vMax.y;
242 }
243 else
244 if (v.y < -vMax.y)
245 {
246 v.y = -vMax.y;
247 }
248 break;
249
250 default:
251 if (v.y > vMax.y)
252 {
253 v.y = vMax.y;
254 }
255 else
256 if (v.y < -vMax.y)
257 {
258 v.y = -vMax.y;
259 }
260 break;
261 }
262 }
263
264 void HCCharacter::UpdateCollisions()
265 {
266 float newX = pos.x + v.x;
267 float newY = pos.y + v.y;
268 s32 row = map->ToRow((s32)pos.y), col = map->ToCol((s32)pos.x);
269 s32 newCol = map->ToCol((s32)(newX));
270 s32 newRow = map->ToRow((s32)(newY));
271
272 switch (map->Cell(row, newCol)->Type())
273 {
274 case HCCELLTYPE_FLOOR:
275 case HCCELLTYPE_CONTFLOOR:
276 v.x = 0.0f;
277 break;
278
279 case HCCELLTYPE_BREAK:
280 if (((HCBreak *)map->Cell(row, newCol))->State() == HCBREAKSTATE_NORMAL)
281 {
282 v.x = 0.0f;
283 }
284 break;
285
286 default:
287 col = newCol;
288 break;
289 }
290
291 switch (map->Cell(newRow, col)->Type())
292 {
293 case HCCELLTYPE_LADDER:
294 case HCCELLTYPE_BAR:
295
296 // New cell is a ladder or a bar
297 switch (state)
298 {
299 case HCCS_UP:
300 case HCCS_DOWN:
301 case HCCS_SLIDE:
302 // In this states do nothing
303 break;
304
305 case HCCS_JUMPLEFT:
306 case HCCS_JUMPRIGHT:
307 case HCCS_JUMP:
308 if (newRow > row && map->Cell(row, col)->Type() == HCCELLTYPE_BLANK)
309 {
310 // Falls over a ladder or bar, must stop
311 v.y = 0.0f;
312 state = HCCS_STOP;
313 FixY(row);
314 }
315 break;
316
317 case HCCS_DIE:
318 if (newRow > row && map->Cell(row, col)->Type() == HCCELLTYPE_BLANK)
319 {
320 // Falls over a ladder or bar, must stop
321 v.y = 0.0f;
322 }
323 break;
324
325 default:
326 // In any other state, stops the character
327 v.y = 0.0f;
328 break;
329 }
330 break;
331
332 default:
333 if ((map->Cell(newRow, col)->Actions() & HCACTION_FALL) == 0)
334 {
335 v.y = 0.0f;
336
337 switch (state)
338 {
339 // If jumping, must stop
340 case HCCS_JUMPLEFT:
341 case HCCS_JUMPRIGHT:
342 case HCCS_JUMP:
343 if (newRow > row)
344 {
345 // Stands over the floor
346 state = HCCS_STOP;
347 FixY(row);
348 }
349 else
350 if (newRow == row)
351 {
352 // Stands over the floor above
353 state = HCCS_STOP;
354 FixY(row - 1);
355 }
356 break;
357
358 case HCCS_DOWN:
359 case HCCS_SLIDE:
360 state = HCCS_STOP;
361 FixY(row);
362 break;
363
364 case HCCS_DIE:
365 if (newRow > row)
366 {
367 // Stands over the floor
368 FixY(row);
369 }
370 break;
371
372 default:
373 break;
374 }
375 }
376 else
377 {
378 if (newRow > row &&
379 state != HCCS_JUMP &&
380 state != HCCS_JUMPLEFT &&
381 state != HCCS_JUMPRIGHT &&
382 state != HCCS_DIE)
383 {
384 State(HCCS_JUMP);
385 }
386 }
387 break;
388 }
389 }
390
391 void HCCharacter::UpdateDialog()
392 {
393 if (dialog != 0)
394 {
395 dialog->Update();
396 }
397 }
398
399 void HCCharacter::CheckBrokenFloor()
400 {
401 // Checks for broken floor
402 if (breakRow != -1)
403 {
404 s32 row = map->ToRow((s32)pos.y + map->CellHeight()/2);
405 s32 col = map->ToCol((s32)pos.x);
406
407 // Inside a break, got out?
408 if (map->Cell(row, col)->Type() != HCCELLTYPE_BREAK || ((HCBreak *)map->Cell(row, col))->State() != HCBREAKSTATE_NORMAL)
409 {
410 // Got out!
411 ((HCBreak *)map->Cell(breakRow, breakCol))->Break();
412 breakRow = -1;
413 }
414 }
415 else
416 {
417 s32 row = map->ToRow((s32)pos.y + map->CellHeight()/2);
418 s32 col = map->ToCol((s32)pos.x);
419
420 if (state == HCCS_STOP ||
421 state == HCCS_LEFT ||
422 state == HCCS_RIGHT)
423 {
424 // Outside a break, got in?
425 if (row < map->Rows() - 1 &&
426 map->Cell(row, col)->Type() == HCCELLTYPE_BREAK &&
427 ((HCBreak *)map->Cell(row, col))->State() == HCBREAKSTATE_NORMAL)
428 {
429 // Got in!
430 breakRow = row;
431 breakCol = col;
432 }
433 }
434 }
435 }
436
437 void HCCharacter::CheckHang()
438 {
439 if (ropes == 0)
440 return;
441
442 if (state != HCCS_HANG &&
443 state != HCCS_DIE)
444 {
445 JImage *edge;
446 for (s32 i = 0; i < numRopes; ++i)
447 {
448 edge = &ropes[i]->Edge();
449 s32 cx = (s32)edge->X() + (edge->Width()/2);
450 s32 cy = (s32)edge->Y() + (edge->Height()/2);
451
452 if (cx > pos.x - hangCheckSize &&
453 cx < pos.x + hangCheckSize &&
454 cy > pos.y - hangCheckYOffset - hangCheckSize &&
455 cy < pos.y - hangCheckYOffset + hangCheckSize)
456 {
457 state = HCCS_HANG;
458 v.x = v.y = a.x = 0.0f;
459 a.y = -map->Gravity();
460 trackRope = ropes[i];
461 Pos(trackRope->Edge().X(), trackRope->Edge().Y());
462 break;
463 }
464 }
465 }
466 }
467
468 s32 HCCharacter::UpdateStop()
469 {
470 return 0;
471 }
472
473 s32 HCCharacter::UpdateRight()
474 {
475 return 0;
476 }
477
478 s32 HCCharacter::UpdateLeft()
479 {
480 return 0;
481 }
482
483 s32 HCCharacter::UpdateUp()
484 {
485 return 0;
486 }
487
488 s32 HCCharacter::UpdateDown()
489 {
490 return 0;
491 }
492
493 s32 HCCharacter::UpdateSlide()
494 {
495 return 0;
496 }
497
498 s32 HCCharacter::UpdateJump()
499 {
500 return 0;
501 }
502
503 s32 HCCharacter::UpdateJumpLeft()
504 {
505 return 0;
506 }
507
508 s32 HCCharacter::UpdateJumpRight()
509 {
510 return 0;
511 }
512
513 s32 HCCharacter::UpdateFall()
514 {
515 return 0;
516 }
517
518 s32 HCCharacter::UpdateDie()
519 {
520 return 0;
521 }
522
523 s32 HCCharacter::UpdateHang()
524 {
525 // Move with the rope!
526 Pos(trackRope->Edge().X() + trackRope->Edge().Width()/2,
527 trackRope->Edge().Y() + trackRope->Edge().Height());
528
529 return 0;
530 }
531
532 void HCCharacter::Pos(float x, float y)
533 {
534 // fprintf(stderr, "En Pos() antes pos.x: %f pos.y: %f v.x: %f v.y: %f x:%f y:%f px+vx:%f py+vy:%f\n", pos.x, pos.y, v.x, v.y, x, y, pos.x + v.x, pos.y + v.y);
535 pos.x = x;
536 pos.y = y;
537 // fprintf(stderr, "En Pos() después pos.x: %f pos.y: %f v.x: %f v.y: %f x:%f y:%f\n", pos.x, pos.y, v.x, v.y, x, y);
538 states[state].Pos(x, y);
539 }
540
541 s32 HCCharacter::Row()
542 {
543 return map->ToRow((s32)pos.y);
544 }
545
546 s32 HCCharacter::Col()
547 {
548 return map->ToCol((s32)pos.x);
549 }
550
551
552 void HCCharacter::FixPos(s32 col, s32 row)
553 {
554 Pos(map->ToX(col), map->ToY(row));
555 }
556
557 void HCCharacter::FixX(s32 col)
558 {
559 Pos(map->ToX(col), (s32)pos.y);
560 }
561
562 void HCCharacter::FixY(s32 row)
563 {
564 Pos(pos.x, map->ToY(row));
565 }
566
567 bool HCCharacter::Act(u32 act)
568 {
569 lastAction = actions;
570 actions = act;
571
572 s32 row = map->ToRow((s32)pos.y);
573 s32 col = map->ToCol((s32)pos.x);
574
575 if (state == HCCS_DIE)
576 {
577 return false;
578 }
579
580 // Nothing
581 if (actions == 0)
582 {
583 // Stop moving aside
584 v.x = a.x = 0.0f;
585
586 switch (state)
587 {
588 case HCCS_JUMP:
589 case HCCS_JUMPLEFT:
590 case HCCS_JUMPRIGHT:
591 {
592 // Vertical jump
593 State(HCCS_JUMP);
594
595 if (v.y < 0.0f)
596 {
597 // Stop going up but not down
598 v.y = 0.0f;
599 }
600 }
601 break;
602
603 case HCCS_UP:
604 case HCCS_DOWN:
605 {
606 v.y = 0.0f;
607 a.y = -map->Gravity();
608 states[state].Paused(true);
609 }
610 break;
611
612 case HCCS_SLIDE:
613 break;
614
615 case HCCS_LEFT:
616 case HCCS_RIGHT:
617 State(HCCS_STOP);
618 break;
619
620 default:
621 break;
622 }
623
624 return true;
625 }
626
627 /////////////////////////////////////////////////////////////////////
628 // Side movement
629 if ((actions & HCCA_LEFT) && (map->Cell(row, col)->Actions() & HCACTION_LEFT))
630 {
631 // Goes left
632 a.x = -aMax.x;
633
634 if (actions & HCCA_JUMP)
635 {
636 a.y = 0.0f;
637 // Jump requested
638 if (state != HCCS_JUMP &&
639 state != HCCS_JUMPLEFT &&
640 state != HCCS_JUMPRIGHT)
641 {
642 // Not jumping, make it jump
643 v.y = -vJumpMax.y;
644 }
645
646 // Jumps facing left
647 State(HCCS_JUMPLEFT);
648
649 // Jump processed, clean it from the pending actions
650 actions &= ~HCCA_JUMP;
651 }
652 else
653 {
654 a.y = 0.0f;
655
656 // Jump not requested
657 if (state == HCCS_JUMPLEFT ||
658 state == HCCS_JUMPRIGHT ||
659 state == HCCS_JUMP)
660 {
661 State(HCCS_JUMPLEFT);
662 }
663 else
664 if (state != HCCS_HANG)
665 {
666 if (map->Cell(row + 1, col)->Actions() & HCACTION_FALL)
667 {
668 // Falls facing right if not climbing or hanging
669 State(HCCS_JUMPLEFT);
670 v.y = 0.0f;
671 }
672 else
673 {
674 // Walks facing right if not climbing or hanging
675 State(HCCS_LEFT);
676 }
677 }
678 }
679 }
680 else
681 if ((actions & HCCA_RIGHT) && (map->Cell(row, col)->Actions() & HCACTION_RIGHT))
682 {
683 // Goes right
684 a.x = aMax.x;
685
686 if (actions & HCCA_JUMP)
687 {
688 a.y = 0.0f;
689 // Jump requested
690 if (state != HCCS_JUMP &&
691 state != HCCS_JUMPLEFT &&
692 state != HCCS_JUMPRIGHT)
693 {
694 // Not jumping, make it jump
695 v.y = -vJumpMax.y;
696 }
697
698 // Jumps facing right
699 State(HCCS_JUMPRIGHT);
700
701 // Jump processed, clean it from the pending actions
702 actions &= ~HCCA_JUMP;
703 }
704 else
705 {
706 a.y = 0.0f;
707 if (state == HCCS_JUMPLEFT ||
708 state == HCCS_JUMPRIGHT ||
709 state == HCCS_JUMP)
710 {
711 State(HCCS_JUMPRIGHT);
712 }
713 else
714 // Jump not requested
715 if (state != HCCS_HANG)
716 {
717 if (map->Cell(row + 1, col)->Actions() & HCACTION_FALL)
718 {
719 // Falls facing right if not climbing or hanging
720 State(HCCS_JUMPRIGHT);
721 v.y = 0.0f;
722 }
723 else
724 {
725 // Walks facing right if not climbing or hanging
726 State(HCCS_RIGHT);
727 }
728 }
729 }
730 }
731 else
732 {
733 v.x = a.x = 0.0f;
734 }
735
736 /////////////////////////////////////////////////////////////////////
737 // Vertical movement
738 if (actions & HCCA_UP && state != HCCS_HANG)
739 {
740 // Up requested
741 if (map->Cell(row, col)->Actions() & HCACTION_UP != 0)
742 {
743 State(HCCS_UP);
744 // Can go up in the current cell
745 if (map->Cell(row - 1, col)->Actions() & HCACTION_UP ||
746 map->Cell(row - 1, col)->Actions() & HCACTION_FALL)
747 {
748 // Can go up in the upper cell or cell above empty, continue
749 a.y = -map->Gravity() - aMax.y;
750 states[state].Paused(false);
751 FixX(col);
752 }
753 else
754 {
755 // Cannot go up in the upper cell, stops
756 a.y = -map->Gravity();
757 v.y = 0.0f;
758 states[state].Paused(true);
759 }
760 }
761 else
762 {
763 a.y = 0.0f;
764
765 if (state == HCCS_UP)
766 {
767 // Cannot go up, wait
768 State(HCCS_STOP);
769 v.y = 0.0f;
770 }
771 }
772 }
773 else
774 if (actions & HCCA_DOWN)
775 {
776 // Down requested
777 if (state == HCCS_HANG)
778 {
779 // If hanging, falls
780 v.x = v.y = a.y = 0.0f;
781 state = HCCS_JUMP;
782 trackRope = 0;
783 Pos(pos.x, pos.y + states[state].MaxH());
784 }
785 else
786 if (map->Cell(row + 1, col)->Actions() & HCACTION_SLIDE)
787 {
788 // Bar like object bellow
789 a.y = -map->Gravity() + aMax.y;
790 state = HCCS_SLIDE;
791 FixX(col);
792 }
793 else
794 if (map->Cell(row + 1, col)->Actions() & HCACTION_DOWN)
795 {
796 // Ladder like object bellow
797 a.y = -map->Gravity() + aMax.y;
798 state = HCCS_DOWN;
799 states[state].Paused(false);
800 FixX(col);
801 }
802 else
803 {
804 // Not a ladder or a bar bellow
805 if (map->Cell(row, col)->Actions() & HCACTION_DOWN ||
806 map->Cell(row, col)->Actions() & HCACTION_SLIDE)
807 {
808 // If still over the ladder or bar, keep going on
809 a.y = -map->Gravity() + aMax.y;
810 states[state].Paused(false);
811 }
812 else
813 if (map->Cell(row + 1, col)->Actions() & HCACTION_FALL)
814 {
815 // There is no bar or ladder either in the current cell or the cell bellow
816 // and the cell bellow is empty
817 if (state != HCCS_JUMP &&
818 state != HCCS_JUMPLEFT &&
819 state != HCCS_JUMPRIGHT &&
820 !(actions & HCCA_JUMP))
821 {
822 // Jump not requested, normal fall
823 v.y = a.y = 0.0f;
824 State(HCCS_JUMP);
825 }
826 }
827 else
828 {
829 a.y = 0.0f;
830
831 if (state == HCCS_DOWN)
832 {
833 // Cannot go down, wait
834 state = HCCS_STOP;
835 FixY(row);
836 }
837 }
838 }
839 }
840
841 // Jumps only if not sliding and the current cell and the cell above are empty or
842 // it's hanging
843 if ((actions & HCCA_JUMP) &&
844 state != HCCS_SLIDE &&
845 (!(map->Cell(row + 1, col)->Actions() & HCACTION_FALL) ||
846 //!(map->Cell(row, col)->Actions() & HCACTION_FALL) ||
847 state == HCCS_HANG))
848 {
849 // Cell bellow or this cell are not empty or the character is hanging
850 v.x = a.x = 0.0f;
851
852 if (state != HCCS_JUMP &&
853 state != HCCS_JUMPLEFT &&
854 state != HCCS_JUMPRIGHT)
855 {
856 a.y = 0.0f;
857 v.y = -vJumpMax.y;
858 State(HCCS_JUMP);
859 }
860 }
861
862 return true;
863 }
864
865 void HCCharacter::State(HCCharacterState newState)
866 {
867 // Gets the current row and col
868 state = newState;
869 states[state].Pos(pos.x, pos.y);
870 }
871
872 u32 HCCharacter::Load(JRW &file)
873 {
874 if (0 == file.ReadLE32(&subtype) ||
875 0 == file.ReadLE32((u32 *)&pos.x) ||
876 0 == file.ReadLE32((u32 *)&pos.y) ||
877 0 == file.ReadLE32((u32 *)&vMax.x) ||
878 0 == file.ReadLE32((u32 *)&vMax.y) ||
879 0 == file.ReadLE32(&maxJumpRows))
880 {
881 fprintf(stderr, "Error reading character's common parameters.\n");
882 return 1;
883 }
884
885 Pos(pos.x, pos.y);
886
887 return 0;
888 }
889
890 u32 HCCharacter::Save(JRW &file)
891 {
892 if (0 == file.WriteLE32(&subtype) ||
893 0 == file.WriteLE32((u32 *)&pos.x) ||
894 0 == file.WriteLE32((u32 *)&pos.y) ||
895 0 == file.WriteLE32((u32 *)&vMax.x) ||
896 0 == file.WriteLE32((u32 *)&vMax.y) ||
897 0 == file.WriteLE32(&maxJumpRows))
898 {
899 fprintf(stderr, "Error writing character's common parameters.\n");
900 return 1;
901 }
902
903 return 0;
904 }
905
906 void HCCharacter::Destroy()
907 {
908 for (s32 i = 0; i < HCCS_COUNT; ++i)
909 {
910 states[i].Destroy();
911 }
912
913 dialog = 0;
914 breakCol = breakRow = -1;
915 }
916
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Holotz's Castle character definition file.
23 * @file HCCharacter.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 30/04/2004
26 * @version 0.0.1 - 30/04/2004 - First version.
27 */
28
29 #ifndef _HCCHARACTER_INCLUDED
30 #define _HCCHARACTER_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Util/JString.h>
34 #include <JLib/Util/JFile.h>
35 #include <JLib/Graphics/JImageSprite.h>
36 #include <HCTheme.h>
37 #include <HCMap.h>
38 #include <HCRope.h>
39 #include <HCText.h>
40 #include <HCPreferences.h>
41
42 class HCed;
43
44 enum HCCharacterState
45 {
46 HCCS_STOP = 0, /**< Stopped state. */
47 HCCS_RIGHT, /**< Walk-right state. */
48 HCCS_LEFT, /**< Walk-left state. */
49 HCCS_UP, /**< Up state. */
50 HCCS_DOWN, /**< Down state. */
51 HCCS_SLIDE, /**< Slide state. */
52 HCCS_JUMP, /**< Jump left state. */
53 HCCS_JUMPLEFT, /**< Jump left state. */
54 HCCS_JUMPRIGHT, /**< Jump right state. */
55 HCCS_FALL, /**< Fall state. */
56 HCCS_DIE, /**< Die state. */
57 HCCS_HANG, /**< Hang state. */
58 HCCS_COUNT, /**< State count. */
59 };
60
61 // Requested actions for the character
62 #define HCCA_STOP 0x00
63 #define HCCA_UP 0x01
64 #define HCCA_DOWN 0x02
65 #define HCCA_LEFT 0x04
66 #define HCCA_RIGHT 0x08
67 #define HCCA_JUMP 0x10
68
69 class HCCharacter : public JDrawable
70 {
71 friend class HCed;
72
73 protected:
74 JImageSprite states[HCCS_COUNT]; /**< Table of state drawables. */
75 HCCharacterState state; /**< Current state of the character. */
76 u32 lastAction; /**< Last action of the character. */
77 u32 actions; /**< Actions requested for the character. */
78 HCMap *map; /**< Map for this character. */
79 JVector v; /**< Veloccity. */
80 JVector a; /**< Acceleration. */
81 JVector vMax; /**< Maximum veloccity. */
82 JVector aMax; /**< Maximum acceleration. */
83 JVector vJumpMax; /**< Maximum veloccity for jumps. */
84 JTimer timer; /**< Timer for jumps. */
85
86 s32 startJumpRow; /**< Row at where jump took place. */
87 s32 maxFallRows; /**< Max. number of cells to free fall if not reached floor or a rope yet. */
88 s32 maxJumpRows; /**< Max. number of cells in vertical it can jump. */
89 s32 maxJumpCols; /**< Max. number of cells in horizontal it can jump. */
90 s32 breakRow; /**< Row starting break floor, -1 if none. */
91 s32 breakCol; /**< Column starting break floor. */
92 s32 hangCheckYOffset; /**< Offset within character for hanging cheks. */
93 s32 hangCheckSize; /**< Size of the square side centered at the offset for hanging cheks. */
94
95 JString name; /**< Name of the character. */
96 s32 subtype; /**< Subtype within the theme. */
97
98 HCRope **ropes; /**< Ropes to check. */
99 s32 numRopes; /**< Number of ropes to check. */
100 HCRope *trackRope; /**< Rope to track when hanging. */
101
102 HCText *dialog; /**< Dialog to say. */
103
104 public:
105
106 /** Creates the character. Init must be called before starting to use it.
107 */
108 HCCharacter();
109
110 /** Initializes the character.
111 * @param sprites Sprites for this character.
112 * @param _map Map for this character.
113 * @param _ropes Ropes this character must check.
114 * @param nRopes Number of ropes this character must check.
115 * @return <b>true</b> if everything goes well, <b>false</b> otherwise.
116 */
117 virtual bool Init(JImageSprite *sprites, HCMap *_map, HCRope **_ropes = 0, s32 nRopes = 0);
118
119 /** Draws the character.
120 */
121 virtual void Draw();
122
123 /** Updates the character. The general character's update pipeline is:
124 * <pre>
125 * 1. Update sprite
126 * 2. If hanging, do nothing (return)
127 * 3. Update vellocity.
128 * 4. Update collisions with the map
129 * 6. Update their dialog
130 * </pre>
131 * @return Return value of the associated drawable's update.
132 */
133 virtual s32 Update();
134
135 /** Updates the veloccity of the character based upon the character's acceleration and the map's gravity.
136 */
137 virtual void UpdateVeloccity();
138
139 /** Updates collisions with the map and modifies the veloccity according to the result of the collision tests.
140 */
141 virtual void UpdateCollisions();
142
143 /** Updates this character's speech dialog.
144 */
145 virtual void UpdateDialog();
146
147 /** Check if the character must fall upon a broken floor and changes its state if so.
148 */
149 virtual void CheckBrokenFloor();
150
151 /** Check if the character must hang of a rope.
152 */
153 virtual void CheckHang();
154
155 /** Updates the character in the Stop state.
156 * @return Return value of the associated drawable's update.
157 */
158 virtual s32 UpdateStop();
159
160 /** Updates the character in the Right state.
161 * @return Return value of the associated drawable's update.
162 */
163 virtual s32 UpdateRight();
164
165 /** Updates the character in the Left state.
166 * @return Return value of the associated drawable's update.
167 */
168 virtual s32 UpdateLeft();
169
170 /** Updates the character in the Up state.
171 * @return Return value of the associated drawable's update.
172 */
173 virtual s32 UpdateUp();
174
175 /** Updates the character in the Down state.
176 * @return Return value of the associated drawable's update.
177 */
178 virtual s32 UpdateDown();
179
180 /** Updates the character in the Slide state.
181 * @return Return value of the associated drawable's update.
182 */
183 virtual s32 UpdateSlide();
184
185 /** Updates the character in the Jump state.
186 * @return Return value of the associated drawable's update.
187 */
188 virtual s32 UpdateJump();
189
190 /** Updates the character in the JumpLeft state.
191 * @return Return value of the associated drawable's update.
192 */
193 virtual s32 UpdateJumpLeft();
194
195 /** Updates the character in the JumpRight state.
196 * @return Return value of the associated drawable's update.
197 */
198 virtual s32 UpdateJumpRight();
199
200 /** Updates the character in the Fall state.
201 * @return Return value of the associated drawable's update.
202 */
203 virtual s32 UpdateFall();
204
205 /** Updates the character in the Die state.
206 * @return Return value of the associated drawable's update.
207 */
208 virtual s32 UpdateDie();
209
210 /** Updates the character in the Hang state.
211 * @return Return value of the associated drawable's update.
212 */
213 virtual s32 UpdateHang();
214
215 /** Set this character's position.
216 * @param x New X coordinate.
217 * @param y New Y coordinate.
218 */
219 virtual void Pos(float x, float y);
220
221 /** Gets this character's position.
222 * @return Character's position.
223 */
224 virtual const JVector & Pos() {return pos;}
225
226 /** Gets the current row.
227 * @return The row this character is at.
228 */
229 s32 Row();
230
231 /** Gets the current column.
232 * @return The column this character is at.
233 */
234 s32 Col();
235
236 /** Fix the character position to the actual row and col.
237 * @param col Column to be fixed at.
238 * @param row Row to be fixed at.
239 */
240 void FixPos(s32 col, s32 row);
241
242 /** Fix the character's x position to the actual col.
243 * @param col Column to be fixed at.
244 */
245 void FixX(s32 col);
246
247 /** Fix the character's y position to the actual row.
248 * @param row Row to be fixed at.
249 */
250 void FixY(s32 row);
251
252 /** Changes the state of the character.
253 * @param newState New state for this character.
254 */
255 void State(HCCharacterState newState);
256
257 /** Returns the state of the character.
258 * @return the state of the character.
259 */
260 HCCharacterState State() {return state;}
261
262 /** Returns the name of this character.
263 */
264 const JString& Name() {return name;}
265
266 /** Sets the name of this character. The name will be the base directory
267 * from where to load its resources.
268 */
269 void Name(const JString &_name) {name = _name;}
270
271 /** Gets the subtype of this character.
272 * @return Subtype of this character.
273 */
274 s32 Subtype() {return subtype;}
275
276 /** Sets the subtype of this character.
277 * @param newSubtype New type of this character.
278 */
279 void Subtype(s32 newSubtype) {subtype = newSubtype;}
280
281 /** Gets the dialog of this character.
282 * @return Dialog of this character.
283 */
284 HCText * Dialog() {return dialog;}
285
286 /** Sets the dialog for this character.
287 * @param newDialog New type of this character.
288 */
289 void Dialog(HCText *newDialog) {dialog = newDialog;}
290
291 /** Returns the current image sprite used.
292 * @return Current image sprite used.
293 */
294 JImageSprite *CurSprite() {return &states[state];}
295
296 /** Tries to put the character in the given state.
297 * @param st State to try to reach.
298 * @return <b>true</b> if the state could be changed, <b>false</b> otherwise.
299 */
300 bool Try(HCCharacterState st);
301
302 /** Sets the actions this character must perform.
303 * @param act Actions requested as a bitmask.
304 * @return <b>true</b> if the state could be changed, <b>false</b> otherwise.
305 */
306 bool Act(u32 act);
307
308 /** Returns the maximum veloccity vector for this character.
309 */
310 JVector & MaxVeloccity() {return vMax;}
311
312 /** Returns the maximum jump veloccity vector for this character.
313 */
314 JVector & JumpMaxVeloccity() {return vJumpMax;}
315
316 /** Returns the veloccity vector for this character.
317 */
318 JVector & Veloccity() {return v;}
319
320 /** Returns the acceleration vector for this character.
321 */
322 JVector & Acceleration() {return a;}
323
324 /** Returns the maximum jump rows parameter for this character.
325 */
326 s32 MaxJumpRows() {return maxJumpRows;}
327
328 /** Sets the maximum jump rows parameter for this character. Computes the
329 * maximum jump y veloccity of the character, also.
330 */
331 void MaxJumpRows(s32 newMaxJumpRows);
332
333 /** Loads the character.
334 * @param file File opened and positioned already.
335 * @return 0 if it succeeds, 1 if there is an I/O error, 2 if integrity error.
336 */
337 u32 Load(JRW &file);
338
339 /** Saves the character. The file must be opened and positioned already.
340 * @param file File opened and positioned already.
341 * @return 0 if it succeeds, 1 if there is an I/O error, 2 if integrity error.
342 */
343 u32 Save(JRW &file);
344
345 /** Destroys the character.
346 */
347 void Destroy();
348
349 /** Destroys the character.
350 */
351 virtual ~HCCharacter() {Destroy();}
352 };
353
354 #endif // _HCCHARACTER_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Continuous floor cell.
23 * @file HCContFloor.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 02/06/2004
26 * @version 0.0.1 - 02/06/2004 - First version.
27 */
28
29 #include <HCContFloor.h>
30
31 void HCContFloor::Build(JImage *parts,
32 bool n7,
33 bool n8,
34 bool n9,
35 bool n4,
36 bool n6,
37 bool n1,
38 bool n2,
39 bool n3)
40 {
41 s32 cw = parts[HCFDT_C1].Width();
42 s32 ch = parts[HCFDT_C1].Height();
43 s32 iw = parts[HCFDT_I].Width();
44 s32 ih = parts[HCFDT_I].Height();
45
46 JImage *img;
47 drawable.Create((cw * 2) + iw, (ch * 2) + ih, 32);
48 img = &drawable;
49
50 // UL Corner
51 if (n7)
52 {
53 if (n4)
54 {
55 if (n8)
56 {
57 // The three exist (*) around us (X):
58 //
59 // **
60 // *X
61 img->Paste(&parts[HCFDT_C], 0, 0, cw, ch, 0, 0);
62 }
63 else
64 {
65 // *
66 // *X
67 img->Paste(&parts[HCFDT_CU], 0, 0, cw, ch, 0, 0);
68 }
69 }
70 else
71 {
72 if (n8)
73 {
74 // **
75 // X
76 img->Paste(&parts[HCFDT_CL], 0, 0, cw, ch, 0, 0);
77 }
78 else
79 {
80 // *
81 // X
82 img->Paste(&parts[HCFDT_C7], 0, 0, cw, ch, 0, 0);
83 }
84 }
85 }
86 else
87 {
88 if (n4)
89 {
90 if (n8)
91 {
92 // *
93 // *X
94 img->Paste(&parts[HCFDT_C7UL], 0, 0, cw, ch, 0, 0);
95 }
96 else
97 {
98 //
99 // *X
100 img->Paste(&parts[HCFDT_CU], 0, 0, cw, ch, 0, 0);
101 }
102 }
103 else
104 {
105 if (n8)
106 {
107 // *
108 // X
109 img->Paste(&parts[HCFDT_CL], 0, 0, cw, ch, 0, 0);
110 }
111 else
112 {
113 //
114 // X
115 img->Paste(&parts[HCFDT_C7], 0, 0, cw, ch, 0, 0);
116 }
117 }
118 }
119
120 // UR Corner
121 if (n9)
122 {
123 if (n6)
124 {
125 if (n8)
126 {
127 // **
128 // X*
129 img->Paste(&parts[HCFDT_C], 0, 0, cw, ch, cw + iw, 0);
130 }
131 else
132 {
133 // *
134 // X*
135 img->Paste(&parts[HCFDT_CU], 0, 0, cw, ch, cw + iw, 0);
136 }
137 }
138 else
139 {
140 if (n8)
141 {
142 // **
143 // X
144 img->Paste(&parts[HCFDT_CR], 0, 0, cw, ch, cw + iw, 0);
145 }
146 else
147 {
148 // *
149 // X
150 img->Paste(&parts[HCFDT_C9], 0, 0, cw, ch, cw + iw, 0);
151 }
152 }
153 }
154 else
155 {
156 if (n6)
157 {
158 if (n8)
159 {
160 // *
161 // X*
162 img->Paste(&parts[HCFDT_C9UR], 0, 0, cw, ch, cw + iw, 0);
163 }
164 else
165 {
166 //
167 // X*
168 img->Paste(&parts[HCFDT_CU], 0, 0, cw, ch, cw + iw, 0);
169 }
170 }
171 else
172 {
173 if (n8)
174 {
175 // *
176 // X
177 img->Paste(&parts[HCFDT_CR], 0, 0, cw, ch, cw + iw, 0);
178 }
179 else
180 {
181 //
182 // X
183 img->Paste(&parts[HCFDT_C9], 0, 0, cw, ch, cw + iw, 0);
184 }
185 }
186 }
187
188 // DL Corner
189 if (n1)
190 {
191 if (n4)
192 {
193 if (n2)
194 {
195 // *X
196 // **
197 img->Paste(&parts[HCFDT_C], 0, 0, cw, ch, 0, ch + ih);
198 }
199 else
200 {
201 // *X
202 // *
203 img->Paste(&parts[HCFDT_C1DL], 0, 0, cw, ch, 0, ch + ih);
204 }
205 }
206 else
207 {
208 if (n2)
209 {
210 // X
211 // **
212 img->Paste(&parts[HCFDT_CL], 0, 0, cw, ch, 0, ch + ih);
213 }
214 else
215 {
216 // X
217 // *
218 img->Paste(&parts[HCFDT_C1], 0, 0, cw, ch, 0, ch + ih);
219 }
220 }
221 }
222 else
223 {
224 if (n4)
225 {
226 if (n2)
227 {
228 // *X
229 // *
230 img->Paste(&parts[HCFDT_C1DL], 0, 0, cw, ch, 0, ch + ih);
231 }
232 else
233 {
234 // *X
235 //
236 img->Paste(&parts[HCFDT_CD], 0, 0, cw, ch, 0, ch + ih);
237 }
238 }
239 else
240 {
241 if (n2)
242 {
243 // X
244 // *
245 img->Paste(&parts[HCFDT_CL], 0, 0, cw, ch, 0, ch + ih);
246 }
247 else
248 {
249 // X
250 //
251 img->Paste(&parts[HCFDT_C1], 0, 0, cw, ch, 0, ch + ih);
252 }
253 }
254 }
255
256 // DR Corner
257 if (n3)
258 {
259 if (n6)
260 {
261 if (n2)
262 {
263 // X*
264 // **
265 img->Paste(&parts[HCFDT_C], 0, 0, cw, ch, cw + iw, ch + ih);
266 }
267 else
268 {
269 // X*
270 // *
271 img->Paste(&parts[HCFDT_CD], 0, 0, cw, ch, cw + iw, ch + ih);
272 }
273 }
274 else
275 {
276 if (n2)
277 {
278 // X
279 // **
280 img->Paste(&parts[HCFDT_CR], 0, 0, cw, ch, cw + iw, ch + ih);
281 }
282 else
283 {
284 // X
285 // *
286 img->Paste(&parts[HCFDT_C3], 0, 0, cw, ch, cw + iw, ch + ih);
287 }
288 }
289 }
290 else
291 {
292 if (n6)
293 {
294 if (n2)
295 {
296 // X*
297 // *
298 img->Paste(&parts[HCFDT_C3DR], 0, 0, cw, ch, cw + iw, ch + ih);
299 }
300 else
301 {
302 // X*
303 //
304 img->Paste(&parts[HCFDT_CD], 0, 0, cw, ch, cw + iw, ch + ih);
305 }
306 }
307 else
308 {
309 if (n2)
310 {
311 // X
312 // *
313 img->Paste(&parts[HCFDT_CR], 0, 0, cw, ch, cw + iw, ch + ih);
314 }
315 else
316 {
317 // X
318 //
319 img->Paste(&parts[HCFDT_C3], 0, 0, cw, ch, cw + iw, ch + ih);
320 }
321 }
322 }
323
324 // U Side
325 if (n8)
326 {
327 // *
328 // X
329 img->Paste(&parts[HCFDT_SV], 0, 0, iw, ch, cw, 0);
330 }
331 else
332 {
333 //
334 // X
335 img->Paste(&parts[HCFDT_S8], 0, 0, iw, ch, cw, 0);
336 }
337
338 // D Side
339 if (n2)
340 {
341 // X
342 // *
343 img->Paste(&parts[HCFDT_SV], 0, 0, iw, ch, cw, ch + ih);
344 }
345 else
346 {
347 // X
348 //
349 img->Paste(&parts[HCFDT_S2], 0, 0, iw, ch, cw, ch + ih);
350 }
351
352 // L Side
353 if (n4)
354 {
355 //
356 // *X
357 img->Paste(&parts[HCFDT_SH], 0, 0, cw, ih, 0, ch);
358 }
359 else
360 {
361 //
362 // X
363 img->Paste(&parts[HCFDT_S4], 0, 0, cw, ih, 0, ch);
364 }
365
366 // R Side
367 if (n6)
368 {
369 //
370 // X*
371 img->Paste(&parts[HCFDT_SH], 0, 0, cw, ih, cw + iw, ch);
372 }
373 else
374 {
375 //
376 // X
377 img->Paste(&parts[HCFDT_S6], 0, 0, cw, ih, cw + iw, ch);
378 }
379
380 // The center cannot change
381 img->Paste(&parts[HCFDT_I], 0, 0, iw, ih, cw, ch);
382 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Continuous floor cell.
23 * @file HCContFloor.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 02/06/2004
26 * @version 0.0.1 - 02/06/2004 - First version.
27 */
28
29 #ifndef _HCCONTFLOOR_INCLUDED
30 #define _HCCONTFLOOR_INCLUDED
31
32 #include <HCCell.h>
33 #include <HCTheme.h>
34
35 class HCContFloor : public HCDrawableCell
36 {
37 public:
38
39 HCContFloor() : HCDrawableCell(HCCELLTYPE_CONTFLOOR, 0, 0)
40 {}
41
42 /** Builds the image for this floor.
43 * @param parts Array of parts of this floor (corners, sides, etc.)
44 * Tipically it is retrieved from HCTheme::ContFloor().
45 * @param n7 Neighbour at position 7 (as in the keypad from your keyboard). false for none.
46 * @param n8 Neighbour at position 8 (as in the keypad from your keyboard). false for none.
47 * @param n9 Neighbour at position 9 (as in the keypad from your keyboard). false for none.
48 * @param n4 Neighbour at position 4 (as in the keypad from your keyboard). false for none.
49 * @param n6 Neighbour at position 6 (as in the keypad from your keyboard). false for none.
50 * @param n1 Neighbour at position 1 (as in the keypad from your keyboard). false for none.
51 * @param n2 Neighbour at position 2 (as in the keypad from your keyboard). false for none.
52 * @param n3 Neighbour at position 3 (as in the keypad from your keyboard). false for none.
53 */
54 void Build(JImage *parts,
55 bool n7,
56 bool n8,
57 bool n9,
58 bool n4,
59 bool n6,
60 bool n1,
61 bool n2,
62 bool n3);
63
64 /** Allows scalar destruction.
65 */
66 virtual ~HCContFloor()
67 {}
68 };
69
70 #endif // _HCCONTFLOOR_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Definition of a generic enemy.
23 * @file HCEnemy.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 27/05/2004
26 * @version 0.0.1 - 27/05/2004 - First version.
27 */
28
29 #include <HCEnemy.h>
30
31 float HCEnemy::maxXVeloccity = 3.0f;
32 float HCEnemy::maxYVeloccity = 3.0f;
33
34 bool HCEnemy::Init(JImageSprite *sprites, HCMap *_map, HCRope **_ropes, s32 nRopes)
35 {
36 if (HCCharacter::Init(sprites, _map, _ropes, nRopes))
37 {
38 v.x = 0;
39
40 // Uses param1 to set veloccities for this enemy, depends also on difficulty
41 // Easy - from 0 to 62.5% MaxV stepping (62.5% MaxV)/10 (10 is the number of possible param1)
42 // Normal - from 0 to 87.5% MaxV stepping (87.5% MaxV)/10
43 // Hard - from 0 to MaxV stepping MaxV/10
44 // i.e.: if maxXVeloccity is 5 and param1 is 1, enemy at EASY level moves with vx = 0.325 pels/sec, at HARD with vx=0.5
45
46 float delta, percent;
47 percent = 1.0f - (float(HCPreferences::Prefs()->Difficulty() - HCPREFERENCES_HARD)/(2.0f * float(HCPREFERENCES_EASY)));
48
49 delta = (maxXVeloccity * percent)/10.0f;
50 vMax.x = JMax(HCENEMY_MIN_MAX_V, delta * float(param1));
51 aMax.x = vMax.x;
52
53 delta = (maxYVeloccity * percent)/10.0f;
54 aMax.y = vMax.y = JMax(HCENEMY_MIN_MAX_V, delta * float(param1));
55
56 return true;
57 }
58
59 return false;
60 }
61
62 s32 HCEnemy::Update()
63 {
64 Act(actions);
65
66 s32 ret = states[state].Update();
67
68 UpdateVeloccity();
69 UpdateCollisions();
70
71 // Only enters here if the sprite has changed
72 switch (state)
73 {
74 case HCCS_STOP:
75 UpdateStop();
76 break;
77
78 case HCCS_RIGHT:
79 UpdateRight();
80 break;
81
82 case HCCS_LEFT:
83 UpdateLeft();
84 break;
85
86 case HCCS_UP:
87 UpdateUp();
88 break;
89
90 case HCCS_SLIDE:
91 UpdateSlide();
92 break;
93
94 case HCCS_DOWN:
95 UpdateDown();
96 break;
97
98 case HCCS_JUMPLEFT:
99 UpdateJumpLeft();
100 break;
101 case HCCS_JUMPRIGHT:
102 UpdateJumpRight();
103 break;
104
105 case HCCS_FALL:
106 UpdateFall();
107 break;
108
109 case HCCS_JUMP:
110 UpdateJump();
111 break;
112
113 case HCCS_DIE:
114 UpdateDie();
115 break;
116
117 case HCCS_HANG:
118 UpdateHang();
119 break;
120
121 default:
122 break;
123 }
124
125 Pos(pos.x + v.x, pos.y + v.y);
126
127 return ret;
128 }
129
130 u32 HCEnemy::Load(JRW &file, HCTheme &theme, HCMap *_map)
131 {
132 if (0 == file.ReadLE32((s32 *)&type) ||
133 0 == file.ReadLE32(&param1) ||
134 0 == file.ReadLE32(&param2) ||
135 0 != HCCharacter::Load(file))
136 {
137 fprintf(stderr, "Error reading enemy's common parameters.\n");
138 return 1;
139 }
140
141 bool ret = false;
142
143 switch (type)
144 {
145 default:
146 case HCENEMYTYPE_BALL:
147 ret = Init(theme.Ball(subtype), _map);
148 break;
149
150 case HCENEMYTYPE_RANDOM:
151 ret = Init(theme.Random(subtype), _map);
152 break;
153
154 case HCENEMYTYPE_STATIC:
155 ret = Init(theme.Static(subtype), _map);
156 break;
157
158 case HCENEMYTYPE_MAKER:
159 ret = Init(theme.Maker(subtype), _map);
160 break;
161
162 case HCENEMYTYPE_CHASER:
163 ret = Init(theme.Chaser(subtype), _map);
164 break;
165 }
166
167 if (!ret)
168 {
169 return 2;
170 }
171
172 // Adjusts the sprite's framerate according to 1st param
173 for (s32 i = 0; i < HCCS_COUNT; ++i)
174 {
175 states[i].FPS(states[i].FPS() + param1 - 5);
176 }
177
178 return 0;
179 }
180
181 u32 HCEnemy::Save(JRW &file)
182 {
183 if (0 == file.WriteLE32((s32 *)&type) ||
184 0 == file.WriteLE32(&param1) ||
185 0 == file.WriteLE32(&param2) ||
186 0 != HCCharacter::Save(file))
187 {
188 fprintf(stderr, "Error writing enemy's common parameters.\n");
189 return 1;
190 }
191
192 return 0;
193 }
194
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Definition of a generic enemy.
23 * @file HCEnemy.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 27/05/2004
26 * @version 0.0.1 - 27/05/2004 - First version.
27 */
28
29 #ifndef _HCENEMY_INCLUDED
30 #define _HCENEMY_INCLUDED
31
32 #include <HCTheme.h>
33 #include <HCCharacter.h>
34
35 #define HCENEMY_MIN_MAX_V 1.0f
36
37 /** Type of enemy.
38 */
39 enum HCEnemyType
40 {
41 HCENEMYTYPE_BALL = 0, /**< Rebounding ball. */
42 HCENEMYTYPE_RANDOM, /**< Random movement enemy. */
43 HCENEMYTYPE_STATIC, /**< Static enemy. */
44 HCENEMYTYPE_MAKER, /**< Enemy maker. */
45 HCENEMYTYPE_CHASER, /**< Chaser enemy. */
46 HCENEMYTYPE_COUNT, /**< Number of different enemy types. */
47 };
48
49 /** Encapsulates a generic enemy. An enemy is a character
50 * that moves by its own.
51 */
52 class HCEnemy : public HCCharacter
53 {
54 protected:
55 HCEnemyType type; /**< Type of enemy. */
56
57 s32 param1; /**< Behaviour param 1. */
58 s32 param2; /**< Behaviour param 2. */
59
60 static float maxXVeloccity; /**< Maximum veloccity in x direction. */
61 static float maxYVeloccity; /**< Maximum veloccity in y direction. */
62
63 public:
64 /** Creates an empty enemy.
65 */
66 HCEnemy(HCEnemyType _type) : HCCharacter(), type(_type), param1(0), param2(0)
67 {}
68
69 /** Initializes this enemy.
70 * @param sprites Sprites for this enemy.
71 * @param _map Map for this enemy.
72 * @param _ropes Ropes this enemy must check.
73 * @param nRopes Number of ropes this enemy must check.
74 * @return <b>true</b> if everything goes well, <b>false</b> otherwise.
75 */
76 virtual bool Init(JImageSprite *sprites, HCMap *_map, HCRope **_ropes = 0, s32 nRopes = 0);
77
78 /** Returns the type of enemy.
79 * @return Type of enemy.
80 */
81 HCEnemyType Type() {return type;}
82
83 /** Returns the behaviour param 1.
84 * @return Behaviour param 1.
85 */
86 s32 Param1() {return param1;}
87
88 /** Returns the behaviour param 2.
89 * @return Behaviour param 2.
90 */
91 s32 Param2() {return param2;}
92
93 /** Sets the behaviour param 1.
94 * @param newParam New behaviour param 1.
95 */
96 void Param1(s32 newParam) {param1 = newParam;}
97
98 /** Sets the behaviour param 2.
99 * @param newParam New behaviour param 2.
100 */
101 void Param2(s32 newParam) {param2 = newParam;}
102
103 /** Updates the enemy.
104 * @return Return value of the associated drawable's update.
105 */
106 virtual s32 Update();
107
108 /** Loads the enemy.
109 * @param file File opened and positioned already.
110 * @param theme The theme to use.
111 * @param _map The level to use.
112 * @return 0 if it succeeds, 1 if there is an I/O error, 2 if integrity error.
113 */
114 u32 Load(JRW &file, HCTheme &theme, HCMap *_map);
115
116 /** Stablishes the maximum global X veloccity for an enemy.
117 * @param mvx Maximum X veloccity for any enemy.
118 */
119 static void MaxXVeloccity(float mvx) {maxXVeloccity = JMax(1.0f, mvx);}
120
121 /** Stablishes the maximum global Y veloccity for an enemy.
122 * @param mvy Maximum Y veloccity for any enemy.
123 */
124 static void MaxYVeloccity(float mvy) {maxYVeloccity = JMax(0.1f, mvy);}
125
126 /** Saves the enemy. The file must be opened and positioned already.
127 * @param file File opened and positioned already.
128 * @return 0 if it succeeds, 1 if there is an I/O error, 2 if integrity error.
129 */
130 u32 Save(JRW &file);
131
132 /** Destroys this enemy and allows scalar destruction.
133 */
134 virtual ~HCEnemy() {}
135 };
136
137 #endif // _HCENEMY_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Defines an enemy ball.
23 * @file HCEnemyBall.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 27/05/2004
26 * @version 0.0.1 - 27/05/2004 - First version.
27 */
28
29 #include <HCEnemyBall.h>
30
31 HCEnemyBall::HCEnemyBall() : HCEnemy(HCENEMYTYPE_BALL)
32 {
33 // Depende de param1 o param2
34 actions = (param1 % 2 ? HCCA_LEFT : HCCA_RIGHT);
35 v.x = (float)(param1 % 2 ? -(param1 + 1) : (param1 + 1));
36 vMax.x = v.x;
37 state = HCCS_LEFT;
38 }
39
40 void HCEnemyBall::UpdateCollisions()
41 {
42 s32 row = map->ToRow((s32)pos.y), col = map->ToCol((s32)pos.x), newCol = map->ToCol((s32)(pos.x + v.x));
43
44 // Side collisions
45 switch (map->Cell(row, newCol)->Type())
46 {
47 case HCCELLTYPE_FLOOR:
48 case HCCELLTYPE_CONTFLOOR:
49 v.x = -v.x;
50 if (actions & HCCA_RIGHT)
51 {
52 actions &= ~HCCA_RIGHT;
53 actions |= HCCA_LEFT;
54 }
55 else
56 {
57 actions &= ~HCCA_LEFT;
58 actions |= HCCA_RIGHT;
59 }
60 break;
61
62 case HCCELLTYPE_BREAK:
63 if (((HCBreak *)map->Cell(row, newCol))->State() == HCBREAKSTATE_NORMAL)
64 {
65 v.x = -v.x;
66 if (actions & HCCA_RIGHT)
67 {
68 actions &= ~HCCA_RIGHT;
69 actions |= HCCA_LEFT;
70 }
71 else
72 {
73 actions &= ~HCCA_LEFT;
74 actions |= HCCA_RIGHT;
75 }
76 }
77 break;
78
79 default:
80 col = newCol;
81 break;
82 }
83
84 s32 newRow = map->ToRow((s32)(pos.y + v.y));
85
86 // Updown collisions
87 switch (map->Cell(newRow, col)->Type())
88 {
89 case HCCELLTYPE_LADDER:
90 case HCCELLTYPE_BAR:
91
92 // New cell is a ladder or a bar
93 switch (state)
94 {
95 case HCCS_UP:
96 case HCCS_DOWN:
97 case HCCS_SLIDE:
98 // In this states do nothing
99 break;
100
101 case HCCS_JUMPLEFT:
102 case HCCS_JUMPRIGHT:
103 case HCCS_JUMP:
104 if (newRow > row && map->Cell(row, col)->Type() == HCCELLTYPE_BLANK)
105 {
106 // Falls over a ladder or bar, must stop
107 v.y = 0.0f;
108 if (actions & HCCA_RIGHT)
109 {
110 actions &= ~HCCA_RIGHT;
111 actions |= HCCA_LEFT;
112 }
113 else
114 {
115 actions &= ~HCCA_LEFT;
116 actions |= HCCA_RIGHT;
117 }
118 }
119 break;
120
121 default:
122 // In any other state, stops the character
123 v.y = 0.0f;
124 break;
125 }
126 break;
127
128 default:
129 if ((map->Cell(newRow, col)->Actions() & HCACTION_FALL) == 0)
130 {
131 v.y = 0.0f;
132
133 switch (state)
134 {
135 // If jumping, must stop
136 case HCCS_JUMPLEFT:
137 case HCCS_JUMPRIGHT:
138 case HCCS_JUMP:
139 if (newRow > row)
140 {
141 actions &= ~HCCA_JUMP;
142 }
143 break;
144
145 case HCCS_DOWN:
146 case HCCS_SLIDE:
147 actions &= ~HCCA_DOWN;
148 break;
149
150 default:
151 break;
152 }
153 }
154 else
155 {
156 if (newRow > row &&
157 state != HCCS_JUMP &&
158 state != HCCS_JUMPLEFT &&
159 state != HCCS_JUMPRIGHT)
160 {
161 actions &= ~HCCA_JUMP;
162 }
163 }
164 break;
165 }
166 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Defines an enemy ball.
23 * @file HCEnemyBall.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 27/05/2004
26 * @version 0.0.1 - 27/05/2004 - First version.
27 */
28
29 #ifndef _HCENEMYBALL_INCLUDED
30 #define _HCENEMYBALL_INCLUDED
31
32 #include <HCEnemy.h>
33 #include <HCLevel.h>
34
35 /** Enemy with the logic of a ball. Only falls, goes left or
36 * right.
37 */
38 class HCEnemyBall : public HCEnemy
39 {
40 public:
41 /** Creates an enemy ball.
42 */
43 HCEnemyBall();
44
45 /** Updates collisions with the map and modifies the state and veloccity according
46 * to the result of the collision tests.
47 */
48 virtual void UpdateCollisions();
49
50 /** Destroys the object and allows scalar destruction.
51 */
52 virtual ~HCEnemyBall() {}
53 };
54
55 #endif // _HCENEMYBALL_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Defines a chaser enemy.
23 * @file HCEnemyChaser.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 27/05/2004
26 * @version 0.0.1 - 27/05/2004 - First version.
27 */
28
29 #include <HCEnemyChaser.h>
30
31 HCEnemyChaser::HCEnemyChaser() : HCEnemy(HCENEMYTYPE_CHASER)
32 {
33 chased = 0;
34 state = HCCS_LEFT;
35 cells = 0;
36 chasePath = 0;
37 tmpPath = 0;
38 chaseIndex = 0;
39 }
40
41 bool HCEnemyChaser::Init(JImageSprite *sprites, HCMap *_map, HCRope **_ropes, s32 nRopes)
42 {
43 if (HCEnemy::Init(sprites, _map, _ropes, nRopes))
44 {
45 // Uses param2 to set search depth for this enemy.
46 // Param2 represents the percentage of the map covered by the search in the greates direction (H or V).
47 searchDepth = (s32)JMax(param2 * (map->Rows() + map->Cols())/10, 3);
48 ResetChaseMap();
49
50 chasePath = new HCChasePath[searchDepth + 2];
51 tmpPath = new HCChasePath[searchDepth + 2];
52
53 return true;
54 }
55
56 return false;
57 }
58
59 void HCEnemyChaser::ResetChaseMap()
60 {
61 if (!cells)
62 {
63 // Creates the cell array from the map
64 cells = new HCChaseCell *[map->Rows()];
65
66 for (s32 j = 0; j < map->Rows(); ++j)
67 {
68 cells[j] = new HCChaseCell[map->Cols()];
69 for (s32 i = 0; i < map->Cols(); ++i)
70 {
71 cells[j][i].cur = map->Cell(j, i);
72 cells[j][i].prev = 0;
73 cells[j][i].tried = 0;
74 cells[j][i].path.row = j;
75 cells[j][i].path.col = i;
76 cells[j][i].path.action = 0;
77 cells[j][i].visited = false;
78 cells[j][i].depth = 0;
79 cells[j][i].numJumpedRows = 0;
80 }
81 }
82 }
83 else
84 {
85 // Only zeroes the chase map
86 for (s32 j = 0; j < map->Rows(); ++j)
87 {
88 for (s32 i = 0; i < map->Cols(); ++i)
89 {
90 cells[j][i].prev = 0;
91
92 // Search optimization
93 switch (map->Cell(j, i)->Type())
94 {
95 case HCCELLTYPE_FLOOR:
96 case HCCELLTYPE_CONTFLOOR:
97 // Blocks this cell and boundary cells towards this cell
98 cells[j][i].tried = HCCHASECELL_CLOSED;
99 if (j > 0) cells[j - 1][i].tried |= HCCA_DOWN;
100 if (i > 0) cells[j][i - 1].tried |= HCCA_RIGHT;
101 if (j < map->Rows()) cells[j + 1][i].tried |= HCCA_UP;
102 if (i < map->Cols()) cells[j][i + 1].tried |= HCCA_LEFT;
103 break;
104
105 case HCCELLTYPE_LADDER:
106 if (map->Cell(j + 1, i - 1)->Type() == HCCELLTYPE_BLANK)
107 {
108 // Can't go left while climbing because there's no floor bellow-left (limitation)
109 cells[j][i].tried |= HCCA_LEFT;
110 }
111
112 if (map->Cell(j + 1, i - 1)->Type() == HCCELLTYPE_BLANK)
113 {
114 // Can't go right while climbing because there's no floor bellow-right (limitation)
115 cells[j][i].tried |= HCCA_LEFT;
116 }
117 break;
118
119 case HCCELLTYPE_BAR:
120 // Cannot go left or right while sliding
121 cells[j][i].tried |= HCCA_LEFT | HCCA_RIGHT;
122 break;
123
124 case HCCELLTYPE_BREAK:
125 if (((HCBreak *)map->Cell(j, i))->State() == HCBREAKSTATE_NORMAL)
126 {
127 // Treats it as a floor
128 if (j > 0) cells[j - 1][i].tried |= HCCA_DOWN;
129 if (i > 0) cells[j][i - 1].tried |= HCCA_RIGHT;
130 if (j < map->Rows()) cells[j + 1][i].tried |= HCCA_UP;
131 if (i < map->Cols()) cells[j][i + 1].tried |= HCCA_LEFT;
132 break;
133 }
134 break;
135
136 default:
137 break;
138 }
139
140 cells[j][i].path.row = j;
141 cells[j][i].path.col = i;
142 cells[j][i].path.action = 0;
143 cells[j][i].visited = false;
144 cells[j][i].depth = 0;
145 cells[j][i].numJumpedRows = 0;
146 }
147 }
148 }
149 }
150
151 /** Goes to the given cell. The cell must be in the same row or in the same column.
152 * @return 0 if going, 1 if reached, 2 before leaving it (at the edge), -1 if unreachable by simple means.
153 */
154 s32 HCEnemyChaser::GoToSimple(s32 row, s32 col)
155 {
156 s32 curRow = map->ToRow((s32)pos.y), curCol = map->ToCol((s32)pos.x);
157
158 if (row != curRow && col != curCol)
159 {
160 return -1;
161 }
162
163 if (row != curRow)
164 {
165 if (row > curRow)
166 {
167 // Going down, test the cells between
168 for (s32 i = curRow; i <= row; ++i)
169 {
170 if (!(map->Cell(i, curCol)->Actions() & HCACTION_DOWN) &&
171 !(map->Cell(i, curCol)->Actions() & HCACTION_FALL))
172 {
173 return -1;
174 }
175 }
176
177 actions = HCCA_DOWN;
178 }
179 else
180 {
181 // Going up, test the cells between
182 for (s32 i = curRow; i >= row; --i)
183 {
184 if (!(map->Cell(i, curCol)->Actions() & HCACTION_UP))
185 {
186 return -1;
187 }
188 }
189
190 actions = HCCA_UP;
191 }
192 }
193 else
194 if (col != curCol)
195 {
196 if (col > curCol)
197 {
198 // Going right, test the cells between
199 for (s32 i = curCol; i <= col; ++i)
200 {
201 if (!(map->Cell(curRow, i)->Actions() & HCACTION_RIGHT))
202 {
203 return -1;
204 }
205 }
206
207 actions = HCCA_RIGHT;
208 }
209 else
210 {
211 // Going left, test the cells between
212 for (s32 i = curCol; i >= col; --i)
213 {
214 if (!(map->Cell(curRow, i)->Actions() & HCACTION_LEFT))
215 {
216 return -1;
217 }
218 }
219
220 actions = HCCA_LEFT;
221 }
222 }
223 else
224 {
225 // Reached
226 return 1;
227 }
228
229 nextRow = row;
230 nextCol = col;
231
232 return 0;
233 }
234
235 void HCEnemyChaser::CheckBestPath()
236 {
237 // Compares the length of each path
238 if (chasePathNumCells > tmpPathNumCells)
239 {
240 //fprintf(stderr, "Mejor path con %d celdas frente a %d\n", tmpPathNumCells, chasePathNumCells);
241 // Tmp path is shorter
242 memcpy(chasePath, tmpPath, (searchDepth + 1) * sizeof(HCChasePath));
243 chasePathNumCells = tmpPathNumCells;
244 }
245 }
246
247 s32 HCEnemyChaser::GoTo(s32 row, s32 col)
248 {
249 if (finalRow != row || finalCol != col || chasePathNumCells == (u32)-1)
250 {
251 s32 curRow = Row(), curCol = Col();
252
253 // New final target cell, computes the best path
254 ResetChaseMap();
255 HCChaseCell *cc = &cells[curRow][curCol]; // Current chase cell
256 HCChaseCell *sc = cc; // Search cell
257 HCChaseCell *tc = &cells[row][col]; // Target cell
258
259 if (sc == tc)
260 {
261 return 0;
262 }
263
264 HCChaseCell *tmp; // Temporary cell
265 HCCell *c, bellow; // Current map cell and cell bellow
266 sc->visited = true;
267
268 s32 index = 0; // Index into the search path
269 chasePathNumCells = (u32)-1; // Init to greatest u32 so it's always worse
270 tmpPathNumCells = 0;
271
272 s32 pathNum = 0;
273
274 while (1)
275 {
276 c = sc->cur;
277 // SDL_Rect rc;
278 // rc.x = map->ToX(sc->path.col) - 2;
279 // rc.y = map->ToY(sc->path.row) - (map->CellHeight()/2 - 2);
280 // rc.w = 2;
281 // rc.h = 2;
282
283 // SDL_FillRect(SDL_GetVideoSurface(), &rc, 0xffffffff);
284 // SDL_UpdateRect(SDL_GetVideoSurface(), rc.x, rc.y, rc.w, rc.h);
285 // fprintf(stderr, "Path %d: Estoy en %d %d index es %d searchDepth es %d ", pathNum, sc->path.row, sc->path.col, index, searchDepth);
286 // fprintf(stderr,
287 // "ACCIONES PROBADAS: %s %s %s %s (%s)\n",
288 // (sc->tried & HCCA_LEFT) ? "L" : " ",
289 // (sc->tried & HCCA_RIGHT) ? "R" : " ",
290 // (sc->tried & HCCA_UP) ? "U" : " ",
291 // (sc->tried & HCCA_DOWN) ? "D" : " ",
292 // sc->visited ? "*** VISITED! ***" : "not visited");
293 // getchar();
294
295 if (sc->depth > searchDepth)
296 {
297 // Maximum reachable search depth reached!, stop searching in this cell
298 sc->tried = HCCHASECELL_CLOSED;
299 }
300
301 if (map->Cell(sc->path.row + 1, sc->path.col)->Type() == HCCELLTYPE_BLANK && sc->prev && !(sc->prev->path.action & HCCA_JUMP))
302 {
303 // Only go by floor, don't jump or fall off in ladders
304 sc->tried |= (HCCA_LEFT | HCCA_RIGHT);
305 }
306
307 if (!(sc->tried & HCCA_DOWN))
308 {
309 // Goes to the neighbour bellow
310 sc->tried |= HCCA_DOWN;
311 tmp = &cells[sc->path.row + 1][sc->path.col];
312
313 if (sc->path.row < map->Rows() &&
314 ((c->Actions() & HCACTION_DOWN) ||
315 (c->Actions() & HCACTION_FALL) ||
316 (map->Cell(sc->path.row + 1, sc->path.col)->Actions() & HCACTION_DOWN)) &&
317 !tmp->visited)
318 {
319 tmp->prev = sc;
320 tmpPath[index].row = sc->path.row;
321 tmpPath[index].col = sc->path.col;
322 tmpPath[index].action = HCCA_DOWN;
323 ++index;
324 sc->visited = true;
325 tmp->depth = sc->depth + 1;
326 sc = tmp;
327 sc->tried |= HCCA_UP;
328 }
329 }
330 else
331 if (!(sc->tried & HCCA_LEFT))
332 {
333 // Goes to the left neighbour
334 sc->tried |= HCCA_LEFT;
335 tmp = &cells[sc->path.row][sc->path.col - 1];
336
337 if ((c->Actions() & HCACTION_LEFT) && sc->path.col > 0 && !tmp->visited)
338 {
339 tmp->prev = sc;
340 tmpPath[index].row = sc->path.row;
341 tmpPath[index].col = sc->path.col;
342 tmpPath[index].action = HCCA_LEFT;
343 ++index;
344 sc->visited = true;
345 tmp->depth = sc->depth + 1;
346 sc = tmp;
347 sc->tried |= HCCA_RIGHT;
348 }
349 }
350 else
351 if (!(sc->tried & HCCA_RIGHT))
352 {
353 // Goes to the right neighbour
354 sc->tried |= HCCA_RIGHT;
355 tmp = &cells[sc->path.row][sc->path.col + 1];
356
357 if ((c->Actions() & HCACTION_RIGHT) && sc->path.col < map->Cols() && !tmp->visited)
358 {
359 tmp->prev = sc;
360 tmpPath[index].row = sc->path.row;
361 tmpPath[index].col = sc->path.col;
362 tmpPath[index].action = HCCA_RIGHT;
363 ++index;
364 sc->visited = true;
365 tmp->depth = sc->depth + 1;
366 sc = tmp;
367 sc->tried |= HCCA_LEFT;
368 }
369 }
370 else
371 if (!(sc->tried & HCCA_UP))
372 {
373 // Goes to the upper neighbour
374 sc->tried |= HCCA_UP;
375 tmp = &cells[sc->path.row - 1][sc->path.col];
376 /* bool cellBellow = sc->path.row < map->Rows();
377 HCCell *lower = 0;
378 if (cellBellow)
379 {
380 //lower = map->Cell(sc->path.row + 1, sc->path.col);
381 lower = map->Cell(sc->path.row, sc->path.col);
382 }*/
383
384 if (sc->path.row > 0 && !tmp->visited)
385 {
386 // Tests up
387 if ((c->Actions() & HCACTION_UP)/* || // Current cell allows going up or
388 (cellBellow && (lower->Actions() & HCACTION_UP))*/) // lower allows going up (since sprite's hotspot for up is above)
389 {
390 tmp->prev = sc;
391 sc->visited = true;
392 tmpPath[index].row = sc->path.row;
393 tmpPath[index].col = sc->path.col;
394 tmpPath[index].action = HCCA_UP;
395 ++index;
396 tmp->depth = sc->depth + 1;
397 sc = tmp;
398 sc->tried |= HCCA_DOWN;
399 }
400 }
401 }
402 /*
403 else
404 if (!(sc->tried & HCCA_JUMP))
405 {
406 // Goes to the upper neighbour
407 sc->tried |= HCCA_JUMP;
408 tmp = &cells[sc->path.row - 1][sc->path.col];
409 bool cellBellow = sc->path.row < map->Rows();
410 HCCell *lower = 0;
411 if (cellBellow)
412 {
413 lower = map->Cell(sc->path.row + 1, sc->path.col);
414 }
415
416 if (sc->path.row > 0 && !tmp->visited)
417 {
418 // Tests jump
419 if ((c->Actions() & HCACTION_FALL) && // current allows jumping and, or
420 ((cellBellow && !(lower->Actions() & HCACTION_FALL)) || // there is floor bellow, or
421 (sc->prev && (sc->prev->action & HCCA_JUMP) && sc->numJumpedRows < maxJumpRows))) // previous action was jump and not reached yet
422 // the jump limit (phew!)
423 {
424 fprintf(stderr, "Salto funciona %d saltadas %d max\n", sc->numJumpedRows, maxJumpRows);
425 getchar();
426 tmp->prev = sc;
427 sc->visited = true;
428 tmpPath[index].row = sc->path.row;
429 tmpPath[index].col = sc->path.col;
430 tmpPath[index].action = HCCA_JUMP;
431 ++index;
432 tmp->depth = sc->depth + 1;
433 sc = tmp;
434 sc->tried |= HCCA_DOWN;
435
436 if (sc->prev)
437 {
438 sc->numJumpedRows = sc->prev->numJumpedRows + 1;
439 }
440 else
441 {
442 sc->numJumpedRows = 1;
443 }
444 }
445 }
446 }*/
447 else
448 {
449 // rc.x = map->ToX(sc->path.col) - 2;
450 // rc.y = map->ToY(sc->path.row) - (map->CellHeight()/2 - 2);
451 // rc.w = 2;
452 // rc.h = 2;
453
454 // SDL_FillRect(SDL_GetVideoSurface(), &rc, 0x00000000);
455 // SDL_UpdateRect(SDL_GetVideoSurface(), rc.x, rc.y, rc.w, rc.h);
456 // getchar();
457
458 // Closed cell
459 sc->tried = 0;
460 sc->visited = false;
461 sc->depth = 0;
462 sc->numJumpedRows = 0;
463 sc = sc->prev;
464
465 if (index > 0)
466 --index;
467
468 if (sc)
469 {
470 sc->visited = false;
471 }
472 else
473 {
474 // Starting cell closed, done
475 //fprintf(stderr, "CLOSED!\n");
476 break;
477 }
478 }
479
480 if (sc == tc)
481 {
482 // The map now contains the search path
483 //fprintf(stderr, "Encontrado, index es %d searchDepth es %d!\n", index, searchDepth);
484
485 if (sc)
486 {
487 sc->visited = false;
488
489 if (sc->prev)
490 {
491 tmpPath[index].row = sc->path.row;
492 tmpPath[index].col = sc->path.col;
493 tmpPath[index].action = sc->path.action;
494 }
495
496 finalRow = row;
497 finalCol = col;
498
499 ++pathNum;
500 tmpPathNumCells = index + 1;
501 CheckBestPath();
502
503 // Continue searching paths
504 sc->visited = false;
505 sc->depth = 0;
506 sc->numJumpedRows = 0;
507 sc = sc->prev;
508
509 if (sc)
510 {
511 sc->visited = false;
512 }
513
514 if (index > 0)
515 --index;
516
517 // Searchs ends after param2 successfull paths have been tried
518 if (pathNum > param2)
519 {
520 break;
521 }
522 }
523 else
524 {
525 break;
526 }
527 }
528 }
529
530 if (pathNum != 0)
531 {
532 chaseIndex = 0;
533 return 0;
534 }
535 else
536 {
537 //fprintf(stderr, "NO PATH FOUND!\n");
538 return -1;
539 }
540 }
541
542 // OK, going
543 return 0;
544 }
545
546 s32 HCEnemyChaser::UpdateChase()
547 {
548 if (chased == 0)
549 {
550 return 0;
551 }
552
553 actions = 0;
554 s32 r = map->ToRow((s32)chased->Y()), c = map->ToCol((s32)chased->X());
555 s32 curRow = Row(), curCol = Col();
556
557 if (chased->State() == HCCS_JUMP ||
558 chased->State() == HCCS_JUMPLEFT ||
559 chased->State() == HCCS_JUMPRIGHT ||
560 chased->State() == HCCS_HANG ||
561 (abs(curRow - r) + abs(curCol - c) <= searchDepth && 0 == GoTo(r, c)))
562 {
563 if (chasePath[chaseIndex].col != curCol || chasePath[chaseIndex].row != curRow && chaseIndex < searchDepth - 1)
564 {
565 // Updates the chase index within the path when the row or column changes
566 ++chaseIndex;
567 }
568
569 if (chasePath[chaseIndex].col == curCol && chasePath[chaseIndex].row == curRow)
570 {
571 // OK, path hasn't been lost
572 actions = chasePath[chaseIndex].action;
573
574 // Resets idle movement
575 nextRow = curRow;
576 nextCol = curCol;
577 return 0;
578 }
579 else
580 {
581 // Path lost
582 chasePathNumCells = (u32)-1;
583 }
584 }
585
586 // No path to target, moves-simple to the randomly generated cell; if reached, select another one
587 if (-1 == GoToSimple(nextRow, nextCol))
588 {
589 // Selects a random cell within the search depth square and tries to simple move over there,
590 // when the chased character is not reachable
591 s32 sign;
592
593 switch (rand()%4)
594 {
595 case 0:
596 case 1:
597 case 3:
598 sign = (rand()%2) == 0 ? 1 : -1;
599 r = sign * ((rand()%searchDepth) + 1);
600 if (0 != GoToSimple(curRow + r, curCol))
601 {
602 c = sign * ((rand()%searchDepth) + 1);
603 return GoToSimple(curRow, curCol + c);
604 }
605 break;
606
607 case 2:
608 sign = (rand()%2) == 0 ? 1 : -1;
609 c = sign * (rand()%searchDepth) + 1;
610 if (0 != GoToSimple(curRow, curCol + c))
611 {
612 r = sign * ((rand()%searchDepth) + 1);
613 return GoToSimple(curRow + r, curCol);
614 }
615 break;
616 }
617 }
618
619 return 0;
620 }
621
622 s32 HCEnemyChaser::Update()
623 {
624 states[state].Update();
625 UpdateChase();
626 Act(actions);
627
628 if (state == HCCS_HANG)
629 {
630 UpdateHang();
631 }
632 else
633 {
634 UpdateVeloccity();
635
636 // OJITO, igual se hace pesado!!
637 CheckHang();
638 }
639
640 // Collisions
641 UpdateCollisions();
642
643 Pos(pos.x + v.x, pos.y + v.y);
644
645 // Updates dialogs
646 UpdateDialog();
647
648 return 0;
649 }
650
651 void HCEnemyChaser::Destroy()
652 {
653 if (cells)
654 {
655 for (s32 j = 0; j < map->Rows(); ++j)
656 {
657 JDELETE_ARRAY(cells[j]);
658 }
659
660 // Creates the cell array from the map
661 delete[] cells;
662 }
663
664 JDELETE_ARRAY(chasePath);
665 JDELETE_ARRAY(tmpPath);
666 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Defines a chaser enemy.
23 * @file HCEnemyChaser.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 27/05/2004
26 * @version 0.0.1 - 27/05/2004 - First version.
27 */
28
29 #ifndef _HCENEMYCHASER_INCLUDED
30 #define _HCENEMYCHASER_INCLUDED
31
32 #include <HCEnemy.h>
33 #include <HCLevel.h>
34 #include <vector>
35
36 #define HCCHASECELL_CLOSED HCCA_UP | HCCA_DOWN | HCCA_LEFT | HCCA_RIGHT
37
38 /** Chase path element.
39 */
40 struct HCChasePath
41 {
42 s32 row; /**< Row of the cell. */
43 s32 col; /**< Column of the cell. */
44 u32 action; /**< Action to perform in this cell. */
45 };
46
47 /** Cell for chase calculations.
48 */
49 struct HCChaseCell
50 {
51 HCChasePath path; /**< Path info. */
52 u32 tried; /**< Tried actions. */
53 bool visited; /**< Flag controlling whether it belongs to the current path or not. */
54 s32 numJumpedRows; /**< Number of rows jumped. */
55 s32 depth; /**< Search depth reached. */
56 HCCell *cur; /**< This chase cell into the map. */
57 HCChaseCell *prev; /**< Previous cell in the search path. */
58 };
59
60 /** Enemy with the logic of a chaser. Goes everywhere
61 * (even jumping or sliding) to reach Ybelle.
62 */
63 class HCEnemyChaser : public HCEnemy
64 {
65 HCCharacter *chased; /**< Chased character. */
66 HCChaseCell **cells; /**< Matrix of chasing cells. */
67
68 HCChasePath *chasePath; /**< Chase path. */
69 u32 chasePathNumCells; /**< Number of cells in the chase path. */
70 s32 chaseIndex; /**< Index within the search path. */
71
72 HCChasePath *tmpPath; /**< Temporary path. */
73 u32 tmpPathNumCells; /**< Number of cells in the temporary path. */
74
75 s32 searchDepth; /**< Maximum number of chase steps. */
76 s32 finalRow; /**< Final row to reach. */
77 s32 finalCol; /**< Final column to reach. */
78 s32 nextRow; /**< Next row to reach. */
79 s32 nextCol; /**< Next column to reach. */
80
81 /** Resets chase cells for a new search.
82 */
83 void ResetChaseMap();
84
85 /** Goes to the given cell. The cell must be in the same row or in the same column.
86 * @param row Row to reach.
87 * @param col Column to reach.
88 * @return 0 if it's reachable, 1 if reached, -1 if not reachable.
89 */
90 s32 GoToSimple(s32 row, s32 col);
91
92 /** Goes to the given cell using GoToSimple() sequences.
93 * @return 0 if going, 1 if reached, 2 before leaving it (at the edge), -1 if not reachable.
94 */
95 s32 GoTo(s32 row, s32 col);
96
97 public:
98 /** Creates a chaser enemy.
99 */
100 HCEnemyChaser();
101
102 /** Initializes this enemy.
103 * @param sprites Sprites for this enemy.
104 * @param _map Map for this enemy.
105 * @param _ropes Ropes this enemy must check.
106 * @param nRopes Number of ropes this enemy must check.
107 * @return <b>true</b> if everything goes well, <b>false</b> otherwise.
108 */
109 virtual bool Init(JImageSprite *sprites, HCMap *_map, HCRope **_ropes = 0, s32 nRopes = 0);
110
111 /** Updates the chase.
112 * @return Return value of the associated drawable's update.
113 */
114 s32 UpdateChase();
115
116 /** Updates the character.
117 * @return Return value of the associated drawable's update.
118 */
119 virtual s32 Update();
120
121 /** Makes this enemy chase the given character.
122 * @param character Character to chase, 0 for none
123 */
124 void Chase(HCCharacter *character) {chased = character;}
125
126 /** Checks whether the temporary path is best than the actual path and updates it if so.
127 */
128 void CheckBestPath();
129
130 /** Destroys the object and allows scalar destruction.
131 */
132 void Destroy();
133
134 /** Destroys the object and allows scalar destruction.
135 */
136 virtual ~HCEnemyChaser() {Destroy();}
137 };
138
139 #endif // _HCENEMYCHASER_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Defines an enemy maker.
23 * @file HCEnemyMaker.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 27/05/2004
26 * @version 0.0.1 - 27/05/2004 - First version.
27 */
28
29 #include <HCEnemyMaker.h>
30
31 HCEnemyMaker::HCEnemyMaker() : HCEnemy(HCENEMYTYPE_MAKER)
32 {}
33
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Defines an enemy maker.
23 * @file HCEnemyMaker.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 27/05/2004
26 * @version 0.0.1 - 27/05/2004 - First version.
27 */
28
29 #ifndef _HCENEMYMAKER_INCLUDED
30 #define _HCENEMYMAKER_INCLUDED
31
32 #include <HCEnemy.h>
33 #include <HCLevel.h>
34
35 /** Enemy with the logic of a maker. Can create enemies and move
36 * around limitedly.
37 */
38 class HCEnemyMaker : public HCEnemy
39 {
40 public:
41 /** Creates an enemy maker.
42 */
43 HCEnemyMaker();
44
45 /** Destroys the object and allows scalar destruction.
46 */
47 virtual ~HCEnemyMaker() {}
48 };
49
50 #endif // _HCENEMYMAKER_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Defines a random enemy.
23 * @file HCEnemyRandom.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 27/05/2004
26 * @version 0.0.1 - 27/05/2004 - First version.
27 */
28
29 #include <HCEnemyRandom.h>
30
31 HCEnemyRandom::HCEnemyRandom() : HCEnemy(HCENEMYTYPE_RANDOM)
32 {
33 lastCol = lastRow = 0;
34 }
35
36 s32 HCEnemyRandom::Update()
37 {
38 s32 ret = HCEnemy::Update();
39 s32 col = map->ToCol((s32)pos.x);
40 s32 row = map->ToRow((s32)pos.y);
41
42 if (state == HCCS_STOP || actions == 0 || states[state].Paused())
43 {
44 s32 rnd = rand() % 4;
45 u32 guess[4];
46 for (s32 i = 0; i < 4; ++i)
47 {
48 guess[i] = 1 << ((rnd + i)% 4);
49 }
50
51 if (map->Cell(row, col - 1)->Actions() & guess[0])
52 {
53 actions = guess[0];
54 }
55 else if (map->Cell(row, col + 1)->Actions() & guess[1])
56 {
57 actions = guess[1];
58 }
59 else if (map->Cell(row, col)->Actions() & guess[2])
60 {
61 actions = guess[2];
62 }
63 else if (map->Cell(row + 1, col)->Actions() & guess[3])
64 {
65 actions = guess[3];
66 }
67 }
68 else
69 {
70 if (lastCol != col || lastRow != row)
71 {
72 lastCol = col;
73 lastRow = row;
74 s32 random = rand() % 10;
75
76 // Only if it has moved 1 cell or more
77 switch (state)
78 {
79 // If walking and a ladder or bar is nearby, decide to use it or not
80 case HCCS_LEFT:
81 case HCCS_RIGHT:
82 switch (random)
83 {
84 default:
85 // Current cell
86 if (map->Cell(row, col)->Type() == HCCELLTYPE_LADDER)
87 {
88 actions = HCCA_UP;
89 }
90 break;
91
92 case 0:
93 case 1:
94 // Lower cell
95 if (map->Cell(row+1, col)->Type() == HCCELLTYPE_BAR ||
96 map->Cell(row+1, col)->Type() == HCCELLTYPE_LADDER)
97 {
98 actions = HCCA_DOWN;
99 }
100 else
101 // Current cell
102 if (map->Cell(row, col)->Type() == HCCELLTYPE_LADDER)
103 {
104 actions = HCCA_UP;
105 }
106 break;
107 }
108 break;
109
110 // If going up or down, checks for floor at the sides
111 case HCCS_UP:
112 case HCCS_DOWN:
113 switch (random)
114 {
115 default:
116 // Lower left cell
117 if (!(map->Cell(row + 1, col - 1)->Actions() & HCACTION_FALL))
118 {
119 actions = HCCA_LEFT;
120 break;
121 }
122 break;
123
124 case 0:
125 case 1:
126 case 2:
127 case 3:
128 // Lower right cell
129 if (!(map->Cell(row + 1, col + 1)->Actions() & HCACTION_FALL))
130 {
131 actions = HCCA_RIGHT;
132 break;
133 }
134 break;
135 }
136 break;
137
138 default:
139 break;
140 }
141 }
142 }
143
144 return ret;
145 }
146
147 void HCEnemyRandom::UpdateCollisions()
148 {
149 float newX = pos.x + v.x;
150 float newY = pos.y + v.y;
151 s32 row = map->ToRow((s32)pos.y), col = map->ToCol((s32)pos.x);
152 s32 newCol = map->ToCol((s32)(newX));
153 s32 newRow = map->ToRow((s32)(newY));
154
155 // Side collisions
156 switch (map->Cell(row, newCol)->Type())
157 {
158 case HCCELLTYPE_FLOOR:
159 case HCCELLTYPE_CONTFLOOR:
160 v.x = a.x = 0;
161 actions = 0;
162 state = HCCS_STOP;
163 break;
164
165 case HCCELLTYPE_BREAK:
166 if (((HCBreak *)map->Cell(row, newCol))->State() == HCBREAKSTATE_NORMAL)
167 {
168 v.x = a.x = 0;
169 actions = 0;
170 state = HCCS_STOP;
171 }
172 break;
173
174 default:
175 col = newCol;
176 break;
177 }
178
179 // Updown collisions
180 switch (map->Cell(newRow, col)->Type())
181 {
182 case HCCELLTYPE_LADDER:
183 case HCCELLTYPE_BAR:
184
185 // New cell is a ladder or a bar
186 switch (state)
187 {
188 case HCCS_UP:
189 case HCCS_DOWN:
190 case HCCS_SLIDE:
191 // In this states do nothing
192 break;
193
194 case HCCS_JUMPLEFT:
195 case HCCS_JUMPRIGHT:
196 case HCCS_JUMP:
197 if (newRow > row && map->Cell(row, col)->Type() == HCCELLTYPE_BLANK)
198 {
199 // Falls over a ladder or bar, must stop
200 v.y = 0.0f;
201 state = HCCS_STOP;
202 FixY(row);
203
204 if (actions & HCCA_RIGHT)
205 {
206 actions &= ~HCCA_RIGHT;
207 actions |= HCCA_LEFT;
208 }
209 else
210 {
211 actions &= ~HCCA_LEFT;
212 actions |= HCCA_RIGHT;
213 }
214 }
215 break;
216
217 case HCCS_DIE:
218 if (newRow > row && map->Cell(row, col)->Type() == HCCELLTYPE_BLANK)
219 {
220 // Falls over a ladder or bar, must stop
221 v.y = 0.0f;
222 }
223 break;
224
225 default:
226 // In any other state, stops the character
227 v.y = 0.0f;
228 break;
229 }
230 break;
231
232 default:
233 if ((map->Cell(newRow, col)->Actions() & HCACTION_FALL) == 0)
234 {
235 v.y = 0.0f;
236
237 switch (state)
238 {
239 // If jumping, must stop
240 case HCCS_JUMPLEFT:
241 case HCCS_JUMPRIGHT:
242 case HCCS_JUMP:
243 if (newRow > row)
244 {
245 actions &= ~HCCA_JUMP;
246
247 // Stands over the floor
248 state = HCCS_STOP;
249 FixY(row);
250 }
251 break;
252
253 case HCCS_DOWN:
254 case HCCS_SLIDE:
255 actions &= ~HCCA_DOWN;
256
257 // Stands over the floor
258 state = HCCS_STOP;
259
260 FixY(row);
261 break;
262
263 case HCCS_DIE:
264 if (newRow > row)
265 {
266 // Stands over the floor
267 FixY(row);
268 }
269 break;
270
271 default:
272 break;
273 }
274 }
275 else
276 {
277 if (newRow > row &&
278 state != HCCS_JUMP &&
279 state != HCCS_JUMPLEFT &&
280 state != HCCS_JUMPRIGHT)
281 {
282 actions &= ~HCCA_JUMP;
283 State(HCCS_JUMP);
284 }
285 }
286 break;
287 }
288 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Defines a random enemy.
23 * @file HCEnemyRandom.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 27/05/2004
26 * @version 0.0.1 - 27/05/2004 - First version.
27 */
28
29 #ifndef _HCENEMYRANDOM_INCLUDED
30 #define _HCENEMYRANDOM_INCLUDED
31
32 #include <HCLevel.h>
33 #include <HCEnemy.h>
34
35 /** Enemy that moves pseudo-randomly. Behaves like a ball but can go up and down too.
36 */
37 class HCEnemyRandom : public HCEnemy
38 {
39 s32 lastRow; /**< Last visited row. */
40 s32 lastCol; /**< Last visited col. */
41
42 public:
43 /** Creates an enemy random.
44 */
45 HCEnemyRandom();
46
47 /** Updates the character.
48 * @return Return value of the associated drawable's update.
49 */
50 virtual s32 Update();
51
52 /** Updates collisions with the map and modifies the state and veloccity according
53 * to the result of the collision tests.
54 */
55 virtual void UpdateCollisions();
56
57 /** Destroys the object and allows scalar destruction.
58 */
59 virtual ~HCEnemyRandom() {}
60 };
61
62 #endif // _HCENEMYRANDOM_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Defines an static enemy.
23 * @file HCEnemyStatic.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 27/05/2004
26 * @version 0.0.1 - 27/05/2004 - First version.
27 */
28
29 #include <HCEnemyStatic.h>
30
31 HCEnemyStatic::HCEnemyStatic() : HCEnemy(HCENEMYTYPE_STATIC)
32 {}
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Defines a static enemy.
23 * @file HCEnemyStatic.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 27/05/2004
26 * @version 0.0.1 - 27/05/2004 - First version.
27 */
28
29 #ifndef _HCENEMYSTATIC_INCLUDED
30 #define _HCENEMYSTATIC_INCLUDED
31
32 #include <HCEnemy.h>
33 #include <HCLevel.h>
34
35 /** Static enemy. Only stays (kind of trap).
36 */
37 class HCEnemyStatic : public HCEnemy
38 {
39 public:
40 /** Creates an enemy static.
41 */
42 HCEnemyStatic();
43
44 /** Updates the enemy.
45 * @return Return value of the associated drawable's update.
46 */
47 virtual s32 Update() {return states[state].Update();}
48
49 /** Destroys the object and allows scalar destruction.
50 */
51 virtual ~HCEnemyStatic() {}
52 };
53
54 #endif // _HCENEMYSTATIC_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Exit gadget for Holtz's castle game.
23 * @file HCExit.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 17/08/2004
26 * @version 0.0.1 - 17/08/2004 - First version.
27 */
28
29 #include <HCExit.h>
30
31 HCExit::HCExit() : map(0), state(HCEXITSTATE_LOCKED), x1(0), y1(0),
32 sparks(0), numSparks(0), character(0), imgCharacter(0)
33 {
34 }
35
36 bool HCExit::Init(HCMap *_map, s32 nSparks, s32 w)
37 {
38 if (!_map)
39 return false;
40
41 map = _map;
42
43 if (nSparks <= 0)
44 {
45 nSparks = 1;
46 }
47
48 Destroy();
49 numSparks = nSparks;
50 sparks = new HCExitSpark[numSparks];
51
52 // Hangs from the ceiling of the cell
53 pos.x = map->ToX(map->ExitCol()) - (map->CellWidth()/2);
54 pos.y = map->ToY(map->ExitRow()) - (map->CellHeight() - 1);
55
56 float x0 = pos.x, y0 = pos.y;
57 x1 = x0 + (w == 0 ? map->CellWidth() : w);
58
59 // Computes the height of the exit box
60 s32 i, j;
61 bool end = false;
62 for (j = map->ExitRow() + 1, i = map->ExitCol(); !end && j < map->Rows(); ++j)
63 {
64 if (map->Cell(j, i)->Type() != HCCELLTYPE_BLANK)
65 {
66 end = true;
67 }
68 }
69
70 y1 = map->ToY((j > 0 ? j - 2: 1));
71
72 // Randomly initializes the sparks into the exit box
73 srand(time(0));
74
75 for (s32 k = 0; k < numSparks; ++k)
76 {
77 sparks[k].c.r = 255;//128 + (rand()%127);
78 sparks[k].c.g = 255;//128 + (rand()%127);
79 sparks[k].c.b = 255;//128 + (rand()%127);
80 sparks[k].y = y0;
81 sparks[k].vy = -(1.7 + (float(rand()%50)/50.0f));
82 sparks[k].c.g = sparks[k].c.r = 0;
83 sparks[k].x = x0 + (rand()%s32(x1 - x0));
84 sparks[k].y = y0 + (rand()%s32(y1 - y0));
85 sparks[k].vy = -(0.1 + (float(rand()%50)/500.0f));
86 sparks[k].vx = -sparks[k].vy * (((x1 - x0)/2) - (sparks[k].x - x0))/(y1 - y0);
87 sparks[k].dc = 255 - (u8)(255.0f * (float(y1 - sparks[k].y)/(y1 - y0)));
88 }
89
90 // Sets the timer to 25 FPS
91 timer.Start(1000/25);
92
93 // By default, the exit is locked
94 Lock();
95
96 return true;
97 }
98
99 void HCExit::Draw()
100 {
101 switch (state)
102 {
103 default:
104 case HCEXITSTATE_LOCKED:
105 {
106 JImage img(SDL_GetVideoSurface());
107 if (0 == img.Lock())
108 {
109 for (s32 k = 0; k < numSparks; ++k)
110 {
111 if (sparks[k].x > 0 && sparks[k].x < JApp::App()->Width() &&
112 sparks[k].y > 0 && sparks[k].y < JApp::App()->Height())
113 {
114 img.PutPixel((s32)sparks[k].x, (s32)sparks[k].y,
115 SDL_MapRGB(img.Format(),
116 sparks[k].c.r,
117 sparks[k].c.g,
118 sparks[k].c.b));
119 }
120 }
121
122 img.Unlock();
123 }
124 }
125 break;
126
127 case HCEXITSTATE_SWALLOWING:
128 case HCEXITSTATE_UNLOCKED:
129 {
130 JImage img(SDL_GetVideoSurface());
131
132 if (0 == img.Lock())
133 {
134 for (s32 k = 0; k < numSparks; ++k)
135 {
136 if (sparks[k].x > 0 && sparks[k].x < JApp::App()->Width() &&
137 sparks[k].y > 0 && sparks[k].y < JApp::App()->Height() - 3)
138 {
139 for (s32 i = 0; i < 3; ++i)
140 {
141 img.PutPixel((s32)sparks[k].x, (s32)sparks[k].y + i,
142 SDL_MapRGB(img.Format(),
143 (sparks[k].c.r/(i+1)),
144 (sparks[k].c.g/(i+1)),
145 (sparks[k].c.b)));
146 }
147 }
148 }
149
150 img.Unlock();
151 }
152 }
153 break;
154 }
155 }
156
157 s32 HCExit::Update()
158 {
159 if (!timer.Changed())
160 return 0;
161
162 float x0 = pos.x, y0 = pos.y;
163
164 switch (state)
165 {
166 default:
167 case HCEXITSTATE_LOCKED:
168 for (s32 k = 0; k < numSparks; ++k)
169 {
170 if (sparks[k].y < pos.y)
171 {
172 sparks[k].vy = -(1.7 + (float(rand()%50)/50.0f));
173 sparks[k].c.g = sparks[k].c.r = 0;
174 sparks[k].x = x0 + (rand()%s32(x1 - x0));
175 sparks[k].y = y0 + (rand()%s32(y1 - y0));
176 sparks[k].vy = -(0.1 + (float(rand()%50)/500.0f));
177 sparks[k].vx = -sparks[k].vy * (((x1 - x0)/2) - (sparks[k].x - x0))/(y1 - y0);
178 sparks[k].dc = 255 - (u8)(255.0f * (float(y1 - sparks[k].y)/(y1 - y0)));
179 }
180 sparks[k].c.r += sparks[k].dc;
181 sparks[k].c.g += sparks[k].dc;
182 sparks[k].x += sparks[k].vx;
183 sparks[k].y += sparks[k].vy;
184 }
185 break;
186
187 case HCEXITSTATE_UNLOCKED:
188 for (s32 k = 0; k < numSparks; ++k)
189 {
190 if (sparks[k].y <= y0)
191 {
192 sparks[k].c.g = sparks[k].c.r = 0;
193 sparks[k].x = x0 + (rand()%s32(x1 - x0));
194 sparks[k].y = y0 + (rand()%s32(y1 - y0));
195 sparks[k].vy = -(4.7 + (float(rand()%10)/5.0f));
196 sparks[k].vx = -sparks[k].vy * 0.1f * (((x1 - x0)/2) - (sparks[k].x - x0))/(x1 - x0);
197 sparks[k].vx = -sparks[k].vy * (((x1 - x0)/2) - (sparks[k].x - x0))/(y1 - y0);
198 sparks[k].dc = 255 - (u8)(255.0f * (float(y1 - sparks[k].y)/(y1 - y0)));
199 }
200 sparks[k].c.g += sparks[k].dc;
201 sparks[k].c.r += sparks[k].dc;
202 sparks[k].x += sparks[k].vx;
203 sparks[k].y += sparks[k].vy;
204 }
205 break;
206
207 case HCEXITSTATE_SWALLOWING:
208 for (s32 k = 0; k < numSparks; ++k)
209 {
210 if (sparks[k].y <= y0)
211 {
212 // Faster, from top to the character's feet
213 sparks[k].c.g = sparks[k].c.r = 0;
214 sparks[k].x = x0 + (rand()%s32(x1 - x0));
215 sparks[k].y = character->Y();//y0 + (rand()%s32(character->Y() - y0 + 5));
216 sparks[k].vy = -(6.7 + (float(rand()%10)/2.0f));
217 sparks[k].vx = -sparks[k].vy * 0.1f * (((x1 - x0)/2) - (sparks[k].x - x0))/(x1 - x0);
218 sparks[k].vx = -sparks[k].vy * (((x1 - x0)/2) - (sparks[k].x - x0))/(y1 - y0);
219 sparks[k].dc = 255 - (u8)(255.0f * (float(y1 - sparks[k].y)/(y1 - y0)));
220 }
221 sparks[k].c.g += sparks[k].dc;
222 sparks[k].c.r += sparks[k].dc;
223 sparks[k].x += sparks[k].vx;
224 sparks[k].y += sparks[k].vy;
225 }
226
227 if (character->Y() <= (y0 + map->CellHeight()))
228 {
229 // Done swallowing
230 state = HCEXITSTATE_SWALLOWED;
231 }
232 else
233 {
234 character->Pos(character->X(), character->Y() + character->Veloccity().y);
235 }
236 break;
237
238 case HCEXITSTATE_SWALLOWED:
239 break;
240 }
241
242 return 1;
243 }
244
245 void HCExit::Unlock()
246 {
247 // Suddenly accelerates the sparks
248 state = HCEXITSTATE_UNLOCKED;
249 for (s32 k = 0; k < numSparks; ++k)
250 {
251 sparks[k].vy = -(1.7 + (float(rand()%10)/5.0f));
252 }
253 }
254
255 void HCExit::Swallow(HCCharacter *ch)
256 {
257 state = HCEXITSTATE_SWALLOWING;
258 character = ch;
259 character->State(HCCS_STOP);
260 character->Veloccity().y = -5.0f;
261
262 // Calculates the veloccity to end in the midpoint of the ceiling
263 character->Veloccity().x = character->Veloccity().y * (((character->X() - pos.x) - (x1 - pos.x)/2))/(y1 - pos.y);
264 }
265
266 void HCExit::Pos(float xPos, float yPos)
267 {
268 float dx = xPos - pos.x, dy = yPos - pos.y;
269 pos.x = xPos;
270 pos.y = yPos;
271 x1 += dx;
272 y1 += dy;
273
274 for (s32 k = 0; k < numSparks; ++k)
275 {
276 sparks[k].x += dx;
277 sparks[k].y += dy;
278 }
279 }
280
281 void HCExit::Destroy()
282 {
283 JDELETE_ARRAY(sparks);
284 JDELETE(imgCharacter);
285 }
286
287 HCExit::~HCExit()
288 {
289 Destroy();
290 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Exit gadget for Holtz's castle game.
23 * @file HCExit.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 17/08/2004
26 * @version 0.0.1 - 17/08/2004 - First version.
27 */
28
29 #ifndef _HCEXIT_INCLUDED
30 #define _HCEXIT_INCLUDED
31
32 #include <JLib/Graphics/JDrawable.h>
33 #include <JLib/Util/JTypes.h>
34 #include <JLib/Util/JTimer.h>
35 #include <JLib/Util/JApp.h>
36 #include <HCCharacter.h>
37 #include <HCMap.h>
38
39 /** State of this exit object.
40 */
41 typedef enum
42 {
43 HCEXITSTATE_LOCKED = 0, /**< The exit is closed. */
44 HCEXITSTATE_UNLOCKED, /**< The exit is opened. */
45 HCEXITSTATE_SWALLOWING, /**< The exit is swallowing a character. */
46 HCEXITSTATE_SWALLOWED /**< The exit has just swallowed the character. */
47 } HCExitState;
48
49 /** A spark.
50 */
51 struct HCExitSpark
52 {
53 float x0, y0, x, y; /**< Position of this spark. */
54 float vx, vy; /**< Veloccity of this spark. */
55 SDL_Color c; /**< Color of this spark. */
56 u8 dc; /**< Color variation rate. */
57 };
58
59 /** Exit for a level. The character must be aligned with it to reach it.
60 */
61 class HCExit : public JDrawable
62 {
63 protected:
64 HCMap *map; /**< Map for this exit. */
65 HCExitState state; /**< Current state. */
66 float x1; /**< X of lower right box for sparkles. */
67 float y1; /**< Y of lower right box for sparkles. */
68 JTimer timer; /**< Timer for FPS count. */
69
70 HCExitSpark *sparks; /**< Sparks. */
71 s32 numSparks; /**< Number of sparkles. */
72
73 HCCharacter *character; /**< Character to swallow. */
74 JImage *imgCharacter; /**< Frame of the character being swallowed. */
75
76 public:
77 /** Creates the exit. Init must be called before starting to use it.
78 */
79 HCExit();
80
81 /** Initializes the exit.
82 * @param _map Map for this exit.
83 * @return <b>true</b> if everything goes well, <b>false</b> otherwise.
84 */
85 virtual bool Init(HCMap *_map, s32 nSparks, s32 w = 0);
86
87 /** Draws the exit.
88 */
89 virtual void Draw();
90
91 /** Updates the exit.
92 * @return Return value of the associated drawable's update.
93 */
94 virtual s32 Update();
95
96 /** Returns the state of the exit. Must use one of Lock(), Unlock() or Swallow() to change the state.
97 * @return the state of the exit.
98 */
99 HCExitState State() {return state;}
100
101 /** Returns the number of sparks.
102 * @return the number of sparks.
103 */
104 s32 NumSparks() {return numSparks;}
105
106 /** Returns the lower right x coordinate of the exit.
107 * @return the lower right x coordinate of the exit.
108 */
109 float X1() {return x1;}
110
111 /** Returns the lower right y coordinate of the exit.
112 * @return the lower right y coordinate of the exit.
113 */
114 float Y1() {return y1;}
115
116 /** Locks the exit.
117 */
118 void Lock() {state = HCEXITSTATE_LOCKED;}
119
120 /** Unlocks the exit.
121 */
122 void Unlock();
123
124 /** Swallows the character.
125 * @param ch Character to swallow.
126 */
127 void Swallow(HCCharacter *ch);
128
129 /** Positions this object.
130 * @param xPos New x coordinate.
131 * @param yPos New y coordinate.
132 */
133 virtual void Pos(float xPos, float yPos);
134
135
136 /** Destroys this exit.
137 */
138 void Destroy();
139
140 /** Destroys this exit. Allows scalar destruction.
141 */
142 virtual ~HCExit();
143 };
144
145 #endif // _HCEXIT_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Game level. Includes a map and its enemies.
23 * @file HCLevel.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 29/05/2004
26 * @version 0.0.1 - 29/05/2004 - First version
27 */
28
29 #include <HCLevel.h>
30
31 #ifndef HC_DATA_DIR
32 #define HC_DATA_DIR "res/"
33 #endif
34
35 HCLevel::HCLevel() : numEnemies(0), enemies(0), numRopes(0),
36 ropes(0), remainingObjects(0), numObjects(0), objects(0),
37 scripted(false), narrative(0), wideMap(false), highMap(false),
38 maxTime(1), timerFont(0)
39 {
40 }
41
42 bool HCLevel::Init()
43 {
44 // Initializes the character
45 character.Init(theme.MainChar(character.Subtype()), &map, ropes, numRopes);
46 character.State(HCCS_STOP);
47
48 // Creates an empty background
49 bg.Destroy();
50 if (!bg.Create(1, 1, 0))
51 {
52 fprintf(stderr, "Error creating empty level background.\n");
53 return false;
54 }
55
56 // Loads sounds
57 soundObjectAcquired.Destroy();
58 musicEndLevel.Destroy();
59
60 if (JApp::App()->SoundEnabled() &&
61 (!soundObjectAcquired.LoadWave(HC_DATA_DIR "sound/HCObjectAcquired.wav") ||
62 !musicEndLevel.LoadWave(HC_DATA_DIR "sound/HCEndLevel.wav") ||
63 !soundExitUnlocked.LoadWave(HC_DATA_DIR "sound/HCExitUnlocked.wav")))
64 {
65 fprintf(stderr, "Error loading sounds, check installation.\n");
66 }
67
68 // Initializes the exit
69 levelExit.Lock();
70 levelExit.Init(&map, 100);
71
72 // Initializes the timer
73 levelTimer.Init(maxTime, timerFont);
74 levelTimer.Pos(0, 0);
75
76 return true;
77 }
78
79 s32 HCLevel::Update()
80 {
81 s32 ret = 0;
82
83 s32 i;
84
85 // Updates the map
86 map.Update();
87
88 // Updates the ropes
89 for (i = 0; i < numRopes; ++i)
90 {
91 ropes[i]->Update();
92 }
93
94 // Updates the character unless it's exiting the level
95 if (!scripted)
96 {
97 switch (LevelExit()->State())
98 {
99 default:
100 case HCEXITSTATE_LOCKED:
101 {
102 if (IsExitUnlocked())
103 {
104 LevelExit()->Unlock();
105
106 if (JApp::App()->SoundEnabled())
107 {
108 soundExitUnlocked.Play();
109 }
110 }
111 character.Update();
112 }
113 break;
114
115 case HCEXITSTATE_UNLOCKED:
116 {
117 character.Update();
118
119 // Checks if the character is in the exit sight and swallows it if so
120 if (Character()->X() >= LevelExit()->X() &&
121 Character()->X() <= LevelExit()->X1() &&
122 Character()->Y() >= LevelExit()->Y() &&
123 Character()->Y() <= LevelExit()->Y1())
124 {
125 // Time stops
126 levelTimer.Pause();
127
128 // Inside, swallow it!
129 LevelExit()->Swallow(Character());
130
131 if (JApp::App()->SoundEnabled())
132 {
133 musicEndLevel.Play();
134 }
135
136 for (i = 0; i < NumEnemies(); ++i)
137 {
138 Enemies()[i]->State(HCCS_DIE);
139 }
140 }
141 }
142 break;
143
144 case HCEXITSTATE_SWALLOWED:
145 {
146 // Level achieved!!
147 if (!JApp::App()->SoundEnabled() || !musicEndLevel.IsPlaying())
148 {
149 ret = 2;
150 }
151 }
152 break;
153
154 case HCEXITSTATE_SWALLOWING:
155 break;
156 }
157 }
158 else
159 {
160 character.Update();
161 }
162
163 // Updates the objects
164 for (i = 0; i < numObjects; ++i)
165 {
166 objects[i]->Update();
167 }
168
169 // Checks for objects to pick up
170 CheckObjects();
171
172 // Positions the level according to the character position so it's always visible
173 // but it can be overriden if any script exists
174 spot = character.Pos();
175
176 // Updates the enemies
177 if (scripted)
178 {
179 for (i = 0; i < numEnemies; ++i)
180 {
181 // Updates the enemies as if they were normal characters
182 enemies[i]->HCCharacter::Update();
183 }
184 }
185 else
186 {
187 bool collide = false;
188
189 for (i = 0; !collide && i < numEnemies; ++i)
190 {
191 enemies[i]->Update();
192
193 if (HCPreferences::Prefs()->Difficulty() != HCPREFERENCES_TOY)
194 {
195 // Checks collisions with enemies, except in toy mode
196 if (!collide && Collide(&character, enemies[i]))
197 {
198 character.State(HCCS_DIE);
199 collide = true;
200 ret = 1;
201 }
202 }
203 }
204
205 // Updates the time remaining, except in toy mode
206 if (levelTimer.Update() <= 0)
207 {
208 if (HCPreferences::Prefs()->Difficulty() != HCPREFERENCES_TOY)
209 {
210 // Time up! (Except in toy mode)
211 character.State(HCCS_DIE);
212 ret = 1;
213 }
214 }
215 }
216
217 if (narrative)
218 {
219 narrative->Update();
220 }
221
222 if (!scripted)
223 {
224 levelExit.Update();
225 }
226
227 // Updates the level position according to the spot position
228 s32 x = (s32)pos.x, y = (s32)pos.y;
229 if (wideMap)
230 {
231 s32 w2 = JApp::App()->Width()/2;
232
233 if (spot.x < (w2 - viewRadius))
234 {
235 // Spot outside viewing spot, moves towards the spot
236 s32 vx = (s32)JMin((w2 - viewRadius - spot.x)/4, map.CellWidth());
237
238 if (vx <= 1) vx = 1;
239
240 x += vx;
241 }
242 else
243 if (spot.x > (w2 + viewRadius))
244 {
245 // Spot outside viewing spot, moves towards the spot
246 s32 vx = (s32)JMin((spot.x - (w2 + viewRadius))/4, map.CellWidth());
247
248 if (vx <= 1) vx = 1;
249
250 x -= vx;
251 }
252 }
253
254 if (highMap)
255 {
256 s32 h2 = JApp::App()->Height()/2;
257
258 if (spot.y < (h2 - viewRadius))
259 {
260 // Spot outside viewing spot, moves towards the spot
261 s32 vy = (s32)JMin((h2 - viewRadius - spot.y)/5, map.CellHeight());
262
263 if (vy <= 1) vy = 1;
264
265 y += vy;
266 }
267 else
268 if (spot.y > (h2 + viewRadius))
269 {
270 // Spot outside viewing spot, moves towards the spot
271 s32 vy = (s32)JMin((spot.y - (h2 + viewRadius))/5, map.CellHeight());
272
273 if (vy <= 1) vy = 1;
274
275 y -= vy;
276 }
277 }
278
279 if (wideMap || highMap)
280 {
281 Pos(x, y);
282 }
283
284 return ret;
285 }
286
287 void HCLevel::Draw()
288 {
289 s32 i;
290
291 // Draws the background
292 bg.Draw();
293
294 // Draws the map
295 map.Draw();
296
297 // Draws the objects
298 for (i = 0; i < numObjects; ++i)
299 {
300 objects[i]->Draw();
301 }
302
303 // Draws the enemies
304 for (i = 0; i < numEnemies; ++i)
305 {
306 enemies[i]->Draw();
307 }
308
309 // Draws the ropes
310 for (i = 0; i < numRopes; ++i)
311 {
312 ropes[i]->Draw();
313 }
314
315 // Draws the main character
316 character.Draw();
317
318 if (narrative)
319 {
320 narrative->Draw();
321 }
322
323 if (!scripted)
324 {
325 levelExit.Draw();
326
327 if (HCPreferences::Prefs()->Difficulty() != HCPREFERENCES_TOY)
328 {
329 // Draws the time remaining
330 levelTimer.Draw();
331 }
332
333 // Draws the remaining objects to complete the level
334 float qw = float(JApp::App()->Width())/4.0f, dx = qw/float(numObjects + 1);
335 for (i = 0; i < numObjects; ++i)
336 {
337 objects[i]->Draw();
338
339 if (objects[i]->State() == HCOBJECTSTATE_NORMAL)
340 {
341 ((JImage *)objects[i]->Normal().Frame(0))->Draw(s32(qw * 3.0f + dx * float(i)), 0);
342 }
343 }
344 }
345 }
346
347 u32 HCLevel::Load(JRW &file, const char *filename)
348 {
349 Destroy();
350
351 // Maximum time to complete the level, 0 means no timed
352 if (0 == file.ReadLE32(&maxTime))
353 {
354 fprintf(stderr, "Error reading the level completion time.\n");
355 perror("");
356
357 return 1;
358 }
359
360 // Adjusts max time according to the level of difficulty (x1, x2, x3)
361 maxTime *= HCPreferences::Prefs()->Difficulty();
362
363 // Theme name
364 JString str;
365 if (0 != str.Load(file))
366 {
367 fprintf(stderr, "Error loading the theme name.\n");
368
369 return 2;
370 }
371
372 // Loads the theme
373 if (!theme.Load(str))
374 {
375 fprintf(stderr, "Error loading the theme %s.\n", theme.Name());
376
377 return 2;
378 }
379
380 // Initializes and loads the map
381 if (!map.Init(theme) ||
382 0 != map.Load(file))
383 {
384 fprintf(stderr, "Error loading the level map.\n");
385
386 return 2;
387 }
388
389 // Main character
390 if (0 != character.Load(file))
391 {
392 fprintf(stderr, "Error loading main character.\n");
393
394 return 1;
395 }
396
397 // Initializes enemie's maximum global veloccities
398 HCEnemy::MaxXVeloccity(character.MaxVeloccity().x);
399 HCEnemy::MaxYVeloccity(character.MaxVeloccity().y);
400
401 // Loads the enemies
402 if (0 == file.ReadLE32(&numEnemies))
403 {
404 fprintf(stderr, "Error reading the number of enemies.\n");
405
406 return 1;
407 }
408
409 if (numEnemies > 0)
410 {
411 enemies = new HCEnemy *[numEnemies];
412
413 s32 enemyType;
414
415 for (s32 i = 0; i < numEnemies; ++i)
416 {
417 if (0 != file.ReadLE32((s32 *)&enemyType))
418 {
419 // Lets the file at ist original position
420 file.Seek(-4, SEEK_CUR);
421
422 // Peeps the type of enemy
423 switch (enemyType)
424 {
425 default:
426 case HCENEMYTYPE_BALL:
427 enemies[i] = new HCEnemyBall;
428 break;
429
430 case HCENEMYTYPE_RANDOM:
431 enemies[i] = new HCEnemyRandom;
432 break;
433
434 case HCENEMYTYPE_STATIC:
435 enemies[i] = new HCEnemyStatic;
436 break;
437
438 case HCENEMYTYPE_MAKER:
439 enemies[i] = new HCEnemyMaker;
440 break;
441
442 case HCENEMYTYPE_CHASER:
443 enemies[i] = new HCEnemyChaser;
444 break;
445 }
446
447 if (0 != enemies[i]->Load(file, theme, &map))
448 {
449 Destroy();
450
451 fprintf(stderr, "Error loading the enemies.\n");
452 return 2;
453 }
454 }
455 }
456 }
457
458 // Loads the objects
459 if (0 == file.ReadLE32(&numObjects))
460 {
461 fprintf(stderr, "Error reading the number of objects.\n");
462
463 return 1;
464 }
465
466 if (numObjects > 0)
467 {
468 remainingObjects = numObjects;
469 objects = new HCObject *[numObjects];
470
471 for (s32 i = 0; i < numObjects; ++i)
472 {
473 objects[i] = new HCObject;
474
475 if (0 != objects[i]->Load(file))
476 {
477 Destroy();
478
479 fprintf(stderr, "Error loading the objects.\n");
480 return 2;
481 }
482
483 objects[i]->Init(&theme);
484 }
485 }
486
487 // Loads the ropes
488 if (0 == file.ReadLE32(&numRopes))
489 {
490 fprintf(stderr, "Error reading the number of ropes.\n");
491
492 return 1;
493 }
494
495 if (numRopes > 0)
496 {
497 ropes = new HCRope *[numRopes];
498
499 for (s32 i = 0; i < numRopes; ++i)
500 {
501 ropes[i] = new HCRope();
502
503 if (0 != ropes[i]->Load(file, theme))
504 {
505 Destroy();
506
507 fprintf(stderr, "Error loading the ropes.\n");
508 return 2;
509 }
510 }
511 }
512
513 if (!Init())
514 {
515 fprintf(stderr, "Error initializing the level.\n");
516 return 2;
517 }
518
519 // Checks if a background named as the file and ended in '.tga' exists
520 str.Format("%s.tga", filename);
521
522 if (JFile::Exists(str))
523 {
524 bg.Destroy();
525
526 if (!bg.Load(str))
527 {
528 fprintf(stderr, "Error loading level background %s.\n", str.Str());
529 return 1;
530 }
531
532 bg.Pos(0, 0);
533 }
534 else
535 {
536 // Creates an empty background
537 if (!bg.Create(1, 1, 0))
538 {
539 fprintf(stderr, "Error creating empty level background.\n");
540 return 2;
541 }
542 }
543
544 // Checks for chaser enemies in the level
545 for (s32 i = 0; i < numEnemies; ++i)
546 {
547 if (enemies[i]->Type() == HCENEMYTYPE_CHASER)
548 {
549 ((HCEnemyChaser *)enemies[i])->Chase(&character);
550 }
551 }
552
553 // Initializes the viewing parameters
554 s32 x = 0, y = 0;
555 viewRadius = 0;
556
557 if (map.Width() > JApp::App()->Width())
558 {
559 wideMap = true;
560
561 // Defaults the viewing square size to a quarter of the application width
562 viewRadius = JApp::App()->Width()/8;
563 }
564 else
565 {
566 x = (JApp::App()->Width() - map.Width())/2;
567 wideMap = false;
568 }
569
570 if (map.Height() > JApp::App()->Height())
571 {
572 highMap = true;
573
574 // Defaults the viewing square size to a quarter of the application height or
575 // the viewRadius, the greatest
576 if (viewRadius != 0)
577 {
578 viewRadius = (s32)JMin(JApp::App()->Height()/6, viewRadius);
579 }
580 else
581 {
582 viewRadius = JApp::App()->Height()/6;
583 }
584 }
585 else
586 {
587 y = (JApp::App()->Height() - map.Height())/2;
588 highMap = false;
589 }
590
591 Pos(x, y);
592
593 return 0;
594 }
595
596 u32 HCLevel::Save(JRW &file)
597 {
598 s32 x, y;
599
600 // Time to complete the level
601 if (0 == file.WriteLE32(&maxTime))
602 {
603 fprintf(stderr, "Error writing the completion time.\n");
604
605 return 1;
606 }
607
608 // Theme name
609 JString str;
610 str = theme.Name();
611 if (0 != str.Save(file))
612 {
613 fprintf(stderr, "Error saving the theme name.\n");
614
615 return 2;
616 }
617
618 if (0 != map.Save(file))
619 {
620 fprintf(stderr, "Error saving the level map.\n");
621
622 return 2;
623 }
624
625 // Main character
626 x = (s32)character.X();
627 y = (s32)character.Y();
628 character.Pos(x - (s32)map.X(), y - (s32)map.Y());
629
630 if (0 != character.Save(file))
631 {
632 fprintf(stderr, "Error saving main character.\n");
633
634 return 1;
635 }
636
637 character.Pos(x, y);
638
639 // Stores the objects, enemies, ropes relative to the map top-left corner
640 if (0 == file.WriteLE32(&numEnemies))
641 {
642 fprintf(stderr, "Error writing the number of enemies.\n");
643
644 return 1;
645 }
646
647 for (s32 i = 0; i < numEnemies; ++i)
648 {
649 x = (s32)enemies[i]->X();
650 y = (s32)enemies[i]->Y();
651 enemies[i]->Pos(x - (s32)map.X(), y - (s32)map.Y());
652
653 if (0 != enemies[i]->Save(file))
654 {
655 fprintf(stderr, "Error saving the enemies.\n");
656 return 2;
657 }
658
659 enemies[i]->Pos(x, y);
660 }
661
662 if (0 == file.WriteLE32(&numObjects))
663 {
664 fprintf(stderr, "Error writing the number of objects.\n");
665
666 return 1;
667 }
668
669 for (s32 i = 0; i < numObjects; ++i)
670 {
671 x = (s32)objects[i]->X();
672 y = (s32)objects[i]->Y();
673 objects[i]->Pos(x - (s32)map.X(), y - (s32)map.Y());
674
675 if (0 != objects[i]->Save(file))
676 {
677 fprintf(stderr, "Error saving the objects.\n");
678 return 2;
679 }
680
681 objects[i]->Pos(x, y);
682 }
683
684 if (0 == file.WriteLE32(&numRopes))
685 {
686 fprintf(stderr, "Error writing the number of ropes.\n");
687
688 return 1;
689 }
690
691 for (s32 i = 0; i < numRopes; ++i)
692 {
693 x = (s32)ropes[i]->X();
694 y = (s32)ropes[i]->Y();
695 ropes[i]->Pos(x - (s32)map.X(), y - (s32)map.Y());
696
697 if (0 != ropes[i]->Save(file))
698 {
699 fprintf(stderr, "Error saving the ropes.\n");
700 return 2;
701 }
702
703 ropes[i]->Pos(x, y);
704 }
705
706 return 0;
707 }
708
709 void HCLevel::Pos(float xPos, float yPos)
710 {
711 float xMap, yMap, xBg, yBg, dx, dy;
712 float xMapOrg = map.X();
713 float yMapOrg = map.Y();
714
715 pos.x = xPos;
716 pos.y = yPos;
717
718 if (map.Width() > bg.Width())
719 {
720 xMap = xPos;
721 xBg = xPos + ((map.Width() - bg.Width())/2);
722 }
723 else
724 {
725 xBg = xPos;
726 xMap = xPos + ((bg.Width() - map.Width())/2);
727 }
728
729 if (map.Height() > bg.Height())
730 {
731 yMap = yPos;
732 yBg = yPos + ((map.Height() - bg.Height())/2);
733 }
734 else
735 {
736 yBg = yPos;
737 yMap = yPos + ((bg.Height() - map.Height())/2);
738 }
739
740 map.Pos(xMap, yMap);
741 bg.Pos(xBg, yBg);
742
743 dx = xMap - xMapOrg;
744 dy = yMap - yMapOrg;
745
746 // Now move the objects
747 float t1, t2;
748 for (s32 i = 0; i < numObjects; ++i)
749 {
750 t1 = objects[i]->X();
751 t2 = objects[i]->Y();
752
753 objects[i]->Pos(objects[i]->X() + (s32)dx,
754 objects[i]->Y() + (s32)dy);
755 }
756
757 // Now move the ropes
758 for (s32 i = 0; i < numRopes; ++i)
759 {
760 ropes[i]->Pos(ropes[i]->X() + (s32)dx,
761 ropes[i]->Y() + (s32)dy);
762 }
763
764 // Now move the enemies
765 for (s32 i = 0; i < numEnemies; ++i)
766 {
767 enemies[i]->Pos(enemies[i]->X() + (s32)dx,
768 enemies[i]->Y() + (s32)dy);
769 }
770
771 // Move the level exit
772 levelExit.Pos(levelExit.X() + (s32)dx, (s32)levelExit.Y() + (s32)dy);
773
774 // And finally the main character
775 character.Pos(character.X() + (s32)dx,
776 character.Y() + (s32)dy);
777 }
778
779 void HCLevel::CheckObjects()
780 {
781 JVector vc, vo;
782 vc = character.Pos();
783
784 // Y Offset of the center of the character
785 JImage * img = (JImage *)character.CurSprite()->Frame(character.CurSprite()->CurFrame());
786 vc.y += img->Pos().y + (img->Width()/2);
787
788 for (s32 i = 0; i < numObjects; ++i)
789 {
790 if (objects[i]->State() == HCOBJECTSTATE_NORMAL)
791 {
792 vo = objects[i]->Pos();
793
794 // Y Offset of the center of the character
795 img = (JImage *)objects[i]->Normal().Frame(objects[i]->Normal().CurFrame());
796 vo.y += img->Pos().y + (img->Width()/2);
797
798 if (vo == vc)
799 {
800 // 0 length case
801 ObjectAcquired(objects[i]);
802
803 if (JApp::App()->SoundEnabled())
804 {
805 soundObjectAcquired.Play();
806 }
807 }
808 else
809 {
810 if ((vo - vc).Length() < (0.9f * character.CurSprite()->MaxW()))
811 {
812 ObjectAcquired(objects[i]);
813
814 if (JApp::App()->SoundEnabled())
815 {
816 soundObjectAcquired.Play();
817 }
818 }
819 }
820 }
821 }
822 }
823
824 void HCLevel::ObjectAcquired(HCObject *object)
825 {
826 if (object)
827 {
828 --remainingObjects;
829
830 object->Acquire();
831 }
832 }
833
834 bool HCLevel::Collide(HCCharacter *c1, HCCharacter *c2)
835 {
836 float px1, py1, px2, py2, pw, ph;
837 float ex1, ey1, ex2, ey2, ew, eh;
838 JImage *cfp, *cfe;
839 float difficulty = 0.75;
840 cfp = (JImage *)c1->CurSprite()->Frame(c1->CurSprite()->CurFrame());
841 cfe = (JImage *)c2->CurSprite()->Frame(c2->CurSprite()->CurFrame());
842
843 pw = cfp->Width() * difficulty;
844 ph = cfp->Height() * difficulty;
845 px1 = c1->CurSprite()->Pos().x + cfp->X() + (cfp->Width()/2) - (pw/2);
846 px2 = px1 + pw;
847 py1 = c1->CurSprite()->Pos().y + cfp->Y() + (cfp->Height()/2) - (ph/2);
848 py2 = py1 + ph;
849
850 ew = cfe->Width() * difficulty;
851 eh = cfe->Height() * difficulty;
852 ex1 = c2->CurSprite()->Pos().x + cfe->X() + (cfe->Width()/2) - (ew/2);
853 ex2 = ex1 + ew;
854 ey1 = c2->CurSprite()->Pos().y + cfe->Y() + (cfe->Height()/2) - (eh/2);
855 ey2 = ey1 + eh;
856
857 // SDL_Rect rcp = {px1, py1, pw, ph};
858 // SDL_Rect rce = {ex1, ey1, ew, eh};
859 // SDL_FillRect(SDL_GetVideoSurface(), &rce, 0xffffffff);
860 // SDL_FillRect(SDL_GetVideoSurface(), &rcp, 0xffffffff);
861 // SDL_Flip(SDL_GetVideoSurface());
862
863 // Approximate collisions using half the width and height, centered of the characters
864 if ((px1 > ex1 && px1 < ex2) ||
865 (px2 > ex1 && px2 < ex2) ||
866 (px1 < ex1 && px2 > ex2) ||
867 (px1 > ex1 && px2 < ex2))
868 {
869 if ((py1 > ey1 && py1 < ey2) ||
870 (py2 > ey1 && py2 < ey2) ||
871 (py1 < ey1 && py2 > ey2) ||
872 (py1 > ey1 && py2 < ey2))
873 {
874 // Collide!
875 return true;
876 }
877 }
878
879 return false;
880 }
881
882 void HCLevel::Destroy()
883 {
884 JDELETE_POINTER_ARRAY(enemies, numEnemies);
885 numEnemies = 0;
886 JDELETE_POINTER_ARRAY(ropes, numRopes);
887 numRopes = 0;
888 JDELETE_POINTER_ARRAY(objects, numObjects);
889 numObjects = 0;
890 map.Destroy();
891 theme.Destroy();
892 levelExit.Destroy();
893 bg.Destroy();
894 character.Destroy();
895 narrative = 0;
896 levelTimer.Destroy();
897 soundObjectAcquired.Destroy();
898 musicEndLevel.Destroy();
899 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Game level. Includes a map and its enemies.
23 * @file HCLevel.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 29/05/2004
26 * @version 0.0.1 - 29/05/2004 - First version
27 */
28
29 #ifndef _HCLEVEL_INCLUDED
30 #define _HCLEVEL_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Sound/JChunk.h>
34 #include <JLib/Graphics/JDrawable.h>
35 #include <HCMap.h>
36 #include <HCRope.h>
37 #include <HCObject.h>
38 #include <HCCharacter.h>
39 #include <HCEnemyBall.h>
40 #include <HCEnemyStatic.h>
41 #include <HCEnemyRandom.h>
42 #include <HCEnemyMaker.h>
43 #include <HCEnemyChaser.h>
44 #include <HCText.h>
45 #include <HCExit.h>
46 #include <HCTimer.h>
47 #include <HCPreferences.h>
48
49 class HCLevel : public JDrawable
50 {
51 // Allows the editor to modify it at pleasure.
52 friend class HCed;
53
54 protected:
55 HCMap map; /**< Level map. */
56 HCTheme theme; /**< Level theme. */
57 HCExit levelExit; /**< Level exit. */
58 JImage bg; /**< Level background. */
59
60 HCCharacter character; /**< Main character. */
61
62 s32 numEnemies; /**< Number of enemies. */
63 HCEnemy **enemies; /**< Array of enemies. */
64
65 s32 numRopes; /**< Number of ropes. */
66 HCRope **ropes; /**< Array of ropes. */
67
68 s32 remainingObjects; /**< Number of objects remaining to unlock the exit. */
69 s32 numObjects; /**< Number of objects. */
70 HCObject **objects; /**< Array of objects. */
71
72 bool scripted; /**< Determines whether it has a script or not. */
73 HCText *narrative; /**< Narrative to be shown. */
74
75 bool wideMap; /**< Indicates wherther the map is wider than the movement window or not. */
76 bool highMap; /**< Indicates wherther the map is higher than the movement window or not. */
77
78 JVector spot; /**< Viewing spot. The level tries always to make it visible. */
79 s32 viewRadius; /**< Radius of the viewing spot. */
80
81 s32 maxTime; /**< Maximum time to complete the level. */
82 HCTimer levelTimer; /**< Level timer. */
83 JFont *timerFont; /**< Level timer font. */
84
85 JChunk soundObjectAcquired; /**< Sound for object acquired. */
86 JChunk musicEndLevel; /**< End level screen music. */
87 JChunk soundExitUnlocked; /**< Exit unlocked sound. */
88
89 public:
90 /** Creates an empty level. One must Load() or call Init and manipulate
91 * directly it (if editing).
92 */
93 HCLevel();
94
95 /** Initializes the level. Creates an empty background for it.
96 * @return <b>true</b> if successful, <b>false</b> otherwise.
97 */
98 bool Init();
99
100 /** Updates the level.
101 * @return 0 if no important event took place, 1 if player died, 2 if player went through the exit.
102 */
103 s32 Update();
104
105 /** Draws the level.
106 */
107 void Draw();
108
109 /** Process game input.
110 * @param input Action mask.
111 */
112 void ProcessInput(u32 input) {character.Act(input);}
113
114 /** Loads the level.
115 * @param file File opened and positioned already.
116 * @param filename name of the file opened.
117 * @return 0 if it succeeds, 1 if there is an I/O error, 2 if integrity error.
118 */
119 u32 Load(JRW &file, const char *filename);
120
121 /** Saves the level. The file must be opened and positioned already.
122 * @param file File opened and positioned already.
123 * @return 0 if it succeeds, 1 if there is an I/O error, 2 if integrity error.
124 */
125 u32 Save(JRW &file);
126
127 /** Returns this level's map.
128 * @return Map.
129 */
130 HCMap & Map() {return map;}
131
132 /** Returns the number of enemies.
133 * @return Number of enemies.
134 */
135 s32 NumEnemies() {return numEnemies;}
136
137 /** Returns the number of ropes.
138 * @return Number of ropes.
139 */
140 s32 NumRopes() {return numRopes;}
141
142 /** Returns the number of objects.
143 * @return Number of objects.
144 */
145 s32 NumObjects() {return numObjects;}
146
147 /** Returns the main character.
148 * @return Main character.
149 */
150 HCCharacter *Character() {return &character;}
151
152 /** Returns the enemies.
153 * @return enemies.
154 */
155 HCEnemy ** Enemies() {return enemies;}
156
157 /** Returns the ropes.
158 * @return ropes.
159 */
160 HCRope ** Ropes() {return ropes;}
161
162 /** Returns the objects.
163 * @return objects.
164 */
165 HCObject ** Objects() {return objects;}
166
167 /** Returns the current narrative object.
168 * @return current narrative object.
169 */
170 HCText *Narrative() {return narrative;}
171
172 /** Sets the current narrative object.
173 * @param Current narrative object to be shown.
174 */
175 void Narrative(HCText *newNarrative) {narrative = newNarrative;}
176
177 /** Returns the exit object.
178 * @return exit object.
179 */
180 HCExit *LevelExit() {return &levelExit;}
181
182 /** Returns the theme.
183 * @return This level's theme.
184 */
185 HCTheme & Theme() {return theme;}
186
187 /** Positions this level. The background is centered respect to the map.
188 * @param xPos New x coordinate of either the background or the map, the widest.
189 * @param yPos New y coordinate of either the background or the map, the highest.
190 */
191 virtual void Pos(float xPos, float yPos);
192
193 /** Checks if the character is over any object.
194 */
195 void CheckObjects();
196
197 /** Updates the number of objects to be acquired to end the level.
198 */
199 void ObjectAcquired(HCObject *object);
200
201 /** Returns whether exit is unlocked or not. Unlocked, means that all
202 * the objects had been collected from the map.
203 * @return <b>true</b> if the exit is unlocked and the character can go
204 * to the next level, <b>false</b> if not.
205 */
206 bool IsExitUnlocked() {return remainingObjects == 0;}
207
208 /** Sets the scripted flag.
209 * @param newState New value for the flag.
210 */
211 void Scripted(bool newState) {scripted = newState;}
212
213 /** Gets the scripted flag.
214 * @return Whether it has an script or not.
215 */
216 bool Scripted() {return scripted;}
217
218 /** Tests if the given characters overlap or not.
219 * @param c1 First character to test.
220 * @param c2 Second character to test.
221 * @return Whether they overlap or not.
222 */
223 bool Collide(HCCharacter *c1, HCCharacter *c2);
224
225 /** Sets the font to render the timer.
226 * @param f Font to use to render the timer.
227 */
228 void SetTimerFont(JFont *f) {timerFont = f;}
229
230 /** Destroys the level, frees resources.
231 */
232 void Destroy();
233
234 /** Pauses or continues the level timer.
235 */
236 void Pause(bool pause) {pause ? levelTimer.Pause() : levelTimer.Continue();}
237
238 /** Starts the timer.
239 */
240 void Start() {levelTimer.Start();}
241
242 /** Destroys the level, frees resources, allows scalar destruction.
243 */
244 virtual ~HCLevel() {Destroy();}
245 };
246
247 #endif // _HCLEVEL_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Game data slot for save and load.
23 * @file HCLoadSaveSlot.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 14/09/2004
26 * @version 0.0.1 - 14/09/2004 - Primera versión.
27 */
28
29 #include <HCLoadSaveSlot.h>
30 #include <HCLevel.h>
31
32 #ifndef _WIN32
33 #include <unistd.h>
34 #endif
35
36 bool HCLoadSaveSlot::Load(s32 slot)
37 {
38 // Loads the name of the story and the level number
39 JRW f;
40 char name[256];
41
42 #ifndef _WIN32
43 char *home;
44 home = getenv("HOME");
45 if (home != NULL)
46 snprintf(name, sizeof(name), "%s/.holotz-castle/slot%02d", home, slot);
47 else
48 snprintf(name, sizeof(name), HC_DATA_DIR "savedata/slot%02d", slot);
49 #else
50 snprintf(name, sizeof(name), HC_DATA_DIR "savedata/slot%02d", slot);
51 #endif
52
53 if (f.Create(name, "rb") &&
54 0 == story.Load(f) &&
55 0 != f.ReadLE32(&level))
56 {
57 return true;
58 }
59
60 return false;
61 }
62
63 bool HCLoadSaveSlot::Save(s32 slot, const JString& s, s32 levelNumber)
64 {
65 level = levelNumber;
66 story = s;
67
68 JRW f;
69 char name[256];
70
71 #ifndef _WIN32
72 char *home;
73 home = getenv("HOME");
74 snprintf(name, sizeof(name), "%s/.holotz-castle", home);
75 mkdir(name, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
76 if (home != NULL)
77 snprintf(name, sizeof(name), "%s/.holotz-castle/slot%02d", home, slot);
78 else
79 snprintf(name, sizeof(name), HC_DATA_DIR "savedata/slot%02d", slot);
80 #else
81 snprintf(name, sizeof(name), HC_DATA_DIR "savedata/slot%02d", slot);
82 #endif
83
84 // Saves the name of the story and the level number
85 if (f.Create(name, "wb"))
86 {
87 if (0 == story.Save(f))
88 {
89 if (0 != f.WriteLE32(&level))
90 {
91 return true;
92 }
93 else
94 {
95 fprintf(stderr, "Error saving level %d\n", level);
96 }
97 }
98 else
99 {
100 fprintf(stderr, "Error saving story %s\n", story.Str());
101 }
102 }
103 else
104 {
105 fprintf(stderr, "Error opening %s\n", name);
106 }
107
108 return false;
109 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Game data slot for save and load.
23 * @file HCLoadSaveSlot.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 14/09/2004
26 * @version 0.0.1 - 14/09/2004 - Primera versión.
27 */
28
29 #ifndef _HCLOADSAVESLOT_INCLUDED
30 #define _HCLOADSAVESLOT_INCLUDED
31
32 #include <JLib/Util/JTextFile.h>
33 #include <JLib/Graphics/JImage.h>
34
35 /** Game data slot for save and load.
36 */
37 class HCLoadSaveSlot
38 {
39 JString story; /**< Story name. */
40 s32 level; /**< Level number within the story. */
41
42 public:
43 /** Creates an empty slot, Init() must be called before.
44 */
45 HCLoadSaveSlot() : level(1)
46 {}
47
48 /** Loads this slot.
49 * @param slot Slot number to load.
50 * @return <b>true</b> if succeeded, <b>false</b> otherwise.
51 */
52 bool Load(s32 slot);
53
54 /** Saves this slot with the given parameters.
55 * @param s Name of the story.
56 * @param levelNumber Ordinal of the level to save.
57 * @param image Image to be stored.
58 * @param f File already opened and positioned.
59 * @return 0 if succeeded, 1 if there was an I/O error, 2 if an integrity error.
60 */
61 bool Save(s32 slot, const JString& s, s32 levelNumber);
62
63 /** Returns the story name.
64 * @return story name.
65 */
66 const char * Story() {return story.Str();}
67
68 /** Returns the level number.
69 * @return level number.
70 */
71 s32 Level() {return level;}
72 };
73
74 #endif // _HCLOADSAVESLOT_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Map definition file for Holotz's Castle.
23 * @file HCMap.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 29/04/2004
26 * @version 0.0.1 - 29/04/2004 - First version.
27 */
28
29 #include <HCMap.h>
30
31 HCMap::HCMap()
32 {
33 cells = 0;
34 rows = cols = cellWidth = cellHeight = 0;
35 width = height = 0;
36 exitRow = exitCol = 0;
37 linkCells = 0;
38
39 //gravity = 0.7f;
40 gravity = 0.9f;
41 }
42
43 bool HCMap::Init(HCTheme &_theme)
44 {
45 cells = 0;
46 rows = cols = 0;
47 width = height = 0;
48 exitRow = exitCol = 0;
49
50 theme = &_theme;
51
52 // Inits common parameters
53 cellWidth = theme->Floor(0).Width();
54 cellHeight = theme->Floor(0).Height();
55
56 Pos(0, 0);
57
58 return true;
59 }
60
61 s32 HCMap::Update()
62 {
63 HCMapCell *mc = linkCells;
64
65 while (mc)
66 {
67 mc->cell->Update();
68 mc = mc->next;
69 }
70
71 return 1;
72 }
73
74 void HCMap::Draw()
75 {
76 HCMapCell *mc = linkCells;
77
78 while (mc)
79 {
80 mc->cell->Draw();
81 mc = mc->next;
82 }
83 }
84
85 void HCMap::Pos(float xPos, float yPos)
86 {
87 pos.x = xPos;
88 pos.y = yPos;
89
90 for (s32 j = 0; j < rows; ++j)
91 {
92 for (s32 i = 0; i < cols; ++i)
93 {
94 cells[j][i]->Pos(xPos + (i * cellWidth), yPos + (j * cellHeight));
95 }
96 }
97 }
98
99 void HCMap::ScreenToMap(s32 &xPos, s32 &yPos)
100 {
101 xPos = ToCol(xPos);
102 yPos = ToRow(yPos);
103 }
104
105 void HCMap::MapToScreen(s32 &col, s32 &row)
106 {
107 col = ToX(col);
108 row = ToY(row);
109
110 // Adds the map offset and the distance to the baseline's mid-point
111 col += (s32)pos.x + cellWidth/2;
112 row += (s32)Y() + cellHeight - 1;
113 }
114
115 s32 HCMap::ToCol(s32 xx)
116 {
117 // Removes map offsets
118 xx -= (s32)pos.x;
119
120 if (xx < 0)
121 {
122 return 0;
123 }
124
125 xx /= cellWidth;
126
127 return (xx > cols-1 ? cols-1 : xx);
128 }
129
130 s32 HCMap::ToRow(s32 yy)
131 {
132 // Removes map offsets
133 yy -= (s32)pos.y;
134
135 if (yy < 0)
136 {
137 return 0;
138 }
139
140 yy /= cellHeight;
141
142 return (yy > rows-1 ? rows-1 : yy);
143 }
144
145 s32 HCMap::ToX(s32 col)
146 {
147 col *= cellWidth;
148
149 // Adds the map offset and the distance to the baseline's mid-point
150 col += (s32)pos.x + cellWidth/2;
151 return col;
152 }
153
154 s32 HCMap::ToY(s32 row)
155 {
156 row *= cellHeight;
157
158 // Adds the map offset and the distance to the baseline's mid-point
159 row += (s32)pos.y + cellHeight - 1;
160 return row;
161 }
162
163 void HCMap::Resize(s32 newRows, s32 newCols, bool growRight, bool growDown)
164 {
165 if (newRows == 0 || newCols == 0)
166 {
167 // Only destroys the cells
168 Destroy();
169
170 return;
171 }
172
173 HCCell ***newCells;
174
175 // Creates the map cells
176 newCells = new HCCell **[newRows];
177
178 for (s32 j = 0; j < newRows; ++j)
179 {
180 newCells[j] = new HCCell *[newCols];
181 memset(newCells[j], 0, sizeof(HCCell*) * newCols);
182 }
183
184 if (cells != 0)
185 {
186 s32 maxRows = rows > newRows ? newRows : rows;
187 s32 maxCols = cols > newCols ? newCols : cols;
188
189 // Copies the existing cells, reducing, if necessary from the top right
190 // corner. Defaults the rest of the cells, in case of enlargement, to blank
191 for (s32 row = 0; row < newRows; ++row)
192 {
193 for (s32 col = 0; col < newCols; ++col)
194 {
195 if (row < maxRows && col < maxCols)
196 {
197 // while reducing
198 if (growDown)
199 {
200 if (growRight)
201 {
202 newCells[row][col] = cells[row][col];
203 cells[row][col] = 0;
204 }
205 else
206 {
207 newCells[row][newCols - 1 - col] = cells[row][cols - col - 1];
208 cells[row][cols - col - 1] = 0;
209 }
210 }
211 else
212 {
213 if (growRight)
214 {
215 newCells[newRows - 1 - row][col] = cells[rows - row - 1][col];
216 cells[rows - row - 1][col] = 0;
217 }
218 else
219 {
220 newCells[newRows - 1 - row][newCols - 1 - col] = cells[rows - row - 1][cols - col - 1];
221 cells[rows - row - 1][cols - col - 1] = 0;
222 }
223 }
224 }
225 else
226 {
227 // If enlarging
228 if (growDown)
229 {
230 if (growRight)
231 {
232 newCells[row][col] = new HCCell; // Grows down-right
233 }
234 else
235 {
236 newCells[row][newCols - 1 - col] = new HCCell; // Grows down-left
237 }
238 }
239 else
240 {
241 if (growRight)
242 {
243 newCells[newRows - 1 - row][col] = new HCCell; // Grows up-left
244 }
245 else
246 {
247 newCells[newRows - 1 - row][newCols - 1 - col] = new HCCell; // Grows up-right
248 }
249 }
250 }
251 }
252 }
253
254 // Destroy the rest of the original cells if reducing
255 Destroy();
256 }
257 else
258 {
259 // Initializes the map to empty cells
260 for (s32 row = 0; row < newRows; ++row)
261 {
262 for (s32 col = 0; col < newCols; ++col)
263 {
264 newCells[row][col] = new HCCell;
265 }
266 }
267 }
268
269 cells = newCells;
270 rows = newRows;
271 cols = newCols;
272 width = cellWidth * cols;
273 height = cellHeight * rows;
274
275 Pos(pos.x, pos.y);
276
277 BuildCellLinkList();
278 }
279
280 void HCMap::Destroy()
281 {
282 if (0 != cells)
283 {
284 for (s32 row = 0; row < rows; ++row)
285 {
286 for (s32 col = 0; col < cols; ++col)
287 {
288 JDELETE(cells[row][col]);
289 }
290
291 delete[] cells[row];
292 cells[row] = 0;
293 }
294
295 delete[] cells;
296 cells = 0;
297 }
298
299 DestroyCellLinkList();
300 }
301
302 void HCMap::BuildContFloorOnce(s32 row, s32 col)
303 {
304 if (cells[row][col]->Type() == HCCELLTYPE_CONTFLOOR)
305 {
306 ((HCContFloor *)cells[row][col])->Build(theme->ContFloor(cells[row][col]->Subtype()),
307 cells[row-1][col-1]->Type() == HCCELLTYPE_CONTFLOOR,
308 cells[row-1][col]->Type() == HCCELLTYPE_CONTFLOOR,
309 cells[row-1][col+1]->Type() == HCCELLTYPE_CONTFLOOR,
310 cells[row][col-1]->Type() == HCCELLTYPE_CONTFLOOR,
311 cells[row][col+1]->Type() == HCCELLTYPE_CONTFLOOR,
312 cells[row+1][col-1]->Type() == HCCELLTYPE_CONTFLOOR,
313 cells[row+1][col]->Type() == HCCELLTYPE_CONTFLOOR,
314 cells[row+1][col+1]->Type() == HCCELLTYPE_CONTFLOOR);
315 }
316 }
317
318 void HCMap::BuildContFloor(s32 row, s32 col)
319 {
320 BuildContFloorOnce(row - 1, col - 1);
321 BuildContFloorOnce(row - 1, col);
322 BuildContFloorOnce(row - 1, col + 1);
323 BuildContFloorOnce(row, col - 1);
324 BuildContFloorOnce(row, col);
325 BuildContFloorOnce(row, col + 1);
326 BuildContFloorOnce(row + 1, col - 1);
327 BuildContFloorOnce(row + 1, col);
328 BuildContFloorOnce(row + 1, col + 1);
329 }
330
331 void HCMap::BuildCellLinkList()
332 {
333 DestroyCellLinkList();
334
335 HCMapCell *mc = 0, *mcOld = 0;
336
337 for (s32 row = 0; row < rows; ++row)
338 {
339 for (s32 col = 0; col < cols; ++col)
340 {
341 if (cells[row][col]->Type() != HCCELLTYPE_BLANK)
342 {
343 mc = new HCMapCell;
344 mc->cell = cells[row][col];
345
346 if (mcOld)
347 {
348 mcOld->next = mc;
349 }
350
351 if (!linkCells)
352 {
353 linkCells = mc;
354 }
355
356 mcOld = mc;
357 }
358 }
359 }
360
361 if (mc)
362 {
363 mc->next = 0;
364 }
365 }
366
367 void HCMap::DestroyCellLinkList()
368 {
369 if (0 != linkCells)
370 {
371 HCMapCell *mc = linkCells, *tmp;
372
373 while (mc)
374 {
375 tmp = mc->next;
376 delete mc;
377 mc = tmp;
378 }
379
380 linkCells = 0;
381 }
382 }
383
384 u32 HCMap::Load(JRW &f)
385 {
386 Destroy();
387
388 // Loads the number of rows and cols, etc.
389 if (0 == f.ReadLE32((u32 *)&gravity) ||
390 0 == f.ReadLE32(&rows) ||
391 0 == f.ReadLE32(&cols) ||
392 0 == f.ReadLE32(&exitRow) ||
393 0 == f.ReadLE32(&exitCol))
394 {
395 return 1;
396 }
397
398 Resize(rows, cols);
399
400 // Loads the cells
401 s32 ret = 1;
402 s32 t, subt;
403 HCBreak *prevBreak = 0;
404
405 for (s32 row = 0; ret != 0 && row < rows; ++row)
406 {
407 for (s32 col = 0; ret != 0 && col < cols; ++col)
408 {
409 ret = f.ReadLE32(&t);
410 ret = f.ReadLE32(&subt);
411
412 if (t != HCCELLTYPE_BREAK)
413 {
414 prevBreak = 0;
415 }
416
417 JDELETE(cells[row][col]);
418
419 switch (t)
420 {
421 case HCCELLTYPE_FLOOR:
422 cells[row][col] = new HCFloorCell(&(theme->Floor(subt)));
423 cells[row][col]->Subtype(subt);
424 break;
425
426 case HCCELLTYPE_CONTFLOOR:
427 cells[row][col] = new HCContFloor;
428 cells[row][col]->Subtype(subt);
429 break;
430
431 case HCCELLTYPE_BAR:
432 cells[row][col] = new HCBarCell(&(theme->Bar(subt)));
433 cells[row][col]->Subtype(subt);
434 break;
435
436 case HCCELLTYPE_LADDER:
437 cells[row][col] = new HCLadderCell(&(theme->Ladder(subt)));
438 cells[row][col]->Subtype(subt);
439 break;
440
441 case HCCELLTYPE_BREAK:
442 cells[row][col] = prevBreak = new HCBreak(theme->Break(subt), prevBreak);
443 cells[row][col]->Subtype(subt);
444 break;
445
446 case HCCELLTYPE_BLANK:
447 default:
448 cells[row][col] = new HCCell;
449 cells[row][col]->Subtype(subt);
450 break;
451 }
452
453 t = cells[row][col]->Type();
454 }
455 }
456
457 for (s32 row = 1; ret != 0 && row < rows - 1; ++row)
458 {
459 for (s32 col = 1; ret != 0 && col < cols - 1; ++col)
460 {
461 if (cells[row][col]->Type() == HCCELLTYPE_CONTFLOOR)
462 BuildContFloor(row, col);
463 }
464 }
465
466 BuildCellLinkList();
467
468 return 0;
469 }
470
471 u32 HCMap::Save(JRW &f)
472 {
473 // Saves the number of rows and cols, etc.
474 if (0 == f.WriteLE32((u32 *)&gravity) ||
475 0 == f.WriteLE32(&rows) ||
476 0 == f.WriteLE32(&cols) ||
477 0 == f.WriteLE32(&exitRow) ||
478 0 == f.WriteLE32(&exitCol))
479 {
480 return 1;
481 }
482
483 // Saves the cells
484 s32 ret = 1;
485 s32 data, index;
486
487 for (s32 row = 0; ret != 0 && row < rows; ++row)
488 {
489 for (s32 col = 0; ret != 0 && col < cols; ++col)
490 {
491 data = cells[row][col]->Type();
492 index = cells[row][col]->Subtype();
493 ret = f.WriteLE32(&data);
494 ret = f.WriteLE32(&index);
495 }
496 }
497
498 return 0;
499 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Map definition file for Holotz's Castle.
23 * @file HCMap.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 29/04/2004
26 * @version 0.0.1 - 29/04/2004 - First version.
27 */
28
29 #ifndef _HCMAP_INCLUDED
30 #define _HCMAP_INCLUDED
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <JLib/Util/JTypes.h>
35 #include <JLib/Graphics/JDrawable.h>
36 #include <JLib/Graphics/JImage.h>
37 #include <JLib/Util/JFile.h>
38 #include <HCTheme.h>
39 #include <HCCell.h>
40 #include <HCBreak.h>
41 #include <HCContFloor.h>
42
43 /** Linked list of cells to be drawn/positioned/updated.
44 */
45 struct HCMapCell
46 {
47 HCCell *cell;
48 HCMapCell *next;
49 };
50
51 /** Holotz's Castle map. Consists of a matrix of cells.
52 */
53 class HCMap : public JDrawable
54 {
55 private:
56 s32 width; /**< Physical width of the map (in pixels). */
57 s32 height; /**< Physical height of the map (in pixels). */
58
59 protected:
60 s32 rows; /**< Map rows (logical height). */
61 s32 cols; /**< Map columns (logical width). */
62 s32 cellWidth; /**< Cell width in pixels. */
63 s32 cellHeight; /**< Cell height in pixels. */
64 HCCell ***cells; /**< Matrix of cells. */
65 HCTheme *theme; /**< Theme to be used. */
66 s32 level; /**< Level within the world. */
67
68 s32 exitRow; /**< Exit row. */
69 s32 exitCol; /**< Exit column. */
70
71 float gravity; /**< Gravity of the map. */
72
73 HCMapCell *linkCells; /**< Linked list of cells to be drawn/updated/positioned. */
74
75 /** Sets allowed actions for every cell in the map.
76 */
77 void SetActions();
78
79 /** Builds only the continuous cell at the given position based upon its neighbours.
80 * @param row Row of the cell to build.
81 * @param col Column of the cell to build.
82 */
83 void BuildContFloorOnce(s32 row, s32 col);
84
85 public:
86 /** Creates an empty map. Init() must be called before starting to use it..
87 */
88 HCMap();
89
90 /** Returns the number of rows.
91 * @return number of rows.
92 */
93 s32 Rows()
94 {
95 return rows;
96 }
97
98 /** Returns the number of cols.
99 * @return number of cols.
100 */
101 s32 Cols()
102 {
103 return cols;
104 }
105
106 /** Returns the width of a cell.
107 * @return the width of a cell.
108 */
109 s32 CellWidth()
110 {
111 return cellWidth;
112 }
113
114 /** Returns the height of a cell.
115 * @return the height of a cell.
116 */
117 s32 CellHeight()
118 {
119 return cellHeight;
120 }
121
122 /** Sets the width of a cell.
123 * @param w The width of a cell.
124 */
125 void CellWidth(s32 w)
126 {
127 cellWidth = w;
128 }
129
130 /** Sets the height of a cell.
131 * @param h The height of a cell.
132 */
133 void CellHeight(s32 h)
134 {
135 cellHeight = h;
136 }
137
138 /** Returns the width of the map.
139 * @return the width of the map.
140 */
141 s32 Width()
142 {
143 return width;
144 }
145
146 /** Returns the height of the map.
147 * @return the height of the map.
148 */
149 s32 Height()
150 {
151 return height;
152 }
153
154 /** Initializes this map.
155 * @param _theme Loaded theme to use.
156 * @return <b>true</b> if it was loaded successfully, <b>false</b> if not.
157 */
158 bool Init(HCTheme &_theme);
159
160 /** Converts from physical (screen) to logical (map) coords.
161 * The result is put in the same variables passed.
162 * @param xPos X coordinate of the pixel and the column after the call.
163 * @param yPos Y coordinate of the pixel and the row after the call.
164 */
165 void ScreenToMap(s32 &xPos, s32 &yPos);
166
167 /** Converts from logical (map) to physical (screen) coords.
168 * The result is put in the same variables passed.
169 * @param col Column of the cell and the x position of the cell's baseline mid-point.
170 * @param row Row of the cell and the y position of the cell's baseline mid-point.
171 */
172 void MapToScreen(s32 &col, s32 &row);
173
174 /** Converts from physical (screen) to logical (map) coords.
175 * @param xx X coordinate of the pixel.
176 * @return the column corresponding to that x.
177 */
178 s32 ToCol(s32 xx);
179
180 /** Converts from physical (screen) to logical (map) coords.
181 * @param yy Y coordinate of the pixel.
182 * @return the row corresponding to that y.
183 */
184 s32 ToRow(s32 yy);
185
186 /** Converts from logical (map) to physical (screen) coords.
187 * @param col Column of the cell.
188 * @return the x coordinate of the mid-point of the baseline of the cell.
189 */
190 s32 ToX(s32 col);
191
192 /** Converts from logical (map) to physical (screen) coords.
193 * @param row Row of the cell.
194 * @return the y coordinate of the mid-point of the baseline of the cell.
195 */
196 s32 ToY(s32 row);
197
198 /** Updates the map.
199 * @return 0 if successful, != 0 if not.
200 */
201 s32 Update();
202
203 /** Draws the map.
204 */
205 virtual void Draw();
206
207 /** Positions this map.
208 * @param xPos New x coordinate.
209 * @param yPos New y coordinate.
210 */
211 virtual void Pos(float xPos, float yPos);
212
213 /** Returns the cells at the row and column specified.
214 * It doesn't check if row and col are valid.
215 * @param row Cell's row.
216 * @param col Cell's column.
217 * @return The requested cell.
218 */
219 HCCell *Cell(s32 row, s32 col)
220 {return cells[row >= rows ? rows - 1 : row][col >= cols ? cols - 1 : col];}
221
222 /** Returns all the cells.
223 * @return The map's cells.
224 */
225 HCCell ***Cells()
226 {return cells;}
227
228 /** Returns the exit column for the main character.
229 * @return the exit column for the main character.
230 */
231 s32 ExitCol() {return exitCol;}
232
233 /** Returns the exit row for the main character.
234 * @return the exit row for the main character.
235 */
236 s32 ExitRow() {return exitRow;}
237
238 /** Returns the exit column for the main character.
239 * @param col The exit column for the main character.
240 */
241 void ExitCol(s32 col) {exitCol = col;}
242
243 /** Returns the exit row for the main character.
244 * @param row The exit row for the main character.
245 */
246 void ExitRow(s32 row) {exitRow = row;}
247
248 /** Loads the map.
249 * @param f The file from where to load, already positioned.
250 * @return 0 if succeeded, 1 if I/O error or 2 if integrity error.
251 */
252 u32 Load(JRW &f);
253
254 /** Saves the map.
255 * @param f The file where to save, already positioned.
256 * @return 0 if succeeded, 1 if I/O error or 2 if integrity error.
257 */
258 u32 Save(JRW &f);
259
260 /** Destroys the object and free its associated resources.
261 */
262 void Destroy();
263
264 /** Resizes the map. If enlarged, the old cells are pasted from the
265 * bottom-left corner of the original map to the same corner of the new map.
266 * @param newRows New number of rows.
267 * @param newCols New number of cols.
268 * @param growRight Indicates whether it must grow to the right (<b>true</b>, by default) or to the left.
269 * @param growDown Indicates whether it must grow down (<b>true</b>, by default) or upwards.
270 */
271 void Resize(s32 newRows, s32 newCols, bool growRight = true, bool growDown = true);
272
273 /** Builds the continuous cell at the given position and its neighbours.
274 * @param row Row of the cell to build.
275 * @param col Column of the cell to build.
276 */
277 void BuildContFloor(s32 row, s32 col);
278
279 /** (Re)Builds the linked list of cells.
280 */
281 void BuildCellLinkList();
282
283 /** Destroys the linked list of cells.
284 */
285 void DestroyCellLinkList();
286
287 /** Sets the gravity for this map.
288 * @param g New gravity for this map.
289 */
290 void Gravity(float g) {gravity = g;}
291
292 /** Gets the gravity for this map.
293 * @return Gravity for this map.
294 */
295 float Gravity() {return gravity;}
296
297 /** Destroys this object.
298 */
299 virtual ~HCMap() {Destroy();}
300 };
301
302 #endif // _HCMAP_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Object definition file.
23 * @file HCObject.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 30/04/2004
26 * @version 0.0.1 - 30/04/2004 - First version.
27 */
28
29 #include <HCObject.h>
30
31 s32 HCObject::Update()
32 {
33 switch (state)
34 {
35 case HCOBJECTSTATE_NORMAL:
36 normal.Update();
37 return 0;
38
39 case HCOBJECTSTATE_ACQUIRED:
40 if (-1 == acquired.Update())
41 {
42 // If the acquired state has ended, places it in a non-drawable state
43 state = HCOBJECTSTATE_NONE;
44 acquired.FirstFrame();
45 }
46 return 1;
47
48 case HCOBJECTSTATE_NONE:
49 default:
50 // Finished with this object
51 return -1;
52 }
53 }
54
55 void HCObject::Draw()
56 {
57 switch (state)
58 {
59 case HCOBJECTSTATE_NORMAL:
60 normal.Draw();
61 return;
62 case HCOBJECTSTATE_ACQUIRED:
63 acquired.Draw();
64 return;
65 case HCOBJECTSTATE_NONE:
66 default:
67 return;
68 }
69 }
70
71 bool HCObject::Init(HCTheme *theme)
72 {
73 normal.Destroy();
74 acquired.Destroy();
75 normal.Ref(theme->Object(subtype)[HCODT_NORMAL]);
76 acquired.Ref(theme->Object(subtype)[HCODT_ACQUIRED]);
77
78 return true;
79 }
80
81 u32 HCObject::Load(JRW &file)
82 {
83 if (0 == file.ReadLE32(&subtype) ||
84 0 == file.ReadLE32((u32 *)&pos.x) ||
85 0 == file.ReadLE32((u32 *)&pos.y))
86 {
87 fprintf(stderr, "Error loading the object.\n");
88
89 return 2;
90 }
91
92 Pos(pos.x, pos.y);
93
94 return 0;
95 }
96
97 u32 HCObject::Save(JRW &file)
98 {
99 if (0 == file.WriteLE32(&subtype) ||
100 0 == file.WriteLE32((u32 *)&pos.x) ||
101 0 == file.WriteLE32((u32 *)&pos.y))
102 {
103 fprintf(stderr, "Error saving the object.\n");
104
105 return 2;
106 }
107
108 return 0;
109 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Object definition file.
23 * @file HCObject.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 30/04/2004
26 * @version 0.0.1 - 30/04/2004 - First version.
27 */
28
29 #ifndef _HCOBJECT_INCLUDED
30 #define _HCOBJECT_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Graphics/JDrawable.h>
34 #include <HCTheme.h>
35 #include <HCCell.h>
36
37 /** Object state.
38 */
39 typedef enum
40 {
41 HCOBJECTSTATE_NONE = 0, /**< Non visible state. */
42 HCOBJECTSTATE_NORMAL, /**< Normal, visible state. */
43 HCOBJECTSTATE_ACQUIRED, /**< Acquired, visible state. */
44 } HCObjectState;
45
46 /** Object class. Defines an object of the game and its behaviour.
47 */
48 class HCObject : public JDrawable
49 {
50 protected:
51 HCObjectState state; /**< Object state. */
52 JImageSprite normal; /**< Normal sprite to show for the object. */
53 JImageSprite acquired; /**< Sprite to show when the object is obtained. */
54 s32 subtype; /**< Subtype (appearance) of this object. */
55
56 public:
57 /** Creates a new object in the HCOBJECTSTATE_NORMAL state.
58 */
59 HCObject() : state(HCOBJECTSTATE_NORMAL), subtype(0)
60 {}
61
62 /** Initializes the object according to the given theme and the current subtype.
63 * @param theme Theme to use.
64 * @return <b>true</b> if successfull, <b>false</b> otherwise.
65 */
66 bool Init(HCTheme *theme);
67
68 /** Updates the object.
69 * @return 0 If the object is in HCOBJECTSTATE_NORMAL, 1 if in HCOBJECTSTATE_ACQUIRED state,
70 * -1 if in HCOBJECTSTATE_NONE state. Any of the two last mean that the object has been
71 * acquired.
72 */
73 virtual s32 Update();
74
75 /** Draws the object.
76 */
77 virtual void Draw();
78
79 /** Places this object in the acquired state.
80 */
81 void Acquire() {state = HCOBJECTSTATE_ACQUIRED;}
82
83 /** Returns the state of this object.
84 * @return The state of this object.
85 */
86 HCObjectState State() {return state;}
87
88 /** Loads the object.
89 * @param file File opened and positioned already.
90 * @return 0 if it succeeds, 1 if there is an I/O error, 2 if integrity error.
91 */
92 u32 Load(JRW &file);
93
94 /** Saves the object.
95 * @param file File opened and positioned already.
96 * @return 0 if it succeeds, 1 if there is an I/O error, 2 if integrity error.
97 */
98 u32 Save(JRW &file);
99
100 /** Gets the subtype of this object.
101 * @return Subtype of this object.
102 */
103 s32 Subtype() {return subtype;}
104
105 /** Sets the subtype of this object.
106 * @param newSubtype New type of this object.
107 */
108 void Subtype(s32 newSubtype) {subtype = newSubtype;}
109
110 /** Positions this object.
111 * @param xPos New x coordinate.
112 * @param yPos New y coordinate.
113 */
114 virtual void Pos(float xPos, float yPos)
115 {normal.Pos(xPos, yPos); acquired.Pos(xPos, yPos); pos.x = xPos; pos.y = yPos;}
116
117 /** Gets this object's position.
118 * @return Object's position.
119 */
120 virtual const JVector & Pos() {return pos;}
121
122 /** Returns the normal sprite.
123 * @return The normal sprite.
124 */
125 JImageSprite & Normal() {return normal;}
126
127 /** Returns the acquired sprite.
128 * @return The acquired sprite.
129 */
130 JImageSprite & Acquired() {return acquired;}
131
132 /** Destroys the object.
133 */
134 virtual ~HCObject()
135 {}
136 };
137
138 #endif // _HCOBJECT_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Playlist for Holotz's castle.
23 * @file HCPlaylist.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 25/08/2004
26 * @version 0.0.1 - 25/08/2004 - First version.
27 */
28
29 #include <HCPlaylist.h>
30
31 #include <string.h>
32
33 #ifdef _WIN32
34 #define FILESYS_BAR '\\'
35 #else
36 #define FILESYS_BAR '/'
37 #endif
38
39 bool HCPlaylist::Load(const char *file)
40 {
41 if (file == 0)
42 {
43 if (!HCUtil::FindStories())
44 {
45 fprintf(stderr, "No stories found. Check manual.\n");
46
47 return false;
48 }
49
50 Destroy();
51
52 for (u32 i = 0; i < HCUtil::Stories().size(); ++i)
53 {
54 stories.push_back(strdup(HCUtil::Stories().at(i).Str()));
55 }
56
57 OrderStories();
58 GoTo(stories[0]);
59
60 return true;
61 }
62
63 if (!HCUtil::FindFile(file))
64 {
65 fprintf(stderr, "Couldn't find playlist file %s. Check manual.\n", file);
66 }
67
68 JTextFile f;
69 if (!f.Load(HCUtil::File()))
70 {
71 return false;
72 }
73
74 Destroy();
75
76 JString strFile;
77 char str[4096];
78
79 // Fills the playlist with each line in the file
80 while (f.ReadLine(str))
81 {
82 strFile = "stories/";
83 strFile += str;
84 if (HCUtil::FindFile(strFile))
85 {
86 stories.push_back(strdup(str));
87 }
88 else
89 {
90 fprintf(stderr, "Playlist entry not found: %s. Check manual.\n", str);
91 }
92 }
93
94 if (stories.size() > 0)
95 {
96 OrderStories();
97 GoTo(stories[0]);
98 }
99
100 return stories.size() > 0;
101 }
102
103 bool HCPlaylist::NextStory()
104 {
105 if (curStory + 1 >= (s32)stories.size())
106 {
107 return false;
108 }
109
110 ++curStory;
111
112 if (!HCUtil::FindFile(JString("stories/") + stories[curStory]))
113 {
114 --curStory;
115 return false;
116 }
117
118 strncpy(storyDir, HCUtil::Path(), sizeof(storyDir));
119 strncat(storyDir, "stories/", sizeof(storyDir));
120
121 return true;
122 }
123
124 bool HCPlaylist::GoTo(const char *_storyName)
125 {
126 bool found = false;
127
128 for (u32 i = 0; !found && i < stories.size(); ++i)
129 {
130 if (strcmp(stories[i], _storyName) == 0)
131 {
132 curStory = i;
133 found = true;
134 }
135 }
136
137 if (found)
138 {
139 if (!HCUtil::FindFile(JString("stories/") + stories[curStory]))
140 {
141 return false;
142 }
143
144 strncpy(storyDir, HCUtil::Path(), sizeof(storyDir));
145 strncat(storyDir, "stories/", sizeof(storyDir));
146 }
147
148 return found;
149 }
150
151 void HCPlaylist::OrderStories()
152 {
153 char *tmp;
154
155 for (u32 i = 0; i < stories.size() - 1; ++i)
156 {
157 for (u32 j = 0; j < stories.size() - 1 - i; ++j)
158 {
159 if (strcmp(stories[j+1], stories[j]) < 0)
160 {
161 tmp = stories[j];
162 stories[j] = stories[j+1];
163 stories[j+1] = tmp;
164 }
165 }
166 }
167 }
168
169 void HCPlaylist::Destroy()
170 {
171 for (u32 i = 0; i < stories.size(); ++i)
172 {
173 free(stories[i]);
174 }
175
176 stories.clear();
177 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Playlist for Holotz's castle.
23 * @file HCPlaylist.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 25/08/2004
26 * @version 0.0.1 - 25/08/2004 - First version.
27 */
28
29 #ifndef _HCPLAYLIST_INCLUDED
30 #define _HCPLAYLIST_INCLUDED
31
32 #include <vector>
33 #include <JLib/Util/JTypes.h>
34 #include <JLib/Util/JTextFile.h>
35 #include <JLib/Util/JObject.h>
36 #include <HCUtil.h>
37
38 #include <string.h>
39
40 #ifndef HC_DATA_DIR
41 #define HC_DATA_DIR "res/"
42 #endif
43
44 #define HCPLAYLIST_DEFFILENAME "playlist.txt"
45
46 class HCPlaylist
47 {
48 protected:
49 std::vector<char *> stories; /**< Playlist with the stories ordered. */
50 s32 curStory; /**< Current story playing. */
51 char storyDir[4096];
52
53 public:
54 /** Creates an empty playlist object. Load must be called before using it.
55 */
56 HCPlaylist() : curStory(0)
57 { strncpy(storyDir, HC_DATA_DIR, sizeof(storyDir)); }
58
59 /** Return the current story directory.
60 */
61 const char * StoryDir() { return storyDir;}
62
63 /** Return the current story name.
64 */
65 const char * StoryName() {return stories[curStory];}
66
67 /** Advances to the next story.
68 * @return <true> if there was another story, <b>false</b> otherwise.
69 */
70 bool NextStory();
71
72 /** Loads the playlist from the specified file.
73 * @param file Name of the file with the playlist.
74 * @return <b>true</b> if succeeded, <b>false</b>otherwise.
75 */
76 bool Load(const char *file = HCPLAYLIST_DEFFILENAME);
77
78 /** Goes to the first story.
79 */
80 void Reset() {curStory = 0;}
81
82 /** Goes to the given story.
83 * @param _storyName Name of the story to go to.
84 * @return <b>true</b> if the story exists, <b>false</b> otherwise.
85 */
86 bool GoTo(const char *_storyName);
87
88 /** Destroys the object.
89 */
90 void Destroy();
91
92 /** Returns the size of the playlist.
93 * @return Size of the playlist.
94 */
95 s32 Size() {return stories.size();}
96
97 /** Returns the element at position index.
98 * @param index Position of the element to retrieve.
99 * @return Element at position index.
100 */
101 char * operator[](s32 index) {return stories[index];}
102
103 /** Orders alphabetically the stories.
104 */
105 void OrderStories();
106
107 /** Destroys the object.
108 */
109 ~HCPlaylist() {Destroy();}
110 };
111
112 #endif // _HCPLAYLIST_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Preferences file for Holotz's Castle.
23 * @file HCPreferences.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 24/08/2004
26 * @version 0.0.1 - 24/08/2004 - First version.
27 */
28
29 #include <HCPreferences.h>
30
31 #ifndef HC_DATA_DIR
32 #define HC_DATA_DIR "res/"
33 #endif
34
35 #ifndef _WIN32
36 #include <string.h>
37 #include <unistd.h>
38 #endif
39
40 HCPreferences * HCPreferences::instance;
41
42 HCPreferences::HCPreferences()
43 {
44 langs = 0;
45 langCodes = 0;
46 numLangs = 0;
47 numVideoModes = 0;
48 videoModes = 0;
49 sound = 0;
50 difficulty = 0;
51 instance = this;
52 Reset();
53 }
54
55 void HCPreferences::Reset()
56 {
57 curLang = HCPREFERENCES_DEFLANGUAGE;
58 videoMode = HCPREFERENCES_DEFVIDEOMODE;
59 bpp = HCPREFERENCES_DEFBPP;
60 fullscreen = HCPREFERENCES_DEFFULLSCREEN;
61 sound = HCPREFERENCES_DEFSOUND;
62 difficulty = HCPREFERENCES_DEFDIFFICULTY;
63 }
64
65 void HCPreferences::BPP(s32 newBPP)
66 {
67 bpp = newBPP;
68
69 if (bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32)
70 bpp = HCPREFERENCES_DEFBPP;
71 }
72
73 s32 HCPreferences::Load(const char *filename)
74 {
75 Destroy();
76
77 s32 ret = 0;
78
79 // Loads the available video modes
80 videoModes = JListVideoModes(&numVideoModes, bpp);
81 if (!videoModes)
82 {
83 fprintf(stderr, "No fullscreen video modes found, forcing to windowed.\n");
84 ret |= 1;
85 }
86
87 // Loads the available languages
88 JTextFile fLang;
89 if (fLang.Load(HC_DATA_DIR HCPREFERENCES_LANGFILE, "rb"))
90 {
91 std::vector<char *> vL, vC;
92 char strLang[64];
93 char strCode[8];
94
95 while (2 == sscanf(fLang.GetPos(), "%[^;];%[a-z]", strLang, strCode))
96 {
97 vL.push_back(strdup(strLang));
98 vC.push_back(strdup(strCode));
99 fLang.NextLine();
100 }
101
102 numLangs = vC.size();
103 langs = new char *[numLangs];
104 langCodes = new char *[numLangs];
105
106 for (s32 i = 0; i < numLangs; ++i)
107 {
108 langs[i] = vL[i];
109 langCodes[i] = vC[i];
110 }
111 }
112 else
113 {
114 ret |= 2;
115 return ret;
116 }
117
118 const char *fname;
119 char name[256];
120
121 if (filename != 0)
122 fname = filename;
123 else
124 {
125 #ifndef _WIN32
126 char *home;
127 home = getenv("HOME");
128 if (home != NULL)
129 {
130 snprintf(name, sizeof(name), "%s/.holotz-castle/" HCPREFERENCES_DEFFILENAME, home);
131 fname = name;
132 }
133 else
134 fname = HC_DATA_DIR HCPREFERENCES_DEFFILENAME;
135 #else
136 fname = HC_DATA_DIR HCPREFERENCES_DEFFILENAME;
137 #endif
138 }
139
140 JTextFile f;
141
142 if (!f.Load(fname, "rb"))
143 {
144 // Error opening
145 // Overrides the default video mode with one that fits into the desktop, this prevents that the first time one plays
146 // and exit without changing the video size, the next time they play the video was bigger than the desktop,
147 // not allowing to see all the window, even the menu
148 if (videoModes)
149 {
150 // Conservative first guess...
151 videoMode = numVideoModes/2;
152
153 // ...but tries to put in a boundary of 640x480
154 for (s32 vmd = 0; vmd < numVideoModes; ++vmd)
155 {
156 if (videoModes[vmd].w <= 640 && videoModes[vmd].h <= 480)
157 {
158 videoMode = vmd;
159 break;
160 }
161 }
162 }
163
164 return 4;
165 }
166
167 // Loads the preferences
168 s32 fs, snd;
169 if (6 != sscanf(f.GetPos(), "language=%d video=%d bpp=%d fullscreen=%d audio=%d difficulty=%d", &curLang, &videoMode, &bpp, &fs, &snd, &difficulty))
170 {
171 // Incorrect file
172 return 8;
173 }
174
175 fullscreen = (fs != 0) ? true : false;
176 sound = (snd != 0) ? true : false;
177
178 BPP(bpp);
179 fullscreen = (fullscreen != 0) ? true : false;
180 sound = (sound != 0) ? true : false;
181 JClamp(difficulty, HCPREFERENCES_HARD, HCPREFERENCES_TOY);
182
183 return 0;
184 }
185
186 s32 HCPreferences::Save(const char *filename)
187 {
188 const char *fname;
189 char name[256];
190
191 if (filename != 0)
192 fname = filename;
193 else
194 {
195 #ifndef _WIN32
196 char *home;
197 home = getenv("HOME");
198 if (home != NULL)
199 {
200 snprintf(name, sizeof(name), "%s/.holotz-castle", home);
201 mkdir(name, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
202 snprintf(name, sizeof(name), "%s/.holotz-castle/" HCPREFERENCES_DEFFILENAME, home);
203 fname = name;
204 }
205 else
206 fname = HC_DATA_DIR HCPREFERENCES_DEFFILENAME;
207 #else
208 fname = HC_DATA_DIR HCPREFERENCES_DEFFILENAME;
209 #endif
210 }
211
212 JTextFile f;
213
214 if (!f.Open(fname, "wb"))
215 {
216 // Error opening
217 return 1;
218 }
219
220 // Saves the preferences
221 if (0 > f.Printf("language=%d\nvideo=%d\nbpp=%d\nfullscreen=%d\naudio=%d\ndifficulty=%d", curLang, videoMode, bpp, fullscreen ? 1 : 0, sound ? 1 : 0, difficulty))
222 {
223 // Incorrect file
224 return 2;
225 }
226
227 return 0;
228 }
229
230 void HCPreferences::Destroy()
231 {
232 if (langs != 0)
233 {
234 for (s32 i = 0; i < numLangs; ++i)
235 {
236 if (langs[i] != 0)
237 {
238 free(langs[i]);
239 }
240 }
241
242 delete[] langs;
243 }
244
245 if (langCodes != 0)
246 {
247 for (s32 i = 0; i < numLangs; ++i)
248 {
249 if (langCodes[i] != 0)
250 {
251 free(langCodes[i]);
252 }
253 }
254
255 delete[] langCodes;
256 }
257
258 numLangs = 0;
259 JDELETE_ARRAY(videoModes);
260 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Preferences file for Holotz's Castle.
23 * @file HCPreferences.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 24/08/2004
26 * @version 0.0.1 - 24/08/2004 - First version.
27 */
28
29 #ifndef _HCPREFERENCES_INCLUDED
30 #define _HCPREFERENCES_INCLUDED
31
32 #include <vector>
33 #include <JLib/Util/JTextFile.h>
34 #include <JLib/Util/JUtil.h>
35 #include <JLib/Util/JTypes.h>
36
37 #define HCPREFERENCES_TOY 5 // Toy difficulty level
38 #define HCPREFERENCES_EASY 4 // Easy difficulty level
39 #define HCPREFERENCES_NORMAL 2 // Normal difficulty level
40 #define HCPREFERENCES_HARD 1 // Hard difficulty level
41
42 #define HCPREFERENCES_DEFFILENAME "preferences.txt"
43 #define HCPREFERENCES_DEFLANGUAGE 0
44 #define HCPREFERENCES_DEFVIDEOMODE 0
45 #define HCPREFERENCES_DEFBPP 16
46 #define HCPREFERENCES_DEFFULLSCREEN false
47 #define HCPREFERENCES_DEFSOUND true
48 #define HCPREFERENCES_LANGFILE "languages.txt"
49 #define HCPREFERENCES_DEFDIFFICULTY HCPREFERENCES_NORMAL
50
51 class HCPreferences
52 {
53 protected:
54 char **langs; /**< Available languages strings. */
55 char **langCodes; /**< Country codes strings for available languages (es, en, de, etc.). */
56 s32 numLangs; /**< Number of different languages. */
57 s32 curLang; /**< Current language index/country code. */
58 s32 videoMode; /**< Video mode from the list of video modes supported. */
59 JVideoMode *videoModes; /**< Available video modes. */
60 s32 numVideoModes; /**< Number of available video modes. */
61 s32 bpp; /**< Color depth in bits per pixel. */
62 bool fullscreen; /**< Fullscreen/windowed flag. */
63 bool sound; /**< Sound on/off flag. */
64 s32 difficulty; /**< Level of difficulty (Easy/Medium/Hard). */
65 static HCPreferences *instance; /**< Unique instance of the object. */
66
67 public:
68 /** Creates an empty preferences object.
69 */
70 HCPreferences();
71
72 /** Returns the instance of this preference object.
73 * @return Instance ob this object.
74 */
75 static HCPreferences * Prefs() {return instance;}
76
77 /** Sets the language.
78 * @param lang Index of the available languages to use.
79 */
80 void CurLang(s32 curLanguage) {curLang = curLanguage; JClamp(curLang, 0, numLangs);}
81
82 /** Gets the current language index.
83 * @return Current language index.
84 */
85 s32 CurLang() {return curLang;}
86
87 /** Gets the available languages strings.
88 * @return Available languages strings.
89 */
90 char **Langs() {return langs;}
91
92 /** Gets the available language country codes.
93 * @return Available language country codes.
94 */
95 char **LangCodes() {return langCodes;}
96
97 /** Gets the number of available languages.
98 * @return Number of available languages.
99 */
100 s32 NumLangs() {return numLangs;}
101
102 /** Gets the number of available video modes.
103 * @return Number of available video modes.
104 */
105 s32 NumVideoModes() {return numVideoModes;}
106
107 /** Gets the available video modes.
108 * @return Available video modes or 0 if none exist.
109 */
110 JVideoMode * VideoModes() {return videoModes;}
111
112 /** Sets the video mode number.
113 * @param Ordinal of the video mode to use, based upon the available modes.
114 */
115 void VideoMode(s32 mode) {videoMode = mode;}
116
117 /** Gets the video mode number.
118 * @return Video mode number.
119 */
120 s32 VideoMode() {return videoMode;}
121
122 /** Sets color depth.
123 * @param New color depth. Supports 8, 16, 24 and 32 bits.
124 */
125 void BPP(s32 newBPP);
126
127 /** Gets the color depth.
128 * @return Color depth.
129 */
130 s32 BPP() {return bpp;}
131
132 /** Sets windowed or fullscreen mode.
133 * @param <b>true</b> to use fullscreen mode, <b>false</b> for windowed mode.
134 */
135 void Fullscreen(bool fs) {fullscreen = fs;}
136
137 /** Gets the playing mode (windowed or full screen).
138 * @return <b>true</b> if fullscreen mode, <b>false</b> if windowed mode.
139 */
140 bool Fullscreen() {return fullscreen;}
141
142 /** Sets sound mode.
143 * @param <b>true</b> activates sound, <b>false</b> deactivates it.
144 */
145 void Sound(bool fs) {sound = fs;}
146
147 /** Gets the sound mode.
148 * @return <b>true</b> if sound is active, <b>false</b> if not.
149 */
150 bool Sound() {return sound;}
151
152 /** Sets the level of difficulty.
153 * @param Level of difficulty, one of HCPREFERENCES_EASY, HCPREFERENCES_NORMAL, HCPREFERENCES_HARD.
154 */
155 void Difficulty(s32 newDiff) {difficulty = newDiff; JClamp(difficulty, HCPREFERENCES_HARD, HCPREFERENCES_TOY);}
156
157 /** Gets the level of difficulty.
158 * @return Current level of difficulty, one of HCPREFERENCES_EASY, HCPREFERENCES_NORMAL, HCPREFERENCES_HARD.
159 */
160 s32 Difficulty() {return difficulty;}
161
162 /** Resets to defaults.
163 */
164 void Reset();
165
166 /** Load the preferences file.
167 * @param filename Name of the file to use or 0 (the default) to use the default file name.
168 * @return 0 if loading succeeded, 1 if I/O error, 2 if integrity error.
169 */
170 s32 Load(const char *filename = 0);
171
172 /** Saves the preferences file.
173 * @param filename Name of the file to use or 0 (the default) to use the default file name.
174 * @return 0 if saving succeeded, 1 if I/O error, 2 if integrity error.
175 */
176 s32 Save(const char *filename = 0);
177
178 /** Destroys this object.
179 */
180 void Destroy();
181
182 /** Destroys this object.
183 */
184 virtual ~HCPreferences() {Destroy();}
185 };
186
187 #endif // _HCPREFERENCES_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Definiton of a rope.
23 * @file HCRope.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 05/06/2004
26 * @version 0.0.1 - 05/06/2004 - First version.
27 */
28
29 #include <HCRope.h>
30
31 bool HCRope::Init(float p, s32 a, u32 l, HCTheme &theme)
32 {
33 // Creates references of the images and places the rope in its original position
34 top.Ref(theme.Rope(subtype)[HCRDT_TOP]);
35 top.Pos(pos.x, pos.y);
36
37 period = p >= 1.0f ? p : 1.0f;
38 w = 6.2831853/period;
39 length = l > 0 ? l : 5;
40 amplitude = abs(a) < length * theme.Rope(subtype)[HCRDT_MIDDLE].Height() ? abs(a) : length * theme.Rope(subtype)[HCRDT_MIDDLE].Height();
41
42 s32 i;
43 float y;
44
45 JDELETE_ARRAY(middle);
46 middle = new JImage [length];
47
48 if (middle == 0)
49 return false;
50
51 for (i = 0; i < length; ++i)
52 {
53 middle[i].Ref(theme.Rope(subtype)[HCRDT_MIDDLE]);
54 y = top.Y() + top.Height() + (i * middle[i].Height());
55 middle[i].Pos(top.X() + (top.Width()/2) - (middle[i].Width()/2), pos.y);
56 }
57
58 edge.Ref(theme.Rope(subtype)[HCRDT_EDGE]);
59 y = top.Y() + top.Height() + (i * middle[0].Height());
60 edge.Pos(top.X() + (top.Width()/2) - (edge.Width()/2), pos.y);
61
62 // 25 fps resolution
63 timer.Start(40);
64
65 return true;
66 }
67
68 void HCRope::Draw()
69 {
70 top.Draw();
71
72 for (s32 i = 0; i < length; ++i)
73 {
74 middle[i].Draw();
75 }
76
77 edge.Draw();
78 }
79
80 s32 HCRope::Update()
81 {
82 float t = float(timer.TotalLap())/1000.0f;
83
84 edge.X((top.X() + top.Width()/2) - (edge.Width()/2) + (amplitude * cos(w * t)));
85
86 float alpha = asin((float(amplitude) * cos(w * t))/float(length * middle[0].Height()));
87 float newY = length * middle[0].Height() * cos(alpha);
88
89 edge.Y(top.Y() + top.Height() + newY);
90
91 float dx = ((edge.X() + edge.Width()/2) - (top.X() + top.Width()/2))/float(length);
92 float dy = ((edge.Y() + edge.Height()/2) - (top.Y() + top.Height()))/float(length);
93
94 for (s32 i = 0; i < length; ++i)
95 {
96 middle[i].X((top.X() + top.Width()/2) + (i * dx) - (middle[i].Width()/2));
97 middle[i].Y((top.Y() + top.Height()) + (i * dy));
98 }
99
100 direction = (s32)(10.0f * dx);
101
102 return 0;
103 }
104
105 void HCRope::Pos(float x, float y)
106 {
107 float dx, dy;
108 dx = x - pos.x;
109 dy = y - pos.y;
110
111 pos.x = x;
112 pos.y = y;
113
114 for (s32 i = 0; i < length; ++i)
115 {
116 middle[i].X(middle[i].X() + dx);
117 middle[i].Y(middle[i].Y() + dy);
118 }
119
120 edge.X(edge.X() + dx);
121 edge.Y(edge.Y() + dy);
122
123 top.X(x);
124 top.Y(y);
125 }
126
127 u32 HCRope::Load(JRW &file)
128 {
129 if (0 == file.ReadLE32((u32 *)&period) ||
130 0 == file.ReadLE32(&amplitude) ||
131 0 == file.ReadLE32(&length) ||
132 0 == file.ReadLE32(&subtype) ||
133 0 == file.ReadLE32((u32 *)&pos.x) ||
134 0 == file.ReadLE32((u32 *)&pos.y))
135 {
136 fprintf(stderr, "Error reading rope parameters.\n");
137
138 return 1;
139 }
140
141 return 0;
142 }
143
144 u32 HCRope::Load(JRW &file, HCTheme &theme)
145 {
146 if (0 != Load(file))
147 {
148 return 1;
149 }
150
151 if (!Init(period, amplitude, length, theme))
152 {
153 return 2;
154 }
155
156 Pos(pos.x, pos.y);
157
158 return 0;
159 }
160
161 u32 HCRope::Save(JRW &file)
162 {
163 if (0 == file.WriteLE32((u32 *)&period) ||
164 0 == file.WriteLE32(&amplitude) ||
165 0 == file.WriteLE32(&length) ||
166 0 == file.WriteLE32(&subtype) ||
167 0 == file.WriteLE32((u32 *)&pos.x) ||
168 0 == file.WriteLE32((u32 *)&pos.y))
169 {
170 fprintf(stderr, "Error writing rope parameters.\n");
171
172 return 1;
173 }
174
175 return 0;
176 }
177
178 HCRope::~HCRope()
179 {
180 JDELETE_ARRAY(middle);
181 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Definiton of a rope.
23 * @file HCRope.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 05/06/2004
26 * @version 0.0.1 - 05/06/2004 - First version.
27 */
28
29 #ifndef _HCROPE_INCLUDED
30 #define _HCROPE_INCLUDED
31
32 #include <JLib/Graphics/JDrawable.h>
33 #include <JLib/Graphics/JImage.h>
34 #include <JLib/Util/JTimer.h>
35 #include <JLib/Util/JFile.h>
36 #include <HCTheme.h>
37
38 /** Encapsulates a rope for Holotz's Castle.
39 * Consists of three base images (top, middle and edge of the rope).
40 * The length of the rope refers to the number of middle parts.
41 */
42 class HCRope : public JDrawable
43 {
44 protected:
45 float w; /**< Angular veloccity of the edge. */
46 float period; /**< Period of the edge. */
47 s32 amplitude; /**< Rope's amplitude. */
48 s32 length; /**< Rope's length. */
49 JImage top; /**< Top image. */
50 JImage *middle; /**< Middle images. */
51 JImage edge; /**< Edge image. */
52 JTimer timer; /**< Timer. */
53
54 s32 subtype; /**< Theme subtype. */
55 s32 direction; /**< Direction of movement (left/right). */
56
57 /** Loads the rope.
58 * @param file File opened and positioned already.
59 * @return 0 if it succeeds, 1 if there is an I/O error, 2 if integrity error.
60 */
61 u32 Load(JRW &file);
62
63 public:
64 /** Creates an empty rope. Init must be called in order to use it.
65 */
66 HCRope() : w(0), period(0), amplitude(0), length(5), middle(0), subtype(0)
67 {}
68
69 /** Initializes the rope with the given parameters.
70 * @param p Complete period of the rope in seconds (the time the edge needs to go
71 * from left to right and return).
72 * @param a Half the amplitude of movement in the horizontal direction.
73 * @param l Length of the rope, in middle image units.
74 * @param theme Theme to use.
75 */
76 bool Init(float p, s32 a, u32 l, HCTheme &theme);
77
78 /** Draws the rope.
79 */
80 void Draw();
81
82 /** Updates the rope.
83 * @return 0 if not changed, 1 if so.
84 */
85 s32 Update();
86
87 /** Sets the position of the top of the rope.
88 * @param newX New x position.
89 * @param newY New y position.
90 */
91 void Pos(float x, float y);
92
93 /** Gets the period of this rope.
94 * @return Period of this rope.
95 */
96 float Period() {return period;}
97
98 /** Gets the amplitude of this rope.
99 * @return Amplitude of this rope.
100 */
101 s32 Amplitude() {return amplitude;}
102
103 /** Gets the length of this rope.
104 * @return Length of this rope.
105 */
106 s32 Length() {return length;}
107
108 /** Returns the edge image.
109 * @return Edge image.
110 */
111 JImage & Edge() {return edge;}
112
113 /** Loads the rope using the given theme.
114 * @param file File opened and positioned already.
115 * @param theme Theme to use for the graphics.
116 * @return 0 if it succeeds, 1 if there is an I/O error, 2 if integrity error.
117 */
118 u32 Load(JRW &file, HCTheme &theme);
119
120 /** Saves the rope. The file must be opened and positioned already.
121 * @param file File opened and positioned already.
122 * @return 0 if it succeeds, 1 if there is an I/O error, 2 if integrity error.
123 */
124 u32 Save(JRW &file);
125
126 /** Gets the subtype of this rope.
127 * @return Subtype of this rope.
128 */
129 s32 Subtype() {return subtype;}
130
131 /** Sets the subtype of this rope.
132 * @param newSubtype New type of this rope.
133 */
134 void Subtype(s32 newSubtype) {subtype = newSubtype;}
135
136 /** Returns the direction of movement.
137 * @return 0 if stopped, > 0 if moving right, < 0 if moving left
138 */
139 s32 Direction() {return direction;}
140
141 /** Destroys the object, frees resources and allows scalar destruction.
142 */
143 virtual ~HCRope();
144 };
145
146 #endif // _HCROPE_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Script engine for Holotz's Castle.
23 * @file HCScript.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 03/07/2004
26 * @version 0.0.1 - 03/07/2004 - Primera versión.
27 */
28
29 #include <HCScript.h>
30
31 bool HCScript::Init(HCLevel *_level)
32 {
33 if (!_level)
34 {
35 return false;
36 }
37
38 level = _level;
39
40 return true;
41 }
42
43 bool HCScript::Load(const char *filename)
44 {
45 JTextFile f;
46
47 if (!f.Load(filename, "rt"))
48 {
49 return false;
50 }
51
52 // Creates the necessary blocks
53 numBlocks = f.CountString("{");
54
55 if (numBlocks == 0)
56 {
57 fprintf(stderr, "HCScript error: No execution blocks.\n");
58 return false;
59 }
60
61 f.StartOfDocument();
62
63 if (numBlocks != (s32)f.CountString("}"))
64 {
65 fprintf(stderr, "HCScript error: Mismatched braces!\n");
66 return false;
67 }
68
69 blocks = new HCScriptBlock[numBlocks];
70
71 // Process each block
72 s8 *begin, *end;
73
74 f.StartOfDocument();
75
76 for (s32 i = 0; i < numBlocks; ++i)
77 {
78 f.FindNext("{");
79
80 begin = f.GetPos();
81 f.FindNext("}");
82 end = f.GetPos();
83
84 f.SetPos(begin);
85
86 // Load the blocks
87 blocks[i].Load(f);
88 }
89
90 // Start!
91 blocks[0].Current();
92
93 return true;
94 }
95
96 s32 HCScript::Update()
97 {
98 if (curBlock == numBlocks)
99 {
100 return -1;
101 }
102
103 s32 ret = blocks[curBlock].Update();
104
105 if (blocks[curBlock].Finished())
106 {
107 ++curBlock;
108
109 if (curBlock == numBlocks)
110 {
111 return -1;
112 }
113
114 // Prepares the block for execution
115 blocks[curBlock].Current();
116 }
117
118 return ret;
119 }
120
121 bool HCScript::Finished()
122 {
123 return curBlock == numBlocks;
124 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Script engine for Holotz's Castle.
23 * @file HCScript.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 03/07/2004
26 * @version 0.0.1 - 03/07/2004 - Primera versión.
27 */
28
29 #ifndef _HCSCRIPT_INCLUDED
30 #define _HCSCRIPT_INCLUDED
31
32 #include <JLib/Util/JTextFile.h>
33 #include <HCScriptBlock.h>
34 #include <HCLevel.h>
35
36 class HCScriptBlock;
37
38 class HCScript
39 {
40 protected:
41 HCScriptBlock *blocks; /**< Execution blocks. */
42 s32 numBlocks; /**< Number of execution blocks. */
43 s32 curBlock; /**< Current block index. */
44 HCLevel *level; /**< Level for this script. */
45
46 public:
47 /** Creates an empty script. Init and Load must be called in order to begin to use it.
48 */
49 HCScript() : blocks(0), numBlocks(0), curBlock(0), level(0)
50 {}
51
52 /** Initializes this script.
53 * @param _level Associated level.
54 * @return <b>true</b> if succeeded, <b>false</b> if not.
55 */
56 bool Init(HCLevel *_level);
57
58 /** Loads a script.
59 * @param filename Name of the file containing the script.
60 * @return <b>true</b> if succeeded, <b>false</b> otherwise.
61 */
62 bool Load(const char *filename);
63
64 /** Skips the dialog actions in the current block.
65 */
66 void Skip() {if (blocks) blocks[curBlock].Skip();}
67
68 /** Updates this script. Checks for block termination and procceeds with
69 * the next block if so.
70 * @return 0 if the execution block hasn't changed, 1 if changed, -1 if the
71 * script has finished.
72 */
73 s32 Update();
74
75 /** Checks if the script has finished its execution.
76 * @return <b>true<b> if it has finished, <b>false<b> otherwise.
77 */
78 bool Finished();
79
80 /** Destroys the object.
81 */
82 void Destroy() {JDELETE_ARRAY(blocks); numBlocks = curBlock = 0; level = 0;}
83
84 /** Destroys the object.
85 */
86 virtual ~HCScript() {Destroy();}
87 };
88
89 #endif // _HCSCRIPT_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Definition of script actions.
23 * @file HCScriptAction.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 03/07/2004
26 * @version 0.0.1 - 03/07/2004 - Primera versión.
27 */
28
29 #include <HCScriptAction.h>
30 #include <HolotzCastle.h>
31
32 s32 HCScriptAction::Update()
33 {
34 finished = true;
35 return 0;
36 }
37
38 HCCharacter * HCScriptAction::Character(const char *name, s32 index)
39 {
40 HCApp *app = (HCApp *)JApp::App();
41
42 if (0 == strcmp(name, "main"))
43 {
44 return app->Level()->Character();
45 }
46 else
47 if (0 == strcmp(name, "enemy"))
48 {
49 if (index >= app->Level()->NumEnemies())
50 {
51 fprintf(stderr, "No such enemy: %d\n", index);
52 }
53
54 return app->Level()->Enemies()[index];
55 }
56 else
57 {
58 fprintf(stderr,
59 "HCScriptAction: Unknown character %s!\n"
60 "Available are main and enemy\n", name);
61 }
62
63 return 0;
64 }
65
66 HCScriptAction * HCScriptAction::Load(JTextFile &f)
67 {
68 char str[1024];
69
70 if (f.FindNext("["))
71 {
72 s8 * start = f.GetPos();
73
74 if (f.SkipNextWord())
75 {
76 if (f.ReadWord(str))
77 {
78 if (strcmp(str, "MOVE") == 0)
79 {
80 // Move action
81 HCScriptActionMove *action = new HCScriptActionMove;
82 f.SetPos(start);
83
84 if (action->Load(f))
85 {
86 f.FindNext("]");
87
88 return action;
89 }
90 }
91 else
92 if (strcmp(str, "DIALOG") == 0)
93 {
94 // Dialog action
95 HCScriptActionDialog *action = new HCScriptActionDialog;
96 f.SetPos(start);
97
98 if (action->Load(f))
99 {
100 f.FindNext("]");
101
102 return action;
103 }
104 }
105 else
106 if (strcmp(str, "NARRATIVE") == 0)
107 {
108 // Narrative action
109 HCScriptActionNarrative *action = new HCScriptActionNarrative;
110 f.SetPos(start);
111
112 if (action->Load(f))
113 {
114 f.FindNext("]");
115
116 return action;
117 }
118 }
119 else
120 if (strcmp(str, "SOUND") == 0)
121 {
122 // Sound action
123 HCScriptActionSound *action = new HCScriptActionSound;
124 f.SetPos(start);
125
126 if (action->Load(f))
127 {
128 f.FindNext("]");
129
130 return action;
131 }
132 }
133 else
134 if (strcmp(str, "WAIT") == 0)
135 {
136 // Wait action
137 HCScriptActionWait *action = new HCScriptActionWait;
138 f.SetPos(start);
139
140 if (action->Load(f))
141 {
142 f.FindNext("]");
143
144 return action;
145 }
146 }
147 else
148 {
149 // Unknown action
150 fprintf(stderr, "Unknown action found!\n");
151
152 return 0;
153 }
154 }
155 }
156 }
157 else
158 {
159 fprintf(stderr, "HCScriptAction: No action found!\n");
160 }
161
162 return 0;
163 }
164
165 bool HCScriptActionMove::Init(HCCharacter *_character, s32 dir, s32 amount)
166 {
167 if (0 == _character)
168 {
169 return false;
170 }
171
172 character = _character;
173 totalAmount = amount;
174 direction = dir;
175
176 return true;
177 }
178
179 bool HCScriptActionMove::Load(JTextFile &f)
180 {
181 char charName[32];
182 s32 index;
183
184 if (4 == sscanf(f.GetPos(), "[ MOVE %[A-Za-z] ( %d ) dir=%d amount=%d ]",
185 charName, &index, &direction, &totalAmount))
186 {
187 HCCharacter *tmpChar;
188
189 tmpChar = Character(charName, index);
190
191 if (0 == tmpChar)
192 {
193 return false;
194 }
195
196 if (direction != 2 && (direction < 4 || direction > 9))
197 {
198 fprintf(stderr, "HCScriptActionMove: Direction must be one of 2 or 4 to 9!\n");
199
200 return false;
201 }
202
203 return Init(tmpChar, direction, totalAmount);
204 }
205
206 fprintf(stderr, "HCScriptActionMove: Failed to load!\n");
207
208 return false;
209 }
210
211 s32 HCScriptActionMove::Update()
212 {
213 if (finished)
214 {
215 return 0;
216 }
217
218 // Finished if not moving leftright or updown.
219 switch (direction)
220 {
221 case 2:
222 character->Act(HCCA_DOWN);
223 if (character->State() != HCCS_DOWN)
224 {
225 character->State(HCCS_STOP);
226 character->Veloccity().y = 0;
227 finished = true;
228 return 0;
229 }
230 break;
231
232 case 4:
233 character->Act(HCCA_LEFT);
234 if (character->Acceleration().x > -0.001f/* || character->State() != HCCS_LEFT*/)
235 {
236 character->Veloccity().x = character->Acceleration().x = 0;
237 character->State(HCCS_STOP);
238 finished = true;
239 return 0;
240 }
241 break;
242
243 case 5:
244 character->Act(HCCA_JUMP);
245 if (character->Veloccity().y > 0.0f || character->State() != HCCS_JUMP)
246 {
247 finished = true;
248 return 0;
249 }
250 break;
251
252 case 6:
253 character->Act(HCCA_RIGHT);
254 if (character->Acceleration().x < 0.001f /*|| character->State() != HCCS_RIGHT*/)
255 {
256 character->Veloccity().x = character->Acceleration().x = 0;
257 character->State(HCCS_STOP);
258 finished = true;
259 return 0;
260 }
261 break;
262
263 case 7:
264 character->Act(HCCA_JUMP | HCCA_LEFT);
265 if (character->Acceleration().x > -0.001f || character->State() != HCCS_JUMPLEFT)
266 {
267 finished = true;
268 return 0;
269 }
270 break;
271
272 case 8:
273 character->Act(HCCA_UP);
274 if (character->State() != HCCS_UP)
275 {
276 character->Veloccity().y = 0;
277 character->State(HCCS_STOP);
278 finished = true;
279 return 0;
280 }
281 break;
282
283 case 9:
284 character->Act(HCCA_JUMP | HCCA_RIGHT);
285 if (character->Acceleration().x < 0.001f || character->State() != HCCS_JUMPRIGHT)
286 {
287 finished = true;
288 return 0;
289 }
290 break;
291
292 default:
293 character->Veloccity().y = 0;
294 character->Veloccity().x = character->Acceleration().x = 0;
295 character->Act(HCCA_STOP);
296 break;
297 }
298
299 s32 row = character->Row();
300 s32 col = character->Col();
301
302 // Cell changed?
303 if (row != lastRow)
304 {
305 lastRow = row;
306 switch (direction)
307 {
308 // Only counts for up and down actions
309 case 8:
310 case 2:
311 ++curAmount;
312 break;
313
314 default:
315 break;
316 }
317 }
318
319 if (col != lastCol)
320 {
321 // This governs also the jumpxxx actions
322 lastCol = col;
323 ++curAmount;
324 }
325
326 // Travelled the specified amount of cells
327 if (curAmount >= totalAmount)
328 {
329 finished = true;
330 }
331
332 if (finished)
333 {
334 switch (direction)
335 {
336 case 5:
337 character->Act(HCCA_JUMP);
338 break;
339
340 default:
341 character->Act(HCCA_STOP);
342 break;
343 }
344
345 direction = 0;
346 return 0;
347 }
348
349 return 1;
350 }
351
352 void HCScriptActionMove::Current()
353 {
354 lastRow = orgRow = character->Row();
355 lastCol = orgCol = character->Col();
356 curAmount = 0;
357 }
358
359 bool HCScriptActionDialog::Init(HCCharacter *_character,
360 const char *text,
361 HCTheme *theme,
362 JFont *font,
363 JFontAlign align,
364 bool left,
365 s32 subtype,
366 u8 r, u8 g, u8 b)
367 {
368 if (0 == _character || 0 == theme || 0 == font)
369 {
370 return false;
371 }
372
373 character = _character;
374 if (!dialog.Init(HCTEXTTYPE_DIALOG, text, theme, font, align, left, subtype, r, g, b))
375 {
376 fprintf(stderr, "Couldn't initialize dialog action.\n");
377 return false;
378 }
379
380 float *x = (float*)&((character->JDrawable::Pos()).x);
381 float *y = (float*)&((character->JDrawable::Pos()).y);
382
383 dialog.Track(x, y);
384 if (left)
385 dialog.Pos(character->CurSprite()->MaxW()/2, -character->CurSprite()->MaxH()/2);
386 else
387 dialog.Pos(-character->CurSprite()->MaxH()/2, -character->CurSprite()->MaxH()/2);
388
389
390 return true;
391 }
392
393 bool HCScriptActionDialog::Load(JTextFile &f)
394 {
395 char charName[32];
396 char text[256];
397 s32 index, left, speed, r, g, b, size, txtAlign, st;
398 JFontAlign fontAlign;
399
400 memset(text, 0, sizeof(text));
401 memset(charName, 0, sizeof(charName));
402
403 if (11 == sscanf(f.GetPos(), "[ DIALOG %[A-Za-z](%d) text=\"%[^\"]\" txtAlign=%d speed=%d size=%d align=%d r=%d g=%d b=%d subtype=%d ]", charName, &index, text, &txtAlign, &speed, &size, &left, &r, &g, &b, &st))
404 {
405 HCApp *app = (HCApp*)JApp::App();
406 HCCharacter *tmpChar = Character(charName, index);
407
408 JClamp(size, 1, 3);
409 JFont *fnt;
410
411 switch (size)
412 {
413 default:
414 case 1: fnt = app->FontSmall(); break;
415 case 2: fnt = app->FontMedium(); break;
416 case 3: fnt = app->FontLarge(); break;
417 }
418
419 s32 oldSpeed = HCText::Speed();
420
421 switch (txtAlign % 3)
422 {
423 case 0:
424 fontAlign = JFONTALIGN_RIGHT;
425 break;
426 default:
427 case 1:
428 fontAlign = JFONTALIGN_LEFT;
429 break;
430 case 2:
431 fontAlign = JFONTALIGN_CENTER;
432 break;
433 }
434
435 Init(tmpChar, text, &app->Level()->Theme(), fnt, fontAlign, left != 0, st, r, g, b);
436
437 HCText::Speed(oldSpeed);
438 }
439 else
440 {
441 fprintf(stderr, "HCScriptActionDialog: Failed to load!\n");
442
443 return false;
444 }
445
446 return true;
447 }
448
449 s32 HCScriptActionDialog::Update()
450 {
451 if (!finished)
452 {
453 if (!dialog.Visible())
454 {
455 finished = true;
456 }
457
458 return 1;
459 }
460
461 return 0;
462 }
463
464 void HCScriptActionDialog::Current()
465 {
466 dialog.Reset();
467 character->Dialog(&dialog);
468 }
469
470 bool HCScriptActionNarrative::Init(s32 alignment,
471 const char *text,
472 HCTheme *theme,
473 JFont *font,
474 JFontAlign align,
475 s32 subtype,
476 u8 r, u8 g, u8 b)
477 {
478 if (0 == theme || 0 == font)
479 {
480 return false;
481 }
482
483 if (!narrative.Init(HCTEXTTYPE_NARRATIVE, text, theme, font, align, false, subtype, r, g, b))
484 {
485 fprintf(stderr, "Couldn't initialize narrative action.\n");
486 return false;
487 }
488
489 // Aligns the frame within the screen
490 s32 x, y;
491 switch (alignment)
492 {
493 case 1:
494 x = 0;
495 y = JApp::App()->Height() - narrative.Image().Height();
496 break;
497 case 2:
498 x = (JApp::App()->Width() - narrative.Image().Width())/2;
499 y = JApp::App()->Height() - narrative.Image().Height();
500 break;
501 case 3:
502 x = JApp::App()->Width() - narrative.Image().Width();
503 y = JApp::App()->Height() - narrative.Image().Height();
504 break;
505 case 4:
506 x = 0;
507 y = (JApp::App()->Height() - narrative.Image().Height())/2;
508 break;
509 case 5:
510 x = (JApp::App()->Width() - narrative.Image().Width())/2;
511 y = (JApp::App()->Height() - narrative.Image().Height())/2;
512 break;
513 case 6:
514 x = JApp::App()->Width() - narrative.Image().Width();
515 y = (JApp::App()->Height() - narrative.Image().Height())/2;
516 break;
517 default:
518 case 7:
519 x = 0;
520 y = 0;
521 break;
522 case 8:
523 x = (JApp::App()->Width() - narrative.Image().Width())/2;
524 y = 0;
525 break;
526 case 9:
527 x = JApp::App()->Width() - narrative.Image().Width();
528 y = 0;
529 break;
530 }
531
532 narrative.Pos(x, y);
533
534 return true;
535 }
536
537 bool HCScriptActionNarrative::Load(JTextFile &f)
538 {
539 char text[256];
540 s32 align, speed, r, g, b, size, txtAlign, st;
541 JFontAlign fontAlign;
542 memset(text, 0, sizeof(text));
543
544 if (9 == sscanf(f.GetPos(),
545 "[ NARRATIVE text=\"%[^\"]\" txtAlign=%d speed=%d size=%d align=%d r=%d g=%d b=%d subtype=%d ]",
546 text, &txtAlign, &speed, &size, &align, &r, &g, &b, &st))
547 {
548 HCApp *app = (HCApp*)JApp::App();
549
550 JClamp(size, 1, 3);
551 JFont *fnt;
552
553 switch (size)
554 {
555 default:
556 case 1: fnt = app->FontSmall(); break;
557 case 2: fnt = app->FontMedium(); break;
558 case 3: fnt = app->FontLarge(); break;
559 }
560
561 s32 oldSpeed = HCText::Speed();
562
563 switch (txtAlign % 3)
564 {
565 case 0:
566 fontAlign = JFONTALIGN_RIGHT;
567 break;
568 default:
569 case 1:
570 fontAlign = JFONTALIGN_LEFT;
571 break;
572 case 2:
573 fontAlign = JFONTALIGN_CENTER;
574 break;
575 }
576
577 Init(align, text, &app->Level()->Theme(), fnt, fontAlign, st, r, g, b);
578
579 HCText::Speed(oldSpeed);
580 }
581 else
582 {
583 fprintf(stderr, "HCScriptActionNarrative: Failed to load!\n");
584
585 return false;
586 }
587
588 return true;
589 }
590
591 s32 HCScriptActionNarrative::Update()
592 {
593 if (!finished)
594 {
595 if (!narrative.Visible())
596 {
597 finished = true;
598 }
599
600 return 1;
601 }
602
603 return 0;
604 }
605
606 void HCScriptActionNarrative::Current()
607 {
608 narrative.Reset();
609 ((HCApp*)JApp::App())->Level()->Narrative(&narrative);
610 }
611
612 bool HCScriptActionSound::Init(const char *filename, s32 loops, bool waitToEnd)
613 {
614 numLoops = loops;
615
616 if (!waitToEnd)
617 {
618 finished = true;
619 }
620
621 if (JApp::App()->SoundEnabled())
622 {
623 return (sound.LoadWave(filename));
624 }
625 else
626 {
627 return true;
628 }
629
630 return false;
631 }
632
633 void HCScriptActionSound::Current()
634 {
635 if (JApp::App()->SoundEnabled())
636 {
637 sound.Play(-1, numLoops);
638 }
639 }
640
641 bool HCScriptActionSound::Load(JTextFile &f)
642 {
643 s32 waitToEnd, loops;
644 char file[1024];
645
646 if (3 == sscanf(f.GetPos(), "[ SOUND file=\"%[^\"]\" loops=%d waitToEnd=%d ]",
647 file, &loops, &waitToEnd))
648 {
649 char filename[1024];
650 snprintf(filename, sizeof(filename), "%s%s", HC_DATA_DIR, file);
651 return Init(filename, loops, waitToEnd != 0);
652 }
653
654 return false;
655 }
656
657 s32 HCScriptActionSound::Update()
658 {
659 if (!finished)
660 {
661 if (!sound.IsPlaying())
662 {
663 finished = true;
664 }
665 }
666
667 return 0;
668 }
669
670 void HCScriptActionWait::Current()
671 {
672 timer.Start(ms);
673 }
674
675 bool HCScriptActionWait::Init(s32 millis)
676 {
677 ms = millis;
678
679 return true;
680 }
681
682 bool HCScriptActionWait::Load(JTextFile &f)
683 {
684 s32 millis;
685
686 if (1 == sscanf(f.GetPos(), "[ WAIT millis=%d ]", &millis))
687 {
688 return Init(millis);
689 }
690
691 return false;
692 }
693
694 s32 HCScriptActionWait::Update()
695 {
696 if (!finished)
697 {
698 if (timer.Changed())
699 {
700 finished = true;
701 }
702 }
703
704 return 0;
705 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Definition of script actions.
23 * @file HCScriptAction.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 03/07/2004
26 * @version 0.0.1 - 03/07/2004 - Primera versión.
27 */
28
29 #ifndef _HCSCRIPTACTION_INCLUDED
30 #define _HCSCRIPTACTION_INCLUDED
31
32 #include <JLib/Util/JTypes.h>
33 #include <JLib/Util/JApp.h>
34 #include <JLib/Util/JTextFile.h>
35 #include <JLib/Util/JUtil.h>
36 #include <JLib/Graphics/JFont.h>
37 #include <HCCharacter.h>
38 #include <HCText.h>
39
40 class HCApp;
41
42 /** Types of action.
43 */
44 enum HCScriptActionType
45 {
46 HCSAT_NOP = 0, /**< No operation. */
47 HCSAT_MOVE, /**< Moves a character. */
48 HCSAT_DIALOG, /**< Makes a character to talk. */
49 HCSAT_NARRATIVE, /**< Shows a narrative text. */
50 HCSAT_SOUND, /**< Plays a sound. */
51 HCSAT_WAIT, /**< Waits. */
52 };
53
54 /** Basic action.
55 */
56 class HCScriptAction
57 {
58 public:
59 HCScriptActionType type; /**< Type of this action. */
60 bool finished; /**< Indicates whether it has finished or not. */
61
62 /** Creates a script action.
63 */
64 HCScriptAction(HCScriptActionType _type = HCSAT_NOP) : type(_type), finished(false)
65 {}
66
67 /** Checks if it has finished.
68 * @return <b>true<b> if it has finished, <b>false</b> otherwise.
69 */
70 bool Finished() {return finished;}
71
72 /** Loads the action from the file. If the method encounters '[ MOVE ball 2 4 5 ]', it will
73 * create and return a new HCScriptActionMove* (MOVE) casted to a HCScriptAction* of
74 * the third (2) ball enemy of the level to move left (4) five cells (5).
75 * @param f File Opened an positioned in the begin of the action (just after character '[').
76 * @return A new action corresponding to the one found or 0 if an error occurred.
77 */
78 static HCScriptAction * Load(JTextFile &f);
79
80 /** Returns the appropiate character based upon its name and index.
81 * @param name Character name. Must be one of "main", "enemy" or "guest".
82 * @index index Index of the character in the array.
83 */
84 HCCharacter * Character(const char *name, s32 index);
85
86 /** Skips this action. Must be implemented in the children classes, if possible.
87 */
88 virtual void Skip() {}
89
90 /** Updates the action.
91 * @return 0 if it didn't need update, 1 otherwise.
92 */
93 virtual s32 Update();
94
95 /** Prepares the action for execution. The block calls this method when its time
96 * to execute the action. The action prepares its data to be executed (init timers, etc.).
97 */
98 virtual void Current() {}
99
100 /** Destroys the object.
101 */
102 virtual ~HCScriptAction() {}
103 };
104
105 /** For unifying the actions' hierarchy.
106 */
107 typedef HCScriptAction HCScriptActionNop;
108
109 class HCScriptActionMove : public HCScriptAction
110 {
111 protected:
112 HCCharacter *character; /**< Character to move. */
113 s32 direction; /**< Direction to follow. */
114 s32 totalAmount; /**< Amount of cells to displace. */
115 s32 curAmount; /**< Current amount of cells. */
116 s32 orgRow; /**< Original row. */
117 s32 orgCol; /**< Original column. */
118 s32 lastRow; /**< Last visited row. */
119 s32 lastCol; /**< Last visited column. */
120
121 public:
122 /** Creates an empty Move Action. Init must be called in order to use it.
123 */
124 HCScriptActionMove() : HCScriptAction(HCSAT_MOVE), character(0)
125 {}
126
127 /** Initializes this action.
128 * @param _character Character to move.
129 * @param dir Movement direction (one of 2, 4, 6 or 8).
130 * @param amount Movement amount in cells.
131 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
132 */
133 bool Init(HCCharacter *_character, s32 dir, s32 amount);
134
135 /** Loads the action from the file.
136 * @param f File Opened an positioned in the begin of the action (just after character '[').
137 * @return <b>true</b> if loading succeeded, <b>false</b> otherwise.
138 */
139 bool Load(JTextFile &f);
140
141 /** Updates the action.
142 * @return 0 if it didn't need update, 1 otherwise.
143 */
144 virtual s32 Update();
145
146 /** Sets the character state.
147 */
148 virtual void Current();
149
150 /** Destroys the object.
151 */
152 virtual ~HCScriptActionMove() {}
153 };
154
155 class HCScriptActionDialog : public HCScriptAction
156 {
157 protected:
158 HCCharacter *character; /**< Character who talks. */
159 HCText dialog; /**< Dialog to show. */
160
161 public:
162 /** Creates an empty Dialog Action. Init must be called in order to use it.
163 */
164 HCScriptActionDialog() : HCScriptAction(HCSAT_DIALOG), character(0)
165 {}
166
167 /** Initializes this action.
168 * @param _character Character to talk.
169 * @param text Text of the dialog.
170 * @param theme Theme to use.
171 * @param font Font to use.
172 * @param align Alignment of text.
173 * @param left Whether the peak must face to the left or to the right.
174 * @param subtype Subtype within the theme.
175 * @param r Color red component.
176 * @param g Color green component.
177 * @param b Color blue component.
178 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
179 */
180 bool Init(HCCharacter *_character,
181 const char *text,
182 HCTheme *theme,
183 JFont *font,
184 JFontAlign align,
185 bool left,
186 s32 subtype,
187 u8 r, u8 g, u8 b);
188
189 /** Loads the action from the file.
190 * @param f File Opened an positioned in the begin of the action (just after character '[').
191 * @return <b>true</b> if loading succeeded, <b>false</b> otherwise.
192 */
193 bool Load(JTextFile &f);
194
195 /** Updates the action.
196 * @return 0 if it didn't need update, 1 otherwise.
197 */
198 virtual s32 Update();
199
200 /** Skips this action.
201 */
202 virtual void Skip() {dialog.Skip();}
203
204 /** Sets the character's dialog and inits the timer.
205 */
206 virtual void Current();
207
208 /** Destroys the object.
209 */
210 virtual ~HCScriptActionDialog() {}
211 };
212
213 class HCScriptActionNarrative : public HCScriptAction
214 {
215 protected:
216 HCText narrative; /**< Narrative to show. */
217
218 public:
219 /** Creates an empty Narrative Action. Init must be called in order to use it.
220 */
221 HCScriptActionNarrative() : HCScriptAction(HCSAT_NARRATIVE)
222 {}
223
224 /** Initializes this action.
225 * @param s32 Frame alignment within screen.
226 * @param text Text of the narrative.
227 * @param theme Theme to use.
228 * @param font Font to use.
229 * @param align Alignment of text.
230 * @param left Whether the peak must face to the left or to the right.
231 * @param subtype Subtype within the theme.
232 * @param r Color red component.
233 * @param g Color green component.
234 * @param b Color blue component.
235 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
236 */
237 bool Init(s32 alignment,
238 const char *text,
239 HCTheme *theme,
240 JFont *font,
241 JFontAlign align,
242 s32 subtype,
243 u8 r, u8 g, u8 b);
244
245 /** Loads the action from the file.
246 * @param f File Opened an positioned in the begin of the action (just after character '[').
247 * @return <b>true</b> if loading succeeded, <b>false</b> otherwise.
248 */
249 bool Load(JTextFile &f);
250
251 /** Updates the action.
252 * @return 0 if it didn't need update, 1 otherwise.
253 */
254 virtual s32 Update();
255
256 /** Prepares for execution.
257 */
258 virtual void Current();
259
260 /** Destroys the object.
261 */
262 virtual ~HCScriptActionNarrative() {}
263 };
264
265 class HCScriptActionSound : public HCScriptAction
266 {
267 protected:
268 JChunk sound; /**< Sound to play. */
269 s32 numLoops; /**< Number of loops, -1 means play forever, 0 means once, 1 means 2 times, and so on. */
270
271 public:
272 /** Creates an empty Sound Action. Init must be called in order to use it.
273 */
274 HCScriptActionSound() : HCScriptAction(HCSAT_SOUND)
275 {}
276
277 /** Initializes this action.
278 * @param filename File name of the sound.
279 * @param loops Number of loops, -1 means forever.
280 * @param waitToEnd Must end to considere it is finished?
281 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
282 */
283 bool Init(const char *filename, s32 loops, bool waitToEnd);
284
285 /** Loads the action from the file.
286 * @param f File Opened an positioned in the begin of the action (just after character '[').
287 * @return <b>true</b> if loading succeeded, <b>false</b> otherwise.
288 */
289 bool Load(JTextFile &f);
290
291 /** Updates the action.
292 * @return 0 if it didn't need update, 1 otherwise.
293 */
294 virtual s32 Update();
295
296 /** Prepares the action for execution. The block calls this method when its time
297 * to execute the action. The action prepares its data to be executed (init timers, etc.).
298 */
299 virtual void Current();
300
301 /** Destroys the object.
302 */
303 virtual ~HCScriptActionSound() {}
304 };
305
306 class HCScriptActionWait : public HCScriptAction
307 {
308 protected:
309 JTimer timer; /**< Timer. */
310 s32 ms; /**< Millisecond to wait. */
311
312 public:
313 /** Creates an empty Wait Action. Init must be called in order to use it.
314 */
315 HCScriptActionWait() : HCScriptAction(HCSAT_WAIT)
316 {}
317
318 /** Initializes this action.
319 * @param loops Number of milliseconds to wait.
320 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
321 */
322 bool Init(s32 millis = 1000);
323
324 /** Loads the action from the file.
325 * @param f File Opened an positioned in the begin of the action (just after character '[').
326 * @return <b>true</b> if loading succeeded, <b>false</b> otherwise.
327 */
328 bool Load(JTextFile &f);
329
330 /** Updates the action.
331 * @return 0 if it didn't need update, 1 otherwise.
332 */
333 virtual s32 Update();
334
335 /** Prepares the action for execution. The block calls this method when its time
336 * to execute the action. The action prepares its data to be executed (init timers, etc.).
337 */
338 virtual void Current();
339
340 /** Destroys the object.
341 */
342 virtual ~HCScriptActionWait() {}
343 };
344
345 #endif // _HCSCRIPTACTION_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Execution block for Holotz's Castle's script engine.
23 * @file HCScriptBlock.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 03/07/2004
26 * @version 0.0.1 - 03/07/2004 - Primera versión.
27 */
28
29 #include <HCScriptBlock.h>
30
31 bool HCScriptBlock::Finished()
32 {
33 bool finished = true;
34
35 for (s32 i = 0; finished && i < numActions; ++i)
36 {
37 finished = actions[i]->Finished();
38 }
39
40 return finished;
41 }
42
43 s32 HCScriptBlock::Update()
44 {
45 s32 ret = 0;
46
47 for (s32 i = 0; i < numActions; ++i)
48 {
49 if (!actions[i]->Finished())
50 {
51 ret |= actions[i]->Update();
52 }
53 }
54
55 return ret;
56 }
57
58 bool HCScriptBlock::Load(JTextFile &f)
59 {
60 // Find the beginning of the block
61 if (f.FindNext("{"))
62 {
63 s8 * start = f.GetPos();
64
65 // Find the end of the block
66 if (f.FindNext("}"))
67 {
68 s8 * end = f.GetPos();
69 f.SetPos(start);
70 JDELETE_POINTER_ARRAY(actions, numActions);
71 numActions = 0;
72
73 // Counts the number of actions in the block
74 while (f.FindNext("[") && f.GetPos() < end)
75 {
76 f.SkipNextWord();
77 ++numActions;
78 }
79
80 f.SetPos(start);
81
82 if (numActions == 0)
83 {
84 fprintf(stderr, "No actions in block!\n");
85 return false;
86 }
87
88 // Creates the action array
89 actions = new HCScriptAction* [numActions];
90
91 for (s32 i = 0; i < numActions; ++i)
92 {
93 f.FindNext("[");
94 actions[i] = HCScriptAction::Load(f);
95 }
96 }
97 else
98 {
99 fprintf(stderr, "Mismatched block brace!\n");
100 }
101 }
102 else
103 {
104 fprintf(stderr, "No block to load!\n");
105 }
106
107 return false;
108 }
109
110 void HCScriptBlock::Skip()
111 {
112 for (s32 i = 0; i < numActions; ++i)
113 {
114 if (actions[i]->type == HCSAT_DIALOG)
115 {
116 actions[i]->Skip();
117 }
118 }
119 }
120
121 void HCScriptBlock::Current()
122 {
123 for (s32 i = 0; i < numActions; ++i)
124 {
125 actions[i]->Current();
126 }
127 }
128
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Execution block for Holotz's Castle's script engine.
23 * @file HCScriptBlock.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 03/07/2004
26 * @version 0.0.1 - 03/07/2004 - Primera versión.
27 */
28
29 #ifndef _HCSCRIPTBLOCK_INCLUDED
30 #define _HCSCRIPTBLOCK_INCLUDED
31
32 #include <JLib/Util/JObject.h>
33 #include <HCScriptAction.h>
34
35 class HCScriptAction;
36
37 class HCScriptBlock
38 {
39 protected:
40 HCScriptAction **actions; /**< Actions of this block. */
41 s32 numActions; /**< Number of actions of this block. */
42
43 public:
44 /** Creates an empty block of actions.
45 */
46 HCScriptBlock() : actions(0), numActions(0)
47 {}
48
49 /** Checks if the block has finished its execution.
50 * @return <b>true<b> if it has finished, <b>false<b> otherwise.
51 */
52 bool Finished();
53
54 /** Updates the actions of this block;
55 * @return 0 if no changes had been made, 1 otherwise.
56 */
57 s32 Update();
58
59 /** Loads the block from the file. If the method encounters '{ ... }', it will
60 * search for valid actions in the '...' section.
61 * @param f File already opened and positioned before the block to read.
62 * @return <b>true</b> if successfull, <b>false</b> otherwise.
63 */
64 bool Load(JTextFile &f);
65
66 /** Skips the dialog actions in this block.
67 */
68 void Skip();
69
70 /** Prepares the block for execution. The script calls this method when its time
71 * to execute the block. The block prepares its actions to be executed.
72 */
73 virtual void Current();
74
75 /** Destroys the block and frees resources.
76 */
77 virtual ~HCScriptBlock() {JDELETE_POINTER_ARRAY(actions, numActions);}
78 };
79
80 #endif // _HCSCRIPTBLOCK_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Text messages for Holotz's Castle. Base class.
23 * @file HCText.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 25/06/2004
26 * @version 0.0.1 - 25/06/2004 - Primera versión.
27 */
28
29 #include <HCText.h>
30
31 s32 HCText::textSpeed = 5;
32 s32 HCText::minDelay = 2000;
33 s32 HCText::maxAlpha = 180;
34
35 bool HCText::Init(HCTextType _type, const char *_text,
36 HCTheme *_theme, JFont *_font,
37 JFontAlign a, bool _left, s32 _subtype,
38 u8 r, u8 g, u8 b)
39 {
40 if (!_text || !_theme || !_font)
41 {
42 return false;
43 }
44
45 theme = _theme;
46 font = _font;
47 left = _left;
48 subtype = _subtype;
49 type = _type;
50
51 JImage *img;
52
53 switch (type)
54 {
55 case HCTEXTTYPE_DIALOG:
56 img = theme->Dialog(subtype);
57 break;
58
59 default:
60 case HCTEXTTYPE_NARRATIVE:
61 img = theme->Narrative(subtype);
62 break;
63 }
64
65 // Builds the text
66 JImage *textImg;
67 SDL_Color fg = {r, g, b, 0};
68 textImg = font->PrintfBlended(a, fg, _text);
69
70 // Builds the frame
71 s32 rows = 0, cols = 0, x = 0, y = 0;
72 cols = (s32)floor(textImg->Width()/img[HCTDT_5].Width()) + 2;
73 rows = (s32)floor(textImg->Height()/img[HCTDT_5].Height()) + 2;
74
75 if (rows < 2)
76 rows = 2;
77
78 if (cols < 2)
79 cols = 2;
80
81 s32 w = cols * img[HCTDT_5].Width(), h = rows * img[HCTDT_5].Height();
82
83 // Makes space for the peak, if necessary
84 if (type == HCTEXTTYPE_DIALOG)
85 {
86 text.Create(w, h + img[HCTDT_5].Height(), SDL_GetVideoSurface()->format->BitsPerPixel);
87 }
88 else
89 {
90 text.Create(w, h, SDL_GetVideoSurface()->format->BitsPerPixel);
91 }
92
93 // Upper left corner
94 text.Paste(&img[HCTDT_7], 0, 0, img[HCTDT_7].Width(), img[HCTDT_7].Height(), x, y);
95 x += img[HCTDT_7].Width();
96
97 // Upper side
98 for (s32 i = 1; i < cols - 1; ++i)
99 {
100 text.Paste(&img[HCTDT_8], 0, 0, img[HCTDT_8].Width(), img[HCTDT_8].Height(), x, y);
101 x += img[HCTDT_8].Width();
102 }
103
104 // Upper right corner
105 text.Paste(&img[HCTDT_9], 0, 0, img[HCTDT_9].Width(), img[HCTDT_9].Height(), x, y);
106 x += img[HCTDT_9].Width();
107
108 y += img[HCTDT_5].Height();
109
110 for (s32 j = 1; j < rows - 1; ++j)
111 {
112 x = 0;
113
114 // Left side
115 text.Paste(&img[HCTDT_4], 0, 0, img[HCTDT_4].Width(), img[HCTDT_4].Height(), x, y);
116 x += img[HCTDT_4].Width();
117
118 // Middle
119 for (s32 i = 1; i < cols - 1; ++i)
120 {
121 text.Paste(&img[HCTDT_5], 0, 0, img[HCTDT_5].Width(), img[HCTDT_5].Height(), x, y);
122 x += img[HCTDT_5].Width();
123 }
124
125 // Right side
126 text.Paste(&img[HCTDT_6], 0, 0, img[HCTDT_6].Width(), img[HCTDT_6].Height(), x, y);
127 x += img[HCTDT_6].Width();
128 y += img[HCTDT_5].Height();
129 }
130
131 // Lower left corner
132 x = 0;
133 text.Paste(&img[HCTDT_1], 0, 0, img[HCTDT_1].Width(), img[HCTDT_1].Height(), x, y);
134 x += img[HCTDT_1].Width();
135
136 // Lower side
137 for (s32 i = 1; i < cols - 1; ++i)
138 {
139 text.Paste(&img[HCTDT_2], 0, 0, img[HCTDT_2].Width(), img[HCTDT_2].Height(), x, y);
140 x += img[HCTDT_2].Width();
141 }
142
143 // Lower right corner
144 text.Paste(&img[HCTDT_3], 0, 0, img[HCTDT_3].Width(), img[HCTDT_3].Height(), x, y);
145
146 if (type == HCTEXTTYPE_DIALOG)
147 {
148 y += img[HCTDT_5].Height() - (img[HCTDT_LEFT].Height() - img[HCTDT_5].Height());
149
150 // The peak is placed in the middle point of the two first or last
151 // frame-squares (depending on the left parameter).
152 // If the image y N pixels high than the full square (HCTDT_5) then
153 // it is placed N pixels up than a normal square (to adjust it to the frame).
154 if (left)
155 {
156 // Places the peak facing left
157 x = img[HCTDT_1].Width()/2;
158 text.Paste(&img[HCTDT_LEFT],
159 0, 0,
160 img[HCTDT_LEFT].Width(), img[HCTDT_LEFT].Height(),
161 x, y);
162 }
163 else
164 {
165 // Places the peak facing rigth
166 x = w - img[HCTDT_RIGHT].Width() - img[HCTDT_1].Width()/2;
167 text.Paste(&img[HCTDT_RIGHT],
168 0, 0,
169 img[HCTDT_RIGHT].Width(), img[HCTDT_RIGHT].Height(),
170 x, y);
171 }
172 }
173
174 switch (a)
175 {
176 case JFONTALIGN_LEFT:
177 x = img[HCTDT_7].Width()/2;
178 break;
179
180 case JFONTALIGN_RIGHT:
181 x = text.Width() - textImg->Width() - img[HCTDT_7].Width();
182 break;
183
184 case JFONTALIGN_CENTER:
185 x = (text.Width() - textImg->Width())/2;
186 break;
187 }
188
189 y = (h - textImg->Height())/2;
190
191 // Pega el texto
192 text.Paste(textImg,
193 0, 0,
194 textImg->Width(), textImg->Height(),
195 x, y);
196
197 text.ColorKey(0);
198
199 delete textImg;
200
201 // Initializes the fading timer
202 if (textSpeed < 1)
203 textSpeed = 1;
204
205 if (textSpeed > 10)
206 textSpeed = 10;
207
208 if (minDelay < 1000)
209 minDelay = 1000;
210
211 if (maxAlpha > 255)
212 maxAlpha = 255;
213
214 if (maxAlpha < 0)
215 maxAlpha = 180;
216
217 // Must be a multiple of 15
218 maxAlpha -= (maxAlpha % 15);
219
220 float delay;
221 delay = 500.0f * float(strlen(_text))/float(textSpeed);
222 if (delay < minDelay)
223 delay = minDelay;
224
225 timer.Start((s32)delay);
226
227 return true;
228 }
229
230 s32 HCText::Update()
231 {
232 if (text.Alpha() > 0)
233 {
234 // Checks for fade-in
235 if (timer.Cycles() == 0 && text.Alpha() < maxAlpha)
236 {
237 // make it appear
238 text.Alpha(text.Alpha() + 15);
239 }
240 else
241 if (timer.Cycles() > 0 && text.Alpha() > 0)
242 {
243 // make it disappear
244 text.Alpha(text.Alpha() - 15);
245 }
246
247 // Updates the pos refered to the peak, if following something, else
248 // let it as is
249 if (trackX != &pos.x)
250 {
251 if (left)
252 {
253 text.X((s32)*trackX - theme->Dialog(subtype)[HCTDT_1].Width()/2 + pos.x);
254 }
255 else
256 {
257 text.X((s32)*trackX - text.Width() + theme->Dialog(subtype)[HCTDT_1].Width()/2 + pos.x);
258 }
259
260 text.Y((s32)*trackY - text.Height() + pos.y);
261
262 return 1;
263 }
264 }
265 else
266 {
267 return 2;
268 }
269
270 return 0;
271 }
272
273 void HCText::Draw()
274 {
275 text.Draw();
276 }
277
278 void HCText::Track(float *x, float *y)
279 {
280 trackX = x ? x : &pos.x;
281 trackY = y ? y : &pos.y;
282 }
283
284 void HCText::Reset()
285 {
286 timer.Start(timer.CycleTime());
287 text.Alpha(15);
288 }
289
290 void HCText::Destroy()
291 {
292 text.Destroy();
293 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Text messages for Holotz's Castle. Base class.
23 * @file HCText.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 25/06/2004
26 * @version 0.0.1 - 25/06/2004 - Primera versión.
27 */
28
29 #ifndef _HCTEXT_INCLUDED
30 #define _HCTEXT_INCLUDED
31
32 #include <JLib/Graphics/JDrawable.h>
33 #include <JLib/Graphics/JImage.h>
34 #include <JLib/Graphics/JFont.h>
35 #include <HCTheme.h>
36
37 typedef enum HCTextType
38 {
39 HCTEXTTYPE_DIALOG, /**< Dialog balloon. */
40 HCTEXTTYPE_NARRATIVE, /**< Narrative frame. */
41 HCTEXTTYPE_COUNT, /**< Number of different types. */
42 };
43
44 /** Encapsulates a generic text message.
45 */
46 class HCText : public JDrawable
47 {
48 protected:
49 JFont *font; /**< Font to render the text with. */
50 JImage text; /**< Rendered text. */
51 HCTheme *theme; /**< Theme of the text object. */
52 HCTextType type; /**< Type of text object. */
53 s32 subtype; /**< Subtype within the theme. */
54 bool left; /**< Peak direction. */
55 float *trackX; /**< Tracked x position. */
56 float *trackY; /**< Tracked y position. */
57
58 JTimer timer; /**< Timer for fades. */
59 static s32 textSpeed; /**< Text duration factor [1-10]. */
60 static s32 minDelay; /**< Minimum delay for text. */
61 static s32 maxAlpha; /**< Maximum alpha value. */
62
63 public:
64 /** Creates an empty text object. Init must be called before using it.
65 */
66 HCText() : font(0), theme(0), type(HCTEXTTYPE_DIALOG),
67 subtype(0), left(true), trackX(&pos.x), trackY(&pos.y)
68 {}
69
70 /** Initializes the object.
71 * @param _type The type of text object.
72 * @param _text Text to draw.
73 * @param _theme Theme from where to load the images.
74 * @param _font Font to use to render the text.
75 * @param a The Alignment of the text.
76 * @param _left Peak direction (only for dialog frames).
77 * @return <b>true</b> if successful, <b>false</b> if not.
78 */
79 bool Init(HCTextType _type, const char *_text, HCTheme *_theme,
80 JFont *_font, JFontAlign a, bool _left = true, s32 _subtype = 0,
81 u8 r = 255, u8 g = 255, u8 b = 255);
82
83 /** Gets the type of this text.
84 * @return Type of this text.
85 */
86 const HCTextType & Type() {return type;}
87
88 /** Sets the type of this text.
89 * @param newType New type of this text.
90 */
91 void Type(const HCTextType &newType) {type = newType;}
92
93 /** Gets the subtype of this text.
94 * @return Subtype of this text.
95 */
96 s32 Subtype() {return subtype;}
97
98 /** Sets the subtype of this text.
99 * @param newSubtype New type of this text.
100 */
101 void Subtype(s32 newSubtype) {subtype = newSubtype;}
102
103 /** Positions this object.
104 * @param x New x coordinate.
105 * @param y New y coordinate.
106 */
107 virtual void Pos(float x, float y)
108 {pos.x = x; pos.y = y; text.Pos(x, y); }
109
110 /** Draws the object.
111 */
112 virtual void Draw();
113
114 /** Updates the object.
115 * @return 2 if disappeared, 1 if following something, 0 otherwise.
116 */
117 virtual s32 Update();
118
119 /** Follows the given coordinates such that every time the coordinates change,
120 * this text moves. If 0 is passed, the no tracking is made.
121 * @param xTrack Pointer to the x position to track.
122 * @param yTrack Pointer to the y position to track.
123 */
124 void Track(float *x = 0, float *y = 0);
125
126 /** Chechs whether this text is visible or not.
127 * @return <b>true</b> if it's visible, <b>false</b> otherwise.
128 */
129 bool Visible() {return text.Alpha() > 0;}
130
131 /** Gets this text's image.
132 * @return This text's image.
133 */
134 JImage& Image() {return text;}
135
136 /** Sets the text speed. The value varies from 1 (slow) to 10 (fast).
137 * @param speed New value for speed.
138 */
139 static void Speed(s32 speed) {textSpeed = speed;}
140
141 /** Gets the text speed. The value varies from 1 (slow) to 10 (fast).
142 * @return speed New value for speed.
143 */
144 static s32 Speed() {return textSpeed;}
145
146 /** Prepares the text to be displayed.
147 */
148 void Reset();
149
150 /** Skips the text.
151 */
152 void Skip() {timer.Start(1);}
153
154 /** Frees resources.
155 */
156 void Destroy();
157
158 /** Destroys the object.
159 */
160 virtual ~HCText() {Destroy();}
161 };
162
163 #endif // _HCTEXT_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Theme for Holotz's castle. Loads several resources as floors
23 * breaks, ladders and bars.
24 * @file HCTheme.cpp
25 * @author Juan Carlos Seijo Pérez
26 * @date 01/06/2004
27 * @version 0.0.1 - 01/06/2004 - First version.
28 */
29
30 #include <HCTheme.h>
31
32 #ifndef HC_DATA_DIR
33 #define HC_DATA_DIR "res/"
34 #endif
35
36 HCTheme::HCTheme() : imgFloor(0), numFloors(0), imgContFloor(0), numContFloors(0), sprBreak(0), numBreaks(0),
37 sprObject(0), numObjects(0), imgBar(0), numBars(0), imgLadder(0), numLadders(0), imgRope(0),
38 numRopes(0), sprMain(0), numMains(0), sprGuest(0), numGuests(0), sprBall(0), numBalls(0),
39 sprRandom(0), numRandoms(0), sprStatic(0), numStatics(0), sprMaker(0), numMakers(0),
40 sprChaser(0), numChasers(0), imgDialog(0), numDialogs(0), imgNarrative(0), numNarratives(0)
41
42 {
43 memset(name, 0, sizeof(name));
44 }
45
46 s32 HCTheme::CountDirs()
47 {
48 char str[256];
49 s32 num = 0;
50 bool cont = true;
51
52 char cwd[2048];
53 getcwd(cwd, 2048);
54
55 do
56 {
57 sprintf(str, "%d", num + 1);
58 if (JFile::Exists(str))
59 {
60 ++num;
61 }
62 else
63 {
64 cont = false;
65 }
66 } while (cont);
67
68 return num;
69 }
70
71 bool HCTheme::LoadFloors()
72 {
73 if (0 != chdir("floor"))
74 {
75 return false;
76 }
77
78 numFloors = CountDirs();
79 if (0 == numFloors)
80 {
81 return false;
82 }
83
84 char strDir[5];
85 memset(strDir, 0, sizeof(strDir));
86 s32 i = 1;
87 bool ret = true;
88
89 // Creates the array
90 imgFloor = new JImage[numFloors];
91
92 for (i = 1; ret && i <= numFloors; ++i)
93 {
94 sprintf(strDir, "%d", i);
95
96 if (0 == chdir(strDir))
97 {
98 if (!imgFloor[i-1].Load("floor.tga"))
99 {
100 fprintf(stderr, "HCTheme: Couldn't load floor.\n");
101
102 ret = false;
103 }
104
105 chdir("..");
106 }
107 }
108
109 chdir("..");
110
111 return ret;
112 }
113
114 bool HCTheme::LoadContFloors()
115 {
116 if (0 != chdir("contfloor"))
117 {
118 return false;
119 }
120
121 numContFloors = CountDirs();
122 if (0 == numContFloors)
123 {
124 return false;
125 }
126
127 char strDir[5];
128 memset(strDir, 0, sizeof(strDir));
129 s32 i = 1;
130 bool ret = true;
131
132 // Creates the array
133 imgContFloor = new JImage* [numContFloors];
134
135 for (s32 c = 0; c < numContFloors; ++c)
136 {
137 imgContFloor[c] = new JImage[HCFDT_COUNT];
138 }
139
140 for (i = 1; ret && i <= numContFloors; ++i)
141 {
142 sprintf(strDir, "%d", i);
143
144 if (0 == chdir(strDir))
145 {
146 // Load floor resources
147 if (!imgContFloor[i-1][HCFDT_C].Load("c.tga") ||
148 !imgContFloor[i-1][HCFDT_C1].Load("c1.tga") ||
149 !imgContFloor[i-1][HCFDT_C1DL].Load("cdl.tga") ||
150 !imgContFloor[i-1][HCFDT_C3].Load("c3.tga") ||
151 !imgContFloor[i-1][HCFDT_C3DR].Load("cdr.tga") ||
152 !imgContFloor[i-1][HCFDT_C7].Load("c7.tga") ||
153 !imgContFloor[i-1][HCFDT_C7UL].Load("cul.tga") ||
154 !imgContFloor[i-1][HCFDT_C9].Load("c9.tga") ||
155 !imgContFloor[i-1][HCFDT_C9UR].Load("cur.tga") ||
156 !imgContFloor[i-1][HCFDT_CU].Load("cu.tga") ||
157 !imgContFloor[i-1][HCFDT_CD].Load("cd.tga") ||
158 !imgContFloor[i-1][HCFDT_CL].Load("cl.tga") ||
159 !imgContFloor[i-1][HCFDT_CR].Load("cr.tga") ||
160 !imgContFloor[i-1][HCFDT_S2].Load("s2.tga") ||
161 !imgContFloor[i-1][HCFDT_S4].Load("s4.tga") ||
162 !imgContFloor[i-1][HCFDT_S6].Load("s6.tga") ||
163 !imgContFloor[i-1][HCFDT_S8].Load("s8.tga") ||
164 !imgContFloor[i-1][HCFDT_SH].Load("sh.tga") ||
165 !imgContFloor[i-1][HCFDT_SV].Load("sv.tga") ||
166 !imgContFloor[i-1][HCFDT_I].Load("i.tga"))
167 {
168 fprintf(stderr, "HCTheme: Couldn't load continuous floor.\n");
169 ret = false;
170 }
171
172 chdir("..");
173 }
174 else
175 {
176 fprintf(stderr, "HCTheme: Couldn't load continuous floor.\n");
177 }
178 }
179
180 chdir("..");
181
182 return ret;
183 }
184
185 bool HCTheme::LoadBreaks()
186 {
187 if (0 != chdir("break"))
188 {
189 return false;
190 }
191
192 numBreaks = CountDirs();
193 if (0 == numBreaks)
194 {
195 return false;
196 }
197
198 JRW f;
199 char strDir[5];
200 memset(strDir, 0, sizeof(strDir));
201 s32 i = 1;
202 bool ret = true;
203
204 // Creates the array
205 sprBreak = new JImageSprite*[numBreaks];
206
207 for (int c = 0; c < numBreaks; ++c)
208 {
209 sprBreak[c] = new JImageSprite[HCBDT_COUNT];
210 }
211
212 for (i = 1; ret && i <= numBreaks; ++i)
213 {
214 sprintf(strDir, "%d", i);
215
216 if (0 == chdir(strDir))
217 {
218 if (!f.Create("normal.spr","rb") || (0 != sprBreak[i-1][HCBDT_NORMAL].Load(f)) ||
219 !f.Create("breaking.spr","rb") || (0 != sprBreak[i-1][HCBDT_BREAKING].Load(f)) ||
220 !f.Create("broken.spr","rb") || (0 != sprBreak[i-1][HCBDT_BROKEN].Load(f)))
221 {
222 fprintf(stderr, "HCTheme: Couldn't load break.\n");
223 ret = false;
224 }
225
226 chdir("..");
227 }
228 }
229
230 chdir("..");
231
232 return ret;
233 }
234
235 bool HCTheme::LoadBars()
236 {
237 if (0 != chdir("bar"))
238 {
239 return false;
240 }
241
242 numBars = CountDirs();
243 if (0 == numBars)
244 {
245 return false;
246 }
247
248 char strDir[5];
249 memset(strDir, 0, sizeof(strDir));
250 s32 i = 1;
251 bool ret = true;
252
253 // Creates the array
254 imgBar = new JImage[numBars];
255
256 for (i = 1; ret && i <= numBars; ++i)
257 {
258 sprintf(strDir, "%d", i);
259
260 if (0 == chdir(strDir))
261 {
262 if (!imgBar[i-1].Load("bar.tga"))
263 {
264 fprintf(stderr, "HCTheme: Couldn't load bar.\n");
265 ret = false;
266 }
267
268 chdir("..");
269 }
270 }
271
272 chdir("..");
273
274 return ret;
275 }
276
277 bool HCTheme::LoadLadders()
278 {
279 if (0 != chdir("ladder"))
280 {
281 return false;
282 }
283
284 numLadders = CountDirs();
285 if (0 == numLadders)
286 {
287 return false;
288 }
289
290 char strDir[5];
291 memset(strDir, 0, sizeof(strDir));
292 s32 i = 1;
293 bool ret = true;
294
295 // Creates the array
296 imgLadder = new JImage[numLadders];
297
298 for (i = 1; ret && i <= numLadders; ++i)
299 {
300 sprintf(strDir, "%d", i);
301
302 if (0 == chdir(strDir))
303 {
304 if (!imgLadder[i-1].Load("ladder.tga"))
305 {
306 fprintf(stderr, "HCTheme: Couldn't load ladder.\n");
307 ret = false;
308 }
309
310 chdir("..");
311 }
312 }
313
314 chdir("..");
315
316 return ret;
317 }
318
319 bool HCTheme::LoadDecos()
320 {
321 /**< @todo: load several decos */
322
323 return true;
324 }
325
326 bool HCTheme::LoadObjects()
327 {
328 if (0 != chdir("object"))
329 {
330 return false;
331 }
332
333 numObjects = CountDirs();
334 if (0 == numObjects)
335 {
336 return false;
337 }
338
339 JRW f;
340 char strDir[5];
341 memset(strDir, 0, sizeof(strDir));
342 s32 i = 1;
343 bool ret = true;
344
345 // Creates the array
346 sprObject = new JImageSprite*[numObjects];
347
348 for (int c = 0; c < numObjects; ++c)
349 {
350 sprObject[c] = new JImageSprite[HCODT_COUNT];
351 }
352
353 for (i = 1; ret && i <= numObjects; ++i)
354 {
355 sprintf(strDir, "%d", i);
356
357 if (0 == chdir(strDir))
358 {
359 if (!f.Create("normal.spr","rb") || 0 != sprObject[i-1][HCODT_NORMAL].Load(f) ||
360 !f.Create("acquired.spr","rb") || 0 != sprObject[i-1][HCODT_ACQUIRED].Load(f))
361 {
362 fprintf(stderr, "HCTheme: Couldn't load object.\n");
363 ret = false;
364 }
365
366 chdir("..");
367 }
368 }
369
370 chdir("..");
371
372 return ret;
373 }
374
375 bool HCTheme::LoadRopes()
376 {
377 if (0 != chdir("rope"))
378 {
379 return false;
380 }
381
382 numRopes = CountDirs();
383 if (0 == numRopes)
384 {
385 return false;
386 }
387
388 char strDir[5];
389 memset(strDir, 0, sizeof(strDir));
390 s32 i = 1;
391 bool ret = true;
392
393 // Creates the array
394 imgRope = new JImage*[numRopes];
395
396 for (int c = 0; c < numRopes; ++c)
397 {
398 imgRope[c] = new JImage[HCRDT_COUNT];
399 }
400
401 for (i = 1; ret && i <= numRopes; ++i)
402 {
403 sprintf(strDir, "%d", i);
404
405 if (0 == chdir(strDir))
406 {
407 if (!imgRope[i-1][HCRDT_EDGE].Load("edge.tga") ||
408 !imgRope[i-1][HCRDT_TOP].Load("top.tga") ||
409 !imgRope[i-1][HCRDT_MIDDLE].Load("middle.tga"))
410 {
411 fprintf(stderr, "HCTheme: Couldn't load rope.\n");
412 ret = false;
413 }
414
415 chdir("..");
416 }
417 }
418
419 chdir("..");
420
421 return ret;
422 }
423
424 bool HCTheme::LoadChar(const char *directory, JImageSprite ** &sprArr, s32 &num)
425 {
426 if (0 != chdir(directory))
427 {
428 return false;
429 }
430
431 const char *files[] = {"stop.spr",
432 "right.spr",
433 "left.spr",
434 "up.spr",
435 "down.spr",
436 "slide.spr",
437 "jump.spr",
438 "jumpleft.spr",
439 "jumpright.spr",
440 "fall.spr",
441 "dead.spr",
442 "hang.spr"};
443
444 JRW f;
445 num = CountDirs();
446
447 if (0 == num)
448 {
449 return false;
450 }
451
452 char strDir[5];
453 memset(strDir, 0, sizeof(strDir));
454 s32 i = 1;
455 bool ret = true;
456
457 // Creates the array
458 sprArr = new JImageSprite*[num];
459
460 for (s32 c = 0; c < num; ++c)
461 {
462 sprArr[c] = new JImageSprite[HCCDT_COUNT];
463 }
464
465 // For each numbered dir loads each character's state
466 for (s32 k = 1; ret && k <= num; ++k)
467 {
468 sprintf(strDir, "%d", k);
469
470 if (0 == chdir(strDir))
471 {
472 for (i = 0; i < HCCDT_COUNT; ++i)
473 {
474 if (JFile::Exists(files[i]))
475 {
476 if (f.Create(files[i],"rb"))
477 {
478 if (0 != sprArr[k - 1][i].Load(f))
479 {
480 fprintf(stderr, "Error loading character sprite file %s\n", files[i]);
481 return false;
482 }
483 }
484 } // if res/char exists
485 else
486 {
487 fprintf(stderr, "File %s does not exist.\n", files[i]);
488 }
489 } // for every state
490
491 chdir("..");
492 } // if chdir()
493 }
494
495 chdir("../..");
496
497 return true;
498 }
499
500 bool HCTheme::LoadCharacters()
501 {
502 if (LoadChar("char/main", sprMain, numMains) &&
503 LoadChar("char/ball", sprBall, numBalls) &&
504 LoadChar("char/random", sprRandom, numRandoms) &&
505 LoadChar("char/static", sprStatic, numStatics) &&
506 LoadChar("char/maker", sprMaker, numMakers) &&
507 LoadChar("char/chaser", sprChaser, numChasers) &&
508 LoadChar("char/guest", sprGuest, numGuests))
509 {
510 return true;
511 }
512
513 return false;
514 }
515
516 bool HCTheme::LoadDialogs()
517 {
518 if (0 != chdir("dialog"))
519 {
520 return false;
521 }
522
523 numDialogs = CountDirs();
524 if (0 == numDialogs)
525 {
526 return false;
527 }
528
529 char strDir[5];
530 memset(strDir, 0, sizeof(strDir));
531 s32 i = 1;
532 bool ret = true;
533
534 // Creates the array
535 imgDialog = new JImage* [numDialogs];
536
537 for (s32 k = 0; k < numDialogs; ++k)
538 {
539 imgDialog[k] = new JImage[11];
540 }
541
542 for (i = 1; ret && i <= numDialogs; ++i)
543 {
544 sprintf(strDir, "%d", i);
545
546 if (0 == chdir(strDir))
547 {
548 if (!imgDialog[i-1][HCTDT_1].Load("1.tga") ||
549 !imgDialog[i-1][HCTDT_2].Load("2.tga") ||
550 !imgDialog[i-1][HCTDT_3].Load("3.tga") ||
551 !imgDialog[i-1][HCTDT_4].Load("4.tga") ||
552 !imgDialog[i-1][HCTDT_5].Load("5.tga") ||
553 !imgDialog[i-1][HCTDT_6].Load("6.tga") ||
554 !imgDialog[i-1][HCTDT_7].Load("7.tga") ||
555 !imgDialog[i-1][HCTDT_8].Load("8.tga") ||
556 !imgDialog[i-1][HCTDT_9].Load("9.tga") ||
557 !imgDialog[i-1][HCTDT_LEFT].Load("left.tga") ||
558 !imgDialog[i-1][HCTDT_RIGHT].Load("right.tga"))
559 {
560 char strcwd[256];
561 getcwd(strcwd, 256);
562 perror("error");
563 fprintf(stderr, "HCTheme: Couldn't load dialog. %s en dir %s\n", SDL_GetError(), strcwd);
564 ret = false;
565 }
566
567 chdir("..");
568 }
569 }
570
571 chdir("..");
572
573 return ret;
574 }
575
576 bool HCTheme::LoadNarratives()
577 {
578 if (0 != chdir("narrative"))
579 {
580 return false;
581 }
582
583 numNarratives = CountDirs();
584 if (0 == numNarratives)
585 {
586 return false;
587 }
588
589 char strDir[5];
590 memset(strDir, 0, sizeof(strDir));
591 s32 i = 1;
592 bool ret = true;
593
594 // Creates the array
595 imgNarrative = new JImage *[numNarratives];
596
597 for (s32 k = 0; k < numNarratives; ++k)
598 {
599 imgNarrative[k] = new JImage[9];
600 }
601
602 for (i = 1; ret && i <= numNarratives; ++i)
603 {
604 sprintf(strDir, "%d", i);
605
606 if (0 == chdir(strDir))
607 {
608 if (!imgNarrative[i-1][HCTDT_1].Load("1.tga") ||
609 !imgNarrative[i-1][HCTDT_2].Load("2.tga") ||
610 !imgNarrative[i-1][HCTDT_3].Load("3.tga") ||
611 !imgNarrative[i-1][HCTDT_4].Load("4.tga") ||
612 !imgNarrative[i-1][HCTDT_5].Load("5.tga") ||
613 !imgNarrative[i-1][HCTDT_6].Load("6.tga") ||
614 !imgNarrative[i-1][HCTDT_7].Load("7.tga") ||
615 !imgNarrative[i-1][HCTDT_8].Load("8.tga") ||
616 !imgNarrative[i-1][HCTDT_9].Load("9.tga"))
617 {
618 fprintf(stderr, "HCTheme: Couldn't load narrative.\n");
619 ret = false;
620 }
621
622 chdir("..");
623 }
624 }
625
626 chdir("..");
627
628 return ret;
629 }
630
631 bool HCTheme::Load(const char *themeName)
632 {
633 Destroy();
634
635 char themeDir[PATH_MAX];
636 char curDir[PATH_MAX];
637 getcwd(curDir, PATH_MAX);
638
639 // Checks for the theme in any of:
640 // - installation directory
641 // - current directory
642 // - home directory
643 strncpy(name, themeName, sizeof(name));
644 snprintf(themeDir, sizeof(themeDir), "theme/%s", name);
645
646 if (!HCUtil::FindFile(themeDir))
647 {
648 fprintf(stderr, "Couldn't find the theme %s\n", themeDir);
649 return false;
650 }
651
652 if (0 != chdir(HCUtil::File()))
653 {
654 fprintf(stderr, "Couldn't find the theme %s\n", HCUtil::File());
655 }
656
657 if (!LoadFloors() ||
658 !LoadContFloors() ||
659 !LoadDecos() ||
660 !LoadBars() ||
661 !LoadBreaks() ||
662 !LoadLadders() ||
663 !LoadObjects() ||
664 !LoadRopes() ||
665 !LoadCharacters() ||
666 !LoadDialogs() ||
667 !LoadNarratives())
668 {
669 fprintf(stderr, "HCTheme: Couldn't load resources.\n");
670
671 chdir(curDir);
672
673 return false;
674 }
675
676 chdir(curDir);
677
678 return true;
679 }
680
681 void HCTheme::Destroy()
682 {
683 JDELETE_ARRAY(imgFloor);
684 JDELETE_ARRAY_ARRAY(imgContFloor, numContFloors);
685 JDELETE_ARRAY_ARRAY(sprBreak, numBreaks);
686 JDELETE_ARRAY(imgBar);
687 JDELETE_ARRAY(imgLadder);
688 JDELETE_ARRAY_ARRAY(sprObject, numObjects);
689 JDELETE_ARRAY_ARRAY(imgRope, numRopes);
690 JDELETE_ARRAY_ARRAY(sprMain, numMains);
691 JDELETE_ARRAY_ARRAY(sprBall, numBalls);
692 JDELETE_ARRAY_ARRAY(sprRandom, numRandoms);
693 JDELETE_ARRAY_ARRAY(sprStatic, numStatics);
694 JDELETE_ARRAY_ARRAY(sprMaker, numMakers);
695 JDELETE_ARRAY_ARRAY(sprChaser, numChasers);
696 JDELETE_ARRAY_ARRAY(sprGuest, numGuests);
697 JDELETE_ARRAY_ARRAY(imgDialog, numDialogs);
698 JDELETE_ARRAY_ARRAY(imgNarrative, numNarratives);
699 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Theme for Holotz's castle. Loads several resources as floors
23 * breaks, ladders, bars and characters.
24 * @file HCTheme.h
25 * @author Juan Carlos Seijo Pérez
26 * @date 01/06/2004
27 * @version 0.0.1 - 01/06/2004 - First version.
28 */
29
30 #ifndef _HCTHEME_INCLUDED
31 #define _HCTHEME_INCLUDED
32
33 #include <unistd.h>
34 #include <JLib/Util/JFile.h>
35 #include <JLib/Graphics/JImage.h>
36 #include <JLib/Graphics/JImageSprite.h>
37 #include <HCUtil.h>
38
39 /** Type of floor image. Used to build dinamically the map.
40 */
41 enum HCFloorDrawType
42 {
43 HCFDT_C = 0, /**< Corner with 3 neighbours. */
44 HCFDT_C1, /**< DL corner. */
45 HCFDT_C1DL, /**< DL corner with DL neighbours. */
46 HCFDT_C3, /**< DR corner. */
47 HCFDT_C3DR, /**< DR corner with DL neighbours. */
48 HCFDT_C7, /**< UL corner. */
49 HCFDT_C7UL, /**< UL corner with UR neighbours. */
50 HCFDT_C9, /**< UR corner. */
51 HCFDT_C9UR, /**< UR corner with UR neighbours. */
52 HCFDT_CU, /**< C7 or C9 with U neighbour. */
53 HCFDT_CD, /**< C1 or C3 with D neighbour. */
54 HCFDT_CL, /**< C1 or C7 with L neighbour. */
55 HCFDT_CR, /**< C3 or C9 with R neighbour. */
56 HCFDT_S2, /**< D side. */
57 HCFDT_S4, /**< L side. */
58 HCFDT_S6, /**< R side. */
59 HCFDT_S8, /**< U side. */
60 HCFDT_SH, /**< U or D sides with U or D neighbour, respectively*/
61 HCFDT_SV, /**< L or R sides with L or R neighbour, respectively*/
62 HCFDT_I, /**< Inner part of the cell. */
63 HCFDT_COUNT, /**< Number of floor part types. */
64 };
65
66 /** Break sprite types.
67 */
68 enum HCBreakDrawType
69 {
70 HCBDT_NORMAL = 0,
71 HCBDT_BREAKING,
72 HCBDT_BROKEN,
73 HCBDT_COUNT,
74 };
75
76 /** Object sprite types.
77 */
78 enum HCObjectDrawType
79 {
80 HCODT_NORMAL = 0,
81 HCODT_ACQUIRED,
82 HCODT_COUNT,
83 };
84
85 /** Rope image types.
86 */
87 enum HCRopeDrawType
88 {
89 HCRDT_TOP = 0,
90 HCRDT_MIDDLE,
91 HCRDT_EDGE,
92 HCRDT_COUNT,
93 };
94
95 /** Character sprite types. Must be the same as
96 * HCCharacterState but is placed here to avoid circular references between
97 * the files.
98 */
99 enum HCCharacterDrawType
100 {
101 HCCDT_STOP = 0, /**< Stopped state. */
102 HCCDT_RIGHT, /**< Walk-right state. */
103 HCCDT_LEFT, /**< Walk-left state. */
104 HCCDT_UP, /**< Up state. */
105 HCCDT_DOWN, /**< Down state. */
106 HCCDT_SLIDE, /**< Slide state. */
107 HCCDT_JUMP, /**< Jump left state. */
108 HCCDT_JUMPLEFT, /**< Jump left state. */
109 HCCDT_JUMPRIGHT, /**< Jump right state. */
110 HCCDT_FALL, /**< Fall state. */
111 HCCDT_DIE, /**< Die state. */
112 HCCDT_HANG, /**< Hang state. */
113 HCCDT_COUNT, /**< State count. */
114 };
115
116 /** Text image types.
117 */
118 enum HCTextDrawType
119 {
120 HCTDT_1 = 0, /**< Lower left corner */
121 HCTDT_2, /**< Lower side */
122 HCTDT_3, /**< Lower right corner */
123 HCTDT_4, /**< Left side */
124 HCTDT_5, /**< Center */
125 HCTDT_6, /**< Right corner */
126 HCTDT_7, /**< Upper left corner */
127 HCTDT_8, /**< Up side */
128 HCTDT_9, /**< Upper right corner */
129 HCTDT_LEFT, /**< Lower left peak (only in dialogs) */
130 HCTDT_RIGHT, /**< Lower right peak (only in dialogs) */
131 };
132
133 /** Theme for Holotz's Castle.
134 */
135 class HCTheme
136 {
137 protected:
138 JImage *imgFloor; /**< Floor images. */
139 s32 numFloors; /**< Number of Floor variants. */
140 JImage **imgContFloor; /**< Continuous floor images. */
141 s32 numContFloors; /**< Number of Continuous Floor variants. */
142 JImageSprite **sprBreak; /**< Break sprites. */
143 s32 numBreaks; /**< Number of Break variants. */
144 JImageSprite **sprObject; /**< Object sprites. */
145 s32 numObjects; /**< Number of Object variants. */
146 JImage *imgBar; /**< Bar images. */
147 s32 numBars; /**< Number of Bar variants. */
148 JImage *imgLadder; /**< Ladder images. */
149 s32 numLadders; /**< Number of Ladder variants. */
150 JImage **imgRope; /**< Rope images. */
151 s32 numRopes; /**< Number of Rope variants. */
152 JImageSprite **sprMain; /**< Main character sprites. */
153 s32 numMains; /**< Number of Main character variants. */
154 JImageSprite **sprGuest; /**< Guest sprites. */
155 s32 numGuests; /**< Number of guest variants. */
156 JImageSprite **sprBall; /**< Ball enemy sprites. */
157 s32 numBalls; /**< Number of Ball variants. */
158 JImageSprite **sprRandom; /**< Random enemy sprites. */
159 s32 numRandoms; /**< Number of Random variants. */
160 JImageSprite **sprStatic; /**< Static enemy sprites. */
161 s32 numStatics; /**< Number of Static variants. */
162 JImageSprite **sprMaker; /**< Maker enemy sprites. */
163 s32 numMakers; /**< Number of Maker variants. */
164 JImageSprite **sprChaser; /**< Chaser enemy sprites. */
165 s32 numChasers; /**< Number of Chaser variants. */
166 JImage **imgDialog; /**< Dialog images. */
167 s32 numDialogs; /**< Number of Dialog variants. */
168 JImage **imgNarrative; /**< Narrative images. */
169 s32 numNarratives; /**< Number of Narrative variants. */
170
171 char name[256]; /**< Theme's name. */
172
173 /** Count the number of correlative dirs starting from 1 in the cwd.
174 * @return Number of correlative dirs starting from 1 in the cwd.
175 */
176 s32 CountDirs();
177
178 /** Load floor resources.
179 * @return <b>true</b> if succeeded, <b>false</b> if not.
180 */
181 bool LoadFloors();
182
183 /** Load continuous floor resources.
184 * @return <b>true</b> if succeeded, <b>false</b> if not.
185 */
186 bool LoadContFloors();
187
188 /** Load break resources.
189 * @return <b>true</b> if succeeded, <b>false</b> if not.
190 */
191 bool LoadBreaks();
192
193 /** Load bar resources.
194 * @return <b>true</b> if succeeded, <b>false</b> if not.
195 */
196 bool LoadBars();
197
198 /** Load ladder resources.
199 * @return <b>true</b> if succeeded, <b>false</b> if not.
200 */
201 bool LoadLadders();
202
203 /** Load decorative resources.
204 * @return <b>true</b> if succeeded, <b>false</b> if not.
205 */
206 bool LoadDecos();
207
208 /** Load object resources.
209 * @return <b>true</b> if succeeded, <b>false</b> if not.
210 */
211 bool LoadObjects();
212
213 /** Load rope resources.
214 * @return <b>true</b> if succeeded, <b>false</b> if not.
215 */
216 bool LoadRopes();
217
218 /** Load main character's resources.
219 * @return <b>true</b> if succeeded, <b>false</b> if not.
220 */
221 bool LoadChar(const char *directory, JImageSprite ** &sprArr, s32 &num);
222
223 /** Load character resources.
224 * @return <b>true</b> if succeeded, <b>false</b> if not.
225 */
226 bool LoadCharacters();
227
228 /** Load dialog resources.
229 * @return <b>true</b> if succeeded, <b>false</b> if not.
230 */
231 bool LoadDialogs();
232
233 /** Load narrative resources.
234 * @return <b>true</b> if succeeded, <b>false</b> if not.
235 */
236 bool LoadNarratives();
237
238 public:
239 /** Creates an empty theme. Load() must be called in order to use it.
240 */
241 HCTheme();
242
243 /** Returns the Floor image.
244 * @param index Element to retrieve.
245 * @return &The Floor image.
246 */
247 JImage & Floor(s32 index) {return imgFloor[index];}
248
249 /** Returns the continuous Floor images.
250 * @param index Element to retrieve.
251 * @return &The continuous Floor images.
252 */
253 JImage * ContFloor(s32 index) {return imgContFloor[index];}
254
255 /** Returns the Break sprites.
256 * @param index Element to retrieve.
257 * @return &The Break sprites.
258 */
259 JImageSprite * Break(s32 index) {return sprBreak[index];}
260
261 /** Returns the Object sprites. index 0 is the key.
262 * @param index Element to retrieve.
263 * @return &The Object sprites.
264 */
265 JImageSprite * Object(s32 index) {return sprObject[index];}
266
267 /** Returns the Bar image.
268 * @param index Element to retrieve.
269 * @return &The Bar image.
270 */
271 JImage & Bar(s32 index) {return imgBar[index];}
272
273 /** Returns the Ladder image.
274 * @param index Element to retrieve.
275 * @return &The Ladder image.
276 */
277 JImage & Ladder(s32 index) {return imgLadder[index];}
278
279 /** Returns the Rope images.
280 * @param index Element to retrieve.
281 * @return &The Rope images.
282 */
283 JImage * Rope(s32 index) {return imgRope[index];}
284
285 /** Returns the Main character sprites.
286 * @param index Element to retrieve.
287 * @return The Main character sprites.
288 */
289 JImageSprite * MainChar(s32 index) {return sprMain[index];}
290
291 /** Returns the Guest sprites.
292 * @param index Element to retrieve.
293 * @return The Guest sprites.
294 */
295 JImageSprite * Guest(s32 index) {return sprGuest[index];}
296
297 /** Returns the Ball enemy sprites.
298 * @param index Element to retrieve.
299 * @return The Ball enemy sprites.
300 */
301 JImageSprite * Ball(s32 index) {return sprBall[index];}
302
303 /** Returns the Random enemy sprites.
304 * @param index Element to retrieve.
305 * @return The Random enemy sprites.
306 */
307 JImageSprite * Random(s32 index) {return sprRandom[index];}
308
309 /** Returns the Static enemy sprites.
310 * @param index Element to retrieve.
311 * @return The Static enemy sprites.
312 */
313 JImageSprite * Static(s32 index) {return sprStatic[index];}
314
315 /** Returns the Maker enemy sprites.
316 * @param index Element to retrieve.
317 * @return The Maker enemy sprites.
318 */
319 JImageSprite * Maker(s32 index) {return sprMaker[index];}
320
321 /** Returns the Chaser enemy sprites.
322 * @param index Element to retrieve.
323 * @return The Chaser enemy sprites.
324 */
325 JImageSprite * Chaser(s32 index) {return sprChaser[index];}
326
327 /** Returns the Dialog image.
328 * @param index Element to retrieve.
329 * @return &The Dialog image.
330 */
331 JImage * Dialog(s32 index) {return imgDialog[index];}
332
333 /** Returns the Narrative image.
334 * @param index Element to retrieve.
335 * @return &The Narrative image.
336 */
337 JImage * Narrative(s32 index) {return imgNarrative[index];}
338
339 /** Loads the theme. The name of the theme is the name of the directory
340 * containing it. The structure is:
341 * <pre>
342 * themeName1
343 * `- 1
344 * `- contfloor - Floor cell parts (corner, sides, interiors)
345 * ` 1
346 * ` [2]
347 * ` ...
348 * `- break - Break cell sprites
349 * ` 1
350 * ` [2]
351 * ` ...
352 * `- ladder - Ladder cell image
353 * ` 1
354 * ` [2]
355 * ` ...
356 * `- bar - Bar cell image
357 * ` 1
358 * ` [2]
359 * ` ...
360 * `- object - Objects (keys, powerups, etc.)
361 * ` 1
362 * ` [2]
363 * ` ...
364 * `- deco - Decorative images/effects
365 * ` 1
366 * ` [2]
367 * ` ...
368 * `- rope - Rope images (edge, top, middle)
369 * ` 1
370 * ` [2]
371 * ` ...
372 * `- char - Sprites for characters
373 * `- main - Sprites of main character
374 * ` 1
375 * ` [2]
376 * ` ...
377 * `- ball - Sprites of ball-like enemies
378 * ` 1
379 * ` [2]
380 * ` ...
381 * `- random - Sprites of random movement enemies
382 * ` 1
383 * ` [2]
384 * ` ...
385 * `- static - Sprites of static enemies
386 * ` 1
387 * ` [2]
388 * ` ...
389 * `- maker - Sprites of maker enemies
390 * ` 1
391 * ` [2]
392 * ` ...
393 * `- chaser - Sprites of chaser enemies
394 * ` 1
395 * ` [2]
396 * ` ...
397 * `- char1 - Sprites of spare character 1
398 * ` 1
399 * ` [2]
400 * ` ...
401 * `- char2 - Sprites of spare character 2
402 * ` 1
403 * ` [2]
404 * ` ...
405 * `- char3 - Sprites of spare character 3
406 * ` 1
407 * ` [2]
408 * ` ...
409 * `- char4 - Sprites of spare character 4
410 * ` 1
411 * ` [2]
412 * ` ...
413 * `- char5 - Sprites of spare character 5
414 * ` 1
415 * ` [2]
416 * ` ...
417 * `- [themeName2]
418 * `- ...
419 *
420 * </pre>
421 * @param themeName This theme's name.
422 * @return <b>true</b> if succeeded, <b>false</b> if not.
423 */
424 bool Load(const char *themeName);
425
426 /** Returns the theme name (directory containing it).
427 * @return Theme name (directory containing it).
428 */
429 const char * Name() {return name;}
430
431 /** Destroys the theme. Frees resources.
432 */
433 void Destroy();
434
435 /** Number of Floor variants.
436 * @return The requested quantity.
437 */
438 s32 NumFloors() {return numFloors;}
439
440 /** Number of Continuous Floor variants.
441 * @return The requested quantity.
442 */
443 s32 NumContFloors() {return numContFloors;}
444
445 /** Number of Break variants.
446 * @return The requested quantity.
447 */
448 s32 NumBreaks() {return numBreaks;}
449
450 /** Number of Object variants.
451 * @return The requested quantity.
452 */
453 s32 NumObjects() {return numObjects;}
454
455 /** Number of Bar variants.
456 * @return The requested quantity.
457 */
458 s32 NumBars() {return numBars;}
459
460 /** Number of Ladder variants.
461 * @return The requested quantity.
462 */
463 s32 NumLadders() {return numLadders;}
464
465 /** Number of Rope variants.
466 * @return The requested quantity.
467 */
468 s32 NumRopes() {return numRopes;}
469
470 /** Number of MainChar variants.
471 * @return Number of MainChar variants.
472 */
473 s32 NumMainChars() {return numMains;}
474
475 /** Number of Guest variants.
476 * @return number of Guest variants.
477 */
478 s32 NumGuests() {return numGuests;}
479
480 /** Number of Ball variants.
481 * @return number of Ball variants.
482 */
483 s32 NumBalls() {return numBalls;}
484
485 /** Number of Random variants.
486 * @return number of Random variants.
487 */
488 s32 NumRandoms() {return numRandoms;}
489
490 /** Number of Static variants.
491 * @return number of Static variants.
492 */
493 s32 NumStatics() {return numStatics;}
494
495 /** Number of Maker variants.
496 * @return number of Maker variants.
497 */
498 s32 NumMakers() {return numMakers;}
499
500 /** Number of Chaser variants.
501 * @return number of Chaser variants.
502 */
503 s32 NumChasers() {return numChasers;}
504
505 /** Number of Dialog variants.
506 * @return number of Dialog variants.
507 */
508 s32 NumDialogs() {return numDialogs;}
509
510 /** Number of Narrative variants.
511 * @return number of Narrative variants.
512 */
513 s32 NumNarratives() {return numNarratives;}
514
515 /** Destroys the theme. Frees resources. Allows scalar destruction.
516 */
517 virtual ~HCTheme() {Destroy();}
518 };
519
520 #endif // _HCTHEME_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Level timer for holotz's castle.
23 * @file HCTimer.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 04/10/2004
26 * @version 0.0.1 - 4/10/2004 - First version.
27 */
28
29 #include <HCTimer.h>
30
31 bool HCTimer::Build(u16 t, u8 r, u8 g, u8 b)
32 {
33 char str[32];
34 sprintf(str, "%d", t);
35
36 SDL_Color c = {r, g, b, 0};
37
38 Destroy();
39 if ((img = font->RenderTextBlended(str, c)))
40 {
41 return true;
42 }
43
44 return false;
45 }
46
47 bool HCTimer::Init(u16 t, JFont *f)
48 {
49 if (!f)
50 {
51 fprintf(stderr, "HCTimer: No hay fuente\n");
52 return false;
53 }
54
55 cycleTime = 1000;
56 maxTime = t * 1000;
57 font = f;
58
59 return Build(t, 255, 255, 255);
60 }
61
62 void HCTimer::Draw()
63 {
64 img->Draw((s32)pos.x, (s32)pos.y);
65 }
66
67 s32 HCTimer::Update()
68 {
69 s32 t = TimeRemaining();
70
71 if (Changed() > 0)
72 {
73 // Turns red as time goes by
74 u8 r = 255;
75 u8 g = 255 * t/maxTime;
76 u8 b = 255 * t/maxTime;
77
78 if (t < 0)
79 {
80 t = 0;
81 Pause();
82 }
83 else
84 {
85 t /= 1000;
86 }
87
88 Build(t, r, g, b);
89 }
90
91 return t;
92 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Level timer for holotz's castle.
23 * @file HCTimer.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 04/10/2004
26 * @version 0.0.1 - 4/10/2004 - First version.
27 */
28
29 #ifndef _HCTIMER_INCLUDED
30 #define _HCTIMER_INCLUDED
31
32 #include <JLib/Util/JTimer.h>
33 #include <JLib/Graphics/JImage.h>
34 #include <JLib/Graphics/JFont.h>
35
36 /** Tracks the time elapsed within the level and updates the marker.
37 */
38 class HCTimer : public JDrawable, public JTimer
39 {
40 protected:
41 JImage *img; /**< Image to draw the time remaining to. */
42 s32 maxTime; /**< Maximum time. */
43 JFont *font; /**< Font to use. */
44
45 /** Build the given time's image.
46 * @param t Seconds to show.
47 * @return <b>true</b> if succedded, <b>false</b> otherwise.
48 */
49 bool Build(u16 t, u8 r, u8 g, u8 b);
50
51 public:
52 /** Creates an empty timer.
53 */
54 HCTimer() : img(0), maxTime(0), font(0)
55 {}
56
57 /** Initializes the timer.
58 * @param t Seconds to count.
59 * @param f Font to use to render the text.
60 * @return <b>true</b> if succedded, <b>false</b> otherwise.
61 */
62 bool Init(u16 t, JFont *f);
63
64 /** Checks whether the time has elapsed or not.
65 * @return Milliseconds remaining to end (note: <= 0 if finished).
66 */
67 s32 TimeRemaining() {return maxTime - TotalLap();}
68
69 /** Draws the timer.
70 */
71 virtual void Draw();
72
73 /** Updates the timer.
74 * @return 0 if not finished, -1 if so.
75 */
76 virtual s32 Update();
77
78 /** Destroys the associated image.
79 */
80 void Destroy() {JDELETE(img);}
81
82 /** Destroys the object.
83 */
84 virtual ~HCTimer() {Destroy();}
85 };
86
87 #endif // _HCTIMER_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Utility functions for Holotz's Castle.
23 * @file HCUtil.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 05/02/2005
26 * @version 0.0.1 - 05/02/2005 - First version.
27 */
28
29 #include <HCUtil.h>
30
31 const char * HCUtil::curDir = "";
32 const char * HCUtil::installHCDir = HC_DATA_DIR;
33 const char * HCUtil::installHCedDir = HCED_DATA_DIR;
34 char HCUtil::homeDir[4096];
35 char HCUtil::lastFile[4096];
36 const char *HCUtil::lastPath;
37 std::vector<JString> HCUtil::themes;
38 std::vector<JString> HCUtil::stories;
39
40 bool HCUtil::FindFile(const char *filename)
41 {
42 char *str;
43
44 #ifndef _WIN32
45 if (strstr(filename, "holotzcastle") == 0 && 0 != (str = getenv("HOME")))
46 {
47 snprintf(homeDir, sizeof(homeDir), "%s/.holotz-castle/", str);
48 }
49 else
50 {
51 homeDir[0] = 0;
52 }
53
54 lastFile[0] = 0;
55
56
57 if (homeDir[0] != 0)
58 {
59 // Searchs in the home dir
60 snprintf(lastFile, sizeof(lastFile), "%s%s", homeDir, filename);
61
62 if (JFile::Exists(lastFile))
63 {
64 lastPath = homeDir;
65 return true;
66 }
67 }
68 #endif // _WIN32
69
70 // Searchs in the current dir
71 if (JFile::Exists(filename))
72 {
73 strncpy(lastFile, filename, sizeof(lastFile));
74 lastPath = curDir;
75 return true;
76 }
77
78 // Searchs in the HC installation dir
79 snprintf(lastFile, sizeof(lastFile), "%s%s", installHCDir, filename);
80
81 if (JFile::Exists(lastFile))
82 {
83 lastPath = installHCDir;
84 return true;
85 }
86
87 // Searchs in the HCED installation dir
88 snprintf(lastFile, sizeof(lastFile), "%s%s", installHCedDir, filename);
89
90 if (JFile::Exists(lastFile))
91 {
92 lastPath = installHCedDir;
93 return true;
94 }
95
96 lastFile[0] = 0;
97 lastPath = 0;
98
99 return false;
100 }
101
102
103 bool HCUtil::FindThemes(bool onlyEdit)
104 {
105 char *str;
106
107 #ifndef _WIN32
108 if (0 != (str = getenv("HOME")))
109 {
110 snprintf(homeDir, sizeof(homeDir), "%s/.holotz-castle/", str);
111 }
112 else
113 {
114 homeDir[0] = 0;
115 }
116
117 const char *dirs[] = {homeDir, curDir, installHCDir, installHCedDir};
118 #else
119 const char *dirs[] = {0, curDir, installHCDir, installHCedDir};
120 #endif // _WIN32
121
122 #ifndef _WIN32
123 if (onlyEdit)
124 {
125 dirs[2] = dirs[3] = 0;
126 }
127 #endif // _WIN32
128
129 DIR *dp;
130 struct dirent *ep;
131 char themesDir[4096];
132
133 // Starts with a new set
134 themes.clear();
135
136 for (s32 i = 0; i < 4; ++i)
137 {
138 if (dirs[i])
139 {
140 snprintf(themesDir, sizeof(themesDir), "%stheme", dirs[i]);
141 dp = opendir(themesDir);
142
143 if (dp != 0)
144 {
145 while ((ep = readdir(dp)))
146 {
147 if (0 != strcmp(ep->d_name, ".") && 0 != strcmp(ep->d_name, ".."))
148 {
149 u32 j;
150 for (j = 0; j < themes.size(); ++j)
151 {
152 if (themes[j] == ep->d_name)
153 break;
154 }
155
156 if (j == themes.size())
157 {
158 themes.push_back(ep->d_name);
159 }
160 }
161 }
162
163 closedir(dp);
164 }
165 }
166 }
167
168 return themes.size() > 0;
169 }
170
171 bool HCUtil::FindStories(bool onlyEdit)
172 {
173 char *str;
174
175 #ifndef _WIN32
176 if (0 != (str = getenv("HOME")))
177 {
178 snprintf(homeDir, sizeof(homeDir), "%s/.holotz-castle/", str);
179 }
180 else
181 {
182 homeDir[0] = 0;
183 }
184
185 const char *dirs[] = {homeDir, curDir, installHCDir, installHCedDir};
186 #else
187 const char *dirs[] = {0, curDir, installHCDir, installHCedDir};
188 #endif // _WIN32
189
190 #ifndef _WIN32
191 if (onlyEdit)
192 {
193 dirs[2] = dirs[3] = 0;
194 }
195 #endif // _WIN32
196
197 DIR *dp;
198 struct dirent *ep;
199 char storiesDir[4096];
200
201 // Starts with a new set
202 stories.clear();
203
204 for (s32 i = 0; i < 4; ++i)
205 {
206 if (dirs[i])
207 {
208 snprintf(storiesDir, sizeof(storiesDir), "%sstories", dirs[i]);
209 dp = opendir(storiesDir);
210
211 if (dp != 0)
212 {
213 while ((ep = readdir(dp)))
214 {
215 if (0 != strcmp(ep->d_name, ".") && 0 != strcmp(ep->d_name, ".."))
216 {
217 u32 j;
218 for (j = 0; j < stories.size(); ++j)
219 {
220 if (stories[j] == ep->d_name)
221 break;
222 }
223
224 if (j == stories.size())
225 {
226 stories.push_back(ep->d_name);
227 }
228 }
229 }
230
231 closedir(dp);
232 }
233 }
234 }
235
236 return stories.size() > 0;
237 }
238
239 s32 HCUtil::CreateStory(const char *story)
240 {
241 if (FindFile("stories"))
242 {
243 // Directory 'stories' found
244 char name[4096];
245 snprintf(name, sizeof(name), "%s%c%s", lastFile, FILESYS_BAR, story);
246
247 if (!FindFile(name))
248 {
249 // The story does not exist, creates its directory
250 #ifndef _WIN32
251 if (0 != mkdir(name, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
252 #else
253 if (0 != mkdir(name))
254 #endif //_WIN32
255 {
256 // Can't create new dir
257 return 3;
258 }
259 else
260 {
261 // Ok!
262 return 0;
263 }
264 }
265 else
266 {
267 // Story already exists
268 return 1;
269 }
270 }
271 else
272 {
273 // Stories directory not found
274 return 2;
275 }
276 }
277
278 void HCUtil::Destroy()
279 {
280 themes.clear();
281 stories.clear();
282 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Utility functions for Holotz's Castle.
23 * @file HCUtil.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 05/02/2005
26 * @version 0.0.1 - 05/02/2005 - First version.
27 */
28
29 #ifndef _HCUTIL_INCLUDED
30 #define _HCUTIL_INCLUDED
31
32 #ifndef HC_DATA_DIR
33 #define HC_DATA_DIR "res/"
34 #endif
35
36 #ifndef FILESYS_BAR
37 #ifdef _WIN32
38 #define FILESYS_BAR '\\'
39 #else
40 #define FILESYS_BAR '/'
41 #endif // _WIN32
42 #endif // FILESYS_BAR
43
44 #include <sys/types.h>
45 #include <dirent.h>
46 #include <stdlib.h>
47 #include <vector>
48 #include <JLib/Util/JFile.h>
49 #include <JLib/Util/JString.h>
50
51 class HCUtil
52 {
53 static const char *curDir;
54 static const char *installHCDir;
55 static const char *installHCedDir;
56 static char homeDir[4096];
57 static char lastFile[4096];
58 static const char *lastPath;
59 static std::vector<JString> themes;
60 static std::vector<JString> stories;
61
62 public:
63 /** Searchs the given file or directory within the standard dirs:
64 * - Current dir
65 * - Installation dir
66 * - Home dir
67 * @return <b>true</b> if found, <b>false<b> otherwise.
68 */
69 static bool FindFile(const char *filename);
70
71 /** Returns the last queried file. If none, returns an empty string.
72 * @return Last queried file, with its full resolved path preceding it.
73 */
74 static const char* File() {return lastFile;}
75
76 /** Returns the last queried file's path, 0 if it wasn't found.
77 * @return Last queried file, with its full resolved path preceding it.
78 */
79 static const char* Path() {return lastPath;}
80
81 /** Searchs for themes within the standard dirs:
82 * - Current dir
83 * - Installation dir (si onlyEdit es false, por defecto)
84 * - Home dir
85 * @param onlyEdit Indica si se debe buscar en el directorio de instalación (protegido) o no.
86 * @return <b>true</b> if any found, <b>false<b> otherwise.
87 */
88 static bool FindThemes(bool onlyEdit = false);
89
90 /** Searchs for stories within the standard dirs:
91 * - Current dir
92 * - Installation dir (si onlyEdit es false, por defecto)
93 * - Home dir
94 * @param onlyEdit Indica si se debe buscar en el directorio de instalación (protegido) o no.
95 * @return <b>true</b> if any found, <b>false<b> otherwise.
96 */
97 static bool FindStories(bool onlyEdit = false);
98
99 /** Returns the found themes.
100 */
101 static std::vector<JString> & Themes() {return themes;}
102
103 /** Returns the found stories.
104 */
105 static std::vector<JString> & Stories() {return stories;}
106
107 /** Creates a new story in the first stories directory found in the standard path:
108 * - Current dir
109 * - Installation dir
110 * - Home dir
111 * @return 0 if stories dir found and there was no other story with the same name, 1 if a story with the same name existed,
112 * 2 if the stories directory couldn't be found and 3 if there was an error creating the story's directory.
113 */
114 static s32 CreateStory(const char *story);
115
116 /** Frees allocated resources and invalidates the themes and stories.
117 */
118 static void Destroy();
119 };
120
121 #endif // _HCUTIL_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Level editor for Holotz's Castle.
23 * @file HCed.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 30/05/2004
26 * @version 0.0.1 - 30/05/2004 - First version
27 * @version 0.0.2 - 30/05/2004 - Install support, Miriam Ruiz (Debian package). Load/Create story support.
28 */
29
30 #include <HCed.h>
31
32 #ifndef _WIN32
33 #include <unistd.h>
34 #endif
35
36 #ifndef HC_DATA_DIR
37 #define HC_DATA_DIR "res/"
38 #endif
39
40 #ifndef HCED_DATA_DIR
41 #define HCED_DATA_DIR "HCedHome/res/"
42 #endif
43
44 /** This application.
45 */
46 HCed *theApp;
47 HCPreferences prefs;
48
49 void HCed::PrintUsage(char *program)
50 {
51 fprintf(stderr, "HCed v1.3. (C) Juan Carlos Seijo Pérez - 2004.\n\n");
52 fprintf(stderr, "Usage: %s [-t themeName] [story name] [levelToLoad]", program);
53 fprintf(stderr, " [-h] [-r numRows] [-c numColumns]");
54 fprintf(stderr, " [-f]ullscreen [-w]indowed [--fps nnn] [-mWxHxBPP]\n");
55 fprintf(stderr, "\n");
56 exit(0);
57 }
58
59 void HCed::OnKeyUp(SDL_keysym key)
60 {
61 if (theApp->state == HCEDSTATE_OPENSTORY)
62 {
63 if (key.sym == SDLK_ESCAPE)
64 {
65 // Ends opening/creating the a story
66 theApp->OnFloor(0);
67 theApp->inputNewStory = 0;
68 }
69
70 if (HCED_INPUT_STORY == theApp->inputNewStory)
71 {
72 bool upd = false;
73
74 if ((key.sym >= SDLK_0 && key.sym <= SDLK_9) ||
75 (key.sym >= SDLK_a && key.sym <= SDLK_z) ||
76 key.sym == SDLK_MINUS)
77 {
78 if (key.sym == SDLK_MINUS && (theApp->KeyMods() & KMOD_SHIFT))
79 {
80 theApp->strNewStoryName += '_';
81 }
82 else
83 {
84 if ((theApp->KeyMods() & KMOD_SHIFT))
85 {
86 theApp->strNewStoryName += toupper(key.sym);
87 }
88 else
89 {
90 theApp->strNewStoryName += key.sym;
91 }
92 }
93
94 upd = true;
95 }
96 else
97 if (key.sym == SDLK_DELETE || key.sym == SDLK_BACKSPACE)
98 {
99 // Deletes last character
100 if (theApp->strNewStoryName.Length() > 0)
101 {
102 JString str(theApp->strNewStoryName, 0, theApp->strNewStoryName.Length() - 1);
103 theApp->strNewStoryName = str;
104 upd = true;
105 }
106 }
107 else
108 if (key.sym == SDLK_RETURN || key.sym == SDLK_KP_ENTER)
109 {
110 theApp->inputNewStory = HCED_INPUT_THEME;
111
112 // Updates the input string
113 JDELETE(theApp->imgNewStory);
114 SDL_Color fg = {0xff, 0xcc, 0x00, 0x00};
115 SDL_Color bg = {0x00, 0x00, 0x00, 0x00};
116 theApp->imgNewStory = theApp->fontLarge.RenderTextShaded("Select a theme", fg, bg);
117 }
118
119 if (upd)
120 {
121 // Updates the input string
122 JDELETE(theApp->imgNewStory);
123 SDL_Color fg = {0xff, 0xcc, 0x00, 0x00};
124 SDL_Color bg = {0x00, 0x00, 0x00, 0x00};
125 theApp->imgNewStory = theApp->fontLarge.RenderTextShaded((const char *)(JString("Name: ") + theApp->strNewStoryName), fg, bg);
126 }
127 }
128 else
129 if (HCED_INPUT_THEME == theApp->inputNewStory)
130 {
131 theApp->menuTheme->TrackKeyboard(key);
132 }
133 else
134 {
135 theApp->menuOpenStory->TrackKeyboard(key);
136 }
137
138 return;
139 }
140
141 switch (key.sym)
142 {
143 case SDLK_1:
144 OnFloor(0);
145 break;
146
147 case SDLK_2:
148 OnContFloor(0);
149 break;
150
151 case SDLK_3:
152 OnLadder(0);
153 break;
154
155 case SDLK_4:
156 OnBar(0);
157 break;
158
159 case SDLK_5:
160 OnBreak(0);
161 break;
162
163 case SDLK_6:
164 OnObject(0);
165 break;
166
167 case SDLK_7:
168 OnRope(0);
169 break;
170
171 case SDLK_8:
172 OnStart(0);
173 break;
174
175 case SDLK_9:
176 OnExit(0);
177 break;
178
179 case SDLK_0:
180 OnEnemy(0);
181 break;
182
183 case SDLK_s:
184 OnSave(0);
185 break;
186
187 case SDLK_PAGEUP:
188 switch (theApp->PrevLevel())
189 {
190 case -1:
191 fprintf(stderr, "HCed: Error going to previous level.\n");
192 break;
193
194 case 1:
195 fprintf(stderr, "HCed: This is the first level.\n");
196 break;
197
198 case 0:
199 default:
200 break;
201 }
202 break;
203
204 case SDLK_PAGEDOWN:
205 if (theApp->NextLevel() < 0)
206 {
207 fprintf(stderr, "HCed: Error going to next level.\n");
208 }
209 break;
210
211 case SDLK_q:
212 if (theApp->KeyMods() & KMOD_CTRL)
213 {
214 theApp->Exit();
215 }
216 break;
217
218 default:
219 break;
220 }
221 }
222
223 void HCed::OnKeyDown(SDL_keysym key)
224 {
225 switch (key.sym)
226 {
227 // Scrolls down the map
228 case SDLK_UP:
229 {
230 HCMap *map = &theApp->level.Map();
231
232 if (map->Y() < HCED_MARGIN)
233 {
234 theApp->level.Pos((s32)map->X(),
235 (s32)map->Y() + map->CellHeight());
236 }
237 else
238 if (map->Y() > HCED_MARGIN && map->Height() > float(theApp->Height() - HCED_MARGIN))
239 {
240 theApp->level.Pos((s32)map->X(), HCED_MARGIN);
241 }
242 }
243 break;
244
245 // Scrolls up the map
246 case SDLK_DOWN:
247 {
248 HCMap *map = &theApp->level.Map();
249
250 if (map->Y() + map->Height() > theApp->Height())
251 {
252 theApp->level.Pos((s32)map->X(),
253 (s32)map->Y() - map->CellHeight());
254 }
255 else
256 if (map->Y() + map->Height() > theApp->Height() &&
257 map->Height() > theApp->Height() - HCED_MARGIN)
258 {
259 theApp->level.Pos((s32)map->X(), HCED_MARGIN);
260 }
261 }
262 break;
263
264 // Scrolls right the map
265 case SDLK_LEFT:
266 {
267 HCMap *map = &theApp->level.Map();
268
269 if (map->X() < HCED_MARGIN)
270 {
271 theApp->level.Pos((s32)map->X() + map->CellWidth(),
272 (s32)map->Y());
273 }
274 else
275 if (map->X() > HCED_MARGIN && map->Width() > float(theApp->Width() - HCED_MARGIN))
276 {
277 theApp->level.Pos(HCED_MARGIN, (s32)map->Y());
278 }
279 }
280 break;
281
282 // Scrolls left the map
283 case SDLK_RIGHT:
284 {
285 HCMap *map = &theApp->level.Map();
286
287 if (map->X() + map->Width() > theApp->Width())
288 {
289 theApp->level.Pos((s32)map->X() - map->CellWidth(),
290 (s32)map->Y());
291 }
292 else
293 if (map->X() + map->Width() > theApp->Width() &&
294 map->Width() > theApp->Width() - HCED_MARGIN)
295 {
296 theApp->level.Pos(HCED_MARGIN, (s32)map->Y());
297 }
298 }
299 break;
300
301 case SDLK_KP_PLUS:
302 {
303 // Time to complete level up
304 theApp->level.maxTime += 1;
305 if (theApp->level.maxTime > 0xffff)
306 {
307 theApp->level.maxTime = 0xffff;
308 }
309 theApp->level.levelTimer.Init(theApp->level.maxTime, &theApp->fontNormal);
310 }
311 break;
312
313 case SDLK_KP_MINUS:
314 {
315 // Time to complete level down
316 theApp->level.maxTime -= 1;
317 if (theApp->level.maxTime == 0)
318 {
319 theApp->level.maxTime = 1;
320 }
321
322 theApp->level.levelTimer.Init(theApp->level.maxTime, &theApp->fontNormal);
323 }
324 break;
325
326 case SDLK_g:
327 {
328 if ((SDL_GetModState() & KMOD_SHIFT))
329 {
330 // Map gravity down
331 theApp->level.map.Gravity(theApp->level.map.Gravity() - 0.1f);
332 }
333 else
334 {
335 // Map gravity up
336 theApp->level.map.Gravity(theApp->level.map.Gravity() + 0.1f);
337 }
338
339 OnGravityChange();
340 }
341 break;
342
343 case SDLK_x:
344 {
345 if ((SDL_GetModState() & KMOD_SHIFT))
346 {
347 // Main character's Vx down
348 theApp->level.character.MaxVeloccity().x -= 0.1f;
349 }
350 else
351 {
352 // Main character's Vx up
353 theApp->level.character.MaxVeloccity().x += 0.1f;
354 }
355
356 OnCharVxChange();
357 }
358 break;
359
360 case SDLK_y:
361 {
362 if ((SDL_GetModState() & KMOD_SHIFT))
363 {
364 // Main character's Vy down
365 theApp->level.character.MaxVeloccity().y -= 0.1f;
366 }
367 else
368 {
369 // Main character's Vy up
370 theApp->level.character.MaxVeloccity().y += 0.1f;
371 }
372
373 OnCharVyChange();
374 }
375 break;
376
377 case SDLK_j:
378 {
379 if ((SDL_GetModState() & KMOD_SHIFT))
380 {
381 // Main character's max jump rows down
382 theApp->level.character.MaxJumpRows(theApp->level.character.MaxJumpRows() - 1);
383 }
384 else
385 {
386 // Main character's max jump rows up
387 theApp->level.character.MaxJumpRows(theApp->level.character.MaxJumpRows() + 1);
388 }
389
390 OnCharJumpRowsChange();
391 }
392 break;
393
394 case SDLK_r:
395 {
396 if ((SDL_GetModState() & KMOD_SHIFT))
397 {
398 if ((SDL_GetModState() & KMOD_CTRL))
399 {
400 // Decrease number of rows from the top
401 theApp->level.map.Resize(theApp->level.map.Rows() - 1, theApp->level.map.Cols(), true, false);
402 }
403 else
404 {
405 // Decrease number of rows from the bottom
406 theApp->level.map.Resize(theApp->level.map.Rows() - 1, theApp->level.map.Cols());
407 }
408 }
409 else
410 {
411 if ((SDL_GetModState() & KMOD_CTRL))
412 {
413 // Increase number of rows from the top
414 theApp->level.map.Resize(theApp->level.map.Rows() + 1, theApp->level.map.Cols(), true, false);
415 }
416 else
417 {
418 // Increase number of rows from the bottom
419 theApp->level.map.Resize(theApp->level.map.Rows() + 1, theApp->level.map.Cols());
420 }
421 }
422
423 OnMapSizeChange();
424 }
425 break;
426
427 case SDLK_c:
428 {
429 if ((SDL_GetModState() & KMOD_SHIFT))
430 {
431 if ((SDL_GetModState() & KMOD_CTRL))
432 {
433 // Decrease number of columns from the left
434 theApp->level.map.Resize(theApp->level.map.Rows(), theApp->level.map.Cols() - 1, false);
435 }
436 else
437 {
438 // Decrease number of columns from the right
439 theApp->level.map.Resize(theApp->level.map.Rows(), theApp->level.map.Cols() - 1);
440 }
441 }
442 else
443 {
444 if ((SDL_GetModState() & KMOD_CTRL))
445 {
446 // Increase number of columns from the left
447 theApp->level.map.Resize(theApp->level.map.Rows(), theApp->level.map.Cols() + 1, false);
448 }
449 else
450 {
451 // Increase number of columns from the right
452 theApp->level.map.Resize(theApp->level.map.Rows(), theApp->level.map.Cols() + 1);
453 }
454 }
455
456 OnMapSizeChange();
457 }
458 break;
459
460 default:
461 break;
462 }
463 }
464
465 void HCed::OnMouseUp(s32 bt, s32 x, s32 y)
466 {
467 switch (theApp->state)
468 {
469 case HCEDSTATE_FLOOR:
470 theApp->menuFloorSubtype->TrackMouse(bt, x, y);
471 break;
472 case HCEDSTATE_CONTFLOOR:
473 theApp->menuContFloorSubtype->TrackMouse(bt, x, y);
474 break;
475 case HCEDSTATE_LADDER:
476 theApp->menuLadderSubtype->TrackMouse(bt, x, y);
477 break;
478 case HCEDSTATE_BAR:
479 theApp->menuBarSubtype->TrackMouse(bt, x, y);
480 break;
481 case HCEDSTATE_BREAK:
482 theApp->menuBreakSubtype->TrackMouse(bt, x, y);
483 break;
484 case HCEDSTATE_OBJECT:
485 theApp->curObject = 0;
486 theApp->menuObjectSubtype->TrackMouse(bt, x, y);
487 break;
488 case HCEDSTATE_ROPE:
489 theApp->curRope = 0;
490 theApp->menuRopePeriod->TrackMouse(bt, x, y);
491 theApp->menuRopeSubtype->TrackMouse(bt, x, y);
492 break;
493 case HCEDSTATE_START:
494 theApp->menuMainSubtype->TrackMouse(bt, x, y);
495 break;
496 case HCEDSTATE_EXIT:
497 break;
498 case HCEDSTATE_ENEMY:
499 theApp->curEnemy = 0;
500 theApp->menuEnemyType->TrackMouse(bt, x, y);
501 theApp->menuEnemySubtype[theApp->enemyType]->TrackMouse(bt, x, y);
502 theApp->menuEnemyParam1->TrackMouse(bt, x, y);
503 theApp->menuEnemyParam2->TrackMouse(bt, x, y);
504 break;
505 case HCEDSTATE_SAVE:
506 break;
507
508 case HCEDSTATE_OPENSTORY:
509 switch (theApp->inputNewStory)
510 {
511 case 0:
512 theApp->menuOpenStory->TrackMouse(bt, x, y);
513 break;
514
515 case HCED_INPUT_THEME:
516 theApp->menuTheme->TrackMouse(bt, x, y);
517 break;
518
519 default:
520 break;
521 }
522 break;
523
524 case HCEDSTATE_APPEXIT:
525 break;
526 default:
527 break;
528 }
529
530 theApp->menuMain->TrackMouse(bt, x, y);
531 }
532
533 void HCed::OnMouseDown(s32 bt, s32 x, s32 y)
534 {
535 switch (theApp->state)
536 {
537 case HCEDSTATE_OBJECT:
538 theApp->curObject = 0;
539 HCObject *obj;
540
541 // Checks for objects bellow the mouse cursor
542 for (s32 i = 0; i < theApp->level.numObjects; ++i)
543 {
544 obj = theApp->level.objects[i];
545
546 if (theApp->MouseX() > obj->X() - obj->Normal().MaxW()/2 &&
547 theApp->MouseX() < obj->X() + obj->Normal().MaxW()/2 &&
548 theApp->MouseY() > obj->Y() - obj->Normal().MaxH() &&
549 theApp->MouseY() < obj->Y())
550 {
551 theApp->curObject = theApp->level.objects[i];
552 }
553 }
554 break;
555
556 case HCEDSTATE_ROPE:
557 theApp->curRope = 0;
558
559 // Checks for ropes bellow the mouse cursor
560 for (s32 i = 0; i < theApp->level.numRopes; ++i)
561 {
562 if (theApp->MouseX() > (theApp->level.ropes[i])->X() - theApp->level.Map().CellWidth()/2 &&
563 theApp->MouseX() < (theApp->level.ropes[i])->X() + theApp->level.Map().CellWidth()/2 &&
564 theApp->MouseY() > (theApp->level.ropes[i])->Y() &&
565 theApp->MouseY() < (theApp->level.ropes[i])->Y() + theApp->level.Map().CellHeight())
566 {
567 theApp->curRope = theApp->level.ropes[i];
568 }
569 }
570
571 if (theApp->curRope)
572 {
573 // Sets the period
574 if (theApp->ropePeriod != theApp->curRope->Period())
575 {
576 theApp->curRope->Init(theApp->ropePeriod,
577 theApp->curRope->Amplitude(),
578 theApp->curRope->Length(),
579 theApp->level.Theme());
580 }
581 }
582 break;
583
584 case HCEDSTATE_ENEMY:
585 theApp->curEnemy = 0;
586
587 // Checks for enemies bellow the mouse cursor
588 for (s32 i = 0; i < theApp->level.numEnemies; ++i)
589 {
590 if (theApp->MouseX() > (theApp->level.enemies[i])->X() - (theApp->level.enemies[i]->states[HCCS_STOP].MaxW()/2) &&
591 theApp->MouseX() < (theApp->level.enemies[i])->X() + (theApp->level.enemies[i]->states[HCCS_STOP].MaxW()/2) &&
592 theApp->MouseY() > (theApp->level.enemies[i])->Y() - (theApp->level.enemies[i]->states[HCCS_STOP].MaxH()/2) &&
593 theApp->MouseY() < (theApp->level.enemies[i])->Y())
594 {
595 theApp->curEnemy = theApp->level.enemies[i];
596 }
597 }
598 break;
599
600 default:
601 break;
602 }
603 }
604
605 int HCed::ParseArg(char *args[], int argc)
606 {
607 printf("Parsing %d args %s\n", argc, args[0]);
608 if (args[0][0] != '-')
609 {
610 // Argument without score, treat it as the story name
611 storyName = args[0];
612
613 if (argc < 2)
614 {
615 levelNumber = 1;
616
617 return 0; // no aditional arguments needed
618 }
619
620 levelNumber = atoi(args[1]);
621
622 if (levelNumber <= 0)
623 {
624 levelNumber = 1;
625 fprintf(stderr, "HCed: The level number must be greater than 0, defaulting to 1.\n");
626 }
627 return 1; // 1 aditional argument used
628 }
629
630 switch (args[0][1])
631 {
632 // '-t themeName' option
633 case 't':
634 if (argc<2)
635 return -2;
636 themeName = args[1];
637 return 1;
638
639 // '-r numRows' option
640 case 'r':
641 if (argc<2)
642 return -2;
643 defRows = atoi(args[1]);
644
645 if (defRows <= 0)
646 {
647 defRows = 10;
648 }
649 return 1;
650
651 // '-c numCols' option
652 case 'c':
653 if (argc<2)
654 return -2;
655 defCols = atoi(args[1]);
656
657 if (defCols <= 0)
658 {
659 defCols = 10;
660 }
661 return 1;
662 }
663
664 return JApp::ParseArg(args, argc);
665 }
666
667 void HCed::ParseArgs(s32 argc, char **argv)
668 {
669 JApp::ParseArgs(argc, argv);
670
671 char str[4096];
672
673 #ifndef _WIN32
674 char *home;
675 home = getenv("HOME");
676 if (home != NULL)
677 {
678 snprintf(str, sizeof(str), "%s/.holotz-castle", home);
679 mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
680 snprintf(str, sizeof(str), "%s/.holotz-castle/stories", home);
681 mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
682 snprintf(str, sizeof(str), "%s/.holotz-castle/stories/%s", home, storyName.Str());
683 mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
684 }
685 #endif
686
687 if (!HCUtil::FindFile("stories"))
688 {
689 fprintf(stderr, "Directory 'stories' not found. Check manual.\n");
690 exit(-1);
691 }
692 else
693 {
694 // Assigns this directory as the default working directory
695 storyDir = HCUtil::File();
696 storyDir += "/";
697 }
698
699 if (levelNumber == -1)
700 {
701 // Selects the next file name from the requested story
702 levelNumber = 1;
703
704 snprintf(str, sizeof(str), "%s%s/level%03d.hlv", storyDir.Str(), storyName.Str(), levelNumber);
705 while (JFile::Exists(str))
706 {
707 snprintf(str, sizeof(str), "%s%s/level%03d.hlv", storyDir.Str(), storyName.Str(), ++levelNumber);
708 }
709
710 filename = str;
711 }
712 else
713 {
714 // Sets the name of the requested story and level number.
715 snprintf(str, sizeof(str), "%s%s/level%03d.hlv", storyDir.Str(), storyName.Str(), levelNumber);
716 filename = str;
717 }
718
719 OnFilenameChange();
720 }
721
722 HCed::HCed() : JApp("HCed v1.1", HCED_REFAPPWIDTH, HCED_REFAPPHEIGHT, false)
723 {
724 state = HCEDSTATE_FLOOR;
725 SetOnMouseUp(&OnMouseUp);
726 SetOnMouseDown(&OnMouseDown);
727 SetOnKeyUp(&OnKeyUp);
728 SetOnKeyDown(&OnKeyDown);
729 doInput = true;
730 curObject = 0;
731 curRope = 0;
732 curEnemy = 0;
733 defRows = defCols = 10;
734 enemyParam1 = 1;
735 enemyParam2 = 1;
736 imgNewStory = 0;
737 imgGravity = 0;
738 imgCharVx = 0;
739 imgCharVy = 0;
740 imgCharJumpRows = 0;
741 imgMapSize = 0;
742 levelNumber = -1;
743 menuMain = 0;
744 menuEnemyType = 0;
745 menuEnemyParam1 = 0;
746 menuEnemyParam2 = 0;
747 menuOpenStory = 0;
748 menuTheme = 0;
749 menuRopePeriod = 0;
750 menuMainSubtype = 0;
751 menuBreakSubtype = 0;
752 menuObjectSubtype = 0;
753 menuFloorSubtype = 0;
754 menuContFloorSubtype = 0;
755 menuBarSubtype = 0;
756 menuLadderSubtype = 0;
757 menuRopeSubtype = 0;
758 appBackColor = 0;
759
760 for (s32 i = 0; i < HCENEMYTYPE_COUNT; ++i)
761 {
762 menuEnemySubtype[i] = 0;
763 }
764
765 storyName = "unknown";
766 themeName = "default";
767 inputNewStory = 0;
768 }
769
770 s32 HCed::LoadLevel()
771 {
772 // If the level exists, loads it
773 bool ok = false;
774
775 // Sets the timer font
776 level.SetTimerFont(&fontNormal);
777
778 if (JFile::Exists(filename))
779 {
780 JRW f;
781 if (f.Create(filename, "rb"))
782 {
783 if (0 == level.Load(f, filename))
784 {
785 if (InitLoadedLevel())
786 {
787 ok = true;
788 }
789 else
790 {
791 fprintf(stderr, "Could not init the loaded level.\n");
792 }
793 }
794 else
795 {
796 fprintf(stderr, "Could not load level from %s.\n", filename.Str());
797 }
798 }
799 else
800 {
801 fprintf(stderr, "Could not open file %s for reading.\n", filename.Str());
802 }
803 }
804 else
805 {
806 fprintf(stderr, "HCed: File %s doesn't exist, creating a new level.\n", filename.Str());
807 }
808
809 // If an error occurred or the file didn't exist, tries to load the default level/theme
810 if (!ok)
811 {
812 if (!InitDefaultLevel())
813 {
814 fprintf(stderr, "Could not init default level.\n");
815 return -1;
816 }
817 }
818
819 // Places the level
820 level.Pos(HCED_MARGIN, HCED_MARGIN);
821
822 // Prepares the current gravity and main character's parameters to be shown
823 OnGravityChange();
824 OnCharVxChange();
825 OnCharVyChange();
826 OnCharJumpRowsChange();
827 OnMapSizeChange();
828
829 // Types and theme subtypes
830 enemyType = HCENEMYTYPE_BALL;
831 enemySubtype = 0;
832 floorSubtype = 0;
833 contFloorSubtype = 0;
834 breakSubtype = 0;
835 barSubtype = 0;
836 ladderSubtype = 0;
837 objectSubtype = 0;
838 ropeSubtype = 0;
839 ropePeriod = 0;
840
841 // Re-initializes level/theme dependant menus
842 return InitLevelMenus();
843 }
844
845 s32 HCed::InitLevelMenus()
846 {
847 imgMouse = 0;
848
849 // Inits the main character subtype menu
850 if (!InitMainSubtypeMenu())
851 {
852 fprintf(stderr, "Failed to init main character's subtype menu.\n");
853
854 return -1;
855 }
856
857 // Inits the break subtypes menu
858 if (!InitBreakSubtypeMenu())
859 {
860 fprintf(stderr, "Failed to init break subtypes menu.\n");
861
862 return -1;
863 }
864
865 // Inits the object subtypes menu
866 if (!InitObjectSubtypeMenu())
867 {
868 fprintf(stderr, "Failed to init object subtypes menu.\n");
869
870 return -1;
871 }
872
873 // Inits the enemy representations menu
874 if (!InitEnemySubtypeMenu())
875 {
876 fprintf(stderr, "Failed to init enemy subtypes menu.\n");
877
878 return -1;
879 }
880
881 // Inits the floor subtypes menu
882 if (!InitFloorSubtypeMenu())
883 {
884 fprintf(stderr, "Failed to init floor subtypes menu.\n");
885
886 return false;
887 }
888
889
890 // Inits the continuous floor subtypes menu
891 if (!InitContFloorSubtypeMenu())
892 {
893 fprintf(stderr, "Failed to init floor subtypes menu.\n");
894
895 return false;
896 }
897
898 // Inits the bar subtypes menu
899 if (!InitBarSubtypeMenu())
900 {
901 fprintf(stderr, "Failed to init bar subtypes menu.\n");
902
903 return false;
904 }
905
906 // Inits the ladder subtypes menu
907 if (!InitLadderSubtypeMenu())
908 {
909 fprintf(stderr, "Failed to init ladder subtypes menu.\n");
910
911 return false;
912 }
913
914 // Inits the rope subtypes menu
915 if (!InitRopeSubtypeMenu())
916 {
917 fprintf(stderr, "Failed to init rope subtypes menu.\n");
918
919 return false;
920 }
921
922 // Inits the open story menu
923 if (!InitOpenStoryMenu())
924 {
925 fprintf(stderr, "Failed to init stories menu.\n");
926
927 return false;
928 }
929
930 // Inits the theme subtypes menu
931 if (!InitThemeMenu())
932 {
933 fprintf(stderr, "Failed to init stories menu.\n");
934
935 return false;
936 }
937
938 return 0;
939 }
940
941 s32 HCed::NextLevel()
942 {
943 char str[256];
944
945 // Sets the name of the story with the next level number.
946 snprintf(str, sizeof(str), "%s%s/level%03d.hlv", storyDir.Str(), storyName.Str(), ++levelNumber);
947 filename = str;
948
949 if (0 == LoadLevel())
950 {
951 themeName = level.Theme().Name();
952 OnFilenameChange();
953
954 if (0 == InitLevelMenus())
955 {
956 OnFloor(this);
957
958 return 0;
959 }
960 }
961
962 return -1;
963 }
964
965 s32 HCed::PrevLevel()
966 {
967 if (levelNumber > 1)
968 {
969 char str[256];
970
971 // Sets the name of the story with the next level number.
972 snprintf(str, sizeof(str), "%s%s/level%03d.hlv", storyDir.Str(), storyName.Str(), --levelNumber);
973 filename = str;
974
975 if (0 == LoadLevel())
976 {
977 OnFilenameChange();
978
979 if (0 == InitLevelMenus())
980 {
981 OnFloor(this);
982
983 return 0;
984 }
985 }
986
987 return -1;
988 }
989
990 // No more levels before
991 return 1;
992 }
993
994 s32 HCed::NewLevel()
995 {
996 if (0 == LoadLevel())
997 {
998 OnFilenameChange();
999
1000 if (0 == InitLevelMenus())
1001 {
1002 OnFloor(this);
1003
1004 return 0;
1005 }
1006 }
1007
1008 return -1;
1009 }
1010
1011 bool HCed::Init(int argc, char **argv)
1012 {
1013 // Parse standard JApp args and HCed args
1014 ParseArgs(argc, argv);
1015
1016 // Inits base system
1017 if (!JApp::Init())
1018 {
1019 fprintf(stderr, "Failed to init base system. Check manual.\n");
1020
1021 return false;
1022 }
1023
1024 // Loads preferences
1025 // if (0 != prefs.Load())
1026 // {
1027 // fprintf(stderr, "Error loading preferences. Check manual.\n");
1028 // }
1029
1030 // In edition mode the time must be that of the highest level of difficulty
1031 prefs.Difficulty(HCPREFERENCES_HARD);
1032
1033 // Initializes fonts
1034 if (!JFile::Exists(HC_DATA_DIR "font/font.ttf"))
1035 {
1036 fprintf(stderr,
1037 "Could not find data directory.\n\n"
1038 "Posible solutions are:\n"
1039 " - Open folder JLib-1.3.1/Games/HolotzCastle and double.\n"
1040 " click 'holotz-castle' application icon.\n"
1041 " - Maybe you did 'make' but didn't do 'make install'.\n"
1042 " - Else, try to reinstall the game.\n");
1043 return false;
1044 }
1045
1046 if (!fontSmall.Open(HC_DATA_DIR "font/font.ttf", 12) ||
1047 !fontNormal.Open(HC_DATA_DIR "font/font.ttf", 18) ||
1048 !fontLarge.Open(HC_DATA_DIR "font/font.ttf", 24))
1049 {
1050 fprintf(stderr, "Couldn't open fonts. Check manual.\n");
1051 return false;
1052 }
1053
1054 // Loads the level
1055 if (0 != LoadLevel())
1056 {
1057 fprintf(stderr, "Couldn't load level. Check manual.\n");
1058 return false;
1059 }
1060
1061 // Inits the main menu
1062 if (!InitMainMenu())
1063 {
1064 fprintf(stderr, "Failed to init main menu.\n");
1065
1066 return false;
1067 }
1068
1069 // Inits the level dependant menus
1070 if (0 != InitLevelMenus())
1071 {
1072 fprintf(stderr, "Failed to init level menus.\n");
1073
1074 return false;
1075 }
1076
1077 // Inits the rope periods menu
1078 if (!InitRopePeriodMenu())
1079 {
1080 fprintf(stderr, "Failed to init rope periods menu.\n");
1081
1082 return false;
1083 }
1084
1085 // Inits the enemy types menu
1086 if (!InitEnemyTypeMenu())
1087 {
1088 fprintf(stderr, "Failed to init enemy types menu.\n");
1089
1090 return false;
1091 }
1092
1093 // Inits the enemy param 1 menu
1094 if (!InitEnemyParam1Menu())
1095 {
1096 fprintf(stderr, "Failed to init enemy param 1 menu.\n");
1097
1098 return false;
1099 }
1100
1101 // Inits the enemy param 2 menu
1102 if (!InitEnemyParam2Menu())
1103 {
1104 fprintf(stderr, "Failed to init enemy param 2 menu.\n");
1105
1106 return false;
1107 }
1108
1109 appBackColor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x07);
1110
1111 OnFloor(this);
1112
1113 return true;
1114 }
1115
1116 bool HCed::InitLoadedLevel()
1117 {
1118 // Nothing for the moment
1119 return true;
1120 }
1121
1122 bool HCed::InitDefaultLevel()
1123 {
1124 // Destroy a previous level
1125 level.Destroy();
1126
1127 // Sets the timer font
1128 level.SetTimerFont(&fontNormal);
1129
1130 // Loads the theme
1131 printf("Using theme %s\n", themeName.Str());
1132 if (!level.Theme().Load(themeName.Str()))
1133 {
1134 fprintf(stderr, "Error loading theme.\n");
1135 return false;
1136 }
1137
1138 // Initializes the map
1139 level.Map().Init(level.Theme());
1140 level.Map().Resize(defRows, defCols);
1141 level.Map().CellWidth(level.Theme().Floor(0).Width());
1142 level.Map().CellHeight(level.Theme().Floor(0).Height());
1143
1144 // Initializes the character
1145 level.character.Pos(20, 20);
1146
1147 if (!level.Init())
1148 {
1149 fprintf(stderr, "Error initializing level.\n");
1150 return false;
1151 }
1152
1153 return true;
1154 }
1155
1156 bool HCed::InitMainMenu()
1157 {
1158 JDELETE(menuMain);
1159 menuMain = new JImageMenu;
1160
1161 char str[256];
1162
1163 for (s32 i = 0; i < HCEDSTATE_COUNT; ++i)
1164 {
1165 snprintf(str, sizeof(str), HCED_DATA_DIR "MainMenu/%d.tga", i);
1166 //fprintf(stderr, "Loading UI Item " HCED_DATA_DIR "MainMenu/%d.tga\n", i);
1167
1168 if (!imgMenu[i].Load(str))
1169 {
1170 return false;
1171 }
1172
1173 snprintf(str, sizeof(str), HCED_DATA_DIR "MainMenu/%d_hi.tga", i);
1174 //fprintf(stderr, "Loading UI Item " HCED_DATA_DIR "MainMenu/%d_hi.tga\n", i);
1175
1176 if (!imgMenuOver[i].Load(str))
1177 {
1178 return false;
1179 }
1180 }
1181
1182 // Adds the options
1183 JTree<JImageMenuEntry *>::Iterator *it = menuMain->Menu();
1184
1185 it->Data(new JImageMenuEntry(&imgMenu[HCEDSTATE_FLOOR],
1186 &imgMenuOver[HCEDSTATE_FLOOR], &OnFloor, this));
1187 it->AddNodeGo(new JImageMenuEntry(&imgMenu[HCEDSTATE_CONTFLOOR],
1188 &imgMenuOver[HCEDSTATE_CONTFLOOR], &OnContFloor, this));
1189 it->AddNodeGo(new JImageMenuEntry(&imgMenu[HCEDSTATE_LADDER],
1190 &imgMenuOver[HCEDSTATE_LADDER], &OnLadder, this));
1191 it->AddNodeGo(new JImageMenuEntry(&imgMenu[HCEDSTATE_BAR],
1192 &imgMenuOver[HCEDSTATE_BAR], &OnBar, this));
1193 it->AddNodeGo(new JImageMenuEntry(&imgMenu[HCEDSTATE_BREAK],
1194 &imgMenuOver[HCEDSTATE_BREAK], &OnBreak, this));
1195 it->AddNodeGo(new JImageMenuEntry(&imgMenu[HCEDSTATE_OBJECT],
1196 &imgMenuOver[HCEDSTATE_OBJECT], &OnObject, this));
1197 it->AddNodeGo(new JImageMenuEntry(&imgMenu[HCEDSTATE_ROPE],
1198 &imgMenuOver[HCEDSTATE_ROPE], &OnRope, this));
1199 it->AddNodeGo(new JImageMenuEntry(&imgMenu[HCEDSTATE_START],
1200 &imgMenuOver[HCEDSTATE_START], &OnStart, this));
1201 it->AddNodeGo(new JImageMenuEntry(&imgMenu[HCEDSTATE_EXIT],
1202 &imgMenuOver[HCEDSTATE_EXIT], &OnExit, this));
1203 it->AddNodeGo(new JImageMenuEntry(&imgMenu[HCEDSTATE_ENEMY],
1204 &imgMenuOver[HCEDSTATE_ENEMY], &OnEnemy, this));
1205 it->AddNodeGo(new JImageMenuEntry(&imgMenu[HCEDSTATE_SAVE],
1206 &imgMenuOver[HCEDSTATE_SAVE], &OnSave, this));
1207 it->AddNodeGo(new JImageMenuEntry(&imgMenu[HCEDSTATE_OPENSTORY],
1208 &imgMenuOver[HCEDSTATE_OPENSTORY], &OnOpenStory, this));
1209 it->AddNodeGo(new JImageMenuEntry(&imgMenu[HCEDSTATE_APPEXIT],
1210 &imgMenuOver[HCEDSTATE_APPEXIT], &OnAppExit, this));
1211 it->Root();
1212
1213 JImageMenuConfig cfg;
1214 cfg.layout = JIMAGEMENU_LEFT;
1215 cfg.trackMouse = true;
1216 cfg.trackKeyboard = false;
1217 cfg.autoEnter = false;
1218
1219 if (!menuMain->Init(cfg))
1220 {
1221 return false;
1222 }
1223
1224 menuMain->Pos(0, 0);
1225 menuMain->Menu()->Root();
1226
1227 return true;
1228 }
1229
1230 bool HCed::InitMainSubtypeMenu()
1231 {
1232 DestroyMainSubtypeMenu();
1233 menuMainSubtype = new JImageMenu;
1234
1235 // Adds the options
1236 JTree<JImageMenuEntry *>::Iterator *it = menuMainSubtype->Menu();
1237 it->Root();
1238
1239 it->Data(new JImageMenuEntry(new JImage(*((JImage*)level.theme.MainChar(0)[HCCDT_STOP].Frame(0))),
1240 new JImage(*((JImage*)level.theme.MainChar(0)[HCCDT_LEFT].Frame(0))),
1241 &OnMainSubtype, (void *)0));
1242
1243 // Adds the subtypes
1244 for (s32 i = 1; i < level.theme.NumMainChars(); ++i)
1245 {
1246 it->AddNodeGo(new JImageMenuEntry(new JImage(*((JImage*)level.theme.MainChar(i)[HCCDT_STOP].Frame(0))),
1247 new JImage(*((JImage*)level.theme.MainChar(i)[HCCDT_LEFT].Frame(0))),
1248 &OnMainSubtype, JCAST_S32_TO_VOIDPTR(i)));
1249 }
1250
1251 it->Root();
1252
1253 JImageMenuConfig cfg;
1254 cfg.layout = JIMAGEMENU_SAMELINE;
1255 cfg.trackMouse = true;
1256 cfg.trackKeyboard = false;
1257 cfg.autoEnter = false;
1258 menuMainSubtype->Pos(HCED_MARGIN, 0);
1259
1260 if (!menuMainSubtype->Init(cfg))
1261 {
1262 return false;
1263 }
1264
1265 menuMainSubtype->Menu()->Root();
1266
1267 return true;
1268 }
1269
1270 bool HCed::InitFloorSubtypeMenu()
1271 {
1272 JDELETE(menuFloorSubtype);
1273 menuFloorSubtype = new JImageMenu;
1274
1275 // Adds the options
1276 JTree<JImageMenuEntry *>::Iterator *it = menuFloorSubtype->Menu();
1277
1278 // At least we must have this
1279 it->Data(new JImageMenuEntry(&level.Theme().Floor(0), &level.Theme().Floor(0), &OnFloorSubtype, (void *)0));
1280
1281 // Adds the rest of subtypes
1282 for (s32 i = 1; i < level.Theme().NumFloors(); ++i)
1283 {
1284 it->AddNodeGo(new JImageMenuEntry(&level.Theme().Floor(i), &level.Theme().Floor(i), &OnFloorSubtype, JCAST_S32_TO_VOIDPTR(i)));
1285 }
1286
1287 it->Root();
1288
1289 JImageMenuConfig cfg;
1290 cfg.layout = JIMAGEMENU_SAMELINE;
1291 cfg.trackMouse = true;
1292 cfg.trackKeyboard = false;
1293 cfg.autoEnter = false;
1294
1295 if (!menuFloorSubtype->Init(cfg))
1296 {
1297 fprintf(stderr, "Error\n");
1298 return false;
1299 }
1300
1301 menuFloorSubtype->Pos(HCED_MARGIN, 0);
1302 menuFloorSubtype->Menu()->Root();
1303
1304 return true;
1305 }
1306
1307 bool HCed::InitContFloorSubtypeMenu()
1308 {
1309 JDELETE(menuContFloorSubtype);
1310 menuContFloorSubtype = new JImageMenu;
1311
1312 // Adds the options
1313 JTree<JImageMenuEntry *>::Iterator *it = menuContFloorSubtype->Menu();
1314
1315 // At least we must have this
1316 it->Data(new JImageMenuEntry(&level.Theme().ContFloor(0)[HCFDT_I], &level.Theme().ContFloor(0)[HCFDT_I], &OnContFloorSubtype, (void *)0));
1317
1318 // Adds the rest of subtypes
1319 for (s32 i = 1; i < level.Theme().NumContFloors(); ++i)
1320 {
1321 it->AddNodeGo(new JImageMenuEntry(&level.Theme().ContFloor(i)[HCFDT_I], &level.Theme().ContFloor(i)[HCFDT_I], &OnContFloorSubtype, JCAST_S32_TO_VOIDPTR(i)));
1322 }
1323
1324 it->Root();
1325
1326 JImageMenuConfig cfg;
1327 cfg.layout = JIMAGEMENU_SAMELINE;
1328 cfg.trackMouse = true;
1329 cfg.trackKeyboard = false;
1330 cfg.autoEnter = false;
1331
1332 if (!menuContFloorSubtype->Init(cfg))
1333 {
1334 fprintf(stderr, "Error\n");
1335 return false;
1336 }
1337
1338 menuContFloorSubtype->Pos(HCED_MARGIN, 0);
1339 menuContFloorSubtype->Menu()->Root();
1340
1341 return true;
1342 }
1343
1344 bool HCed::InitBreakSubtypeMenu()
1345 {
1346 DestroyBreakSubtypeMenu();
1347 menuBreakSubtype = new JImageMenu;
1348
1349 // Adds the options
1350 JTree<JImageMenuEntry *>::Iterator *it = menuBreakSubtype->Menu();
1351 it->Root();
1352
1353 // At least we must have this
1354 it->Data(new JImageMenuEntry(new JImage(*((JImage*)level.Theme().Break(0)[HCBDT_NORMAL].Frame(0))),
1355 new JImage(*((JImage*)level.Theme().Break(0)[HCBDT_NORMAL].Frame(0))),
1356 &OnBreakSubtype, (void *)0));
1357
1358 // Adds the rest of subtypes
1359 for (s32 i = 1; i < level.Theme().NumBreaks(); ++i)
1360 {
1361 it->AddNodeGo(new JImageMenuEntry(new JImage(*((JImage*)level.Theme().Break(i)[HCBDT_NORMAL].Frame(0))),
1362 new JImage(*((JImage*)level.Theme().Break(i)[HCBDT_NORMAL].Frame(0))),
1363 &OnBreakSubtype, JCAST_S32_TO_VOIDPTR(i)));
1364 }
1365
1366 it->Root();
1367
1368 JImageMenuConfig cfg;
1369 cfg.layout = JIMAGEMENU_SAMELINE;
1370 cfg.trackMouse = true;
1371 cfg.trackKeyboard = false;
1372 cfg.autoEnter = false;
1373 menuBreakSubtype->Pos(HCED_MARGIN, 0);
1374
1375 if (!menuBreakSubtype->Init(cfg))
1376 {
1377 return false;
1378 }
1379
1380 menuBreakSubtype->Menu()->Root();
1381
1382 return true;
1383 }
1384
1385 bool HCed::InitBarSubtypeMenu()
1386 {
1387 JDELETE(menuBarSubtype);
1388 menuBarSubtype = new JImageMenu;
1389
1390 // Adds the options
1391 JTree<JImageMenuEntry *>::Iterator *it = menuBarSubtype->Menu();
1392
1393 // At least we must have this
1394 it->Data(new JImageMenuEntry(&level.Theme().Bar(0), &level.Theme().Bar(0), &OnBarSubtype, (void *)0));
1395
1396 // Adds the rest of subtypes
1397 for (s32 i = 1; i < level.Theme().NumBars(); ++i)
1398 {
1399 it->AddNodeGo(new JImageMenuEntry(&level.Theme().Bar(i), &level.Theme().Bar(i), &OnBarSubtype, JCAST_S32_TO_VOIDPTR(i)));
1400 }
1401
1402 it->Root();
1403
1404 JImageMenuConfig cfg;
1405 cfg.layout = JIMAGEMENU_SAMELINE;
1406 cfg.trackMouse = true;
1407 cfg.trackKeyboard = false;
1408 cfg.autoEnter = false;
1409 menuBarSubtype->Pos(HCED_MARGIN, 0);
1410
1411 if (!menuBarSubtype->Init(cfg))
1412 {
1413 return false;
1414 }
1415
1416 menuBarSubtype->Menu()->Root();
1417
1418 return true;
1419 }
1420
1421 bool HCed::InitLadderSubtypeMenu()
1422 {
1423 JDELETE(menuLadderSubtype);
1424 menuLadderSubtype = new JImageMenu;
1425
1426 // Adds the options
1427 JTree<JImageMenuEntry *>::Iterator *it = menuLadderSubtype->Menu();
1428
1429 // At least we must have this
1430 it->Data(new JImageMenuEntry(&level.Theme().Ladder(0), &level.Theme().Ladder(0), &OnLadderSubtype, (void *)0));
1431
1432 // Adds the rest of subtypes
1433 for (s32 i = 1; i < level.Theme().NumLadders(); ++i)
1434 {
1435 it->AddNodeGo(new JImageMenuEntry(&level.Theme().Ladder(i), &level.Theme().Ladder(i), &OnLadderSubtype, JCAST_S32_TO_VOIDPTR(i)));
1436 }
1437
1438 it->Root();
1439
1440 JImageMenuConfig cfg;
1441 cfg.layout = JIMAGEMENU_SAMELINE;
1442 cfg.trackMouse = true;
1443 cfg.trackKeyboard = false;
1444 cfg.autoEnter = false;
1445 menuLadderSubtype->Pos(HCED_MARGIN, 0);
1446
1447 if (!menuLadderSubtype->Init(cfg))
1448 {
1449 return false;
1450 }
1451
1452 menuLadderSubtype->Menu()->Root();
1453
1454 return true;
1455 }
1456
1457 bool HCed::InitObjectSubtypeMenu()
1458 {
1459 DestroyObjectSubtypeMenu();
1460 menuObjectSubtype = new JImageMenu;
1461
1462 // Adds the options
1463 JTree<JImageMenuEntry *>::Iterator *it = menuObjectSubtype->Menu();
1464 it->Root();
1465
1466 // At least we must have this
1467 it->Data(new JImageMenuEntry(new JImage(*((JImage*)level.Theme().Object(0)[HCODT_NORMAL].Frame(0))),
1468 new JImage(*((JImage*)level.Theme().Object(0)[HCODT_ACQUIRED].Frame(0))),
1469 &OnObjectSubtype,
1470 (void *)0));
1471
1472 // Adds the rest of subtypes
1473 for (s32 i = 1; i < level.Theme().NumObjects(); ++i)
1474 {
1475 it->AddNodeGo(new JImageMenuEntry(new JImage(*((JImage*)level.Theme().Object(i)[HCODT_NORMAL].Frame(0))),
1476 new JImage(*((JImage*)level.Theme().Object(i)[HCODT_ACQUIRED].Frame(0))),
1477 &OnObjectSubtype,
1478 JCAST_S32_TO_VOIDPTR(i)));
1479 }
1480
1481 it->Root();
1482
1483 JImageMenuConfig cfg;
1484 cfg.layout = JIMAGEMENU_SAMELINE;
1485 cfg.trackMouse = true;
1486 cfg.trackKeyboard = false;
1487 cfg.autoEnter = false;
1488 menuObjectSubtype->Pos(HCED_MARGIN, 0);
1489
1490 if (!menuObjectSubtype->Init(cfg))
1491 {
1492 return false;
1493 }
1494
1495 menuObjectSubtype->Menu()->Root();
1496
1497 return true;
1498 }
1499
1500 bool HCed::InitRopeSubtypeMenu()
1501 {
1502 JDELETE(menuRopeSubtype);
1503 menuRopeSubtype = new JImageMenu;
1504
1505 // Adds the options
1506 JTree<JImageMenuEntry *>::Iterator *it = menuRopeSubtype->Menu();
1507
1508 // At least we must have this
1509 it->Data(new JImageMenuEntry(&level.Theme().Rope(0)[HCRDT_TOP], &level.Theme().Rope(0)[HCRDT_TOP], &OnRopeSubtype, (void *)0));
1510
1511 // Adds the rest of subtypes
1512 for (s32 i = 1; i < level.Theme().NumRopes(); ++i)
1513 {
1514 it->AddNodeGo(new JImageMenuEntry(&level.Theme().Rope(i)[HCRDT_TOP], &level.Theme().Rope(i)[HCRDT_TOP], &OnRopeSubtype, JCAST_S32_TO_VOIDPTR(i)));
1515 }
1516
1517 it->Root();
1518
1519 JImageMenuConfig cfg;
1520 cfg.layout = JIMAGEMENU_SAMELINE;
1521 cfg.trackMouse = true;
1522 cfg.trackKeyboard = false;
1523 cfg.autoEnter = false;
1524 menuRopeSubtype->Pos(HCED_MARGIN, 0);
1525
1526 if (!menuRopeSubtype->Init(cfg))
1527 {
1528 return false;
1529 }
1530
1531 menuRopeSubtype->Menu()->Root();
1532
1533 return true;
1534 }
1535
1536 bool HCed::InitRopePeriodMenu()
1537 {
1538 JDELETE(menuRopePeriod);
1539 menuRopePeriod = new JTextMenu;
1540
1541 // Crea el menú
1542 JTree<JTextMenuEntry *>::Iterator *it = menuRopePeriod->Menu();
1543
1544 it->Data(new JTextMenuEntry("1", &OnRopePeriod, (void *)1));
1545 it->AddNodeGo(new JTextMenuEntry("2", &OnRopePeriod, (void *)2));
1546 it->AddNodeGo(new JTextMenuEntry("3", &OnRopePeriod, (void *)3));
1547 it->AddNodeGo(new JTextMenuEntry("4", &OnRopePeriod, (void *)4));
1548 it->AddNodeGo(new JTextMenuEntry("5", &OnRopePeriod, (void *)5));
1549 it->AddNodeGo(new JTextMenuEntry("6", &OnRopePeriod, (void *)6));
1550 it->AddNodeGo(new JTextMenuEntry("7", &OnRopePeriod, (void *)7));
1551 it->AddNodeGo(new JTextMenuEntry("8", &OnRopePeriod, (void *)8));
1552 it->AddNodeGo(new JTextMenuEntry("9", &OnRopePeriod, (void *)9));
1553 it->AddNodeGo(new JTextMenuEntry("10", &OnRopePeriod, (void *)10));
1554 it->Root();
1555
1556 JTextMenuConfig cfg;
1557 cfg.font = &fontSmall;
1558 cfg.color.r = 0x00;
1559 cfg.color.g = 0x00;
1560 cfg.color.b = 0x00;
1561 cfg.backColor.r = 0xff;
1562 cfg.backColor.g = 0xcc;
1563 cfg.backColor.b = 0x00;
1564 cfg.hiColor.r = 0xff;
1565 cfg.hiColor.g = 0xff;
1566 cfg.hiColor.b = 0xff;
1567 cfg.hiBackColor.r = 0xff;
1568 cfg.hiBackColor.g = 0xdd;
1569 cfg.hiBackColor.b = 0x00;
1570 cfg.renderMode = JTEXTMENU_SHADED;
1571 cfg.layout = JTEXTMENU_SAMELINE;
1572 cfg.trackKeyboard = true;
1573 cfg.trackMouse = true;
1574 cfg.autoEnter = true;
1575
1576 if (!menuRopePeriod->Init(cfg))
1577 {
1578 return false;
1579 }
1580
1581 menuRopePeriod->Pos(Width() - (12 * HCED_MARGIN), 0);
1582 menuRopePeriod->Menu()->Root();
1583
1584 return true;
1585 }
1586
1587 bool HCed::InitEnemySubtypeMenu()
1588 {
1589 DestroyEnemySubtypeMenu();
1590
1591 for (s32 n = 0; n < HCENEMYTYPE_COUNT; ++n)
1592 {
1593 menuEnemySubtype[n] = new JImageMenu;
1594
1595 // Adds the options
1596 JTree<JImageMenuEntry *>::Iterator *it = menuEnemySubtype[n]->Menu();
1597 it->Root();
1598
1599 it->Data(new JImageMenuEntry(new JImage(*((JImage*)GetEnemySprites((HCEnemyType)n, 0)[HCCDT_STOP].Frame(0))),
1600 new JImage(*((JImage*)GetEnemySprites((HCEnemyType)n, 0)[HCCDT_STOP].Frame(0))),
1601 &OnEnemySubtype, (void *)0));
1602
1603 // Adds the subtypes
1604 for (s32 i = 1; i < GetNumEnemySprites((HCEnemyType)n); ++i)
1605 {
1606 // Scales the normal and highlighted images to fit 20 and 32 pixels, respectively
1607 it->AddNodeGo(new JImageMenuEntry(new JImage(*((JImage*)GetEnemySprites((HCEnemyType)n, i)[HCCDT_STOP].Frame(0))),
1608 new JImage(*((JImage*)GetEnemySprites((HCEnemyType)n, i)[HCCDT_STOP].Frame(0))),
1609 &OnEnemySubtype, JCAST_S32_TO_VOIDPTR(i)));
1610 }
1611
1612 it->Root();
1613
1614 JImageMenuConfig cfg;
1615 cfg.layout = JIMAGEMENU_SAMELINE;
1616 cfg.trackMouse = true;
1617 cfg.trackKeyboard = false;
1618 cfg.autoEnter = false;
1619 menuEnemySubtype[n]->Pos(HCED_MARGIN, 0);
1620
1621 if (!menuEnemySubtype[n]->Init(cfg))
1622 {
1623 return false;
1624 }
1625
1626 menuEnemySubtype[n]->Menu()->Root();
1627 }
1628
1629 return true;
1630 }
1631
1632 bool HCed::InitEnemyTypeMenu()
1633 {
1634 char str[256];
1635
1636 if (!menuEnemyType)
1637 {
1638 for (s32 i = 0; i < HCENEMYTYPE_COUNT; ++i)
1639 {
1640 snprintf(str, sizeof(str), HCED_DATA_DIR "EnemyMenu/%d.tga", i);
1641 //fprintf(stderr, "Loading UI Item " HCED_DATA_DIR "EnemyMenu/%d.tga\n", i);
1642
1643 if (!imgEnemy[i].Load(str))
1644 {
1645 return false;
1646 }
1647
1648 snprintf(str, sizeof(str), HCED_DATA_DIR "EnemyMenu/%d_hi.tga", i);
1649 //fprintf(stderr, "Loading UI Item " HCED_DATA_DIR "EnemyMenu/%d_hi.tga\n", i);
1650
1651 if (!imgEnemyOver[i].Load(str))
1652 {
1653 return false;
1654 }
1655 }
1656 }
1657
1658 JDELETE(menuEnemyType);
1659 menuEnemyType = new JImageMenu;
1660
1661 // Adds the options
1662 JTree<JImageMenuEntry *>::Iterator *it = menuEnemyType->Menu();
1663
1664 it->Data(new JImageMenuEntry(&imgEnemy[HCENEMYTYPE_BALL],
1665 &imgEnemyOver[HCENEMYTYPE_BALL],
1666 &OnEnemyType, (void *)HCENEMYTYPE_BALL));
1667 it->AddNodeGo(new JImageMenuEntry(&imgEnemy[HCENEMYTYPE_RANDOM],
1668 &imgEnemyOver[HCENEMYTYPE_RANDOM],
1669 &OnEnemyType, (void *)HCENEMYTYPE_RANDOM));
1670 it->AddNodeGo(new JImageMenuEntry(&imgEnemy[HCENEMYTYPE_STATIC],
1671 &imgEnemyOver[HCENEMYTYPE_STATIC],
1672 &OnEnemyType, (void *)HCENEMYTYPE_STATIC));
1673 it->AddNodeGo(new JImageMenuEntry(&imgEnemy[HCENEMYTYPE_MAKER],
1674 &imgEnemyOver[HCENEMYTYPE_MAKER],
1675 &OnEnemyType, (void *)HCENEMYTYPE_MAKER));
1676 it->AddNodeGo(new JImageMenuEntry(&imgEnemy[HCENEMYTYPE_CHASER],
1677 &imgEnemyOver[HCENEMYTYPE_CHASER],
1678 &OnEnemyType, (void *)HCENEMYTYPE_CHASER));
1679 it->Root();
1680
1681 JImageMenuConfig cfg;
1682 cfg.layout = JIMAGEMENU_SAMELINE;
1683 cfg.trackMouse = true;
1684 cfg.trackKeyboard = false;
1685 cfg.autoEnter = false;
1686 menuEnemyType->Pos(Width() - (5 * HCED_MARGIN), 0);
1687
1688 if (!menuEnemyType->Init(cfg))
1689 {
1690 return false;
1691 }
1692
1693 menuEnemyType->Menu()->Root();
1694
1695 return true;
1696 }
1697
1698 bool HCed::InitEnemyParam1Menu()
1699 {
1700 JDELETE(menuEnemyParam1);
1701 menuEnemyParam1 = new JTextMenu;
1702
1703 // Crea el menú
1704 JTree<JTextMenuEntry *>::Iterator *it = menuEnemyParam1->Menu();
1705
1706 it->Data(new JTextMenuEntry(" 1 ", &OnEnemyParam1, (void *)1));
1707 it->AddNodeGo(new JTextMenuEntry(" 2 ", &OnEnemyParam1, (void *)2));
1708 it->AddNodeGo(new JTextMenuEntry(" 3 ", &OnEnemyParam1, (void *)3));
1709 it->AddNodeGo(new JTextMenuEntry(" 4 ", &OnEnemyParam1, (void *)4));
1710 it->AddNodeGo(new JTextMenuEntry(" 5 ", &OnEnemyParam1, (void *)5));
1711 it->AddNodeGo(new JTextMenuEntry(" 6 ", &OnEnemyParam1, (void *)6));
1712 it->AddNodeGo(new JTextMenuEntry(" 7 ", &OnEnemyParam1, (void *)7));
1713 it->AddNodeGo(new JTextMenuEntry(" 8 ", &OnEnemyParam1, (void *)8));
1714 it->AddNodeGo(new JTextMenuEntry(" 9 ", &OnEnemyParam1, (void *)9));
1715 it->AddNodeGo(new JTextMenuEntry(" 10 ", &OnEnemyParam1, (void *)10));
1716 it->Root();
1717
1718 JTextMenuConfig cfg;
1719 cfg.font = &fontSmall;
1720 cfg.color.r = 0x00;
1721 cfg.color.g = 0x00;
1722 cfg.color.b = 0x00;
1723 cfg.backColor.r = 0x00;
1724 cfg.backColor.g = 0x00;
1725 cfg.backColor.b = 0xcc;
1726 cfg.hiColor.r = 0xff;
1727 cfg.hiColor.g = 0xff;
1728 cfg.hiColor.b = 0xff;
1729 cfg.hiBackColor.r = 0x00;
1730 cfg.hiBackColor.g = 0x00;
1731 cfg.hiBackColor.b = 0xcc;
1732 cfg.renderMode = JTEXTMENU_SHADED;
1733 cfg.layout = JTEXTMENU_SAMELINE;
1734 cfg.trackKeyboard = true;
1735 cfg.trackMouse = true;
1736 cfg.autoEnter = true;
1737
1738 if (!menuEnemyParam1->Init(cfg))
1739 {
1740 return false;
1741 }
1742
1743 menuEnemyParam1->Pos(Width() - (20 * 20), 32);
1744 menuEnemyParam1->Menu()->Root();
1745
1746 return true;
1747 }
1748
1749 bool HCed::InitEnemyParam2Menu()
1750 {
1751 JDELETE(menuEnemyParam2);
1752 menuEnemyParam2 = new JTextMenu;
1753
1754 // Crea el menú
1755 JTree<JTextMenuEntry *>::Iterator *it = menuEnemyParam2->Menu();
1756
1757 it->Data(new JTextMenuEntry(" 1 ", &OnEnemyParam2, (void *)1));
1758 it->AddNodeGo(new JTextMenuEntry(" 2 ", &OnEnemyParam2, (void *)2));
1759 it->AddNodeGo(new JTextMenuEntry(" 3 ", &OnEnemyParam2, (void *)3));
1760 it->AddNodeGo(new JTextMenuEntry(" 4 ", &OnEnemyParam2, (void *)4));
1761 it->AddNodeGo(new JTextMenuEntry(" 5 ", &OnEnemyParam2, (void *)5));
1762 it->AddNodeGo(new JTextMenuEntry(" 6 ", &OnEnemyParam2, (void *)6));
1763 it->AddNodeGo(new JTextMenuEntry(" 7 ", &OnEnemyParam2, (void *)7));
1764 it->AddNodeGo(new JTextMenuEntry(" 8 ", &OnEnemyParam2, (void *)8));
1765 it->AddNodeGo(new JTextMenuEntry(" 9 ", &OnEnemyParam2, (void *)9));
1766 it->AddNodeGo(new JTextMenuEntry(" 10 ", &OnEnemyParam2, (void *)10));
1767 it->Root();
1768
1769 JTextMenuConfig cfg;
1770 cfg.font = &fontSmall;
1771 cfg.color.r = 0x00;
1772 cfg.color.g = 0x00;
1773 cfg.color.b = 0x00;
1774 cfg.backColor.r = 0x00;
1775 cfg.backColor.g = 0xcc;
1776 cfg.backColor.b = 0x00;
1777 cfg.hiColor.r = 0xff;
1778 cfg.hiColor.g = 0xff;
1779 cfg.hiColor.b = 0xff;
1780 cfg.hiBackColor.r = 0x00;
1781 cfg.hiBackColor.g = 0xcc;
1782 cfg.hiBackColor.b = 0x00;
1783 cfg.renderMode = JTEXTMENU_SHADED;
1784 cfg.layout = JTEXTMENU_SAMELINE;
1785 cfg.trackKeyboard = true;
1786 cfg.trackMouse = true;
1787 cfg.autoEnter = true;
1788
1789 if (!menuEnemyParam2->Init(cfg))
1790 {
1791 return false;
1792 }
1793
1794 menuEnemyParam2->Pos(Width() - (10 * 20), 32);
1795 menuEnemyParam2->Menu()->Root();
1796
1797 return true;
1798 }
1799
1800 bool HCed::InitOpenStoryMenu()
1801 {
1802 HCUtil::FindStories(true);
1803
1804 JDELETE(menuOpenStory);
1805 menuOpenStory = new JTextMenu;
1806
1807 // Crea el menú
1808 JTree<JTextMenuEntry *>::Iterator *it = menuOpenStory->Menu();
1809
1810 if (HCUtil::Stories().size() > 0)
1811 {
1812 it->Data(new JTextMenuEntry(HCUtil::Stories()[0], &OnSelectStory, (void *)0));
1813
1814 for (u32 i = 1; i < HCUtil::Stories().size(); ++i)
1815 {
1816 it->AddNodeGo(new JTextMenuEntry(HCUtil::Stories()[i], &OnSelectStory, JCAST_S32_TO_VOIDPTR(i)));
1817 }
1818
1819 it->AddNodeGo(new JTextMenuEntry("<------>", &OnSelectStory, (void *)-1));
1820 }
1821 else
1822 {
1823 it->Data(new JTextMenuEntry("<------>", &OnSelectStory, (void *)-1));
1824 }
1825
1826 it->Root();
1827
1828 JTextMenuConfig cfg;
1829 cfg.font = &fontSmall;
1830 cfg.lineDistance = 3;
1831 cfg.color.r = 0xff;
1832 cfg.color.g = 0xcc;
1833 cfg.color.b = 0x00;
1834 cfg.backColor.r = 0x00;
1835 cfg.backColor.g = 0x00;
1836 cfg.backColor.b = 0x00;
1837 cfg.hiColor.r = 0xff;
1838 cfg.hiColor.g = 0xff;
1839 cfg.hiColor.b = 0xff;
1840 cfg.hiBackColor.r = 0x00;
1841 cfg.hiBackColor.g = 0x00;
1842 cfg.hiBackColor.b = 0x00;
1843 cfg.renderMode = JTEXTMENU_BLENDED;
1844 cfg.layout = JTEXTMENU_CENTER;
1845 cfg.layoutV = JTEXTMENU_CENTER;
1846 cfg.trackKeyboard = true;
1847 cfg.trackMouse = true;
1848 cfg.autoEnter = false;
1849
1850 if (!menuOpenStory->Init(cfg))
1851 {
1852 return false;
1853 }
1854
1855 menuOpenStory->Pos(Width()/2, Height()/2);
1856 menuOpenStory->Menu()->Root();
1857
1858 return true;
1859 }
1860
1861 bool HCed::InitThemeMenu()
1862 {
1863 if (HCUtil::FindThemes())
1864 {
1865 JDELETE(menuTheme);
1866 menuTheme = new JTextMenu;
1867
1868 // Crea el menú
1869 JTree<JTextMenuEntry *>::Iterator *it = menuTheme->Menu();
1870
1871 it->Data(new JTextMenuEntry(HCUtil::Themes()[0], &OnSelectTheme, 0));
1872 for (u32 i = 1; i < HCUtil::Themes().size(); ++i)
1873 {
1874 it->AddNodeGo(new JTextMenuEntry(HCUtil::Themes()[i], &OnSelectTheme, JCAST_S32_TO_VOIDPTR(i)));
1875 }
1876
1877 it->Root();
1878
1879 JTextMenuConfig cfg;
1880 cfg.font = &fontSmall;
1881 cfg.lineDistance = 3;
1882 cfg.color.r = 0xff;
1883 cfg.color.g = 0xcc;
1884 cfg.color.b = 0x00;
1885 cfg.backColor.r = 0x00;
1886 cfg.backColor.g = 0x00;
1887 cfg.backColor.b = 0x00;
1888 cfg.hiColor.r = 0xff;
1889 cfg.hiColor.g = 0xff;
1890 cfg.hiColor.b = 0xff;
1891 cfg.hiBackColor.r = 0x00;
1892 cfg.hiBackColor.g = 0x00;
1893 cfg.hiBackColor.b = 0x00;
1894 cfg.renderMode = JTEXTMENU_BLENDED;
1895 cfg.layout = JTEXTMENU_CENTER;
1896 cfg.layoutV = JTEXTMENU_CENTER;
1897 cfg.trackKeyboard = true;
1898 cfg.trackMouse = true;
1899 cfg.autoEnter = false;
1900
1901 if (!menuTheme->Init(cfg))
1902 {
1903 return false;
1904 }
1905
1906 menuTheme->Pos(Width()/2, Height()/2);
1907 menuTheme->Menu()->Root();
1908
1909 return true;
1910 }
1911
1912 return false;
1913 }
1914
1915 bool HCed::Draw()
1916 {
1917 bool ret = true;
1918
1919 SDL_FillRect(screen, 0, appBackColor);
1920 level.Draw();
1921 menuMain->Draw();
1922
1923 // Draws the mouse cursor
1924 imgMouse->Draw(MouseX() + imgMouse->Width(), MouseY() + imgMouse->Height());
1925
1926 switch (state)
1927 {
1928 case HCEDSTATE_FLOOR:
1929 ret = DrawFloor();
1930 break;
1931 case HCEDSTATE_CONTFLOOR:
1932 ret = DrawContFloor();
1933 break;
1934 case HCEDSTATE_LADDER:
1935 ret = DrawLadder();
1936 break;
1937 case HCEDSTATE_BAR:
1938 ret = DrawBar();
1939 break;
1940 case HCEDSTATE_BREAK:
1941 ret = DrawBreak();
1942 break;
1943 case HCEDSTATE_OBJECT:
1944 ret = DrawObject();
1945 break;
1946 case HCEDSTATE_ROPE:
1947 ret = DrawRope();
1948 break;
1949 case HCEDSTATE_START:
1950 ret = DrawStart();
1951 break;
1952 case HCEDSTATE_EXIT:
1953 ret = DrawExit();
1954 break;
1955 case HCEDSTATE_ENEMY:
1956 ret = DrawEnemy();
1957 break;
1958 case HCEDSTATE_SAVE:
1959 ret = DrawSave();
1960 break;
1961 case HCEDSTATE_OPENSTORY:
1962 ret = DrawOpenStory();
1963 break;
1964 case HCEDSTATE_APPEXIT:
1965 ret = DrawAppExit();
1966 break;
1967 default:
1968 break;
1969 }
1970
1971 level.levelTimer.Y(13 * 32);
1972 level.levelTimer.Draw();
1973
1974 imgGravity->Y(14 * 32);
1975 imgGravity->Draw();
1976
1977 imgCharVx->Y(15 * 32);
1978 imgCharVx->Draw();
1979
1980 imgCharVy->Y(16 * 32);
1981 imgCharVy->Draw();
1982
1983 imgCharJumpRows->Y(17 * 32);
1984 imgCharJumpRows->Draw();
1985
1986 imgMapSize->Y(18 * 32);
1987 imgMapSize->Draw();
1988
1989 // Swaps buffers!
1990 Flip();
1991
1992 return ret;
1993 }
1994
1995 bool HCed::DrawFloor()
1996 {
1997 menuFloorSubtype->Draw();
1998
1999 return true;
2000 }
2001
2002 bool HCed::DrawContFloor()
2003 {
2004 menuContFloorSubtype->Draw();
2005
2006 return true;
2007 }
2008
2009 bool HCed::DrawLadder()
2010 {
2011 menuLadderSubtype->Draw();
2012
2013 return true;
2014 }
2015
2016 bool HCed::DrawBar()
2017 {
2018 menuBarSubtype->Draw();
2019
2020 return true;
2021 }
2022
2023 bool HCed::DrawBreak()
2024 {
2025 menuBreakSubtype->Draw();
2026
2027 return true;
2028 }
2029
2030 bool HCed::DrawObject()
2031 {
2032 menuObjectSubtype->Draw();
2033
2034 return true;
2035 }
2036
2037 bool HCed::DrawRope()
2038 {
2039 menuRopeSubtype->Draw();
2040 menuRopePeriod->Draw();
2041
2042 return true;
2043 }
2044
2045 bool HCed::DrawStart()
2046 {
2047 menuMainSubtype->Draw();
2048
2049 return true;
2050 }
2051
2052 bool HCed::DrawExit()
2053 {
2054 return true;
2055 }
2056
2057 bool HCed::DrawEnemy()
2058 {
2059 menuEnemyType->Draw();
2060 menuEnemySubtype[enemyType]->Draw();
2061 menuEnemyParam1->Draw();
2062 menuEnemyParam2->Draw();
2063
2064 return true;
2065 }
2066
2067 bool HCed::DrawSave()
2068 {
2069
2070
2071 return true;
2072 }
2073
2074 bool HCed::DrawOpenStory()
2075 {
2076 switch (inputNewStory)
2077 {
2078 case 0:
2079 // Selecting story
2080 menuOpenStory->Draw();
2081 break;
2082
2083 case HCED_INPUT_STORY:
2084 // Input of new story name
2085 if (imgNewStory)
2086 {
2087 imgNewStory->Draw();
2088 }
2089 break;
2090
2091 case HCED_INPUT_THEME:
2092 // Selection of theme
2093 if (imgNewStory)
2094 {
2095 imgNewStory->Draw();
2096 }
2097
2098 menuTheme->Draw();
2099 break;
2100 }
2101
2102 return true;
2103 }
2104
2105 bool HCed::DrawAppExit()
2106 {
2107
2108
2109 return true;
2110 }
2111
2112 bool HCed::Update()
2113 {
2114 menuMain->Update();
2115
2116 // Updates the objects
2117 for (s32 i = 0; i < level.numObjects; ++i)
2118 {
2119 level.objects[i]->Update();
2120 }
2121
2122 // Updates the ropes
2123 for (s32 i = 0; i < level.numRopes; ++i)
2124 {
2125 level.ropes[i]->Update();
2126 }
2127
2128 // Updates the enemies
2129 //for (s32 i = 0; i < level.numEnemies; ++i)
2130 //{
2131 // level.enemies[i]->Update();
2132 //}
2133
2134 // Updates the exit
2135 level.levelExit.Update();
2136
2137 switch (state)
2138 {
2139 case HCEDSTATE_FLOOR:
2140 return UpdateFloor();
2141 case HCEDSTATE_CONTFLOOR:
2142 return UpdateContFloor();
2143 case HCEDSTATE_LADDER:
2144 return UpdateLadder();
2145 case HCEDSTATE_BAR:
2146 return UpdateBar();
2147 case HCEDSTATE_BREAK:
2148 return UpdateBreak();
2149 case HCEDSTATE_OBJECT:
2150 return UpdateObject();
2151 case HCEDSTATE_ROPE:
2152 return UpdateRope();
2153 case HCEDSTATE_START:
2154 return UpdateStart();
2155 case HCEDSTATE_EXIT:
2156 return UpdateExit();
2157 case HCEDSTATE_ENEMY:
2158 return UpdateEnemy();
2159 case HCEDSTATE_SAVE:
2160 return UpdateSave();
2161 case HCEDSTATE_OPENSTORY:
2162 return UpdateOpenStory();
2163 case HCEDSTATE_APPEXIT:
2164 return UpdateAppExit();
2165
2166 default:
2167 break;
2168 }
2169
2170 return true;
2171 }
2172
2173 void HCed::UpdateEraseFloor()
2174 {
2175 if (MouseBt() & SDL_BUTTON_RIGHT)
2176 {
2177 s32 row = level.Map().ToRow(MouseY()), col = level.Map().ToCol(MouseX());
2178
2179 // Put a blank cell border around the map, do no let edit those cells
2180 if (row > 0 && col > 0 && row < level.Map().Rows() - 1 && col < level.Map().Cols() - 1)
2181 {
2182 HCCell ***cells = level.Map().Cells();
2183 float x = cells[row][col]->X(), y = cells[row][col]->Y();
2184
2185 // Erases the floor
2186 JDELETE(cells[row][col]);
2187 cells[row][col] = new HCCell;
2188 level.Map().BuildContFloor(row, col);
2189 cells[row][col]->Subtype(0);
2190 cells[row][col]->Pos((s32)x, (s32)y);
2191 level.Map().BuildCellLinkList();
2192 }
2193 }
2194 }
2195
2196 bool HCed::UpdateFloor()
2197 {
2198 // Button down
2199 if (MouseOverMap())
2200 {
2201 if (MouseBt() & SDL_BUTTON_LEFT)
2202 {
2203 s32 row = level.Map().ToRow(MouseY()), col = level.Map().ToCol(MouseX());
2204
2205 // Put a blank cell border around the map, do no let edit those cells
2206 if (row > 0 && col > 0 && row < level.Map().Rows() - 1 && col < level.Map().Cols() - 1)
2207 {
2208 HCCell ***cells = level.Map().Cells();
2209 float x = cells[row][col]->X(), y = cells[row][col]->Y();
2210
2211 if (cells[row][col]->Type() != HCCELLTYPE_FLOOR ||
2212 cells[row][col]->Subtype() != floorSubtype)
2213 {
2214 // Substitutes the floor
2215 JDELETE(cells[row][col]);
2216 cells[row][col] = new HCFloorCell(&level.Theme().Floor(floorSubtype));
2217 cells[row][col]->Subtype(floorSubtype);
2218 cells[row][col]->Pos((s32)x, (s32)y);
2219 }
2220
2221 level.Map().BuildContFloor(row, col);
2222 level.Map().BuildCellLinkList();
2223 }
2224 }
2225 else
2226 {
2227 UpdateEraseFloor();
2228 }
2229 }
2230
2231 return true;
2232 }
2233
2234 bool HCed::UpdateContFloor()
2235 {
2236 // Button down
2237 if (MouseOverMap())
2238 {
2239 if (MouseBt() & SDL_BUTTON_LEFT)
2240 {
2241 s32 row = level.Map().ToRow(MouseY()), col = level.Map().ToCol(MouseX());
2242
2243 // Put a blank cell border around the map, do no let edit those cells
2244 if (row > 0 && col > 0 && row < level.Map().Rows() - 1 && col < level.Map().Cols() - 1)
2245 {
2246 HCCell ***cells = level.Map().Cells();
2247 float x = cells[row][col]->X(), y = cells[row][col]->Y();
2248
2249 if (cells[row][col]->Type() != HCCELLTYPE_CONTFLOOR ||
2250 cells[row][col]->Subtype() != contFloorSubtype)
2251 {
2252 // Substitutes the floor
2253 JDELETE(cells[row][col]);
2254 cells[row][col] = new HCContFloor;
2255 cells[row][col]->Subtype(contFloorSubtype);
2256 level.Map().BuildContFloor(row, col);
2257 cells[row][col]->Pos((s32)x, (s32)y);
2258 level.Map().BuildCellLinkList();
2259 }
2260 }
2261 }
2262 else
2263 {
2264 UpdateEraseFloor();
2265 }
2266 }
2267
2268 return true;
2269 }
2270
2271 bool HCed::UpdateLadder()
2272 {
2273 // Button down
2274 if (MouseOverMap())
2275 {
2276 if (MouseBt() & SDL_BUTTON_LEFT)
2277 {
2278 s32 row = level.Map().ToRow(MouseY()), col = level.Map().ToCol(MouseX());
2279
2280 // Put a blank cell border around the map, do no let edit those cells
2281 if (row > 0 && col > 0 && row < level.Map().Rows() - 1 && col < level.Map().Cols() - 1)
2282 {
2283 HCCell ***cells = level.Map().Cells();
2284 float x = cells[row][col]->X(), y = cells[row][col]->Y();
2285
2286 if (cells[row][col]->Type() != HCCELLTYPE_LADDER ||
2287 cells[row][col]->Subtype() != ladderSubtype)
2288 {
2289 // Substitutes the ladder
2290 JDELETE(cells[row][col]);
2291 cells[row][col] = new HCLadderCell(&level.Theme().Ladder(ladderSubtype));
2292 cells[row][col]->Subtype(ladderSubtype);
2293 cells[row][col]->Pos((s32)x, (s32)y);
2294 level.Map().BuildCellLinkList();
2295 }
2296
2297 level.Map().BuildContFloor(row, col);
2298 }
2299 }
2300 else
2301 {
2302 UpdateEraseFloor();
2303 }
2304 }
2305
2306 return true;
2307 }
2308
2309 bool HCed::UpdateBar()
2310 {
2311 // Button down
2312 if (MouseOverMap())
2313 {
2314 if (MouseBt() & SDL_BUTTON_LEFT)
2315 {
2316 s32 row = level.Map().ToRow(MouseY()), col = level.Map().ToCol(MouseX());
2317
2318 // Put a blank cell border around the map, do no let edit those cells
2319 if (row > 0 && col > 0 && row < level.Map().Rows() - 1 && col < level.Map().Cols() - 1)
2320 {
2321 HCCell ***cells = level.Map().Cells();
2322 float x = cells[row][col]->X(), y = cells[row][col]->Y();
2323
2324 if (cells[row][col]->Type() != HCCELLTYPE_BAR ||
2325 cells[row][col]->Subtype() != barSubtype)
2326 {
2327 // Substitutes the bar
2328 JDELETE(cells[row][col]);
2329 cells[row][col] = new HCBarCell(&level.Theme().Bar(barSubtype));
2330 cells[row][col]->Subtype(barSubtype);
2331 cells[row][col]->Pos((s32)x, (s32)y);
2332 }
2333
2334 level.Map().BuildContFloor(row, col);
2335 level.Map().BuildCellLinkList();
2336 }
2337 }
2338 else
2339 {
2340 UpdateEraseFloor();
2341 }
2342 }
2343
2344 return true;
2345 }
2346
2347 bool HCed::UpdateBreak()
2348 {
2349 // Button down
2350 if (MouseOverMap())
2351 {
2352 if (MouseBt() & SDL_BUTTON_LEFT)
2353 {
2354 s32 row = level.Map().ToRow(MouseY()), col = level.Map().ToCol(MouseX());
2355
2356 // Put a blank cell border around the map, do no let edit those cells
2357 if (row > 0 && col > 0 && row < level.Map().Rows() - 1 && col < level.Map().Cols() - 1)
2358 {
2359 HCCell ***cells = level.Map().Cells();
2360 float x = cells[row][col]->X(), y = cells[row][col]->Y();
2361
2362 if (cells[row][col]->Type() != HCCELLTYPE_BREAK ||
2363 cells[row][col]->Subtype() != breakSubtype)
2364 {
2365 // Substitutes the cell
2366 JDELETE(cells[row][col]);
2367 cells[row][col] = new HCBreak(level.Theme().Break(breakSubtype));
2368 cells[row][col]->Subtype(breakSubtype);
2369 cells[row][col]->Pos((s32)x, (s32)y);
2370 }
2371
2372 level.Map().BuildContFloor(row, col);
2373 level.Map().BuildCellLinkList();
2374 }
2375 }
2376 else
2377 {
2378 UpdateEraseFloor();
2379 }
2380 }
2381
2382 return true;
2383 }
2384
2385 bool HCed::UpdateObject()
2386 {
2387 // Button down
2388 if (MouseOverMap())
2389 {
2390 if (MouseBt() & SDL_BUTTON_LEFT)
2391 {
2392 if (curObject != 0)
2393 {
2394 // An object is selected
2395 if (KeyMods() & KMOD_CTRL)
2396 {
2397 // Adjust to map cell
2398 s32 row = level.Map().ToRow(MouseY()), col = level.Map().ToCol(MouseX());
2399 curObject->Pos(level.Map().ToX(col), level.Map().ToY(row));
2400 }
2401 else
2402 {
2403 // Place the object right bellow the mouse cursor
2404 curObject->Pos(MouseX(), MouseY());
2405 }
2406 }
2407 else
2408 {
2409 // No selected object, create it
2410 AddObject(MouseX(), MouseY());
2411 }
2412 }
2413 else
2414 // Erase object
2415 if (MouseBt() & SDL_BUTTON_RIGHT)
2416 {
2417 // Delete the current object
2418 DeleteObject();
2419 }
2420 }
2421
2422 return true;
2423 }
2424
2425 bool HCed::UpdateRope()
2426 {
2427 // Button down
2428 if (MouseOverMap())
2429 {
2430 if (MouseBt() & SDL_BUTTON_LEFT)
2431 {
2432 if (curRope != 0)
2433 {
2434 // A rope is selected
2435 if (KeyMods() & KMOD_CTRL)
2436 {
2437 // Adjust to map cell ('ceiling')
2438 s32 row = level.Map().ToRow(MouseY()), col = level.Map().ToCol(MouseX());
2439 curRope->Pos(level.Map().ToX(col) - level.Map().CellWidth()/2,
2440 level.Map().ToY(row) - level.Map().CellHeight() + 1);
2441 }
2442 else
2443 if (KeyMods() & KMOD_SHIFT)
2444 {
2445 // Adjust the amplitude
2446 s32 amplitude = abs(MouseX() - (s32)curRope->X());
2447 curRope->Init(ropePeriod, amplitude, curRope->Length(), level.Theme());
2448 }
2449 else
2450 if (KeyMods() & KMOD_ALT)
2451 {
2452 // Adjust the length
2453 s32 length = abs(MouseY() - (s32)curRope->Y());
2454 curRope->Init(ropePeriod, curRope->Amplitude(), length, level.Theme());
2455 }
2456 else
2457 {
2458 // Place the rope right bellow the mouse cursor
2459 curRope->Pos(MouseX(), MouseY());
2460 }
2461 }
2462 else
2463 {
2464 // No selected rope, create it
2465 AddRope(MouseX(), MouseY());
2466 }
2467 }
2468 else
2469 // Erase rope
2470 if (MouseBt() & SDL_BUTTON_RIGHT)
2471 {
2472 // Delete the current rope
2473 DeleteRope();
2474 }
2475 }
2476
2477 return true;
2478 }
2479
2480 bool HCed::UpdateStart()
2481 {
2482 if (MouseOverMap())
2483 {
2484 if (MouseBt() & SDL_BUTTON_LEFT)
2485 {
2486 HCMap *m = &level.Map();
2487
2488 if ((KeyMods() & KMOD_CTRL))
2489 {
2490 s32 row = m->ToRow(MouseY()), col = m->ToCol(MouseX());
2491 level.character.Pos(m->ToX(col), m->ToY(row));
2492 }
2493 else
2494 {
2495 level.character.Pos(MouseX(), MouseY());
2496 }
2497 }
2498 }
2499
2500 return true;
2501 }
2502
2503 bool HCed::UpdateExit()
2504 {
2505 if (MouseOverMap())
2506 {
2507 if (MouseBt() & SDL_BUTTON_LEFT)
2508 {
2509 HCMap *m = &level.Map();
2510 s32 row = m->ToRow(MouseY()), col = m->ToCol(MouseX());
2511 if (m->ExitRow() != row || m->ExitCol() != col)
2512 {
2513 m->ExitRow(row);
2514 m->ExitCol(col);
2515 level.levelExit.Init(m, 100);
2516 }
2517 }
2518 }
2519
2520 return true;
2521 }
2522
2523 bool HCed::UpdateEnemy()
2524 {
2525 // Button down
2526 if (MouseOverMap())
2527 {
2528 if (MouseBt() & SDL_BUTTON_LEFT)
2529 {
2530 if (curEnemy != 0)
2531 {
2532 // An enemy is selected
2533 if (KeyMods() & KMOD_CTRL)
2534 {
2535 // Adjust to map cell
2536 s32 row = level.Map().ToRow(MouseY()), col = level.Map().ToCol(MouseX());
2537 curEnemy->Pos(level.Map().ToX(col), level.Map().ToY(row));
2538 }
2539 else
2540 {
2541 // Place the enemy right bellow the mouse cursor
2542 curEnemy->Pos(MouseX(), MouseY());
2543 }
2544
2545 curEnemy->Param1(enemyParam1);
2546 curEnemy->Param2(enemyParam2);
2547 }
2548 else
2549 {
2550 // No selected enemy, create it
2551 AddEnemy(MouseX(), MouseY());
2552 }
2553 }
2554 else
2555 // Erase enemy
2556 if (MouseBt() & SDL_BUTTON_RIGHT)
2557 {
2558 // Delete the current enemy
2559 DeleteEnemy();
2560 }
2561 }
2562
2563 return true;
2564 }
2565
2566 bool HCed::UpdateSave()
2567 {
2568
2569
2570 return true;
2571 }
2572
2573 bool HCed::UpdateOpenStory()
2574 {
2575 switch (inputNewStory)
2576 {
2577 case 0:
2578 // Only updates if not waiting for user input on new story
2579 menuOpenStory->Update();
2580 break;
2581
2582 case 2:
2583 menuTheme->Update();
2584 break;
2585
2586 default:
2587 break;
2588 }
2589
2590 return true;
2591 }
2592
2593 bool HCed::UpdateAppExit()
2594 {
2595
2596
2597 return true;
2598 }
2599
2600 void HCed::OnFilenameChange()
2601 {
2602 JString strTitle;
2603 strTitle.Format("%s - HCed v1.0", filename.Str());
2604 Title(strTitle);
2605 }
2606
2607 void HCed::OnGravityChange()
2608 {
2609 SDL_Color c;
2610
2611 float maxG = theApp->level.Map().CellHeight()/5.0f;
2612
2613 // Forces the gravity value to be between maxG and -maxG
2614 float g = theApp->level.Map().Gravity();
2615 JClamp(g, -maxG, maxG);
2616 theApp->level.Map().Gravity(g);
2617
2618 // Positive values tend to green, negative ones tend to red.
2619 c.unused = 255;
2620 c.b = 0;
2621 c.g = (u8)(255 * ((g + maxG)/(2.0f * maxG)));
2622 c.r = 255 - c.g;
2623
2624 JDELETE(theApp->imgGravity);
2625 theApp->imgGravity = theApp->fontSmall.PrintfBlended(JFONTALIGN_LEFT, c, "g: %1.1f", theApp->level.Map().Gravity());
2626 }
2627
2628 void HCed::OnCharVxChange()
2629 {
2630 SDL_Color c;
2631
2632 float maxVx = theApp->level.Map().CellWidth() - 1;
2633
2634 // Forces the Vx value to be between maxVx and 0
2635 float v = theApp->level.character.MaxVeloccity().x;
2636 JClamp(v, 0.0f, maxVx);
2637 theApp->level.character.MaxVeloccity().x = v;
2638
2639 // Greater values tend to yellow, small ones tend to grey.
2640 c.unused = 255;
2641 c.b = 127 + (u8)(255 * (v/(2.0f * maxVx)));
2642 c.r = c.g;
2643 c.g = 127;
2644
2645 JDELETE(theApp->imgCharVx);
2646 theApp->imgCharVx = theApp->fontSmall.PrintfBlended(JFONTALIGN_LEFT, c, "vX:%1.1f", theApp->level.character.MaxVeloccity().x);
2647 }
2648
2649 void HCed::OnCharVyChange()
2650 {
2651 SDL_Color c;
2652
2653 float maxVy = theApp->level.Map().CellWidth() - 1;
2654
2655 // Forces the Vy value to be between maxVy and 0
2656 float v = theApp->level.character.MaxVeloccity().y;
2657 JClamp(v, 0.0f, maxVy);
2658 theApp->level.character.MaxVeloccity().y = v;
2659
2660 // Greater values tend to yellow, small ones tend to grey.
2661 c.unused = 255;
2662 c.g = 127 + (u8)(255 * (v/(2.0f * maxVy)));
2663 c.r = c.g;
2664 c.b = 127;
2665
2666 JDELETE(theApp->imgCharVy);
2667 theApp->imgCharVy = theApp->fontSmall.PrintfBlended(JFONTALIGN_LEFT, c, "vY:%1.1f", theApp->level.character.MaxVeloccity().y);
2668 }
2669
2670 void HCed::OnCharJumpRowsChange()
2671 {
2672 SDL_Color c;
2673
2674 s32 maxJ = theApp->level.Map().Rows();
2675
2676 // Forces the jump value to be between maxJ and 0
2677 s32 j = theApp->level.character.MaxJumpRows();
2678 JClamp(j, 0, maxJ);
2679 theApp->level.character.MaxJumpRows(j);
2680
2681 // Greater values tend to light blue, small ones tend to dark blue.
2682 c.unused = 255;
2683 c.b = 127 + (u8)(255 * (j/(2.0f * maxJ)));
2684 c.r = c.b/2;
2685 c.g = 127;
2686
2687 JDELETE(theApp->imgCharJumpRows);
2688 theApp->imgCharJumpRows = theApp->fontSmall.PrintfBlended(JFONTALIGN_LEFT, c, "Jump:%d", theApp->level.character.MaxJumpRows());
2689 }
2690
2691 void HCed::OnMapSizeChange()
2692 {
2693 SDL_Color c;
2694
2695 c.unused = 255;
2696 c.r = 0xff;
2697 c.b = 0xcc;
2698 c.g = 0x00;
2699
2700 JDELETE(theApp->imgMapSize);
2701 theApp->imgMapSize = theApp->fontSmall.PrintfBlended(JFONTALIGN_LEFT,
2702 c,
2703 "Map: %dx%d",
2704 theApp->level.map.Rows(),
2705 theApp->level.map.Cols());
2706 }
2707
2708 void HCed::OnFloor(void *data)
2709 {
2710 theApp->state = HCEDSTATE_FLOOR;
2711 theApp->imgMouse = &theApp->level.Theme().Floor(theApp->floorSubtype);
2712 }
2713
2714 void HCed::OnContFloor(void *data)
2715 {
2716 theApp->state = HCEDSTATE_CONTFLOOR;
2717 theApp->imgMouse = &theApp->imgMenu[theApp->state];
2718 }
2719
2720 void HCed::OnLadder(void *data)
2721 {
2722 theApp->state = HCEDSTATE_LADDER;
2723 theApp->imgMouse = &theApp->imgMenu[theApp->state];
2724 }
2725
2726 void HCed::OnBar(void *data)
2727 {
2728 theApp->state = HCEDSTATE_BAR;
2729 theApp->imgMouse = &theApp->imgMenu[theApp->state];
2730 }
2731
2732 void HCed::OnBreak(void *data)
2733 {
2734 theApp->state = HCEDSTATE_BREAK;
2735 theApp->imgMouse = &theApp->imgMenu[theApp->state];
2736 }
2737
2738 void HCed::OnObject(void *data)
2739 {
2740 theApp->state = HCEDSTATE_OBJECT;
2741 theApp->imgMouse = &theApp->imgMenu[theApp->state];
2742 }
2743
2744 void HCed::OnRope(void *data)
2745 {
2746 theApp->state = HCEDSTATE_ROPE;
2747 theApp->imgMouse = &theApp->imgMenu[theApp->state];
2748 }
2749
2750 void HCed::OnStart(void *data)
2751 {
2752 theApp->state = HCEDSTATE_START;
2753 theApp->imgMouse = &theApp->imgMenu[theApp->state];
2754 }
2755
2756 void HCed::OnExit(void *data)
2757 {
2758 theApp->state = HCEDSTATE_EXIT;
2759 theApp->imgMouse = &theApp->imgMenu[theApp->state];
2760 }
2761
2762 void HCed::OnEnemy(void *data)
2763 {
2764 theApp->state = HCEDSTATE_ENEMY;
2765 theApp->imgMouse = &theApp->imgMenu[theApp->state];
2766 }
2767
2768 void HCed::OnSave(void *data)
2769 {
2770 HCedState old = theApp->state;
2771 theApp->state = HCEDSTATE_SAVE;
2772 theApp->imgMouse = &theApp->imgMenu[theApp->state];
2773 theApp->Draw();
2774
2775 // Save in the command line-given file.
2776 JRW file;
2777
2778 if (file.Create(theApp->filename, "wb"))
2779 {
2780 fprintf(stderr, "Saving the level to %s.\n", theApp->filename.Str());
2781
2782 if (0 != theApp->level.Save(file))
2783 {
2784 fprintf(stderr, "Could not save the level to %s.\n", theApp->filename.Str());
2785 }
2786
2787 file.Close();
2788 }
2789 else
2790 {
2791 fprintf(stderr, "Could not open file %s.\n", theApp->filename.Str());
2792 }
2793
2794 // Return to the old state
2795 theApp->state = old;
2796 theApp->imgMouse = &theApp->imgMenu[theApp->state];
2797 }
2798
2799 void HCed::OnOpenStory(void *data)
2800 {
2801 theApp->state = HCEDSTATE_OPENSTORY;
2802 theApp->imgMouse = &theApp->imgMenu[theApp->state];
2803 theApp->strNewStoryName = "";
2804 }
2805
2806 void HCed::OnSelectStory(void *data)
2807 {
2808 if ((long)data < 0)
2809 {
2810 theApp->inputNewStory = HCED_INPUT_STORY;
2811
2812 // Updates the input string
2813 JDELETE(theApp->imgNewStory);
2814 SDL_Color fg = {0xff, 0xcc, 0x00, 0x00};
2815 SDL_Color bg = {0x00, 0x00, 0x00, 0x00};
2816 theApp->imgNewStory = theApp->fontLarge.RenderTextShaded("Name: ", fg, bg);
2817 }
2818 else
2819 {
2820 theApp->OnFloor(0);
2821 theApp->filename = JString(theApp->storyDir) + JString(HCUtil::Stories()[(long)data]) + "/level001.hlv";
2822
2823 if (0 != theApp->NewLevel())
2824 {
2825 fprintf(stderr, "Error loading %s\n", theApp->filename.Str());
2826 return;
2827 }
2828
2829 theApp->storyName = HCUtil::Stories()[(long)data];
2830 theApp->levelNumber = 1;
2831 }
2832 }
2833
2834 void HCed::OnSelectTheme(void *data)
2835 {
2836 s32 rt = HCUtil::CreateStory(theApp->strNewStoryName);
2837
2838 switch (rt)
2839 {
2840 case 0:
2841 {
2842 // Creates new story
2843 JString oldName = theApp->filename;
2844 JString oldTheme = theApp->themeName;
2845 s32 oldLevel = theApp->levelNumber;
2846 theApp->filename = JString(theApp->storyDir) + JString(theApp->strNewStoryName) + JString("/level001.hlv");
2847 theApp->themeName = HCUtil::Themes()[(long)data];
2848 theApp->levelNumber = 1;
2849
2850 if (0 != theApp->NewLevel())
2851 {
2852 fprintf(stderr, "Error initializing new level %s\n", (const char *)theApp->filename);
2853 theApp->filename = oldName;
2854 theApp->themeName = oldTheme;
2855 theApp->levelNumber = oldLevel;
2856 }
2857 else
2858 {
2859 // All went right
2860 JDELETE(theApp->imgNewStory);
2861 theApp->storyName = theApp->strNewStoryName;
2862 theApp->inputNewStory = 0;
2863 }
2864 }
2865 break;
2866
2867 case 1: fprintf(stderr, "Story %s already exists, give it a different name, please.\n", (const char *)theApp->strNewStoryName); break;
2868 case 2: fprintf(stderr, "Directory 'stories' could not be found, check installation.\n"); break;
2869 case 3: fprintf(stderr, "Couldn't create story. Check permissions for %s.\n", (const char *)theApp->strNewStoryName); break;
2870 default:
2871 break;
2872 }
2873 }
2874
2875 void HCed::OnAppExit(void *data)
2876 {
2877 theApp->state = HCEDSTATE_APPEXIT;
2878 theApp->imgMouse = &theApp->imgMenu[theApp->state];
2879 theApp->Exit();
2880 }
2881
2882 void HCed::OnMainSubtype(void *data)
2883 {
2884 theApp->level.character.subtype = (long)data;
2885 theApp->level.character.Init(theApp->level.theme.MainChar((long)data), &theApp->level.map);
2886 }
2887
2888 void HCed::OnFloorSubtype(void *data)
2889 {
2890 theApp->floorSubtype = (long)data;
2891 theApp->imgMouse = &(theApp->level.Theme().Floor(theApp->floorSubtype));
2892 }
2893
2894 void HCed::OnContFloorSubtype(void *data)
2895 {
2896 theApp->contFloorSubtype = (long)data;
2897 theApp->imgMouse = &(theApp->level.Theme().ContFloor(theApp->contFloorSubtype)[HCFDT_I]);
2898 }
2899
2900 void HCed::OnBarSubtype(void *data)
2901 {
2902 theApp->barSubtype = (long)data;
2903 theApp->imgMouse = &(theApp->level.Theme().Bar(theApp->barSubtype));
2904 }
2905
2906 void HCed::OnLadderSubtype(void *data)
2907 {
2908 theApp->ladderSubtype = (long)data;
2909 theApp->imgMouse = &(theApp->level.Theme().Ladder(theApp->ladderSubtype));
2910 }
2911
2912 void HCed::OnBreakSubtype(void *data)
2913 {
2914 theApp->breakSubtype = (long)data;
2915 theApp->imgMouse = (JImage *)(theApp->level.Theme().Break(theApp->breakSubtype)[HCBDT_NORMAL].Frame(0));
2916 }
2917
2918 void HCed::OnObjectSubtype(void *data)
2919 {
2920 theApp->objectSubtype = (long)data;
2921 theApp->imgMouse = (JImage *)(theApp->level.Theme().Object(theApp->objectSubtype)[HCODT_NORMAL].Frame(0));
2922 }
2923
2924 void HCed::OnRopeSubtype(void *data)
2925 {
2926 theApp->ropeSubtype = (long)data;
2927 theApp->imgMouse = &(theApp->level.Theme().Rope(theApp->ropeSubtype)[HCRDT_TOP]);
2928 }
2929
2930 void HCed::OnRopePeriod(void *data)
2931 {
2932 theApp->ropePeriod = 0.5f + (0.25f * float((long)data));
2933 }
2934
2935 void HCed::OnEnemySubtype(void *data)
2936 {
2937 theApp->enemySubtype = (long)data;
2938 theApp->imgMouse = (JImage *)(theApp->GetEnemySprites(theApp->enemyType, theApp->enemySubtype)[HCCDT_STOP].Frame(0));
2939 }
2940
2941 void HCed::OnEnemyType(void *data)
2942 {
2943 // 0 always is a valid subtype so init to that
2944 theApp->enemySubtype = 0;
2945
2946 theApp->enemyType = (HCEnemyType)(long)data;
2947 theApp->imgMouse = (JImage *)(theApp->GetEnemySprites(theApp->enemyType, theApp->enemySubtype)[HCCDT_STOP].Frame(0));
2948 }
2949
2950 void HCed::OnEnemyParam1(void *data)
2951 {
2952 theApp->enemyParam1 = (long)data;
2953 }
2954
2955 void HCed::OnEnemyParam2(void *data)
2956 {
2957 theApp->enemyParam2 = (long)data;
2958 }
2959
2960 bool HCed::MouseOverMap()
2961 {
2962 return (MouseX() > HCED_MARGIN &&
2963 MouseX() < (level.Map().X() + (level.Map().Cols() * level.Map().CellWidth())) &&
2964 MouseY() > HCED_MARGIN &&
2965 MouseY() < (level.Map().Y() + (level.Map().Rows() * level.Map().CellHeight())));
2966 }
2967
2968 void HCed::AddObject(s32 x, s32 y)
2969 {
2970 curObject = new HCObject;
2971
2972 // Update the level objects
2973 HCObject **tmp = level.objects;
2974
2975 level.objects = new HCObject *[level.numObjects + 1];
2976
2977 // Copies the old elements
2978 s32 i = 0;
2979 for (i = 0; i < level.numObjects; ++i)
2980 {
2981 level.objects[i] = tmp[i];
2982 }
2983
2984 // New and last element
2985 level.objects[i] = curObject;
2986
2987 ++level.numObjects;
2988
2989 curObject->Subtype(objectSubtype);
2990 curObject->Init(&level.Theme());
2991 curObject->Pos(x, y);
2992
2993 // If it exists, deletes the old array of pointers (not the pointers inside)
2994 JDELETE_ARRAY(tmp);
2995 }
2996
2997 void HCed::AddRope(s32 x, s32 y)
2998 {
2999 curRope = new HCRope();
3000 curRope->Init(ropePeriod, 0, 0, level.Theme());
3001 curRope->Subtype(ropeSubtype);
3002
3003 // Update the level ropes
3004 HCRope **tmp = level.ropes;
3005
3006 level.ropes = new HCRope *[level.numRopes + 1];
3007
3008 // Copies the old elements
3009 s32 i = 0;
3010 for (i = 0; i < level.numRopes; ++i)
3011 {
3012 level.ropes[i] = tmp[i];
3013 }
3014
3015 // New and last element
3016 level.ropes[i] = curRope;
3017
3018 ++level.numRopes;
3019
3020 curRope->Pos(x, y);
3021
3022 // If it exists, deletes the old array of pointers (not the pointers inside)
3023 JDELETE_ARRAY(tmp);
3024 }
3025
3026 void HCed::AddEnemy(s32 x, s32 y)
3027 {
3028 switch (enemyType)
3029 {
3030 default:
3031 case HCENEMYTYPE_BALL:
3032 curEnemy = new HCEnemyBall();
3033 curEnemy->Init(level.Theme().Ball(enemySubtype), &level.Map());
3034 break;
3035
3036 case HCENEMYTYPE_RANDOM:
3037 curEnemy = new HCEnemyRandom();
3038 curEnemy->Init(level.Theme().Random(enemySubtype), &level.Map());
3039 break;
3040
3041 case HCENEMYTYPE_STATIC:
3042 curEnemy = new HCEnemyStatic();
3043 curEnemy->Init(level.Theme().Static(enemySubtype), &level.Map());
3044 break;
3045
3046 case HCENEMYTYPE_MAKER:
3047 curEnemy = new HCEnemyMaker();
3048 curEnemy->Init(level.Theme().Maker(enemySubtype), &level.Map());
3049 break;
3050
3051 case HCENEMYTYPE_CHASER:
3052 curEnemy = new HCEnemyChaser();
3053 curEnemy->Init(level.Theme().Chaser(enemySubtype), &level.Map());
3054 break;
3055 }
3056
3057 curEnemy->Subtype(enemySubtype);
3058 curEnemy->Param1(enemyParam1);
3059 curEnemy->Param2(enemyParam2);
3060
3061 // Update the level enemies
3062 HCEnemy **tmp = level.enemies;
3063
3064 level.enemies = new HCEnemy *[level.numEnemies + 1];
3065
3066 // Copies the old elements
3067 s32 i = 0;
3068 for (i = 0; i < level.numEnemies; ++i)
3069 {
3070 level.enemies[i] = tmp[i];
3071 }
3072
3073 // New and last element
3074 level.enemies[i] = curEnemy;
3075
3076 ++level.numEnemies;
3077
3078 curEnemy->Pos(x, y);
3079
3080 // If it exists, deletes the old array of pointers (not the pointers inside)
3081 JDELETE_ARRAY(tmp);
3082 }
3083
3084 void HCed::DeleteObject()
3085 {
3086 if (curObject)
3087 {
3088 // Update the level objects
3089 HCObject **tmp = level.objects;
3090
3091 level.objects = new HCObject *[level.numObjects - 1];
3092
3093 // Copies all but the selected object
3094 for (s32 i = 0, newI = 0; i < level.numObjects; ++i, ++newI)
3095 {
3096 if (tmp[i] != curObject)
3097 {
3098 level.objects[newI] = tmp[i];
3099 }
3100 else
3101 {
3102 // Note that tmp is 1 element larger than level.objects
3103 // we have to delay 1 its index after curObject has been found inside of it
3104 --newI;
3105 }
3106 }
3107
3108 --level.numObjects;
3109
3110 // If it exists, deletes the old array of pointers (not the pointers inside)
3111 JDELETE_ARRAY(tmp);
3112
3113 delete curObject;
3114 curObject = 0;
3115 }
3116 }
3117
3118 void HCed::DeleteRope()
3119 {
3120 if (curRope)
3121 {
3122 // Update the level ropes
3123 HCRope **tmp = level.ropes;
3124
3125 level.ropes = new HCRope *[level.numRopes - 1];
3126
3127 // Copies all but the selected rope
3128 for (s32 i = 0, newI = 0; i < level.numRopes; ++i, ++newI)
3129 {
3130 if (tmp[i] != curRope)
3131 {
3132 level.ropes[newI] = tmp[i];
3133 }
3134 else
3135 {
3136 // Note that tmp is 1 element larger than level.ropes
3137 // we have to delay 1 its index after curRope has been found inside of it
3138 --newI;
3139 }
3140 }
3141
3142 --level.numRopes;
3143
3144 // If it exists, deletes the old array of pointers (not the pointers inside)
3145 JDELETE_ARRAY(tmp);
3146
3147 delete curRope;
3148 curRope = 0;
3149 }
3150 }
3151
3152 void HCed::DeleteEnemy()
3153 {
3154 if (curEnemy)
3155 {
3156 // Update the level enemies
3157 HCEnemy **tmp = level.enemies;
3158
3159 level.enemies = new HCEnemy *[level.numEnemies - 1];
3160
3161 // Copies all but the selected enemy
3162 for (s32 i = 0, newI = 0; i < level.numEnemies; ++i, ++newI)
3163 {
3164 if (tmp[i] != curEnemy)
3165 {
3166 level.enemies[newI] = tmp[i];
3167 }
3168 else
3169 {
3170 // Note that tmp is 1 element larger than level.enemies
3171 // we have to delay 1 its index after curEnemy has been found inside of it
3172 --newI;
3173 }
3174 }
3175
3176 --level.numEnemies;
3177
3178 // If it exists, deletes the old array of pointers (not the pointers inside)
3179 JDELETE_ARRAY(tmp);
3180
3181 delete curEnemy;
3182 curEnemy = 0;
3183 }
3184 }
3185
3186 JImageSprite * HCed::GetEnemySprites(HCEnemyType t, s32 s)
3187 {
3188 switch (t)
3189 {
3190 case HCENEMYTYPE_BALL:
3191 return level.theme.Ball(s);
3192
3193 case HCENEMYTYPE_STATIC:
3194 return level.theme.Static(s);
3195
3196 case HCENEMYTYPE_MAKER:
3197 return level.theme.Maker(s);
3198
3199 case HCENEMYTYPE_RANDOM:
3200 return level.theme.Random(s);
3201
3202 case HCENEMYTYPE_CHASER:
3203 return level.theme.Chaser(s);
3204
3205 default:
3206 break;
3207 }
3208
3209 return 0;
3210 }
3211
3212 s32 HCed::GetNumEnemySprites(HCEnemyType t)
3213 {
3214 switch (t)
3215 {
3216 case HCENEMYTYPE_BALL:
3217 return level.theme.NumBalls();
3218
3219 case HCENEMYTYPE_STATIC:
3220 return level.theme.NumStatics();
3221
3222 case HCENEMYTYPE_MAKER:
3223 return level.theme.NumMakers();
3224
3225 case HCENEMYTYPE_RANDOM:
3226 return level.theme.NumRandoms();
3227
3228 case HCENEMYTYPE_CHASER:
3229 return level.theme.NumChasers();
3230
3231 default:
3232 break;
3233 }
3234
3235 return 0;
3236 }
3237
3238 void HCed::DestroyMainSubtypeMenu()
3239 {
3240 if (menuMainSubtype)
3241 {
3242 JImage *img;
3243 JTree<JImageMenuEntry *>::Iterator *it;
3244 it = menuMainSubtype->Menu();
3245 it->Root();
3246
3247 do
3248 {
3249 if (it->Data())
3250 {
3251 img = it->Data()->Image();
3252 JDELETE(img);
3253 img = it->Data()->HiImage();
3254 JDELETE(img);
3255 }
3256 } while (it->Next());
3257
3258 delete menuMainSubtype;
3259 }
3260 }
3261
3262 void HCed::DestroyBreakSubtypeMenu()
3263 {
3264 if (menuBreakSubtype)
3265 {
3266 JImage *img;
3267 JTree<JImageMenuEntry *>::Iterator *it;
3268 it = menuBreakSubtype->Menu();
3269 it->Root();
3270
3271 do
3272 {
3273 if (it->Data())
3274 {
3275 img = it->Data()->Image();
3276 JDELETE(img);
3277 img = it->Data()->HiImage();
3278 JDELETE(img);
3279 }
3280 } while (it->Next());
3281
3282 delete menuBreakSubtype;
3283 }
3284 }
3285
3286 void HCed::DestroyObjectSubtypeMenu()
3287 {
3288 if (menuObjectSubtype)
3289 {
3290 JImage *img;
3291 JTree<JImageMenuEntry *>::Iterator *it;
3292 it = menuObjectSubtype->Menu();
3293 it->Root();
3294
3295 do
3296 {
3297 if (it->Data())
3298 {
3299 img = it->Data()->Image();
3300 JDELETE(img);
3301 img = it->Data()->HiImage();
3302 JDELETE(img);
3303 }
3304 } while (it->Next());
3305
3306 delete menuObjectSubtype;
3307 }
3308 }
3309
3310 void HCed::DestroyEnemySubtypeMenu()
3311 {
3312 JImage *img;
3313 JTree<JImageMenuEntry *>::Iterator *it;
3314
3315 for (s32 n = 0; n < HCENEMYTYPE_COUNT; ++n)
3316 {
3317 if (menuEnemySubtype[n])
3318 {
3319 it = menuEnemySubtype[n]->Menu();
3320 it->Root();
3321
3322 do
3323 {
3324 if (it->Data())
3325 {
3326 img = it->Data()->Image();
3327 JDELETE(img);
3328 img = it->Data()->HiImage();
3329 JDELETE(img);
3330 }
3331 } while (it->Next());
3332
3333 delete menuEnemySubtype[n];
3334 }
3335 }
3336 }
3337
3338 void HCed::DestroyLevelMenus()
3339 {
3340 DestroyMainSubtypeMenu();
3341 DestroyBreakSubtypeMenu();
3342 DestroyObjectSubtypeMenu();
3343 DestroyEnemySubtypeMenu();
3344 }
3345
3346 HCed::~HCed()
3347 {
3348 JDELETE(menuMain);
3349 JDELETE(menuEnemyType);
3350 JDELETE(menuEnemyParam1);
3351 JDELETE(menuEnemyParam2);
3352 JDELETE(menuRopePeriod);
3353 JDELETE(menuFloorSubtype);
3354 JDELETE(menuContFloorSubtype);
3355 JDELETE(menuBarSubtype);
3356 JDELETE(menuLadderSubtype);
3357 JDELETE(menuRopeSubtype);
3358 JDELETE(menuOpenStory);
3359 JDELETE(menuTheme);
3360
3361 DestroyLevelMenus();
3362
3363 JDELETE(imgGravity);
3364 JDELETE(imgCharVx);
3365 JDELETE(imgCharVy);
3366 JDELETE(imgCharJumpRows);
3367 JDELETE(imgMapSize);
3368 }
3369
3370 int main(s32 argc, char **argv)
3371 {
3372 HCed editor;
3373
3374 theApp = &editor;
3375
3376 if (!editor.Init(argc, argv))
3377 {
3378 fprintf(stderr, "Error launching the editor.\n");
3379
3380 return -1;
3381 }
3382
3383 return editor.MainLoop();
3384 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** Level editor for Holotz's Castle.
23 * @file HCed.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 30/05/2004
26 * @version 0.0.1 - 30/05/2004 - First version
27 */
28
29 #ifndef _HCED_INCLUDED
30 #define _HCED_INCLUDED
31
32 #include <JLib/Util/JApp.h>
33 #include <JLib/Graphics/JFont.h>
34 #include <JLib/Graphics/JImage.h>
35 #include <JLib/Graphics/JTextMenu.h>
36 #include <JLib/Graphics/JImageMenu.h>
37 #include <HCUtil.h>
38 #include <HCLevel.h>
39 #include <HCEnemyBall.h>
40 #include <HCEnemyStatic.h>
41 #include <HCEnemyRandom.h>
42 #include <HCEnemyChaser.h>
43 #include <HCEnemyMaker.h>
44 #include <HCPreferences.h>
45 #include <list>
46
47 #define HCED_MARGIN 48 /**< Margin for menus. */
48 #define HCED_REFAPPWIDTH 800 /**< Referential app width, overridable with -f option of JApp. */
49 #define HCED_REFAPPHEIGHT 600 /**< Referential app height, overridable with -f option of JApp. */
50 #define HCED_INPUT_STORY 1 /**< Input new story name. */
51 #define HCED_INPUT_THEME 2 /**< Input theme. */
52
53 /** State of the application.
54 */
55 enum HCedState
56 {
57 HCEDSTATE_FLOOR = 0,
58 HCEDSTATE_CONTFLOOR,
59 HCEDSTATE_LADDER,
60 HCEDSTATE_BAR,
61 HCEDSTATE_BREAK,
62 HCEDSTATE_OBJECT,
63 HCEDSTATE_ROPE,
64 HCEDSTATE_START,
65 HCEDSTATE_EXIT,
66 HCEDSTATE_ENEMY,
67 HCEDSTATE_SAVE,
68 HCEDSTATE_OPENSTORY,
69 HCEDSTATE_APPEXIT,
70 HCEDSTATE_COUNT,
71 };
72
73 /** Level editor for Holotz's Castle.
74 */
75 class HCed : public JApp
76 {
77 HCedState state; /**< State of the app. */
78
79 JImage imgMenu[HCEDSTATE_COUNT]; /**< Main menu images. */
80 JImage imgMenuOver[HCEDSTATE_COUNT]; /**< Main menu over images. */
81 JImage imgEnemy[HCENEMYTYPE_COUNT]; /**< Enemy type menu images. */
82 JImage imgEnemyOver[HCENEMYTYPE_COUNT]; /**< Enemy type menu images. */
83 JImage imgCredits; /**< Credits image. */
84
85 JImage * imgMouse; /**< Current state image. */
86
87 // Application menus
88 JImageMenu *menuMain; /**< Application menu. */
89 JImageMenu *menuEnemyType; /**< Enemy type menu. */
90 JTextMenu *menuEnemyParam1; /**< Enemy param 1 menu. */
91 JTextMenu *menuEnemyParam2; /**< Enemy param 2 menu. */
92 JTextMenu *menuRopePeriod; /**< Rope period menu. */
93 JTextMenu *menuOpenStory; /**< Open story menu. */
94 JTextMenu *menuTheme; /**< Theme menu. */
95 s32 inputNewStory; /**< New story input flag 0 no input, 1 story name, 2 theme select. */
96 JString strNewStoryName; /**< New story input string. */
97 JImage *imgNewStory; /**< New story image. */
98 JString storyDir; /**< Stories directory. */
99
100 // These application menus depend on the level
101 // 'Types' are applied in different ways depending on the action
102 // 'Subtypes' define the representation (in dirs 1, 2, etc.)
103 JImageMenu *menuMainSubtype; /**< Main character subtype menu. */
104 JImageMenu *menuBreakSubtype; /**< Break subtype menu. */
105 JImageMenu *menuObjectSubtype; /**< Object subtype menu. */
106 JImageMenu *menuEnemySubtype[HCENEMYTYPE_COUNT]; /**< Enemy subtype menus. */
107 JImageMenu *menuFloorSubtype; /**< Floor subtype menu. */
108 JImageMenu *menuContFloorSubtype; /**< Continuous floor subtype menu. */
109 JImageMenu *menuBarSubtype; /**< Bar subtype menu. */
110 JImageMenu *menuLadderSubtype; /**< Ladder subtype menu. */
111 JImageMenu *menuRopeSubtype; /**< Rope subtype menu. */
112 u32 appBackColor; /**< Application back color. */
113
114 JImage imgBackground; /**< Background image. */
115
116 HCMap map; /**< Holotz's castle map. */
117 HCLevel level; /**< Holotz's castle level. */
118
119 JString storyName; /**< Name of the story to load/save */
120 JString filename; /**< Full-path name of the file to load/save */
121 JString themeName; /**< Theme name */
122 s32 defRows; /**< Default number of rows. */
123 s32 defCols; /**< Default number of columns. */
124 s32 levelNumber; /**< Level number. */
125
126 HCEnemyType enemyType; /**< Current enemy type. */
127 s32 enemySubtype; /**< Current enemy subtype. */
128 s32 enemyParam1; /**< Current enemy param 1. */
129 s32 enemyParam2; /**< Current enemy param 2. */
130 s32 floorSubtype; /**< Current floor subtype. */
131 s32 contFloorSubtype; /**< Current continuous floor subtype. */
132 s32 breakSubtype; /**< Current break subtype. */
133 s32 barSubtype; /**< Current bar subtype. */
134 s32 ladderSubtype; /**< Current ladder subtype. */
135 s32 objectSubtype; /**< Current object subtype. */
136 s32 ropeSubtype; /**< Current rope subtype. */
137 float ropePeriod; /**< Current rope period. */
138
139 HCObject *curObject; /**< Current edited object. */
140 HCRope *curRope; /**< Current edited rope. */
141 HCEnemy *curEnemy; /**< Current edited enemy. */
142
143 JFont fontSmall; /**< Small font. */
144 JFont fontNormal; /**< Normal font. */
145 JFont fontLarge; /**< Large font. */
146
147 JImage *imgGravity; /**< Map's gravity image. */
148 JImage *imgCharVx; /**< Main character's x veloccity. */
149 JImage *imgCharVy; /**< Main character's y veloccity. */
150 JImage *imgCharJumpRows; /**< Main character's maximum jump rows. */
151 JImage *imgMapSize; /**< Map size image. */
152
153 public:
154 /** Creates the editor. Init() must be called in order to use the object.
155 */
156 HCed();
157
158 /** Initializes the application.
159 * @param argc Argument count from the command line, as in main().
160 * @param argv Argument list from the command line, as in main().
161 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
162 */
163 bool Init(int argc, char **argv);
164
165 /** Initializes a default level.
166 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
167 */
168 bool InitDefaultLevel();
169
170 /** Initializes a loaded level.
171 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
172 */
173 bool InitLoadedLevel();
174
175 /** Initializes the level dependant menus.
176 * @return 0 if initialization succeeded, -1 otherwise.
177 */
178 s32 InitLevelMenus();
179
180 /** Destroy the level dependant menus.
181 */
182 void DestroyLevelMenus();
183
184 /** Initializes the main menu.
185 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
186 */
187 bool InitMainMenu();
188
189 /** Initializes the main character subtype menu.
190 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
191 */
192 bool InitMainSubtypeMenu();
193
194 /** Initializes the floor subtype menu.
195 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
196 */
197 bool InitFloorSubtypeMenu();
198
199 /** Initializes the continuous floor subtype menu.
200 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
201 */
202 bool InitContFloorSubtypeMenu();
203
204 /** Initializes the break subtype menu.
205 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
206 */
207 bool InitBreakSubtypeMenu();
208
209 /** Initializes the bar subtype menu.
210 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
211 */
212 bool InitBarSubtypeMenu();
213
214 /** Initializes the ladder subtype menu.
215 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
216 */
217 bool InitLadderSubtypeMenu();
218
219 /** Initializes the object subtype menu.
220 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
221 */
222 bool InitObjectSubtypeMenu();
223
224 /** Initializes the rope period menu.
225 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
226 */
227 bool InitRopePeriodMenu();
228
229 /** Initializes the rope subtype menu.
230 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
231 */
232 bool InitRopeSubtypeMenu();
233
234 /** Initializes the enemy type menu.
235 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
236 */
237 bool InitEnemyTypeMenu();
238
239 /** Initializes the enemy subtype menu.
240 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
241 */
242 bool InitEnemySubtypeMenu();
243
244 /** Initializes the enemy param 1 menu.
245 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
246 */
247 bool InitEnemyParam1Menu();
248
249 /** Initializes the enemy param 2 menu.
250 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
251 */
252 bool InitEnemyParam2Menu();
253
254 /** Initializes the open story menu.
255 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
256 */
257 bool InitOpenStoryMenu();
258
259
260 /** Initializes the theme menu.
261 * @return <b>true</b> if initialization succeeded, <b>false</b> otherwise.
262 */
263 bool InitThemeMenu();
264
265 /** Destroys the main character subtype menu.
266 */
267 void DestroyMainSubtypeMenu();
268
269 /** Destroys the break subtype menu.
270 */
271 void DestroyBreakSubtypeMenu();
272
273 /** Destroys the object subtype menu.
274 */
275 void DestroyObjectSubtypeMenu();
276
277 /** Destroys the enemy subtype menu.
278 */
279 void DestroyEnemySubtypeMenu();
280
281 /** Draws the application.
282 * @return <b>true</b> if drawing succeeded, <b>false</b> otherwise.
283 */
284 bool Draw();
285
286 /** Draws the application in the FLOOR state.
287 * @return <b>true</b> if drawing succeeded, <b>false</b> otherwise.
288 */
289 bool DrawFloor();
290
291 /** Draws the application in the CONTFLOOR state.
292 * @return <b>true</b> if drawing succeeded, <b>false</b> otherwise.
293 */
294 bool DrawContFloor();
295
296 /** Draws the application in the LADDER state.
297 * @return <b>true</b> if drawing succeeded, <b>false</b> otherwise.
298 */
299 bool DrawLadder();
300
301 /** Draws the application in the BAR state.
302 * @return <b>true</b> if drawing succeeded, <b>false</b> otherwise.
303 */
304 bool DrawBar();
305
306 /** Draws the application in the BREAK state.
307 * @return <b>true</b> if drawing succeeded, <b>false</b> otherwise.
308 */
309 bool DrawBreak();
310
311 /** Draws the application in the OBJECT state.
312 * @return <b>true</b> if drawing succeeded, <b>false</b> otherwise.
313 */
314 bool DrawObject();
315
316 /** Draws the application in the ROPE state.
317 * @return <b>true</b> if drawing succeeded, <b>false</b> otherwise.
318 */
319 bool DrawRope();
320
321 /** Draws the application in the START state.
322 * @return <b>true</b> if drawing succeeded, <b>false</b> otherwise.
323 */
324 bool DrawStart();
325
326 /** Draws the application in the EXIT state.
327 * @return <b>true</b> if drawing succeeded, <b>false</b> otherwise.
328 */
329 bool DrawExit();
330
331 /** Draws the application in the ENEMY state.
332 * @return <b>true</b> if drawing succeeded, <b>false</b> otherwise.
333 */
334 bool DrawEnemy();
335
336 /** Draws the application in the SAVE state.
337 * @return <b>true</b> if drawing succeeded, <b>false</b> otherwise.
338 */
339 bool DrawSave();
340
341 /** Draws the application in the OPENSTORY state.
342 * @return <b>true</b> if drawing succeeded, <b>false</b> otherwise.
343 */
344 bool DrawOpenStory();
345
346 /** Draws the application in the APPEXIT state.
347 * @return <b>true</b> if drawing succeeded, <b>false</b> otherwise.
348 */
349 bool DrawAppExit();
350
351 /** Updates the application.
352 * @return <b>true</b> if update succeeded, <b>false</b> otherwise.
353 */
354 bool Update();
355
356 /** Checks for floor erasing.
357 */
358 void UpdateEraseFloor();
359
360 /** Updates the application in the FLOOR state.
361 * @return <b>true</b> if update succeeded, <b>false</b> otherwise.
362 */
363 bool UpdateFloor();
364
365 /** Updates the application in the CONTFLOOR state.
366 * @return <b>true</b> if update succeeded, <b>false</b> otherwise.
367 */
368 bool UpdateContFloor();
369
370 /** Updates the application in the LADDER state.
371 * @return <b>true</b> if update succeeded, <b>false</b> otherwise.
372 */
373 bool UpdateLadder();
374
375 /** Updates the application in the BAR state.
376 * @return <b>true</b> if update succeeded, <b>false</b> otherwise.
377 */
378 bool UpdateBar();
379
380 /** Updates the application in the BREAK state.
381 * @return <b>true</b> if update succeeded, <b>false</b> otherwise.
382 */
383 bool UpdateBreak();
384
385 /** Updates the application in the OBJECT state.
386 * @return <b>true</b> if update succeeded, <b>false</b> otherwise.
387 */
388 bool UpdateObject();
389
390 /** Updates the application in the ROPE state.
391 * @return <b>true</b> if update succeeded, <b>false</b> otherwise.
392 */
393 bool UpdateRope();
394
395 /** Updates the application in the START state.
396 * @return <b>true</b> if update succeeded, <b>false</b> otherwise.
397 */
398 bool UpdateStart();
399
400 /** Updates the application in the EXIT state.
401 * @return <b>true</b> if update succeeded, <b>false</b> otherwise.
402 */
403 bool UpdateExit();
404
405 /** Updates the application in the ENEMY state.
406 * @return <b>true</b> if update succeeded, <b>false</b> otherwise.
407 */
408 bool UpdateEnemy();
409
410 /** Updates the application in the SAVE state.
411 * @return <b>true</b> if update succeeded, <b>false</b> otherwise.
412 */
413 bool UpdateSave();
414
415 /** Updates the application in the OPENSTORY state.
416 * @return <b>true</b> if update succeeded, <b>false</b> otherwise.
417 */
418 bool UpdateOpenStory();
419
420 /** Updates the application in the APPEXIT state.
421 * @return <b>true</b> if update succeeded, <b>false</b> otherwise.
422 */
423 bool UpdateAppExit();
424
425 /** Process key down events.
426 * @param key Key released.
427 */
428 static void OnKeyDown(SDL_keysym key);
429
430 /** Process key up events.
431 * @param key Key released.
432 */
433 static void OnKeyUp(SDL_keysym key);
434
435 /** Process mouse up events.
436 * @param bt Released button mask.
437 * @param x X position of the release.
438 * @param y Y position of the release.
439 */
440 static void OnMouseUp(s32 bt, s32 x, s32 y);
441
442 /** Process mouse down events.
443 * @param bt Pressed button mask.
444 * @param x X position of the press.
445 * @param y Y position of the press.
446 */
447 static void OnMouseDown(s32 bt, s32 x, s32 y);
448
449 /** Updates the window title.
450 */
451 void OnFilenameChange();
452
453 /** Updates the gravity image.
454 */
455 static void OnGravityChange();
456
457 /** Updates the character' Vx image.
458 */
459 static void OnCharVxChange();
460
461 /** Updates the character' Vy image.
462 */
463 static void OnCharVyChange();
464
465 /** Updates the character' jump rows image.
466 */
467 static void OnCharJumpRowsChange();
468
469 /** Updates the map size image.
470 */
471 static void OnMapSizeChange();
472
473 /** Floor action.
474 * @param data Additional data.
475 */
476 static void OnFloor(void *data);
477
478 /** Continuous floor action.
479 * @param data Additional data.
480 */
481 static void OnContFloor(void *data);
482
483 /** Ladder action.
484 * @param data Additional data.
485 */
486 static void OnLadder(void *data);
487
488 /** Bar action.
489 * @param data Additional data.
490 */
491 static void OnBar(void *data);
492
493 /** Break action.
494 * @param data Additional data.
495 */
496 static void OnBreak(void *data);
497
498 /** Object action.
499 * @param data Additional data.
500 */
501 static void OnObject(void *data);
502
503 /** Rope action.
504 * @param data Additional data.
505 */
506 static void OnRope(void *data);
507
508 /** Start action.
509 * @param data Additional data.
510 */
511 static void OnStart(void *data);
512
513 /** Exit action.
514 * @param data Additional data.
515 */
516 static void OnExit(void *data);
517
518 /** Enemy action.
519 * @param data Additional data.
520 */
521 static void OnEnemy(void *data);
522
523 /** Save action.
524 * @param data Additional data.
525 */
526 static void OnSave(void *data);
527
528 /** OpenStory action.
529 * @param data Additional data.
530 */
531 static void OnOpenStory(void *data);
532
533 /** Story selection action.
534 * @param data Additional data.
535 */
536 static void OnSelectStory(void *data);
537
538 /** Theme selection action.
539 * @param data Additional data.
540 */
541 static void OnSelectTheme(void *data);
542
543 /** AppExit action.
544 * @param data Additional data.
545 */
546 static void OnAppExit(void *data);
547
548 /** Main subtype selection method.
549 * @param data Main subtype casted.
550 */
551 static void OnMainSubtype(void *data);
552
553 /** Floor subtype selection method.
554 * @param data Floor subtype casted.
555 */
556 static void OnFloorSubtype(void *data);
557
558 /** Continuous floor subtype selection method.
559 * @param data Floor subtype casted.
560 */
561 static void OnContFloorSubtype(void *data);
562
563 /** Bar subtype selection method.
564 * @param data Bar subtype casted.
565 */
566 static void OnBarSubtype(void *data);
567
568 /** Ladder subtype selection method.
569 * @param data Ladder subtype casted.
570 */
571 static void OnLadderSubtype(void *data);
572
573 /** Break subtype selection method.
574 * @param data Break subtype casted.
575 */
576 static void OnBreakSubtype(void *data);
577
578 /** Rope subtype selection method.
579 * @param data Rope type casted.
580 */
581 static void OnRopeSubtype(void *data);
582
583 /** Rope period selection method.
584 * @param data Period casted.
585 */
586 static void OnRopePeriod(void *data);
587
588 /** Object subtype selection method.
589 * @param data Subtype casted.
590 */
591 static void OnObjectSubtype(void *data);
592
593 /** Enemy subtype selection method.
594 * @param data Enemy type casted.
595 */
596 static void OnEnemySubtype(void *data);
597
598 /** Enemy type selection method.
599 * @param data Enemy type casted.
600 */
601 static void OnEnemyType(void *data);
602
603 /** Enemy param 1 selection method.
604 * @param data Enemy param 1 casted.
605 */
606 static void OnEnemyParam1(void *data);
607
608 /** Enemy param 2 selection method.
609 * @param data Enemy param 2 casted.
610 */
611 static void OnEnemyParam2(void *data);
612
613 /** Builds the continuous floor at the specified cell. Not performs
614 * update of the surrounding continuous floors.
615 * @param row Row of the continuous floor.
616 * @param col Col of the continuous floor.
617 */
618 void BuildContFloorOnce(s32 row, s32 col);
619
620 /** Builds the continuous floor at the specified cell and updates
621 * the surrounding continuous floors.
622 * @param row Row of the continuous floor.
623 * @param col Col of the continuous floor.
624 */
625 void BuildContFloor(s32 row, s32 col);
626
627 /** Determines whether the mouse is over the map or not.
628 * @return <b>true</b> if the mouse is over, <b>false</b> if not.
629 */
630 inline bool MouseOverMap();
631
632 /** Adds a new object to the level at the given position.
633 * Sets it as the current edited object.
634 */
635 void AddObject(s32 x, s32 y);
636
637 /** Adds a new rope to the level hanging from the given position.
638 * Sets it as the current edited rope.
639 */
640 void AddRope(s32 x, s32 y);
641
642 /** Adds a new enemy to the level in the given position.
643 * Sets it as the current edited enemy.
644 */
645 void AddEnemy(s32 x, s32 y);
646
647 /** Deletes the current object.
648 */
649 void DeleteObject();
650
651 /** Deletes the current rope.
652 */
653 void DeleteRope();
654
655 /** Deletes the current enemy.
656 */
657 void DeleteEnemy();
658
659 /** Returns the enmy corresponding to the given type and subtype
660 * @param t Type of enemy.
661 * @param s Subtype of enemy.
662 * @return requested sprites or 0 if they don't exist.
663 */
664 JImageSprite * GetEnemySprites(HCEnemyType t, s32 s);
665
666 /** Returns the number of enemy subtypes corresponding to the given type.
667 * @param t Type of enemy.
668 * @return The number of subtypes.
669 */
670 s32 GetNumEnemySprites(HCEnemyType t);
671
672 /** Parses argument.
673 * @param args Command line arguments.
674 * @return Number of parameters used.
675 */
676 virtual int ParseArg(char *args[], int argc);
677
678 /** Parses the application arguments.
679 * @param argc Command line argument count.
680 * @param argv Command line arguments.
681 */
682 void ParseArgs(s32 argc, char **argv);
683
684 /** Shows the usage string.
685 */
686 virtual void PrintUsage(char *program);
687
688 /** Loads the level pointed by filename. If it doesn't exist, creates it with the default values.
689 * @return 0 if it was succesfully loaded, -1 if there was an error or 1 if the current level is the first.
690 */
691 s32 LoadLevel();
692
693 /** Loads the next level within the story. If it doesn't exist, creates it with the default values.
694 * @return 0 if it was succesfully loaded, -1 if there was an error.
695 */
696 s32 NextLevel();
697
698 /** Loads the previous level within the story. If it doesn't exist, creates it with the default values.
699 * @return 0 if it was succesfully loaded, -1 if there was an error or 1 if the current level is the first.
700 */
701 s32 PrevLevel();
702
703 /** Loads the level indicated by the member 'filename'.
704 * @return 0 if it was succesfully loaded, -1 if there was an error.
705 */
706 s32 NewLevel();
707
708 /** Destroys the app. Allows scalar destruction.
709 */
710 virtual ~HCed();
711 };
712
713 #endif // _HCED_INCLUDED
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** The game of Holotz's Castle.
23 * @file HolotzCastle.cpp
24 * @author Juan Carlos Seijo Pérez
25 * @date 27/04/2004
26 * @version 0.0.1 - 27/04/2004 - First version.
27 * @version 0.0.2 - 02/01/2005 - Debian package adaptation, Miriam Ruiz.
28 */
29
30 #include <HolotzCastle.h>
31
32 #ifndef HC_DATA_DIR
33 #define HC_DATA_DIR "res/"
34 #endif
35
36 /** This application.
37 */
38 HCApp *theApp;
39
40 void HCApp::OnKeyUp(SDL_keysym key)
41 {
42 switch (theApp->state)
43 {
44 case HCS_PLAYING:
45 switch (key.sym)
46 {
47 case SDLK_ESCAPE:
48 theApp->State(HCS_MENU);
49 theApp->ProcessStateChange();
50 break;
51
52 case SDLK_p:
53 theApp->State(HCS_PAUSED);
54 theApp->ProcessStateChange();
55 break;
56
57 case SDLK_F1:
58 theApp->State(HCS_PAUSED);
59 theApp->ProcessStateChange();
60 theApp->InitHelp();
61 break;
62
63 default:
64 break;
65 } // switch (key)
66 break;
67
68 case HCS_ENDLEVEL:
69 break;
70
71 case HCS_GAMEOVER:
72 switch (key.sym)
73 {
74 // Skip game over screen
75 case SDLK_RETURN:
76 theApp->State(HCS_PLAYING);
77 theApp->ProcessStateChange();
78 break;
79
80 // Goes to main menu
81 case SDLK_ESCAPE:
82 theApp->State(HCS_MENU);
83 theApp->ProcessStateChange();
84 break;
85
86 default:
87 break;
88 }
89 break;
90
91 case HCS_SCRIPT:
92 switch (key.sym)
93 {
94 // Skip script
95 case SDLK_RETURN:
96 theApp->State(HCS_ENDLEVEL);
97 theApp->ProcessStateChange();
98 break;
99
100 case SDLK_SPACE:
101 // Skip current dialog actions in the script
102 {
103 theApp->script.Skip();
104 }
105 break;
106
107 case SDLK_ESCAPE:
108 theApp->State(HCS_MENU);
109 theApp->ProcessStateChange();
110 break;
111
112 case SDLK_p:
113 theApp->State(HCS_PAUSED);
114 theApp->ProcessStateChange();
115 break;
116
117 default:
118 break;
119 }
120 break;
121
122 case HCS_PAUSED:
123 switch (key.sym)
124 {
125 case SDLK_ESCAPE:
126 case SDLK_F1:
127 case SDLK_p:
128 if (theApp->imgHelp)
129 {
130 theApp->DestroyHelp();
131 }
132
133 theApp->State(theApp->lastState);
134 theApp->ProcessStateChange();
135 break;
136
137 default:
138 break;
139 } // switch (key)
140 break;
141
142 case HCS_MENU:
143 if (theApp->imgHelp)
144 {
145 switch (key.sym)
146 {
147 case SDLK_ESCAPE:
148 case SDLK_F1:
149 case SDLK_p:
150 theApp->DestroyHelp();
151 break;
152
153 default:
154 break;
155 }
156 }
157 else
158 {
159 theApp->menu->TrackKeyboard(key);
160 }
161 break;
162
163 default:
164 case HCS_INTRO:
165 case HCS_CREDITS:
166 theApp->State(HCS_MENU);
167 theApp->ProcessStateChange();
168 break;
169 } // switch (appState)
170 }
171
172 HCApp::HCApp() : JApp("Holotz's Castle", 640, 480, false, 16, SDL_HWSURFACE | SDL_DOUBLEBUF)
173 {
174 theApp = this;
175 doInput = true;
176 levelNumber = 1;
177 SetOnKeyUp(&OnKeyUp);
178 imgBack = 0;
179 textBack = 0;
180 imgHelp = 0;
181 imgIntro = 0;
182 textIntro = 0;
183 menu = 0;
184 imgMenu = 0;
185 state = lastState = HCS_INTRO;
186 memset(imgCredits, 0, sizeof(imgCredits));
187 memset(textCredits, 0, sizeof(textCredits));
188 fps = 25;
189 playlistName = 0;
190 stateChanged = false;
191 }
192
193 bool HCApp::Init(s32 argc, char **argv)
194 {
195 // Loads fonts
196 if (!InitFonts())
197 {
198 fprintf(stderr, "Couldn't load fonts.\n");
199 return false;
200 }
201
202 // Tries to get the current preferences
203 if (0 != preferences.Load())
204 {
205 // Generates a new preferences file if it doesn't exist
206 if (0 != preferences.Save())
207 {
208 fprintf(stderr, "Couldn't write preferences file. Check the manual.\n");
209 }
210 }
211 else
212 {
213 depth = preferences.BPP();
214 fullScreen = preferences.Fullscreen();
215 if (preferences.VideoModes())
216 {
217 width = preferences.VideoModes()[preferences.VideoMode()].w;
218 height = preferences.VideoModes()[preferences.VideoMode()].h;
219 }
220 }
221
222 // Sets the icon image name
223 Icon(HC_DATA_DIR "icon/icon.bmp");
224
225 ParseArgs(argc, argv);
226
227 // Tries to get the current playlist
228 if (!playlist.Load(playlistName))
229 {
230 fprintf(stderr, "Couldn't load playlist file. Check the manual.\n");
231 return false;
232 }
233
234 if (!JApp::Init())
235 {
236 return false;
237 }
238
239 if (!InitSound())
240 {
241 fprintf(stderr, "Failed to init sound. Check the manual.\n");
242 }
243 else
244 {
245 SoundEnabled(preferences.Sound());
246 }
247
248 // Quitamos el cursor del ratón
249 MouseCursor(false);
250
251 State(HCS_INTRO);
252 ProcessStateChange();
253
254 return true;
255 }
256
257 bool HCApp::InitSound()
258 {
259 // Initializes the sound
260 return (0 == mixer.Init());
261 }
262
263 bool HCApp::InitFonts()
264 {
265 fontSmall.Destroy();
266 fontMedium.Destroy();
267 fontLarge.Destroy();
268
269 // Loads the fonts according to the resolution
270 if (!JFile::Exists(HC_DATA_DIR "font/font.ttf"))
271 {
272 fprintf(stderr,
273 "Could not find data directory.\n\n"
274 "Posible solutions are:\n"
275 " - Open folder JLib-1.3.1/Games/HolotzCastle and double.\n"
276 " click 'holotz-castle' application icon.\n"
277 " - Maybe you did 'make' but didn't do 'make install'.\n"
278 " - Else, try to reinstall the game.\n");
279 return false;
280 }
281
282 if (JFont::Init() &&
283 fontSmall.Open(HC_DATA_DIR "font/font.ttf", (long)JMax(11, height/35)) &&
284 fontMedium.Open(HC_DATA_DIR "font/font.ttf", (long)JMax(12, height/30)) &&
285 fontLarge.Open(HC_DATA_DIR "font/font.ttf", (long)JMax(13, height/25)))
286 {
287 level.SetTimerFont(&fontLarge);
288 return true;
289 }
290
291 return false;
292 }
293
294 bool HCApp::InitMenu()
295 {
296 // Reflects changes in resolution
297 if (!InitFonts())
298 {
299 fprintf(stderr, "Couldn't load fonts.\n");
300 return false;
301 }
302
303 // Load game slots
304 if (!InitSlots())
305 {
306 fprintf(stderr, "Couldn't load game slots.\n");
307 return false;
308 }
309
310 imgMenu = new JImage;
311
312 if (!imgMenu->Load(HC_DATA_DIR "main/main.tga"))
313 {
314 return false;
315 }
316
317 if (imgMenu->Height() > Height())
318 {
319 float h = float(imgMenu->Height());
320 do
321 {
322 h /= 1.5f;
323 }
324 while (h > Height());
325
326 JImage *tmp = imgMenu;
327 imgMenu = imgMenu->Scale(h/float(imgMenu->Height()), h/float(imgMenu->Height()));
328
329 if (imgMenu)
330 delete tmp;
331 else
332 imgMenu = tmp;
333 }
334
335 imgMenu->Pos((width - imgMenu->Width())/2, (height - imgMenu->Height())/8);
336
337 JDELETE(menu);
338 menu = new JTextMenu;
339
340 // Reads the menu file in the correct language
341 char str[256];
342 snprintf(str, sizeof(str), HC_DATA_DIR "menu/%s/menu.txt", preferences.LangCodes()[preferences.CurLang()]);
343
344 JTextFile f;
345 if (!f.Load(str, "rb"))
346 {
347 return false;
348 }
349
350 // Adds the options
351 JTree<JTextMenuEntry *>::Iterator *it = menu->Menu();
352
353 if (f.ReadLine(str)) it->Data(new JTextMenuEntry(str, &OnContinue, 0)); else return false; // Continue game
354 if (f.ReadLine(str)) it->AddNodeGo(new JTextMenuEntry(str, 0, 0)); else return false; // Play
355 {
356 if (playlist.Size() > 0) it->AddBranchGo(new JTextMenuEntry(playlist[0], &OnNew, 0)); else return false;// Story 1
357
358 for (s32 sn = 1; sn < playlist.Size(); ++sn)
359 {
360 it->AddNodeGo(new JTextMenuEntry(playlist[sn], &OnNew, JCAST_S32_TO_VOIDPTR(sn))); // Story N
361 }
362
363 it->Parent();
364 }
365 if (f.ReadLine(str)) it->AddNodeGo(new JTextMenuEntry(str, &OnHelp, 0)); else return false; // Help
366 if (f.ReadLine(str)) it->AddNodeGo(new JTextMenuEntry(str, 0, 0)); else return false; // Options
367 {
368 if (f.ReadLine(str)) it->AddBranchGo(new JTextMenuEntry(str, 0, 0)); else return false; // Video
369 {
370 if (f.ReadLine(str)) it->AddBranchGo(new JTextMenuEntry(str, 0, 0)); else return false; // Size
371 {
372 // Shows all the supported modes in the current depth
373 if (preferences.NumVideoModes() > 0)
374 {
375 snprintf(str, 128, "%dx%d", preferences.VideoModes()[0].w, preferences.VideoModes()[0].h);
376 it->AddBranchGo(new JTextMenuEntry(str, &OnVideoMode, (void *)0)); // Modes
377
378 // Adds the rest of video modes found
379 for (s32 i = 1; i < preferences.NumVideoModes(); ++i)
380 {
381 snprintf(str, 128, "%dx%d", preferences.VideoModes()[i].w, preferences.VideoModes()[i].h);
382 it->AddNodeGo(new JTextMenuEntry(str, &OnVideoMode, JCAST_S32_TO_VOIDPTR(i))); // Modes
383 }
384
385 it->Parent();
386 }
387 }
388
389 if (f.ReadLine(str)) it->AddNodeGo(new JTextMenuEntry(str, 0, 0)); else return false; // BPP
390 {
391 it->AddBranchGo(new JTextMenuEntry("32", &OnBPP, (void *)32)); // 32
392 it->AddNodeGo(new JTextMenuEntry("24", &OnBPP, (void *)24)); // 24
393 it->AddNodeGo(new JTextMenuEntry("16", &OnBPP, (void *)16)); // 16
394 it->AddNodeGo(new JTextMenuEntry("8", &OnBPP, (void *)8)); // 8
395 it->Parent();
396 }
397
398 if (f.ReadLine(str)) it->AddNodeGo(new JTextMenuEntry(str, 0, 0)); else return false; // Window
399 {
400 if (f.ReadLine(str)) // Windowed
401 it->AddBranchGo(new JTextMenuEntry(str, &OnWindowMode, (void *)0));
402 else return false;
403
404 if (f.ReadLine(str)) // Fullscreen
405 it->AddNodeGo(new JTextMenuEntry(str, &OnWindowMode, (void *)1));
406 else return false;
407
408 it->Parent();
409 }
410
411 if (f.ReadLine(str)) it->AddNodeGo(new JTextMenuEntry(str, &OnDefaults)); else return false; // Defaults
412 it->Parent();
413 }
414
415 if (f.ReadLine(str)) it->AddNodeGo(new JTextMenuEntry(str, 0, 0)); else return false; // Sound
416 {
417 if (f.ReadLine(str)) it->AddBranchGo(new JTextMenuEntry(str, &OnSound, (void*)1)); else return false;// On
418 if (f.ReadLine(str)) it->AddNodeGo(new JTextMenuEntry(str, &OnSound, (void*)0)); else return false; // Off
419 it->Parent();
420 }
421
422 if (f.ReadLine(str)) it->AddNodeGo(new JTextMenuEntry(str, 0, 0)); else return false; // Difficulty
423 {
424 if (f.ReadLine(str)) // Easy
425 it->AddBranchGo(new JTextMenuEntry(str, &OnDifficulty, (void*)HCPREFERENCES_TOY));
426 else return false;
427 if (f.ReadLine(str)) // Easy
428 it->AddNodeGo(new JTextMenuEntry(str, &OnDifficulty, (void*)HCPREFERENCES_EASY));
429 else return false;
430 if (f.ReadLine(str)) // Medium
431 it->AddNodeGo(new JTextMenuEntry(str, &OnDifficulty, (void*)HCPREFERENCES_NORMAL));
432 else return false;
433 if (f.ReadLine(str)) // Hard
434 it->AddNodeGo(new JTextMenuEntry(str, &OnDifficulty, (void*)HCPREFERENCES_HARD));
435 else return false;
436 it->Parent();
437 }
438
439 if (f.ReadLine(str)) it->AddNodeGo(new JTextMenuEntry(str, 0, 0)); else return false; // Language
440 {
441 if (preferences.NumLangs() > 0)
442 {
443 it->AddBranchGo(new JTextMenuEntry(preferences.Langs()[0], &OnLanguage, (void *)0)); // Available langs
444 for (s32 c = 1; c < preferences.NumLangs(); ++c)
445 {
446 it->AddNodeGo(new JTextMenuEntry(preferences.Langs()[c], &OnLanguage, JCAST_S32_TO_VOIDPTR(c))); // Available langs
447 }
448
449 it->Parent();
450 }
451 }
452 it->Parent();
453 }
454
455 char strLev[64];
456 if (f.ReadLine(str)) it->AddNodeGo(new JTextMenuEntry(str, 0, 0)); else return false; // Load
457 {
458 if (strlen(saveData[0].Story()) == 0)
459 {
460 // Empty slot
461 it->AddBranchGo(new JTextMenuEntry("< ******* >", 0, 0)); // Slot 0
462 }
463 else
464 {
465 snprintf(strLev, sizeof(strLev), "< %s - %d >", saveData[0].Story(), saveData[0].Level());
466 it->AddBranchGo(new JTextMenuEntry(strLev, &OnLoad, (void *)0)); // Slot 0
467 }
468
469 for (s32 i = 1; i < HC_NUM_SLOTS; ++i)
470 {
471 if (strlen(saveData[i].Story()) == 0)
472 {
473 // Empty slot
474 it->AddNodeGo(new JTextMenuEntry("< ******* >", 0, 0)); // ...
475 }
476 else
477 {
478 snprintf(strLev, sizeof(strLev), "< %s - %d >", saveData[i].Story(), saveData[i].Level());
479 it->AddNodeGo(new JTextMenuEntry(strLev, &OnLoad, JCAST_S32_TO_VOIDPTR(i))); // Slot N
480 }
481 }
482 it->Parent();
483 }
484
485 if (f.ReadLine(str)) it->AddNodeGo(new JTextMenuEntry(str, 0, 0)); else return false; // Save
486 {
487 if (strlen(saveData[0].Story()) == 0)
488 {
489 // Empty slot
490 it->AddBranchGo(new JTextMenuEntry("< ******* >", &OnSave, (void *)0)); // Slot 0
491 }
492 else
493 {
494 snprintf(strLev, sizeof(strLev), "< %s - %d >", saveData[0].Story(), saveData[0].Level());
495 it->AddBranchGo(new JTextMenuEntry(strLev, &OnSave, (void *)0)); // Slot 0
496 }
497
498 for (s32 i = 1; i < HC_NUM_SLOTS; ++i)
499 {
500 if (strlen(saveData[i].Story()) == 0)
501 {
502 // Empty slot
503 it->AddNodeGo(new JTextMenuEntry("< ******* >", &OnSave, JCAST_S32_TO_VOIDPTR(i))); // ...
504 }
505 else
506 {
507 snprintf(strLev, sizeof(strLev), "< %s - %d >", saveData[i].Story(), saveData[i].Level());
508 it->AddNodeGo(new JTextMenuEntry(strLev, &OnSave, JCAST_S32_TO_VOIDPTR(i))); // Slot N
509 }
510 }
511 it->Parent();
512 }
513
514 if (f.ReadLine(str)) it->AddNodeGo(new JTextMenuEntry(str, &OnCredits, this)); else return false; // Credits
515 if (f.ReadLine(str)) it->AddNodeGo(new JTextMenuEntry(str, &OnExit, this)); else return false; // Exit
516
517 it->Root();
518
519 JTextMenuConfig cfg;
520 memset(&cfg, 0, sizeof(cfg));
521 cfg.renderMode = JTEXTMENU_BLENDED;
522 cfg.layout = JTEXTMENU_RIGHT;
523 cfg.layoutV = JTEXTMENU_DOWN;
524 cfg.trackKeyboard = true;
525 cfg.autoEnter = true;
526 cfg.lineDistance = 0;
527 cfg.font = &fontLarge;
528 cfg.hiColor.r = cfg.hiColor.g = cfg.hiColor.b = 255;
529 cfg.color.b = 255;
530 cfg.color.r = cfg.color.g = 128;
531 menu->Pos(width, height);
532
533 if (!menu->Init(cfg))
534 {
535 return false;
536 }
537
538 menu->Menu()->Root();
539
540 // Loads the main title's sounds
541 if (musicMainTitle.LoadWave(HC_DATA_DIR "sound/HCMainTitle.wav"))
542 {
543 if (SoundEnabled())
544 {
545 musicMainTitle.FadeIn(1000, -1, -1);
546 }
547 }
548
549 imgMenu->Alpha(0);
550
551 return true;
552 }
553
554 bool HCApp::InitIntro()
555 {
556 SDL_Color fg = {0xff, 0xcc, 0x00, 0x00}, bg = {0x00, 0x00, 0x00, 0x00};
557
558 imgIntro = new JImage;
559 imgFatalFun = new JImage;
560
561 char str[256];
562 snprintf(str, sizeof(str) - 1, HC_DATA_DIR "intro/%s/intro.txt", preferences.LangCodes()[preferences.CurLang()]);
563
564 JTextFile f;
565 if (!f.Load(str))
566 {
567 strcpy(str, "Proudly presents...");
568 }
569 else
570 {
571 f.ReadWord(str);
572 }
573
574 if (imgIntro->Load(HC_DATA_DIR "intro/intro.tga", true) &&
575 imgFatalFun->Load(HC_DATA_DIR "intro/ff.tga", true, 0x0000ffff) &&
576 0 != (textIntro = fontMedium.RenderTextShaded(str, fg, bg)))
577 {
578 if (imgIntro->Width() > width)
579 {
580 float w = float(imgIntro->Width());
581 do
582 {
583 w /= 1.5f;
584 }
585 while (w > Width());
586
587 JImage *tmp = imgIntro;
588 imgIntro = imgIntro->Scale(w/float(imgIntro->Width()), w/float(imgIntro->Width()));
589
590 if (imgIntro)
591 delete tmp;
592 else
593 imgIntro = tmp;
594 }
595
596 if (imgFatalFun->Width() > width)
597 {
598 float w = float(imgFatalFun->Width());
599 do
600 {
601 w /= 1.5f;
602 }
603 while (w > Width());
604
605 JImage *tmp = imgFatalFun;
606 imgFatalFun = imgFatalFun->Scale(w/float(imgFatalFun->Width()), w/float(imgFatalFun->Width()));
607
608 if (imgFatalFun)
609 delete tmp;
610 else
611 imgFatalFun = tmp;
612 }
613
614 imgIntro->Alpha(0);
615 imgFatalFun->Alpha(0);
616 textIntro->Alpha(0);
617 imgIntro->Pos(((width - imgIntro->Width())/2), ((height - imgIntro->Height())/2));
618 imgFatalFun->Pos(((width - imgFatalFun->Width())/2), ((height - imgFatalFun->Height())/2));
619 textIntro->Pos(((width - textIntro->Width())/2), ((imgIntro->Y() + imgIntro->Height()) + (height - (imgIntro->Y() + imgIntro->Height()) - textIntro->Height())/2));
620
621 timerGeneral.Start(1000);
622
623 return true;
624 }
625
626 fprintf(stderr, "Error loading intro. Switching to game menu.\n");
627
628 return false;
629 }
630
631 bool HCApp::InitPaused()
632 {
633 // Pauses the level
634 level.Pause(true);
635
636 // Copies the scene as is
637 JImage img(screen);
638 JDELETE(imgBack);
639 imgBack = new JImage(img.Width(), img.Height());
640 imgBack->Paste(&img, 0, 0, img.Width(), img.Height());
641
642 imgBack->Alpha(255);
643 JDELETE(textBack);
644
645 // Reads the pause file in the correct language
646 char str[256];
647 snprintf(str, sizeof(str), HC_DATA_DIR "messages/%s/messages.txt", preferences.LangCodes()[preferences.CurLang()]);
648
649 JTextFile f;
650 if (!f.Load(str, "rb"))
651 {
652 snprintf(str, sizeof(str), "... ZzZzZz ...");
653 }
654 else
655 {
656 f.NextLine();
657 f.ReadLine(str);
658 }
659
660 textBack = new HCText;
661 textBack->Init(HCTEXTTYPE_NARRATIVE, str, &level.Theme(), &fontLarge, JFONTALIGN_CENTER, false, 0);
662 textBack->Pos((Width() - textBack->Image().Width())/2, (Height() - textBack->Image().Height())/2);
663
664 return true;
665 }
666
667 bool HCApp::InitPlaying()
668 {
669 if (SoundEnabled())
670 {
671 musicMainTitle.FadeOut(3000);
672 }
673
674 // Loads the world map and character
675 switch (LoadWorld())
676 {
677 // Error
678 case 0:
679 fprintf(stderr, "Error loading the world.\n");
680 return false;
681
682 // Game end
683 case -1:
684 State(HCS_CREDITS);
685 ProcessStateChange();
686 return true;
687 }
688
689 // Checks for an existing script
690 JString str;
691 str.Format("%s%s/script/%s/level%03d.hcs", playlist.StoryDir(), playlist.StoryName(), preferences.LangCodes()[preferences.CurLang()], levelNumber);
692
693 if (JFile::Exists(str))
694 {
695 if (!script.Load(str))
696 {
697 fprintf(stderr, "Error loading the level script %s.\n", str.Str());
698 return false;
699 }
700 else
701 {
702 level.Scripted(true);
703 State(HCS_SCRIPT);
704 ProcessStateChange();
705 }
706 }
707 else
708 {
709 level.Scripted(false);
710
711 // Loads the start-of-level music
712 if (SoundEnabled() && musicBeginLevel.LoadWave(HC_DATA_DIR "sound/HCBeginLevel.wav"))
713 {
714 musicBeginLevel.Play();
715 }
716
717 // Starts the level timer
718 level.Start();
719 }
720
721 return true;
722 }
723
724 bool HCApp::InitGameOver()
725 {
726 timerGeneral.Start();
727
728 // Loads the game over music
729 if (SoundEnabled() && musicGameOver.LoadWave(HC_DATA_DIR "sound/HCGameOver.wav"))
730 {
731 musicGameOver.FadeIn(5000, -1, 0);
732 }
733
734 return true;
735 }
736
737 bool HCApp::InitEndLevel()
738 {
739 // Copies the scene as is
740 JImage img(screen);
741 JDELETE(imgBack);
742 imgBack = new JImage(img.Width(), img.Height());
743
744 imgBack->Paste(&img, 0, 0, img.Width(), img.Height());
745
746 return true;
747 }
748
749 bool HCApp::InitCredits()
750 {
751 const char *files[HCCREDITS_IMAGE_COUNT] = {HC_DATA_DIR "credits/programming.tga",
752 HC_DATA_DIR "credits/story.tga",
753 HC_DATA_DIR "credits/drawing0.tga",
754 HC_DATA_DIR "credits/drawing1.tga",
755 HC_DATA_DIR "credits/drawing2.tga",
756 HC_DATA_DIR "credits/animation0.tga",
757 HC_DATA_DIR "credits/animation1.tga",
758 HC_DATA_DIR "credits/animation2.tga",
759 HC_DATA_DIR "credits/animation3.tga",
760 HC_DATA_DIR "credits/music.tga",
761 HC_DATA_DIR "main/main.tga",
762 HC_DATA_DIR "intro/intro.tga"};
763
764 const char *strings[HCCREDITS_TEXT_COUNT] = {"Programming\nJuan Carlos Seijo Pérez",
765 "Story\nJuan Carlos Seijo Pérez",
766 "Graphics\nJuan Carlos Seijo Pérez",
767 "Animation\nJuan Carlos Seijo Pérez",
768 "Music\nJuan Carlos Seijo Pérez",
769 "Thanks for playing!\nCheck for more games at\nwww.mainreactor.net\n&\nwww.FatalFun.com",
770 "Holotz's Castle\n(C) Juan Carlos Seijo Pérez 2004-2009",
771 ACKNOWLEDGEMENTS};
772
773 bool ok;
774 ok = true;
775 for (s32 i = 0; ok && i < HCCREDITS_IMAGE_COUNT; ++i)
776 {
777 JDELETE(imgCredits[i]);
778 imgCredits[i] = new JImage();
779 ok = imgCredits[i]->Load(files[i]);
780 }
781
782 if (!ok)
783 {
784 return false;
785 }
786
787 // Adjusts main and intro images so they fit on the screen
788 if (width < imgCredits[HCCREDITS_HOLOTZCASTLE]->Width())
789 {
790 JImage *tmp;
791 float factor = 0.8f * width/imgCredits[HCCREDITS_HOLOTZCASTLE]->Width();
792 if ((tmp = imgCredits[HCCREDITS_HOLOTZCASTLE]->Scale(factor, factor)))
793 {
794 JDELETE(imgCredits[HCCREDITS_HOLOTZCASTLE]);
795 imgCredits[HCCREDITS_HOLOTZCASTLE] = tmp;
796 }
797 else
798 {
799 return false;
800 }
801 }
802
803 if (width < imgCredits[HCCREDITS_LOGO]->Width())
804 {
805 JImage *tmp;
806 float factor = 0.8f * width/imgCredits[HCCREDITS_LOGO]->Width();
807 if ((tmp = imgCredits[HCCREDITS_LOGO]->Scale(factor, factor)))
808 {
809 JDELETE(imgCredits[HCCREDITS_LOGO]);
810 imgCredits[HCCREDITS_LOGO] = tmp;
811 }
812 else
813 {
814 return false;
815 }
816 }
817
818 SDL_Color fg;
819 fg.b = 255;
820 fg.r = fg.g = 128;
821
822 SDL_Color bg;
823 bg.r = bg.g = bg.b = 0;
824
825 s8 dr = 128/(HCCREDITS_TEXT_COUNT - 1), dg = -(fg.g - 0xcc)/(HCCREDITS_TEXT_COUNT - 1), db = -255/(HCCREDITS_TEXT_COUNT - 1);
826
827 ok = true;
828
829 for (s32 i = 0; ok && i < HCCREDITS_TEXT_COUNT; ++i, fg.r += dr, fg.g += dg, fg.b += db)
830 {
831 JDELETE(textCredits[i]);
832
833 textCredits[i] = fontLarge.PrintfShaded(JFONTALIGN_CENTER, fg, bg, strings[i]);
834 ok = (textCredits[i] != 0);
835 }
836
837 if (!ok)
838 {
839 return false;
840 }
841
842 // Initializes positions
843
844 // Adjusts initial Y
845 textCredits[HCCREDITS_ACK_TEXT]->Y(height);
846
847 imgCredits[HCCREDITS_PROGRAMMING]->Y(textCredits[HCCREDITS_ACK_TEXT]->Y() + textCredits[HCCREDITS_ACK_TEXT]->Height() + Height()/2);
848 textCredits[HCCREDITS_PROGRAMMING_TEXT]->Y(imgCredits[HCCREDITS_PROGRAMMING]->Y() + imgCredits[HCCREDITS_PROGRAMMING]->Height());
849
850 imgCredits[HCCREDITS_STORY]->Y(imgCredits[HCCREDITS_PROGRAMMING]->Y() + (2 * imgCredits[HCCREDITS_PROGRAMMING]->Height()));
851 textCredits[HCCREDITS_STORY_TEXT]->Y(imgCredits[HCCREDITS_STORY]->Y() + imgCredits[HCCREDITS_STORY]->Height());
852
853 imgCredits[HCCREDITS_DRAWING0]->Y(imgCredits[HCCREDITS_STORY]->Y() + (2 * imgCredits[HCCREDITS_STORY]->Height()));
854 imgCredits[HCCREDITS_DRAWING1]->Y(imgCredits[HCCREDITS_STORY]->Y() + (2 * imgCredits[HCCREDITS_STORY]->Height()));
855 imgCredits[HCCREDITS_DRAWING2]->Y(imgCredits[HCCREDITS_STORY]->Y() + (2 * imgCredits[HCCREDITS_STORY]->Height()));
856 textCredits[HCCREDITS_DRAWING_TEXT]->Y(imgCredits[HCCREDITS_DRAWING0]->Y() + imgCredits[HCCREDITS_DRAWING0]->Height());
857
858 imgCredits[HCCREDITS_ANIMATION0]->Y(imgCredits[HCCREDITS_DRAWING0]->Y() + (2 * imgCredits[HCCREDITS_DRAWING0]->Height()));
859 imgCredits[HCCREDITS_ANIMATION1]->Y(imgCredits[HCCREDITS_DRAWING0]->Y() + (2 * imgCredits[HCCREDITS_DRAWING0]->Height()));
860 imgCredits[HCCREDITS_ANIMATION2]->Y(imgCredits[HCCREDITS_DRAWING0]->Y() + (2 * imgCredits[HCCREDITS_DRAWING0]->Height()));
861 imgCredits[HCCREDITS_ANIMATION3]->Y(imgCredits[HCCREDITS_DRAWING0]->Y() + (2 * imgCredits[HCCREDITS_DRAWING0]->Height()));
862 textCredits[HCCREDITS_ANIMATION_TEXT]->Y(imgCredits[HCCREDITS_ANIMATION0]->Y() + imgCredits[HCCREDITS_ANIMATION0]->Height());
863
864 imgCredits[HCCREDITS_MUSIC]->Y(imgCredits[HCCREDITS_ANIMATION0]->Y() + (2 * imgCredits[HCCREDITS_ANIMATION0]->Height()));
865 textCredits[HCCREDITS_MUSIC_TEXT]->Y(imgCredits[HCCREDITS_MUSIC]->Y() + imgCredits[HCCREDITS_MUSIC]->Height());
866
867 imgCredits[HCCREDITS_HOLOTZCASTLE]->Y(imgCredits[HCCREDITS_MUSIC]->Y() + (2 * imgCredits[HCCREDITS_MUSIC]->Height()));
868 textCredits[HCCREDITS_HOLOTZCASTLE_TEXT]->Y(imgCredits[HCCREDITS_HOLOTZCASTLE]->Y() + imgCredits[HCCREDITS_HOLOTZCASTLE]->Height());
869
870 imgCredits[HCCREDITS_LOGO]->Y(imgCredits[HCCREDITS_HOLOTZCASTLE]->Y() + (2 * imgCredits[HCCREDITS_HOLOTZCASTLE]->Height()));
871 textCredits[HCCREDITS_LOGO_TEXT]->Y(imgCredits[HCCREDITS_LOGO]->Y() + imgCredits[HCCREDITS_LOGO]->Height());
872
873 // Adjusts initial X
874 textCredits[HCCREDITS_ACK_TEXT]->X((float)(width - textCredits[HCCREDITS_ACK_TEXT]->Width())/2);
875
876 imgCredits[HCCREDITS_PROGRAMMING]->X(float(width) * 0.3f);
877 textCredits[HCCREDITS_PROGRAMMING_TEXT]->X((float)(width - textCredits[HCCREDITS_PROGRAMMING_TEXT]->Width())/2);
878
879 imgCredits[HCCREDITS_STORY]->X(float(width) * 0.5f);
880 textCredits[HCCREDITS_STORY_TEXT]->X((float)(width - textCredits[HCCREDITS_STORY_TEXT]->Width())/2);
881
882 imgCredits[HCCREDITS_DRAWING0]->X(float(width) * 0.2f);
883 imgCredits[HCCREDITS_DRAWING1]->X(float(width) * 0.2f);
884 imgCredits[HCCREDITS_DRAWING2]->X(float(width) * 0.2f);
885 textCredits[HCCREDITS_DRAWING_TEXT]->X((float)(width - textCredits[HCCREDITS_DRAWING_TEXT]->Width())/2);
886
887 imgCredits[HCCREDITS_ANIMATION0]->X(float(width) * 0.6f);
888 imgCredits[HCCREDITS_ANIMATION1]->X(float(width) * 0.6f);
889 imgCredits[HCCREDITS_ANIMATION2]->X(float(width) * 0.6f);
890 imgCredits[HCCREDITS_ANIMATION3]->X(float(width) * 0.6f);
891 textCredits[HCCREDITS_ANIMATION_TEXT]->X((float)(width - textCredits[HCCREDITS_ANIMATION_TEXT]->Width())/2);
892
893 imgCredits[HCCREDITS_MUSIC]->X(float(width) * 0.4f);
894 textCredits[HCCREDITS_MUSIC_TEXT]->X((float)(width - textCredits[HCCREDITS_MUSIC_TEXT]->Width())/2);
895
896 imgCredits[HCCREDITS_HOLOTZCASTLE]->X((float)(width - imgCredits[HCCREDITS_HOLOTZCASTLE]->Width())/2);
897 textCredits[HCCREDITS_HOLOTZCASTLE_TEXT]->X((float)(width - textCredits[HCCREDITS_HOLOTZCASTLE_TEXT]->Width())/2);
898
899 imgCredits[HCCREDITS_LOGO]->X((float)(width - imgCredits[HCCREDITS_LOGO]->Width())/2);
900 textCredits[HCCREDITS_LOGO_TEXT]->X((float)(width - textCredits[HCCREDITS_LOGO_TEXT]->Width())/2);
901
902 // Adjust alpha values and control variables for drawing and animation credits
903 imgCredits[HCCREDITS_DRAWING1]->Alpha(0);
904 imgCredits[HCCREDITS_DRAWING2]->Alpha(0);
905 imgCredits[HCCREDITS_ANIMATION1]->Alpha(0);
906 imgCredits[HCCREDITS_ANIMATION2]->Alpha(0);
907 imgCredits[HCCREDITS_ANIMATION3]->Alpha(0);
908 outDrawing = 0;
909 inDrawing = 1;
910 outAnimation = 0;
911 inAnimation = 1;
912
913 // Loads the credits' sounds
914 if (musicCredits.LoadWave(HC_DATA_DIR "sound/HCCredits.wav"))
915 {
916 musicCredits.FadeIn(1000, -1, -1);
917 }
918
919 return true;
920 }
921
922 bool HCApp::InitHelp()
923 {
924 JDELETE(imgHelp);
925
926 JTextFile f;
927 char str[256];
928
929 snprintf(str, sizeof(str), HC_DATA_DIR "help/%s/help.txt", preferences.LangCodes()[preferences.CurLang()]);
930
931 if (!f.Load(str, "rt"))
932 {
933 fprintf(stderr, "Couldn't load help file %s. Check manual.\n", str);
934 return false;
935 }
936
937 s32 sz = f.BufferSize();
938 char *strText = new char[sz + 1];
939 memcpy(strText, f.Buffer(), sz);
940 strText[sz] = '\0';
941
942 SDL_Color fg = {0xff, 0xcc, 0x00, 0xff};
943 SDL_Color bg = {0x00, 0x00, 0x33, 0xff};
944
945 imgHelp = fontLarge.PrintfShaded(JFONTALIGN_CENTER, fg, bg, strText);
946
947 if (!imgHelp)
948 {
949 fprintf(stderr, "Couldn't create help image, out of memory. Check manual.\n");
950 JDELETE_ARRAY(strText);
951 return false;
952 }
953
954 JDELETE_ARRAY(strText);
955 imgHelp->Pos((Width() - imgHelp->Width())/2,
956 (Height() - imgHelp->Height())/2);
957 imgHelp->Alpha(128);
958
959 return true;
960 }
961
962 void HCApp::DestroyHelp()
963 {
964 JDELETE(imgHelp);
965 }
966
967 bool HCApp::InitSlots()
968 {
969 bool ok = true;
970 for (s32 i = 0; i < HC_NUM_SLOTS && ok; ++i)
971 {
972 // Loads an existing slot
973 saveData[i].Load(i);
974 }
975
976 return ok;
977 }
978
979 void HCApp::OnExit(void *data)
980 {
981 ((HCApp*)data)->Exit();
982 }
983
984 void HCApp::OnCredits(void *data)
985 {
986 ((HCApp*)data)->State(HCS_CREDITS);
987 }
988
989 void HCApp::OnDifficulty(void *data)
990 {
991 HCPreferences::Prefs()->Difficulty((long)data);
992 HCPreferences::Prefs()->Save();
993 theApp->menu->Menu()->Root();
994 }
995
996 void HCApp::OnSound(void *data)
997 {
998 HCApp *a = (HCApp *)App();
999 a->SoundEnabled(0 != (long)data);
1000
1001 if (0 != (long)data)
1002 {
1003 if (a->SoundEnabled())
1004 {
1005 a->Mixer().Volume(-1, MIX_MAX_VOLUME);
1006
1007 // Sound successfully enabled
1008 a->preferences.Sound(true);
1009 a->preferences.Save();
1010 if (!a->musicMainTitle.IsPlaying())
1011 {
1012 a->musicMainTitle.FadeIn(1000, -1, -1);
1013 }
1014 }
1015 }
1016 else
1017 {
1018 a->musicMainTitle.Halt();
1019 a->preferences.Sound(false);
1020 a->preferences.Save();
1021 }
1022 }
1023
1024 void HCApp::OnNew(void *data)
1025 {
1026 if (theApp->playlist.GoTo(theApp->playlist[JCAST_VOIDPTR_TO_S32(data)]))
1027 {
1028 theApp->levelNumber = 1;
1029 theApp->State(HCS_PLAYING);
1030 }
1031 }
1032
1033 void HCApp::OnContinue(void *data)
1034 {
1035 // Just play, at the story it was
1036 theApp->State(HCS_PLAYING);
1037 }
1038
1039 void HCApp::OnHelp(void *data)
1040 {
1041 theApp->InitHelp();
1042 }
1043
1044 void HCApp::OnVideoMode(void *data)
1045 {
1046 HCApp *a = (HCApp *)App();
1047 a->preferences.VideoMode(JCAST_VOIDPTR_TO_S32(data));
1048 a->preferences.Save();
1049 App()->Resize(a->preferences.VideoModes()[JCAST_VOIDPTR_TO_S32(data)].w,
1050 a->preferences.VideoModes()[JCAST_VOIDPTR_TO_S32(data)].h,
1051 a->preferences.Fullscreen());
1052 a->State(HCS_MENU);
1053 }
1054
1055 void HCApp::OnBPP(void *data)
1056 {
1057 HCApp *a = (HCApp *)App();
1058 a->preferences.BPP(JCAST_VOIDPTR_TO_S32(data));
1059 a->preferences.Save();
1060 a->depth = JCAST_VOIDPTR_TO_S32(data);
1061 App()->Resize(a->preferences.VideoModes()[a->preferences.VideoMode()].w,
1062 a->preferences.VideoModes()[a->preferences.VideoMode()].h,
1063 a->preferences.Fullscreen());
1064 a->State(HCS_MENU);
1065 }
1066
1067 void HCApp::OnWindowMode(void *data)
1068 {
1069 HCApp *a = (HCApp *)App();
1070 a->preferences.Fullscreen(JCAST_VOIDPTR_TO_S32(data));
1071 a->preferences.Save();
1072 App()->Resize(a->preferences.VideoModes()[a->preferences.VideoMode()].w,
1073 a->preferences.VideoModes()[a->preferences.VideoMode()].h,
1074 a->preferences.Fullscreen());
1075 a->State(HCS_MENU);
1076 }
1077
1078 void HCApp::OnLanguage(void *data)
1079 {
1080 HCApp *a = (HCApp *)App();
1081 a->preferences.CurLang(JCAST_VOIDPTR_TO_S32(data));
1082 a->preferences.Save();
1083 a->State(HCS_MENU);
1084 }
1085
1086 void HCApp::OnDefaults(void *data)
1087 {
1088 HCApp *a = (HCApp *)App();
1089 a->preferences.Reset();
1090 a->preferences.Save();
1091 App()->Resize(a->preferences.VideoModes()[JCAST_VOIDPTR_TO_S32(data)].w,
1092 a->preferences.VideoModes()[JCAST_VOIDPTR_TO_S32(data)].h,
1093 a->preferences.Fullscreen());
1094 a->State(HCS_MENU);
1095 }
1096
1097 void HCApp::OnLoad(void *data)
1098 {
1099 HCApp *app = (HCApp *)App();
1100 if (app->playlist.GoTo(app->saveData[JCAST_VOIDPTR_TO_S32(data)].Story()))
1101 {
1102 app->levelNumber = app->saveData[JCAST_VOIDPTR_TO_S32(data)].Level();
1103 app->State(HCS_PLAYING);
1104 }
1105 }
1106
1107 void HCApp::OnSave(void *data)
1108 {
1109 HCApp *app = (HCApp *)App();
1110 if (app->saveData[JCAST_VOIDPTR_TO_S32(data)].Save(JCAST_VOIDPTR_TO_S32(data), app->playlist.StoryName(), app->levelNumber))
1111 {
1112 app->State(HCS_MENU);
1113 }
1114 }
1115
1116 bool HCApp::DrawMenu()
1117 {
1118 SDL_FillRect(screen, 0, 0);
1119
1120 imgMenu->Draw();
1121
1122 if (imgHelp)
1123 {
1124 imgHelp->Draw();
1125 }
1126 else
1127 {
1128 menu->Draw();
1129 }
1130
1131 Flip();
1132
1133 return true;
1134 }
1135
1136 bool HCApp::DrawPlaying()
1137 {
1138 //static s32 index = 0;
1139 //s32 t;
1140 //t = AppTime();
1141
1142 SDL_FillRect(screen, 0, 0);
1143
1144 // Draws game elements
1145 level.Draw();
1146
1147 Flip();
1148
1149 //t = AppTime() - t;
1150 //printf("%3.3f FPS\n", 1000.0f/float(t));
1151
1152 return true;
1153 }
1154
1155 bool HCApp::DrawPaused()
1156 {
1157 SDL_FillRect(screen, 0, 0);
1158
1159 imgBack->Draw();
1160
1161 // If help requested, show help instead
1162 if (imgHelp)
1163 {
1164 imgHelp->Draw();
1165 }
1166 else
1167 {
1168 textBack->Draw();
1169 }
1170
1171 Flip();
1172
1173 return true;
1174 }
1175
1176 bool HCApp::DrawIntro()
1177 {
1178 if (timerGeneral.TotalLap() < 6000)
1179 {
1180 SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 255, 255, 255));
1181 imgFatalFun->Draw();
1182 }
1183 else
1184 if (timerGeneral.TotalLap() < 7000)
1185 {
1186 int a = 255 - ((timerGeneral.TotalLap()-6000)*255)/1000;
1187 SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, a, a, a));
1188 }
1189 else
1190 {
1191 SDL_FillRect(screen, 0, 0);
1192 imgIntro->Draw();
1193 textIntro->Draw();
1194 }
1195
1196 Flip();
1197
1198 return true;
1199 }
1200
1201 bool HCApp::DrawCredits()
1202 {
1203 SDL_FillRect(screen, 0, 0);
1204
1205 for (s32 i = 0; i < HCCREDITS_IMAGE_COUNT; ++i)
1206 {
1207 if (imgCredits[i]->Y() < height && imgCredits[i]->Y() + imgCredits[i]->Height() > 0)
1208 imgCredits[i]->Draw();
1209 }
1210
1211 for (s32 i = 0; i < HCCREDITS_TEXT_COUNT; ++i)
1212 {
1213 if (textCredits[i]->Y() < height && textCredits[i]->Y() + textCredits[i]->Height() > 0)
1214 textCredits[i]->Draw();
1215 }
1216
1217 Flip();
1218
1219 return true;
1220 }
1221
1222 bool HCApp::DrawScript()
1223 {
1224 SDL_FillRect(screen, 0, 0);
1225
1226 // Draws game elements
1227 level.Draw();
1228
1229 Flip();
1230
1231 return true;
1232 }
1233
1234 bool HCApp::DrawEndLevel()
1235 {
1236 SDL_FillRect(screen, 0, 0);
1237 imgBack->Draw();
1238 Flip();
1239
1240 return true;
1241 }
1242
1243 bool HCApp::DrawGameOver()
1244 {
1245 SDL_FillRect(screen, 0, 0);
1246 if (imgBack)
1247 {
1248 imgBack->Draw();
1249 textBack->Draw();
1250 }
1251 else
1252 {
1253 level.Draw();
1254 }
1255
1256 Flip();
1257
1258 return true;
1259 }
1260
1261 bool HCApp::Draw()
1262 {
1263 switch (state)
1264 {
1265 default:
1266 case HCS_MENU:
1267 DrawMenu();
1268 break;
1269
1270 case HCS_PLAYING:
1271 return DrawPlaying();
1272
1273 case HCS_PAUSED:
1274 return DrawPaused();
1275
1276 case HCS_INTRO:
1277 DrawIntro();
1278 break;
1279
1280 case HCS_CREDITS:
1281 return DrawCredits();
1282
1283 case HCS_SCRIPT:
1284 DrawScript();
1285 break;
1286
1287 case HCS_GAMEOVER:
1288 return DrawGameOver();
1289
1290 case HCS_ENDLEVEL:
1291 return DrawEndLevel();
1292 }
1293
1294 /*
1295 static s32 i = 0;
1296
1297 char str[32];
1298 sprintf(str, "video%05d.bmp", i++);
1299 SDL_SaveBMP(screen, str);
1300 */
1301
1302 return true;
1303 }
1304
1305 bool HCApp::UpdateMenu()
1306 {
1307 // Make a fade-in
1308 if (imgMenu->Alpha() < 255)
1309 imgMenu->Alpha(imgMenu->Alpha() + 15);
1310
1311 return true;
1312 }
1313
1314 bool HCApp::UpdatePlaying()
1315 {
1316 u32 actions = 0;
1317
1318 if (level.LevelExit()->State() < HCEXITSTATE_SWALLOWING)
1319 {
1320 if (Keys()[SDLK_LEFT] || JoystickX() < -3000)
1321 {
1322 actions |= HCCA_LEFT;
1323 }
1324 else
1325 if (Keys()[SDLK_RIGHT] || JoystickX() > 3000)
1326 {
1327 actions |= HCCA_RIGHT;
1328 }
1329
1330 if (Keys()[SDLK_UP] || JoystickY() < -3000)
1331 {
1332 actions |= HCCA_UP;
1333 }
1334 else
1335 if (Keys()[SDLK_DOWN] || JoystickY() > 3000)
1336 {
1337 actions |= HCCA_DOWN;
1338 }
1339
1340 if (Keys()[SDLK_SPACE] || JoystickButton())
1341 {
1342 actions |= HCCA_JUMP;
1343 }
1344
1345 level.ProcessInput(actions);
1346 }
1347
1348 // Updates game elements
1349 switch (level.Update())
1350 {
1351 // Player died
1352 case 1:
1353 State(HCS_GAMEOVER);
1354 ProcessStateChange();
1355 break;
1356
1357 // Level ended
1358 case 2:
1359 State(HCS_ENDLEVEL);
1360 ProcessStateChange();
1361 break;
1362
1363 // Nothing happened
1364 case 0:
1365 default:
1366 break;
1367 }
1368
1369 return true;
1370 }
1371
1372 bool HCApp::UpdatePaused()
1373 {
1374 // If help requested, don't update back text
1375 if (imgHelp)
1376 {
1377 return true;
1378 }
1379
1380 if (textBack->Update() == 2)
1381 {
1382 // Disappeared, show it again!
1383 textBack->Reset();
1384 }
1385
1386 return true;
1387 }
1388
1389 bool HCApp::UpdateIntro()
1390 {
1391 if (timerGeneral.TotalLap() > 10000)
1392 {
1393 if (imgIntro->Alpha() > 0)
1394 {
1395 // Fades out
1396 imgIntro->Alpha(imgIntro->Alpha() - 15);
1397 textIntro->Alpha(textIntro->Alpha() - 15);
1398
1399 return true;
1400 }
1401 else
1402 {
1403 // Done, show menu
1404 State(HCS_MENU);
1405 ProcessStateChange();
1406
1407 return true;
1408 }
1409 }
1410 else
1411 if (timerGeneral.TotalLap() > 7000)
1412 {
1413 if (imgIntro->Alpha() < 255)
1414 {
1415 // Fades in the intro image
1416 imgIntro->Alpha(imgIntro->Alpha() + 15);
1417 }
1418 else
1419 {
1420 if (timerGeneral.TotalLap() > 8000)
1421 {
1422 if (textIntro->Alpha() < 255)
1423 {
1424 // Fades in the intro text
1425 textIntro->Alpha(textIntro->Alpha() + 15);
1426 }
1427 }
1428 }
1429 }
1430 else
1431 if (timerGeneral.TotalLap() > 5000)
1432 {
1433 if (imgFatalFun->Alpha() > 0)
1434 {
1435 // Fades out
1436 imgFatalFun->Alpha(imgFatalFun->Alpha() - 15);
1437
1438 return true;
1439 }
1440 }
1441 else
1442 {
1443 if (imgFatalFun->Alpha() < 255)
1444 {
1445 // Fades in the intro image
1446 imgFatalFun->Alpha(imgFatalFun->Alpha() + 15);
1447 }
1448 }
1449
1450 return true;
1451 }
1452
1453 bool HCApp::UpdateCredits()
1454 {
1455 for (s32 i = 0; i < HCCREDITS_IMAGE_COUNT; ++i)
1456 {
1457 imgCredits[i]->Y(imgCredits[i]->Y() - 1.0f);
1458 }
1459
1460 for (s32 i = 0; i < HCCREDITS_TEXT_COUNT; ++i)
1461 {
1462 textCredits[i]->Y(textCredits[i]->Y() - 1.0f);
1463 }
1464
1465 // Updates fade-in's
1466 u8 alpha = imgCredits[HCCREDITS_DRAWING0 + outDrawing]->Alpha();
1467 if (alpha > 0)
1468 {
1469 imgCredits[HCCREDITS_DRAWING0 + outDrawing]->Alpha(alpha - 5);
1470 imgCredits[HCCREDITS_DRAWING0 + inDrawing]->Alpha(imgCredits[HCCREDITS_DRAWING0 + inDrawing]->Alpha() + 5);
1471 }
1472 else
1473 {
1474 outDrawing = inDrawing;
1475 inDrawing = inDrawing < 2 ? inDrawing + 1 : 0;
1476 }
1477
1478 alpha = imgCredits[HCCREDITS_ANIMATION0 + outAnimation]->Alpha();
1479 if (alpha > 0)
1480 {
1481 imgCredits[HCCREDITS_ANIMATION0 + outAnimation]->Alpha(alpha - 5);
1482 imgCredits[HCCREDITS_ANIMATION0 + inAnimation]->Alpha(imgCredits[HCCREDITS_ANIMATION0 + inAnimation]->Alpha() + 5);
1483 }
1484 else
1485 {
1486 outAnimation = inAnimation;
1487 inAnimation = inAnimation < 3 ? inAnimation + 1 : 0;
1488 }
1489
1490 if (imgCredits[HCCREDITS_LOGO]->Y() <= (height - imgCredits[HCCREDITS_LOGO]->Height())/2)
1491 {
1492 if (SoundEnabled() && !musicCredits.Fading())
1493 {
1494 musicCredits.FadeOut(3000);
1495 }
1496
1497
1498 // Fade out logo
1499 if (imgCredits[HCCREDITS_LOGO]->Alpha() > 0)
1500 {
1501 imgCredits[HCCREDITS_LOGO]->Alpha(imgCredits[HCCREDITS_LOGO]->Alpha() - 5);
1502
1503 if (imgCredits[HCCREDITS_LOGO]->Alpha() < 85)
1504 {
1505 textCredits[HCCREDITS_LOGO_TEXT]->Alpha(textCredits[HCCREDITS_LOGO_TEXT]->Alpha() - 15);
1506 }
1507 }
1508 else
1509 {
1510 // Done with the credits
1511 State(HCS_MENU);
1512 ProcessStateChange();
1513 }
1514 }
1515
1516 return true;
1517 }
1518
1519 bool HCApp::UpdateScript()
1520 {
1521 // Updates script elements
1522 script.Update();
1523 level.Update();
1524
1525 if (script.Finished())
1526 {
1527 State(HCS_ENDLEVEL);
1528 ProcessStateChange();
1529 }
1530
1531 return true;
1532 }
1533
1534 bool HCApp::UpdateEndLevel()
1535 {
1536 if (imgBack->Alpha() > 0)
1537 {
1538 // Fades out
1539 imgBack->Alpha(imgBack->Alpha() - 15);
1540 }
1541 else
1542 {
1543 // Next level
1544 ++levelNumber;
1545 State(HCS_PLAYING);
1546 ProcessStateChange();
1547 }
1548
1549 return true;
1550 }
1551
1552 bool HCApp::UpdateGameOver()
1553 {
1554 if (timerGeneral.TotalLap() > 4000)
1555 {
1556 if (!imgBack)
1557 {
1558 // Copies the scene as is
1559 JImage img(screen);
1560 imgBack = new JImage(img.Width(), img.Height());
1561
1562 imgBack->Paste(&img, 0, 0, img.Width(), img.Height());
1563 imgBack->Alpha(255);
1564
1565 // Reads the pause file in the correct language
1566 char str[256];
1567 snprintf(str, sizeof(str), HC_DATA_DIR "messages/%s/messages.txt", preferences.LangCodes()[preferences.CurLang()]);
1568
1569 JTextFile f;
1570 if (!f.Load(str, "rb"))
1571 {
1572 snprintf(str, sizeof(str), "Game Over");
1573 }
1574 else
1575 {
1576 f.ReadLine(str);
1577 }
1578
1579 textBack = new HCText;
1580
1581 if (!textBack->Init(HCTEXTTYPE_NARRATIVE, str, &level.Theme(), &fontLarge, JFONTALIGN_CENTER, false, 0))
1582 {
1583 return false;
1584 }
1585
1586 textBack->Pos((Width() - textBack->Image().Width())/2,
1587 (Height() - textBack->Image().Height())/2);
1588 textBack->Image().Alpha(0);
1589 }
1590
1591 if (imgBack->Alpha() > 0)
1592 {
1593 // Fades out back image and fades in the text
1594 imgBack->Alpha(imgBack->Alpha() - 15);
1595 textBack->Image().Alpha(textBack->Image().Alpha() + 15);
1596 }
1597 else
1598 {
1599 if (timerGeneral.TotalLap() > 8000)
1600 {
1601 if (textBack->Image().Alpha() > 0)
1602 {
1603 // Fades out GAME OVER text
1604 textBack->Image().Alpha(textBack->Image().Alpha() - 15);
1605 }
1606 else
1607 {
1608 State(HCS_PLAYING);
1609 ProcessStateChange();
1610 }
1611 }
1612 }
1613 }
1614 else
1615 {
1616 level.Update();
1617 }
1618
1619 return true;
1620 }
1621
1622 bool HCApp::Update()
1623 {
1624 bool ret = false;
1625
1626 UpdateEvents();
1627
1628 if (stateChanged)
1629 {
1630 ProcessStateChange();
1631 }
1632
1633 switch (state)
1634 {
1635 case HCS_MENU:
1636 ret = UpdateMenu();
1637 break;
1638
1639 case HCS_PLAYING:
1640 ret = UpdatePlaying();
1641 break;
1642
1643 case HCS_PAUSED:
1644 ret = UpdatePaused();
1645 break;
1646
1647 case HCS_INTRO:
1648 ret = UpdateIntro();
1649 break;
1650
1651 case HCS_CREDITS:
1652 ret = UpdateCredits();
1653 break;
1654
1655 case HCS_SCRIPT:
1656 ret = UpdateScript();
1657 break;
1658
1659 case HCS_GAMEOVER:
1660 ret = UpdateGameOver();
1661 break;
1662
1663 case HCS_ENDLEVEL:
1664 ret = UpdateEndLevel();
1665 break;
1666
1667 default:
1668 return false;
1669 }
1670
1671 return ret;
1672 }
1673
1674 s32 HCApp::LoadWorld()
1675 {
1676 JString str;
1677 str.Format("%s%s/level%03d.hlv", playlist.StoryDir(), playlist.StoryName(), levelNumber);
1678
1679 if (!JFile::Exists(str))
1680 {
1681 // Goes to the next story
1682 if (playlist.NextStory())
1683 {
1684 levelNumber = 1;
1685 return LoadWorld();
1686 }
1687 else
1688 {
1689 // Game end, start from the beggining
1690 playlist.Reset();
1691 levelNumber = 1;
1692
1693 return -1;
1694 }
1695 }
1696
1697 JRW f;
1698 if (!f.Create(str, "rb") ||
1699 0 != level.Load(f, str))
1700 {
1701 fprintf(stderr, "Error loading the level %s.\n", str.Str());
1702 return 0;
1703 }
1704
1705 // Centers the map within the screen
1706 level.Pos((width - level.Map().Width())/2, (height - level.Map().Height())/2);
1707
1708 return 1;
1709 }
1710
1711 HCState HCApp::State()
1712 {
1713 return state;
1714 }
1715
1716 void HCApp::State(HCState newState)
1717 {
1718 lastState = state;
1719 state = newState;
1720 stateChanged = true;
1721 }
1722
1723 void HCApp::ProcessStateChange()
1724 {
1725 stateChanged = false;
1726
1727 switch (lastState)
1728 {
1729 case HCS_PLAYING:
1730 if (state != HCS_ENDLEVEL &&
1731 state != HCS_SCRIPT &&
1732 state != HCS_PAUSED &&
1733 state != HCS_GAMEOVER)
1734 {
1735 // Frees allocated resources if not a script, paused or game over
1736 Destroy();
1737 }
1738 break;
1739
1740 case HCS_SCRIPT:
1741 if (state != HCS_ENDLEVEL &&
1742 state != HCS_PAUSED &&
1743 state != HCS_GAMEOVER)
1744 {
1745 // Frees allocated resources if not paused or game over
1746 Destroy();
1747 }
1748 break;
1749
1750 case HCS_GAMEOVER:
1751 case HCS_ENDLEVEL:
1752 case HCS_INTRO:
1753 case HCS_MENU:
1754 case HCS_CREDITS:
1755 // Frees allocated resources
1756 Destroy();
1757 break;
1758
1759 case HCS_PAUSED:
1760 level.Pause(false);
1761 JDELETE(imgBack);
1762 JDELETE(textBack);
1763 return;
1764
1765
1766 default:
1767 break;
1768 }
1769
1770 switch(state)
1771 {
1772 case HCS_INTRO:
1773 if (!InitIntro())
1774 {
1775 fprintf(stderr, "Failed to init intro. Check the manual.\n");
1776 State(HCS_MENU);
1777 ProcessStateChange();
1778 }
1779 break;
1780
1781 case HCS_MENU:
1782 if (!InitMenu())
1783 {
1784 fprintf(stderr, "Failed to init application menu. Check the manual.\n");
1785 Destroy();
1786 Exit();
1787 }
1788 break;
1789
1790 // Play!
1791 case HCS_PLAYING:
1792 if (!InitPlaying())
1793 {
1794 fprintf(stderr, "Failed to init game. Check the manual.\n");
1795 Destroy();
1796 Exit();
1797 }
1798 break;
1799
1800 case HCS_PAUSED:
1801 if (!InitPaused())
1802 {
1803 fprintf(stderr, "Failed to init pause. Check the manual.\n");
1804 State(HCS_PLAYING);
1805 ProcessStateChange();
1806 }
1807 break;
1808
1809 case HCS_GAMEOVER:
1810 if (!InitGameOver())
1811 {
1812 fprintf(stderr, "Failed to init game over. Check the manual.\n");
1813 State(HCS_PLAYING);
1814 ProcessStateChange();
1815 }
1816 break;
1817
1818 case HCS_ENDLEVEL:
1819 if (!InitEndLevel())
1820 {
1821 fprintf(stderr, "Failed to init end of level. Check the manual.\n");
1822 State(HCS_PLAYING);
1823 ProcessStateChange();
1824 }
1825 break;
1826
1827 case HCS_CREDITS:
1828 if (!InitCredits())
1829 {
1830 fprintf(stderr, "Failed to init credits. Check the manual.\n");
1831 State(HCS_MENU);
1832 ProcessStateChange();
1833 }
1834 break;
1835
1836 default:
1837 break;
1838 }
1839 }
1840
1841 void HCApp::Destroy()
1842 {
1843 JDELETE(imgBack);
1844 JDELETE(textBack);
1845 JDELETE(imgHelp);
1846 JDELETE(imgIntro);
1847 JDELETE(textIntro);
1848 JDELETE(imgMenu);
1849 JDELETE(menu);
1850 script.Destroy();
1851 level.Destroy();
1852
1853 musicMainTitle.Destroy();
1854 musicCredits.Destroy();
1855 musicGameOver.Destroy();
1856
1857 if (SoundEnabled())
1858 {
1859 mixer.Volume(-1, MIX_MAX_VOLUME);
1860 }
1861
1862 for (s32 i = 0; i < HCCREDITS_IMAGE_COUNT; ++i)
1863 {
1864 JDELETE(imgCredits[i]);
1865 }
1866
1867 for (s32 i = 0; i < HCCREDITS_TEXT_COUNT; ++i)
1868 {
1869 JDELETE(textCredits[i]);
1870 }
1871
1872 HCUtil::Destroy();
1873 }
1874
1875 // Main function
1876 int main(int argc, char **argv)
1877 {
1878 HCApp app;
1879
1880 if (app.Init(argc, argv))
1881 {
1882 return app.MainLoop();
1883 }
1884
1885 fprintf(stderr, "There was an error initializing the App.\n");
1886 return -1;
1887 }
1888
1889 void HCApp::PrintUsage(char *program)
1890 {
1891 fprintf(stderr, "Holotz's Castle v1.3.7 (C) Juan Carlos Seijo Pérez - 2004.\n\n");
1892 fprintf(stderr, "Usage: %s [-p playlist]", program);
1893 fprintf(stderr, " [-f]ullscreen [-w]indowed [--fps nnn] [-mWxHxBPP]\n");
1894 fprintf(stderr, "\n");
1895 exit(0);
1896 }
1897
1898 int HCApp::ParseArg(char *args[], int argc)
1899 {
1900 if (args[0][0]!='-')
1901 return -1;
1902
1903 switch (args[0][1])
1904 {
1905 // '-p playlist'
1906 case 'p':
1907 if (argc<1)
1908 return -2;
1909 playlistName = args[1];
1910 return 1; // 1 argument used
1911 }
1912 return JApp::ParseArg(args, argc);
1913 }
0 /*
1 * Holotz's Castle
2 * Copyright (C) 2004 Juan Carlos Seijo Pérez
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Juan Carlos Seijo Pérez
19 * jacob@mainreactor.net
20 */
21
22 /** The game of Holotz's Castle.
23 * @file HolotzCastle.h
24 * @author Juan Carlos Seijo Pérez
25 * @date 27/04/2004
26 * @version 0.0.1 - 27/04/2004 - First version.
27 */
28
29 #ifndef _HOLOTZ_INCLUDED
30 #define _HOLOTZ_INCLUDED
31
32 #include <JLib/Util/JApp.h>
33 #include <JLib/Util/JTypes.h>
34 #include <JLib/Graphics/JTextMenu.h>
35 #include <HCLevel.h>
36 #include <HCScript.h>
37 #include <HCEnemyChaser.h>
38 #include <HCPreferences.h>
39 #include <HCPlaylist.h>
40 #include <HCLoadSaveSlot.h>
41 #include <HCUtil.h>
42
43 class HCScript;
44 class HCScriptAction;
45 class HCEnemy;
46 class HCEnemyChaser;
47
48 #define ACKNOWLEDGEMENTS \
49 "Special thanks go to:\n"\
50 " \n"\
51 "Martinica (the best beta-tester mother),\n"\
52 "Bebo, Ampis & Roberto & Oscar, Padre, Cris &\n"\
53 "Rafa & Lucía & Paula & Rafael\n"\
54 "Quique & Marga & Jorge & Javier,\n"\
55 "Carlos & Julia & Jorge & Jose\n"\
56 "Ana & Nathan & María & Marco,\n"\
57 "Jorge & Amelia & Alejandro,\n"\
58 "Carlos & Vero & Álvaro & Irene, Edu & Vero,\n"\
59 "Alex, Chily, Santos & Rocío & África, Félix &\n"\
60 "Carmen, Ossuna's, Jose & Gloria, Ori &\n"\
61 "Loli, Diana & David, Luis,\n"\
62 "Ángel, Celia, Íñigo,\n"\
63 "Markus Rath/Ronny Standtke (German translation),\n"\
64 "Milan Babuškov (Add-on levels),\n"\
65 "Miriam Ruiz (Debian package),\n"\
66 "Nicolas Elie (French translation),\n"\
67 "Вячеслав Диконов \n(Vyacheslav Dikonov - Russian translation),\n"\
68 "3ARRANO Euskalgintza (Euskara translation),\n"\
69 "Andreas Jochens (AMD64 Patches),\n"\
70 "Maksim Mokriyev (Ukranian translation)\n"\
71 "Filip (Triple T) Bártek (Czech translation)\n"\
72 "Pierre-Paul Lavoie (FreeBSD porting)\n"\
73 "Filipe Silva (Portuguese translation)\n"\
74 "Ben Wong (English translation, patches)\n"\
75 "Federico 'hs1' Tolomei (Italian translation)\n"\
76 "Jarno van der Kolk (Dutch translation/Joystick)\n"\
77 "Jason Woofenden (PPC Patches)\n"\
78 "Syltbullen (Swedish translation)\n"\
79 "Nikola Smolenski (Serbian translation)\n"\
80 "...and you for playing!"
81
82 /** Possible states of the game.
83 */
84 typedef enum
85 {
86 HCS_MENU = 1, /**< Showing main menu. */
87 HCS_PLAYING, /**< Playing. */
88 HCS_PAUSED, /**< Paused. */
89 HCS_INTRO, /**< Intro. */
90 HCS_CREDITS, /**< Game Credits. */
91 HCS_SCRIPT, /**< Scripted level. */
92 HCS_ENDLEVEL, /**< Level ends. */
93 HCS_GAMEOVER, /**< Game over. */
94 HCS_HELP, /**< Help. */
95 } HCState;
96
97 typedef enum
98 {
99 HCCREDITS_PROGRAMMING = 0, /**< Programming image. */
100 HCCREDITS_STORY, /**< Story image. */
101 HCCREDITS_DRAWING0, /**< Drawing 1st image. */
102 HCCREDITS_DRAWING1, /**< Drawing 2nd image. */
103 HCCREDITS_DRAWING2, /**< Drawing 3rd image. */
104 HCCREDITS_ANIMATION0, /**< Animation 1st image. */
105 HCCREDITS_ANIMATION1, /**< Animation 2nd image. */
106 HCCREDITS_ANIMATION2, /**< Animation 3rd image. */
107 HCCREDITS_ANIMATION3, /**< Animation 4th image. */
108 HCCREDITS_MUSIC, /**< Music image. */
109 HCCREDITS_HOLOTZCASTLE, /**< Holotz's castle image. */
110 HCCREDITS_LOGO, /**< Mainrector image. */
111 HCCREDITS_IMAGE_COUNT /**< Number of images. */
112 } HCCreditsImageType;
113
114 typedef enum
115 {
116 HCCREDITS_PROGRAMMING_TEXT = 0, /**< Programming text. */
117 HCCREDITS_STORY_TEXT, /**< Story text. */
118 HCCREDITS_DRAWING_TEXT, /**< Drawing 1st text. */
119 HCCREDITS_ANIMATION_TEXT, /**< Animation 1st text. */
120 HCCREDITS_MUSIC_TEXT, /**< Music text. */
121 HCCREDITS_HOLOTZCASTLE_TEXT, /**< Holotz's castle text. */
122 HCCREDITS_LOGO_TEXT, /**< Holotz's castle text. */
123 HCCREDITS_ACK_TEXT, /**< Acknowledgements text. */
124 HCCREDITS_TEXT_COUNT /**< Number of texts. */
125 } HCCreditsTextType;
126
127 #define HC_NUM_SLOTS 5 /**< Number of slots to save and load. */
128
129 /** Application class.
130 */
131 class HCApp : public JApp
132 {
133 protected:
134 HCState lastState; /**< Last state of the game. */
135 HCState state; /**< Current state of the game. */
136
137 JImage *imgMenu; /**< Main title background. */
138 JTextMenu *menu; /**< Application menu. */
139
140 JImage *imgCredits[HCCREDITS_IMAGE_COUNT]; /**< Credits images. */
141 JImage *textCredits[HCCREDITS_TEXT_COUNT]; /**< Credits texts. */
142 s32 inDrawing; /**< Current drawing fading in. */
143 s32 outDrawing; /**< Current drawing fading out. */
144 s32 inAnimation; /**< Current animation fading in. */
145 s32 outAnimation; /**< Current animation fading out. */
146
147 HCPreferences preferences; /**< Preferences for the game. */
148 HCPlaylist playlist; /**< Playlist with the story order. */
149 char *playlistName; /**< Name of the playlist. */
150
151 JTimer timerGeneral; /**< Timer for general use. */
152 JImage *imgIntro; /**< Intro image (MainReactor). */
153 JImage *imgFatalFun; /**< Intro image (Fatalfun). */
154 JImage *textIntro; /**< Intro text (Presents...). */
155
156 HCLevel level; /**< Game level. */
157 HCScript script; /**< Level script. */
158 s32 levelNumber; /**< Current level within the current world. */
159
160 JChunk musicMainTitle; /**< Main title screen music. */
161 JChunk musicCredits; /**< Credits screen music. */
162 JChunk musicGameOver; /**< Game over screen music. */
163 JChunk musicBeginLevel; /**< Start-of-level music. */
164
165 JFont fontSmall; /**< Small font. */
166 JFont fontMedium; /**< Medium font. */
167 JFont fontLarge; /**< Large font. */
168
169 JImage *imgBack; /**< Image for background storing. */
170 HCText *textBack; /**< General purpouse text message. */
171 JImage *imgHelp; /**< Help text message. */
172
173 HCLoadSaveSlot saveData[HC_NUM_SLOTS];/**< Slots for loading and saving. */
174
175 bool stateChanged; /**< App state change flag */
176
177 /** Initializes the menu state.
178 * @return <b>true</b> if initialization succeeded, <b>false</b> if not.
179 */
180 bool InitMenu();
181
182 /** Initializes the intro state.
183 * @return <b>true</b> if initialization succeeded, <b>false</b> if not.
184 */
185 bool InitIntro();
186
187 /** Initializes the paused state.
188 * @return <b>true</b> if initialization succeeded, <b>false</b> if not.
189 */
190 bool InitPaused();
191
192 /** Initializes the playing state.
193 * @return <b>true</b> if initialization succeeded, <b>false</b> if not.
194 */
195 bool InitPlaying();
196
197 /** Initializes the game over state.
198 * @return <b>true</b> if initialization succeeded, <b>false</b> if not.
199 */
200 bool InitGameOver();
201
202 /** Initializes the end level state.
203 * @return <b>true</b> if initialization succeeded, <b>false</b> if not.
204 */
205 bool InitEndLevel();
206
207 /** Initializes the credits state.
208 * @return <b>true</b> if initialization succeeded, <b>false</b> if not.
209 */
210 bool InitCredits();
211
212 /** Initializes the help text.
213 * @return <b>true</b> if initialization succeeded, <b>false</b> if not.
214 */
215 bool InitHelp();
216
217 /** Destroys the help text.
218 */
219 void DestroyHelp();
220
221 /** Initializes the data slot for loading and saving.
222 * @return <b>true</b> if initialization succeeded, <b>false</b> if not.
223 */
224 bool InitSlots();
225
226 /** Initializes the sound.
227 * @return <b>true</b> if initialization succeeded, <b>false</b> if not.
228 */
229 bool InitSound();
230
231 /** (Re)initializes the fonts.
232 * @return <b>true</b> if initialization succeeded, <b>false</b> if not.
233 */
234 bool InitFonts();
235
236 /** Callback: App exit.
237 * @param data App.
238 */
239 static void OnExit(void *data);
240
241 /** Callback: Credits.
242 * @param data App.
243 */
244 static void OnCredits(void *data);
245
246 /** Callback: Difficulty level select.
247 * @param data Value casted to s32, HCPREFERENCES_EASY or HCPREFERENCES_NORMAL or HCPREFERENCES_HARD.
248 */
249 static void OnDifficulty(void *data);
250
251 /** Callback: Sound select.
252 * @param data Value casted to s32, 0 to turn off and 1 to turn on.
253 */
254 static void OnSound(void *data);
255
256 /** Callback: New game.
257 */
258 static void OnNew(void *data);
259
260 /** Callback: Continue game.
261 */
262 static void OnContinue(void *data);
263
264 /** Callback: Help.
265 */
266 static void OnHelp(void *data);
267
268 /** Callback: video mode select.
269 * @param data Mode number according to preferences casted to a s32.
270 */
271 static void OnVideoMode(void *data);
272
273 /** Callback: Color depth select.
274 * @param data BPP casted to a s32.
275 */
276 static void OnBPP(void *data);
277
278 /** Callback: Window mode select.
279 * @param data Window mode casted to s32.
280 */
281 static void OnWindowMode(void *data);
282
283 /** Callback: Language select.
284 * @param data Language index according to preferences casted to a s32.
285 */
286 static void OnLanguage(void *data);
287
288 /** Callback: Restore defaults.
289 * @param data Null.
290 */
291 static void OnDefaults(void *data);
292
293 /** Callback: Load game.
294 * @param data Slot number to load from.
295 */
296 static void OnLoad(void *data);
297
298 /** Callback: Save game.
299 * @param data Slot number to save to.
300 */
301 static void OnSave(void *data);
302
303 /** Draws the menu.
304 * @return <b>true</b> if drawing succeeded, <b>false</b> if not.
305 */
306 bool DrawMenu();
307
308 /** Draws the game.
309 * @return <b>true</b> if drawing succeeded, <b>false</b> if not.
310 */
311 bool DrawPlaying();
312
313 /** Draws the game paused.
314 * @return <b>true</b> if drawing succeeded, <b>false</b> if not.
315 */
316 bool DrawPaused();
317
318 /** Draws the game in the ending level state.
319 * @return <b>true</b> if drawing succeeded, <b>false</b> if not.
320 */
321 bool DrawEndLevel();
322
323 /** Draws the game in the game over state.
324 * @return <b>true</b> if drawing succeeded, <b>false</b> if not.
325 */
326 bool DrawGameOver();
327
328 /** Draws the hall of fame.
329 * @return <b>true</b> if drawing succeeded, <b>false</b> if not.
330 */
331 bool DrawIntro();
332
333 /** Draws the credits.
334 * @return <b>true</b> if drawing succeeded, <b>false</b> if not.
335 */
336 bool DrawCredits();
337
338 /** Draws the load state.
339 * @return <b>true</b> if drawing succeeded, <b>false</b> if not.
340 */
341 bool DrawLoad();
342
343 /** Draws the save state.
344 * @return <b>true</b> if drawing succeeded, <b>false</b> if not.
345 */
346 bool DrawSave();
347
348 /** Draws the scripted level.
349 * @return <b>true</b> if drawing succeeded, <b>false</b> if not.
350 */
351 bool DrawScript();
352
353 /** Updates the menu.
354 * @return <b>true</b> if updating succeeded, <b>false</b> if not.
355 */
356 bool UpdateMenu();
357
358 /** Updates the game.
359 * @return <b>true</b> if updating succeeded, <b>false</b> if not.
360 */
361 bool UpdatePlaying();
362
363 /** Updates the game paused.
364 * @return <b>true</b> if updating succeeded, <b>false</b> if not.
365 */
366 bool UpdatePaused();
367
368 /** Updates the game in the ending level state.
369 * @return <b>true</b> if updateing succeeded, <b>false</b> if not.
370 */
371 bool UpdateEndLevel();
372
373 /** Updates the game in the game over state.
374 * @return <b>true</b> if updateing succeeded, <b>false</b> if not.
375 */
376 bool UpdateGameOver();
377
378 /** Updates the hall of fame.
379 * @return <b>true</b> if updating succeeded, <b>false</b> if not.
380 */
381 bool UpdateIntro();
382
383 /** Updates the credits.
384 * @return <b>true</b> if updating succeeded, <b>false</b> if not.
385 */
386 bool UpdateCredits();
387
388 /** Updates the load state.
389 * @return <b>true</b> if updating succeeded, <b>false</b> if not.
390 */
391 bool UpdateLoad();
392
393 /** Updates the save state.
394 * @return <b>true</b> if updating succeeded, <b>false</b> if not.
395 */
396 bool UpdateSave();
397
398 /** Updates the script.
399 * @return <b>true</b> if updating succeeded, <b>false</b> if not.
400 */
401 bool UpdateScript();
402
403 /** Loads the current world/level.
404 * @return 1 if loading succeeded, 0 if not, -1 if game ended.
405 */
406 s32 LoadWorld();
407
408 /** Process key up events.
409 */
410 static void OnKeyUp(SDL_keysym key);
411
412 /** Process key down events.
413 */
414 static void OnKeyDown(SDL_keysym key);
415
416 /** Process the state change of the app.
417 */
418 void ProcessStateChange();
419
420 public:
421 /** Creates the application object.
422 */
423 HCApp();
424
425 /** Initializes the application.
426 * @param argc Argument count from the command line, as in main().
427 * @param argv Argument list from the command line, as in main().
428 * @return <b>true</b> if initialization is ok, <b>false</b> if not.
429 */
430 bool Init(s32 argc = 0, char **argv = 0);
431
432 /** Draws the application.
433 * @return <b>true</b> if drawing succeeded, <b>false</b> if not.
434 */
435 bool Draw();
436
437 /** Updates the application.
438 * @return <b>true</b> if update succeeded, <b>false</b> if not.
439 */
440 bool Update();
441
442 /** Returns the state of the app.
443 * @return State of the app.
444 */
445 inline HCState State();
446
447 /** Changes the state of the app.
448 * @param newState New state of the app.
449 */
450 void State(HCState newState);
451
452 /** Process user input.
453 */
454 void ProcessInput();
455
456 /** Returns the current level.
457 * @return Current level.
458 */
459 HCLevel *Level() {return &level;}
460
461 /** Returns the small font.
462 * @return Small font.
463 */
464 JFont *FontSmall() {return &fontSmall;}
465
466 /** Returns the medium font.
467 * @return Medium font.
468 */
469 JFont *FontMedium() {return &fontMedium;}
470
471 /** Returns the large font.
472 * @return Large font.
473 */
474 JFont *FontLarge() {return &fontLarge;}
475
476 /** Parses argument.
477 * @param args Command line arguments.
478 * @param argc Arguments left.
479 * @return Number of parameters used.
480 */
481 virtual int ParseArg(char *args[], int argc);
482
483 /** Shows the usage string.
484 */
485 virtual void PrintUsage(char *program);
486
487 /** Frees the allocated resources.
488 */
489 void Destroy();
490
491 /** Destroys the application object.
492 */
493 virtual ~HCApp() {Destroy();}
494
495 friend void OnKeyUp(SDL_keysym key);
496 };
497
498 #endif // _HOLOTZ_INCLUDED
0 # Makefile Para Holotz's Castle. (C) Juan Carlos Seijo Pérez - 2004.
1 # Makefile for Holotz's Castle.
2
3 ifndef SDL_CONFIG
4 SDL_CONFIG = sdl-config
5 endif
6
7 # Uncomment these lines if you don't want to install the game. Then
8 # you'll only be able to execute it from the directory it is in.
9 # Also comment lines bellow.
10 # Descomenta estas l�neas si no quieres instalar el juego. S�lo
11 # podr�s ejecutarlo desde el directorio donde est�.
12 # Comenta las l�neas m�s abajo.
13 ifdef I486_BUILD
14 HC_DATA = res/
15 HCED_DATA = HCedHome/res/
16 endif
17
18 # Edit these lines to change the data and game installation dirs or
19 # comment out these lines to not install the game (also uncomment lines above)
20 # Edita estas l�neas para cambiar el directorio de instalaci�n de datos y del juego o bien
21 # comenta estas l�neas si no quieres instalar el juego (y descomenta las de arriba)
22
23 ifndef I486_BUILD
24 HC_BASE = /usr/share/games/holotz-castle/
25 HC_DATA = $(HC_BASE)game/
26 HCED_DATA = $(HC_BASE)editor/
27 HC_BIN_DIR = /usr/local/bin/
28 endif
29
30 DEFINES = -DHC_DATA_DIR=\"$(HC_DATA)\" -DHCED_DATA_DIR=\"$(HCED_DATA)\"
31
32 all: JLib HC HCed
33
34 HC_OBJ_MAIN=HolotzCastle.o
35 HC_OBJS=HCUtil.o HCTimer.o HCLoadSaveSlot.o HCPlaylist.o HCPreferences.o HCTheme.o HCText.o \
36 HCBreak.o HCRope.o HCContFloor.o HCObject.o HCMap.o HCExit.o HCCharacter.o \
37 HCEnemy.o HCEnemyBall.o HCEnemyChaser.o HCEnemyMaker.o HCEnemyRandom.o \
38 HCEnemyStatic.o HCScriptAction.o HCScriptBlock.o HCScript.o HCLevel.o
39
40 HCED_OBJ_MAIN=HCed.o
41
42 # Definir -D_JLIB_DEBUG para debug con JLib. Ponerlo también en el Makefile de JLib.
43 # Define -D_JLIB_DEBUG for JLib debug mode. Put it also in JLib's Makefile.
44 CFLAGS=-fno-strict-aliasing -I. -I../JLib `$(SDL_CONFIG) --cflags` -I/usr/local/include/ -I/usr/local/include/SDL -O3 -Wall -Werror -Wshadow $(CPU_OPTS) -ffast-math -c
45 LDFLAGS=-L. -ffast-math -lSDL_image -lSDL_ttf -lSDL_mixer `$(SDL_CONFIG) --libs`
46
47
48 JLib:
49 $(MAKE) -C ../JLib;
50
51 %.o: %.cpp %.h
52 g++ $(CFLAGS) $(DEFINES) $< -o $@
53
54 HC: $(HC_OBJS) $(HC_OBJ_MAIN) ../JLib/libJLib.a
55 g++ $(LDFLAGS) $? -o $@;\
56 mv HC ../holotz-castle
57
58 # HCed (Holotz's Castle editor).
59 HCed: $(HC_OBJS) $(HCED_OBJ_MAIN) ../JLib/libJLib.a
60 g++ $(LDFLAGS) $? -o $@;\
61 mv HCed ../holotz-castle-editor
62
63 install:
64 mkdir -p $(HC_DATA);\
65 mkdir -p $(HCED_DATA);\
66 chmod -R a+rx $(HC_DATA) $(HCED_DATA);\
67 mkdir -p $(HC_BIN_DIR);\
68 cp -r ../res/[^H]* $(HC_DATA) && cp -r ../HCedHome/res/* $(HCED_DATA);\
69 chmod -R a+x ../holotz-castle ../holotz-castle-editor;\
70 cp ../holotz-castle ../holotz-castle-editor $(HC_BIN_DIR);\
71 chmod -R a+r $(HC_DATA) $(HCED_DATA);
72
73 uninstall:
74 rm -rf $(HC_BASE);\
75 rm -f $(HC_BIN_DIR)holotz-castle $(HC_BIN_DIR)holotz-castle-editor;\
76
77 .PHONY: clean
78 clean:
79 rm -f ../holotz-castle;\
80 rm -f ../holotz-castle-editor;\
81 rm -f *\.o;\
82 $(MAKE) -C ../JLib clean
0 # Makefile Para Holotz's Castle. (C) Juan Carlos Seijo Pérez - 2004.
1 # Makefile for Holotz's Castle.
2
3
4
5 HC_DATA = res/
6 HCED_DATA = HCedHome/res/
7
8 DEFINES = -DHC_DATA_DIR=\"$(HC_DATA)\" -DHCED_DATA_DIR=\"$(HCED_DATA)\"
9
10 all: JLib HC HCed
11
12 HC_OBJ_MAIN=HolotzCastle.o
13 HC_OBJS=HCUtil.o HCTimer.o HCLoadSaveSlot.o HCPlaylist.o HCPreferences.o HCTheme.o HCText.o \
14 HCBreak.o HCRope.o HCContFloor.o HCObject.o HCMap.o HCExit.o HCCharacter.o \
15 HCEnemy.o HCEnemyBall.o HCEnemyChaser.o HCEnemyMaker.o HCEnemyRandom.o \
16 HCEnemyStatic.o HCScriptAction.o HCScriptBlock.o HCScript.o HCLevel.o
17
18 HCED_OBJ_MAIN=HCed.o
19
20 # Definir -D_JLIB_DEBUG para debug con JLib. Ponerlo también en el Makefile de JLib.
21 # Define -D_JLIB_DEBUG for JLib debug mode. Put it also in JLib's Makefile.
22
23 CFLAGS=-O3 -Wshadow -ffast-math -c -I/mingw/include/SDL -I../JLib -I. -I/mingw/include -I/usr/local/include -I/usr/include $(shell sdl-config --cflags) -D_WIN32 -DWIN32
24
25 LDFLAGS=-s -L/mingw/lib -L/usr/lib -L/usr/local/lib -mwindows -ffast-math -lglu32 -lopengl32 -lgdi32 -lcomctl32 -lwsock32 -lmingw32 -lSDLmain -lSDL -lSDL_image -lSDL_mixer -lSDL_ttf -lzdll
26
27 JLib:
28 make -C ../JLib -f Makefile.win32;
29
30 %.o: %.cpp %.h
31 g++ $(CFLAGS) $(DEFINES) $< -o $@
32
33 HC: $(HC_OBJS) $(HC_OBJ_MAIN) ../JLib/libJLib.a
34 g++ $? -o $@ $(LDFLAGS);\
35 mv $@.exe ../holotz-castle.exe
36
37 # HCed (Holotz's Castle editor).
38 HCed: $(HC_OBJS) $(HCED_OBJ_MAIN) ../JLib/libJLib.a
39 g++ $? -o $@ $(LDFLAGS);\
40 mv $@.exe ../holotz-castle-editor.exe
41
42 .PHONY: clean
43 clean:
44 rm *.o
45 rm ../holotz-castle.exe
46 rm ../holotz-castle-editor.exe
47