| @@ -1,5 +1,6 @@ | |||||
| SRC = test-map.cpp video.cpp tiler.cpp tileset.cpp scene.cpp layer.cpp map.cpp | |||||
| SRC = test-map.cpp \ | |||||
| game.cpp video.cpp tiler.cpp tileset.cpp scene.cpp layer.cpp map.cpp | |||||
| all: test-map | all: test-map | ||||
| @@ -0,0 +1,51 @@ | |||||
| #include "game.h" | |||||
| #include "map.h" | |||||
| /* | |||||
| * Game implementation class | |||||
| */ | |||||
| class GameData | |||||
| { | |||||
| friend class Game; | |||||
| private: | |||||
| Map *map; | |||||
| int x, y; | |||||
| int mousex, mousey; | |||||
| }; | |||||
| /* | |||||
| * Public Game class | |||||
| */ | |||||
| Game::Game(char const *mapname) | |||||
| { | |||||
| data = new GameData(); | |||||
| data->map = new Map(mapname); | |||||
| data->x = data->y = 0; | |||||
| } | |||||
| Game::~Game() | |||||
| { | |||||
| delete data->map; | |||||
| delete data; | |||||
| } | |||||
| void Game::SetMouse(int x, int y) | |||||
| { | |||||
| data->mousex = x; | |||||
| data->mousey = y; | |||||
| } | |||||
| void Game::Render() | |||||
| { | |||||
| Scene *scene = new Scene(); | |||||
| data->map->Render(scene, data->mousex, data->mousey, 0); | |||||
| scene->Render(); | |||||
| delete scene; | |||||
| } | |||||
| @@ -0,0 +1,25 @@ | |||||
| /* | |||||
| * The game object | |||||
| */ | |||||
| #if !defined __DH_GAME_H__ | |||||
| #define __DH_GAME_H__ | |||||
| class GameData; | |||||
| class Game | |||||
| { | |||||
| public: | |||||
| Game(char const *mapname); | |||||
| ~Game(); | |||||
| void SetMouse(int x, int y); | |||||
| void Render(); | |||||
| private: | |||||
| GameData *data; | |||||
| }; | |||||
| #endif // __DH_GAME_H__ | |||||
| @@ -3,11 +3,11 @@ | |||||
| #include "layer.h" | #include "layer.h" | ||||
| Layer::Layer(int w, int h, int in_z, uint32_t *in_data) | |||||
| Layer::Layer(int w, int h, int z, uint32_t *in_data) | |||||
| { | { | ||||
| width = w; | width = w; | ||||
| height = h; | height = h; | ||||
| z = in_z; | |||||
| altitude = z; | |||||
| data = in_data; | data = in_data; | ||||
| #if 0 | #if 0 | ||||
| @@ -26,20 +26,17 @@ Layer::~Layer() | |||||
| free(data); | free(data); | ||||
| } | } | ||||
| void Layer::Draw() | |||||
| void Layer::Render(Scene *scene, int x, int y, int z) | |||||
| { | { | ||||
| for (int y = 0; y < 32; y++) | |||||
| for (int x = 0; x < 32; x++) | |||||
| ;//tileset->AddTile(GetTile(x, y), x * 32, y * 32, z); | |||||
| for (int j = 0; j < height; j++) | |||||
| for (int i = 0; i < width; i++) | |||||
| if (data[j * width + i]) | |||||
| scene->AddTile(data[j * width + i], | |||||
| i * 32 - x, j * 32 - y, altitude + z); | |||||
| } | } | ||||
| int Layer::GetZ() | int Layer::GetZ() | ||||
| { | { | ||||
| return z; | |||||
| } | |||||
| unsigned int Layer::GetTile(int x, int y) | |||||
| { | |||||
| return data[y * width + x]; | |||||
| return altitude; | |||||
| } | } | ||||
| @@ -6,9 +6,10 @@ | |||||
| #if !defined __DH_LAYER_H__ | #if !defined __DH_LAYER_H__ | ||||
| #define __DH_LAYER_H__ | #define __DH_LAYER_H__ | ||||
| #include <cstdio> | |||||
| #include <stdint.h> | #include <stdint.h> | ||||
| #include "scene.h" | |||||
| class Layer | class Layer | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -16,12 +17,11 @@ public: | |||||
| ~Layer(); | ~Layer(); | ||||
| int GetZ(); | int GetZ(); | ||||
| unsigned int GetTile(int x, int y); | |||||
| void Draw(); | |||||
| void Render(Scene *scene, int x, int y, int z); | |||||
| private: | private: | ||||
| int width, height, z; | |||||
| int width, height, altitude; | |||||
| uint32_t *data; | uint32_t *data; | ||||
| }; | }; | ||||
| @@ -56,7 +56,7 @@ Map::Map(char const *path) | |||||
| /* Read a line, then decide what to do with it. */ | /* Read a line, then decide what to do with it. */ | ||||
| fgets(tmp, BUFSIZ, fp); | fgets(tmp, BUFSIZ, fp); | ||||
| if (tiles) | |||||
| if (tiles && !strchr(tmp, '<')) | |||||
| { | { | ||||
| /* We are in the process of reading layer data. Only stop | /* We are in the process of reading layer data. Only stop | ||||
| * when we have read the expected number of tiles. */ | * when we have read the expected number of tiles. */ | ||||
| @@ -94,6 +94,7 @@ Map::Map(char const *path) | |||||
| data->layers[data->nlayers] = new Layer(width, height, level, tiles); | data->layers[data->nlayers] = new Layer(width, height, level, tiles); | ||||
| data->nlayers++; | data->nlayers++; | ||||
| tiles = NULL; | tiles = NULL; | ||||
| //fprintf(stderr, "new layer %ix%i\n", width, height); | |||||
| } | } | ||||
| } | } | ||||
| else if (sscanf(tmp, " <tileset firstgid=\"%i\"", &i) == 1) | else if (sscanf(tmp, " <tileset firstgid=\"%i\"", &i) == 1) | ||||
| @@ -106,6 +107,7 @@ Map::Map(char const *path) | |||||
| /* This is a tileset image file. Associate it with firstgid. */ | /* This is a tileset image file. Associate it with firstgid. */ | ||||
| data->tilers[data->ntilers] = Tiler::Register(str); | data->tilers[data->ntilers] = Tiler::Register(str); | ||||
| data->ntilers++; | data->ntilers++; | ||||
| //fprintf(stderr, "new tiler %s\n", str); | |||||
| } | } | ||||
| else if (sscanf(tmp, " <layer name=\"%c%i%c%*[^\"]\" " | else if (sscanf(tmp, " <layer name=\"%c%i%c%*[^\"]\" " | ||||
| "width=\"%i\" height=\"%i\"", &a, &i, &b, &j, &k) == 5) | "width=\"%i\" height=\"%i\"", &a, &i, &b, &j, &k) == 5) | ||||
| @@ -134,9 +136,9 @@ Map::~Map() | |||||
| delete data; | delete data; | ||||
| } | } | ||||
| void Map::Draw() | |||||
| void Map::Render(Scene *scene, int x, int y, int z) | |||||
| { | { | ||||
| for (int i = 0; i < data->nlayers; i++) | for (int i = 0; i < data->nlayers; i++) | ||||
| data->layers[i]->Draw(); | |||||
| data->layers[i]->Render(scene, x, y, z); | |||||
| } | } | ||||
| @@ -6,9 +6,7 @@ | |||||
| #if !defined __DH_MAP_H__ | #if !defined __DH_MAP_H__ | ||||
| #define __DH_MAP_H__ | #define __DH_MAP_H__ | ||||
| #include <cstdio> | |||||
| #include "layer.h" | |||||
| #include "scene.h" | |||||
| class MapData; | class MapData; | ||||
| @@ -18,7 +16,7 @@ public: | |||||
| Map(char const *path); | Map(char const *path); | ||||
| ~Map(); | ~Map(); | ||||
| void Draw(); | |||||
| void Render(Scene *scene, int x, int y, int z); | |||||
| private: | private: | ||||
| MapData *data; | MapData *data; | ||||
| @@ -1,5 +1,14 @@ | |||||
| #include <stdlib.h> | |||||
| #include "scene.h" | #include "scene.h" | ||||
| #include "tiler.h" | |||||
| struct Tile | |||||
| { | |||||
| uint32_t prio, code; | |||||
| int x, y; | |||||
| }; | |||||
| /* | /* | ||||
| * Scene implementation class | * Scene implementation class | ||||
| @@ -10,7 +19,16 @@ class SceneData | |||||
| friend class Scene; | friend class Scene; | ||||
| private: | private: | ||||
| int dummy; | |||||
| static int Compare(void const *p1, void const *p2) | |||||
| { | |||||
| Tile const *t1 = (Tile const *)p1; | |||||
| Tile const *t2 = (Tile const *)p2; | |||||
| return t1->prio - t2->prio; | |||||
| } | |||||
| Tile *tiles; | |||||
| int ntiles; | |||||
| }; | }; | ||||
| /* | /* | ||||
| @@ -20,6 +38,8 @@ private: | |||||
| Scene::Scene() | Scene::Scene() | ||||
| { | { | ||||
| data = new SceneData(); | data = new SceneData(); | ||||
| data->tiles = 0; | |||||
| data->ntiles = 0; | |||||
| } | } | ||||
| Scene::~Scene() | Scene::~Scene() | ||||
| @@ -27,3 +47,27 @@ Scene::~Scene() | |||||
| delete data; | delete data; | ||||
| } | } | ||||
| void Scene::AddTile(uint32_t code, int x, int y, int z) | |||||
| { | |||||
| if ((data->ntiles % 1024) == 0) | |||||
| data->tiles = (Tile *)realloc(data->tiles, | |||||
| (data->ntiles + 1024) * sizeof(Tile)); | |||||
| data->tiles[data->ntiles].prio = 0; | |||||
| data->tiles[data->ntiles].code = code; | |||||
| data->tiles[data->ntiles].x = x; | |||||
| data->tiles[data->ntiles].y = y; | |||||
| data->ntiles++; | |||||
| } | |||||
| void Scene::Render() // XXX: rename to Blit() | |||||
| { | |||||
| qsort(data->tiles, data->ntiles, sizeof(Tile), SceneData::Compare); | |||||
| for (int i = 0; i < data->ntiles; i++) | |||||
| Tiler::Render(data->tiles[i].code, data->tiles[i].x, data->tiles[i].y); | |||||
| free(data->tiles); | |||||
| data->tiles = 0; | |||||
| data->ntiles = 0; | |||||
| } | |||||
| @@ -6,7 +6,6 @@ | |||||
| #if !defined __DH_SCENE_H__ | #if !defined __DH_SCENE_H__ | ||||
| #define __DH_SCENE_H__ | #define __DH_SCENE_H__ | ||||
| #include <cstdio> | |||||
| #include <stdint.h> | #include <stdint.h> | ||||
| class SceneData; | class SceneData; | ||||
| @@ -17,6 +16,9 @@ public: | |||||
| Scene(); | Scene(); | ||||
| ~Scene(); | ~Scene(); | ||||
| void AddTile(uint32_t code, int x, int y, int z); | |||||
| void Render(); | |||||
| private: | private: | ||||
| SceneData *data; | SceneData *data; | ||||
| }; | }; | ||||
| @@ -6,29 +6,23 @@ | |||||
| #include <math.h> | #include <math.h> | ||||
| #include "video.h" | #include "video.h" | ||||
| #include "tiler.h" | |||||
| #include "map.h" | |||||
| #include "game.h" | |||||
| int main(int argc, char **argv) | int main(int argc, char **argv) | ||||
| { | { | ||||
| Video *video = new Video("Deus Hax", 640, 480); | Video *video = new Video("Deus Hax", 640, 480); | ||||
| Map *map = new Map("maps/testmap-grass.tmx"); | |||||
| Game *game = new Game("maps/testmap-library.tmx"); | |||||
| for (int done = 0; !done; ) | for (int done = 0; !done; ) | ||||
| { | { | ||||
| video->Clear(); | video->Clear(); | ||||
| //map->Draw(tiler); | |||||
| /* Test stuff */ | /* Test stuff */ | ||||
| int playerx, playery; | |||||
| SDL_GetMouseState(&playerx, &playery); | |||||
| playerx = playerx * (640 - 32) / 640; | |||||
| playery = playery * (480 - 32) / 480; | |||||
| //tiler->AddTile(50, playerx, playery, 1); | |||||
| int mx, my; | |||||
| SDL_GetMouseState(&mx, &my); | |||||
| game->SetMouse(mx * (640 - 32) / 640, my * (480 - 32) / 480); | |||||
| //tiler->Render(); | |||||
| game->Render(); | |||||
| video->Refresh(33.33333f); | video->Refresh(33.33333f); | ||||
| /* This could go in a separate function */ | /* This could go in a separate function */ | ||||
| @@ -47,7 +41,7 @@ int main(int argc, char **argv) | |||||
| } | } | ||||
| } | } | ||||
| delete map; | |||||
| delete game; | |||||
| delete video; | delete video; | ||||
| return EXIT_SUCCESS; | return EXIT_SUCCESS; | ||||
| @@ -83,3 +83,10 @@ void Tiler::Deregister(int id) | |||||
| } | } | ||||
| } | } | ||||
| void Tiler::Render(uint32_t code, int x, int y) | |||||
| { | |||||
| int id = (code >> 16) - 1; /* ID 0 is for the empty tileset */ | |||||
| data->tilesets[id]->BlitTile(code & 0xffff, x, y); | |||||
| } | |||||
| @@ -6,11 +6,15 @@ | |||||
| #if !defined __DH_TILER_H__ | #if !defined __DH_TILER_H__ | ||||
| #define __DH_TILER_H__ | #define __DH_TILER_H__ | ||||
| #include <stdint.h> | |||||
| class Tiler | class Tiler | ||||
| { | { | ||||
| public: | public: | ||||
| static int Register(char const *path); | static int Register(char const *path); | ||||
| static void Deregister(int id); | static void Deregister(int id); | ||||
| static void Render(uint32_t code, int x, int y); | |||||
| }; | }; | ||||
| #endif // __DH_TILER_H__ | #endif // __DH_TILER_H__ | ||||
| @@ -41,7 +41,6 @@ private: | |||||
| int ntiles; | int ntiles; | ||||
| GLuint texture[1]; | GLuint texture[1]; | ||||
| GLuint buflist[3]; | |||||
| }; | }; | ||||
| /* | /* | ||||
| @@ -77,15 +76,11 @@ TileSet::TileSet(char const *path) | |||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||||
| /* Three GPU buffers */ | |||||
| glGenBuffers(3, data->buflist); | |||||
| } | } | ||||
| TileSet::~TileSet() | TileSet::~TileSet() | ||||
| { | { | ||||
| glDeleteTextures(1, data->texture); | glDeleteTextures(1, data->texture); | ||||
| glDeleteBuffers(3, data->buflist); | |||||
| free(data->tiles); | free(data->tiles); | ||||
| free(data->name); | free(data->name); | ||||
| @@ -107,97 +102,21 @@ char const *TileSet::GetName() | |||||
| return data->name; | return data->name; | ||||
| } | } | ||||
| void TileSet::AddTile(int n, int x, int y, int z) | |||||
| void TileSet::BlitTile(uint32_t id, int x, int y) | |||||
| { | { | ||||
| if ((data->ntiles % 1024) == 0) | |||||
| { | |||||
| data->tiles = (int *)realloc(data->tiles, | |||||
| (data->ntiles + 1024) * 4 * sizeof(int)); | |||||
| } | |||||
| data->tiles[4 * data->ntiles] = n; | |||||
| data->tiles[4 * data->ntiles + 1] = x; | |||||
| data->tiles[4 * data->ntiles + 2] = y; | |||||
| data->tiles[4 * data->ntiles + 3] = z; | |||||
| data->ntiles++; | |||||
| } | |||||
| void TileSet::Render() | |||||
| { | |||||
| /* Sort tiles */ | |||||
| qsort(data->tiles, data->ntiles, 4 * sizeof(int), TileSetData::Compare); | |||||
| /* Texture coord buffer */ | |||||
| float uvs[8 * data->ntiles]; | |||||
| for (int n = 0; n < data->ntiles; n++) | |||||
| { | |||||
| int tile = data->tiles[4 * n]; | |||||
| float ty = .0625f * (tile / 16); | |||||
| float tx = .0625f * (tile % 16); | |||||
| uvs[8 * n + 0] = tx; | |||||
| uvs[8 * n + 1] = ty; | |||||
| uvs[8 * n + 2] = tx + .0625f; | |||||
| uvs[8 * n + 3] = ty; | |||||
| uvs[8 * n + 4] = tx + .0625f; | |||||
| uvs[8 * n + 5] = ty + .0625f; | |||||
| uvs[8 * n + 6] = tx; | |||||
| uvs[8 * n + 7] = ty + .0625f; | |||||
| } | |||||
| glBindBuffer(GL_ARRAY_BUFFER, data->buflist[1]); | |||||
| glBufferData(GL_ARRAY_BUFFER, | |||||
| 8 * data->ntiles * sizeof(float), uvs, GL_STATIC_DRAW); | |||||
| /* Vertex buffer */ | |||||
| float vertices[8 * data->ntiles]; | |||||
| for (int n = 0; n < data->ntiles; n++) | |||||
| { | |||||
| int x = data->tiles[4 * n + 1]; | |||||
| int y = data->tiles[4 * n + 2]; | |||||
| vertices[8 * n + 0] = x; | |||||
| vertices[8 * n + 1] = y; | |||||
| vertices[8 * n + 2] = x + 32; | |||||
| vertices[8 * n + 3] = y; | |||||
| vertices[8 * n + 4] = x + 32; | |||||
| vertices[8 * n + 5] = y + 32; | |||||
| vertices[8 * n + 6] = x; | |||||
| vertices[8 * n + 7] = y + 32; | |||||
| } | |||||
| glBindBuffer(GL_ARRAY_BUFFER, data->buflist[0]); | |||||
| glBufferData(GL_ARRAY_BUFFER, 8 * data->ntiles * sizeof(float), | |||||
| vertices, GL_STATIC_DRAW); | |||||
| /* Index buffer */ | |||||
| int indices[4 * data->ntiles]; | |||||
| for (int n = 0; n < 4 * data->ntiles; n++) | |||||
| indices[n] = n; | |||||
| glBindBuffer(GL_ARRAY_BUFFER, data->buflist[2]); | |||||
| glBufferData(GL_ARRAY_BUFFER, 4 * data->ntiles * sizeof(int), | |||||
| indices, GL_STATIC_DRAW); | |||||
| /* Draw everything */ | |||||
| glEnableClientState(GL_VERTEX_ARRAY); | |||||
| glEnableClientState(GL_TEXTURE_COORD_ARRAY); | |||||
| glEnableClientState(GL_INDEX_ARRAY); | |||||
| float tx = .0625f * (id & 0xf); | |||||
| float ty = .0625f * ((id >> 4) & 0xf); | |||||
| glBindTexture(GL_TEXTURE_2D, data->texture[0]); | glBindTexture(GL_TEXTURE_2D, data->texture[0]); | ||||
| glBindBuffer(GL_ARRAY_BUFFER, data->buflist[0]); | |||||
| glVertexPointer(2, GL_FLOAT, 0, NULL); | |||||
| glBindBuffer(GL_ARRAY_BUFFER, data->buflist[1]); | |||||
| glTexCoordPointer(2, GL_FLOAT, 0, NULL); | |||||
| glBindBuffer(GL_ARRAY_BUFFER, data->buflist[2]); | |||||
| glIndexPointer(GL_INT, 0, NULL); | |||||
| glDrawArrays(GL_QUADS, 0, 4 * data->ntiles); | |||||
| glDisableClientState(GL_VERTEX_ARRAY); | |||||
| glDisableClientState(GL_TEXTURE_COORD_ARRAY); | |||||
| glDisableClientState(GL_INDEX_ARRAY); | |||||
| /* Empty our shit */ | |||||
| free(data->tiles); | |||||
| data->tiles = NULL; | |||||
| data->ntiles = 0; | |||||
| glBegin(GL_QUADS); | |||||
| glTexCoord2f(tx, ty); | |||||
| glVertex2f(x, y); | |||||
| glTexCoord2f(tx + .0625f, ty); | |||||
| glVertex2f(x + 32, y); | |||||
| glTexCoord2f(tx + .0625f, ty + .0625f); | |||||
| glVertex2f(x + 32, y + 32); | |||||
| glTexCoord2f(tx, ty + .0625f); | |||||
| glVertex2f(x, y + 32); | |||||
| glEnd(); | |||||
| } | } | ||||
| @@ -6,6 +6,8 @@ | |||||
| #if !defined __DH_TILESET_H__ | #if !defined __DH_TILESET_H__ | ||||
| #define __DH_TILESET_H__ | #define __DH_TILESET_H__ | ||||
| #include <stdint.h> | |||||
| class TileSetData; | class TileSetData; | ||||
| class TileSet | class TileSet | ||||
| @@ -19,9 +21,7 @@ public: | |||||
| char const *GetName(); | char const *GetName(); | ||||
| void AddTile(int n, int x, int y, int z); | |||||
| void Render(); | |||||
| void BlitTile(uint32_t id, int x, int y); | |||||
| private: | private: | ||||
| TileSetData *data; | TileSetData *data; | ||||
| @@ -54,7 +54,7 @@ Video::Video(char const *title, int width, int height) | |||||
| SDL_WM_SetCaption(title, NULL); | SDL_WM_SetCaption(title, NULL); | ||||
| SDL_ShowCursor(0); | SDL_ShowCursor(0); | ||||
| //SDL_WM_GrabInput(SDL_GRAB_ON); | |||||
| SDL_WM_GrabInput(SDL_GRAB_ON); | |||||
| /* Initialise OpenGL */ | /* Initialise OpenGL */ | ||||
| glViewport(0, 0, data->video->w, data->video->h); | glViewport(0, 0, data->video->w, data->video->h); | ||||