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,
};
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);

View file

@ -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());
}
SDL_Surface * SpriteCache::get(const std::string &type, const std::string &name) {
std::string id = type + "/" + name;
SpriteCache::sprite_value SpriteCache::load(const std::string &id, unsigned rotation) {
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)
surface = load(id);
surface = load(id, rotation);
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
#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();