@@ -21,13 +21,15 @@ public: | |||
void setTileID(World &world, RelPos pos, Tile::ID id); | |||
Tile &getTile(World &world, RelPos pos); | |||
void redraw(World &world); | |||
void render(World &world); | |||
void draw(Win &win); | |||
ChunkPos pos_; | |||
Tile::ID tiles_[CHUNK_WIDTH][CHUNK_HEIGHT]; | |||
private: | |||
static sf::Uint8 *imgbuf; | |||
void drawBlock(RelPos pos, const Tile &t); | |||
void drawBlock(World &world, RelPos pos, Tile::ID id); | |||
bool dirty_ = false; |
@@ -4,6 +4,8 @@ | |||
namespace Swan { | |||
sf::Uint8 *Chunk::imgbuf = new sf::Uint8[CHUNK_WIDTH * TILE_SIZE * CHUNK_HEIGHT * TILE_SIZE * 4]; | |||
void Chunk::setTileID(World &world, RelPos pos, Tile::ID id) { | |||
tiles_[pos.x_][pos.y_] = id; | |||
drawBlock(world, pos, id); | |||
@@ -14,7 +16,7 @@ Tile &Chunk::getTile(World &world, RelPos pos) { | |||
} | |||
void Chunk::drawBlock(RelPos pos, const Tile &t) { | |||
texture_.update(t. image_, pos.x_ * TILE_SIZE, pos.y_ * TILE_SIZE); | |||
texture_.update(t.image_, pos.x_ * TILE_SIZE, pos.y_ * TILE_SIZE); | |||
dirty_ = true; | |||
} | |||
@@ -22,12 +24,31 @@ void Chunk::drawBlock(World &world, RelPos pos, Tile::ID id) { | |||
drawBlock(pos, world.getTileByID(id)); | |||
} | |||
void Chunk::redraw(World &world) { | |||
void Chunk::render(World &world) { | |||
Tile::ID prevID = Tile::INVALID_ID; | |||
Tile &tile = Tile::INVALID_TILE; | |||
for (int x = 0; x < CHUNK_WIDTH; ++x) { | |||
for (int y = 0; y < CHUNK_HEIGHT; ++y) { | |||
drawBlock(world, ChunkPos(x, y), tiles_[x][y]); | |||
Tile::ID id = tiles_[x][y]; | |||
if (id != prevID) { | |||
prevID = id; | |||
tile = world.getTileByID(id); | |||
} | |||
const sf::Uint8 *imgptr = tile.image_.getPixelsPtr(); | |||
for (int imgy = 0; imgy < TILE_SIZE; ++imgy) { | |||
int pixx = x * TILE_SIZE; | |||
int pixy = y * TILE_SIZE + imgy; | |||
sf::Uint8 *pix = imgbuf + | |||
pixy * CHUNK_WIDTH * TILE_SIZE * 4 + | |||
pixx * 4; | |||
memcpy(pix, imgptr + imgy * TILE_SIZE * 4, TILE_SIZE * 4); | |||
} | |||
} | |||
} | |||
texture_.update(imgbuf, CHUNK_WIDTH * TILE_SIZE, CHUNK_HEIGHT * TILE_SIZE, 0, 0); | |||
} | |||
void Chunk::draw(Win &win) { |
@@ -1,12 +1,17 @@ | |||
#include "World.h" | |||
#include <SFML/System/Clock.hpp> | |||
namespace Swan { | |||
static bool chunkLine(int l, int &left, WorldPlane &plane, ChunkPos &abspos, const Vec2i &dir) { | |||
static bool chunkLine(int l, sf::Clock &clock, WorldPlane &plane, ChunkPos &abspos, const Vec2i &dir) { | |||
for (int i = 0; i < l; ++i) { | |||
if (!plane.hasChunk(abspos)) { | |||
plane.getChunk(abspos); | |||
if (--left == 0) | |||
// Don't blow our frame budget on generating chunks, | |||
// but generate as many as possible within the budget | |||
if (clock.getElapsedTime().asSeconds() > 1.0 / 100) | |||
return true; | |||
} | |||
abspos += dir; | |||
@@ -16,15 +21,15 @@ static bool chunkLine(int l, int &left, WorldPlane &plane, ChunkPos &abspos, con | |||
} | |||
void World::ChunkRenderer::tick(WorldPlane &plane, ChunkPos abspos) { | |||
sf::Clock clock; | |||
int l = 0; | |||
int left = 4; | |||
for (int i = 0; i < 8; ++i) { | |||
if (chunkLine(l, left, plane, abspos, Vec2i(0, -1))) return; | |||
if (chunkLine(l, left, plane, abspos, Vec2i(1, 0))) return; | |||
if (chunkLine(l, clock, plane, abspos, Vec2i(0, -1))) break; | |||
if (chunkLine(l, clock, plane, abspos, Vec2i(1, 0))) break; | |||
l += 1; | |||
if (chunkLine(l, left, plane, abspos, Vec2i(0, 1))) return; | |||
if (chunkLine(l, left, plane, abspos, Vec2i(-1, 0))) return; | |||
if (chunkLine(l, clock, plane, abspos, Vec2i(0, 1))) break; | |||
if (chunkLine(l, clock, plane, abspos, Vec2i(-1, 0))) break; | |||
l += 1; | |||
} | |||
} |
@@ -46,7 +46,7 @@ Chunk &WorldPlane::getChunk(ChunkPos pos) { | |||
if (iter == chunks_.end()) { | |||
iter = chunks_.emplace(pos, new Chunk(pos)).first; | |||
gen_->genChunk(*this, *iter->second); | |||
iter->second->redraw(*world_); | |||
iter->second->render(*world_); | |||
} | |||
return *iter->second; |