source: trunk/src/map.cpp @ 664

Last change on this file since 664 was 633, checked in by sam, 10 years ago

TileSets can now be initialised either using the tile size, or the
known number of tiles in a row and a column. Necessary for ticket #24.

  • Property svn:keywords set to Id
File size: 4.6 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <cstdio>
16#include <cstring>
17#include <cstdlib>
18#include <cmath>
19#include <ctype.h>
20
21#include "core.h"
22
23/*
24 * Map implementation class
25 */
26
27class MapData
28{
29    friend class Map;
30
31    static int const MAX_TILERS = 128;
32
33private:
34    int tilers[MAX_TILERS];
35    int ntilers;
36
37    Layer **layers;
38    int nlayers;
39
40    int width, height;
41};
42
43/*
44 * Public Map class
45 */
46
47Map::Map(char const *path)
48  : data(new MapData())
49{
50    data->ntilers = 0;
51    data->layers = NULL;
52    data->nlayers = 0;
53    data->width = 0;
54    data->height = 0;
55
56    char tmp[BUFSIZ];
57    int gids[MapData::MAX_TILERS];
58    uint32_t *tiles = NULL;
59    int level = 0, orientation = 0, ntiles = 0;
60
61    FILE *fp = fopen(path, "r");
62
63    if (!fp)
64        return;
65
66    while (!feof(fp))
67    {
68        char str[1024];
69        int i, j, k;
70        char a, b;
71
72        /* Read a line, then decide what to do with it. */
73        fgets(tmp, BUFSIZ, fp);
74
75        if (tiles && !strchr(tmp, '<'))
76        {
77            /* We are in the process of reading layer data. Only stop
78             * when we have read the expected number of tiles. */
79            char const *parser = tmp;
80            while (ntiles < data->width * data->height)
81            {
82                uint32_t code = 0;
83                int id = atoi(parser);
84                if (id)
85                {
86                    for (int n = 0; n < data->ntilers; n++)
87                    {
88                        if (id < gids[n])
89                            continue;
90                        if (n == data->ntilers - 1
91                             || id < gids[n + 1])
92                        {
93                            code = (data->tilers[n] << 16) | (id - gids[n]);
94                            break;
95                        }
96                    }
97                }
98
99                int x = ntiles % data->width;
100                int y = data->height - 1 - (ntiles / data->width);
101                tiles[y * data->width + x] = code;
102                ntiles++;
103
104                while (isdigit(*parser))
105                    parser++;
106                if (*parser == ',')
107                    parser++;
108                if (!isdigit(*parser))
109                    break;
110            }
111
112            if (ntiles == data->width * data->height)
113            {
114                Layer *l = new Layer(data->width, data->height,
115                                     level, orientation, tiles);
116                data->layers[data->nlayers] = l;
117                data->nlayers++;
118                tiles = NULL;
119                //fprintf(stderr, "new layer %ix%i\n", data->width, data->height);
120            }
121        }
122        else if (sscanf(tmp, " <tileset firstgid=\"%i\"", &i) == 1)
123        {
124            /* This is a tileset description. Remember its first gid value. */
125            gids[data->ntilers] = i;
126        }
127        else if (sscanf(tmp, " <image source=\"%[^\"]\"", str) == 1)
128        {
129            /* This is a tileset image file. Associate it with firstgid. */
130            data->tilers[data->ntilers] = Tiler::Register(str, 32, 0,
131                                                          sqrtf(2));
132            data->ntilers++;
133            //fprintf(stderr, "new tiler %s\n", str);
134        }
135        else if (sscanf(tmp, " <layer name=\"%c%i%c%*[^\"]\" "
136                        "width=\"%i\" height=\"%i\"", &a, &i, &b, &j, &k) == 5)
137        {
138            /* This is a layer description. Prepare to read the data. */
139            data->layers = (Layer **)realloc(data->layers,
140                                       sizeof(Layer **) * (data->nlayers + 1));
141            orientation = toupper(a) == 'V' ? 1 : 0;
142            level = i * 32;
143            data->width = j;
144            data->height = k;
145            tiles = (uint32_t *)malloc(j * k * sizeof(uint32_t));
146            ntiles = 0;
147        }
148    }
149
150    fclose(fp);
151}
152
153Map::~Map()
154{
155    for (int i = 0; i < data->ntilers; i++)
156        Tiler::Deregister(data->tilers[i]);
157    for (int i = 0; i < data->nlayers; i++)
158        delete data->layers[i];
159    free(data->layers);
160    delete data;
161}
162
163void Map::Render(int x, int y, int z)
164{
165    for (int i = 0; i < data->nlayers; i++)
166        data->layers[i]->Render(x, y, z);
167}
168
169int Map::GetWidth()
170{
171    return data->width * 32;
172}
173
174int Map::GetHeight()
175{
176    return data->height * 32;
177}
178
Note: See TracBrowser for help on using the repository browser.