source: trunk/src/map.cpp @ 734

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

core: create a logger class to reduce printf usage.

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