fixed resize but , controller support - audio - api added

This commit is contained in:
will
2026-04-11 16:37:20 +01:00
parent 97e9611b33
commit 65771dbcf8
68 changed files with 44863 additions and 37111 deletions

View File

@@ -1,4 +1,7 @@
#include "Engine.h"
#include "Input.h"
#include "Json.h"
#include "MainMenu.h"
#include "LevelEditor.cpp"
#include <iostream>
#include <random>
@@ -456,52 +459,263 @@ public:
// ---------------------------------------------
// main: choose demo, stress, or monkey by arg
// LandscapeDemo: large terrain with trees, rocks
// Full PS4/PS5 controller + keyboard camera
// ---------------------------------------------
class LandscapeDemo : public Engine {
private:
float time_ = 0.0f;
// Free-fly camera state
float cam_yaw_ = -90.0f;
float cam_pitch_ = 15.0f;
glm::vec3 cam_pos_{0.0f, 20.0f, 40.0f};
float cam_speed_ = 20.0f;
float look_sensitivity_ = 80.0f;
std::mt19937 rng_{42};
public:
LandscapeDemo()
: Engine(1920, 1080, "ZoomEngine - Landscape (Gamepad + Keyboard)") {}
bool OnInitialize() override {
std::cout << "Generating landscape..." << std::endl;
// Large terrain
auto terrain = CreateTerrain(128, 200.0f, 10.0f);
auto terrainObj = CreateGameObject(terrain, glm::vec3(0, 0, 0));
AddGameObject(terrainObj);
// Scatter trees (cylinder trunk + cone foliage)
auto trunk_prim = CreateCylinder(0.3f, 3.0f, 8, glm::vec3(0.4f, 0.25f, 0.1f));
auto leaves_prim = CreateCone(1.5f, 3.0f, 8, glm::vec3(0.15f, 0.45f, 0.1f));
auto leaves_prim2 = CreateCone(1.2f, 2.5f, 8, glm::vec3(0.1f, 0.55f, 0.12f));
std::uniform_real_distribution<float> pos_dist(-80.0f, 80.0f);
std::uniform_real_distribution<float> scale_dist(0.7f, 1.5f);
for (int i = 0; i < 120; ++i) {
float x = pos_dist(rng_);
float z = pos_dist(rng_);
// Approximate terrain height at this position
float h = 0.0f;
h += std::sin(x * 0.1f) * std::cos(z * 0.1f) * 5.0f;
h += std::sin(x * 0.25f + 1.3f) * std::cos(z * 0.3f + 0.7f) * 2.5f;
h += std::sin(x * 0.6f + 2.1f) * std::cos(z * 0.5f + 1.5f) * 1.25f;
float s = scale_dist(rng_);
// Trunk
auto t = CreateGameObject(trunk_prim, glm::vec3(x, h + 1.5f * s, z));
t->SetScale(glm::vec3(s, s, s));
AddGameObject(t);
// Lower foliage
auto f1 = CreateGameObject(leaves_prim, glm::vec3(x, h + 4.0f * s, z));
f1->SetScale(glm::vec3(s, s, s));
AddGameObject(f1);
// Upper foliage
auto f2 = CreateGameObject(leaves_prim2, glm::vec3(x, h + 5.5f * s, z));
f2->SetScale(glm::vec3(s * 0.8f, s * 0.8f, s * 0.8f));
AddGameObject(f2);
}
// Scatter rocks (spheres squished flat)
auto rock_prim = CreateSphere(8, glm::vec3(0.45f, 0.42f, 0.4f));
std::uniform_real_distribution<float> rock_scale(0.4f, 1.2f);
for (int i = 0; i < 60; ++i) {
float x = pos_dist(rng_);
float z = pos_dist(rng_);
float h = 0.0f;
h += std::sin(x * 0.1f) * std::cos(z * 0.1f) * 5.0f;
h += std::sin(x * 0.25f + 1.3f) * std::cos(z * 0.3f + 0.7f) * 2.5f;
float rs = rock_scale(rng_);
auto r = CreateGameObject(rock_prim, glm::vec3(x, h + rs * 0.3f, z));
r->SetScale(glm::vec3(rs, rs * 0.5f, rs));
AddGameObject(r);
}
std::cout << "Landscape ready: " << game_objects_.size() << " objects" << std::endl;
std::cout << "Controls:" << std::endl;
std::cout << " Gamepad: Left stick = move, Right stick = look" << std::endl;
std::cout << " R2 = up, L2 = down, Cross = sprint" << std::endl;
std::cout << " Keyboard: WASD = move, Arrow keys = look, Space/Shift = up/down" << std::endl;
return true;
}
void OnUpdate(float dt) override {
time_ += dt;
float speed = cam_speed_;
// --- Gamepad camera ---
if (Input::IsGamepadConnected()) {
// Sprint with Cross
if (Input::IsGamepadButtonDown(Input::GamepadButton::Cross))
speed *= 3.0f;
// Left stick: move forward/back + strafe
glm::vec2 ls = Input::GetLeftStick();
// Right stick: look
glm::vec2 rs = Input::GetRightStick();
cam_yaw_ += rs.x * look_sensitivity_ * dt;
cam_pitch_ -= rs.y * look_sensitivity_ * dt;
if (cam_pitch_ > 89.0f) cam_pitch_ = 89.0f;
if (cam_pitch_ < -89.0f) cam_pitch_ = -89.0f;
glm::vec3 forward;
forward.x = std::cos(glm::radians(cam_yaw_)) * std::cos(glm::radians(cam_pitch_));
forward.y = std::sin(glm::radians(cam_pitch_));
forward.z = std::sin(glm::radians(cam_yaw_)) * std::cos(glm::radians(cam_pitch_));
forward = glm::normalize(forward);
glm::vec3 right = glm::normalize(glm::cross(forward, glm::vec3(0, 1, 0)));
cam_pos_ += forward * (-ls.y) * speed * dt;
cam_pos_ += right * ls.x * speed * dt;
// Triggers for vertical movement
cam_pos_.y += Input::GetR2() * speed * dt;
cam_pos_.y -= Input::GetL2() * speed * dt;
}
// --- Keyboard camera ---
{
float kspeed = speed;
if (Input::IsKeyHeld(GLFW_KEY_LEFT_SHIFT)) kspeed *= 3.0f;
if (Input::IsKeyHeld(GLFW_KEY_LEFT)) cam_yaw_ -= look_sensitivity_ * dt;
if (Input::IsKeyHeld(GLFW_KEY_RIGHT)) cam_yaw_ += look_sensitivity_ * dt;
if (Input::IsKeyHeld(GLFW_KEY_UP)) cam_pitch_ += look_sensitivity_ * dt;
if (Input::IsKeyHeld(GLFW_KEY_DOWN)) cam_pitch_ -= look_sensitivity_ * dt;
if (cam_pitch_ > 89.0f) cam_pitch_ = 89.0f;
if (cam_pitch_ < -89.0f) cam_pitch_ = -89.0f;
glm::vec3 forward;
forward.x = std::cos(glm::radians(cam_yaw_)) * std::cos(glm::radians(cam_pitch_));
forward.y = std::sin(glm::radians(cam_pitch_));
forward.z = std::sin(glm::radians(cam_yaw_)) * std::cos(glm::radians(cam_pitch_));
forward = glm::normalize(forward);
glm::vec3 right = glm::normalize(glm::cross(forward, glm::vec3(0, 1, 0)));
if (Input::IsKeyHeld(GLFW_KEY_W)) cam_pos_ += forward * kspeed * dt;
if (Input::IsKeyHeld(GLFW_KEY_S)) cam_pos_ -= forward * kspeed * dt;
if (Input::IsKeyHeld(GLFW_KEY_A)) cam_pos_ -= right * kspeed * dt;
if (Input::IsKeyHeld(GLFW_KEY_D)) cam_pos_ += right * kspeed * dt;
if (Input::IsKeyHeld(GLFW_KEY_SPACE)) cam_pos_.y += kspeed * dt;
if (Input::IsKeyHeld(GLFW_KEY_LEFT_CONTROL)) cam_pos_.y -= kspeed * dt;
}
// Apply camera
glm::vec3 forward;
forward.x = std::cos(glm::radians(cam_yaw_)) * std::cos(glm::radians(cam_pitch_));
forward.y = std::sin(glm::radians(cam_pitch_));
forward.z = std::sin(glm::radians(cam_yaw_)) * std::cos(glm::radians(cam_pitch_));
SetCameraPosition(cam_pos_);
SetCameraTarget(cam_pos_ + glm::normalize(forward));
}
};
// ---------------------------------------------
// Launch a scene by action string
// ---------------------------------------------
static void runScene(const std::string& mode) {
if (mode == "stress") {
std::cout << "Running Stress Test..." << std::endl;
StressTest demo;
demo.Run();
}
else if (mode == "monkeygrid") {
std::cout << "Starting Monkey Grid Demo..." << std::endl;
MonkeyGridDemo demo;
demo.Run();
}
else if (mode == "edit") {
std::cout << "Starting Zoom Level Editor..." << std::endl;
LevelEditor edit;
edit.Run();
}
else if (mode == "landscape") {
std::cout << "Starting Landscape Demo..." << std::endl;
LandscapeDemo demo;
demo.Run();
}
else if (mode == "monkey") {
SpinningMonkey demo;
demo.Run();
}
else {
std::cout << "Starting Scene Demo..." << std::endl;
SceneDemo demo;
demo.Run();
}
}
// ---------------------------------------------
// main: menu (default) or direct scene by arg
// ---------------------------------------------
int main(int argc, char** argv) {
try {
std::string mode = (argc > 1) ? std::string(argv[1]) : "demo";
if (mode == "stress") {
std::cout << "Running Stress Test..." << std::endl;
StressTest demo;
demo.Run();
return 0;
// Direct launch: ./ModernEngine <scene>
if (argc > 1) {
std::string mode = argv[1];
if (mode != "menu") {
runScene(mode);
return 0;
}
}
}
else if (mode == "monkeygrid") {
std::cout << "Starting Monkey Grid Demo..." << std::endl;
MonkeyGridDemo demo;
demo.Run();
return 0;
// Menu mode: load JSON config and show interactive menu
// Try assets/menu.json, then fall back to built-in default
json::Value menuConfig;
try {
menuConfig = json::parseFile("../assets/menu.json");
std::cout << "Loaded menu from assets/menu.json" << std::endl;
} catch (...) {
try {
menuConfig = json::parseFile("assets/menu.json");
std::cout << "Loaded menu from assets/menu.json" << std::endl;
} catch (...) {
// Built-in fallback
menuConfig = json::parse(R"({
"title": "ZOOMENGINE",
"background_color": [0.04, 0.04, 0.1],
"title_color": [1.0, 0.85, 0.2],
"item_color": [0.65, 0.65, 0.7],
"selected_color": [1.0, 1.0, 0.3],
"items": [
{ "label": "Landscape", "action": "landscape" },
{ "label": "Scene Demo", "action": "demo" },
{ "label": "Stress Test", "action": "stress" },
{ "label": "Spinning Monkey", "action": "monkey" },
{ "label": "Monkey Grid", "action": "monkeygrid" },
{ "label": "Level Editor", "action": "edit" },
{ "label": "Quit", "action": "quit" }
]
})");
std::cout << "Using built-in menu config" << std::endl;
}
}
else if (mode == "edit") {
std::cout << "Starting Zoom Level Editor ..." << std::endl;
LevelEditor edit;
edit.Run();
return 0;
// Menu loop: show menu, launch scene, return to menu
while (true) {
std::string action;
{
MainMenu menu(menuConfig, [&](const std::string& a) { action = a; });
menu.Run();
action = menu.getSelectedAction();
}
if (action.empty() || action == "quit")
break;
// GLFW needs re-init after the menu window closes
glfwTerminate();
runScene(action);
// After scene exits, GLFW terminates — loop back to re-show menu
glfwTerminate();
}
else if (mode == "monkey") {
std::cout << "🐵 Starting Spinning Monkey Demo..." << std::endl;
std::cout << "====================================" << std::endl;
std::cout << "Place your monkey.obj in models/ folder" << std::endl;
std::cout << "Optionally add monkey.bmp in textures/ folder" << std::endl;
std::cout << "====================================" << std::endl;
SpinningMonkey demo;
demo.Run();
std::cout << "====================================" << std::endl;
std::cout << "Monkey demo completed successfully! 🐵" << std::endl;
return 0;
} else {
std::cout << "Starting Modern C++ Engine Scene Demo..." << std::endl;
std::cout << "=========================================" << std::endl;
SceneDemo demo;
demo.Run();
std::cout << "=========================================" << std::endl;
std::cout << "Demo completed successfully!" << std::endl;
return 0;
}
return 0;
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return -1;