OneLoneCoder / olcPixelGameEngine

The official distribution of olcPixelGameEngine, a tool used in javidx9's YouTube videos and projects
Other
3.86k stars 913 forks source link

Decals don't work if not constructed in PixelGameEngine class #386

Closed SmokeyCosmy closed 1 month ago

SmokeyCosmy commented 2 months ago

Hello,

I think I found a weird bug that I can't wrap my head around: Decals don't work if they're not constructed in PixelGameEngine class, one of it's virtual methods (OnUserCreate, etc) or in a object instance created in the PixelGameEngine class or one of it's virtual methods.

Code example:

#define OLC_PGE_APPLICATION
#include "olcPixelGameEngine.h"

class DrawingObject {
    public:
        olc::Sprite* sprite;
        olc::Decal* decal;
        DrawingObject();
        ~DrawingObject();
        void Draw(olc::PixelGameEngine* pge);
};

class Example : public olc::PixelGameEngine
{
public:
    DrawingObject* body = new DrawingObject();
    olc::Decal* decalMain;
    Example()
    {
        sAppName = "Example";
    }
    ~Example() {
        delete decalMain;
        delete body;
    }
    bool OnUserCreate() override
    {
        // body = new DrawingObject(); // If uncommented, everything works as expected
        decalMain = new olc::Decal(body->sprite);
        return true;
    }
    bool OnUserUpdate(float fElapsedTime) override{
        body->Draw(this);
        this->DrawSprite({0, 0}, body->sprite);
        this->DrawDecal({0,300}, body->decal);
        this->DrawDecal({300, 300}, decalMain);
        return true;
    }
};

DrawingObject::DrawingObject() {
            sprite = new olc::Sprite("body_tracks.png");
            decal = new olc::Decal(sprite);
        };
DrawingObject::~DrawingObject() {
            delete sprite;
            delete decal;
        };

void DrawingObject::Draw(olc::PixelGameEngine* pge) {
            pge->DrawDecal({300, 0}, decal);
};

int main()
{
    Example demo;
    if (demo.Construct(800, 600, 1, 1))
        demo.Start();
    return 0;
}

Output: DecalNotWorking

Expected results (just uncomment the line): Expected

Tested on windows with msvc and g++

Piratux commented 2 months ago

Hey,

The issue here, is that decals can't be created before OnUserCreate() runs. That's because to create decals, PixelGameEngine needs to initialise GPU first and that's not done before OnUserCreate() runs. This means you can't initialise class member fields that create decals.

To fix your issue replace this:

DrawingObject* body = new DrawingObject();

With following:

DrawingObject* body;

And then uncomment this line:

// body = new DrawingObject(); // If uncommented, everything works as expected
SmokeyCosmy commented 2 months ago

Ok, that makes sense. Thanks for the answer.

However, there still should be some kind of exception thrown for this (if this is the expected way). Or someway to at least check if a decal was not created for some reason (e.g. no openGL texture was created, which actually happens above, yet all calls to openGL are still done like it's a valid decal). Or, even better yet, "load" the created decals in GPU when the time is right.

As it currently stands it's really hard when hitting this problem to figure out what the issue is and what the solution is (not to mention why that is). And it seems exactly the kind of thing anyone new (like me) to the library would stumble upon. I'm surprised it wasn't brought up until now.

Piratux commented 2 months ago

I agree with you there, there definitely should be some error indication here, considering it's an issue people often stumble into.

Will ask maintainers about it.