Ei kuvausta
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

debuggers.cpp 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. #include "debuggers.h"
  2. #include <algorithm>
  3. #include <cmath>
  4. #include <ctime>
  5. #include <iostream>
  6. #include <random>
  7. namespace pabloader {
  8. std::string& rtrim(std::string& str, const std::string& chars = "\t\n\v\f\r ")
  9. {
  10. str.erase(str.find_last_not_of(chars) + 1);
  11. return str;
  12. }
  13. template <>
  14. float Debuggers::GetRandom<float>(float from, float to)
  15. {
  16. if (from > to) {
  17. std::swap(from, to);
  18. }
  19. std::uniform_real_distribution<float> dist(from, to);
  20. return dist(generator);
  21. }
  22. template <>
  23. int Debuggers::GetRandom<int>(int from, int to)
  24. {
  25. if (from > to) {
  26. std::swap(from, to);
  27. }
  28. std::uniform_int_distribution<int> dist(from, to - 1);
  29. return dist(generator);
  30. }
  31. bool Debuggers::OnUserCreate()
  32. {
  33. SetPixelMode(olc::Pixel::MASK);
  34. std::srand(std::time(0));
  35. if (!olc::SOUND::InitialiseAudio()) {
  36. std::cerr << "Cannot init audio" << std::endl;
  37. return false;
  38. }
  39. if (!pack.LoadPack("debuggers.pgp")) {
  40. std::cerr << "Cannot load resource pack res/debuggers.pgp" << std::endl;
  41. return false;
  42. }
  43. // Load Player
  44. std::string fileName = "res/player.pgs";
  45. if (!playerSprite.LoadFromPGESprFile(fileName, &pack)) {
  46. std::cerr << "[Load player] File " << fileName << " is not found" << std::endl;
  47. return false;
  48. }
  49. fileName = "res/fall.wav";
  50. playerFallSample = olc::SOUND::LoadAudioSample(fileName, &pack);
  51. if (playerFallSample < 0) {
  52. std::cerr << "[Load fall] File " << fileName << " is not found" << std::endl;
  53. return false;
  54. }
  55. // Load enemies
  56. fileName = "res/enemies.pgs";
  57. if (!enemiesSprite.LoadFromPGESprFile(fileName, &pack)) {
  58. std::cerr << "[Load enemies] File " << fileName << " is not found" << std::endl;
  59. return false;
  60. }
  61. fileName = "res/bug_fall.wav";
  62. bugFallSample = olc::SOUND::LoadAudioSample(fileName, &pack);
  63. if (bugFallSample < 0) {
  64. std::cerr << "[Load bug fall] File " << fileName << " is not found" << std::endl;
  65. return false;
  66. }
  67. fileName = "res/bug_catch.wav";
  68. bugCatchSample = olc::SOUND::LoadAudioSample(fileName, &pack);
  69. if (bugCatchSample < 0) {
  70. std::cerr << "[Load bug catch] File " << fileName << " is not found" << std::endl;
  71. return false;
  72. }
  73. // Load bonuses
  74. fileName = "res/bonuses.pgs";
  75. if (!bonusesSprite.LoadFromPGESprFile(fileName, &pack)) {
  76. std::cerr << "[Load bonuses] File " << fileName << " is not found" << std::endl;
  77. return false;
  78. }
  79. // Load background
  80. fileName = "res/bg.pgs";
  81. if (!backgroundSprite.LoadFromPGESprFile(fileName, &pack)) {
  82. std::cerr << "[Load background] File " << fileName << " is not found" << std::endl;
  83. return false;
  84. }
  85. fileName = "src/programmer.cpp";
  86. auto streamBuffer = pack.GetStreamBuffer(fileName);
  87. if (streamBuffer.data == nullptr) {
  88. std::cerr << "[Load source] File " << fileName << " is not found" << std::endl;
  89. return false;
  90. }
  91. std::istream is(&streamBuffer);
  92. std::string line;
  93. while (std::getline(is, line)) {
  94. if (!rtrim(line).empty())
  95. sourceCode.push_back(line);
  96. }
  97. totalLines = sourceCode.size();
  98. // Free Memory
  99. pack.ClearPack();
  100. // Creating entities
  101. auto player = new Player(this);
  102. programmers.push_back(player);
  103. return true;
  104. }
  105. bool Debuggers::OnUserUpdate(float fElapsedTime)
  106. {
  107. if (!IsFocused())
  108. return true;
  109. if (sourceCode.size() == 0) {
  110. return GameOver();
  111. }
  112. DrawSprite(0, 0, &backgroundSprite);
  113. uint32_t bugsSize = bugs.size();
  114. auto aliveBugs = std::count_if(bugs.begin(), bugs.end(), [](Bug* bug) { return bug->IsActive() && bug->IsAlive(); });
  115. Programmer* player = programmers.at(0);
  116. for (auto bug : bugs) {
  117. if (bug->IsActive()) {
  118. bug->Update(fElapsedTime);
  119. bug->Draw();
  120. for (auto& programmer : programmers) {
  121. if (programmer->Collides(bug)) {
  122. bugsCatched++;
  123. if (programmer == player) {
  124. bugsCatchedByPlayer++;
  125. }
  126. bug->Kill();
  127. olc::SOUND::PlaySample(bugCatchSample);
  128. SpawnBug();
  129. }
  130. }
  131. } else if (bug->IsAlive()) {
  132. bugsMissed++;
  133. sourceCode.erase(sourceCode.begin());
  134. SpawnBug();
  135. olc::SOUND::PlaySample(bugFallSample);
  136. }
  137. }
  138. for (auto& bonus : bonuses) {
  139. if (bonus->IsActive()) {
  140. bonus->Update(fElapsedTime);
  141. bonus->Draw();
  142. if (player->Collides(bonus)) {
  143. auto type = bonus->GetType();
  144. if (type == BONUS_DOCUMENTATION) {
  145. if (aliveBugs > 1) {
  146. for (auto& bug : bugs) {
  147. if (bug->IsAlive() && bug->IsActive()) {
  148. bug->Kill();
  149. break;
  150. }
  151. }
  152. }
  153. } else {
  154. bonusesCatched[type]++;
  155. }
  156. bonus->Kill();
  157. // TODO play pickup sound
  158. }
  159. } else {
  160. bonus->Kill();
  161. }
  162. }
  163. linesOfCode = (sourceCode.size() * 4 / totalLines) + 1;
  164. for (auto it = programmers.rbegin(); it != programmers.rend(); it++) {
  165. auto& programmer = *it;
  166. programmer->Think();
  167. programmer->Update(fElapsedTime);
  168. programmer->Draw();
  169. }
  170. if (bugsSize == 0 && player->IsOnGround()) {
  171. SpawnBug();
  172. }
  173. auto programmersSize = programmers.size();
  174. if (bugsCatchedByPlayer >= 15 * programmersSize * programmersSize && player->GetSkin() < programmersSize) {
  175. player->UpgradeLevel();
  176. SpawnBug();
  177. SpawnProgrammer();
  178. }
  179. if (bugsCatched > 10 * bugsSize) {
  180. SpawnBug();
  181. }
  182. if (GetRandom<float>() < 0.01 * fElapsedTime) {
  183. SpawnBonus();
  184. }
  185. #ifdef _DEBUG
  186. if (debug) {
  187. DrawString(1, 37, "Bg: " + std::to_string(bugs.size()) + " Ab: " + std::to_string(aliveBugs));
  188. DrawString(1, 46, "Ps: " + std::to_string(programmers.size()) + " Bn: " + std::to_string(bonuses.size()));
  189. DrawString(1, 55, "Cp: " + std::to_string(bugsCatchedByPlayer));
  190. DrawString(1, 64, "DBG: " + std::to_string(bonusesCatched[BONUS_DEBUGGER]));
  191. DrawString(1, 73, "UTS: " + std::to_string(bonusesCatched[BONUS_UNIT_TEST]));
  192. if (GetKey(olc::B).bPressed) {
  193. SpawnBug();
  194. }
  195. if (GetKey(olc::N).bPressed) {
  196. SpawnBonus();
  197. }
  198. if (GetKey(olc::P).bPressed) {
  199. SpawnProgrammer();
  200. }
  201. }
  202. if (GetKey(olc::K0).bReleased) {
  203. debug = !debug;
  204. }
  205. #endif
  206. DrawString(1, 1, "A,S,D - move; SPACE - jump", olc::CYAN);
  207. DrawString(1, 10, "Don't let the bugs destroy your code!", olc::YELLOW);
  208. DrawString(1, 19, "Bugs catched: " + std::to_string(bugsCatched));
  209. DrawString(1, 28, "Bugs missed: " + std::to_string(bugsMissed));
  210. int y = GameScreenHeight();
  211. FillRect(0, y - 1, ScreenWidth(), ScreenHeight() - y + 1, olc::VERY_DARK_GREY);
  212. for (auto& line : sourceCode) {
  213. DrawString(1, y, line);
  214. y += 10;
  215. if (y >= ScreenHeight())
  216. break;
  217. }
  218. return true;
  219. }
  220. bool Debuggers::GameOver()
  221. {
  222. DrawSprite(0, 0, &backgroundSprite);
  223. DrawString(ScreenWidth() / 2 - 143, ScreenHeight() / 2 - 15, "GAME OVER", olc::BLACK, 4);
  224. DrawString(ScreenWidth() / 2 - 144, ScreenHeight() / 2 - 16, "GAME OVER", olc::RED, 4);
  225. DrawString(ScreenWidth() / 2 - 144, ScreenHeight() / 2 + 16, "Bugs catched: " + std::to_string(bugsCatched), olc::CYAN, 2);
  226. return true;
  227. }
  228. void Debuggers::SpawnBug()
  229. {
  230. auto bug = CreateBug();
  231. bug->ResetPosition();
  232. }
  233. void Debuggers::SpawnBonus()
  234. {
  235. auto bonus = CreateBonus();
  236. bonus->ResetPosition();
  237. }
  238. void Debuggers::SpawnProgrammer()
  239. {
  240. auto programmer = new Programmer(this);
  241. programmers.push_back(programmer);
  242. }
  243. Bug* Debuggers::CreateBug()
  244. {
  245. for (auto bug : bugs) {
  246. if (!bug->IsActive() || !bug->IsAlive())
  247. return bug;
  248. }
  249. auto bug = new Bug(this);
  250. bugs.push_back(bug);
  251. return bug;
  252. }
  253. Bonus* Debuggers::CreateBonus()
  254. {
  255. for (auto bonus : bonuses) {
  256. if (!bonus->IsActive())
  257. return bonus;
  258. }
  259. auto bonus = new Bonus(this);
  260. bonuses.push_back(bonus);
  261. return bonus;
  262. }
  263. bool Debuggers::OnUserDestroy()
  264. {
  265. olc::SOUND::DestroyAudio();
  266. return true;
  267. }
  268. }