added inventory & active object

This commit is contained in:
Vlad committed 2026-04-09 15:33:55 +06:00
1 parent e1b491be73
commit b3fda88784
16 files changed
+793 -98

No files matched your search

+134 -32
View File
@@ -148,34 +148,11 @@ namespace ZL
roomMesh.RefreshVBO();
std::cout << "Load resurces step 5" << std::endl;
// Load static game objects
gameObjects = GameObjectLoader::loadAndCreateGameObjects("resources/config2/gameobjects.json", renderer, CONST_ZIP_FILE);
/*
std::cout << "Load resurces step 5" << std::endl;
fireboxTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/w/Cube001.png", CONST_ZIP_FILE));
fireboxMesh.data = LoadFromTextFile02("resources/w/firebox.txt", CONST_ZIP_FILE);
fireboxMesh.data.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI * 0.5, Eigen::Vector3f::UnitY())).toRotationMatrix());
fireboxMesh.RefreshVBO();
std::cout << "Load resurces step 6" << std::endl;
inaiTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/w/inai001.png", CONST_ZIP_FILE));
std::cout << "Load resurces step 6.1" << std::endl;
inaiMesh.data = LoadFromTextFile02("resources/w/inai001.txt", CONST_ZIP_FILE);
inaiMesh.data.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI * 0.5, Eigen::Vector3f::UnitY())).toRotationMatrix());
inaiMesh.data.Move({ 2.5, 1.4, -9.9 });
inaiMesh.RefreshVBO();
std::cout << "Load resurces step 7" << std::endl;
benchTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/w/bench001opt.png", CONST_ZIP_FILE));
benchMesh.data = LoadFromTextFile02("resources/w/bench002opt.txt", CONST_ZIP_FILE);
benchMesh.data.Scale(3.f);
benchMesh.data.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY())).toRotationMatrix());
benchMesh.data.Move({ -2.1, 0.5, -7.9 });
benchMesh.RefreshVBO();
*/
std::cout << "Load resurces step 8" << std::endl;
// Load interactive objects
interactiveObjects = GameObjectLoader::loadAndCreateInteractiveObjects("resources/config2/gameobjects.json", renderer, CONST_ZIP_FILE);
auto violaTexture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/viola.png", CONST_ZIP_FILE));
@@ -236,8 +213,91 @@ namespace ZL
scriptEngine.init(this);
std::cout << "Load resurces step 13" << std::endl;
// Load UI with inventory button
try {
menuManager.uiManager.loadFromFile("resources/config2/ui_inventory.json", renderer, CONST_ZIP_FILE);
std::cout << "UI loaded successfully" << std::endl;
menuManager.uiManager.setNodeVisible("inventory_items_panel", false);
menuManager.uiManager.setNodeVisible("close_inventory_button", false);
menuManager.uiManager.setTextButtonCallback("inventory_button", [this](const std::string& name) {
std::cout << "[UI] Inventory button clicked" << std::endl;
//scriptEngine.callItemPickupCallback("toggle_inventory");
scriptEngine.showInventory(this);
//scriptEngine
//scriptEngine
});
menuManager.uiManager.setTextButtonCallback("close_inventory_button", [this](const std::string& name) {
std::cout << "[UI] Close button clicked" << std::endl;
menuManager.uiManager.setNodeVisible("inventory_items_panel", false);
menuManager.uiManager.setNodeVisible("close_inventory_button", false);
inventoryOpen = false;
});
}
catch (const std::exception& e) {
std::cerr << "Failed to load UI: " << e.what() << std::endl;
}
}
InteractiveObject* Game::raycastInteractiveObjects(const Eigen::Vector3f& rayOrigin, const Eigen::Vector3f& rayDir) {
if (interactiveObjects.empty()) {
std::cout << "[RAYCAST] No interactive objects to check" << std::endl;
return nullptr;
}
std::cout << "[RAYCAST] Starting raycast with " << interactiveObjects.size() << " objects" << std::endl;
std::cout << "[RAYCAST] Ray origin: (" << rayOrigin.x() << ", " << rayOrigin.y() << ", " << rayOrigin.z() << ")" << std::endl;
std::cout << "[RAYCAST] Ray dir: (" << rayDir.x() << ", " << rayDir.y() << ", " << rayDir.z() << ")" << std::endl;
float closestDistance = FLT_MAX;
InteractiveObject* closestObject = nullptr;
for (auto& intObj : interactiveObjects) {
std::cout << "[RAYCAST] Checking object: " << intObj.name << " (active: " << intObj.isActive << ")" << std::endl;
if (!intObj.isActive) {
std::cout << "[RAYCAST] -> Object inactive, skipping" << std::endl;
continue;
}
std::cout << "[RAYCAST] Position: (" << intObj.position.x() << ", " << intObj.position.y() << ", "
<< intObj.position.z() << "), Radius: " << intObj.interactionRadius << std::endl;
Eigen::Vector3f toObject = intObj.position - rayOrigin;
std::cout << "[RAYCAST] Vector to object: (" << toObject.x() << ", " << toObject.y() << ", " << toObject.z() << ")" << std::endl;
float distanceAlongRay = toObject.dot(rayDir);
std::cout << "[RAYCAST] Distance along ray: " << distanceAlongRay << std::endl;
if (distanceAlongRay < 0.1f) {
std::cout << "[RAYCAST] -> Object behind camera, skipping" << std::endl;
continue;
}
Eigen::Vector3f closestPointOnRay = rayOrigin + rayDir * distanceAlongRay;
float distToObject = (closestPointOnRay - intObj.position).norm();
std::cout << "[RAYCAST] Distance to object: " << distToObject
<< " (interaction radius: " << intObj.interactionRadius << ")" << std::endl;
if (distToObject <= intObj.interactionRadius && distanceAlongRay < closestDistance) {
std::cout << "[RAYCAST] *** HIT DETECTED! ***" << std::endl;
closestDistance = distanceAlongRay;
closestObject = &intObj;
}
}
if (closestObject) {
std::cout << "[RAYCAST] *** RAYCAST SUCCESS: Found object " << closestObject->name << " ***" << std::endl;
} else {
std::cout << "[RAYCAST] No objects hit" << std::endl;
}
return closestObject;
}
void Game::drawUI()
{
@@ -291,6 +351,11 @@ namespace ZL
glBindTexture(GL_TEXTURE_2D, benchTexture->getTexID());
renderer.DrawVertexRenderStruct(benchMesh);
*/
for (auto& intObj : interactiveObjects) {
if (intObj.isActive) {
intObj.draw(renderer);
}
}
if (player) player->draw(renderer);
for (auto& npc : npcs) npc->draw(renderer);
@@ -374,9 +439,23 @@ namespace ZL
if (player) player->update(delta);
for (auto& npc : npcs) npc->update(delta);
// Check if player reached target interactive object
if (targetInteractiveObject && player) {
float distToObject = (player->position - targetInteractiveObject->position).norm();
// If player is close enough to pick up the item
if (distToObject <= targetInteractiveObject->interactionRadius + 1.0f) {
std::cout << "[PICKUP] Player reached object! Distance: " << distToObject << std::endl;
std::cout << "[PICKUP] Calling Lua callback for: " << targetInteractiveObject->id << std::endl;
// Call Lua callback
scriptEngine.callItemPickupCallback(targetInteractiveObject->id);
targetInteractiveObject = nullptr;
}
}
}
}
void Game::render() {
@@ -456,13 +535,14 @@ namespace ZL
if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) {
if (event.button.button == SDL_BUTTON_LEFT) {
// Преобразуем экранные пиксели в проекционные единицы
int mx = static_cast<int>((float)event.button.x / Environment::width * Environment::projectionWidth);
int my = static_cast<int>((float)event.button.y / Environment::height * Environment::projectionHeight);
if (event.type == SDL_MOUSEBUTTONDOWN) {
std::cout << "\n========== MOUSE DOWN EVENT ==========" << std::endl;
handleDown(ZL::UiManager::MOUSE_FINGER_ID, mx, my);
// Unproject click to ground plane (y=0) for Viola's walk target
// Calculate ray for picking
float ndcX = 2.0f * event.button.x / Environment::width - 1.0f;
float ndcY = 1.0f - 2.0f * event.button.y / Environment::height;
float aspect = (float)Environment::width / (float)Environment::height;
@@ -479,11 +559,33 @@ namespace ZL
Eigen::Vector3f rayDir = (camForward + camRight * (ndcX * aspect * tanHalfFov) + camUp * (ndcY * tanHalfFov)).normalized();
if (rayDir.y() < -0.001f && player) {
std::cout << "[CLICK] Camera position: (" << camPos.x() << ", " << camPos.y() << ", " << camPos.z() << ")" << std::endl;
std::cout << "[CLICK] Ray direction: (" << rayDir.x() << ", " << rayDir.y() << ", " << rayDir.z() << ")" << std::endl;
// First check if we clicked on interactive object
InteractiveObject* clickedObject = raycastInteractiveObjects(camPos, rayDir);
if (clickedObject && player && clickedObject->isActive) {
std::cout << "[CLICK] *** SUCCESS: Clicked on interactive object: " << clickedObject->name << " ***" << std::endl;
std::cout << "[CLICK] Object position: (" << clickedObject->position.x() << ", "
<< clickedObject->position.y() << ", " << clickedObject->position.z() << ")" << std::endl;
std::cout << "[CLICK] Player position: (" << player->position.x() << ", "
<< player->position.y() << ", " << player->position.z() << ")" << std::endl;
targetInteractiveObject = clickedObject;
player->setTarget(clickedObject->position);
std::cout << "[CLICK] Player moving to object..." << std::endl;
}
else if (rayDir.y() < -0.001f && player) {
// Otherwise, unproject click to ground plane for Viola's walk target
float t = -camPos.y() / rayDir.y();
Eigen::Vector3f hit = camPos + rayDir * t;
std::cout << "[CLICK] Clicked on ground at: (" << hit.x() << ", " << hit.z() << ")" << std::endl;
player->setTarget(Eigen::Vector3f(hit.x(), 0.f, hit.z()));
}
else {
std::cout << "[CLICK] No valid target found" << std::endl;
}
std::cout << "========================================\n" << std::endl;
} else {
handleUp(ZL::UiManager::MOUSE_FINGER_ID, mx, my);
}