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
Index: makefile
===================================================================
--- makefile	(revision 699e83a728c7db8f10c4637546020207c0b0d4c0)
+++ makefile	(revision f809ae61a5d5445348cd3ecae245fea1da9cf902)
@@ -60,5 +60,5 @@
 
 GUI_SRC_FILES = gui/screen.cpp gui/main-screen.cpp gui/game-screen.cpp gui/ui-element.cpp gui/button.cpp gui/panel.cpp
-GUI_HEADER_FILES = gui/screen.hpp gui/main-screen.hpp gui/game-screen.hpp gui/ui-element.hpp gui/button.hpp gui/panel.hpp
+GUI_HEADER_FILES = gui/screen.hpp gui/main-screen.hpp gui/game-screen.hpp gui/ui-element.hpp gui/button.hpp gui/panel.hpp gui/ui-value.hpp
 
 SRC_FILES = main-vulkan.cpp vulkan-game.cpp crash-logger.cpp logger.cpp vulkan-utils.cpp utils.cpp game-gui-sdl.cpp $(GUI_SRC_FILES)
Index: vulkan-game.cpp
===================================================================
--- vulkan-game.cpp	(revision 699e83a728c7db8f10c4637546020207c0b0d4c0)
+++ vulkan-game.cpp	(revision f809ae61a5d5445348cd3ecae245fea1da9cf902)
@@ -44,4 +44,6 @@
 
    cout << "Vulkan Game" << endl;
+
+   this->score = 0;
 
    if (initUI(width, height, guiFlags) == RTWO_ERROR) {
@@ -674,4 +676,7 @@
    curTime = duration<float, seconds::period>(high_resolution_clock::now() - this->startTime).count();
 
+   this->fpsStartTime = curTime;
+   this->frameCount = 0;
+
    lastSpawn_asteroid = curTime;
 
@@ -681,4 +686,13 @@
       curTime = duration<float, seconds::period>(high_resolution_clock::now() - this->startTime).count();
       this->elapsedTime = curTime - this->prevTime;
+
+      if (curTime - this->fpsStartTime >= 1.0f) {
+         this->fps = (float)frameCount / (curTime - this->fpsStartTime);
+
+         this->frameCount = 0;
+         this->fpsStartTime = curTime;
+      }
+
+      this->frameCount++;
 
       gui->processEvents();
@@ -818,5 +832,4 @@
       }
 
-      // renderUI();
       currentScreen->renderUI();
 
@@ -877,5 +890,5 @@
             addExplosion(model_mat, 0.5f, curTime);
 
-            // TODO: Increment player's score here
+            this->score++;
          } else if ((objCenter.z - asteroid.radius) > -NEAR_CLIP) {
             asteroid.ssbo.deleted = true;
@@ -1022,27 +1035,4 @@
 
    VulkanUtils::copyDataToMemory(device, uniformBuffersMemory_explosionPipeline[currentImage], 0, explosion_UBO);
-}
-
-void VulkanGame::renderUI() {
-   SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00);
-   SDL_RenderClear(renderer);
-
-   SDL_Rect rect = {280, 220, 100, 100};
-   SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
-   SDL_RenderFillRect(renderer, &rect);
-
-   rect = {10, 10, 0, 0};
-   SDL_QueryTexture(fontSDLTexture, nullptr, nullptr, &(rect.w), &(rect.h));
-   SDL_RenderCopy(renderer, fontSDLTexture, nullptr, &rect);
-
-   rect = {10, 80, 0, 0};
-   SDL_QueryTexture(imageSDLTexture, nullptr, nullptr, &(rect.w), &(rect.h));
-   SDL_RenderCopy(renderer, imageSDLTexture, nullptr, &rect);
-
-   SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0xFF, 0xFF);
-   SDL_RenderDrawLine(renderer, 50, 5, 150, 500);
-
-   VulkanUtils::populateVulkanImageFromSDLTexture(device, physicalDevice, commandPool, uiOverlay, renderer,
-      sdlOverlayImage, graphicsQueue);
 }
 
Index: vulkan-game.hpp
===================================================================
--- vulkan-game.hpp	(revision 699e83a728c7db8f10c4637546020207c0b0d4c0)
+++ vulkan-game.hpp	(revision f809ae61a5d5445348cd3ecae245fea1da9cf902)
@@ -204,4 +204,7 @@
       TTF_Font* proggyFont;
 
+      int score;
+      float fps;
+
       GraphicsPipeline_Vulkan<OverlayVertex, void*> overlayPipeline;
 
@@ -345,4 +348,7 @@
       float prevTime, elapsedTime;
 
+      float fpsStartTime;
+      int frameCount;
+
       float shipSpeed = 0.5f;
       float asteroidSpeed = 2.0f;
@@ -363,5 +369,4 @@
       void mainLoop();
       void updateScene(uint32_t currentImage);
-      void renderUI();
       void renderScene();
       void cleanup();
