Search code examples
c++graphicsphysicsraylib

How to update the screen/re-draw screen in Raylib?


As a way to learn C++ I wanted to make a double pendulum simulation using a graphics framework so I chose Raylib because its the only framework I need. So far I have been able to draw a double pendulum and I am able to modify the angle so that whenever theta is modified it will change the position of the pendulum. However, I cannot animate this whenever I try to update theta1 or theta2 within the main while loop. Before I can actually implement some physics I need to know that I will be able to animate the pendulum based on its separate angles. Only when I set the angle for the first time it will change. I cant re-set the angle anywhere else only initially, I am new to 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;
}

//Default constructor
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); //Can only set this once and cant anywhere else, why?
    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); //Can only set this once and cant anywhere else, why?
    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};

    /**--------------------------TEST VARIABLES--------------------------*/
    //Pendulum 1 & 2 properties:
    float l1 = 150.0f; //Length 1
    float l2 = 150.0f; //Length 2

    float m1 = 20.0f;
    float m2 = 20.0f;

    static float angle1 = 0.0f * DEG2RAD;
    static float angle2 = 0.0f * DEG2RAD;

    //First pendulum x & y
    float x1 = l1 * sin(theta1);
    float y1 = l1 * cos(theta1);

    //Second pendulum x & y
    float x2 = x1 + (l2 * sin(theta2));
    float y2 = y1 + (l2 * cos(theta2));
    /**--------------------------TEST VARIABLES--------------------------*/

    InitWindow((int) screenWidth, (int) screenHeight, "Double-Pendulum-Sim");

    int state = 0;
    int frameCounter = 0;

    SetTargetFPS(60);


    while (!WindowShouldClose()) {

        /**------------------Update------------------*/
        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;
            }
        }

    /**---------------------------------Draw-Pendulums---------------------------------- */
        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;
}

//Test function
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();
    }

}

Solution

  • After going through I noticed that to draw the actual shapes I needed the pendulum x and y components, using the variables px1, px2, py1, py2. So I needed to update those variables along with incrementing the angle. This isn't the full pendulum simulator this is just the fix to making it move when incrementing the angle, will post Github link when finished. Also, the only file modified was main.cpp therefore it's the only one that will be shared.

    main.cpp:

    #include <iostream>
    #include "raylib.h"
    #include "includes/pendulum.h"
    #include <rlgl.h>
    #include <cmath>
    
    void _testPendulum();
    
    pendulum pen1;
    pendulum pen2;
    
    
    int main() {
    
    
        //Prompt to make the initial values themselves
        float uLength1, uLength2, uMass1, uMass2, uAngle1, uAngle2;
    
        try {
    
            std::cout << "Please choose the length of each pendulum, starting with Pendulum 1, then Pendulum 2. Each value provided can be up to 7 decimal digits" << "\n";
            std::cin >> uLength1 >> uLength2;
            std::cout << "Please choose the mass of each pendulum, starting with Pendulum 1, then Pendulum 2. Each value provided can be up to 7 decimal digits" << "\n";
            std::cin >> uMass1 >> uMass2;
            std::cout << "Please choose the starting angle of each pendulum, starting with Pendulum 1, then Pendulum 2. Each value provided can be up to 7 decimal digits" << "\n";
            std::cin >> uAngle1 >> uAngle2;
    
        } catch (const std::exception & e) {
            std::cout << e.what();
        }
    
    
    
        pen1.setMass(uMass1);
        pen1.setLength(uLength1);
        pen1.setAngle(uAngle1); //Can only set this once and cant anywhere else, why?
        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(uMass2);
        pen2.setLength(uLength2);
        pen2.setAngle(uAngle2); //Can only set this once and cant anywhere else, why?
        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;
    
        InitWindow((int) screenWidth, (int) screenHeight, "Double-Pendulum-Sim");
    
        int frameCounter = 0;
    
        SetTargetFPS(60);
    
        float px1 = pen1.getX();
        float py1 = pen1.getY();
    
        float px2 = pen2.getX();
        float py2 = pen2.getY();
    
        while (!WindowShouldClose()) {
    
    
            Vector2 rod1{px1,py1};
            Vector2 rod2 {px2, py2};
    
            /**------------------Update------------------*/
    
                frameCounter++;
                uAngle1 = (float) frameCounter;
                pen1.setAngle(uAngle1); //Can only set this once and cant anywhere else, why?
                pen1.setX(pen1.pLength,pen1.getAngle());
                pen1.setY(pen1.pLength, pen1.getAngle());
    
                px1 = pen1.getX();
                py1 = pen1.getY();
    
                uAngle2 += 5.0f;
                pen2.setAngle(uAngle2); //Can only set this once and cant anywhere else, why?
                pen2.setX( pen2.pLength,pen2.getAngle());
                pen2.setY( pen2.pLength,pen2.getAngle());
                pen2.x = pen1.getX() + pen2.getX();
                pen2.y = pen1.getY() + pen2.getY();
    
                px2 = pen2.getX();
                py2 = pen2.getY();
    
    
        /**---------------------------------Draw-Pendulums---------------------------------- */
            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;
    }
    
    //Test function
    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();
        }
    
    }