@@ -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__ | |||