source: trunk/src/map.cpp @ 218

Last change on this file since 218 was 218, checked in by sam, 9 years ago

The Tile size can now be specified upon TileSet load. Add a sample
with the Monsterz tiles.

  • 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, 32);
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.