Add support for rotated sprites
This commit is contained in:
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 |
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Reference in a new issue