#include"window.hpp" #include"SDL.h" #include"SDL_ttf.h" #include<iostream> #include<vector> #include<cstdlib> #include<ctime> namespace game { struct SDL_RenderObject : public RenderObject { SDL_Window *window = NULL; SDL_Renderer *ren = NULL; std::vector<SDL_Surface *> surfaces; std::vector<TTF_Font *> fonts; SDL_Texture *tex = NULL; SDL_Surface *surface = NULL; int width = 0, height = 0; ~SDL_RenderObject() { release_images(); TTF_Quit(); SDL_Quit(); } void release_images() { for(std::size_t i = 0; i < surfaces.size(); ++i) { SDL_FreeSurface(surfaces[i]); std::cout << "released image index: [" << i << "]\n"; } if(!surfaces.empty()) surfaces.erase(surfaces.begin(), surfaces.end()); for(std::size_t i = 0; i< fonts.size(); ++i) { TTF_CloseFont(fonts[i]); std::cout << "released font index: [" << i << "]\n"; } if(!fonts.empty()) fonts.erase(fonts.begin(), fonts.end()); } void drawAt(Image image, int x, int y) override { SDL_Rect rc = { x, y, surfaces[image]->w, surfaces[image]->h }; SDL_BlitSurface(surfaces[image], 0, surface, &rc); } void drawAtRect(Image image, int x, int y, int w, int h) override { SDL_Rect rc = { x, y, w, h }; SDL_BlitSurface(surfaces[image], 0, surface, &rc); } void drawAtRect(Image image, int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) override { SDL_Rect rc = { x1, y1, w1, h1 }; SDL_Rect rc2 = { x2, y2, w2, h2 }; SDL_BlitSurface(surfaces[image], &rc, surface, &rc2); } void printText(Font font, int x, int y, const std::string &text, const Color &col) override { SDL_Color col_s = { col.r, col.g, col.b, 255 }; SDL_Surface *surf = TTF_RenderText_Solid(fonts[font], text.c_str(), col_s); SDL_Rect rc = { x, y, surf->w, surf->h }; SDL_BlitSurface(surf, 0, surface, &rc); SDL_FreeSurface(surf); } Font loadImage(const std::string &text) override { SDL_Surface *surface = SDL_LoadBMP(text.c_str()); if(!surface) { std::cerr << "Error could not load surface: " << text << "\n"; SDL_Quit(); exit(EXIT_FAILURE); } surfaces.push_back(surface); int index = surfaces.size()-1; std::cout << "loaded image [" << text << "] at index: [" << index << "]\n"; return index; } void setImageColorKey(Image image, const Color &c) override { SDL_SetColorKey(surfaces[image], SDL_TRUE, SDL_MapRGB(surfaces[image]->format, c.r, c.g, c.b)); } Image loadFont(const std::string &text, int size) override { TTF_Font *font = TTF_OpenFont(text.c_str(), size); if(!font) { std::cerr << "Error could not load font: " << text << "\n" << SDL_GetError() << "\n"; TTF_Quit(); SDL_Quit(); exit(EXIT_FAILURE); } fonts.push_back(font); int index = fonts.size()-1; std::cout << "loaded font [" << text << "] at index: [" << index << "]\n"; return index; } void update() { } bool init(const std::string &text, int w, int h) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { std::cerr << "Error initaliziing SDL\n"; return false; } TTF_Init(); window = SDL_CreateWindow(text.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, SDL_WINDOW_SHOWN); if(!window) { std::cerr << "Error creating window: " << SDL_GetError() << "...\n"; TTF_Quit(); SDL_Quit(); return false; } ren = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if(!ren) { std::cerr << "Error creating Renderer: " << SDL_GetError() << "\n"; TTF_Quit(); SDL_Quit(); return false; } tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 1280, 720); if(!tex) { std::cerr << "Could not create texture: " << SDL_GetError() << "\n"; TTF_Quit(); SDL_Quit(); return false; } surface = SDL_CreateRGBSurfaceFrom(NULL, 1280, 720, 32, w*4, 0x00FF0000, 0x0000FF00,0x000000FF,0xFF000000); if(!surface) { std::cerr << "Could not create main surface: " << SDL_GetError() << "\n"; TTF_Quit(); SDL_Quit(); return false; } width = w; height = h; srand(static_cast<unsigned int>(time(0))); return true; } unsigned int getTicks() override { return static_cast<unsigned int>(SDL_GetTicks()); } bool keyDown(const Key &c) override { const Uint8 *keys = SDL_GetKeyboardState(0); switch(c) { case Key::KEY_LEFT: if(keys[SDL_SCANCODE_LEFT]) return true; break; case Key::KEY_RIGHT: if(keys[SDL_SCANCODE_RIGHT]) return true; break; case Key::KEY_UP: if(keys[SDL_SCANCODE_UP]) return true; break; case Key::KEY_DOWN: if(keys[SDL_SCANCODE_DOWN]) return true; break; default: return false; } return false; } }; bool Window::active; GameObject *Window::current_object = nullptr; SDL_RenderObject render_object; bool Window::createWindow(const std::string &text, int w, int h) { return render_object.init(text, w, h); } void Window::setObject(GameObject *obj) { Window::current_object = obj; } void Window::init_object(GameObject *obj) { obj->init(&render_object); } int Window::loop() { if(current_object == nullptr) { std::cerr << "Error must initalize a game object.\n"; return EXIT_FAILURE; } SDL_Event e; active = true; while (active) { SDL_RenderClear(render_object.ren); SDL_LockTexture(render_object.tex, 0, &render_object.surface->pixels, &render_object.surface->pitch); current_object->draw(&render_object); SDL_UnlockTexture(render_object.tex); SDL_Rect rc = { 0, 0, render_object.width, render_object.height }; SDL_RenderCopy(render_object.ren, render_object.tex, 0, &rc); SDL_RenderPresent(render_object.ren); while(SDL_PollEvent(&e)) { switch(e.type) { case SDL_QUIT: active = false; break; case SDL_KEYDOWN: if(e.key.keysym.sym == SDLK_ESCAPE) active = false; current_object->keydown(e.key.keysym.sym); break; case SDL_KEYUP: current_object->keyup(e.key.keysym.sym); break; } } } return EXIT_SUCCESS; } }