Add support for rotated sprites

This commit is contained in:
Matthias Schiffer 2014-09-26 03:08:15 +02:00
parent 8e0395e39c
commit 9b91d6f3d0
4 changed files with 95 additions and 16 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

After

Width:  |  Height:  |  Size: 118 B

View file

@ -59,7 +59,7 @@ MapView::MapView(const std::shared_ptr<Window> &window0, const std::vector<std::
.h = 0, .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_SetSurfaceBlendMode(sprite, SDL_BLENDMODE_NONE);
SDL_BlitSurface(sprite, nullptr, surface, &rect); SDL_BlitSurface(sprite, nullptr, surface, &rect);

View file

@ -26,6 +26,8 @@
#include "SpriteCache.hpp" #include "SpriteCache.hpp"
#include <cstring>
#include <SDL_image.h> #include <SDL_image.h>
@ -33,26 +35,89 @@ namespace RPGEdit {
namespace View { namespace View {
std::unique_ptr<SDL_Surface, SpriteCache::SDL_Surface_deleter> SpriteCache::load(const std::string &name) { SpriteCache::sprite_value SpriteCache::load(const std::string &id) {
std::string filename = "../resources/sprite/" + name + ".png"; std::string filename = "../resources/sprite/" + id + ".png";
SDL_Surface *surface = IMG_Load(filename.c_str()); 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());
} }
SDL_Surface * SpriteCache::get(const std::string &type, const std::string &name) { SpriteCache::sprite_value SpriteCache::load(const std::string &id, unsigned rotation) {
std::string id = type + "/" + name; if (!rotation)
return load(id);
std::unique_ptr<SDL_Surface, SDL_Surface_deleter> &surface = sprites[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());
}
SpriteCache::sprite_value & SpriteCache::get(const std::string &id, unsigned rotation) {
sprite_key key(id, rotation);
sprite_value &surface = sprites[key];
if (!surface) if (!surface)
surface = load(id); surface = load(id, rotation);
if (!surface) if (!surface)
sprites.erase(sprites.find(id)); sprites.erase(sprites.find(key));
return surface.get(); return surface;
}
SDL_Surface * SpriteCache::get(const std::string &type, const std::string &name, unsigned rotation) {
if (rotation >= 4)
return nullptr;
return get(type + "/" + name, rotation).get();
} }

View file

@ -27,6 +27,7 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <string>
#include <unordered_map> #include <unordered_map>
#include <SDL.h> #include <SDL.h>
@ -38,19 +39,32 @@ namespace View {
class SpriteCache { class SpriteCache {
private: private:
class SDL_Surface_deleter { struct SDL_Surface_deleter {
public: void operator()(SDL_Surface *surface) const {
void operator()(SDL_Surface *surface) {
SDL_FreeSurface(surface); 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: 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() { void clear() {
sprites.clear(); sprites.clear();