| @@ -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 | |||
| @@ -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" | |||
| 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; | |||
| height = h; | |||
| z = in_z; | |||
| altitude = z; | |||
| data = in_data; | |||
| #if 0 | |||
| @@ -26,20 +26,17 @@ Layer::~Layer() | |||
| 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() | |||
| { | |||
| 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__ | |||
| #define __DH_LAYER_H__ | |||
| #include <cstdio> | |||
| #include <stdint.h> | |||
| #include "scene.h" | |||
| class Layer | |||
| { | |||
| public: | |||
| @@ -16,12 +17,11 @@ public: | |||
| ~Layer(); | |||
| int GetZ(); | |||
| unsigned int GetTile(int x, int y); | |||
| void Draw(); | |||
| void Render(Scene *scene, int x, int y, int z); | |||
| private: | |||
| int width, height, z; | |||
| int width, height, altitude; | |||
| uint32_t *data; | |||
| }; | |||
| @@ -56,7 +56,7 @@ Map::Map(char const *path) | |||
| /* Read a line, then decide what to do with it. */ | |||
| fgets(tmp, BUFSIZ, fp); | |||
| if (tiles) | |||
| if (tiles && !strchr(tmp, '<')) | |||
| { | |||
| /* We are in the process of reading layer data. Only stop | |||
| * 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->nlayers++; | |||
| tiles = NULL; | |||
| //fprintf(stderr, "new layer %ix%i\n", width, height); | |||
| } | |||
| } | |||
| 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. */ | |||
| data->tilers[data->ntilers] = Tiler::Register(str); | |||
| data->ntilers++; | |||
| //fprintf(stderr, "new tiler %s\n", str); | |||
| } | |||
| else if (sscanf(tmp, " <layer name=\"%c%i%c%*[^\"]\" " | |||
| "width=\"%i\" height=\"%i\"", &a, &i, &b, &j, &k) == 5) | |||
| @@ -134,9 +136,9 @@ Map::~Map() | |||
| delete data; | |||
| } | |||
| void Map::Draw() | |||
| void Map::Render(Scene *scene, int x, int y, int z) | |||
| { | |||
| 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__ | |||
| #define __DH_MAP_H__ | |||
| #include <cstdio> | |||
| #include "layer.h" | |||
| #include "scene.h" | |||
| class MapData; | |||
| @@ -18,7 +16,7 @@ public: | |||
| Map(char const *path); | |||
| ~Map(); | |||
| void Draw(); | |||
| void Render(Scene *scene, int x, int y, int z); | |||
| private: | |||
| MapData *data; | |||
| @@ -1,5 +1,14 @@ | |||
| #include <stdlib.h> | |||
| #include "scene.h" | |||
| #include "tiler.h" | |||
| struct Tile | |||
| { | |||
| uint32_t prio, code; | |||
| int x, y; | |||
| }; | |||
| /* | |||
| * Scene implementation class | |||
| @@ -10,7 +19,16 @@ class SceneData | |||
| friend class Scene; | |||
| 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() | |||
| { | |||
| data = new SceneData(); | |||
| data->tiles = 0; | |||
| data->ntiles = 0; | |||
| } | |||
| Scene::~Scene() | |||
| @@ -27,3 +47,27 @@ Scene::~Scene() | |||
| 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__ | |||
| #define __DH_SCENE_H__ | |||
| #include <cstdio> | |||
| #include <stdint.h> | |||
| class SceneData; | |||
| @@ -17,6 +16,9 @@ public: | |||
| Scene(); | |||
| ~Scene(); | |||
| void AddTile(uint32_t code, int x, int y, int z); | |||
| void Render(); | |||
| private: | |||
| SceneData *data; | |||
| }; | |||
| @@ -6,29 +6,23 @@ | |||
| #include <math.h> | |||
| #include "video.h" | |||
| #include "tiler.h" | |||
| #include "map.h" | |||
| #include "game.h" | |||
| int main(int argc, char **argv) | |||
| { | |||
| 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; ) | |||
| { | |||
| video->Clear(); | |||
| //map->Draw(tiler); | |||
| /* 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); | |||
| /* This could go in a separate function */ | |||
| @@ -47,7 +41,7 @@ int main(int argc, char **argv) | |||
| } | |||
| } | |||
| delete map; | |||
| delete game; | |||
| delete video; | |||
| 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__ | |||
| #define __DH_TILER_H__ | |||
| #include <stdint.h> | |||
| class Tiler | |||
| { | |||
| public: | |||
| static int Register(char const *path); | |||
| static void Deregister(int id); | |||
| static void Render(uint32_t code, int x, int y); | |||
| }; | |||
| #endif // __DH_TILER_H__ | |||
| @@ -41,7 +41,6 @@ private: | |||
| int ntiles; | |||
| 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_MIN_FILTER, GL_NEAREST); | |||
| /* Three GPU buffers */ | |||
| glGenBuffers(3, data->buflist); | |||
| } | |||
| TileSet::~TileSet() | |||
| { | |||
| glDeleteTextures(1, data->texture); | |||
| glDeleteBuffers(3, data->buflist); | |||
| free(data->tiles); | |||
| free(data->name); | |||
| @@ -107,97 +102,21 @@ char const *TileSet::GetName() | |||
| 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]); | |||
| 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__ | |||
| #define __DH_TILESET_H__ | |||
| #include <stdint.h> | |||
| class TileSetData; | |||
| class TileSet | |||
| @@ -19,9 +21,7 @@ public: | |||
| 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: | |||
| TileSetData *data; | |||
| @@ -54,7 +54,7 @@ Video::Video(char const *title, int width, int height) | |||
| SDL_WM_SetCaption(title, NULL); | |||
| SDL_ShowCursor(0); | |||
| //SDL_WM_GrabInput(SDL_GRAB_ON); | |||
| SDL_WM_GrabInput(SDL_GRAB_ON); | |||
| /* Initialise OpenGL */ | |||
| glViewport(0, 0, data->video->w, data->video->h); | |||