fixed resize but , controller support - audio - api added
This commit is contained in:
294
src/main.cpp
294
src/main.cpp
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user