/* * 2D Physic Engine * graphics.cpp: utilities to display stuff. * Based on pikuma.com Learn Game Physics Engine Programming course. * Copyright (c) 2022 986-Studio. All rights reserved. * * Created by Manoƫl Trapier on 07/06/2022. */ #include #include #include #include #include #include #include #include #include #include SDL_Window* graphics::window = nullptr; SDL_Renderer* graphics::renderer = nullptr; int graphics::windowWidth = 0; int graphics::windowHeight = 0; TTF_Font *graphics::font = nullptr; bool graphics::openWindow() { if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { logger::critical("Error initializing SDL: %s", SDL_GetError()); return false; } if (TTF_Init()) { logger::critical("SDL_ttf Initialisation error: %s", SDL_GetError()); return false; } SDL_DisplayMode display_mode; SDL_GetCurrentDisplayMode(0, &display_mode); graphics::windowWidth = display_mode.w; graphics::windowHeight = display_mode.h; graphics::window = SDL_CreateWindow(nullptr, 0, 0, windowWidth, windowHeight, SDL_WINDOW_BORDERLESS); if (!graphics::window) { logger::critical("Error creating SDL window: %s", SDL_GetError()); return false; } graphics::renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (!graphics::renderer) { logger::critical("Error creating SDL renderer: %s", SDL_GetError()); return false; } graphics::font = TTF_OpenFont("assets/pico8.ttf", 8); if (graphics::font == nullptr) { logger::critical("Cannot open the font for printing...: %s", SDL_GetError()); return false; } SDL_SetWindowFullscreen(graphics::window, SDL_WINDOW_FULLSCREEN); ImGui::CreateContext(); ImGuiSDL::Initialize(graphics::renderer, graphics::windowWidth, graphics::windowHeight); return true; } void graphics::closeWindow() { SDL_DestroyRenderer(graphics::renderer); SDL_DestroyWindow(graphics::window); SDL_Quit(); } SDL_Texture *graphics::loadTexture(const char *filename) { SDL_Surface *surface = IMG_Load(filename); if (!surface) { logger::error("Error opening texture file '%s'!", filename); return nullptr; } SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface); SDL_FreeSurface(surface); logger::info("Loaded texture %s", filename); return texture; } void graphics::renderFrame() { SDL_RenderPresent(graphics::renderer); } void graphics::clearScreen(uint32_t color) { SDL_SetRenderDrawColor(graphics::renderer, color >> 16, color >> 8, color, 255); SDL_RenderClear(graphics::renderer); } void graphics::draw::line(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint32_t color) { lineColor(graphics::renderer, x0, y0, x1, y1, color); } void graphics::draw::circle(int16_t x, int16_t y, int16_t radius, double angle, uint32_t color) { circleColor(graphics::renderer, x, y, radius, color); lineColor(graphics::renderer, x, y, floor(x + cos(angle) * radius), floor(y + sin(angle) * radius), color); } void graphics::draw::fillCircle(int16_t x, int16_t y, int16_t radius, uint32_t color) { filledCircleColor(graphics::renderer, x, y, radius, color); } void graphics::draw::rect(int16_t x, int16_t y, int16_t width, int16_t height, uint32_t color) { lineColor(graphics::renderer, floor(x - width / 2.0), floor(y - height / 2.0), floor(x + width / 2.0), floor(y - height / 2.0), color); lineColor(graphics::renderer, floor(x + width / 2.0), floor(y - height / 2.0), floor(x + width / 2.0), floor(y + height / 2.0), color); lineColor(graphics::renderer, floor(x + width / 2.0), floor(y + height / 2.0), floor(x - width / 2.0), floor(y + height / 2.0), color); lineColor(graphics::renderer, floor(x - width / 2.0), floor(y + height / 2.0), floor(x - width / 2.0), floor(y - height / 2.0), color); } void graphics::draw::fillRect(int16_t x, int16_t y, int16_t width, int16_t height, uint32_t color) { boxColor(graphics::renderer, floor(x - width / 2.0), floor(y - height / 2.0), floor(x + width / 2.0), floor(y + height / 2.0), color); } void graphics::draw::polygon(int16_t x, int16_t y, const std::vector &vertices, uint32_t color) { for (uint32_t i = 0; i < vertices.size(); i++) { uint32_t currIndex = i; uint32_t nextIndex = (i + 1) % vertices.size(); lineColor(graphics::renderer, floor(vertices[currIndex].x), floor(vertices[currIndex].y), floor(vertices[nextIndex].x), floor(vertices[nextIndex].y), color); } filledCircleColor(graphics::renderer, x, y, 1, color); } void graphics::draw::fillPolygon(int16_t x, int16_t y, const std::vector &vertices, uint32_t color) { std::vector vx; std::vector vy; for (const auto & vertice : vertices) { vx.push_back(static_cast(vertice.x)); } for (const auto & vertice : vertices) { vy.push_back(static_cast(vertice.y)); } filledPolygonColor(graphics::renderer, &vx[0], &vy[0], vertices.size(), color); filledCircleColor(graphics::renderer, x, y, 1, 0xFF000000); } void graphics::draw::texture(int16_t x, int16_t y, int16_t width, int16_t height, double rotation, SDL_Texture *texture) { SDL_Rect dstRect = {x - (width / 2), y - (height / 2), width, height}; double rotationDeg = rotation * 57.2958; SDL_RenderCopyEx(graphics::renderer, texture, nullptr, &dstRect, rotationDeg, nullptr, SDL_FLIP_NONE); } void graphics::draw::text(int16_t x, int16_t y, uint32_t colour, const char *format, ...) { va_list va; uint8_t r = ((colour >> 16) & 0xFF); uint8_t g = ((colour >> 8) & 0xFF); uint8_t b = ((colour ) & 0xFF); SDL_Color c = { r, g, b , 255}; char buffer[512]; va_start(va, format); vsnprintf(buffer, 512, format, va); va_end(va); SDL_Surface *surface = TTF_RenderText_Blended(font, buffer, c); SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface); int labelWidth, labelHeight; SDL_QueryTexture(texture, nullptr, nullptr, &labelWidth, &labelHeight); SDL_Rect destRect = { x, y, labelWidth, labelHeight }; SDL_RenderCopyEx(renderer, texture, nullptr, &destRect,0, nullptr, SDL_FLIP_NONE); SDL_FreeSurface(surface); SDL_DestroyTexture(texture); }