void setTileID(World &world, RelPos pos, Tile::ID id); | void setTileID(World &world, RelPos pos, Tile::ID id); | ||||
Tile &getTile(World &world, RelPos pos); | Tile &getTile(World &world, RelPos pos); | ||||
void redraw(World &world); | |||||
void render(World &world); | |||||
void draw(Win &win); | void draw(Win &win); | ||||
ChunkPos pos_; | ChunkPos pos_; | ||||
Tile::ID tiles_[CHUNK_WIDTH][CHUNK_HEIGHT]; | Tile::ID tiles_[CHUNK_WIDTH][CHUNK_HEIGHT]; | ||||
private: | private: | ||||
static sf::Uint8 *imgbuf; | |||||
void drawBlock(RelPos pos, const Tile &t); | void drawBlock(RelPos pos, const Tile &t); | ||||
void drawBlock(World &world, RelPos pos, Tile::ID id); | void drawBlock(World &world, RelPos pos, Tile::ID id); | ||||
bool dirty_ = false; | bool dirty_ = false; |
namespace Swan { | 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) { | void Chunk::setTileID(World &world, RelPos pos, Tile::ID id) { | ||||
tiles_[pos.x_][pos.y_] = id; | tiles_[pos.x_][pos.y_] = id; | ||||
drawBlock(world, pos, id); | drawBlock(world, pos, id); | ||||
} | } | ||||
void Chunk::drawBlock(RelPos pos, const Tile &t) { | 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; | dirty_ = true; | ||||
} | } | ||||
drawBlock(pos, world.getTileByID(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 x = 0; x < CHUNK_WIDTH; ++x) { | ||||
for (int y = 0; y < CHUNK_HEIGHT; ++y) { | 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) { | void Chunk::draw(Win &win) { |
#include "World.h" | #include "World.h" | ||||
#include <SFML/System/Clock.hpp> | |||||
namespace Swan { | 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) { | for (int i = 0; i < l; ++i) { | ||||
if (!plane.hasChunk(abspos)) { | if (!plane.hasChunk(abspos)) { | ||||
plane.getChunk(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; | return true; | ||||
} | } | ||||
abspos += dir; | abspos += dir; | ||||
} | } | ||||
void World::ChunkRenderer::tick(WorldPlane &plane, ChunkPos abspos) { | void World::ChunkRenderer::tick(WorldPlane &plane, ChunkPos abspos) { | ||||
sf::Clock clock; | |||||
int l = 0; | int l = 0; | ||||
int left = 4; | |||||
for (int i = 0; i < 8; ++i) { | 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; | 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; | l += 1; | ||||
} | } | ||||
} | } |
if (iter == chunks_.end()) { | if (iter == chunks_.end()) { | ||||
iter = chunks_.emplace(pos, new Chunk(pos)).first; | iter = chunks_.emplace(pos, new Chunk(pos)).first; | ||||
gen_->genChunk(*this, *iter->second); | gen_->genChunk(*this, *iter->second); | ||||
iter->second->redraw(*world_); | |||||
iter->second->render(*world_); | |||||
} | } | ||||
return *iter->second; | return *iter->second; |