Minor quality of life updates, pause, adjustable window, ability to place all block types.

This commit is contained in:
Jake 2025-05-27 21:57:39 -04:00
parent f4cfde8cf9
commit 585f72a4bd
8 changed files with 112 additions and 61 deletions

View File

@ -5,6 +5,15 @@ Implements a voxel chunk renderer. Chunks are stored as a 3D array of block stru
Code is rough and messy and not much is implemented yet.
Controls:
- WASD - move
- Mouse - look
- LMB - Remove block
- RMB - Place Block
- ESC - Pause
- F11 - Fullscreen
- 1-8 - Select Block
Depends on Raylib.
## Build Instructions:
@ -12,4 +21,5 @@ Depends on Raylib.
1) Install Raylib.
2) Clone the repo.
3) Build by running make.
4) run bin/voxelThing

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

View File

@ -14,5 +14,6 @@
#define TILE_LOG_TOP 6
#define TILE_LOG_SIDE 7
#define TILE_LEAF 8
#define TILE_PLANK 9
#endif

View File

@ -11,6 +11,7 @@
#define BLOCK_GRAVEL 5 // 5
#define BLOCK_LOG 6 // top 6, sides 7, bottom 6
#define BLOCK_LEAF 7 // 8
#define BLOCK_PLANK 8 // 9
typedef struct {
int id;

View File

@ -6,7 +6,7 @@
#include "raylib.h"
#define CHUNK_SIZE_X 16
#define CHUNK_SIZE_Y 16
#define CHUNK_SIZE_Y 256
#define CHUNK_SIZE_Z 16

View File

@ -37,16 +37,9 @@ static const BlockType blockTable[] = {
.faceTiles = { TILE_SAND, TILE_SAND, TILE_SAND, TILE_SAND, TILE_SAND, TILE_SAND }
},
[BLOCK_GRAVEL] = {
.id = BLOCK_GRASS,
.name = "Grass",
.faceTiles = {
TILE_GRASS_SIDE, // -X
TILE_GRASS_SIDE, // +X
TILE_DIRT, // -Y
TILE_GRASS_TOP, // +Y
TILE_GRASS_SIDE, // -Z
TILE_GRASS_SIDE // +Z
}
.id = BLOCK_GRAVEL,
.name = "Gravel",
.faceTiles = { TILE_GRAVEL, TILE_GRAVEL, TILE_GRAVEL, TILE_GRAVEL, TILE_GRAVEL, TILE_GRAVEL }
},
[BLOCK_LOG] = {
.id = BLOCK_LOG,
@ -65,6 +58,11 @@ static const BlockType blockTable[] = {
.name = "Leaves",
.faceTiles = { TILE_LEAF, TILE_LEAF, TILE_LEAF, TILE_LEAF, TILE_LEAF, TILE_LEAF }
},
[BLOCK_PLANK] = {
.id = BLOCK_PLANK,
.name = "Planks",
.faceTiles = { TILE_PLANK, TILE_PLANK, TILE_PLANK, TILE_PLANK, TILE_PLANK, TILE_PLANK }
},
};
const BlockType *GetBlockType(int blockID) {

View File

@ -14,9 +14,14 @@
#include "playerController.h"
#include "chunkGenerator.h"
// Bunch of global variables to clean up later.
float cameraYaw = 0;
float cameraPitch = 0;
bool paused = false;
RaycastHit hit;
int blockSelection = BLOCK_SAND;
// Random helper function for returning what direction you're facing.'
const char* GetCompassDirection(float yaw) {
yaw = fmodf(yaw * RAD2DEG + 360.0f, 360.0f);
if (yaw < 22.5f || yaw >= 337.5f) return "South (+Z)";
@ -29,11 +34,18 @@ const char* GetCompassDirection(float yaw) {
return "Southeast (-X+Z)";
}
// Another random helper function, this time for checking if a Vector3 is non-zero.
static inline bool Vector3IsNonZero(Vector3 v) {
return v.x != 0.0f || v.y != 0.0f || v.z != 0.0f;
}
int main(void) {
// --- Screen setup ---
const int screenWidth = 800;
const int screenHeight = 600;
int screenWidth = 800;
int screenHeight = 600;
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
InitWindow(screenWidth, screenHeight, "VoxelThing");
SetExitKey(-1);
DisableCursor(); // Lock mouse to window for FPS-style camera
// --- World generation ---
@ -52,16 +64,44 @@ int main(void) {
camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Initial camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Looking toward origin
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Y-up world
camera.fovy = 45.0f; // Field of view
camera.fovy = 90.0f; // Field of view
camera.projection = CAMERA_PERSPECTIVE; // Use perspective projection
SetTargetFPS(60);
// --- Main game loop ---
while (!WindowShouldClose()) {
screenWidth = GetScreenWidth();
screenHeight = GetScreenHeight();
BeginDrawing();
ClearBackground(RAYWHITE);
// --- Handle jumping to fullscreen mode with F11 ---
if (IsKeyPressed(KEY_F11)) {
ToggleFullscreen();
Vector2 center = { GetScreenWidth() / 2.0f, GetScreenHeight() / 2.0f };
SetMousePosition(center.x, center.y);
}
// --- Handle pausing ---
if (IsKeyPressed(KEY_ESCAPE)) {
paused = !paused;
if (paused) EnableCursor();
else DisableCursor();
}
// --- Handle selecting blocks ---
if (IsKeyPressed(KEY_ONE)) blockSelection = BLOCK_STONE;
if (IsKeyPressed(KEY_TWO)) blockSelection = BLOCK_DIRT;
if (IsKeyPressed(KEY_THREE)) blockSelection = BLOCK_GRASS;
if (IsKeyPressed(KEY_FOUR)) blockSelection = BLOCK_SAND;
if (IsKeyPressed(KEY_FIVE)) blockSelection = BLOCK_GRAVEL;
if (IsKeyPressed(KEY_SIX)) blockSelection = BLOCK_LOG;
if (IsKeyPressed(KEY_SEVEN)) blockSelection = BLOCK_LEAF;
if (IsKeyPressed(KEY_EIGHT)) blockSelection = BLOCK_PLANK;
if (!paused) {
// --- Update camera and direction ---
UpdateFreeCamera(&camera, 10.0f, &cameraYaw, &cameraPitch); // Move camera with user input
@ -81,7 +121,7 @@ int main(void) {
.position = camera.position,
.direction = Vector3Normalize(camDir)
};
RaycastHit hit = RaycastChunk(&chunk, ray.position, ray.direction, 10.0f);
hit = RaycastChunk(&chunk, ray.position, ray.direction, 10.0f);
// --- Begin 3D rendering ---
BeginMode3D(camera);
@ -90,23 +130,16 @@ int main(void) {
if (hit.hit) {
// Draw a wireframe cube where the ray hit
DrawCubeWires(Vector3Add(hit.position, (Vector3){0.5f, 0.5f, 0.5f}), 1.02f, 1.02f, 1.02f, RED);
DrawFaceHighlight(hit.position, hit.normal); // Highlight the specific face hit
DrawCubeWires(Vector3Add(hit.position, (Vector3){0.5f, 0.5f, 0.5f}), 1.02f, 1.02f, 1.02f, BLACK);
//DrawFaceHighlight(hit.position, hit.normal); // Highlight the specific face hit
}
// Draw debug ray.
camDir = Vector3Normalize(Vector3Subtract(camera.target, camera.position));
Vector3 rayEnd = Vector3Add(camera.position, Vector3Scale(camDir, 10.0f));
DrawLine3D(camera.position, rayEnd, PURPLE);
Vector3 hitPoint = Vector3Add(ray.position, Vector3Scale(ray.direction, hit.t));
DrawCubeWires(hitPoint, 0.05f, 0.05f, 0.05f, RED);
// Draw a lil debug cube where the player is looking.
//Vector3 hitPoint = Vector3Add(ray.position, Vector3Scale(ray.direction, hit.t));
//DrawCubeWires(hitPoint, 0.05f, 0.05f, 0.05f, RED);
EndMode3D();
Vector3 testPoint = Vector3Add(camera.position, Vector3Scale(camDir, 2.0f));
Vector2 projected = GetWorldToScreen(testPoint, camera);
DrawCircleV(projected, 4, RED);
// --- Draw crosshair in screen center ---
DrawLine(screenWidth/2 - 5, screenHeight/2, screenWidth/2 + 5, screenHeight/2, DARKGRAY);
DrawLine(screenWidth/2, screenHeight/2 - 5, screenWidth/2, screenHeight/2 + 5, DARKGRAY);
@ -114,6 +147,14 @@ int main(void) {
// -- Draw debug info ---
DrawText(TextFormat("Facing: %s", GetCompassDirection(cameraYaw)), 10, 10, 20, DARKGRAY);
DrawText(TextFormat("Yaw: %.1f° Pitch: %.1f°", cameraYaw * RAD2DEG, cameraPitch * RAD2DEG), 10, 30, 20, GRAY);
}
// --- Draw pause menu if paused ---
if (paused) {
DrawRectangle(0, 0, screenWidth, screenHeight, Fade(DARKGRAY, 0.5f));
DrawText("Paused", screenWidth / 2 - MeasureText("Paused", 40) / 2, screenHeight / 2 - 20, 40, RAYWHITE);
DrawText("Press ESC to resume", screenWidth / 2 - MeasureText("Press ESC to resume", 20) / 2, screenHeight / 2 + 30, 20, LIGHTGRAY);
}
EndDrawing();
@ -136,7 +177,7 @@ int main(void) {
py >= 0 && py < CHUNK_SIZE_Y &&
pz >= 0 && pz < CHUNK_SIZE_Z) {
chunk.blocks[px][py][pz].type = BLOCK_SAND;
chunk.blocks[px][py][pz].type = blockSelection;
chunkMesh = GenerateChunkMesh(&chunk);
printf("Hit at (%f %f %f), normal (%f %f %f), placing at (%d %d %d)\n",