#include "stdafx.h" #include #include #include #include #include bool _finish = false; SDL_Window *_window; SDL_Renderer *_renderer; static const uint32 FRAME_DELAY = 30; class ImageData { public: ImageData(const std::string &name) { std::string img_path = name + ".png"; this->image = IMG_LoadTexture(_renderer, img_path.c_str()); if (this->image == nullptr) { throw std::string(SDL_GetError()); } std::string mask0_path = name + "_m0.png"; this->masks.emplace_back(IMG_LoadTexture(_renderer, mask0_path.c_str())); if (this->masks[0] == nullptr) { throw std::string(SDL_GetError()); } std::string mask1_path = name + "_m1.png"; this->masks.emplace_back(IMG_LoadTexture(_renderer, mask1_path.c_str())); if (this->masks[1] == nullptr) { throw std::string(SDL_GetError()); } } ~ImageData() { SDL_DestroyTexture(this->image); this->image = nullptr; for (auto &mask : this->masks) { SDL_DestroyTexture(mask); mask = nullptr; } } uint32 flags; ///< Flags of the image. @see ImageFlags uint16 width = 0; ///< Width of the image. uint16 height = 0; ///< Height of the image. int16 xoffset; ///< Horizontal offset of the image. int16 yoffset; ///< Vertical offset of the image. SDL_Texture *image; std::vector masks; }; std::vector> _sprites; /** Returns true when event polling ending event happens */ bool HandleEvent() { SDL_Event event; if (SDL_PollEvent(&event) != 1) return true; switch (event.type) { case SDL_USEREVENT: return true; case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_q: _finish = true; return true; default: break; } return false; case SDL_WINDOWEVENT: default: return false; } } uint8 GetR(uint32 rgba) { return rgba >> 24; } uint8 GetG(uint32 rgba) { return rgba >> 16; } uint8 GetB(uint32 rgba) { return rgba >> 8; } uint8 GetA(uint32 rgba) { return rgba; } void DrawSprite(int x, int y, const std::vector &cols) { auto &imd = _sprites[0]; int w, h; SDL_QueryTexture(imd->image, nullptr, nullptr, &w, &h); SDL_Rect rect = {x, y, w, h}; SDL_RenderCopy(_renderer, imd->image, NULL, &rect); SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_BLEND); for (size_t i = 0; i < imd->masks.size(); i++) { auto &mask = imd->masks[i]; SDL_SetTextureColorMod(mask, GetR(cols[i]), GetG(cols[i]), GetB(cols[i])); SDL_RenderCopy(_renderer, mask, nullptr, &rect); } } void OnNewFrame(uint delay) { (void)delay; DrawSprite(50, 50, {0x0000FF00, 0x00FF0000}); SDL_RenderPresent(_renderer); } void LoadSprite(const std::string &name) { _sprites.emplace_back(new ImageData(name)); } int main() { SDL_CreateWindowAndRenderer(800, 600, SDL_WINDOW_RESIZABLE, &_window, &_renderer); IMG_Init(IMG_INIT_PNG); if (_window == nullptr || _renderer == nullptr) return 1; try { LoadSprite("icecream"); } catch(std::string& ex) { std::cout << ex << std::endl; } SDL_SetRenderDrawColor(_renderer, 0, 0, 0, 255); while(!_finish) { uint start = SDL_GetTicks(); OnNewFrame(FRAME_DELAY); for (;;) { if (HandleEvent()) break; } if (_finish) break; uint now = SDL_GetTicks(); if (now >= start) { now -= start; if (now < FRAME_DELAY) SDL_Delay(FRAME_DELAY - now); // Wait } } }