@@ -4,7 +4,7 @@ noinst_PROGRAMS = test-map editor | |||||
noinst_LIBRARIES = libcommon.a | noinst_LIBRARIES = libcommon.a | ||||
libcommon_a_SOURCES = \ | libcommon_a_SOURCES = \ | ||||
core.h matrix.h game.cpp game.h tiler.cpp tiler.h \ | |||||
core.h matrix.h game.cpp game.h tiler.cpp tiler.h dict.cpp dict.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 \ | ||||
entity.cpp entity.h ticker.cpp ticker.h tileset.cpp tileset.h \ | entity.cpp entity.h ticker.cpp ticker.h tileset.cpp tileset.h \ | ||||
forge.cpp forge.h video.cpp video.h timer.cpp timer.h bitfield.h \ | forge.cpp forge.h video.cpp video.h timer.cpp timer.h bitfield.h \ | ||||
@@ -28,6 +28,7 @@ | |||||
#include "tileset.h" | #include "tileset.h" | ||||
// Other objects | // Other objects | ||||
#include "dict.h" | |||||
#include "map.h" | #include "map.h" | ||||
#include "layer.h" | #include "layer.h" | ||||
@@ -21,7 +21,7 @@ class DebugFpsData | |||||
friend class DebugFps; | friend class DebugFps; | ||||
private: | private: | ||||
Font *font; | |||||
int fontid; | |||||
int frame; | int frame; | ||||
}; | }; | ||||
@@ -33,7 +33,7 @@ DebugFps::DebugFps() | |||||
{ | { | ||||
data = new DebugFpsData(); | data = new DebugFpsData(); | ||||
data->font = Forge::GetFont("gfx/font/ascii.png"); | |||||
data->fontid = Forge::Register("gfx/font/ascii.png"); | |||||
data->frame = 0; | data->frame = 0; | ||||
} | } | ||||
@@ -49,35 +49,36 @@ void DebugFps::TickRender(float deltams) | |||||
data->frame++; | data->frame++; | ||||
char buf[1024]; | char buf[1024]; | ||||
Font *font = Forge::GetFont(data->fontid); | |||||
sprintf(buf, "%2.2f fps (%i)", | sprintf(buf, "%2.2f fps (%i)", | ||||
1e3f / Profiler::GetMean(Profiler::STAT_TICK_FRAME), data->frame); | 1e3f / Profiler::GetMean(Profiler::STAT_TICK_FRAME), data->frame); | ||||
data->font->PrintBold(10, 10, buf); | |||||
font->PrintBold(10, 10, buf); | |||||
sprintf(buf, "Game % 7.2f % 7.2f", | sprintf(buf, "Game % 7.2f % 7.2f", | ||||
Profiler::GetMean(Profiler::STAT_TICK_GAME), | Profiler::GetMean(Profiler::STAT_TICK_GAME), | ||||
Profiler::GetMax(Profiler::STAT_TICK_GAME)); | Profiler::GetMax(Profiler::STAT_TICK_GAME)); | ||||
data->font->PrintBold(10, 34, buf); | |||||
font->PrintBold(10, 34, buf); | |||||
sprintf(buf, "Render % 7.2f % 7.2f", | sprintf(buf, "Render % 7.2f % 7.2f", | ||||
Profiler::GetMean(Profiler::STAT_TICK_RENDER), | Profiler::GetMean(Profiler::STAT_TICK_RENDER), | ||||
Profiler::GetMax(Profiler::STAT_TICK_RENDER)); | Profiler::GetMax(Profiler::STAT_TICK_RENDER)); | ||||
data->font->PrintBold(10, 50, buf); | |||||
font->PrintBold(10, 50, buf); | |||||
sprintf(buf, "Blit % 7.2f % 7.2f", | sprintf(buf, "Blit % 7.2f % 7.2f", | ||||
Profiler::GetMean(Profiler::STAT_TICK_BLIT), | Profiler::GetMean(Profiler::STAT_TICK_BLIT), | ||||
Profiler::GetMax(Profiler::STAT_TICK_BLIT)); | Profiler::GetMax(Profiler::STAT_TICK_BLIT)); | ||||
data->font->PrintBold(10, 66, buf); | |||||
font->PrintBold(10, 66, buf); | |||||
sprintf(buf, "Frame % 7.2f % 7.2f", | sprintf(buf, "Frame % 7.2f % 7.2f", | ||||
Profiler::GetMean(Profiler::STAT_TICK_FRAME), | Profiler::GetMean(Profiler::STAT_TICK_FRAME), | ||||
Profiler::GetMax(Profiler::STAT_TICK_FRAME)); | Profiler::GetMax(Profiler::STAT_TICK_FRAME)); | ||||
data->font->PrintBold(10, 82, buf); | |||||
font->PrintBold(10, 82, buf); | |||||
} | } | ||||
DebugFps::~DebugFps() | DebugFps::~DebugFps() | ||||
{ | { | ||||
Forge::ReleaseFont(data->font); | |||||
Forge::Deregister(data->fontid); | |||||
delete data; | delete data; | ||||
} | } | ||||
@@ -0,0 +1,111 @@ | |||||
// | |||||
// 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 "core.h" | |||||
/* | |||||
* Dict implementation class | |||||
*/ | |||||
class DictData | |||||
{ | |||||
friend class Dict; | |||||
public: | |||||
DictData() : | |||||
entities(0), | |||||
nentities(0) | |||||
{ | |||||
/* Nothing to do */ | |||||
} | |||||
~DictData() | |||||
{ | |||||
if (nentities) | |||||
fprintf(stderr, "ERROR: still %i entities in dict\n", nentities); | |||||
free(entities); | |||||
} | |||||
private: | |||||
Entity **entities; | |||||
int nentities; | |||||
}; | |||||
/* | |||||
* Public Dict class | |||||
*/ | |||||
Dict::Dict() | |||||
{ | |||||
data = new DictData(); | |||||
} | |||||
Dict::~Dict() | |||||
{ | |||||
delete data; | |||||
} | |||||
int Dict::MakeSlot(char const *name) | |||||
{ | |||||
int id, empty = -1; | |||||
/* If the entry is already registered, remember its ID. Look for an | |||||
* empty slot at the same time. */ | |||||
for (id = 0; id < data->nentities; id++) | |||||
{ | |||||
Entity *e = data->entities[id]; | |||||
if (!e) | |||||
empty = id; | |||||
else if (!strcasecmp(name, e->GetName())) | |||||
break; | |||||
} | |||||
/* If this is a new entry, create a new slot for it. */ | |||||
if (id == data->nentities) | |||||
{ | |||||
if (empty == -1) | |||||
{ | |||||
empty = data->nentities++; | |||||
data->entities = (Entity **)realloc(data->entities, | |||||
data->nentities * sizeof(Entity *)); | |||||
} | |||||
data->entities[empty] = NULL; | |||||
id = empty; | |||||
} | |||||
else | |||||
{ | |||||
data->entities[id]->Ref(); | |||||
} | |||||
return id; | |||||
} | |||||
void Dict::RemoveSlot(int id) | |||||
{ | |||||
if (data->entities[id]->Unref() == 0) | |||||
data->entities[id] = NULL; | |||||
} | |||||
void Dict::SetEntity(int id, Entity *entity) | |||||
{ | |||||
entity->Ref(); | |||||
data->entities[id] = entity; | |||||
} | |||||
Entity *Dict::GetEntity(int id) | |||||
{ | |||||
return data->entities[id]; | |||||
} | |||||
@@ -0,0 +1,35 @@ | |||||
// | |||||
// Deus Hax (working title) | |||||
// Copyright (c) 2010 Sam Hocevar <sam@hocevar.net> | |||||
// | |||||
// | |||||
// The Dict class | |||||
// -------------- | |||||
// | |||||
#if !defined __DH_DICT_H__ | |||||
#define __DH_DICT_H__ | |||||
#include "entity.h" | |||||
class DictData; | |||||
class Dict | |||||
{ | |||||
public: | |||||
Dict(); | |||||
~Dict(); | |||||
int MakeSlot(char const *name); | |||||
void RemoveSlot(int id); | |||||
void SetEntity(int id, Entity *entity); | |||||
Entity *GetEntity(int id); | |||||
private: | |||||
DictData *data; | |||||
}; | |||||
#endif // __DH_DICT_H__ | |||||
@@ -35,6 +35,11 @@ Entity::~Entity() | |||||
#endif | #endif | ||||
} | } | ||||
char const *Entity::GetName() | |||||
{ | |||||
return "Generic entity"; | |||||
} | |||||
Entity::Group Entity::GetGroup() | Entity::Group Entity::GetGroup() | ||||
{ | { | ||||
return GROUP_DEFAULT; | return GROUP_DEFAULT; | ||||
@@ -20,6 +20,7 @@ class Entity | |||||
{ | { | ||||
friend class Ticker; | friend class Ticker; | ||||
friend class TickerData; | friend class TickerData; | ||||
friend class Dict; | |||||
public: | public: | ||||
virtual void Ref(); | virtual void Ref(); | ||||
@@ -40,6 +41,7 @@ protected: | |||||
Entity(); | Entity(); | ||||
virtual ~Entity(); | virtual ~Entity(); | ||||
virtual char const *GetName(); | |||||
virtual Group GetGroup(); | virtual Group GetGroup(); | ||||
virtual void TickGame(float deltams); | virtual void TickGame(float deltams); | ||||
@@ -23,13 +23,12 @@ public: | |||||
protected: | protected: | ||||
/* Inherited from Entity */ | /* Inherited from Entity */ | ||||
virtual char const *GetName(); | |||||
virtual Group GetGroup(); | virtual Group GetGroup(); | ||||
virtual void TickRender(float deltams); | virtual void TickRender(float deltams); | ||||
public: | public: | ||||
/* New methods */ | /* New methods */ | ||||
char const *GetName(); | |||||
void Print(int x, int y, char const *str); | void Print(int x, int y, char const *str); | ||||
void PrintBold(int x, int y, char const *str); | void PrintBold(int x, int y, char const *str); | ||||
@@ -7,10 +7,6 @@ | |||||
# include "config.h" | # include "config.h" | ||||
#endif | #endif | ||||
#include <cstring> | |||||
#include <cstdio> | |||||
#include <cstdlib> | |||||
#include "core.h" | #include "core.h" | ||||
#if defined WIN32 | #if defined WIN32 | ||||
@@ -26,23 +22,7 @@ static class ForgeData | |||||
friend class Forge; | friend class Forge; | ||||
public: | 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; | |||||
Dict fonts; | |||||
} | } | ||||
forgedata; | forgedata; | ||||
@@ -52,47 +32,26 @@ static ForgeData * const data = &forgedata; | |||||
* Public Forge class | * Public Forge class | ||||
*/ | */ | ||||
Font *Forge::GetFont(char const *path) | |||||
int Forge::Register(char const *path) | |||||
{ | { | ||||
int id, empty = -1; | |||||
int id = data->fonts.MakeSlot(path); | |||||
/* 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++) | |||||
if (!data->fonts.GetEntity(id)) | |||||
{ | { | ||||
Font *t = data->fonts[id]; | |||||
if (!t) | |||||
empty = id; | |||||
else if (!strcasecmp(path, t->GetName())) | |||||
break; | |||||
Font *font = new Font(path); | |||||
data->fonts.SetEntity(id, font); | |||||
} | } | ||||
/* 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; | |||||
} | |||||
return id; | |||||
} | |||||
data->fonts[id]->Ref(); | |||||
return data->fonts[id]; | |||||
void Forge::Deregister(int id) | |||||
{ | |||||
data->fonts.RemoveSlot(id); | |||||
} | } | ||||
void Forge::ReleaseFont(Font *font) | |||||
Font *Forge::GetFont(int id) | |||||
{ | { | ||||
if (font->Unref() == 0) | |||||
for (int id = 0; id < data->nfonts; id++) | |||||
if (font == data->fonts[id]) | |||||
{ | |||||
data->fonts[id] = NULL; | |||||
break; | |||||
} | |||||
return (Font *)data->fonts.GetEntity(id); | |||||
} | } | ||||
@@ -17,8 +17,9 @@ | |||||
class Forge | class Forge | ||||
{ | { | ||||
public: | public: | ||||
static Font *GetFont(char const *path); | |||||
static void ReleaseFont(Font *font); | |||||
static int Register(char const *path); | |||||
static void Deregister(int id); | |||||
static Font *GetFont(int id); | |||||
}; | }; | ||||
#endif // __DH_FORGE_H__ | #endif // __DH_FORGE_H__ | ||||
@@ -7,10 +7,6 @@ | |||||
# include "config.h" | # include "config.h" | ||||
#endif | #endif | ||||
#include <cstring> | |||||
#include <cstdio> | |||||
#include <cstdlib> | |||||
#include "core.h" | #include "core.h" | ||||
#if defined WIN32 | #if defined WIN32 | ||||
@@ -26,23 +22,7 @@ static class TilerData | |||||
friend class Tiler; | friend class Tiler; | ||||
public: | public: | ||||
TilerData() : | |||||
tilesets(0), | |||||
ntilesets(0) | |||||
{ | |||||
/* Nothing to do */ | |||||
} | |||||
~TilerData() | |||||
{ | |||||
if (ntilesets) | |||||
fprintf(stderr, "ERROR: still %i tilesets in tiler\n", ntilesets); | |||||
free(tilesets); | |||||
} | |||||
private: | |||||
TileSet **tilesets; | |||||
int ntilesets; | |||||
Dict tilesets; | |||||
} | } | ||||
tilerdata; | tilerdata; | ||||
@@ -54,49 +34,27 @@ static TilerData * const data = &tilerdata; | |||||
int Tiler::Register(char const *path) | int Tiler::Register(char const *path) | ||||
{ | { | ||||
int id, empty = -1; | |||||
/* If the tileset is already registered, remember its ID. Look for an | |||||
* empty slot at the same time. */ | |||||
for (id = 0; id < data->ntilesets; id++) | |||||
{ | |||||
TileSet *t = data->tilesets[id]; | |||||
if (!t) | |||||
empty = id; | |||||
else if (!strcasecmp(path, t->GetName())) | |||||
break; | |||||
} | |||||
int id = data->tilesets.MakeSlot(path); | |||||
/* If this is a new tileset, create a new one. */ | |||||
if (id == data->ntilesets) | |||||
if (!data->tilesets.GetEntity(id)) | |||||
{ | { | ||||
if (empty == -1) | |||||
{ | |||||
empty = data->ntilesets++; | |||||
data->tilesets = (TileSet **)realloc(data->tilesets, | |||||
data->ntilesets * sizeof(TileSet *)); | |||||
} | |||||
data->tilesets[empty] = new TileSet(path); | |||||
id = empty; | |||||
TileSet *tileset = new TileSet(path); | |||||
data->tilesets.SetEntity(id, tileset); | |||||
} | } | ||||
data->tilesets[id]->Ref(); | |||||
return id + 1; /* ID 0 is for the empty tileset */ | return id + 1; /* ID 0 is for the empty tileset */ | ||||
} | } | ||||
void Tiler::Deregister(int id) | void Tiler::Deregister(int id) | ||||
{ | { | ||||
--id; /* ID 0 is for the empty tileset */ | |||||
if (data->tilesets[id]->Unref() == 0) | |||||
data->tilesets[id] = NULL; | |||||
data->tilesets.RemoveSlot(id - 1); /* ID 0 is for the empty tileset */ | |||||
} | } | ||||
void Tiler::BlitTile(uint32_t code, int x, int y, int z, int o) | void Tiler::BlitTile(uint32_t code, int x, int y, int z, int o) | ||||
{ | { | ||||
int id = (code >> 16) - 1; /* ID 0 is for the empty tileset */ | int id = (code >> 16) - 1; /* ID 0 is for the empty tileset */ | ||||
data->tilesets[id]->BlitTile(code & 0xffff, x, y, z, o); | |||||
TileSet *tileset = (TileSet *)data->tilesets.GetEntity(id); | |||||
tileset->BlitTile(code & 0xffff, x, y, z, o); | |||||
} | } | ||||
@@ -28,13 +28,12 @@ public: | |||||
protected: | protected: | ||||
/* Inherited from Entity */ | /* Inherited from Entity */ | ||||
virtual char const *GetName(); | |||||
virtual Group GetGroup(); | virtual Group GetGroup(); | ||||
virtual void TickRender(float deltams); | virtual void TickRender(float deltams); | ||||
public: | public: | ||||
/* New methods */ | /* New methods */ | ||||
char const *GetName(); | |||||
void BlitTile(uint32_t id, int x, int y, int z, int o); | void BlitTile(uint32_t id, int x, int y, int z, int o); | ||||
private: | private: | ||||