Skip to content

Conversation

@RobLoach
Copy link
Owner

Fixes #356

@RobLoach RobLoach mentioned this pull request Mar 19, 2025
@RobLoach
Copy link
Owner Author

@leyloe Mind testing this out? Running the basic window example may be enough to see things running.

@leyloe
Copy link

leyloe commented Mar 19, 2025

@leyloe Mind testing this out? Running the basic window example may be enough to see things running.

sure, im getting home

@leyloe
Copy link

leyloe commented Mar 19, 2025

@leyloe Mind testing this out? Running the basic window example may be enough to see things running.

it's flipping a variable at the end of the scope. hopefully some compilers can optimize this to keep up with the "0 cost abstraction"

since this "loop" shouldn't iterate a second time

@leyloe
Copy link

leyloe commented Mar 19, 2025

image

the compiler does indeed optimize it on release builds :D

for instance here is the debug build
image

everything is tested, and seems to work fine. if you wanna consider this, maybe. ill see if i can come up with any more ideas so it isnt so nested/you can aswell ig

@leyloe
Copy link

leyloe commented Mar 19, 2025

while (!window.ShouldClose() | window.Drawing())

this seems to work, i dunno if it causes ub, but the program runs just fine. screw it, turn it into a one liner

but.....
image
OR
image

the compiler output seems to have worsened, same functionality tho

@RobLoach
Copy link
Owner Author

Shouldn't that be an && instead of a |?

@leyloe
Copy link

leyloe commented Mar 19, 2025

Shouldn't that be an && instead of a |?

nah you gotta pipe it, && crashes the program

i don't really recommend this approach as it generates unoptimal assembly in release compared to the nested loops.

however, if you can figure out how to remove the extra nesting without the compiler generating extra code maybe via extra library functionality that would help

@leyloe
Copy link

leyloe commented Mar 19, 2025

Shouldn't that be an && instead of a |?

nah you gotta pipe it, && crashes the program

i don't really recommend this approach as it generates unoptimal assembly in release compared to the nested loops.

however, if you can figure out how to remove the extra nesting without the compiler generating extra code maybe via extra library functionality that would help

disregard, i forgot that stuff exists outside of the draw calls, but still exist in the should close loop

@kyomawolf
Copy link
Contributor

I do not think this is a good approach in general.
As often discussed previously here, it should be just a wrapper for a more convenient cpp interface.
Also from an architecture perspective this is a bad idea.
You have the ability to call the draw mode yourself, controlling the program flow there directly -
but adding this to activate the draw mode automatically is a sideeffect, not expected by the user.

What could be good idea is to set a state in the begin and end drawing mode functions, checking the state and log an error, when its attempted to draw without the correct state set.

@leyloe
Copy link

leyloe commented Mar 20, 2025

I do not think this is a good approach in general. As often discussed previously here, it should be just a wrapper for a more convenient cpp interface. Also from an architecture perspective this is a bad idea. You have the ability to call the draw mode yourself, controlling the program flow there directly - but adding this to activate the draw mode automatically is a sideeffect, not expected by the user.

What could be good idea is to set a state in the begin and end drawing mode functions, checking the state and log an error, when its attempted to draw without the correct state set.

are you stating that this is a functionality issue or a aesthetic issue? regardless this feature seems to be optional anyway

and isnt the aim of c++ is to make everything RAII and scoped based? with that, seemingly opinionated wrapper impls are inevitable as any project grows. this codebase already has opinionated stuff already and thats fine. as long as it doesnt mess with functionality and it lets you opt for less code, and more safety

also, this scoped based drawing method doesnt affect functionality at all, again heres the decomp
image
of
image

and i guess you can say, whilst not officially. but while loops can be scope containers with a little magic

@leyloe
Copy link

leyloe commented Mar 20, 2025

but yeah, i haven’t started using raylib in a advanced way yet. but im putting a game together and im liking this scoped draw feature so far. if anyone objects/wants to challenge this opinion, please provide a clear code example of it ruining the functionality of any common case—something the legacy draw scope didn’t have problems with, unlike this.

if anyone wants to try it just pull a zip from the ref head

set(RAYLIB_VERSION 5.5)
set(RAYLIB_CPP_VERSION drawing)

FetchContent_Declare(
    raylib
    URL https://github.com/raysan5/raylib/archive/refs/tags/${RAYLIB_VERSION}.tar.gz
)

FetchContent_Declare(
    raylib_cpp
    URL https://github.com/RobLoach/raylib-cpp/archive/refs/heads/${RAYLIB_CPP_VERSION}.zip
)

FetchContent_MakeAvailable(
    raylib 
    raylib_cpp
)

@kyomawolf
Copy link
Contributor

Sorry for the comment yesterday, I was tired, and misread the file changes. I like the idea of the approach, as a defined scope in a loop is more readable.
So the program flow is like this:

int main() {
    while (Drawing()) {
        //do drawing
       // do logic here?
    }
}

But I personally still dont see a benefit, as my code looks more like this:

void    DoDrawing() {
    BeginDrawing();
    //render scene
    EndDrawing();
}

int main() {
    while (/*program runs*/) {
        DoLogic();
        DoDrawing();
        CheckStates();
    }
}

@leyloe
Copy link

leyloe commented Mar 20, 2025

Sorry for the comment yesterday, I was tired, and misread the file changes. I like the idea of the approach, as a defined scope in a loop is more readable.

So the program flow is like this:


int main() {

    while (Drawing()) {

        //do drawing

       // do logic here?

    }

}

But I personally still dont see a benefit, as my code looks more like this:


void    DoDrawing() {

    BeginDrawing();

    //render scene

    EndDrawing();

}



int main() {

    while (/*program runs*/) {

        DoLogic();

        DoDrawing();

        CheckStates();

    }

}

i meann it's just c++ style syntactic sugar and abstraction. this library has lots of it.

with your point. whats the point of using this library?

and i guess this just makes the draw more raii. that's about it

@leyloe
Copy link

leyloe commented Mar 20, 2025

Sorry for the comment yesterday, I was tired, and misread the file changes. I like the idea of the approach, as a defined scope in a loop is more readable.

So the program flow is like this:


int main() {

    while (Drawing()) {

        //do drawing

       // do logic here?

    }

}

But I personally still dont see a benefit, as my code looks more like this:


void    DoDrawing() {

    BeginDrawing();

    //render scene

    EndDrawing();

}



int main() {

    while (/*program runs*/) {

        DoLogic();

        DoDrawing();

        CheckStates();

    }

}

no, its

while (!window.shouldclose())
{
    // calculate cube stuff in the backend

    while(window.Drawing)
    {
        // actual frontend
    }

    // stuff to do after
}

also, that can be an option, sure. but it depends if you're passing external objects into the loop. your function would have a million arguments

@RobLoach
Copy link
Owner Author

Correct, you usually want to separate your logic from your rendering. This window.Drawing() function doesn't dictate how you do that, just provides an optional wrapper for calling BeginDrawing() and EndDrawing() with a scope.

@leyloe
Copy link

leyloe commented Mar 20, 2025

Correct, you usually want to separate your logic from your rendering. This window.Drawing() function doesn't dictate how you do that, just provides an optional wrapper for calling BeginDrawing() and EndDrawing() with a scope.

like this?

while(window.Drawing) doRender();

@leyloe
Copy link

leyloe commented Mar 20, 2025

@RobLoach @kyomawolf i guess this expands on and addresses your concerns relating to logic modularization

#include <raylib-cpp.hpp>

#define SCREEN_WIDTH 1280
#define SCREEN_HEIGHT 800
#define WINDOW_TITLE "Pong"

class Ball
{
public:
    Ball(raylib::Vector2 position, float radius, float speed) : m_Position{position}, m_Radius{radius}, m_Speed{speed, speed}
    {
    }

    void Draw()
    {
        m_Position.DrawCircle(m_Radius, raylib::Color::White());
    }

    void Update()
    {
        m_Position += m_Speed;

        if (m_Position.y + m_Radius >= SCREEN_HEIGHT || m_Position.y - m_Radius <= 0)
            m_Speed.y *= -1;

        if (m_Position.x + m_Radius >= SCREEN_WIDTH || m_Position.x - m_Radius <= 0)
            m_Speed.x *= -1;
    }

private:
    raylib::Vector2 m_Position;
    raylib::Vector2 m_Speed;
    float m_Radius;
};

raylib::Window window(SCREEN_WIDTH, SCREEN_HEIGHT, WINDOW_TITLE);
raylib::Vector2 center{SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2};

Ball ball{center, 20, 7};

void Setup()
{
    window.SetTargetFPS(60);
}

void Update()
{
    ball.Update();
}

void Render()
{
    window.ClearBackground(raylib::Color::Black());
    DrawLine(center.x, 0, center.x, SCREEN_HEIGHT, raylib::Color::White());
    ball.Draw();
}

int main()
{
    Setup();

    while (!window.ShouldClose())
    {
        Update();

        while (window.Drawing())
            Render();
    }

    return 0;
}

@RobLoach
Copy link
Owner Author

Since this is a small change, I think it's worth bringing in. It doesn't enforce its use, just saves you a line of code in your rendering method 😉

@RobLoach RobLoach merged commit 59478e4 into master Mar 21, 2025
16 checks passed
@RobLoach RobLoach deleted the drawing branch March 21, 2025 02:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A Draw class

4 participants