@@ -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); | ||||