Renderer.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. //
  2. // Created by jovian on 18/07/17.
  3. //
  4. #include <iostream>
  5. #include <SDL_image.h>
  6. #include "Renderer.h"
  7. #define RAD_TO_DEG 57.2957795130f
  8. Renderer::Renderer()
  9. : m_screenWidth(0), m_screenHeight(0), m_window(nullptr), m_renderer(nullptr), m_font(nullptr) {}
  10. Renderer::~Renderer() {
  11. // Destroy textures
  12. while (!m_pictureTab.empty()) {
  13. if (m_pictureTab.back() != nullptr)
  14. SDL_DestroyTexture(m_pictureTab.back());
  15. m_pictureTab.pop_back();
  16. }
  17. // Destroy string textures
  18. for (auto it(m_stringTab.begin()); it != m_stringTab.end(); it++) {
  19. if (it->second != nullptr)
  20. SDL_DestroyTexture(it->second);
  21. it->second = nullptr;
  22. }
  23. m_stringTab.clear();
  24. // Destroy SDL renderer
  25. if (m_renderer != nullptr) {
  26. SDL_DestroyRenderer(m_renderer);
  27. m_renderer = nullptr;
  28. }
  29. // Destroy the beautiful window
  30. if (m_window != nullptr) {
  31. SDL_DestroyWindow(m_window);
  32. m_window = nullptr;
  33. }
  34. // Quit modules
  35. TTF_Quit();
  36. IMG_Quit();
  37. SDL_Quit();
  38. }
  39. bool Renderer::initialize() {
  40. // Announce
  41. std::cout << "Renderer::initialize() > ";
  42. // Already initialized
  43. if (m_window != nullptr) {
  44. std::cout << "Window already created." << std::endl << std::endl;
  45. return false;
  46. }
  47. // Default screen size
  48. m_screenWidth = 1200;
  49. m_screenHeight = 700;
  50. // Init video
  51. if (SDL_Init(SDL_INIT_VIDEO) != 0) {
  52. std::cout << "SDL video failed : " << SDL_GetError() << std::endl << std::endl;
  53. return false;
  54. }
  55. // Init font
  56. if (TTF_Init() == -1) {
  57. std::cout << "TTF failed : " << TTF_GetError() << std::endl << std::endl;
  58. return false;
  59. }
  60. m_font = TTF_OpenFont("droid.ttf", 28);
  61. if (m_font == NULL) {
  62. std::cout << "Open droid.ttf failed : " << TTF_GetError() << std::endl << std::endl;
  63. return false;
  64. }
  65. // Opening window
  66. m_window = SDL_CreateWindow("SpaceExpansion",
  67. SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
  68. m_screenWidth, m_screenHeight,
  69. SDL_WINDOW_SHOWN /*| SDL_WINDOW_FULLSCREEN_DESKTOP*/);
  70. if (m_window == nullptr) {
  71. std::cout << "Window creation failed : " << SDL_GetError() << std::endl << std::endl;
  72. SDL_Quit();
  73. return false;
  74. }
  75. // Hardware physical screen size
  76. SDL_GetWindowSize(m_window, &m_screenWidth, &m_screenHeight);
  77. // Create renderer
  78. m_renderer = SDL_CreateRenderer(m_window, -1,
  79. SDL_RENDERER_ACCELERATED |
  80. SDL_RENDERER_PRESENTVSYNC);
  81. if (m_renderer == nullptr) {
  82. SDL_DestroyWindow(m_window);
  83. std::cout << "SDL Renderer creation failed : " << SDL_GetError() << std::endl << std::endl;
  84. SDL_Quit();
  85. return false;
  86. }
  87. // End
  88. std::cout << "Done, no error detected." << std::endl;
  89. // Okay
  90. return loadEveryPicture();
  91. }
  92. void Renderer::clearWindow() {
  93. // Clean up buffer
  94. SDL_SetRenderDrawColor(m_renderer, 0x00, 0x00, 0x00, 0x00);
  95. SDL_RenderClear(m_renderer);
  96. }
  97. void Renderer::renderScene(std::vector<Visual *> &scope, const b2Vec2 &center, float zoom) {
  98. // Texture existence
  99. if (m_pictureTab.empty())
  100. return;
  101. // Rect
  102. SDL_Rect dst;
  103. SDL_Texture *tex;
  104. b2Vec2 rel;
  105. float localZoom;
  106. // For each
  107. for (auto it(scope.begin()); it != scope.end(); it++) {
  108. // Skip if no invalid texture
  109. if ((*it)->getImgId() > m_pictureTab.size() || m_pictureTab[(*it)->getImgId()] == nullptr)
  110. tex = m_pictureTab[0];
  111. else
  112. tex = m_pictureTab[(*it)->getImgId()];
  113. // Adjusting local zoom
  114. localZoom = zoom * (*it)->getScale();
  115. // Rect set up
  116. rel = (*it)->getPos() - center;
  117. dst.x = (int) (rel.x * zoom) + m_screenWidth / 2;
  118. dst.y = (int) (rel.y * zoom) + m_screenHeight / 2;
  119. SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h);
  120. // Zoom correction
  121. dst.w = (int) (localZoom * dst.w / DEFAULT_ZOOM);
  122. dst.h = (int) (localZoom * dst.h / DEFAULT_ZOOM);
  123. // Center texture
  124. dst.x -= dst.w / 2;
  125. dst.y -= dst.h / 2;
  126. // SDL rendering
  127. SDL_RenderCopyEx(m_renderer, tex, NULL, &dst, (*it)->getAngle() * RAD_TO_DEG, NULL, SDL_FLIP_NONE);
  128. }
  129. }
  130. void Renderer::renderPlanetHUD(PlanetDef def) {
  131. // Variable
  132. SDL_Rect dst;
  133. // Line under color
  134. const Uint8 uncl(0xaf);
  135. // Render rect
  136. dst.x = 10;
  137. dst.y = 10;
  138. int w = m_screenWidth / 2 - 2*dst.x + 24;
  139. int h = m_screenHeight * 2 / 3 - 2*dst.y;
  140. dst.w = w;
  141. dst.h = h;
  142. SDL_SetRenderDrawColor(m_renderer, 0x66, 0x66, 0x66, 0xff);
  143. SDL_RenderFillRect(m_renderer, &dst);
  144. SDL_SetRenderDrawColor(m_renderer, 0xff, 0xff, 0xff, 0xff);
  145. SDL_RenderDrawRect(m_renderer, &dst);
  146. SDL_RenderDrawLine(m_renderer, dst.x, dst.y + 37, dst.x + dst.w - 1, dst.y + 37);
  147. // Render planet name
  148. dst.x = 11;
  149. dst.y = 11;
  150. renderName(dst, def.name);
  151. // Column
  152. dst.x = 20;
  153. // Jumps
  154. #define H_NEXT_BAR 32
  155. #define H_OFFSET_BAR 10
  156. // People
  157. dst.y = 60;
  158. SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
  159. SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
  160. renderName(dst, "People");
  161. renderBar(dst.y + H_OFFSET_BAR, def.stock.get(PEOPLE));
  162. // Ore
  163. dst.y += H_NEXT_BAR;
  164. SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
  165. SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
  166. renderName(dst, "Ore");
  167. renderBar(dst.y + H_OFFSET_BAR, def.stock.get(ORE));
  168. // Metal
  169. dst.y += H_NEXT_BAR;
  170. SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
  171. SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
  172. renderName(dst, "Metal");
  173. renderBar(dst.y + H_OFFSET_BAR, def.stock.get(METAL));
  174. // Energy
  175. dst.y += H_NEXT_BAR;
  176. SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
  177. SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
  178. renderName(dst, "Energy");
  179. renderBar(dst.y + H_OFFSET_BAR, def.stock.get(ENERGY));
  180. // Nuclear ore
  181. dst.y += H_NEXT_BAR;
  182. SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
  183. SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
  184. renderName(dst, "Nuclear ore");
  185. renderBar(dst.y + H_OFFSET_BAR, def.stock.get(NUCLEAR_ORE));
  186. // Solar panels
  187. dst.y += H_NEXT_BAR;
  188. SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
  189. SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
  190. renderName(dst, "Solar panels");
  191. renderBar(dst.y + H_OFFSET_BAR, def.stock.get(SOLAR_PANELS));
  192. // Radioactivity
  193. dst.y += H_NEXT_BAR;
  194. SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
  195. SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
  196. renderName(dst, "Radioactivity");
  197. renderBar(dst.y + H_OFFSET_BAR, def.stock.get(RADIOACTIVITY));
  198. // Metal industry
  199. dst.y += H_NEXT_BAR;
  200. SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
  201. SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
  202. renderName(dst, "Metal industry");
  203. renderBar(dst.y + H_OFFSET_BAR, def.stock.get(METAL_INDUSTRY));
  204. // Solar industry
  205. dst.y += H_NEXT_BAR;
  206. SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
  207. SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
  208. renderName(dst, "Solar industry");
  209. renderBar(dst.y + H_OFFSET_BAR, def.stock.get(SOLAR_INDUSTRY));
  210. // Nuclear industry
  211. dst.y += H_NEXT_BAR;
  212. SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
  213. SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
  214. renderName(dst, "Nuke industry");
  215. renderBar(dst.y + H_OFFSET_BAR, def.stock.get(NUCLEAR_INDUSTRY));
  216. // Ship industry
  217. dst.y += H_NEXT_BAR;
  218. SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
  219. SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
  220. renderName(dst, "Ship industry");
  221. renderBar(dst.y + H_OFFSET_BAR, def.stock.get(SHIP_INDUSTRY));
  222. // Ship progress
  223. dst.y += H_NEXT_BAR;
  224. SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff);
  225. SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8);
  226. renderName(dst, "Ship progress");
  227. renderBar(dst.y + H_OFFSET_BAR, def.stock.get(SHIP_PROGRESS));
  228. }
  229. void Renderer::renderName(SDL_Rect &dst, std::string name) {
  230. // Seek an existing name texture
  231. auto it(m_stringTab.find(name));
  232. if (it == m_stringTab.end()) {
  233. // Not loaded yet, let's fix this !
  234. if (!loadStringTexture(name))
  235. return;
  236. SDL_QueryTexture(m_stringTab[name], NULL, NULL, &dst.w, &dst.h);
  237. SDL_RenderCopy(m_renderer, m_stringTab[name], NULL, &dst);
  238. }
  239. else {
  240. // Faster plot
  241. SDL_QueryTexture(it->second, NULL, NULL, &dst.w, &dst.h);
  242. SDL_RenderCopy(m_renderer, it->second, NULL, &dst);
  243. }
  244. }
  245. void Renderer::renderBar(int y, const int &value) {
  246. // Set position
  247. SDL_Rect dst;
  248. dst.x = 208;
  249. dst.y = y;
  250. dst.h = 16;
  251. // Set color and scale
  252. if (value == 0) {
  253. SDL_SetRenderDrawColor(m_renderer, 0x00, 0x00, 0x00, 0xff);
  254. dst.w = dst.h;
  255. }
  256. else if (value < 400) {
  257. SDL_SetRenderDrawColor(m_renderer, 0x00, 0xff, 0x00, 0xff);
  258. dst.w = value;
  259. }
  260. else if (value < 4000) {
  261. SDL_SetRenderDrawColor(m_renderer, 0xff, 0xff, 0x00, 0xff);
  262. dst.w = value / 10;
  263. }
  264. else if (value < 400000) {
  265. SDL_SetRenderDrawColor(m_renderer, 0xff, 0xaa, 0x00, 0xff);
  266. dst.w = value / 1000;
  267. }
  268. else if (value < 40000000) {
  269. SDL_SetRenderDrawColor(m_renderer, 0xff, 0x55, 0x00, 0xff);
  270. dst.w = value / 100000;
  271. }
  272. else {
  273. SDL_SetRenderDrawColor(m_renderer, 0xff, 0x00, 0x00, 0xff);
  274. dst.w = value / 10000000;
  275. }
  276. // Draw
  277. SDL_RenderFillRect(m_renderer, &dst);
  278. SDL_SetRenderDrawColor(m_renderer, 0xaf, 0xaf, 0xaf, 0xff);
  279. if (value == 0) {
  280. SDL_RenderDrawLine(m_renderer, dst.x, dst.y, dst.x + dst.w - 1, dst.y + dst.h - 1);
  281. SDL_RenderDrawLine(m_renderer, dst.x, dst.y + dst.h - 1, dst.x + dst.w - 1, dst.y);
  282. } else {
  283. dst.w = 400;
  284. }
  285. SDL_RenderDrawRect(m_renderer, &dst);
  286. }
  287. void Renderer::presentWindow() {
  288. // Activate display
  289. SDL_RenderPresent(m_renderer);
  290. }
  291. bool Renderer::loadPicture(std::string name) {
  292. SDL_Texture *texture = IMG_LoadTexture(m_renderer, name.c_str());
  293. if (texture == nullptr) {
  294. std::cout << "Renderer::loadPicture() > " << SDL_GetError() << std::endl << std::endl;
  295. return false;
  296. }
  297. m_pictureTab.push_back(texture);
  298. return true;
  299. }
  300. bool Renderer::loadStringTexture(std::string name) {
  301. // Render text surface
  302. //SDL_Surface* textSurface = TTF_RenderText_Solid(m_font, name.c_str(), {0, 255, 0, 255});
  303. SDL_Surface* textSurface = TTF_RenderText_Shaded(m_font, name.c_str(), {0x00, 0xff, 0x00, 0xff}, {0x66, 0x66, 0x66, 0xff});
  304. if (textSurface == NULL) {
  305. std::cout << "Renderer::loadStringTexture() [1] > " << TTF_GetError() << std::endl << std::endl;
  306. return false;
  307. }
  308. // Create texture from surface pixels
  309. SDL_Texture* texture(SDL_CreateTextureFromSurface(m_renderer, textSurface));
  310. SDL_FreeSurface(textSurface);
  311. if (texture == NULL) {
  312. std::cout << "Renderer::loadStringTexture() [2] > " << SDL_GetError() << std::endl << std::endl;
  313. return false;
  314. }
  315. m_stringTab[name] = texture;
  316. // All right
  317. return true;
  318. }
  319. bool Renderer::loadEveryPicture() {
  320. bool okay(true);
  321. okay = okay && loadPicture("Pictures/NoPict.png"); // 0
  322. okay = okay && loadPicture("Pictures/Planet1.png"); // 1
  323. okay = okay && loadPicture("Pictures/Planet2.png"); // 2
  324. okay = okay && loadPicture("Pictures/Planet3.png"); // 3
  325. okay = okay && loadPicture("Pictures/Planet4.png"); // 4
  326. okay = okay && loadPicture("Pictures/Planet5.png"); // 5
  327. okay = okay && loadPicture("Pictures/Ship1Gaz.png"); // 6
  328. okay = okay && loadPicture("Pictures/Ship2Ion.png"); // 7
  329. okay = okay && loadPicture("Pictures/Ship3Laser.png"); // 8
  330. okay = okay && loadPicture("Pictures/Ship4AntiMater.png"); // 9
  331. okay = okay && loadPicture("Pictures/Ship5Gravity.png"); // 10
  332. okay = okay && loadPicture("Pictures/Ship6Alcubierre.png"); // 11
  333. okay = okay && loadPicture("Pictures/Ship7Hyperdrive.png"); // 12
  334. okay = okay && loadPicture("Pictures/Sun.png"); // 13
  335. return okay;
  336. }
  337. SDL_Window *Renderer::getWindow() const {
  338. return m_window;
  339. }