From dfa2d88008052fb2d808c2af6fcb030c837aa151 Mon Sep 17 00:00:00 2001
From: Tamir Atias <engine.games@gmail.com>
Date: Wed, 1 Feb 2012 02:15:54 +0200
Subject: [PATCH] [Add] Levels and leveling up!

---
 Unuk-QT/Unuk-QT.pro.user            |  2 +-
 src/Unuk/Game.cpp                   | 32 ++++++++++++++++++++++++-----
 src/Unuk/Game.h                     |  2 ++
 src/Unuk/Player.cpp                 | 27 +++++++++++++++++++++++-
 src/Unuk/Player.h                   | 14 +++++++++++++
 src/libUnuk/Engine/WorldManager.cpp |  5 ++++-
 src/libUnuk/Engine/WorldManager.h   |  4 ++--
 src/libUnuk/LevelGen/LevelGen.cpp   | 10 +++++++++
 8 files changed, 86 insertions(+), 10 deletions(-)

diff --git a/Unuk-QT/Unuk-QT.pro.user b/Unuk-QT/Unuk-QT.pro.user
index 56889ad..1c2634f 100644
--- a/Unuk-QT/Unuk-QT.pro.user
+++ b/Unuk-QT/Unuk-QT.pro.user
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE QtCreatorProject>
-<!-- Written by Qt Creator 2.4.0, 2012-01-30T01:06:01. -->
+<!-- Written by Qt Creator 2.4.0, 2012-02-01T02:13:25. -->
 <qtcreator>
  <data>
   <variable>ProjectExplorer.Project.ActiveTarget</variable>
diff --git a/src/Unuk/Game.cpp b/src/Unuk/Game.cpp
index 79a8398..d8a78cc 100644
--- a/src/Unuk/Game.cpp
+++ b/src/Unuk/Game.cpp
@@ -20,6 +20,9 @@ gameNavVal_t Game::Run(const string savegameIDArg) {
 	_player->LoadSprites("../Data/Media/Images/Characters/Player.png", 40, 45);
 
   LoadSavegame(savegameIDArg);
+  
+  // some weird bug. player->_exp is set to unreasonable number randomally after LoadSavegame returns.
+  _player->SetExpNeeded(Player::BASE_EXP_NEEDED);
 
   int fps = 0;
   int frame = 0;
@@ -34,18 +37,18 @@ gameNavVal_t Game::Run(const string savegameIDArg) {
   Timer renderTimer;
   Timer updateTimer;
 
-  _gameRenderTime.SetXY(10, 50);
+  _gameRenderTime.SetXY(10, 70);
   _gameRenderTime.SetTextBlended("Render - XX", vsmall, COLOUR_BLACK);
 
-  _gameUpdateTime.SetXY(10, 70);
+  _gameUpdateTime.SetXY(10, 90);
   _gameUpdateTime.SetTextBlended("Update - XX", vsmall, COLOUR_BLACK);
 
   stringstream playerXYString;
-  _playerXY.SetXY(10, 90);
+  _playerXY.SetXY(10, 110);
   _playerXY.SetTextBlended("Player coords - XX XX", vsmall, COLOUR_BLACK);
 
   stringstream npcHealth;
-  _npcHealth.SetXY(10, 110);
+  _npcHealth.SetXY(10, 130);
 	_npcHealth.SetTextBlended("NPC X Health - XX", vsmall, COLOUR_BLACK);
 
   _playerHealthBar.SetBackgroundRGB(0, 0, 0);
@@ -53,10 +56,20 @@ gameNavVal_t Game::Run(const string savegameIDArg) {
   _playerHealthBar.SetXY(10, 20);
   _playerHealthBar.SetWidthHeight(200, 25);
 
+  _playerExpBar.SetBackgroundRGB(0, 0, 0);
+  _playerExpBar.SetForegroundRGB(0, 0, 255);
+  _playerExpBar.SetXY(10, 50);
+  _playerExpBar.SetWidthHeight(200, 25);
+  _playerExpBar.SetProgress(0.0f);
+  
   stringstream playerHealth;
   _playerHealth.SetXY(15, 27);
   _playerHealth.SetTextBlended("Player Health - XX", vsmall, COLOUR_WHITE);
 
+  stringstream playerExp;
+  _playerExp.SetXY(15, 57);
+  _playerExp.SetTextBlended("Player Level XX (XX/XX)", vsmall, COLOUR_WHITE);
+  
   _gameRunning = true;
   while(_gameRunning) {
 		bool stillRunning = true;
@@ -96,10 +109,16 @@ gameNavVal_t Game::Run(const string savegameIDArg) {
       frame = 0;
 
       playerHealth.str("");
-      playerHealth << "Player Health: " << _player->GetHealth();
+      playerHealth << "Player Health - " << _player->GetHealth();
       _playerHealth.SetTextBlended(playerHealth.str(), vsmall, COLOUR_WHITE);
 
       _playerHealthBar.SetProgress((float)_player->GetHealth() / 100.0f);
+      
+      playerExp.str("");
+      playerExp << "Player Level " << _player->GetLevel() <<  "  (" << _player->GetExp() << "/" << _player->GetExpNeeded() << ")";
+      _playerExp.SetTextBlended(playerExp.str(), vsmall, COLOUR_WHITE);
+      
+      _playerExpBar.SetProgress((float)_player->GetExp() / (float)_player->GetExpNeeded());
 
       // Check to see if we are allowed to display debug info.
       if(debugEnabled) {
@@ -205,6 +224,9 @@ void Game::Render(void) {
 
     _playerHealthBar.DrawLiteral();
     _playerHealth.RenderLiteral();
+    
+    _playerExpBar.DrawLiteral();
+    _playerExp.RenderLiteral();
    
     if(debugEnabled) {
       _gameRenderTime.RenderLiteral();
diff --git a/src/Unuk/Game.h b/src/Unuk/Game.h
index 68b9ab0..aaf34f0 100644
--- a/src/Unuk/Game.h
+++ b/src/Unuk/Game.h
@@ -59,7 +59,9 @@ private:
   Player* _player;
 
   Text  _playerHealth;
+  Text  _playerExp;
   Bar   _playerHealthBar;
+  Bar   _playerExpBar;
 
   EventHistory _eventHistory;
 };
diff --git a/src/Unuk/Player.cpp b/src/Unuk/Player.cpp
index 628bcd7..f5d5fc9 100644
--- a/src/Unuk/Player.cpp
+++ b/src/Unuk/Player.cpp
@@ -3,8 +3,13 @@
 // Pixels * 60 / sec.
 const float Player::PLAYER_SPEED = Character::CHARACTER_SPEED + 0.5f;
 
-Player::Player(LevelGen *mapArg) : Character(mapArg) {
+// Amount of Exp needed to level up from 1 to 2
+const int Player::BASE_EXP_NEEDED = 10;
 
+Player::Player(LevelGen *mapArg) : Character(mapArg) {
+    _level = 1;
+    _exp = 0;
+    _expNeeded = BASE_EXP_NEEDED;
 }
 
 Player::~Player(void) {
@@ -101,3 +106,23 @@ void Player::Move() {
     map->Load(map->GetMapTransitionName(tileX, tileY));
   }
 }
+
+void Player::SetLevel(int level) {
+  _level = level;
+  _exp = _exp - _expNeeded;
+  if(_exp < 0) {
+    _exp = 0;
+  }
+  _expNeeded = pow(BASE_EXP_NEEDED, _level);
+}
+
+void Player::SetExp(int exp) {
+  _exp += exp;
+  if(_exp >= _expNeeded) {
+      SetLevel(_level + 1);
+  } 
+}
+
+void Player::SetExpNeeded(int expNeeded) {
+  _expNeeded = expNeeded;
+}
diff --git a/src/Unuk/Player.h b/src/Unuk/Player.h
index f2fe62c..e30cfc4 100644
--- a/src/Unuk/Player.h
+++ b/src/Unuk/Player.h
@@ -16,7 +16,18 @@ public:
 
   void SetName(string nameArg);
   string GetName(void) { return _name; }
+  
+  void SetLevel(int level);
+  int GetLevel() { return _level; }
 
+  void SetExp(int exp);
+  int GetExp() { return _exp; }
+  
+  int GetExpNeeded() { return _expNeeded; }
+  void SetExpNeeded(int expNeeded);
+  
+  static const int BASE_EXP_NEEDED;
+  
 protected:
   void Move(void);
   void CheckTileCollisions(void);
@@ -27,4 +38,7 @@ private:
 
   string _name;
   //int _health;
+  int _level;
+  int _exp;
+  int _expNeeded;
 };
diff --git a/src/libUnuk/Engine/WorldManager.cpp b/src/libUnuk/Engine/WorldManager.cpp
index 0f8fc81..4a5ba03 100644
--- a/src/libUnuk/Engine/WorldManager.cpp
+++ b/src/libUnuk/Engine/WorldManager.cpp
@@ -1,5 +1,6 @@
 #include "WorldManager.h"
 #include "NPC.h"
+#include "../../Unuk/Player.h"
 
 WorldManager::WorldManager(void) {
 }
@@ -53,7 +54,7 @@ NPC* WorldManager::GetNPC(int index) {
   return NULL;
 }
 
-void WorldManager::OnPlayerAttack(Character* player) {
+void WorldManager::OnPlayerAttack(Player* player) {
   int playerX = (int)(player->GetX() / 32.0f);
   int playerY = (int)(player->GetY() / 32.0f);
   int playerDir = player->GetDirectionFacing();
@@ -95,6 +96,8 @@ void WorldManager::OnPlayerAttack(Character* player) {
     npc->OnAttack();
 
     if(npc->GetHealth() <= 0) {
+      int expGain = 3 + (rand() % 2);
+      player->SetExp(player->GetExp() + expGain);
       i = _npcs.erase(i);
       delete npc;
     }
diff --git a/src/libUnuk/Engine/WorldManager.h b/src/libUnuk/Engine/WorldManager.h
index 001b0f9..dfa77e3 100644
--- a/src/libUnuk/Engine/WorldManager.h
+++ b/src/libUnuk/Engine/WorldManager.h
@@ -2,7 +2,7 @@
 #include <list>
 
 class NPC;
-class Character;
+class Player;
 
 class WorldManager {
 public:
@@ -18,7 +18,7 @@ public:
 
   int  GetNPCCount() { return _npcs.size(); }
 
-  void OnPlayerAttack(Character* player);
+  void OnPlayerAttack(Player* player);
 
 private:
   std::list<NPC*> _npcs;
diff --git a/src/libUnuk/LevelGen/LevelGen.cpp b/src/libUnuk/LevelGen/LevelGen.cpp
index 82ebb2f..1ad3c24 100644
--- a/src/libUnuk/LevelGen/LevelGen.cpp
+++ b/src/libUnuk/LevelGen/LevelGen.cpp
@@ -143,6 +143,16 @@ void LevelGen::Load(const string filename) {
   npc->SetXY(100, 250);
   npc->LoadSprites("../Data/Media/Images/Characters/template.png", 40,45);
   _world.AddNPC(npc);
+  
+  npc = new NPC(this);
+  npc->SetXY(170, 250);
+  npc->LoadSprites("../Data/Media/Images/Characters/template.png", 40,45);
+  _world.AddNPC(npc);
+  
+  npc = new NPC(this);
+  npc->SetXY(170, 230);
+  npc->LoadSprites("../Data/Media/Images/Characters/template.png", 40,45);
+  _world.AddNPC(npc);
 }
 
 void LevelGen::Update(void) {