| @@ -7,7 +7,8 @@ libcommon_a_SOURCES = \ | |||||
| game.cpp game.h tiler.cpp tiler.h tileset.cpp tileset.h \ | game.cpp game.h tiler.cpp tiler.h tileset.cpp tileset.h \ | ||||
| scene.cpp scene.h font.cpp font.h layer.cpp layer.h map.cpp map.h \ | scene.cpp scene.h font.cpp font.h layer.cpp layer.h map.cpp map.h \ | ||||
| joystick.cpp joystick.h asset.cpp asset.h ticker.cpp ticker.h \ | joystick.cpp joystick.h asset.cpp asset.h ticker.cpp ticker.h \ | ||||
| video.cpp video.h | |||||
| forge.cpp forge.h video.cpp video.h \ | |||||
| debugfps.cpp debugfps.h | |||||
| libcommon_a_CXXFLAGS = `pkg-config --cflags sdl gl SDL_image` | libcommon_a_CXXFLAGS = `pkg-config --cflags sdl gl SDL_image` | ||||
| test_map_SOURCES = test-map.cpp sdlinput.cpp sdlinput.h | test_map_SOURCES = test-map.cpp sdlinput.cpp sdlinput.h | ||||
| @@ -27,7 +27,7 @@ Asset::Asset() : | |||||
| Asset::~Asset() | Asset::~Asset() | ||||
| { | { | ||||
| #if !defined FINAL_RELEASE | |||||
| #if !FINAL_RELEASE | |||||
| if (!destroy) | if (!destroy) | ||||
| fprintf(stderr, "ERROR: asset destructor called directly\n"); | fprintf(stderr, "ERROR: asset destructor called directly\n"); | ||||
| #endif | #endif | ||||
| @@ -0,0 +1,61 @@ | |||||
| // | |||||
| // Deus Hax (working title) | |||||
| // Copyright (c) 2010 Sam Hocevar <sam@hocevar.net> | |||||
| // | |||||
| #if defined HAVE_CONFIG_H | |||||
| # include "config.h" | |||||
| #endif | |||||
| #include <cstdio> | |||||
| #include "debugfps.h" | |||||
| #include "forge.h" | |||||
| /* | |||||
| * DebugFps implementation class | |||||
| */ | |||||
| class DebugFpsData | |||||
| { | |||||
| friend class DebugFps; | |||||
| private: | |||||
| Font *font; | |||||
| int frame; | |||||
| }; | |||||
| /* | |||||
| * Public DebugFps class | |||||
| */ | |||||
| DebugFps::DebugFps() | |||||
| { | |||||
| data = new DebugFpsData(); | |||||
| data->font = Forge::GetFont("gfx/font/ascii.png"); | |||||
| data->frame = 0; | |||||
| } | |||||
| Asset::Group DebugFps::GetGroup() | |||||
| { | |||||
| return GROUP_AFTER; | |||||
| } | |||||
| void DebugFps::TickRender(float delta_time) | |||||
| { | |||||
| Asset::TickGame(delta_time); | |||||
| char buf[1024]; | |||||
| sprintf(buf, "%3.2f fps (%i)", 1000.0f / delta_time, data->frame++); | |||||
| data->font->Print(10, 10, buf); | |||||
| data->font->Print(11, 10, buf); | |||||
| data->font->Print(10, 11, buf); | |||||
| } | |||||
| DebugFps::~DebugFps() | |||||
| { | |||||
| Forge::ReleaseFont(data->font); | |||||
| delete data; | |||||
| } | |||||
| @@ -0,0 +1,33 @@ | |||||
| // | |||||
| // Deus Hax (working title) | |||||
| // Copyright (c) 2010 Sam Hocevar <sam@hocevar.net> | |||||
| // | |||||
| // | |||||
| // The DebugFps class | |||||
| // ------------------ | |||||
| // | |||||
| #if !defined __DH_DEBUGFPS_H__ | |||||
| #define __DH_DEBUGFPS_H__ | |||||
| #include "asset.h" | |||||
| class DebugFpsData; | |||||
| class DebugFps : public Asset | |||||
| { | |||||
| public: | |||||
| DebugFps(); | |||||
| virtual ~DebugFps(); | |||||
| protected: | |||||
| virtual Group GetGroup(); | |||||
| virtual void TickRender(float delta_time); | |||||
| private: | |||||
| DebugFpsData *data; | |||||
| }; | |||||
| #endif // __DH_DEBUGFPS_H__ | |||||
| @@ -32,6 +32,8 @@ class FontData | |||||
| friend class Font; | friend class Font; | ||||
| private: | private: | ||||
| char *name; | |||||
| SDL_Surface *img; | SDL_Surface *img; | ||||
| GLuint texture[1]; | GLuint texture[1]; | ||||
| }; | }; | ||||
| @@ -43,6 +45,7 @@ private: | |||||
| Font::Font(char const *path) | Font::Font(char const *path) | ||||
| { | { | ||||
| data = new FontData(); | data = new FontData(); | ||||
| data->name = strdup(path); | |||||
| data->img = NULL; | data->img = NULL; | ||||
| for (char const *name = path; *name; name++) | for (char const *name = path; *name; name++) | ||||
| @@ -73,6 +76,21 @@ Font::~Font() | |||||
| delete data; | delete data; | ||||
| } | } | ||||
| Asset::Group Font::GetGroup() | |||||
| { | |||||
| return GROUP_BEFORE; | |||||
| } | |||||
| void Font::TickRender(float delta_time) | |||||
| { | |||||
| Asset::TickRender(delta_time); | |||||
| } | |||||
| char const *Font::GetName() | |||||
| { | |||||
| return data->name; | |||||
| } | |||||
| void Font::Print(int x, int y, char const *str) | void Font::Print(int x, int y, char const *str) | ||||
| { | { | ||||
| int w = data->img->w / 16; | int w = data->img->w / 16; | ||||
| @@ -11,14 +11,25 @@ | |||||
| #if !defined __DH_FONT_H__ | #if !defined __DH_FONT_H__ | ||||
| #define __DH_FONT_H__ | #define __DH_FONT_H__ | ||||
| #include "asset.h" | |||||
| class FontData; | class FontData; | ||||
| class Font | |||||
| class Font : public Asset | |||||
| { | { | ||||
| public: | public: | ||||
| Font(char const *path); | Font(char const *path); | ||||
| ~Font(); | ~Font(); | ||||
| protected: | |||||
| /* Inherited from Asset */ | |||||
| virtual Group GetGroup(); | |||||
| virtual void TickRender(float delta_time); | |||||
| public: | |||||
| /* New methods */ | |||||
| char const *GetName(); | |||||
| void Print(int x, int y, char const *str); | void Print(int x, int y, char const *str); | ||||
| private: | private: | ||||
| @@ -0,0 +1,98 @@ | |||||
| // | |||||
| // Deus Hax (working title) | |||||
| // Copyright (c) 2010 Sam Hocevar <sam@hocevar.net> | |||||
| // | |||||
| #if defined HAVE_CONFIG_H | |||||
| # include "config.h" | |||||
| #endif | |||||
| #include <cstring> | |||||
| #include <cstdio> | |||||
| #include <cstdlib> | |||||
| #include "forge.h" | |||||
| #if defined WIN32 | |||||
| # define strcasecmp _stricmp | |||||
| #endif | |||||
| /* | |||||
| * Forge implementation class | |||||
| */ | |||||
| static class ForgeData | |||||
| { | |||||
| friend class Forge; | |||||
| public: | |||||
| ForgeData() : | |||||
| fonts(0), | |||||
| nfonts(0) | |||||
| { | |||||
| /* Nothing to do */ | |||||
| } | |||||
| ~ForgeData() | |||||
| { | |||||
| if (nfonts) | |||||
| fprintf(stderr, "ERROR: still %i fonts in forge\n", nfonts); | |||||
| free(fonts); | |||||
| } | |||||
| private: | |||||
| Font **fonts; | |||||
| int nfonts; | |||||
| } | |||||
| forgedata; | |||||
| static ForgeData * const data = &forgedata; | |||||
| /* | |||||
| * Public Forge class | |||||
| */ | |||||
| Font *Forge::GetFont(char const *path) | |||||
| { | |||||
| int id, empty = -1; | |||||
| /* If the font is already registered, remember its ID. Look for an | |||||
| * empty slot at the same time. */ | |||||
| for (id = 0; id < data->nfonts; id++) | |||||
| { | |||||
| Font *t = data->fonts[id]; | |||||
| if (!t) | |||||
| empty = id; | |||||
| else if (!strcasecmp(path, t->GetName())) | |||||
| break; | |||||
| } | |||||
| /* If this is a new font, create a new one. */ | |||||
| if (id == data->nfonts) | |||||
| { | |||||
| if (empty == -1) | |||||
| { | |||||
| empty = data->nfonts++; | |||||
| data->fonts = (Font **)realloc(data->fonts, | |||||
| data->nfonts * sizeof(Font *)); | |||||
| } | |||||
| data->fonts[empty] = new Font(path); | |||||
| id = empty; | |||||
| } | |||||
| data->fonts[id]->Ref(); | |||||
| return data->fonts[id]; | |||||
| } | |||||
| void Forge::ReleaseFont(Font *font) | |||||
| { | |||||
| if (font->Unref() == 0) | |||||
| for (int id = 0; id < data->nfonts; id++) | |||||
| if (font == data->fonts[id]) | |||||
| { | |||||
| data->fonts[id] = NULL; | |||||
| break; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,25 @@ | |||||
| // | |||||
| // Deus Hax (working title) | |||||
| // Copyright (c) 2010 Sam Hocevar <sam@hocevar.net> | |||||
| // | |||||
| // | |||||
| // The Forge class | |||||
| // --------------- | |||||
| // The Forge is a static class that manages fonts. | |||||
| // | |||||
| #if !defined __DH_FORGE_H__ | |||||
| #define __DH_FORGE_H__ | |||||
| #include "font.h" | |||||
| class Forge | |||||
| { | |||||
| public: | |||||
| static Font *GetFont(char const *path); | |||||
| static void ReleaseFont(Font *font); | |||||
| }; | |||||
| #endif // __DH_FORGE_H__ | |||||
| @@ -11,7 +11,6 @@ | |||||
| #include "game.h" | #include "game.h" | ||||
| #include "map.h" | #include "map.h" | ||||
| #include "font.h" | |||||
| /* | /* | ||||
| * Game implementation class | * Game implementation class | ||||
| @@ -23,7 +22,6 @@ class GameData | |||||
| private: | private: | ||||
| Map *map; | Map *map; | ||||
| Font *font; | |||||
| int x, y; | int x, y; | ||||
| int mousex, mousey; | int mousex, mousey; | ||||
| int done; | int done; | ||||
| @@ -39,7 +37,6 @@ Game::Game(char const *mapname) | |||||
| { | { | ||||
| data = new GameData(); | data = new GameData(); | ||||
| data->map = new Map(mapname); | data->map = new Map(mapname); | ||||
| data->font = new Font("gfx/font/ascii.png"); | |||||
| data->x = data->y = 0; | data->x = data->y = 0; | ||||
| data->done = 0; | data->done = 0; | ||||
| data->frame = 0; | data->frame = 0; | ||||
| @@ -47,7 +44,6 @@ Game::Game(char const *mapname) | |||||
| Game::~Game() | Game::~Game() | ||||
| { | { | ||||
| delete data->font; | |||||
| delete data->map; | delete data->map; | ||||
| delete data; | delete data; | ||||
| } | } | ||||
| @@ -72,10 +68,6 @@ void Game::TickRender(float delta_time) | |||||
| scene->Render(); | scene->Render(); | ||||
| delete scene; | delete scene; | ||||
| char buf[1024]; | |||||
| sprintf(buf, "Frame %i", data->frame++); | |||||
| data->font->Print(10, 10, buf); | |||||
| } | } | ||||
| void Game::SetMouse(int x, int y) | void Game::SetMouse(int x, int y) | ||||
| @@ -15,6 +15,7 @@ | |||||
| #include <gtkgl/gtkglarea.h> | #include <gtkgl/gtkglarea.h> | ||||
| #include "ticker.h" | #include "ticker.h" | ||||
| #include "debugfps.h" | |||||
| #include "video.h" | #include "video.h" | ||||
| #include "game.h" | #include "game.h" | ||||
| @@ -146,6 +147,7 @@ int main(int argc, char **argv) | |||||
| // FIXME: detect when the game is killed | // FIXME: detect when the game is killed | ||||
| new Game("maps/testmap.tmx"); | new Game("maps/testmap.tmx"); | ||||
| new DebugFps(); | |||||
| //gtk_idle_add(tick, glarea); | //gtk_idle_add(tick, glarea); | ||||
| gtk_timeout_add(33, tick, glarea); | gtk_timeout_add(33, tick, glarea); | ||||
| @@ -13,6 +13,7 @@ | |||||
| #include <SDL.h> | #include <SDL.h> | ||||
| #include "sdlinput.h" | #include "sdlinput.h" | ||||
| #include "debugfps.h" | |||||
| #include "game.h" | #include "game.h" | ||||
| #include "ticker.h" | #include "ticker.h" | ||||
| #include "video.h" | #include "video.h" | ||||
| @@ -49,8 +50,9 @@ int main(int argc, char **argv) | |||||
| /* Create a game */ | /* Create a game */ | ||||
| Game *game = new Game("maps/testmap.tmx"); | Game *game = new Game("maps/testmap.tmx"); | ||||
| /* Register an input driver */ | |||||
| /* Register an input driver and some debug stuff */ | |||||
| new SdlInput(game); | new SdlInput(game); | ||||
| new DebugFps(); | |||||
| while (!game->Finished()) | while (!game->Finished()) | ||||
| { | { | ||||
| @@ -24,6 +24,7 @@ static class TickerData | |||||
| public: | public: | ||||
| TickerData() : | TickerData() : | ||||
| todo(0), | |||||
| nassets(0) | nassets(0) | ||||
| { | { | ||||
| for (int i = 0; i < Asset::GROUP_COUNT; i++) | for (int i = 0; i < Asset::GROUP_COUNT; i++) | ||||
| @@ -32,11 +33,14 @@ public: | |||||
| ~TickerData() | ~TickerData() | ||||
| { | { | ||||
| #if !FINAL_RELEASE | |||||
| if (nassets) | if (nassets) | ||||
| fprintf(stderr, "ERROR: still %i assets in ticker\n", nassets); | fprintf(stderr, "ERROR: still %i assets in ticker\n", nassets); | ||||
| #endif | |||||
| } | } | ||||
| private: | private: | ||||
| Asset *todo; | |||||
| Asset *list[Asset::GROUP_COUNT]; | Asset *list[Asset::GROUP_COUNT]; | ||||
| int nassets; | int nassets; | ||||
| } | } | ||||
| @@ -50,14 +54,27 @@ static TickerData * const data = &tickerdata; | |||||
| void Ticker::Register(Asset *asset) | void Ticker::Register(Asset *asset) | ||||
| { | { | ||||
| int i = asset->GetGroup(); | |||||
| asset->next = data->list[i]; | |||||
| data->list[i] = asset; | |||||
| data->nassets++; | |||||
| /* If we are called from its constructor, the object's vtable is not | |||||
| * ready yet, so we do not know which group this asset belongs to. Wait | |||||
| * until the first tick. */ | |||||
| asset->next = data->todo; | |||||
| data->todo = asset; | |||||
| } | } | ||||
| void Ticker::TickGame(float delta_time) | void Ticker::TickGame(float delta_time) | ||||
| { | { | ||||
| /* Insert waiting objects in the appropriate lists */ | |||||
| while (data->todo) | |||||
| { | |||||
| Asset *a = data->todo; | |||||
| data->todo = a->next; | |||||
| int i = a->GetGroup(); | |||||
| a->next = data->list[i]; | |||||
| data->list[i] = a; | |||||
| data->nassets++; | |||||
| } | |||||
| /* Garbage collect objects that can be destroyed */ | /* Garbage collect objects that can be destroyed */ | ||||
| for (int i = 0; i < Asset::GROUP_COUNT; i++) | for (int i = 0; i < Asset::GROUP_COUNT; i++) | ||||
| for (Asset *a = data->list[i], *prev = NULL; a; prev = a, a = a->next) | for (Asset *a = data->list[i], *prev = NULL; a; prev = a, a = a->next) | ||||