source: trunk/src/map.cpp @ 98

Last change on this file since 98 was 98, checked in by sam, 11 years ago

Implement a naive garbage collector.

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