| @@ -1,5 +1,5 @@ | |||
| SRC = test-map.cpp video.cpp tileset.cpp layer.cpp map.cpp | |||
| SRC = test-map.cpp video.cpp tiler.cpp tileset.cpp scene.cpp layer.cpp map.cpp | |||
| all: test-map | |||
| @@ -1,4 +1,6 @@ | |||
| #include <stdlib.h> | |||
| #include "layer.h" | |||
| Layer::Layer(int w, int h, int in_z, uint32_t *in_data) | |||
| @@ -21,7 +23,14 @@ Layer::Layer(int w, int h, int in_z, uint32_t *in_data) | |||
| Layer::~Layer() | |||
| { | |||
| delete data; | |||
| free(data); | |||
| } | |||
| void Layer::Draw() | |||
| { | |||
| for (int y = 0; y < 32; y++) | |||
| for (int x = 0; x < 32; x++) | |||
| ;//tileset->AddTile(GetTile(x, y), x * 32, y * 32, z); | |||
| } | |||
| int Layer::GetZ() | |||
| @@ -18,6 +18,8 @@ public: | |||
| int GetZ(); | |||
| unsigned int GetTile(int x, int y); | |||
| void Draw(); | |||
| private: | |||
| int width, height, z; | |||
| uint32_t *data; | |||
| @@ -7,15 +7,40 @@ | |||
| #include "map.h" | |||
| #include "layer.h" | |||
| #include "tiler.h" | |||
| Map::Map(char const *path) : | |||
| layers(0), | |||
| nlayers(0) | |||
| #define MAX_TILERS 128 | |||
| /* | |||
| * Map implementation class | |||
| */ | |||
| class MapData | |||
| { | |||
| friend class Map; | |||
| private: | |||
| int tilers[MAX_TILERS]; | |||
| int ntilers; | |||
| Layer **layers; | |||
| int nlayers; | |||
| }; | |||
| /* | |||
| * Public Map class | |||
| */ | |||
| Map::Map(char const *path) | |||
| { | |||
| data = new MapData(); | |||
| data->ntilers = 0; | |||
| data->layers = NULL; | |||
| data->nlayers = 0; | |||
| char tmp[BUFSIZ]; | |||
| uint32_t *data = NULL; | |||
| int width = 0, height = 0, level = 0, orientation = 0; | |||
| int firstgid = 0, ntiles = 0; | |||
| int gids[MAX_TILERS]; | |||
| uint32_t *tiles = NULL; | |||
| int width = 0, height = 0, level = 0, orientation = 0, ntiles = 0; | |||
| FILE *fp = fopen(path, "r"); | |||
| @@ -28,16 +53,34 @@ Map::Map(char const *path) : | |||
| int i, j, k; | |||
| char a, b; | |||
| /* Read a line, then decide what to do with it. */ | |||
| fgets(tmp, BUFSIZ, fp); | |||
| if (data) | |||
| if (tiles) | |||
| { | |||
| /* We are in the process of reading layer data. Only stop | |||
| * when we have read the expected number of tiles. */ | |||
| char const *parser = tmp; | |||
| while (ntiles < width * height) | |||
| { | |||
| data[ntiles++] = atoi(parser); | |||
| uint32_t code = 0; | |||
| int id = atoi(parser); | |||
| if (id) | |||
| { | |||
| for (int n = 0; n < data->ntilers; n++) | |||
| { | |||
| if (id < gids[n]) | |||
| continue; | |||
| if (n == data->ntilers - 1 | |||
| || id < gids[n + 1]) | |||
| { | |||
| code = (data->tilers[n] << 16) | (id - 1); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| tiles[ntiles++] = code; | |||
| while (isdigit(*parser)) | |||
| parser++; | |||
| if (*parser == ',') | |||
| @@ -48,31 +91,33 @@ Map::Map(char const *path) : | |||
| if (ntiles == width * height) | |||
| { | |||
| layers[nlayers] = new Layer(width, height, level, data); | |||
| nlayers++; | |||
| data = NULL; | |||
| data->layers[data->nlayers] = new Layer(width, height, level, tiles); | |||
| data->nlayers++; | |||
| tiles = NULL; | |||
| } | |||
| } | |||
| else if (sscanf(tmp, " <tileset firstgid=\"%i\"", &i) == 1) | |||
| { | |||
| /* This is a tileset description. Remember its firstgid value. */ | |||
| firstgid = i; | |||
| /* This is a tileset description. Remember its first gid value. */ | |||
| gids[data->ntilers] = i; | |||
| } | |||
| else if (sscanf(tmp, " <image source=\"%[^\"]\"", str) == 1) | |||
| { | |||
| /* This is a tileset image file. Associate it with firstgid. */ | |||
| data->tilers[data->ntilers] = Tiler::Register(str); | |||
| data->ntilers++; | |||
| } | |||
| else if (sscanf(tmp, " <layer name=\"%c%i%c%*[^\"]\" " | |||
| "width=\"%i\" height=\"%i\"", &a, &i, &b, &j, &k) == 5) | |||
| { | |||
| /* This is a layer description. Prepare to read the data. */ | |||
| layers = (Layer **)realloc(layers, | |||
| sizeof(Layer **) * (nlayers + 1)); | |||
| data->layers = (Layer **)realloc(data->layers, | |||
| sizeof(Layer **) * (data->nlayers + 1)); | |||
| orientation = toupper(a) == 'V' ? 1 : 0; | |||
| width = j; | |||
| height = k; | |||
| tiles = (uint32_t *)malloc(width * height * sizeof(uint32_t)); | |||
| ntiles = 0; | |||
| data = (uint32_t *)malloc(width * height * sizeof(uint32_t)); | |||
| } | |||
| } | |||
| @@ -81,20 +126,17 @@ Map::Map(char const *path) : | |||
| Map::~Map() | |||
| { | |||
| for (int i = 0; i < nlayers; i++) | |||
| delete layers[i]; | |||
| free(layers); | |||
| for (int i = 0; i < data->ntilers; i++) | |||
| Tiler::Deregister(data->tilers[i]); | |||
| for (int i = 0; i < data->nlayers; i++) | |||
| delete data->layers[i]; | |||
| free(data->layers); | |||
| delete data; | |||
| } | |||
| void Map::Draw(Tileset *tileset) | |||
| void Map::Draw() | |||
| { | |||
| for (int i = 0; i < nlayers; i++) | |||
| { | |||
| int z = layers[i]->GetZ(); | |||
| for (int y = 0; y < 32; y++) | |||
| for (int x = 0; x < 32; x++) | |||
| tileset->AddTile(layers[i]->GetTile(x, y), x * 32, y * 32, z); | |||
| } | |||
| for (int i = 0; i < data->nlayers; i++) | |||
| data->layers[i]->Draw(); | |||
| } | |||
| @@ -9,7 +9,8 @@ | |||
| #include <cstdio> | |||
| #include "layer.h" | |||
| #include "tileset.h" | |||
| class MapData; | |||
| class Map | |||
| { | |||
| @@ -17,11 +18,10 @@ public: | |||
| Map(char const *path); | |||
| ~Map(); | |||
| void Draw(Tileset *tileset); | |||
| void Draw(); | |||
| private: | |||
| Layer **layers; | |||
| int nlayers; | |||
| MapData *data; | |||
| }; | |||
| #endif // __DH_MAP_H__ | |||
| @@ -0,0 +1,29 @@ | |||
| #include "scene.h" | |||
| /* | |||
| * Scene implementation class | |||
| */ | |||
| class SceneData | |||
| { | |||
| friend class Scene; | |||
| private: | |||
| int dummy; | |||
| }; | |||
| /* | |||
| * Public Scene class | |||
| */ | |||
| Scene::Scene() | |||
| { | |||
| data = new SceneData(); | |||
| } | |||
| Scene::~Scene() | |||
| { | |||
| delete data; | |||
| } | |||
| @@ -0,0 +1,25 @@ | |||
| /* | |||
| * The scene object | |||
| */ | |||
| #if !defined __DH_SCENE_H__ | |||
| #define __DH_SCENE_H__ | |||
| #include <cstdio> | |||
| #include <stdint.h> | |||
| class SceneData; | |||
| class Scene | |||
| { | |||
| public: | |||
| Scene(); | |||
| ~Scene(); | |||
| private: | |||
| SceneData *data; | |||
| }; | |||
| #endif // __DH_SCENE_H__ | |||
| @@ -6,20 +6,19 @@ | |||
| #include <math.h> | |||
| #include "video.h" | |||
| #include "tileset.h" | |||
| #include "tiler.h" | |||
| #include "map.h" | |||
| int main(int argc, char **argv) | |||
| { | |||
| Video *video = new Video("Deus Hax", 640, 480); | |||
| Tileset *tileset = new Tileset(); | |||
| Map *map = new Map("maps/testmap-grass.tmx"); | |||
| for (int done = 0; !done; ) | |||
| { | |||
| video->Clear(); | |||
| map->Draw(tileset); | |||
| //map->Draw(tiler); | |||
| /* Test stuff */ | |||
| int playerx, playery; | |||
| @@ -27,9 +26,9 @@ int main(int argc, char **argv) | |||
| playerx = playerx * (640 - 32) / 640; | |||
| playery = playery * (480 - 32) / 480; | |||
| tileset->AddTile(50, playerx, playery, 1); | |||
| //tiler->AddTile(50, playerx, playery, 1); | |||
| tileset->Render(); | |||
| //tiler->Render(); | |||
| video->Refresh(33.33333f); | |||
| /* This could go in a separate function */ | |||
| @@ -49,7 +48,6 @@ int main(int argc, char **argv) | |||
| } | |||
| delete map; | |||
| delete tileset; | |||
| delete video; | |||
| return EXIT_SUCCESS; | |||
| @@ -0,0 +1,85 @@ | |||
| #include <cstring> | |||
| #include <cstdio> | |||
| #include <stdlib.h> | |||
| #include "tiler.h" | |||
| #include "tileset.h" | |||
| /* | |||
| * Tiler implementation class | |||
| */ | |||
| static class TilerData | |||
| { | |||
| friend class Tiler; | |||
| public: | |||
| TilerData() : | |||
| tilesets(0), | |||
| ntilesets(0) | |||
| { | |||
| /* Nothing to do */ | |||
| } | |||
| ~TilerData() | |||
| { | |||
| free(tilesets); | |||
| } | |||
| private: | |||
| TileSet **tilesets; | |||
| int ntilesets; | |||
| } | |||
| tilerdata; | |||
| static TilerData * const data = &tilerdata; | |||
| /* | |||
| * Public Tiler class | |||
| */ | |||
| int Tiler::Register(char const *path) | |||
| { | |||
| int id, empty = -1; | |||
| /* If the tileset is already registered, remember its ID. Look for an | |||
| * empty slot at the same time. */ | |||
| for (id = 0; id < data->ntilesets; id++) | |||
| { | |||
| TileSet *t = data->tilesets[id]; | |||
| if (!t) | |||
| empty = id; | |||
| else if (!strcasecmp(path, t->GetName())) | |||
| break; | |||
| } | |||
| /* If this is a new tileset, create a new one. */ | |||
| if (id == data->ntilesets) | |||
| { | |||
| if (empty == -1) | |||
| { | |||
| empty = data->ntilesets++; | |||
| data->tilesets = (TileSet **)realloc(data->tilesets, | |||
| data->ntilesets * sizeof(TileSet *)); | |||
| } | |||
| data->tilesets[empty] = new TileSet(path); | |||
| id = empty; | |||
| } | |||
| data->tilesets[id]->Ref(); | |||
| return id + 1; /* ID 0 is for the empty tileset */ | |||
| } | |||
| void Tiler::Deregister(int id) | |||
| { | |||
| --id; /* ID 0 is for the empty tileset */ | |||
| if (data->tilesets[id]->Unref() == 0) | |||
| { | |||
| delete data->tilesets[id]; | |||
| data->tilesets[id] = NULL; | |||
| } | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| /* | |||
| * The tile manager | |||
| */ | |||
| #if !defined __DH_TILER_H__ | |||
| #define __DH_TILER_H__ | |||
| class Tiler | |||
| { | |||
| public: | |||
| static int Register(char const *path); | |||
| static void Deregister(int id); | |||
| }; | |||
| #endif // __DH_TILER_H__ | |||
| @@ -19,12 +19,12 @@ | |||
| #include "tileset.h" | |||
| /* | |||
| * Tileset implementation class | |||
| * TileSet implementation class | |||
| */ | |||
| class TilesetData | |||
| class TileSetData | |||
| { | |||
| friend class Tileset; | |||
| friend class TileSet; | |||
| private: | |||
| static int Compare(void const *p1, void const *p2) | |||
| @@ -35,6 +35,8 @@ private: | |||
| return n1[2] + 32 * n1[3] - (n2[2] + 32 * n2[3]); | |||
| } | |||
| char *name; | |||
| int ref; | |||
| int *tiles; | |||
| int ntiles; | |||
| @@ -43,17 +45,23 @@ private: | |||
| }; | |||
| /* | |||
| * Public Tileset class | |||
| * Public TileSet class | |||
| */ | |||
| Tileset::Tileset() | |||
| TileSet::TileSet(char const *path) | |||
| { | |||
| data = new TilesetData(); | |||
| SDL_Surface *img = NULL; | |||
| data = new TileSetData(); | |||
| data->name = strdup(path); | |||
| data->ref = 0; | |||
| data->tiles = NULL; | |||
| data->ntiles = 0; | |||
| /* One tile texture */ | |||
| SDL_Surface *img = IMG_Load("art/test/grasstest.png"); | |||
| for (char const *name = path; *name; name++) | |||
| if ((img = IMG_Load(name))) | |||
| break; | |||
| if (!img) | |||
| { | |||
| @@ -61,7 +69,7 @@ Tileset::Tileset() | |||
| exit(1); | |||
| } | |||
| glGenTextures(1, &data->texture[0]); | |||
| glGenTextures(1, data->texture); | |||
| glBindTexture(GL_TEXTURE_2D, data->texture[0]); | |||
| glTexImage2D(GL_TEXTURE_2D, 0, 4, img->w, img->h, 0, | |||
| @@ -74,13 +82,32 @@ Tileset::Tileset() | |||
| glGenBuffers(3, data->buflist); | |||
| } | |||
| Tileset::~Tileset() | |||
| TileSet::~TileSet() | |||
| { | |||
| glDeleteTextures(1, data->texture); | |||
| glDeleteBuffers(3, data->buflist); | |||
| free(data->tiles); | |||
| free(data->name); | |||
| delete data; | |||
| } | |||
| void Tileset::AddTile(int n, int x, int y, int z) | |||
| void TileSet::Ref() | |||
| { | |||
| data->ref++; | |||
| } | |||
| int TileSet::Unref() | |||
| { | |||
| return --data->ref; | |||
| } | |||
| char const *TileSet::GetName() | |||
| { | |||
| return data->name; | |||
| } | |||
| void TileSet::AddTile(int n, int x, int y, int z) | |||
| { | |||
| if ((data->ntiles % 1024) == 0) | |||
| { | |||
| @@ -96,10 +123,10 @@ void Tileset::AddTile(int n, int x, int y, int z) | |||
| data->ntiles++; | |||
| } | |||
| void Tileset::Render() | |||
| void TileSet::Render() | |||
| { | |||
| /* Sort tiles */ | |||
| qsort(data->tiles, data->ntiles, 4 * sizeof(int), TilesetData::Compare); | |||
| qsort(data->tiles, data->ntiles, 4 * sizeof(int), TileSetData::Compare); | |||
| /* Texture coord buffer */ | |||
| float uvs[8 * data->ntiles]; | |||
| @@ -3,24 +3,29 @@ | |||
| * The tile manager | |||
| */ | |||
| #if !defined __DH_TILER_H__ | |||
| #define __DH_TILER_H__ | |||
| #if !defined __DH_TILESET_H__ | |||
| #define __DH_TILESET_H__ | |||
| class TilesetData; | |||
| class TileSetData; | |||
| class Tileset | |||
| class TileSet | |||
| { | |||
| public: | |||
| Tileset(); | |||
| ~Tileset(); | |||
| TileSet(char const *path); | |||
| ~TileSet(); | |||
| void Ref(); | |||
| int Unref(); | |||
| char const *GetName(); | |||
| void AddTile(int n, int x, int y, int z); | |||
| void Render(); | |||
| private: | |||
| TilesetData *data; | |||
| TileSetData *data; | |||
| }; | |||
| #endif // __DH_TILER_H__ | |||
| #endif // __DH_TILESET_H__ | |||