#include "../Engine/Core/engine.h" #include "../Engine/Core/logger.h" #include "../Engine/Core/timer.h" #include "../Engine/Core/asset_manager.h" #include "../Engine/Rendering/graphics_device.h" #include "../Engine/Rendering/renderer.h" #include "../Engine/Rendering/shader.h" #include "../Engine/Rendering/mesh.h" #include "../Engine/Rendering/material.h" #include "../Engine/Rendering/texture.h" #include "../Engine/Rendering/camera.h" #include "../Engine/Scene/scene_graph.h" #include "../Engine/Scene/scene_render.h" #include "../Engine/include/engine_api.h" #include "../Engine/ASM/math_c_fallback.h" #include #include #include #include #include static Scene* g_scene = NULL; static AssetManager* g_assets = NULL; static Asset* g_shader_asset = NULL; static Camera g_camera; static int g_mouse_down[3] = {0}; static int g_last_mx = 0, g_last_my = 0, g_mouse_first = 1; static float player_x = 0, player_z = -8, player_y = 0; static float cam_yaw = 0, cam_pitch = 0.3f, cam_dist = 6.0f, cam_height = 3.0f; static SceneNode* g_player = NULL; static float player_vy = 0; static int g_ground = 1; static SceneNode* mknode(Scene* s, SceneNode* p, AssetManager* am, ID3D11Device* dev, const char* name, MeshType mt, Vec3 pos, Vec3 scl, Material* mat) { SceneNode* n = scene_create_node(s, name); if (!n) return NULL; if (p) scene_set_parent(n, p); n->position = pos; n->scale = scl; Asset* ma = asset_manager_load_mesh(am, dev, name); if (!ma) { const char* b = mt == MESH_CUBE ? "cube" : mt == MESH_SPHERE ? "sphere" : "plane"; ma = asset_manager_load_mesh(am, dev, b); } if (ma && mat) { MeshRenderer* mr = mesh_renderer_create(mt, (Mesh*)asset_data(ma), mat); scene_node_set_mesh_renderer(n, mr); } return n; } static Scene* create_world(AssetManager* am, ID3D11Device* dev) { Scene* scene = (Scene*)malloc(sizeof(Scene)); if (!scene) return NULL; scene_init(scene); SceneNode* root = scene->root; root->name[0] = '\0'; strncpy(root->name, "root", sizeof(root->name) - 1); Shader* sh = (Shader*)asset_data(g_shader_asset); Material* m_green = material_create(sh, NULL); m_green->color = (Vec4){0.25f, 0.55f, 0.2f, 1}; Material* m_dkgrn = material_create(sh, NULL); m_dkgrn->color = (Vec4){0.15f, 0.4f, 0.12f, 1}; Material* m_brown = material_create(sh, NULL); m_brown->color = (Vec4){0.45f, 0.28f, 0.15f, 1}; Material* m_stone = material_create(sh, NULL); m_stone->color = (Vec4){0.5f, 0.5f, 0.5f, 1}; Material* m_dstone = material_create(sh, NULL); m_dstone->color = (Vec4){0.35f, 0.35f, 0.38f, 1}; Material* m_red = material_create(sh, NULL); m_red->color = (Vec4){0.8f, 0.2f, 0.15f, 1}; Material* m_blue = material_create(sh, NULL); m_blue->color = (Vec4){0.2f, 0.4f, 0.8f, 1}; Material* m_yellow = material_create(sh, NULL); m_yellow->color = (Vec4){0.85f, 0.75f, 0.2f, 1}; Material* m_white = material_create(sh, NULL); m_white->color = (Vec4){0.85f, 0.85f, 0.85f, 1}; Material* m_water = material_create(sh, NULL); m_water->color = (Vec4){0.15f, 0.3f, 0.6f, 0.8f}; Material* m_orange = material_create(sh, NULL); m_orange->color = (Vec4){0.9f, 0.5f, 0.1f, 1}; Material* m_purple = material_create(sh, NULL); m_purple->color = (Vec4){0.5f, 0.15f, 0.6f, 1}; Material* m_player = material_create(sh, NULL); m_player->color = (Vec4){0.1f, 0.8f, 0.3f, 1}; Material* m_path = material_create(sh, NULL); m_path->color = (Vec4){0.6f, 0.55f, 0.45f, 1}; Material* m_hill = material_create(sh, NULL); m_hill->color = (Vec4){0.2f, 0.4f, 0.18f, 1}; Material* m_flower = material_create(sh, NULL); m_flower->color = (Vec4){0.9f, 0.2f, 0.4f, 1}; mknode(scene, root, am, dev, "ground", MESH_PLANE, (Vec3){0, -0.01f, 0}, (Vec3){40, 1, 40}, m_green); g_player = mknode(scene, root, am, dev, "player", MESH_CUBE, (Vec3){player_x, 0.4f, player_z}, (Vec3){0.3f, 0.8f, 0.3f}, m_player); // 村庄 mknode(scene, root, am, dev, "house1", MESH_CUBE, (Vec3){-5, 1, -5}, (Vec3){2, 2, 2}, m_red); mknode(scene, root, am, dev, "house2", MESH_CUBE, (Vec3){-2, 1.25f, -8}, (Vec3){2.5f, 2.5f, 2}, m_blue); mknode(scene, root, am, dev, "house3", MESH_CUBE, (Vec3){1, 0.9f, -6}, (Vec3){1.8f, 1.8f, 1.8f}, m_yellow); mknode(scene, root, am, dev, "tower", MESH_CUBE, (Vec3){-7, 1.5f, -2}, (Vec3){1.5f, 3, 1.5f}, m_white); mknode(scene, root, am, dev, "house4", MESH_CUBE, (Vec3){4, 1, -4}, (Vec3){2, 2, 2}, m_orange); // 屋顶 mknode(scene, root, am, dev, "roof1", MESH_CUBE, (Vec3){-5, 2.15f, -5}, (Vec3){2.3f, 0.3f, 2.3f}, m_dstone); mknode(scene, root, am, dev, "roof2", MESH_CUBE, (Vec3){-2, 2.65f, -8}, (Vec3){2.8f, 0.3f, 2.3f}, m_dstone); mknode(scene, root, am, dev, "roof3", MESH_CUBE, (Vec3){1, 2.0f, -6}, (Vec3){2.1f, 0.3f, 2.1f}, m_brown); mknode(scene, root, am, dev, "roof4", MESH_CUBE, (Vec3){4, 2.15f, -4}, (Vec3){2.3f, 0.3f, 2.3f}, m_brown); // 树木 float trees[][2] = {{-12,3},{-10,5},{-8,8},{-6,10},{-3,12},{2,14},{5,10},{8,7},{10,4},{12,2}, {-14,-1},{-12,-6},{-10,-10},{8,-8},{12,-5},{15,8},{-15,12},{0,18},{-5,15},{10,15}, {-8,-14},{5,-12},{12,-10},{-14,6},{14,-2},{3,8},{-2,10},{7,12},{-11,8},{9,3}}; for (int i = 0; i < 30; i++) { float x = trees[i][0], z = trees[i][1]; mknode(scene, root, am, dev, "trunk", MESH_CUBE, (Vec3){x, 0.5f, z}, (Vec3){0.2f, 1, 0.2f}, m_brown); mknode(scene, root, am, dev, "leaves", MESH_SPHERE, (Vec3){x, 1.8f, z}, (Vec3){0.8f, 0.7f, 0.8f}, m_dkgrn); } // 岩石 float rocks[][3] = {{6,-2,0.6f},{-9,2,0.4f},{10,10,0.8f},{-6,-12,0.5f},{14,6,0.7f},{-13,-8,0.3f},{3,-10,0.5f},{-4,14,0.4f},{11,-8,0.6f}}; for (int i = 0; i < 9; i++) mknode(scene, root, am, dev, "rock", MESH_SPHERE, (Vec3){rocks[i][0], rocks[i][2]*0.3f, rocks[i][1]}, (Vec3){rocks[i][2], rocks[i][2]*0.6f, rocks[i][2]}, m_stone); // 水塘 mknode(scene, root, am, dev, "water", MESH_PLANE, (Vec3){-10, 0.02f, -4}, (Vec3){3, 1, 3}, m_water); // 小路 for (float tz = -10; tz <= 2; tz += 1.5f) mknode(scene, root, am, dev, "path", MESH_PLANE, (Vec3){0, 0.01f, tz}, (Vec3){0.6f, 1, 0.4f}, m_path); // 山丘 mknode(scene, root, am, dev, "hill1", MESH_SPHERE, (Vec3){-18, -0.5f, 15}, (Vec3){8, 3, 8}, m_hill); mknode(scene, root, am, dev, "hill2", MESH_SPHERE, (Vec3){20, -0.8f, 12}, (Vec3){10, 4, 10}, m_hill); mknode(scene, root, am, dev, "hill3", MESH_SPHERE, (Vec3){0, -0.3f, 22}, (Vec3){12, 3, 8}, m_hill); // 花 float flowers[][2] = {{-3,-2},{-1,-3},{2,-1},{-4,0},{3,1}}; for (int i = 0; i < 5; i++) mknode(scene, root, am, dev, "flower", MESH_SPHERE, (Vec3){flowers[i][0], 0.15f, flowers[i][1]}, (Vec3){0.1f, 0.1f, 0.1f}, m_flower); scene_update(scene); return scene; } static void on_render(Engine* engine) { Renderer* r = engine_get_renderer(engine); GraphicsDevice* dev = engine_get_graphics_device(engine); if (!r || !dev || !g_scene) return; renderer_set_view(r, camera_get_view(&g_camera)); renderer_set_projection(r, camera_get_projection(&g_camera)); renderer_begin_frame(r); scene_update(g_scene); scene_render(g_scene, r); renderer_end_frame(r); } static void update_camera(void) { g_camera.position = (Vec3){ player_x - sinf(cam_yaw) * cam_dist, cam_height + sinf(cam_pitch) * cam_dist * 0.5f, player_z - cosf(cam_yaw) * cam_dist }; g_camera.target = (Vec3){player_x, 0.5f, player_z}; g_camera.dirty = 1; } static void on_update(Engine* engine, double dt) { (void)engine; float fdt = (float)dt; float spd = (GetAsyncKeyState(VK_SHIFT) & 0x8000) ? 10.0f * fdt : 5.0f * fdt; float fwd_x = sinf(cam_yaw), fwd_z = cosf(cam_yaw); float rgt_x = cosf(cam_yaw), rgt_z = -sinf(cam_yaw); if (GetAsyncKeyState('W') & 0x8000) { player_x += fwd_x * spd; player_z += fwd_z * spd; } if (GetAsyncKeyState('S') & 0x8000) { player_x -= fwd_x * spd; player_z -= fwd_z * spd; } if (GetAsyncKeyState('A') & 0x8000) { player_x -= rgt_x * spd; player_z -= rgt_z * spd; } if (GetAsyncKeyState('D') & 0x8000) { player_x += rgt_x * spd; player_z += rgt_z * spd; } if (GetAsyncKeyState('Q') & 0x8000) cam_yaw -= 2.0f * fdt; if (GetAsyncKeyState('E') & 0x8000) cam_yaw += 2.0f * fdt; if ((GetAsyncKeyState(VK_SPACE) & 0x8000) && g_ground) { player_vy = 8.0f; g_ground = 0; } player_vy -= 20.0f * fdt; player_y += player_vy * fdt; if (player_y < 0) { player_y = 0; player_vy = 0; g_ground = 1; } if (player_x < -19) player_x = -19; if (player_x > 19) player_x = 19; if (player_z < -19) player_z = -19; if (player_z > 21) player_z = 21; if (g_player) { g_player->position.x = player_x; g_player->position.y = 0.4f + player_y; g_player->position.z = player_z; quat_from_euler(0, cam_yaw, 0, &g_player->rotation); g_player->dirty = 1; } update_camera(); } static void on_key(Engine* engine, int key) { if (key == VK_ESCAPE) engine_request_quit(engine); } static void on_mouse_move(Engine* engine, int x, int y) { (void)engine; if (g_mouse_down[0]) { if (g_mouse_first) { g_last_mx = x; g_last_my = y; g_mouse_first = 0; } else { cam_yaw += (float)(x - g_last_mx) * 0.005f; cam_pitch += (float)(y - g_last_my) * 0.003f; if (cam_pitch > 1.2f) cam_pitch = 1.2f; if (cam_pitch < -0.2f) cam_pitch = -0.2f; g_last_mx = x; g_last_my = y; update_camera(); } } else { g_mouse_first = 1; } } static void on_mouse_button(Engine* engine, int button, int pressed) { (void)engine; if (button >= 0 && button < 3) g_mouse_down[button] = pressed; } static void on_resize(Engine* engine, int width, int height) { Renderer* r = engine_get_renderer(engine); if (r && width > 0 && height > 0) { renderer_resize(r, width, height); g_camera.aspect = (float)width / (float)height; g_camera.dirty = 1; } } int main(int argc, char* argv[]) { (void)argc; (void)argv; EngineConfig config = engine_default_config(); config.app_name = "Lity Explorer"; config.vsync = 0; config.window_width = 1280; config.window_height = 720; Engine* engine = engine_create(); if (!engine_init(engine, &config)) { LOG_FATAL("Init failed"); return -1; } GraphicsDevice* dev = engine_get_graphics_device(engine); Renderer* r = engine_get_renderer(engine); g_assets = asset_manager_create(); g_shader_asset = asset_manager_load_shader(g_assets, dev->device, NULL, NULL); if (!g_shader_asset) { LOG_FATAL("Shader failed"); return -1; } g_scene = create_world(g_assets, dev->device); float aspect = (float)config.window_width / config.window_height; g_camera = camera_perspective(1.0472f, aspect, 0.1f, 200.0f); g_camera.position = (Vec3){0, cam_height, -8 - cam_dist}; g_camera.target = (Vec3){0, 0.5f, -8}; g_camera.dirty = 1; engine_set_update_callback(engine, on_update); engine_set_render_callback(engine, on_render); engine_set_key_callback(engine, on_key); engine_set_mouse_move_callback(engine, on_mouse_move); engine_set_mouse_button_callback(engine, on_mouse_button); engine_set_resize_callback(engine, on_resize); LOG_INFO("Lity Explorer started!"); engine_run(engine); scene_destroy_renderers(g_scene); scene_destroy(g_scene); free(g_scene); asset_manager_destroy(g_assets); engine_shutdown(engine); return 0; }