@@ -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 | |||
@@ -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 | |||
@@ -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; | |||
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; | |||
@@ -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: | |||
@@ -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 "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) | |||
@@ -15,6 +15,7 @@ | |||
#include <gtkgl/gtkglarea.h> | |||
#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); | |||
@@ -13,6 +13,7 @@ | |||
#include <SDL.h> | |||
#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()) | |||
{ | |||
@@ -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) | |||