Index: gui/game-screen.cpp
===================================================================
--- gui/game-screen.cpp	(revision 699e83a728c7db8f10c4637546020207c0b0d4c0)
+++ gui/game-screen.cpp	(revision f809ae61a5d5445348cd3ecae245fea1da9cf902)
@@ -9,4 +9,5 @@
 #include "button.hpp"
 #include "panel.hpp"
+#include "ui-value.hpp"
 
 using namespace std;
@@ -20,4 +21,9 @@
       Screen(renderer, gameInfo) {
    Panel *statsPanel = new Panel(10, 50, 95, 46, 0x161616FF, this->renderer);
+
+   statsPanel->addUIElement(new UIValue(0, 0, "Score: ", this->gameInfo.score,
+      this->gameInfo.proggyFont, 0xFFFFFFFF, this->renderer));
+   statsPanel->addUIElement(new UIValue(14, 19, "FPS: ", this->gameInfo.fps,
+      this->gameInfo.proggyFont, 0xFFFFFFFF, this->renderer));
 
    // TODO: Add the button to the panel it's in, not directly to the window
Index: gui/ui-value.hpp
===================================================================
--- gui/ui-value.hpp	(revision f809ae61a5d5445348cd3ecae245fea1da9cf902)
+++ gui/ui-value.hpp	(revision f809ae61a5d5445348cd3ecae245fea1da9cf902)
@@ -0,0 +1,105 @@
+#ifndef _UI_VALUE_HPP
+#define _UI_VALUE_HPP
+
+#include <sstream>
+#include <stdint.h>
+#include <string>
+
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_ttf.h>
+
+#include "ui-element.hpp"
+
+template<class T>
+class UIValue : public UIElement {
+public:
+   UIValue(int x, int y, string label, T& value, TTF_Font* font, uint32_t textColor,
+      SDL_Renderer& renderer);
+   ~UIValue() override;
+
+   void render(int x, int y) override;
+
+private:
+   string label;
+   T* value;
+   T oldValue;
+
+   TTF_Font* font;
+   SDL_Color textColor;
+
+   SDL_Texture* texture;
+
+   void createTexture();
+};
+
+template<class T>
+UIValue<T>::UIValue(int x, int y, string label, T& value, TTF_Font* font, uint32_t textColor,
+      SDL_Renderer& renderer) :
+      UIElement(x, y, 0, 0, renderer, nullptr, nullptr, nullptr),
+      label(label), value(&value), oldValue(value), font(font), texture(nullptr) {
+   this->textColor = {
+      static_cast<Uint8>((textColor >> 24) & 0xFF),
+      static_cast<Uint8>((textColor >> 16) & 0xFF),
+      static_cast<Uint8>((textColor >> 8) & 0xFF),
+      static_cast<Uint8>(textColor & 0xFF)
+   };
+
+   this->createTexture();
+}
+
+template<class T>
+UIValue<T>::~UIValue() {
+   if (this->texture != nullptr) {
+      SDL_DestroyTexture(this->texture);
+      this->texture = nullptr;
+   }
+}
+
+template<class T>
+void UIValue<T>::createTexture() {
+   // destroy the old texture before re-creating it
+   if (this->texture != nullptr) {
+      SDL_DestroyTexture(this->texture);
+      this->texture = nullptr;
+   }
+
+   ostringstream oss;
+   oss << label << *this->value;
+
+   string text = oss.str();
+
+   SDL_Surface* surface = TTF_RenderText_Blended(this->font, text.c_str(),
+      this->textColor);
+   if (surface == nullptr) {
+      cout << "Unable to render text surface! SDL_ttf Error: " << TTF_GetError() << endl;
+   }
+
+   this->texture = SDL_CreateTextureFromSurface(&this->renderer, surface);
+   if (this->texture == nullptr) {
+      cout << "Unable to create texture from rendered text! SDL Error: " << SDL_GetError() << endl;
+      // SDL_FreeSurface(surface);
+   }
+
+   SDL_FreeSurface(surface);
+
+   TTF_SizeText(this->font, text.c_str(), &this->width, &this->height);
+}
+
+template<class T>
+void UIValue<T>::render(int x, int y) {
+   if (this->oldValue != *this->value) {
+      this->createTexture();
+      this->oldValue = *this->value;
+   }
+
+   SDL_Rect rect = {
+         this->x + x,
+         this->y + y,
+         this->width,
+         this->height
+   };
+
+   SDL_RenderCopy(&this->renderer, this->texture, nullptr, &rect);
+}
+
+#endif // _UI_VALUE_HPP
