source: trunk/src/map.cpp @ 186

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

Support tilesets larger than 512x512 and switch the coordinates system to
(0,0) at the bottom left.

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