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

Raylib屏幕更新/重绘方法及双摆动画角度更新问题求助

双摆动画不更新问题解决

我正在学习C++,用Raylib框架做双摆模拟。现在能画出双摆,初始设置摆角能改变位置,但主循环里更新theta1或theta2时没动画效果,只有第一次设置角度有用。我是C++新手,想解决这个问题继续做物理效果。


pendulum.h

#ifndef DOUBLE_PENDULUM_SIM_PENDULUM_H
#define DOUBLE_PENDULUM_SIM_PENDULUM_H

class pendulum {
public:
    float pLength{};
    float pMass{};
    float x{};
    float y{};
    float pAngle{};

public:
    [[nodiscard]] float getX() const ;
    [[nodiscard]] float getY() const ;
    [[nodiscard]] float getAngle() const ;

    void setX(float length, float angle);
    void setY(float length, float angle);

    void setLength(float length);
    void setMass(float mass);
    void setAngle(float angle);

    pendulum();
    pendulum(float length, float mass, float angle) : pLength(length), pMass(mass), pAngle(angle) {}
    ~pendulum();
};

#endif //DOUBLE_PENDULUM_SIM_PENDULUM_H

pendulum.cpp

#include "includes/pendulum.h"
#include <cmath>
#include <iostream>
#include <raylib.h>

void pendulum::setX(float length, float angle) {
    x = length * sin(angle);
}

void pendulum::setY(float length, float angle) {
    y = length * cos(angle);
}

float pendulum::getX() const {
    return x;
}

float pendulum::getY() const {
    return y;
}

void pendulum::setLength(float length) {
    pLength = length;
}

void pendulum::setMass(float mass) {
    pMass = mass;
}

float pendulum::getAngle() const {
    return pAngle;
}

pendulum::~pendulum() {
    std::cout << "Pendulum destroyed" << std::endl;
}

void pendulum::setAngle(float angle) {
    pAngle = angle * DEG2RAD;
}

pendulum::pendulum() = default;

main.cpp

#include <iostream>
#include "raylib.h"
#include "includes/pendulum.h"
#include <rlgl.h>
#include <cmath>

void _testPendulum();

pendulum pen1;
pendulum pen2;

int main() {
    float theta1 = 0.0f;
    float theta2 = 0.0f;

    pen1.setMass(20.0f);
    pen1.setLength(150.0f);
    pen1.setAngle(theta1);
    pen1.setX(pen1.pLength,pen1.getAngle());
    pen1.setY(pen1.pLength, pen1.getAngle());

    std::cout << "X coord: " << pen1.getX() << " Y coord: " << pen1.getY() << std::endl;

    pen2.setMass(50.0f);
    pen2.setLength(150.0f);
    pen2.setAngle(theta2);
    pen2.setX( pen2.pLength,pen2.getAngle());
    pen2.setY( pen2.pLength,pen2.getAngle());
    pen2.x = pen1.getX() + pen2.getX();
    pen2.y = pen1.getY() + pen2.getY();

    std::cout << "X coord: " << pen2.getX() << " Y coord: " << pen2.getY() << std::endl;

    Vector2 origin{0,0};
    double screenWidth = 800;
    double screenHeight = 800;

    float px1 = pen1.getX();
    float py1 = pen1.getY();
    float px2 = pen2.getX();
    float py2 = pen2.getY();

    Vector2 rod1{px1,py1};
    Vector2 rod2 {px2, py2};

    float l1 = 150.0f;
    float l2 = 150.0f;
    float m1 = 20.0f;
    float m2 = 20.0f;
    static float angle1 = 0.0f * DEG2RAD;
    static float angle2 = 0.0f * DEG2RAD;
    float x1 = l1 * sin(theta1);
    float y1 = l1 * cos(theta1);
    float x2 = x1 + (l2 * sin(theta2));
    float y2 = y1 + (l2 * cos(theta2));

    InitWindow((int) screenWidth, (int) screenHeight, "Double-Pendulum-Sim");
    int state = 0;
    int frameCounter = 0;
    SetTargetFPS(60);

    while (!WindowShouldClose()) {
        if(state == 0) {
            frameCounter++;
            theta1 = (float) frameCounter;
            pen1.setAngle(theta1);

            if(frameCounter >= 500) {
                frameCounter = 0;
                state = 1;
            }
        } else if(state == 1) {
            frameCounter++;
            theta2 = (float) frameCounter;
            pen2.setAngle(theta2);

            if(frameCounter >= 600) {
                frameCounter = 0;
                state = 2;
            }
        }

        BeginDrawing();
            ClearBackground(BLACK);
            DrawFPS(-350, -200);
            rlTranslatef(400,250,0);

            DrawLineEx(origin, rod1, 5.0f, RAYWHITE);
            DrawCircle(px1,py1,pen1.pMass,RAYWHITE);

            DrawLineEx(rod1, rod2, 5.0f, RAYWHITE);
            DrawCircle(px2,py2,pen2.pMass,RAYWHITE);

            std::cout << "Pendulum 1 X & Y: " << pen1.getX() << " " << pen1.getY() << std::endl;
            std::cout << "Pendulum 2 X & Y: " << pen2.getX() << " " << pen2.getY() << std::endl;
        EndDrawing();
    }
    CloseWindow();
    return 0;
}

void _testPendulum() {
    try {
        pen1.setMass(20.0f);
        pen1.setLength(150.0f);
        pen1.setAngle(0.0f);
        pen1.setX(pen1.pLength,pen1.getAngle());
        pen1.setY(pen1.pLength, pen1.getAngle());

        std::cout << "X coord: " << pen1.getX() << " Y coord: " << pen1.getY() << std::endl;

        pen2.setMass(50.0f);
        pen2.setLength(150.0f);
        pen2.setAngle(0.0f);
        pen2.setX( pen2.pLength,pen2.getAngle());
        pen2.setY( pen2.pLength,pen2.getAngle());
        pen2.x = pen1.getX() + pen2.getX();
        pen2.y = pen1.getY() + pen2.getY();

        std::cout << "X coord: " << pen2.getX() << " Y coord: " << pen2.getY() << std::endl;
    } catch (const std::exception & e) {
        std::cout << e.what();
    }
}

问题根源

  1. 角度更新后未同步坐标:调用setAngle后没有重新计算x/y,pendulum对象的坐标始终是初始值。
  2. 绘制变量未实时更新:px1、rod1等绘制用变量只在初始化时赋值,之后没有同步pendulum的最新数据,导致绘制位置不变。
  3. 双摆位置逻辑错误:第二个摆的绝对位置需要基于第一个摆的实时位置计算,而不是只在初始化时叠加。

修复方案

1. 自动同步坐标到角度更新

修改pendulum.cpp的setAngle方法,更新角度时自动计算坐标:

void pendulum::setAngle(float angle) {
    pAngle = angle * DEG2RAD;
    setX(pLength, pAngle);
    setY(pLength, pAngle);
}

2. 主循环中实时同步绘制数据

在每次绘制前,从pendulum对象获取最新坐标并更新绘制变量:

while (!WindowShouldClose()) {
    // 原更新逻辑保留
    if(state == 0) {
        frameCounter++;
        theta1 = (float)frameCounter * 0.5f; // 减慢角度增长速度
        pen1.setAngle(theta1);
        // 更新第二个摆的绝对位置
        pen2.x = pen1.getX() + pen2.getX();
        pen2.y = pen1.getY() + pen2.getY();

        if(frameCounter >= 500) {
            frameCounter = 0;
            state = 1;
        }
    } else if(state == 1) {
        frameCounter++;
        theta2 = (float)frameCounter * 0.5f;
        pen2.setAngle(theta2);
        pen2.x = pen1.getX() + pen2.getX();
        pen2.y = pen1.getY() + pen2.getY();

        if(frameCounter >= 600) {
            frameCounter = 0;
            state = 2;
        }
    }

    BeginDrawing();
        ClearBackground(BLACK);
        DrawFPS(10, 10); // 调整FPS到可见位置
        rlTranslatef(400,250,0);

        // 实时同步绘制变量
        px1 = pen1.getX();
        py1 = pen1.getY();
        px2 = pen2.getX();
        py2 = pen2.getY();
        rod1 = {px1, py1};
        rod2 = {px2, py2};

        // 原绘制代码保留
        DrawLineEx(origin, rod1, 5.0f, RAYWHITE);
        DrawCircle(px1,py1,pen1.pMass,RAYWHITE);
        DrawLineEx(rod1, rod2, 5.0f, RAYWHITE);
        DrawCircle(px2,py2,pen2.pMass,RAYWHITE);
    EndDrawing();
}

3. 优化初始化逻辑

确保初始化时第二个摆的位置正确计算:

pen1.setAngle(theta1);
pen2.setAngle(theta2);
pen2.x = pen1.getX() + pen2.getX();
pen2.y = pen1.getY() + pen2.getY();

内容的提问来源于stack exchange,提问作者Cr3

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 17:39:34