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(); } }
问题根源
- 角度更新后未同步坐标:调用
setAngle后没有重新计算x/y,pendulum对象的坐标始终是初始值。 - 绘制变量未实时更新:
px1、rod1等绘制用变量只在初始化时赋值,之后没有同步pendulum的最新数据,导致绘制位置不变。 - 双摆位置逻辑错误:第二个摆的绝对位置需要基于第一个摆的实时位置计算,而不是只在初始化时叠加。
修复方案
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
相关产品推荐
相关产品推荐

