minecraft

minecraft
git clone git://git.evenfri.pw/minecraft.git
Log | Files | Refs | README

commit e970cd928bc8d6c72717e8ca08b64a4eb8ad01d3
parent 0843fdab7a06297b0dc3ccaa600edf63c5c7e1a0
Author: evenfri <evenfri@4plt.ch>
Date:   Mon,  2 Nov 2026 22:23:33 +0800

add world generation, chunks, block air, dont render close sides of blocks and chunks (lagged: textures)

Diffstat:
Mblocks.c | 2+-
Mdat.h | 21++++++++++++++++++---
Mfns.h | 3++-
Mmain.c | 7+++++--
Mmkfile | 1+
Mrender.c | 108++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Aworld.c | 42++++++++++++++++++++++++++++++++++++++++++
7 files changed, 160 insertions(+), 24 deletions(-)

diff --git a/blocks.c b/blocks.c @@ -1,7 +1,7 @@ #include "minecraft.h" #include "stb_image.h" -Block blocks[] = { +Block_t blocks[] = { { BLOCK_GRASS, { "assets/grass_side.png", /* back */ "assets/grass_side.png", /* front */ diff --git a/dat.h b/dat.h @@ -7,6 +7,10 @@ #define WINDOW_HEIGHT 600 #define WINDOW_TITLE "window" +#define CHUNK_SIZE 16 +#define CHUNK_HEIGHT 64 +#define WORLD_SIZE 2 + typedef struct { float x, y, z; } vec3; typedef struct { float m[16]; } mat4; @@ -36,17 +40,28 @@ typedef struct { typedef struct { unsigned int id; char *texture_paths[FACE_COUNT]; -} Block; +} Block_t; + +typedef struct { + int blocks[CHUNK_SIZE][CHUNK_HEIGHT][CHUNK_SIZE]; + vec3 position; +} Chunk_t; + +typedef struct { + Chunk_t *chunks[WORLD_SIZE][WORLD_SIZE]; +} World_t; +#define BLOCK_AIR 0 #define BLOCK_GRASS 1 #define BLOCK_STONE 2 -#define BLOCK_DIRT 3 +#define BLOCK_DIRT 3 #define BLOCK_COBBLESTONE 4 extern GLFWwindow *Window; extern unsigned int Shader; extern Camera camera; -extern Block blocks[]; +extern Block_t blocks[]; extern int block_count; +extern World_t World; #endif /* DAT_H */ diff --git a/fns.h b/fns.h @@ -27,6 +27,7 @@ void camera_process_mouse(float dx, float dy); void blocks_init(void); void blocks_end(void); unsigned int block_texture(unsigned int id, int face); -void render_block(unsigned int block_id, vec3 pos); + +void world_generate(); #endif /* FNS_H */ diff --git a/main.c b/main.c @@ -1,9 +1,11 @@ #include "minecraft.h" +#include <unistd.h> int main() { window_init(); - camera_init(vec3_make(0, 2, 0)); + camera_init(vec3_make(0, (CHUNK_HEIGHT / 2) + 2, 0)); shader_init(); + world_generate(); render_init(); float last = (float)glfwGetTime(); @@ -15,9 +17,10 @@ int main() { process_input(dt); render_frame(); + usleep(16000); } shader_end(); render_end(); glfwTerminate(); - exit(1); + exit(0); } diff --git a/mkfile b/mkfile @@ -11,6 +11,7 @@ ofiles = \ shader.$o \ camera.$o \ blocks.$o \ + world.$o \ main.$o hfiles = \ diff --git a/render.c b/render.c @@ -6,8 +6,6 @@ unsigned int VBO, VAO, EBO; unsigned int Texture; static int u_model, u_view, u_proj; -#define CHUNK_SIZE 16 - void render_init() { float vertices[] = { /* back */ @@ -86,11 +84,24 @@ void render_init() { blocks_init(); } -void render_block(unsigned int block_id, vec3 pos) { +void render_block(unsigned int block_id, vec3 pos, + uint8_t r_back, + uint8_t r_front, + uint8_t r_left, + uint8_t r_right, + uint8_t r_bottom, + uint8_t r_top) { mat4 model = mat4_translate(pos.x, pos.y, pos.z); glUniformMatrix4fv(u_model, 1, GL_FALSE, model.m); for (int face = 0; face < FACE_COUNT; face++) { + if (face == FACE_BACK && r_back == 0) continue; + if (face == FACE_FRONT && r_front == 0) continue; + if (face == FACE_LEFT && r_left == 0) continue; + if (face == FACE_RIGHT && r_right == 0) continue; + if (face == FACE_BOTTOM && r_bottom == 0) continue; + if (face == FACE_TOP && r_top == 0) continue; + unsigned int tex = block_texture(block_id, face); if (!tex) continue; glActiveTexture(GL_TEXTURE0); @@ -99,18 +110,85 @@ void render_block(unsigned int block_id, vec3 pos) { } } -void render_chunk(vec3 position) { - int base_x = (int)(position.x * CHUNK_SIZE); - int base_z = (int)(position.z * CHUNK_SIZE); +void render_chunk(Chunk_t *chunk, + Chunk_t *chunk_front, Chunk_t *chunk_back, + Chunk_t *chunk_right, Chunk_t *chunk_left) { + if (!chunk) return; + + uint8_t back_face_vis = 0; + uint8_t front_face_vis = 0; + uint8_t left_face_vis = 0; + uint8_t right_face_vis = 0; + uint8_t bottom_face_vis = 0; + uint8_t top_face_vis = 0; + + int base_x = (int)(chunk->position.x * CHUNK_SIZE); + int base_z = (int)(chunk->position.z * CHUNK_SIZE); for (int x = 0; x < CHUNK_SIZE; x++) { for (int z = 0; z < CHUNK_SIZE; z++) { - float wx = (float)(base_x + x); - float wz = (float)(base_z + z); + for (int y = 0; y < CHUNK_HEIGHT; y++) { + int block_id = chunk->blocks[x][y][z]; + if (block_id == BLOCK_AIR) continue; + + float wx = (float)(base_x + x); + float wz = (float)(base_z + z); + + if (z == 0) { + back_face_vis = + (!chunk_back || chunk_back->blocks[x][y][CHUNK_SIZE - 1] == 0); + } else { + back_face_vis = (chunk->blocks[x][y][z - 1] == 0); + } + + if (z == CHUNK_SIZE - 1) { + front_face_vis = (!chunk_front || chunk_front->blocks[x][y][0] == 0); + } else { + front_face_vis = (chunk->blocks[x][y][z + 1] == 0); + } + + if (x == 0) { + left_face_vis = + (!chunk_left || chunk_left->blocks[CHUNK_SIZE - 1][y][z] == 0); + } else { + left_face_vis = (chunk->blocks[x - 1][y][z] == 0); + } + + if (x == CHUNK_SIZE - 1) { + right_face_vis = + (!chunk_right || chunk_right->blocks[0][y][z] == 0); + } else { + right_face_vis = (chunk->blocks[x + 1][y][z] == 0); + } + + bottom_face_vis = (y == 0 || chunk->blocks[x][y - 1][z] == 0); + top_face_vis = + (y == CHUNK_HEIGHT - 1 || chunk->blocks[x][y + 1][z] == 0); + + render_block(block_id, (vec3){ wx, y, wz }, + back_face_vis, + front_face_vis, + left_face_vis, + right_face_vis, + bottom_face_vis, + top_face_vis); + } + } + } +} + +void render_world() { + for (int x = 0; x < WORLD_SIZE; x++) { + for (int z = 0; z < WORLD_SIZE; z++) { + Chunk_t *current = World.chunks[x][z]; + if (!current) continue; + + Chunk_t *c_left = (x > 0) ? World.chunks[x - 1][z] : NULL; + Chunk_t *c_right = (x < WORLD_SIZE - 1) ? World.chunks[x + 1][z] : NULL; + Chunk_t *c_back = (z > 0) ? World.chunks[x][z - 1] : NULL; + Chunk_t *c_front = (z < WORLD_SIZE - 1) ? World.chunks[x][z + 1] : NULL; - render_block(BLOCK_GRASS, (vec3){ wx, 0.0f, wz }); - render_block(BLOCK_DIRT, (vec3){ wx, -1.0f, wz }); - render_block(BLOCK_STONE, (vec3){ wx, -2.0f, wz }); + render_chunk(current, c_front, c_back, c_right, c_left); } } } @@ -121,7 +199,7 @@ void render_frame() { glUseProgram(Shader); - mat4 view = camera_get_view(); + mat4 view = camera_get_view(); mat4 projection = mat4_perspective(camera.fov, (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 0.1f, 100.0f); @@ -130,11 +208,7 @@ void render_frame() { glBindVertexArray(VAO); - for (int x = -2; x < 2; x++) { - for (int z = -2; z < 2; z++) { - render_chunk((vec3){x, 0, z}); - } - } + render_world(); glfwPollEvents(); glfwSwapBuffers(Window); diff --git a/world.c b/world.c @@ -0,0 +1,42 @@ +#include "minecraft.h" + +World_t World; + +Chunk_t* world_generate_chunk(vec3 position) { + Chunk_t *ret = calloc(1, sizeof(*ret)); + if (!ret) { perror("calloc"); exit(1); } + + int block_id = 0; + + for (int x = 0; x < CHUNK_SIZE; x++) { + for (int z = 0; z < CHUNK_SIZE; z++) { + for (int y = 0; y < CHUNK_HEIGHT/2; y++) { + if (y >= CHUNK_HEIGHT/2) { + } else if (y == (CHUNK_HEIGHT/2) - 1) { + block_id = BLOCK_GRASS; + } else if (y >= (CHUNK_HEIGHT/2) - 3) { + block_id = BLOCK_DIRT; + } else { + block_id = BLOCK_STONE; + } + + ret->blocks[x][y][z] = block_id; + } + } + } + + ret->position = position; + + return ret; +} + +void world_generate() { + int half_world = WORLD_SIZE / 2; + for (int x = 0; x < WORLD_SIZE; x++) { + for (int z = 0; z < WORLD_SIZE; z++) { + Chunk_t *chunk = + world_generate_chunk((vec3){x - half_world, 0, z - half_world}); + World.chunks[x][z] = chunk; + } + } +}