From 9b91d6f3d0187e0daf29a262cf19ad08ba2b7cf5 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 26 Sep 2014 03:08:15 +0200 Subject: Add support for rotated sprites --- resources/sprite/tile/horizontal_bar.png | Bin 118 -> 118 bytes src/view/MapView.cpp | 2 +- src/view/SpriteCache.cpp | 83 +++++++++++++++++++++++++++---- src/view/SpriteCache.hpp | 26 +++++++--- 4 files changed, 95 insertions(+), 16 deletions(-) diff --git a/resources/sprite/tile/horizontal_bar.png b/resources/sprite/tile/horizontal_bar.png index 08f99de..c666b08 100644 Binary files a/resources/sprite/tile/horizontal_bar.png and b/resources/sprite/tile/horizontal_bar.png differ diff --git a/src/view/MapView.cpp b/src/view/MapView.cpp index d8a69d5..c1c0639 100644 --- a/src/view/MapView.cpp +++ b/src/view/MapView.cpp @@ -59,7 +59,7 @@ MapView::MapView(const std::shared_ptr &window0, const std::vectorget("tile", tileset[i]); + SDL_Surface *sprite = spriteCache->get("tile", tileset[i], 0); SDL_SetSurfaceBlendMode(sprite, SDL_BLENDMODE_NONE); SDL_BlitSurface(sprite, nullptr, surface, &rect); diff --git a/src/view/SpriteCache.cpp b/src/view/SpriteCache.cpp index 82f669f..bd67346 100644 --- a/src/view/SpriteCache.cpp +++ b/src/view/SpriteCache.cpp @@ -26,6 +26,8 @@ #include "SpriteCache.hpp" +#include + #include @@ -33,26 +35,89 @@ namespace RPGEdit { namespace View { -std::unique_ptr SpriteCache::load(const std::string &name) { - std::string filename = "../resources/sprite/" + name + ".png"; +SpriteCache::sprite_value SpriteCache::load(const std::string &id) { + std::string filename = "../resources/sprite/" + id + ".png"; SDL_Surface *surface = IMG_Load(filename.c_str()); - return std::unique_ptr(surface, SDL_Surface_deleter()); + return sprite_value(surface, SDL_Surface_deleter()); +} + +SpriteCache::sprite_value SpriteCache::load(const std::string &id, unsigned rotation) { + if (!rotation) + return load(id); + + sprite_value &base = get(id, 0); + SDL_Surface *surface; + + SDL_LockSurface(base.get()); + + int w = base->w, h = base->h, d = base->format->BytesPerPixel, w2, h2; + + if (rotation == 2) { + w2 = w; + h2 = h; + } + else { + w2 = h; + h2 = w; + } + + surface = SDL_CreateRGBSurface(0, w2, h2, base->format->BitsPerPixel, + base->format->Rmask, base->format->Gmask, base->format->Bmask, base->format->Amask); + + SDL_LockSurface(surface); + + uint8_t *src = reinterpret_cast(base->pixels); + uint8_t *dst = reinterpret_cast(surface->pixels); + + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + int x2, y2; + + switch (rotation) { + case 1: + x2 = y; + y2 = w - x - 1; + break; + case 2: + x2 = w - x - 1; + y2 = h - y - 1; + break; + case 3: + x2 = h - y - 1; + y2 = x; + } + + std::memcpy(dst + d * (y2*w2 + x2), src + d * (y*w + x), d); + } + } + + SDL_UnlockSurface(surface); + SDL_UnlockSurface(base.get()); + + return sprite_value(surface, SDL_Surface_deleter()); } -SDL_Surface * SpriteCache::get(const std::string &type, const std::string &name) { - std::string id = type + "/" + name; +SpriteCache::sprite_value & SpriteCache::get(const std::string &id, unsigned rotation) { + sprite_key key(id, rotation); - std::unique_ptr &surface = sprites[id]; + sprite_value &surface = sprites[key]; if (!surface) - surface = load(id); + surface = load(id, rotation); if (!surface) - sprites.erase(sprites.find(id)); + sprites.erase(sprites.find(key)); + + return surface; +} + +SDL_Surface * SpriteCache::get(const std::string &type, const std::string &name, unsigned rotation) { + if (rotation >= 4) + return nullptr; - return surface.get(); + return get(type + "/" + name, rotation).get(); } diff --git a/src/view/SpriteCache.hpp b/src/view/SpriteCache.hpp index c08ba6f..ae01887 100644 --- a/src/view/SpriteCache.hpp +++ b/src/view/SpriteCache.hpp @@ -27,6 +27,7 @@ #pragma once #include +#include #include #include @@ -38,19 +39,32 @@ namespace View { class SpriteCache { private: - class SDL_Surface_deleter { - public: - void operator()(SDL_Surface *surface) { + struct SDL_Surface_deleter { + void operator()(SDL_Surface *surface) const { SDL_FreeSurface(surface); } }; - std::unordered_map> sprites; + typedef std::pair sprite_key; + typedef std::unique_ptr sprite_value; - std::unique_ptr load(const std::string &name); + struct sprite_key_hash { + size_t operator()(const sprite_key &k) const { + std::hash string_hash; + std::hash int_hash; + + return string_hash(k.first) ^ int_hash(k.second); + } + }; + + std::unordered_map sprites; + + sprite_value load(const std::string &id); + sprite_value load(const std::string &id, unsigned rotation); + sprite_value & get(const std::string &id, unsigned rotation); public: - SDL_Surface * get(const std::string &type, const std::string &name); + SDL_Surface * get(const std::string &type, const std::string &name, unsigned rotation = 0); void clear() { sprites.clear(); -- cgit v1.2.3