Add player viewmodel and fix item icons - v1.6.1
This commit is contained in:
parent
224b80311a
commit
3d23e0c896
Binary file not shown.
|
After Width: | Height: | Size: 476 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 647 KiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 476 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 647 KiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 476 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 647 KiB |
162
src/main.cpp
162
src/main.cpp
|
|
@ -18,7 +18,8 @@
|
|||
|
||||
enum BlockType {
|
||||
AIR = 0, GRASS = 1, DIRT = 2, COBBLESTONE = 3, LOG = 4, LEAVES = 5, PLANK = 6,
|
||||
STONE = 7, BEDROCK = 8, DIAMOND_ORE = 9, IRON_ORE = 10, GRAVEL = 11, CRAFTING_TABLE = 12, SAND = 13
|
||||
STONE = 7, BEDROCK = 8, DIAMOND_ORE = 9, IRON_ORE = 10, GRAVEL = 11, CRAFTING_TABLE = 12, SAND = 13,
|
||||
STICK = 14, WOOD_AXE = 15
|
||||
};
|
||||
|
||||
// Simple 2D Perlin Noise implementation
|
||||
|
|
@ -622,7 +623,11 @@ int main(void)
|
|||
MenuState optionsReturnState = MAIN_MENU;
|
||||
|
||||
InventorySlot mouseHeldItem(AIR, 0);
|
||||
float gameTime = 0.0f; // Total game time for day/night cycle
|
||||
float gameTime = 75.0f; // Start at 6:00 AM
|
||||
float breakProgress = 0.0f;
|
||||
int lastHitX = -1, lastHitY = -1, lastHitZ = -1;
|
||||
float swingTime = 0.0f;
|
||||
bool isSwinging = false;
|
||||
|
||||
float targetZoom = 1.1f;
|
||||
float currentZoom = 1.1f;
|
||||
|
|
@ -676,6 +681,10 @@ int main(void)
|
|||
// Safety Fallback: Use Planks if custom textures failed to load (prevents crash)
|
||||
if (craftingSideTexture.id == 0) craftingSideTexture = blockTextures[PLANK];
|
||||
if (craftingTopTexture.id == 0) craftingTopTexture = blockTextures[PLANK];
|
||||
blockTextures[CRAFTING_TABLE] = craftingSideTexture; // Preview for inventory
|
||||
|
||||
blockTextures[STICK] = LoadTexture("assets/stick.png");
|
||||
blockTextures[WOOD_AXE] = LoadTexture("assets/wooden_axe.png");
|
||||
|
||||
// Inventory Crafting State
|
||||
InventorySlot craftingSlots[4]; // Default to AIR/0
|
||||
|
|
@ -690,14 +699,44 @@ int main(void)
|
|||
if (craftingSlots[0].blockType == PLANK && craftingSlots[1].blockType == PLANK &&
|
||||
craftingSlots[2].blockType == PLANK && craftingSlots[3].blockType == PLANK) {
|
||||
craftingResult = InventorySlot(CRAFTING_TABLE, 1);
|
||||
} else {
|
||||
}
|
||||
// Recipe: 2 Planks (vertical) -> 4 Sticks
|
||||
else if ((craftingSlots[0].blockType == PLANK && craftingSlots[2].blockType == PLANK) ||
|
||||
(craftingSlots[1].blockType == PLANK && craftingSlots[3].blockType == PLANK)) {
|
||||
craftingResult = InventorySlot(STICK, 4);
|
||||
}
|
||||
else {
|
||||
craftingResult = InventorySlot(AIR, 0);
|
||||
}
|
||||
};
|
||||
|
||||
auto UpdateTableCrafting = [&]() {
|
||||
// Example: 1 plank -> 4 buttons? No, let's just keep it empty for now or add one.
|
||||
tableResult = InventorySlot(AIR, 0);
|
||||
// Wooden Axe Recipe
|
||||
// [P P .]
|
||||
// [P S .]
|
||||
// [. S .]
|
||||
if (tableSlots[0].blockType == PLANK && tableSlots[1].blockType == PLANK &&
|
||||
tableSlots[3].blockType == PLANK && tableSlots[4].blockType == STICK &&
|
||||
tableSlots[7].blockType == STICK) {
|
||||
tableResult = InventorySlot(WOOD_AXE, 1);
|
||||
}
|
||||
// Sticks (vertical anywhere)
|
||||
else if ((tableSlots[0].blockType == PLANK && tableSlots[3].blockType == PLANK) ||
|
||||
(tableSlots[1].blockType == PLANK && tableSlots[4].blockType == PLANK) ||
|
||||
(tableSlots[2].blockType == PLANK && tableSlots[5].blockType == PLANK) ||
|
||||
(tableSlots[3].blockType == PLANK && tableSlots[6].blockType == PLANK) ||
|
||||
(tableSlots[4].blockType == PLANK && tableSlots[7].blockType == PLANK) ||
|
||||
(tableSlots[5].blockType == PLANK && tableSlots[8].blockType == PLANK)) {
|
||||
tableResult = InventorySlot(STICK, 4);
|
||||
}
|
||||
// 4 Planks -> 1 Table (3x3 grid)
|
||||
else if (tableSlots[0].blockType == PLANK && tableSlots[1].blockType == PLANK &&
|
||||
tableSlots[3].blockType == PLANK && tableSlots[4].blockType == PLANK) {
|
||||
tableResult = InventorySlot(CRAFTING_TABLE, 1);
|
||||
}
|
||||
else {
|
||||
tableResult = InventorySlot(AIR, 0);
|
||||
}
|
||||
};
|
||||
// Block Selection State (for wireframe)
|
||||
bool hitBlock = false;
|
||||
|
|
@ -903,13 +942,41 @@ int main(void)
|
|||
}
|
||||
|
||||
if (hitBlock) {
|
||||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
|
||||
int targetBlock = GetBlock(hitX, hitY, hitZ);
|
||||
if (targetBlock != BEDROCK) {
|
||||
AddToInventory(targetBlock);
|
||||
SetBlock(hitX, hitY, hitZ, AIR);
|
||||
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) {
|
||||
if (hitX != lastHitX || hitY != lastHitY || hitZ != lastHitZ) {
|
||||
breakProgress = 0.0f;
|
||||
lastHitX = hitX; lastHitY = hitY; lastHitZ = hitZ;
|
||||
}
|
||||
} else if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) {
|
||||
|
||||
int targetBlock = GetBlock(hitX, hitY, hitZ);
|
||||
if (targetBlock != AIR && targetBlock != BEDROCK) {
|
||||
float breakSpeed = 2.0f; // Seconds to break
|
||||
|
||||
// Axe logic: Wood/Plank/Logs are faster
|
||||
if (targetBlock == LOG || targetBlock == PLANK || targetBlock == CRAFTING_TABLE) {
|
||||
if (hotbar[activeHotbarSlot].blockType == WOOD_AXE) breakSpeed = 0.5f; // Fast
|
||||
else breakSpeed = 1.5f; // Normal
|
||||
} else if (targetBlock == LEAVES) {
|
||||
breakSpeed = 0.2f; // Very fast
|
||||
}
|
||||
|
||||
breakProgress += GetFrameTime();
|
||||
|
||||
if (breakProgress >= breakSpeed) {
|
||||
AddToInventory(targetBlock);
|
||||
SetBlock(hitX, hitY, hitZ, AIR);
|
||||
breakProgress = 0.0f;
|
||||
isSwinging = true; // Swing when finishing
|
||||
}
|
||||
|
||||
// Visual swing while mining
|
||||
if (fmodf(breakProgress, 0.4f) < 0.1f) isSwinging = true;
|
||||
}
|
||||
} else {
|
||||
breakProgress = 0.0f;
|
||||
}
|
||||
|
||||
if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) {
|
||||
int targetBlock = GetBlock(hitX, hitY, hitZ);
|
||||
if (targetBlock == CRAFTING_TABLE) {
|
||||
currentState = CRAFTING_GUI;
|
||||
|
|
@ -922,6 +989,7 @@ int main(void)
|
|||
hotbar[activeHotbarSlot].count--;
|
||||
if (hotbar[activeHotbarSlot].count == 0)
|
||||
hotbar[activeHotbarSlot].blockType = AIR;
|
||||
isSwinging = true; // Swing when placing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -986,8 +1054,8 @@ int main(void)
|
|||
DrawTexturePro(titleTexture, sourceRec, destRec, origin, 0.0f, WHITE);
|
||||
EndMode2D();
|
||||
|
||||
// Show Version Number (v1.5.2) in Red
|
||||
DrawTextEx(customFont, "v1.5.2", (Vector2){ (float)currentWidth - 140, (float)currentHeight - 40 }, 22, 1.0f, RED);
|
||||
// Show Version Number (v1.6.1) in Red
|
||||
DrawTextEx(customFont, "v1.6.1", (Vector2){ (float)currentWidth - 140, (float)currentHeight - 40 }, 22, 1.0f, RED);
|
||||
}
|
||||
|
||||
Vector2 mousePos = GetMousePosition();
|
||||
|
|
@ -1417,7 +1485,7 @@ int main(void)
|
|||
}
|
||||
|
||||
// Draw Gameplay overlay if we entered gameplay
|
||||
if (currentState == GAMEPLAY || currentState == PAUSE_MENU) {
|
||||
if (currentState == GAMEPLAY || currentState == PAUSE_MENU || currentState == CRAFTING_GUI) {
|
||||
// ---- Day / Night Cycle Calculations ----
|
||||
float cycleLength = 300.0f; // 5 minutes
|
||||
float timeOfDay = fmodf(gameTime, cycleLength) / cycleLength;
|
||||
|
|
@ -1556,8 +1624,66 @@ int main(void)
|
|||
}
|
||||
}
|
||||
// Draw Block Selection Wireframe
|
||||
if (hitBlock && !inventoryOpen) {
|
||||
DrawCubeWires((Vector3){(float)hitX, (float)hitY, (float)hitZ}, 1.02f, 1.02f, 1.02f, BLACK);
|
||||
if (hitBlock && !inventoryOpen && currentState != CRAFTING_GUI) {
|
||||
float size = 1.02f;
|
||||
DrawCubeWires((Vector3){(float)hitX, (float)hitY, (float)hitZ}, size, size, size, BLACK);
|
||||
|
||||
// Draw breaking progress indicator
|
||||
// Draw breaking progress indicator
|
||||
if (breakProgress > 0.0f) {
|
||||
float pSize = (breakProgress / 1.5f) * 1.05f; // Scale visual based on progress
|
||||
if (pSize > 1.05f) pSize = 1.05f;
|
||||
DrawCubeWires((Vector3){(float)hitX, (float)hitY, (float)hitZ}, pSize, pSize, pSize, RED);
|
||||
}
|
||||
}
|
||||
|
||||
// --- DRAW VIEWMODEL (ARM/HELD ITEM) ---
|
||||
if (!inventoryOpen && currentState != CRAFTING_GUI) {
|
||||
if (isSwinging) {
|
||||
swingTime += GetFrameTime() * 8.0f;
|
||||
if (swingTime >= 1.0f) {
|
||||
swingTime = 0.0f;
|
||||
isSwinging = false;
|
||||
}
|
||||
}
|
||||
|
||||
float swingVal = sinf(swingTime * PI);
|
||||
|
||||
rlDisableDepthTest(); // Draw on top
|
||||
rlPushMatrix();
|
||||
// Transform to camera space manually for the viewmodel
|
||||
Vector3 forwardVM = Vector3Subtract(camera3D.target, camera3D.position);
|
||||
forwardVM = Vector3Normalize(forwardVM);
|
||||
Vector3 rightVM = Vector3CrossProduct(forwardVM, camera3D.up);
|
||||
rightVM = Vector3Normalize(rightVM);
|
||||
Vector3 upVM = Vector3CrossProduct(rightVM, forwardVM);
|
||||
upVM = Vector3Normalize(upVM);
|
||||
|
||||
Vector3 handPos = Vector3Add(camera3D.position, Vector3Scale(forwardVM, 0.4f));
|
||||
handPos = Vector3Add(handPos, Vector3Scale(rightVM, 0.25f));
|
||||
handPos = Vector3Add(handPos, Vector3Scale(upVM, -0.2f - swingVal * 0.1f));
|
||||
|
||||
// Draw Arm
|
||||
DrawCube(handPos, 0.08f, 0.2f, 0.08f, (Color){220, 180, 150, 255});
|
||||
|
||||
// Draw Held Item
|
||||
int heldBT = hotbar[activeHotbarSlot].blockType;
|
||||
if (heldBT != AIR) {
|
||||
Vector3 itemPos = Vector3Add(handPos, Vector3Scale(upVM, 0.1f));
|
||||
itemPos = Vector3Add(itemPos, Vector3Scale(forwardVM, 0.1f));
|
||||
|
||||
if (heldBT < STICK) {
|
||||
// Block
|
||||
DrawCube(itemPos, 0.15f, 0.15f, 0.15f, blockTint);
|
||||
DrawCubeWires(itemPos, 0.151f, 0.151f, 0.151f, BLACK);
|
||||
} else {
|
||||
// Item (Stick/Axe) - use small thin cube for now
|
||||
Color itemColor = (heldBT == STICK) ? BROWN : DARKGRAY;
|
||||
DrawCube(itemPos, 0.03f, 0.25f, 0.03f, itemColor);
|
||||
}
|
||||
}
|
||||
rlPopMatrix();
|
||||
rlEnableDepthTest();
|
||||
}
|
||||
|
||||
EndMode3D();
|
||||
|
|
@ -1662,6 +1788,10 @@ int main(void)
|
|||
Rectangle dst = { (float)(px+5),(float)(py+5), (float)(invSlotSize-10),(float)(invSlotSize-10) };
|
||||
Color tint = (bt == GRASS) ? (Color){124,189,107,255} : WHITE;
|
||||
DrawTexturePro(tex, src, dst, (Vector2){0,0}, 0.0f, tint);
|
||||
} else if (bt >= STICK) {
|
||||
// Fallback rendering for items if texture failed
|
||||
Color itemCol = (bt == STICK) ? BROWN : DARKGRAY;
|
||||
DrawRectangle(px + 10, py + 10, invSlotSize - 20, invSlotSize - 20, itemCol);
|
||||
}
|
||||
Vector2 cSize = MeasureTextEx(customFont, TextFormat("%i", slot.count), 12, 1.0f);
|
||||
DrawTextEx(customFont, TextFormat("%i", slot.count),
|
||||
|
|
|
|||
Loading…
Reference in New Issue