diff --git a/src/Makefile.am b/src/Makefile.am
index d72a6630..5519b34b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,7 +7,7 @@ liblol_a_SOURCES = \
     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 \
     profiler.cpp profiler.h input.h input.cpp world.cpp world.h \
-    sample.cpp sample.h sampler.cpp sampler.h \
+    sample.cpp sample.h sampler.cpp sampler.h text.cpp text.h \
     \
     sdlinput.cpp sdlinput.h \
     \
diff --git a/src/core.h b/src/core.h
index 903057cc..7bdb1c63 100644
--- a/src/core.h
+++ b/src/core.h
@@ -30,8 +30,9 @@
 // Entities
 #include "entity.h"
 #include "font.h"
-#include "tileset.h"
 #include "sample.h"
+#include "text.h"
+#include "tileset.h"
 #include "world.h"
 
 // Other objects
diff --git a/src/debugfps.cpp b/src/debugfps.cpp
index 05c33950..8ede59df 100644
--- a/src/debugfps.cpp
+++ b/src/debugfps.cpp
@@ -26,8 +26,7 @@ class DebugFpsData
     friend class DebugFps;
 
 private:
-    int x, y;
-    int fontid;
+    Text *lines[5];
 };
 
 /*
@@ -37,52 +36,50 @@ private:
 DebugFps::DebugFps(int x, int y)
   : data(new DebugFpsData())
 {
-    data->fontid = Forge::Register("gfx/font/ascii.png");
-    data->x = x;
-    data->y = y;
-
-    drawgroup = DRAWGROUP_HUD;
+    for (int i = 0; i < 5; i ++)
+    {
+        data->lines[i] = new Text(NULL, "gfx/font/ascii.png");
+        data->lines[i]->SetPos(Int3(x, y + (i ? 8 : 0) + 16 * i, 0));
+        Ticker::Ref(data->lines[i]);
+    }
 }
 
-void DebugFps::TickDraw(float deltams)
+void DebugFps::TickGame(float deltams)
 {
-    Entity::TickDraw(deltams);
+    Entity::TickGame(deltams);
 
     char buf[1024];
-    Font *font = Forge::GetFont(data->fontid);
-
-    int x = data->x;
-    int y = data->y;
 
     sprintf(buf, "%2.2f fps (%i)",
             1e3f / Profiler::GetAvg(Profiler::STAT_TICK_FRAME),
             Ticker::GetFrameNum());
-    font->PrintBold(x, y, buf);
+    data->lines[0]->SetText(buf);
 
     sprintf(buf, "Game  % 7.2f % 7.2f",
             Profiler::GetAvg(Profiler::STAT_TICK_GAME),
             Profiler::GetMax(Profiler::STAT_TICK_GAME));
-    font->PrintBold(x, y + 24, buf);
+    data->lines[1]->SetText(buf);
 
     sprintf(buf, "Draw  % 7.2f % 7.2f",
             Profiler::GetAvg(Profiler::STAT_TICK_DRAW),
             Profiler::GetMax(Profiler::STAT_TICK_DRAW));
-    font->PrintBold(x, y + 40, buf);
+    data->lines[2]->SetText(buf);
 
     sprintf(buf, "Blit  % 7.2f % 7.2f",
             Profiler::GetAvg(Profiler::STAT_TICK_BLIT),
             Profiler::GetMax(Profiler::STAT_TICK_BLIT));
-    font->PrintBold(x, y + 56, buf);
+    data->lines[3]->SetText(buf);
 
     sprintf(buf, "Frame % 7.2f % 7.2f",
             Profiler::GetAvg(Profiler::STAT_TICK_FRAME),
             Profiler::GetMax(Profiler::STAT_TICK_FRAME));
-    font->PrintBold(x, y + 72, buf);
+    data->lines[4]->SetText(buf);
 }
 
 DebugFps::~DebugFps()
 {
-    Forge::Deregister(data->fontid);
+    for (int i = 0; i < 5; i ++)
+        Ticker::Unref(data->lines[i]);
     delete data;
 }
 
diff --git a/src/debugfps.h b/src/debugfps.h
index 67b17072..2f33c95c 100644
--- a/src/debugfps.h
+++ b/src/debugfps.h
@@ -27,7 +27,7 @@ public:
     virtual ~DebugFps();
 
 protected:
-    virtual void TickDraw(float deltams);
+    virtual void TickGame(float deltams);
 
 private:
     DebugFpsData *data;
diff --git a/src/text.cpp b/src/text.cpp
new file mode 100644
index 00000000..bf6d85ab
--- /dev/null
+++ b/src/text.cpp
@@ -0,0 +1,79 @@
+//
+// Lol Engine
+//
+// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
+//   This program is free software; you can redistribute it and/or
+//   modify it under the terms of the Do What The Fuck You Want To
+//   Public License, Version 2, as published by Sam Hocevar. See
+//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+//
+
+#if defined HAVE_CONFIG_H
+#   include "config.h"
+#endif
+
+#include <cstdio>
+#include <cstdlib> /* free() */
+#include <cstring> /* strdup() */
+
+#include "core.h"
+
+/*
+ * Text implementation class
+ */
+
+class TextData
+{
+    friend class Text;
+
+private:
+    int font;
+    char *text;
+    Int3 pos;
+};
+
+/*
+ * Public Text class
+ */
+
+Text::Text(char const *text, char const *font)
+  : data(new TextData())
+{
+    data->font = Forge::Register(font);
+    data->text = text ? strdup(text) : NULL;
+    data->pos = Int3(0, 0, 0);
+
+    drawgroup = DRAWGROUP_HUD;
+}
+
+void Text::SetText(char const *text)
+{
+    if (data->text)
+        free(data->text);
+    data->text = text ? strdup(text) : NULL;
+}
+
+void Text::SetPos(Int3 pos)
+{
+    data->pos = pos;
+}
+
+void Text::TickDraw(float deltams)
+{
+    Entity::TickDraw(deltams);
+
+    if (data->text)
+    {
+        Font *font = Forge::GetFont(data->font);
+        font->PrintBold(data->pos.x, data->pos.y, data->text);
+    }
+}
+
+Text::~Text()
+{
+    if (data->text)
+        free(data->text);
+    Forge::Deregister(data->font);
+    delete data;
+}
+
diff --git a/src/text.h b/src/text.h
new file mode 100644
index 00000000..6f4a32ec
--- /dev/null
+++ b/src/text.h
@@ -0,0 +1,40 @@
+//
+// Lol Engine
+//
+// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
+//   This program is free software; you can redistribute it and/or
+//   modify it under the terms of the Do What The Fuck You Want To
+//   Public License, Version 2, as published by Sam Hocevar. See
+//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+//
+
+//
+// The Text class
+// --------------
+//
+
+#if !defined __DH_TEXT_H__
+#define __DH_TEXT_H__
+
+#include "entity.h"
+
+class TextData;
+
+class Text : public Entity
+{
+public:
+    Text(char const *text, char const *font);
+    virtual ~Text();
+
+    void SetText(char const *text);
+    void SetPos(Int3 pos);
+
+protected:
+    virtual void TickDraw(float deltams);
+
+private:
+    TextData *data;
+};
+
+#endif // __DH_TEXT_H__
+
diff --git a/win32/deushax.vcxproj b/win32/deushax.vcxproj
index ff20a23f..9f69b0df 100644
--- a/win32/deushax.vcxproj
+++ b/win32/deushax.vcxproj
@@ -33,6 +33,7 @@
     <ClInclude Include="..\src\sampler.h" />
     <ClInclude Include="..\src\scene.h" />
     <ClInclude Include="..\src\sdlinput.h" />
+    <ClInclude Include="..\src\text.h" />
     <ClInclude Include="..\src\ticker.h" />
     <ClInclude Include="..\src\tiler.h" />
     <ClInclude Include="..\src\tileset.h" />
@@ -61,6 +62,7 @@
     <ClCompile Include="..\src\sampler.cpp" />
     <ClCompile Include="..\src\scene.cpp" />
     <ClCompile Include="..\src\sdlinput.cpp" />
+    <ClCompile Include="..\src\text.cpp" />
     <ClCompile Include="..\src\ticker.cpp" />
     <ClCompile Include="..\src\tiler.cpp" />
     <ClCompile Include="..\src\tileset.cpp" />
diff --git a/win32/deushax.vcxproj.filters b/win32/deushax.vcxproj.filters
index 9ae5c6cf..fd701e11 100644
--- a/win32/deushax.vcxproj.filters
+++ b/win32/deushax.vcxproj.filters
@@ -57,6 +57,9 @@
     <ClInclude Include="..\src\sdlinput.h">
       <Filter>lolengine</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\text.h">
+      <Filter>lolengine</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\ticker.h">
       <Filter>lolengine</Filter>
     </ClInclude>
@@ -130,6 +133,9 @@
     <ClCompile Include="..\src\sdlinput.cpp">
       <Filter>lolengine</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\text.cpp">
+      <Filter>lolengine</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\ticker.cpp">
       <Filter>lolengine</Filter>
     </ClCompile>
@@ -161,4 +167,4 @@
       <Filter>lolengine</Filter>
     </ClCompile>
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/win32/monsterz.vcxproj b/win32/monsterz.vcxproj
index 51e9b806..1dd468db 100644
--- a/win32/monsterz.vcxproj
+++ b/win32/monsterz.vcxproj
@@ -36,6 +36,7 @@
     <ClInclude Include="..\src\sampler.h" />
     <ClInclude Include="..\src\scene.h" />
     <ClInclude Include="..\src\sdlinput.h" />
+    <ClInclude Include="..\src\text.h" />
     <ClInclude Include="..\src\ticker.h" />
     <ClInclude Include="..\src\tiler.h" />
     <ClInclude Include="..\src\tileset.h" />
@@ -66,6 +67,7 @@
     <ClCompile Include="..\src\sampler.cpp" />
     <ClCompile Include="..\src\scene.cpp" />
     <ClCompile Include="..\src\sdlinput.cpp" />
+    <ClCompile Include="..\src\text.cpp" />
     <ClCompile Include="..\src\ticker.cpp" />
     <ClCompile Include="..\src\tiler.cpp" />
     <ClCompile Include="..\src\tileset.cpp" />
@@ -149,4 +151,4 @@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/win32/monsterz.vcxproj.filters b/win32/monsterz.vcxproj.filters
index 9d9de497..074ca199 100644
--- a/win32/monsterz.vcxproj.filters
+++ b/win32/monsterz.vcxproj.filters
@@ -57,6 +57,9 @@
     <ClInclude Include="..\src\sdlinput.h">
       <Filter>lolengine</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\text.h">
+      <Filter>lolengine</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\ticker.h">
       <Filter>lolengine</Filter>
     </ClInclude>
@@ -133,6 +136,9 @@
     <ClCompile Include="..\src\sdlinput.cpp">
       <Filter>lolengine</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\text.cpp">
+      <Filter>lolengine</Filter>
+    </ClCompile>
     <ClCompile Include="..\src\ticker.cpp">
       <Filter>lolengine</Filter>
     </ClCompile>
@@ -166,4 +172,4 @@
       <Filter>lolengine</Filter>
     </ClCompile>
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>