1 /*
2 * Holotz's Castle
3 * Copyright (C) 2004 Juan Carlos Seijo P�rez
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc., 59
17 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * Juan Carlos Seijo P�rez
20 * jacob@mainreactor.net
21 */
22
23 /** Map definition file for Holotz's Castle.
24 * @file HCMap.cpp
25 * @author Juan Carlos Seijo P�rez
26 * @date 29/04/2004
27 * @version 0.0.1 - 29/04/2004 - First version.
28 */
29
30 #include <HCMap.h>
31
HCMap()32 HCMap::HCMap()
33 {
34 cells = 0;
35 rows = cols = cellWidth = cellHeight = 0;
36 width = height = 0;
37 exitRow = exitCol = 0;
38 linkCells = 0;
39
40 //gravity = 0.7f;
41 gravity = 0.9f;
42 }
43
Init(HCTheme & _theme)44 bool HCMap::Init(HCTheme &_theme)
45 {
46 cells = 0;
47 rows = cols = 0;
48 width = height = 0;
49 exitRow = exitCol = 0;
50
51 theme = &_theme;
52
53 // Inits common parameters
54 cellWidth = theme->Floor(0).Width();
55 cellHeight = theme->Floor(0).Height();
56
57 Pos(0, 0);
58
59 return true;
60 }
61
Update()62 s32 HCMap::Update()
63 {
64 HCMapCell *mc = linkCells;
65
66 while (mc)
67 {
68 mc->cell->Update();
69 mc = mc->next;
70 }
71
72 return 1;
73 }
74
Draw()75 void HCMap::Draw()
76 {
77 HCMapCell *mc = linkCells;
78
79 while (mc)
80 {
81 mc->cell->Draw();
82 mc = mc->next;
83 }
84 }
85
Pos(float xPos,float yPos)86 void HCMap::Pos(float xPos, float yPos)
87 {
88 pos.x = xPos;
89 pos.y = yPos;
90
91 for (s32 j = 0; j < rows; ++j)
92 {
93 for (s32 i = 0; i < cols; ++i)
94 {
95 cells[j][i]->Pos(xPos + (i * cellWidth), yPos + (j * cellHeight));
96 }
97 }
98 }
99
ScreenToMap(s32 & xPos,s32 & yPos)100 void HCMap::ScreenToMap(s32 &xPos, s32 &yPos)
101 {
102 xPos = ToCol(xPos);
103 yPos = ToRow(yPos);
104 }
105
MapToScreen(s32 & col,s32 & row)106 void HCMap::MapToScreen(s32 &col, s32 &row)
107 {
108 col = ToX(col);
109 row = ToY(row);
110
111 // Adds the map offset and the distance to the baseline's mid-point
112 col += (s32)pos.x + cellWidth/2;
113 row += (s32)Y() + cellHeight - 1;
114 }
115
ToCol(s32 xx)116 s32 HCMap::ToCol(s32 xx)
117 {
118 // Removes map offsets
119 xx -= (s32)pos.x;
120
121 if (xx < 0)
122 {
123 return 0;
124 }
125
126 xx /= cellWidth;
127
128 return (xx > cols-1 ? cols-1 : xx);
129 }
130
ToRow(s32 yy)131 s32 HCMap::ToRow(s32 yy)
132 {
133 // Removes map offsets
134 yy -= (s32)pos.y;
135
136 if (yy < 0)
137 {
138 return 0;
139 }
140
141 yy /= cellHeight;
142
143 return (yy > rows-1 ? rows-1 : yy);
144 }
145
ToX(s32 col)146 s32 HCMap::ToX(s32 col)
147 {
148 col *= cellWidth;
149
150 // Adds the map offset and the distance to the baseline's mid-point
151 col += (s32)pos.x + cellWidth/2;
152 return col;
153 }
154
ToY(s32 row)155 s32 HCMap::ToY(s32 row)
156 {
157 row *= cellHeight;
158
159 // Adds the map offset and the distance to the baseline's mid-point
160 row += (s32)pos.y + cellHeight - 1;
161 return row;
162 }
163
Resize(s32 newRows,s32 newCols,bool growRight,bool growDown)164 void HCMap::Resize(s32 newRows, s32 newCols, bool growRight, bool growDown)
165 {
166 if (newRows == 0 || newCols == 0)
167 {
168 // Only destroys the cells
169 Destroy();
170
171 return;
172 }
173
174 HCCell ***newCells;
175
176 // Creates the map cells
177 newCells = new HCCell **[newRows];
178
179 for (s32 j = 0; j < newRows; ++j)
180 {
181 newCells[j] = new HCCell *[newCols];
182 memset(newCells[j], 0, sizeof(HCCell*) * newCols);
183 }
184
185 if (cells != 0)
186 {
187 s32 maxRows = rows > newRows ? newRows : rows;
188 s32 maxCols = cols > newCols ? newCols : cols;
189
190 // Copies the existing cells, reducing, if necessary from the top right
191 // corner. Defaults the rest of the cells, in case of enlargement, to blank
192 for (s32 row = 0; row < newRows; ++row)
193 {
194 for (s32 col = 0; col < newCols; ++col)
195 {
196 if (row < maxRows && col < maxCols)
197 {
198 // while reducing
199 if (growDown)
200 {
201 if (growRight)
202 {
203 newCells[row][col] = cells[row][col];
204 cells[row][col] = 0;
205 }
206 else
207 {
208 newCells[row][newCols - 1 - col] = cells[row][cols - col - 1];
209 cells[row][cols - col - 1] = 0;
210 }
211 }
212 else
213 {
214 if (growRight)
215 {
216 newCells[newRows - 1 - row][col] = cells[rows - row - 1][col];
217 cells[rows - row - 1][col] = 0;
218 }
219 else
220 {
221 newCells[newRows - 1 - row][newCols - 1 - col] = cells[rows - row - 1][cols - col - 1];
222 cells[rows - row - 1][cols - col - 1] = 0;
223 }
224 }
225 }
226 else
227 {
228 // If enlarging
229 if (growDown)
230 {
231 if (growRight)
232 {
233 newCells[row][col] = new HCCell; // Grows down-right
234 }
235 else
236 {
237 newCells[row][newCols - 1 - col] = new HCCell; // Grows down-left
238 }
239 }
240 else
241 {
242 if (growRight)
243 {
244 newCells[newRows - 1 - row][col] = new HCCell; // Grows up-left
245 }
246 else
247 {
248 newCells[newRows - 1 - row][newCols - 1 - col] = new HCCell; // Grows up-right
249 }
250 }
251 }
252 }
253 }
254
255 // Destroy the rest of the original cells if reducing
256 Destroy();
257 }
258 else
259 {
260 // Initializes the map to empty cells
261 for (s32 row = 0; row < newRows; ++row)
262 {
263 for (s32 col = 0; col < newCols; ++col)
264 {
265 newCells[row][col] = new HCCell;
266 }
267 }
268 }
269
270 cells = newCells;
271 rows = newRows;
272 cols = newCols;
273 width = cellWidth * cols;
274 height = cellHeight * rows;
275
276 Pos(pos.x, pos.y);
277
278 BuildCellLinkList();
279 }
280
Destroy()281 void HCMap::Destroy()
282 {
283 if (0 != cells)
284 {
285 for (s32 row = 0; row < rows; ++row)
286 {
287 for (s32 col = 0; col < cols; ++col)
288 {
289 JDELETE(cells[row][col]);
290 }
291
292 delete[] cells[row];
293 cells[row] = 0;
294 }
295
296 delete[] cells;
297 cells = 0;
298 }
299
300 DestroyCellLinkList();
301 }
302
BuildContFloorOnce(s32 row,s32 col)303 void HCMap::BuildContFloorOnce(s32 row, s32 col)
304 {
305 if (cells[row][col]->Type() == HCCELLTYPE_CONTFLOOR)
306 {
307 ((HCContFloor *)cells[row][col])->Build(theme->ContFloor(cells[row][col]->Subtype()),
308 cells[row-1][col-1]->Type() == HCCELLTYPE_CONTFLOOR,
309 cells[row-1][col]->Type() == HCCELLTYPE_CONTFLOOR,
310 cells[row-1][col+1]->Type() == HCCELLTYPE_CONTFLOOR,
311 cells[row][col-1]->Type() == HCCELLTYPE_CONTFLOOR,
312 cells[row][col+1]->Type() == HCCELLTYPE_CONTFLOOR,
313 cells[row+1][col-1]->Type() == HCCELLTYPE_CONTFLOOR,
314 cells[row+1][col]->Type() == HCCELLTYPE_CONTFLOOR,
315 cells[row+1][col+1]->Type() == HCCELLTYPE_CONTFLOOR);
316 }
317 }
318
BuildContFloor(s32 row,s32 col)319 void HCMap::BuildContFloor(s32 row, s32 col)
320 {
321 BuildContFloorOnce(row - 1, col - 1);
322 BuildContFloorOnce(row - 1, col);
323 BuildContFloorOnce(row - 1, col + 1);
324 BuildContFloorOnce(row, col - 1);
325 BuildContFloorOnce(row, col);
326 BuildContFloorOnce(row, col + 1);
327 BuildContFloorOnce(row + 1, col - 1);
328 BuildContFloorOnce(row + 1, col);
329 BuildContFloorOnce(row + 1, col + 1);
330 }
331
BuildCellLinkList()332 void HCMap::BuildCellLinkList()
333 {
334 DestroyCellLinkList();
335
336 HCMapCell *mc = 0, *mcOld = 0;
337
338 for (s32 row = 0; row < rows; ++row)
339 {
340 for (s32 col = 0; col < cols; ++col)
341 {
342 if (cells[row][col]->Type() != HCCELLTYPE_BLANK)
343 {
344 mc = new HCMapCell;
345 mc->cell = cells[row][col];
346
347 if (mcOld)
348 {
349 mcOld->next = mc;
350 }
351
352 if (!linkCells)
353 {
354 linkCells = mc;
355 }
356
357 mcOld = mc;
358 }
359 }
360 }
361
362 if (mc)
363 {
364 mc->next = 0;
365 }
366 }
367
DestroyCellLinkList()368 void HCMap::DestroyCellLinkList()
369 {
370 if (0 != linkCells)
371 {
372 HCMapCell *mc = linkCells, *tmp;
373
374 while (mc)
375 {
376 tmp = mc->next;
377 delete mc;
378 mc = tmp;
379 }
380
381 linkCells = 0;
382 }
383 }
384
Load(JRW & f)385 u32 HCMap::Load(JRW &f)
386 {
387 Destroy();
388
389 // Loads the number of rows and cols, etc.
390 if (0 == f.ReadLE32((u32 *)&gravity) ||
391 0 == f.ReadLE32(&rows) ||
392 0 == f.ReadLE32(&cols) ||
393 0 == f.ReadLE32(&exitRow) ||
394 0 == f.ReadLE32(&exitCol))
395 {
396 return 1;
397 }
398
399 Resize(rows, cols);
400
401 // Loads the cells
402 s32 ret = 1;
403 s32 t, subt;
404 HCBreak *prevBreak = 0;
405
406 for (s32 row = 0; ret != 0 && row < rows; ++row)
407 {
408 for (s32 col = 0; ret != 0 && col < cols; ++col)
409 {
410 ret = f.ReadLE32(&t);
411 ret = f.ReadLE32(&subt);
412
413 if (t != HCCELLTYPE_BREAK)
414 {
415 prevBreak = 0;
416 }
417
418 JDELETE(cells[row][col]);
419
420 switch (t)
421 {
422 case HCCELLTYPE_FLOOR:
423 cells[row][col] = new HCFloorCell(&(theme->Floor(subt)));
424 cells[row][col]->Subtype(subt);
425 break;
426
427 case HCCELLTYPE_CONTFLOOR:
428 cells[row][col] = new HCContFloor;
429 cells[row][col]->Subtype(subt);
430 break;
431
432 case HCCELLTYPE_BAR:
433 cells[row][col] = new HCBarCell(&(theme->Bar(subt)));
434 cells[row][col]->Subtype(subt);
435 break;
436
437 case HCCELLTYPE_LADDER:
438 cells[row][col] = new HCLadderCell(&(theme->Ladder(subt)));
439 cells[row][col]->Subtype(subt);
440 break;
441
442 case HCCELLTYPE_BREAK:
443 cells[row][col] = prevBreak = new HCBreak(theme->Break(subt), prevBreak);
444 cells[row][col]->Subtype(subt);
445 break;
446
447 case HCCELLTYPE_BLANK:
448 default:
449 cells[row][col] = new HCCell;
450 cells[row][col]->Subtype(subt);
451 break;
452 }
453
454 t = cells[row][col]->Type();
455 }
456 }
457
458 for (s32 row = 1; ret != 0 && row < rows - 1; ++row)
459 {
460 for (s32 col = 1; ret != 0 && col < cols - 1; ++col)
461 {
462 if (cells[row][col]->Type() == HCCELLTYPE_CONTFLOOR)
463 BuildContFloor(row, col);
464 }
465 }
466
467 BuildCellLinkList();
468
469 return 0;
470 }
471
Save(JRW & f)472 u32 HCMap::Save(JRW &f)
473 {
474 // Saves the number of rows and cols, etc.
475 if (0 == f.WriteLE32((u32 *)&gravity) ||
476 0 == f.WriteLE32(&rows) ||
477 0 == f.WriteLE32(&cols) ||
478 0 == f.WriteLE32(&exitRow) ||
479 0 == f.WriteLE32(&exitCol))
480 {
481 return 1;
482 }
483
484 // Saves the cells
485 s32 ret = 1;
486 s32 data, index;
487
488 for (s32 row = 0; ret != 0 && row < rows; ++row)
489 {
490 for (s32 col = 0; ret != 0 && col < cols; ++col)
491 {
492 data = cells[row][col]->Type();
493 index = cells[row][col]->Subtype();
494 ret = f.WriteLE32(&data);
495 ret = f.WriteLE32(&index);
496 }
497 }
498
499 return 0;
500 }
501