You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 18:15:56