Test monde infini

This commit is contained in:
MarcEricMartel
2021-12-02 18:12:35 -05:00
parent 2ad6b7e2c6
commit 033f69465c
159 changed files with 332 additions and 327 deletions

View File

@@ -79,10 +79,11 @@ void World::TransposeWorld(Player& player) {
player.Transpose(x, y);
}
void World::CleanUpWorld(int& frames) {
if (!m_tbDeleted.empty() && !frames) {
void World::CleanUpWorld(int& deleteframes, bool clear = false) {
if (clear) m_tbDeleted.clear();
if (!m_tbDeleted.empty() && !deleteframes) {
m_tbDeleted.pop_back();
frames = FRAMES_DELETE_CHUNKS;
deleteframes = FRAMES_DELETE_CHUNKS;
}
}
@@ -97,3 +98,270 @@ Chunk* World::RetrieveChunk(int x, int y) {
return nullptr;
}
void World::GetScope(int& x, int& y) {
x = m_center[0];
y = m_center[1];
}
void World::Update(int& rendercount, int& badhitcount, Player& player, Transformation& world, Shader& shader, TextureAtlas& atlas, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]) {
atlas.Bind();
TransposeWorld(player);
RenderWorld(rendercount, badhitcount, player, world, shader);
UpdateWorld(player, perlin, blockinfo);
shader.Disable();
}
bool World::GenerateChunk(int chx, int chy, Perlin& perlin) {
if (chx < WORLD_SIZE_X * CHUNK_SIZE_X && chy < WORLD_SIZE_Y * CHUNK_SIZE_Z &&
chx >= 0 && chy >= 0)
if (!ChunkAt(chx, 1, chy)) {
for (int index = 0; index < m_tbDeleted.size(); ++index) { // V<>rifie l'existence d'un chunk dans le buffer de suppression avec sa position.
int x, y;
m_tbDeleted.at(index)->GetPosition(x, y);
if (chx / CHUNK_SIZE_X + m_center[0] == x &&
chy / CHUNK_SIZE_Z + m_center[1] == y) {
GetChunks().Set(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, std::move(m_tbDeleted.at(index)));
return true;
}
}
std::ostringstream pos; // V<>rifie l'existence d'un fichier .chunk avec sa position.
pos << CHUNK_PATH << chx / CHUNK_SIZE_X + m_center[0] << '_' << chy / CHUNK_SIZE_Z + m_center[1] << ".chunk";
std::ifstream input(pos.str().c_str(), std::fstream::binary);
if (input.fail()) {
GetChunks().Set(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, new Chunk(chx / CHUNK_SIZE_X + m_center[0], chy / CHUNK_SIZE_Z + m_center[1]));
Chunk* chunk = GetChunks().Get(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z);
for (int x = 0; x < CHUNK_SIZE_X; ++x)
for (int z = 0; z < CHUNK_SIZE_Z; ++z) {
Vector3f noise;
noise.x = x * (CHUNK_SIZE_X + 1) + (CHUNK_SIZE_X - 1) * (chx + m_center[0]);
noise.y = 0;
noise.z = z * (CHUNK_SIZE_Z + 1) + (CHUNK_SIZE_Z - 1) * (chy + m_center[1]);
noise.Normalize();
float height = perlin.Get(noise.x, noise.z) * 3 - 32;
for (int y = 0; y <= (int)height % CHUNK_SIZE_Y; ++y)
chunk->SetBlock(x, y, z, BTYPE_METAL, this);
}
for (int x = 0; x < CHUNK_SIZE_X; ++x)
for (int z = 0; z < CHUNK_SIZE_Z; ++z) {
Vector3f noise;
noise.x = x * (CHUNK_SIZE_X + 1) + (CHUNK_SIZE_X - 1) * (chx + m_center[0]);
noise.y = 0;
noise.z = z * (CHUNK_SIZE_Z + 1) + (CHUNK_SIZE_Z - 1) * (chy + m_center[1]);
noise.Normalize();
float height = perlin.Get(noise.x, noise.z) + 16;
for (int y = 0; y <= (int)height % CHUNK_SIZE_Y; ++y) {
if (chunk->GetBlock(x, y, z) == BTYPE_AIR)
chunk->SetBlock(x, y, z, BTYPE_GRASS, this);
}
}
for (int x = 0; x < CHUNK_SIZE_X; ++x)
for (int z = 0; z < CHUNK_SIZE_Z; ++z) {
for (int y = 0; y <= 10; ++y) {
if (chunk->GetBlock(x, y, z) == BTYPE_AIR)
chunk->SetBlock(x, y, z, BTYPE_ICE, this);
}
}
for (int x = 0; x < CHUNK_SIZE_X; ++x)
for (int z = 0; z < CHUNK_SIZE_Z; ++z) {
for (int y = 0; y < CHUNK_SIZE_Y; ++y) {
Vector3f noise;
noise.x = x * (CHUNK_SIZE_X + 1) + (CHUNK_SIZE_X - 1) * (chx + m_center[0]);
noise.y = (x + z) * CHUNK_SIZE_Y + m_center[0];
noise.z = z * (CHUNK_SIZE_Z + 1) + (CHUNK_SIZE_Z - 1) * (chy + m_center[1]);
noise.Normalize();
float height = perlin.Get(noise.x, noise.y, noise.z);
if (chunk->GetBlock(x, y, z) != BTYPE_AIR && height > 18)
chunk->SetBlock(x, y, z, BTYPE_DIRT, this);
}
}
}
else {
input.seekg(0, std::ios_base::end);
int size = input.tellg();
input.seekg(0, std::ios_base::beg);
char* data = new char[size];
input.read(data, size);
input.close();
GetChunks().Set(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, new Chunk(chx / CHUNK_SIZE_X + m_center[0], chy / CHUNK_SIZE_Z + m_center[1], data));
delete[] data;
}
std::cout << "Chunk generated: " << chx / CHUNK_SIZE_X + m_center[0] << ", " << chy / CHUNK_SIZE_Z + m_center[1] << std::endl;
return true;
}
return false;
}
void World::UpdateChunk(int& generates, int& updates, int chx, int chy, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]) {
if (generates == 0 && GenerateChunk(chx, chy, perlin)) generates = FRAMES_RENDER_CHUNKS;
if (updates == 0 && ChunkAt(chx, 1, chy) &&
ChunkAt(chx, 1, chy)->IsDirty()) {
ChunkAt(chx, 1, chy)->Update(blockinfo, this);
updates = FRAMES_UPDATE_CHUNKS;
}
}
void World::ChangeBlockAtCursor(BlockType blockType, Player& player, bool& block) {
Vector3f currentPos = player.GetPosition();
Vector3f currentBlock = currentPos;
Vector3f ray = player.GetDirection();
bool found = false;
if (block) return;
while ((currentPos - currentBlock).Length() <= MAX_SELECTION_DISTANCE && !found) {
currentBlock += ray / 10.f;
BlockType bt = BlockAt(currentBlock);
if (bt != BTYPE_AIR)
found = true;
}
if (found)
if (blockType != BTYPE_AIR) {
found = false;
while ((currentPos - currentBlock).Length() >= 1.7f && !found) {
currentBlock -= ray / 10.f;
BlockType bt = BlockAt(currentBlock);
if (bt == BTYPE_AIR) { // V<>rification pour <20>tre s<>r que le bloc <20> changer n'est pas dans le joueur.
int Bx = (int)currentBlock.x;
int By = (int)currentBlock.y;
int Bz = (int)currentBlock.z;
int Px = (int)currentPos.x;
int PyA = (int)currentPos.y;
int PyB = (int)(currentPos.y - .9f);
int PyC = (int)(currentPos.y - 1.7f);
int Pz = (int)currentPos.z;
if (!(Bx == Px &&
(By == PyA ||
By == PyB ||
By == PyC) &&
Bz == Pz))
found = true;
}
}
}
if (found && (int)currentBlock.y < CHUNK_SIZE_Y) {
int bx = (int)currentBlock.x % CHUNK_SIZE_X;
int by = (int)currentBlock.y % CHUNK_SIZE_Y;
int bz = (int)currentBlock.z % CHUNK_SIZE_Z;
ChunkAt(currentBlock)->SetBlock(bx, by, bz, blockType, this);
ChunkAt(currentBlock)->MakeModified();
block = true;
}
}
void World::RenderWorld(int& rendercount, int& badhitcount, Player& player, Transformation& world, Shader& shader) {
shader.Use();
rendercount = 0;
badhitcount = 0;
static std::vector<Vector3i> renderManifest;
Vector3f angle;
Vector3f cursor;
Vector3f direct = player.GetDirection();
Vector3f pos = player.GetPosition() - direct;
direct.y = 0;
direct.Normalize();
pos.y = 1;
renderManifest.clear();
for (int dist = VIEW_DISTANCE; dist >= 0; dist -= CHUNK_SIZE_X) {
// Configuration du radar.
angle.x = direct.z + direct.x;
angle.y = 0;
angle.z = direct.z - direct.x;
angle.Normalize();
float sinus = .01745240643; // sin(1 degr<67>)
float cosinus = .99984769515; // cos(1 degr<67>)
int echantillons = 90;
for (int radar = 0; radar < echantillons; ++radar) {
float x = angle.x;
float z = angle.z;
angle.x = x * cosinus - z * sinus;
angle.z = z * cosinus + x * sinus;
angle.Normalize();
cursor = pos - direct * CHUNK_SIZE_X * 2 + angle * dist;
if (cursor.y >= 128.f || cursor.y >= 0.f) cursor.y = 1;
bool valide = true;
if (ChunkAt(cursor)) {
int chx, chy;
ChunkAt(cursor)->GetPosition(chx, chy);
for (int index = 0; index < renderManifest.size(); ++index)
if (renderManifest[index] == Vector3i(chx, 0, chy)) {
valide = false;
++badhitcount;
}
if (valide) {
world.ApplyTranslation((chx - m_center[0]) * CHUNK_SIZE_X, 0, (chy - m_center[1]) * CHUNK_SIZE_Z);
world.Use();
float dist = (pos - cursor).Length();
float blend = ((float)VIEW_DISTANCE - dist * 2.f + 128.f) / (float)VIEW_DISTANCE;
glBlendColor(0.f, 0.f, 0.f, blend);
ChunkAt(cursor)->Render();
world.ApplyTranslation(-(chx - m_center[0]) * CHUNK_SIZE_X, 0, -(chy - m_center[1]) * CHUNK_SIZE_Z);
renderManifest.push_back(Vector3i(chx, 0, chy));
++rendercount;
}
}
}
}
shader.Disable();
};
void World::UpdateWorld(Player& player, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]) {
int cx = player.GetPosition().x;
int cy = player.GetPosition().z;
static int frameGenerate = 0;
static int frameUpdate = 0;
static int frameDelete = 0;
int side = 0;
if (frameGenerate > 0) --frameGenerate;
if (frameUpdate > 0) --frameUpdate;
if (frameDelete > 0) --frameDelete;
if (!frameGenerate || !frameUpdate)
while (side * CHUNK_SIZE_X <= VIEW_DISTANCE * 2) {
int tx = -side, ty = -side;
for (; tx <= side; ++tx)
UpdateChunk(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z, perlin, blockinfo);
for (; ty <= side; ++ty)
UpdateChunk(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z, perlin, blockinfo);
for (; tx >= -side; --tx)
UpdateChunk(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z, perlin, blockinfo);
for (; ty >= -side; --ty)
UpdateChunk(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z, perlin, blockinfo);
++side;
}
CleanUpWorld(frameDelete);
}