Martin Dørum 3 лет назад
Родитель
Сommit
e8315c9332
4 измененных файлов: 75 добавлений и 9 удалений
  1. 23
    1
      libswan/include/swan/Chunk.h
  2. 16
    0
      libswan/include/swan/Win.h
  3. 4
    0
      libswan/include/swan/gfxutil.h
  4. 32
    8
      libswan/src/Chunk.cc

+ 23
- 1
libswan/include/swan/Chunk.h Просмотреть файл

public: public:
using RelPos = TilePos; using RelPos = TilePos;


static constexpr size_t DATA_SIZE =
CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID) + // Tiles
CHUNK_WIDTH * CHUNK_HEIGHT; // Light levels

// What does this chunk want the world gen to do after a tick? // What does this chunk want the world gen to do after a tick?
enum class TickAction { enum class TickAction {
DEACTIVATE, DEACTIVATE,
}; };


Chunk(ChunkPos pos): pos_(pos) { Chunk(ChunkPos pos): pos_(pos) {
data_.reset(new uint8_t[CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID)]);
data_.reset(new uint8_t[DATA_SIZE]);
memset(getLightData(), 255, CHUNK_WIDTH * CHUNK_HEIGHT);
} }


Tile::ID *getTileData() { Tile::ID *getTileData() {
return (Tile::ID *)data_.get(); return (Tile::ID *)data_.get();
} }


uint8_t *getLightData() {
assert(isActive());
return data_.get() + CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID);
}

Tile::ID getTileID(RelPos pos) { Tile::ID getTileID(RelPos pos) {
return getTileData()[pos.y * CHUNK_WIDTH + pos.x]; return getTileData()[pos.y * CHUNK_WIDTH + pos.x];
} }
need_render_ = true; need_render_ = true;
} }


uint8_t getLightLevel(RelPos pos) {
return getLightData()[pos.y * CHUNK_WIDTH + pos.x];
}

void setLightLevel(RelPos pos, uint8_t level, SDL_Renderer *rnd);

void setLightData(RelPos pos, uint8_t level) {
getLightData()[pos.y * CHUNK_WIDTH + pos.x] = level;
need_render_ = true;
}

void render(const Context &ctx, SDL_Renderer *rnd); void render(const Context &ctx, SDL_Renderer *rnd);


void compress(); void compress();
bool is_modified_ = false; bool is_modified_ = false;


CPtr<SDL_Texture, SDL_DestroyTexture> texture_; CPtr<SDL_Texture, SDL_DestroyTexture> texture_;
CPtr<SDL_Texture, SDL_DestroyTexture> light_texture_;
}; };


} }

+ 16
- 0
libswan/include/swan/Win.h Просмотреть файл

warn << "RenderCopyEx failed: " << SDL_GetError(); warn << "RenderCopyEx failed: " << SDL_GetError();
} }


void showTexture(const Vec2 &pos, SDL_Texture *tex, SDL_Rect *srcrect,
SDL_Rect *dest, ShowTextureArgs args) {
SDL_Point *center = args.center ? &*args.center : nullptr;
SDL_Rect destrect = createDestRect(pos, Vec2(dest->w * args.hscale, dest->h * args.hscale));
if (SDL_RenderCopyEx(renderer_, tex, srcrect, &destrect, args.angle, center, args.flip) < 0)
warn << "RenderCopyEx failed: " << SDL_GetError();
}

// We want an overload which uses RenderCopy instead of RenderCopyEx, // We want an overload which uses RenderCopy instead of RenderCopyEx,
// because RenderCopy might be faster // because RenderCopy might be faster
void showTexture(const Vec2 &pos, SDL_Texture *tex, SDL_Rect *srcrect) { void showTexture(const Vec2 &pos, SDL_Texture *tex, SDL_Rect *srcrect) {
warn << "RenderCopy failed: " << SDL_GetError(); warn << "RenderCopy failed: " << SDL_GetError();
} }


// Another overload without RenderCopyEx
void showTexture(const Vec2 &pos, SDL_Texture *tex, SDL_Rect *srcrect,
SDL_Rect *dest) {
SDL_Rect destrect = createDestRect(pos, Vec2(dest->w, dest->h));
if (SDL_RenderCopy(renderer_, tex, srcrect, &destrect) < 0)
warn << "RenderCopy failed: " << SDL_GetError();
}

void drawRect(const Vec2 &pos, const Vec2 &size) { void drawRect(const Vec2 &pos, const Vec2 &size) {
SDL_Rect destrect = createDestRect(pos, size * TILE_SIZE); SDL_Rect destrect = createDestRect(pos, size * TILE_SIZE);
if (SDL_RenderDrawRect(renderer_, &destrect) < 0) if (SDL_RenderDrawRect(renderer_, &destrect) < 0)

+ 4
- 0
libswan/include/swan/gfxutil.h Просмотреть файл

SDL_SetRenderDrawColor(rnd_, r, g, b, a); SDL_SetRenderDrawColor(rnd_, r, g, b, a);
} }


void change(Uint8 r, Uint8 g, Uint8 b, Uint8 a = 255) {
SDL_SetRenderDrawColor(rnd_, r, g, b, a);
}

~RenderDrawColor() { ~RenderDrawColor() {
SDL_SetRenderDrawColor(rnd_, r_, g_, b_, a_); SDL_SetRenderDrawColor(rnd_, r_, g_, b_, a_);
} }

+ 32
- 8
libswan/src/Chunk.cc Просмотреть файл

uLongf destlen = sizeof(dest); uLongf destlen = sizeof(dest);
int ret = compress2( int ret = compress2(
(Bytef *)dest, &destlen, (Bytef *)dest, &destlen,
(Bytef *)data_.get(), CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID),
(Bytef *)data_.get(), DATA_SIZE,
Z_BEST_COMPRESSION); Z_BEST_COMPRESSION);


if (ret == Z_OK) { if (ret == Z_OK) {


info info
<< "Compressed chunk " << pos_ << " from " << "Compressed chunk " << pos_ << " from "
<< CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID) << " bytes "
<< DATA_SIZE << " bytes "
<< "to " << destlen << " bytes"; << "to " << destlen << " bytes";
} else if (ret == Z_BUF_ERROR) { } else if (ret == Z_BUF_ERROR) {
info info
if (!isCompressed()) if (!isCompressed())
return; return;


auto dest = std::make_unique<uint8_t[]>(CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID));
uLongf destlen = CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID);
auto dest = std::make_unique<uint8_t[]>(DATA_SIZE);
uLongf destlen = DATA_SIZE;
int ret = uncompress( int ret = uncompress(
dest.get(), &destlen, dest.get(), &destlen,
(Bytef *)data_.get(), compressed_size_); (Bytef *)data_.get(), compressed_size_);
info info
<< "Decompressed chunk " << pos_ << " from " << "Decompressed chunk " << pos_ << " from "
<< compressed_size_ << " bytes to " << compressed_size_ << " bytes to "
<< CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID) << " bytes.";
<< DATA_SIZE << " bytes.";
compressed_size_ = -1; compressed_size_ = -1;
} }


target.emplace(rnd, texture_.get()); target.emplace(rnd, texture_.get());
} }


// Same with light texture
if (!light_texture_) {
light_texture_.reset(SDL_CreateTexture(
ctx.game.win_.renderer_, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET,
CHUNK_WIDTH, CHUNK_HEIGHT));
SDL_SetTextureBlendMode(light_texture_.get(), SDL_BLENDMODE_BLEND);
}

// We're caching tiles so we don't have to world.getTileByID() every time // We're caching tiles so we don't have to world.getTileByID() every time
Tile::ID prevID = Tile::INVALID_ID; Tile::ID prevID = Tile::INVALID_ID;
Tile *tile = ctx.game.invalid_tile_.get(); Tile *tile = ctx.game.invalid_tile_.get();


// Fill tile texture
for (int y = 0; y < CHUNK_HEIGHT; ++y) { for (int y = 0; y < CHUNK_HEIGHT; ++y) {
for (int x = 0; x < CHUNK_WIDTH; ++x) { for (int x = 0; x < CHUNK_WIDTH; ++x) {
Tile::ID id = getTileID(RelPos(x, y)); Tile::ID id = getTileID(RelPos(x, y));
} }
} }


// Fill light texture
target.emplace(rnd, light_texture_.get());
RenderBlendMode mode(rnd, SDL_BLENDMODE_NONE);
RenderDrawColor color(rnd, 0, 0, 0, 0);
for (int y = 0; y < CHUNK_HEIGHT; ++y) {
for (int x = 0; x < CHUNK_WIDTH; ++x) {
color.change(0, 0, 0, 255 - getLightLevel({ x, y }));
SDL_Rect rect{ x, y, 1, 1 };
SDL_RenderFillRect(rnd, &rect);
}
}

need_render_ = false; need_render_ = false;
} }


draw_list_.clear(); draw_list_.clear();
} }



auto chunkpos = pos_ * Vec2i(CHUNK_WIDTH, CHUNK_HEIGHT);
SDL_Rect rect{ 0, 0, CHUNK_WIDTH * TILE_SIZE, CHUNK_HEIGHT * TILE_SIZE }; SDL_Rect rect{ 0, 0, CHUNK_WIDTH * TILE_SIZE, CHUNK_HEIGHT * TILE_SIZE };
win.showTexture(
pos_ * Vec2i(CHUNK_WIDTH, CHUNK_HEIGHT),
texture_.get(), &rect);
win.showTexture(chunkpos, texture_.get(), &rect);

SDL_Rect texrect{ 0, 0, CHUNK_WIDTH, CHUNK_HEIGHT };
win.showTexture(chunkpos, light_texture_.get(), &texrect, &rect);
} }


Chunk::TickAction Chunk::tick(float dt) { Chunk::TickAction Chunk::tick(float dt) {

Загрузка…
Отмена
Сохранить