Browse Source

light map

fix/style
Martin Dørum 3 years ago
parent
commit
e8315c9332
4 changed files with 75 additions and 9 deletions
  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 View File

@@ -17,6 +17,10 @@ class Chunk {
public:
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?
enum class TickAction {
DEACTIVATE,
@@ -25,7 +29,8 @@ public:
};

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() {
@@ -33,6 +38,11 @@ public:
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) {
return getTileData()[pos.y * CHUNK_WIDTH + pos.x];
}
@@ -47,6 +57,17 @@ public:
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 compress();
@@ -76,6 +97,7 @@ private:
bool is_modified_ = false;

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

}

+ 16
- 0
libswan/include/swan/Win.h View File

@@ -68,6 +68,14 @@ public:
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,
// because RenderCopy might be faster
void showTexture(const Vec2 &pos, SDL_Texture *tex, SDL_Rect *srcrect) {
@@ -76,6 +84,14 @@ public:
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) {
SDL_Rect destrect = createDestRect(pos, size * TILE_SIZE);
if (SDL_RenderDrawRect(renderer_, &destrect) < 0)

+ 4
- 0
libswan/include/swan/gfxutil.h View File

@@ -37,6 +37,10 @@ public:
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() {
SDL_SetRenderDrawColor(rnd_, r_, g_, b_, a_);
}

+ 32
- 8
libswan/src/Chunk.cc View File

@@ -24,7 +24,7 @@ void Chunk::compress() {
uLongf destlen = sizeof(dest);
int ret = compress2(
(Bytef *)dest, &destlen,
(Bytef *)data_.get(), CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID),
(Bytef *)data_.get(), DATA_SIZE,
Z_BEST_COMPRESSION);

if (ret == Z_OK) {
@@ -36,7 +36,7 @@ void Chunk::compress() {

info
<< "Compressed chunk " << pos_ << " from "
<< CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID) << " bytes "
<< DATA_SIZE << " bytes "
<< "to " << destlen << " bytes";
} else if (ret == Z_BUF_ERROR) {
info
@@ -51,8 +51,8 @@ void Chunk::decompress() {
if (!isCompressed())
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(
dest.get(), &destlen,
(Bytef *)data_.get(), compressed_size_);
@@ -68,7 +68,7 @@ void Chunk::decompress() {
info
<< "Decompressed chunk " << pos_ << " from "
<< compressed_size_ << " bytes to "
<< CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID) << " bytes.";
<< DATA_SIZE << " bytes.";
compressed_size_ = -1;
}

@@ -91,10 +91,19 @@ void Chunk::render(const Context &ctx, SDL_Renderer *rnd) {
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
Tile::ID prevID = Tile::INVALID_ID;
Tile *tile = ctx.game.invalid_tile_.get();

// Fill tile texture
for (int y = 0; y < CHUNK_HEIGHT; ++y) {
for (int x = 0; x < CHUNK_WIDTH; ++x) {
Tile::ID id = getTileID(RelPos(x, y));
@@ -108,6 +117,18 @@ void Chunk::render(const Context &ctx, SDL_Renderer *rnd) {
}
}

// 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;
}

@@ -143,10 +164,13 @@ void Chunk::draw(const Context &ctx, Win &win) {
draw_list_.clear();
}


auto chunkpos = pos_ * Vec2i(CHUNK_WIDTH, CHUNK_HEIGHT);
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) {

Loading…
Cancel
Save