summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/view/MapView.cpp2
-rw-r--r--src/view/SpriteCache.cpp83
-rw-r--r--src/view/SpriteCache.hpp26
3 files changed, 95 insertions, 16 deletions
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<Window> &window0, const std::vector<std::
.h = 0,
};
- SDL_Surface *sprite = spriteCache->get("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 <cstring>
+
#include <SDL_image.h>
@@ -33,26 +35,89 @@ namespace RPGEdit {
namespace View {
-std::unique_ptr<SDL_Surface, SpriteCache::SDL_Surface_deleter> 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<SDL_Surface, SDL_Surface_deleter>(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<uint8_t *>(base->pixels);
+ uint8_t *dst = reinterpret_cast<uint8_t *>(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<SDL_Surface, SDL_Surface_deleter> &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 <memory>
+#include <string>
#include <unordered_map>
#include <SDL.h>
@@ -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<std::string, std::unique_ptr<SDL_Surface, SDL_Surface_deleter>> sprites;
+ typedef std::pair<std::string, int> sprite_key;
+ typedef std::unique_ptr<SDL_Surface, SDL_Surface_deleter> sprite_value;
- std::unique_ptr<SDL_Surface, SDL_Surface_deleter> load(const std::string &name);
+ struct sprite_key_hash {
+ size_t operator()(const sprite_key &k) const {
+ std::hash<std::string> string_hash;
+ std::hash<int> int_hash;
+
+ return string_hash(k.first) ^ int_hash(k.second);
+ }
+ };
+
+ std::unordered_map<sprite_key, sprite_value, sprite_key_hash> 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();