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:
| M | blocks.c | | | 2 | +- |
| M | dat.h | | | 21 | ++++++++++++++++++--- |
| M | fns.h | | | 3 | ++- |
| M | main.c | | | 7 | +++++-- |
| M | mkfile | | | 1 | + |
| M | render.c | | | 108 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- |
| A | world.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;
+ }
+ }
+}