如何在Raylib中实现3D玩家立方体45度横向旋转?
实现立方体横向45度转向的Raylib解决方案
针对你的需求,只需在现有代码基础上添加Y轴旋转角度记录、转向输入处理,并替换绘制函数实现定向渲染即可,具体步骤如下:
1. 扩展Player结构体,添加旋转属性
在Player结构体中加入记录Y轴旋转的变量(横向转向仅绕Y轴,只需一个yaw值):
struct Player { int width{ 2 }; int height{ 2 }; int length{ 2 }; float speed{ 0.1 }; Color playercolor{RED}; float yaw{0.0f}; // 绕Y轴的旋转角度,单位:弧度 }; Player;
2. 添加转向输入逻辑
在游戏循环的Update部分,添加按键处理,每次触发时让立方体旋转45度(Raylib使用弧度,45度对应PI/4):
// 立方体转向逻辑(仅绕Y轴横向旋转) if (IsKeyPressed(KEY_Q)) { // 向左转45度 player.yaw -= PI/4; } if (IsKeyPressed(KEY_E)) { // 向右转45度 player.yaw += PI/4; }
使用IsKeyPressed确保每次按键仅旋转一次,若需手柄控制,替换为IsGamepadButtonPressed即可,比如GAMEPAD_BUTTON_RIGHT_FACE_LEFT和GAMEPAD_BUTTON_RIGHT_FACE_RIGHT。
3. 修改立方体绘制函数
将DrawCube替换为DrawCubeEx,该函数支持指定旋转轴和角度,实现定向渲染:
// 替换原有DrawCube调用 DrawCubeEx( cubePosition, player.width, player.height, player.length, (Vector3){0.0f, 1.0f, 0.0f}, // 旋转轴固定为Y轴 player.yaw * RAD2DEG, // 将弧度转为角度传入(DrawCubeEx接受角度单位) player.playercolor );
4. 可选:让移动跟随朝向(进阶)
若希望立方体移动沿自身朝向而非世界坐标系,可通过Vector3RotateByAxisAngle计算移动方向:
// 替换原有的世界坐标系移动逻辑 Vector3 moveDir = {0.0f, 0.0f, 0.0f}; if (IsKeyDown(KEY_UP)) moveDir.z -= 1.0f; if (IsKeyDown(KEY_DOWN)) moveDir.z += 1.0f; if (IsKeyDown(KEY_LEFT)) moveDir.x -= 1.0f; if (IsKeyDown(KEY_RIGHT)) moveDir.x += 1.0f; // 将移动方向绕Y轴旋转至当前朝向 moveDir = Vector3RotateByAxisAngle(moveDir, (Vector3){0.0f, 1.0f, 0.0f}, player.yaw); // 归一化方向,避免斜向移动速度过快 moveDir = Vector3Normalize(moveDir); // 应用速度更新位置 cubePosition = Vector3Add(cubePosition, Vector3Scale(moveDir, player.speed));
修改后的完整代码
整合所有修改的完整代码如下,标注了新增/修改部分:
#ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS #endif #define RAYGUI_IMPLEMENTATION #include "raygui.h" // Required for GUI controls #include "raylib.h" //Main Raylib core library #include "raymath.h" //Raylib Math functions library #include "rlgl.h" //RayLib OpenGL library #define XBOX_ALIAS_1 "xbox" #define XBOX_ALIAS_2 "x-box" //information about all our in-game objects------ //Information about our players features struct Enemy { int radius{ 1 }; float speed{ 0.1 }; Color enemycolor{ BLACK }; }; Enemy; //Information about our enemys features struct Player { int width{ 2 }; int height{ 2 }; int length{ 2 }; float speed{ 0.1 }; Color playercolor{RED}; float yaw{0.0f}; // 新增:记录绕Y轴的旋转角度(弧度) }; Player; //information about our bullets features struct Bullet { int width{ 9 }; int height{ 5 }; int speed{ 4 }; Color bulletcolor{ YELLOW }; bool IsBulletActive; int NumOfBullet{ 4 }; }; Bullet; //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ int main(void) { // Initialization //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); // Define the camera to look into our 3d world------- Camera3D camera = { 0 }; camera.position = Vector3{ 0.0f, 10.0f, 10.0f }; // Camera position camera.target = Vector3{ 0.0f, 0.0f, 0.0f }; // Camera looking at point camera.up = Vector3{ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) camera.fovy = 50.0f; // Camera field-of-view Y camera.projection = CAMERA_PERSPECTIVE; // Camera mode type Vector3 cubePosition = { 0.0f, 2.0f, 0.0f }; Vector3 SpherePosition = { 0.0f, 3.0f, -6.0f }; Vector3 displacement = { 0.0f, 0.0f, 0.0f }; double cameraspeed = 0.3; SetTargetFPS(60); //-------------------------------------------------------------------------------------- int gamepad = 0; Player player; Enemy enemy; // Main game loop while (!WindowShouldClose()) { //Update-- if (IsGamepadAvailable(gamepad)){ displacement.x = (GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_X) * cameraspeed); displacement.y = (GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_Y) * cameraspeed); displacement.z = (GetGamepadAxisMovement(gamepad, GAMEPAD_BUTTON_LEFT_FACE_UP) * cameraspeed); } camera.position.x += displacement.x; camera.position.y += displacement.y; camera.position.z += displacement.z; // 新增:立方体转向逻辑(Q键左转45度,E键右转45度) if (IsKeyPressed(KEY_Q)) { player.yaw -= PI/4; } if (IsKeyPressed(KEY_E)) { player.yaw += PI/4; } // 可选:替换为跟随朝向的移动逻辑(取消注释启用) /* Vector3 moveDir = {0.0f, 0.0f, 0.0f}; if (IsKeyDown(KEY_UP)) moveDir.z -= 1.0f; if (IsKeyDown(KEY_DOWN)) moveDir.z += 1.0f; if (IsKeyDown(KEY_LEFT)) moveDir.x -= 1.0f; if (IsKeyDown(KEY_RIGHT)) moveDir.x += 1.0f; moveDir = Vector3RotateByAxisAngle(moveDir, (Vector3){0.0f, 1.0f, 0.0f}, player.yaw); moveDir = Vector3Normalize(moveDir); cubePosition = Vector3Add(cubePosition, Vector3Scale(moveDir, player.speed)); */ // 原有的世界坐标系移动逻辑(不需要跟随朝向后可保留) if (IsKeyDown(KEY_DOWN)) { cubePosition.z += enemy.speed; } if (IsKeyDown(KEY_UP)) { cubePosition.z -= enemy.speed; } if (IsKeyDown(KEY_RIGHT)) { cubePosition.x += enemy.speed; } if (IsKeyDown(KEY_LEFT)) { cubePosition.x -= enemy.speed; } if (IsKeyDown(KEY_A)) { cubePosition.y -= enemy.speed; } if (IsKeyDown(KEY_Z)) { cubePosition.y += enemy.speed; } //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY); ClearBackground(RAYWHITE); BeginMode3D(camera); DrawSphere(SpherePosition, enemy.radius, enemy.enemycolor); // 修改:使用DrawCubeEx绘制带旋转的立方体 DrawCubeEx( cubePosition, player.width, player.height, player.length, (Vector3){0.0f, 1.0f, 0.0f}, // 旋转轴固定为Y轴,实现横向转向 player.yaw * RAD2DEG, // 弧度转角度传入 player.playercolor ); DrawGrid(40, 0.5f); EndMode3D(); EndDrawing(); //---------------------------------------------------------------------------------- } CloseWindow(); return 0; };
内容的提问来源于stack exchange,提问作者Sammy00
相关产品推荐
相关产品推荐

