diff --git a/src/Makefile.am b/src/Makefile.am index 49651617..ccdd1c34 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,7 +7,8 @@ libcommon_a_SOURCES = \ 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 \ 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` test_map_SOURCES = test-map.cpp sdlinput.cpp sdlinput.h diff --git a/src/asset.cpp b/src/asset.cpp index 4d45bbd8..f4e4cb48 100644 --- a/src/asset.cpp +++ b/src/asset.cpp @@ -27,7 +27,7 @@ Asset::Asset() : Asset::~Asset() { -#if !defined FINAL_RELEASE +#if !FINAL_RELEASE if (!destroy) fprintf(stderr, "ERROR: asset destructor called directly\n"); #endif diff --git a/src/debugfps.cpp b/src/debugfps.cpp new file mode 100644 index 00000000..9a1414f9 --- /dev/null +++ b/src/debugfps.cpp @@ -0,0 +1,61 @@ +// +// Deus Hax (working title) +// Copyright (c) 2010 Sam Hocevar +// + +#if defined HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#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; +} + diff --git a/src/debugfps.h b/src/debugfps.h new file mode 100644 index 00000000..7c4e0bff --- /dev/null +++ b/src/debugfps.h @@ -0,0 +1,33 @@ +// +// Deus Hax (working title) +// Copyright (c) 2010 Sam Hocevar +// + +// +// 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__ + diff --git a/src/font.cpp b/src/font.cpp index 8ef64ca6..72d28383 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -32,6 +32,8 @@ class FontData friend class Font; private: + char *name; + SDL_Surface *img; GLuint texture[1]; }; @@ -43,6 +45,7 @@ private: Font::Font(char const *path) { data = new FontData(); + data->name = strdup(path); data->img = NULL; for (char const *name = path; *name; name++) @@ -73,6 +76,21 @@ Font::~Font() 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) { int w = data->img->w / 16; diff --git a/src/font.h b/src/font.h index d4777c94..18f59bf3 100644 --- a/src/font.h +++ b/src/font.h @@ -11,14 +11,25 @@ #if !defined __DH_FONT_H__ #define __DH_FONT_H__ +#include "asset.h" + class FontData; -class Font +class Font : public Asset { public: Font(char const *path); ~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); private: diff --git a/src/forge.cpp b/src/forge.cpp new file mode 100644 index 00000000..772eae15 --- /dev/null +++ b/src/forge.cpp @@ -0,0 +1,98 @@ +// +// Deus Hax (working title) +// Copyright (c) 2010 Sam Hocevar +// + +#if defined HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#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; + } +} + diff --git a/src/forge.h b/src/forge.h new file mode 100644 index 00000000..58b91ffb --- /dev/null +++ b/src/forge.h @@ -0,0 +1,25 @@ +// +// Deus Hax (working title) +// Copyright (c) 2010 Sam Hocevar +// + +// +// 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__ + diff --git a/src/game.cpp b/src/game.cpp index ff0592fd..85312f10 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -11,7 +11,6 @@ #include "game.h" #include "map.h" -#include "font.h" /* * Game implementation class @@ -23,7 +22,6 @@ class GameData private: Map *map; - Font *font; int x, y; int mousex, mousey; int done; @@ -39,7 +37,6 @@ Game::Game(char const *mapname) { data = new GameData(); data->map = new Map(mapname); - data->font = new Font("gfx/font/ascii.png"); data->x = data->y = 0; data->done = 0; data->frame = 0; @@ -47,7 +44,6 @@ Game::Game(char const *mapname) Game::~Game() { - delete data->font; delete data->map; delete data; } @@ -72,10 +68,6 @@ void Game::TickRender(float delta_time) scene->Render(); delete scene; - - char buf[1024]; - sprintf(buf, "Frame %i", data->frame++); - data->font->Print(10, 10, buf); } void Game::SetMouse(int x, int y) diff --git a/src/gtk/editor.cpp b/src/gtk/editor.cpp index 972b8d5d..0af8eab8 100644 --- a/src/gtk/editor.cpp +++ b/src/gtk/editor.cpp @@ -15,6 +15,7 @@ #include #include "ticker.h" +#include "debugfps.h" #include "video.h" #include "game.h" @@ -146,6 +147,7 @@ int main(int argc, char **argv) // FIXME: detect when the game is killed new Game("maps/testmap.tmx"); + new DebugFps(); //gtk_idle_add(tick, glarea); gtk_timeout_add(33, tick, glarea); diff --git a/src/test-map.cpp b/src/test-map.cpp index a509a3d1..0481ad35 100644 --- a/src/test-map.cpp +++ b/src/test-map.cpp @@ -13,6 +13,7 @@ #include #include "sdlinput.h" +#include "debugfps.h" #include "game.h" #include "ticker.h" #include "video.h" @@ -49,8 +50,9 @@ int main(int argc, char **argv) /* Create a game */ Game *game = new Game("maps/testmap.tmx"); - /* Register an input driver */ + /* Register an input driver and some debug stuff */ new SdlInput(game); + new DebugFps(); while (!game->Finished()) { diff --git a/src/ticker.cpp b/src/ticker.cpp index dbb92bbe..6d3e24ab 100644 --- a/src/ticker.cpp +++ b/src/ticker.cpp @@ -24,6 +24,7 @@ static class TickerData public: TickerData() : + todo(0), nassets(0) { for (int i = 0; i < Asset::GROUP_COUNT; i++) @@ -32,11 +33,14 @@ public: ~TickerData() { +#if !FINAL_RELEASE if (nassets) fprintf(stderr, "ERROR: still %i assets in ticker\n", nassets); +#endif } private: + Asset *todo; Asset *list[Asset::GROUP_COUNT]; int nassets; } @@ -50,14 +54,27 @@ static TickerData * const data = &tickerdata; 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) { + /* 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 */ for (int i = 0; i < Asset::GROUP_COUNT; i++) for (Asset *a = data->list[i], *prev = NULL; a; prev = a, a = a->next)