// // Created by jovian on 18/07/17. // #include #include #include "Renderer.h" #define RAD_TO_DEG 57.2957795130f Renderer::Renderer() : m_screenWidth(0), m_screenHeight(0), m_window(nullptr), m_renderer(nullptr), m_font(nullptr) {} Renderer::~Renderer() { // Destroy textures while (!m_pictureTab.empty()) { if (m_pictureTab.back() != nullptr) SDL_DestroyTexture(m_pictureTab.back()); m_pictureTab.pop_back(); } // Destroy string textures for (auto it(m_stringTab.begin()); it != m_stringTab.end(); it++) { if (it->second != nullptr) SDL_DestroyTexture(it->second); it->second = nullptr; } m_stringTab.clear(); // Destroy SDL renderer if (m_renderer != nullptr) { SDL_DestroyRenderer(m_renderer); m_renderer = nullptr; } // Destroy the beautiful window if (m_window != nullptr) { SDL_DestroyWindow(m_window); m_window = nullptr; } // Quit modules TTF_Quit(); IMG_Quit(); SDL_Quit(); } bool Renderer::initialize() { // Announce std::cout << "Renderer::initialize() > "; // Already initialized if (m_window != nullptr) { std::cout << "Window already created." << std::endl << std::endl; return false; } // Default screen size m_screenWidth = 1200; m_screenHeight = 700; // Init video if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "SDL video failed : " << SDL_GetError() << std::endl << std::endl; return false; } // Init font if (TTF_Init() == -1) { std::cout << "TTF failed : " << TTF_GetError() << std::endl << std::endl; return false; } m_font = TTF_OpenFont("droid.ttf", 28); if (m_font == NULL) { std::cout << "Open droid.ttf failed : " << TTF_GetError() << std::endl << std::endl; return false; } // Opening window m_window = SDL_CreateWindow("SpaceExpansion", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_screenWidth, m_screenHeight, SDL_WINDOW_SHOWN /*| SDL_WINDOW_FULLSCREEN_DESKTOP*/); if (m_window == nullptr) { std::cout << "Window creation failed : " << SDL_GetError() << std::endl << std::endl; SDL_Quit(); return false; } // Hardware physical screen size SDL_GetWindowSize(m_window, &m_screenWidth, &m_screenHeight); // Create renderer m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (m_renderer == nullptr) { SDL_DestroyWindow(m_window); std::cout << "SDL Renderer creation failed : " << SDL_GetError() << std::endl << std::endl; SDL_Quit(); return false; } // End std::cout << "Done, no error detected." << std::endl; // Okay return loadEveryPicture(); } void Renderer::clearWindow() { // Clean up buffer SDL_SetRenderDrawColor(m_renderer, 0x00, 0x00, 0x00, 0x00); SDL_RenderClear(m_renderer); } void Renderer::renderScene(std::vector &scope, const b2Vec2 ¢er, float zoom) { // Texture existence if (m_pictureTab.empty()) return; // Rect SDL_Rect dst; SDL_Texture *tex; b2Vec2 rel; float localZoom; // For each for (auto it(scope.begin()); it != scope.end(); it++) { // Skip if no invalid texture if ((*it)->getImgId() > m_pictureTab.size() || m_pictureTab[(*it)->getImgId()] == nullptr) tex = m_pictureTab[0]; else tex = m_pictureTab[(*it)->getImgId()]; // Adjusting local zoom localZoom = zoom * (*it)->getScale(); // Rect set up rel = (*it)->getPos() - center; dst.x = (int) (rel.x * zoom) + m_screenWidth / 2; dst.y = (int) (rel.y * zoom) + m_screenHeight / 2; SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h); // Zoom correction dst.w = (int) (localZoom * dst.w / DEFAULT_ZOOM); dst.h = (int) (localZoom * dst.h / DEFAULT_ZOOM); // Center texture dst.x -= dst.w / 2; dst.y -= dst.h / 2; // SDL rendering SDL_RenderCopyEx(m_renderer, tex, NULL, &dst, (*it)->getAngle() * RAD_TO_DEG, NULL, SDL_FLIP_NONE); } } void Renderer::renderPlanetHUD(PlanetDef def) { // Variable SDL_Rect dst; // Line under color const Uint8 uncl(0xaf); // Render rect dst.x = 10; dst.y = 10; int w = m_screenWidth / 2 - 2*dst.x + 24; int h = m_screenHeight * 2 / 3 - 2*dst.y; dst.w = w; dst.h = h; SDL_SetRenderDrawColor(m_renderer, 0x66, 0x66, 0x66, 0xff); SDL_RenderFillRect(m_renderer, &dst); SDL_SetRenderDrawColor(m_renderer, 0xff, 0xff, 0xff, 0xff); SDL_RenderDrawRect(m_renderer, &dst); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + 37, dst.x + dst.w - 1, dst.y + 37); // Render planet name dst.x = 11; dst.y = 11; renderName(dst, def.name); // Column dst.x = 20; // Jumps #define H_NEXT_BAR 32 #define H_OFFSET_BAR 10 // People dst.y = 60; SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8); renderName(dst, "People"); renderBar(dst.y + H_OFFSET_BAR, def.stock.get(PEOPLE)); // Ore dst.y += H_NEXT_BAR; SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8); renderName(dst, "Ore"); renderBar(dst.y + H_OFFSET_BAR, def.stock.get(ORE)); // Metal dst.y += H_NEXT_BAR; SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8); renderName(dst, "Metal"); renderBar(dst.y + H_OFFSET_BAR, def.stock.get(METAL)); // Energy dst.y += H_NEXT_BAR; SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8); renderName(dst, "Energy"); renderBar(dst.y + H_OFFSET_BAR, def.stock.get(ENERGY)); // Nuclear ore dst.y += H_NEXT_BAR; SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8); renderName(dst, "Nuclear ore"); renderBar(dst.y + H_OFFSET_BAR, def.stock.get(NUCLEAR_ORE)); // Solar panels dst.y += H_NEXT_BAR; SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8); renderName(dst, "Solar panels"); renderBar(dst.y + H_OFFSET_BAR, def.stock.get(SOLAR_PANELS)); // Radioactivity dst.y += H_NEXT_BAR; SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8); renderName(dst, "Radioactivity"); renderBar(dst.y + H_OFFSET_BAR, def.stock.get(RADIOACTIVITY)); // Metal industry dst.y += H_NEXT_BAR; SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8); renderName(dst, "Metal industry"); renderBar(dst.y + H_OFFSET_BAR, def.stock.get(METAL_INDUSTRY)); // Solar industry dst.y += H_NEXT_BAR; SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8); renderName(dst, "Solar industry"); renderBar(dst.y + H_OFFSET_BAR, def.stock.get(SOLAR_INDUSTRY)); // Nuclear industry dst.y += H_NEXT_BAR; SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8); renderName(dst, "Nuke industry"); renderBar(dst.y + H_OFFSET_BAR, def.stock.get(NUCLEAR_INDUSTRY)); // Ship industry dst.y += H_NEXT_BAR; SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8); renderName(dst, "Ship industry"); renderBar(dst.y + H_OFFSET_BAR, def.stock.get(SHIP_INDUSTRY)); // Ship progress dst.y += H_NEXT_BAR; SDL_SetRenderDrawColor(m_renderer, uncl, uncl, uncl, 0xff); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + H_OFFSET_BAR + 8, dst.x + w - 12, dst.y + H_OFFSET_BAR + 8); renderName(dst, "Ship progress"); renderBar(dst.y + H_OFFSET_BAR, def.stock.get(SHIP_PROGRESS)); } void Renderer::renderName(SDL_Rect &dst, std::string name) { // Seek an existing name texture auto it(m_stringTab.find(name)); if (it == m_stringTab.end()) { // Not loaded yet, let's fix this ! if (!loadStringTexture(name)) return; SDL_QueryTexture(m_stringTab[name], NULL, NULL, &dst.w, &dst.h); SDL_RenderCopy(m_renderer, m_stringTab[name], NULL, &dst); } else { // Faster plot SDL_QueryTexture(it->second, NULL, NULL, &dst.w, &dst.h); SDL_RenderCopy(m_renderer, it->second, NULL, &dst); } } void Renderer::renderBar(int y, const int &value) { // Set position SDL_Rect dst; dst.x = 208; dst.y = y; dst.h = 16; // Set color and scale if (value == 0) { SDL_SetRenderDrawColor(m_renderer, 0x00, 0x00, 0x00, 0xff); dst.w = dst.h; } else if (value < 400) { SDL_SetRenderDrawColor(m_renderer, 0x00, 0xff, 0x00, 0xff); dst.w = value; } else if (value < 4000) { SDL_SetRenderDrawColor(m_renderer, 0xff, 0xff, 0x00, 0xff); dst.w = value / 10; } else if (value < 400000) { SDL_SetRenderDrawColor(m_renderer, 0xff, 0xaa, 0x00, 0xff); dst.w = value / 1000; } else if (value < 40000000) { SDL_SetRenderDrawColor(m_renderer, 0xff, 0x55, 0x00, 0xff); dst.w = value / 100000; } else { SDL_SetRenderDrawColor(m_renderer, 0xff, 0x00, 0x00, 0xff); dst.w = value / 10000000; } // Draw SDL_RenderFillRect(m_renderer, &dst); SDL_SetRenderDrawColor(m_renderer, 0xaf, 0xaf, 0xaf, 0xff); if (value == 0) { SDL_RenderDrawLine(m_renderer, dst.x, dst.y, dst.x + dst.w - 1, dst.y + dst.h - 1); SDL_RenderDrawLine(m_renderer, dst.x, dst.y + dst.h - 1, dst.x + dst.w - 1, dst.y); } else { dst.w = 400; } SDL_RenderDrawRect(m_renderer, &dst); } void Renderer::presentWindow() { // Activate display SDL_RenderPresent(m_renderer); } bool Renderer::loadPicture(std::string name) { SDL_Texture *texture = IMG_LoadTexture(m_renderer, name.c_str()); if (texture == nullptr) { std::cout << "Renderer::loadPicture() > " << SDL_GetError() << std::endl << std::endl; return false; } m_pictureTab.push_back(texture); return true; } bool Renderer::loadStringTexture(std::string name) { // Render text surface //SDL_Surface* textSurface = TTF_RenderText_Solid(m_font, name.c_str(), {0, 255, 0, 255}); SDL_Surface* textSurface = TTF_RenderText_Shaded(m_font, name.c_str(), {0x00, 0xff, 0x00, 0xff}, {0x66, 0x66, 0x66, 0xff}); if (textSurface == NULL) { std::cout << "Renderer::loadStringTexture() [1] > " << TTF_GetError() << std::endl << std::endl; return false; } // Create texture from surface pixels SDL_Texture* texture(SDL_CreateTextureFromSurface(m_renderer, textSurface)); SDL_FreeSurface(textSurface); if (texture == NULL) { std::cout << "Renderer::loadStringTexture() [2] > " << SDL_GetError() << std::endl << std::endl; return false; } m_stringTab[name] = texture; // All right return true; } bool Renderer::loadEveryPicture() { bool okay(true); okay = okay && loadPicture("Pictures/NoPict.png"); // 0 okay = okay && loadPicture("Pictures/Planet1.png"); // 1 okay = okay && loadPicture("Pictures/Planet2.png"); // 2 okay = okay && loadPicture("Pictures/Planet3.png"); // 3 okay = okay && loadPicture("Pictures/Planet4.png"); // 4 okay = okay && loadPicture("Pictures/Planet5.png"); // 5 okay = okay && loadPicture("Pictures/Ship1Gaz.png"); // 6 okay = okay && loadPicture("Pictures/Ship2Ion.png"); // 7 okay = okay && loadPicture("Pictures/Ship3Laser.png"); // 8 okay = okay && loadPicture("Pictures/Ship4AntiMater.png"); // 9 okay = okay && loadPicture("Pictures/Ship5Gravity.png"); // 10 okay = okay && loadPicture("Pictures/Ship6Alcubierre.png"); // 11 okay = okay && loadPicture("Pictures/Ship7Hyperdrive.png"); // 12 okay = okay && loadPicture("Pictures/Sun.png"); // 13 return okay; } SDL_Window *Renderer::getWindow() const { return m_window; }