// // 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_border(1) {} Renderer::~Renderer() { // Destroy textures while (!m_pictureTab.empty()) { if (m_pictureTab.back() != nullptr) SDL_DestroyTexture(m_pictureTab.back()); m_pictureTab.pop_back(); } // 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; } } bool Renderer::initialize(int nbPlayers) { // 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; } // Opening window m_window = SDL_CreateWindow("< TinyShooter >", 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; } // Split-screen locateViews(nbPlayers); // 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, int which) { // Rect SDL_Rect dst; SDL_Texture *tex; b2Vec2 rel; // View port (useful with split-screen) if (which < 0 || which > 3) return; SDL_RenderSetViewport(m_renderer, &m_viewPort[which]); SDL_SetRenderDrawColor(m_renderer, 0x01, 0x00, 0x11, 0xFF); dst.x = 0; dst.y = 0; dst.w = m_viewPort[which].w; dst.h = m_viewPort[which].h; SDL_RenderFillRect(m_renderer, &dst); // For each for (auto it(scope.begin()); it != scope.end(); it++) { // Skip if invalid texture if ((*it)->getImgId() > m_pictureTab.size() || m_pictureTab[(*it)->getImgId()] == nullptr) continue; tex = m_pictureTab[(*it)->getImgId()]; // Rect set up rel = (*it)->getPos() - center; dst.x = (int) (rel.x * zoom) + m_viewPort[which].w / 2; dst.y = (int) (rel.y * zoom) + m_viewPort[which].h / 2; SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h); // Zoom correction dst.w = (int) (zoom * dst.w / DEFAULT_ZOOM); dst.h = (int) (zoom * 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::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::loadEveryPicture() { bool okay(true); okay = okay && loadPicture("Pictures/NoPict.png"); // 0 okay = okay && loadPicture("Pictures/Ally.png"); // 1 okay = okay && loadPicture("Pictures/TinyWall1.png"); // 2 okay = okay && loadPicture("Pictures/TinyWall2.png"); // 3 okay = okay && loadPicture("Pictures/TinyWall3.png"); // 4 okay = okay && loadPicture("Pictures/TinyWall4.png"); // 5 okay = okay && loadPicture("Pictures/HighWall1.png"); // 6 okay = okay && loadPicture("Pictures/HighWall2.png"); // 7 okay = okay && loadPicture("Pictures/HighWall3.png"); // 8 okay = okay && loadPicture("Pictures/HighWall4.png"); // 9 okay = okay && loadPicture("Pictures/RedVisor.png"); // 10 okay = okay && loadPicture("Pictures/RedArrow.png"); // 11 okay = okay && loadPicture("Pictures/Bullet1.png"); // 12 okay = okay && loadPicture("Pictures/Foe.png"); // 13 okay = okay && loadPicture("Pictures/Bullet2.png"); // 14 okay = okay && loadPicture("Pictures/LifeBar1.png"); // 15 okay = okay && loadPicture("Pictures/LifeBar2.png"); // 16 okay = okay && loadPicture("Pictures/LifeBar3.png"); // 17 okay = okay && loadPicture("Pictures/LifeBar4.png"); // 18 okay = okay && loadPicture("Pictures/LifeBar5.png"); // 19 okay = okay && loadPicture("Pictures/LifeBar6.png"); // 20 okay = okay && loadPicture("Pictures/WideWall1.png"); // 21 okay = okay && loadPicture("Pictures/WideWall2.png"); // 22 okay = okay && loadPicture("Pictures/WideWall3.png"); // 23 okay = okay && loadPicture("Pictures/WideWall4.png"); // 24 okay = okay && loadPicture("Pictures/BigWall1.png"); // 25 okay = okay && loadPicture("Pictures/BigWall2.png"); // 26 okay = okay && loadPicture("Pictures/BigWall3.png"); // 27 okay = okay && loadPicture("Pictures/BigWall4.png"); // 28 return okay; } SDL_Window *Renderer::getWindow() const { return m_window; } void Renderer::locateViews(int nbPlayers) { switch (nbPlayers) { default: // One player // First and single screen m_viewPort[0].x = 0; m_viewPort[0].y = 0; m_viewPort[0].w = m_screenWidth; m_viewPort[0].h = m_screenHeight; break; case 2: // Two players // First screen m_viewPort[0].x = 0; m_viewPort[0].y = 0; m_viewPort[0].w = m_screenWidth / 2 - m_border; m_viewPort[0].h = m_screenHeight; // Second screen m_viewPort[1].x = m_screenWidth / 2 + m_border; m_viewPort[1].y = 0; m_viewPort[1].w = m_screenWidth / 2; m_viewPort[1].h = m_screenHeight; break; case 3: // Three players // First screen m_viewPort[0].x = 0; m_viewPort[0].y = 0; m_viewPort[0].w = m_screenWidth / 2 - m_border; m_viewPort[0].h = m_screenHeight / 2; // Second screen m_viewPort[1].x = m_screenWidth / 2 + m_border; m_viewPort[1].y = 0; m_viewPort[1].w = m_screenWidth / 2; m_viewPort[1].h = m_screenHeight / 2; // Third screen m_viewPort[2].x = m_screenWidth / 4; m_viewPort[2].y = m_screenHeight / 2 + m_border; m_viewPort[2].w = m_screenWidth / 2; m_viewPort[2].h = m_screenHeight / 2; break; case 4: // Four players // First screen m_viewPort[0].x = 0; m_viewPort[0].y = 0; m_viewPort[0].w = m_screenWidth / 2 - m_border; m_viewPort[0].h = m_screenHeight / 2; // Second screen m_viewPort[1].x = m_screenWidth / 2 + m_border; m_viewPort[1].y = 0; m_viewPort[1].w = m_screenWidth / 2; m_viewPort[1].h = m_screenHeight / 2; // Third screen m_viewPort[2].x = 0; m_viewPort[2].y = m_screenHeight / 2; m_viewPort[2].w = m_screenWidth / 2 - m_border; m_viewPort[2].h = m_screenHeight / 2; // Fourth screen m_viewPort[3].x = m_screenWidth / 2 + m_border; m_viewPort[3].y = m_screenHeight / 2; m_viewPort[3].w = m_screenWidth / 2; m_viewPort[3].h = m_screenHeight / 2; break; } } b2Vec2 Renderer::computeDiago(float zoom, int which) { // Test limits if (which < 0 || which > 3) return b2Vec2_zero; // Compute with view-port dims and zoom b2Vec2 rep; rep.x = m_viewPort[which].w / 2; rep.x /= zoom; rep.y = m_viewPort[which].h / 2; rep.y /= zoom; return rep; }