Я отлаживал программу SDL2 в Visual Studio, и мне пришлось принудительно завершить работу, и теперь мой экран становится ярче вне программы. Почему и как это исправить? - PullRequest
0 голосов
/ 06 мая 2020

Я делал небольшую программу, чтобы попрактиковаться в использовании указателя и рендеринге.
Я пытался отладить незаконный доступ к памяти, и моя программа вылетела.

Проблема в том, что он разбился, и мне пришлось принудительно завершить сеанс отладки, нажав shift-f5, потому что моя программа находилась в фокусе мыши, и я не мог ничего щелкнуть.
Теперь мой экран постоянно ярче, чем раньше, вероятно, из-за операции рисования, которая должна была рисовать полноэкранный белый прямоугольник.

Это, вероятно, будет исправлено, когда я перезапущу свой P C .... но это все еще проблема, если это складывается, поскольку мне придется перезапускать каждые 3 сеанса отладки, чтобы не обжечь глаза.

Любые советы о том, как ОБЕСПЕЧИТЬ, что моя программа высвобождает ресурсы?
Отредактируйте для воспроизводимого примера:

#include "SDL.h"
#include "SDL_render.h"
#include <stdio.h>
#include <iostream>
#include <list>
#include <string>
#include <ft2build.h>
#include <SDL_ttf.h>
#include <functional>
#include <memory>
#include FT_FREETYPE_H


struct element {
    SDL_Rect* area;
    SDL_Texture* texture;
    SDL_Surface* surface;
    std::string name = "";
    std::function<void()> functionPointer;
    element(SDL_Rect* rect, SDL_Texture* tex, SDL_Surface* surf, std::string elementName, std::function<void()> fp) {
        area = rect;
        texture = tex;
        surface = surf;
        name = elementName;
        functionPointer = fp;
    }
    ~element() {
        SDL_FreeSurface(surface);
        SDL_DestroyTexture(texture);
        area = nullptr;
        surface = nullptr;
        texture = nullptr;
        name = "";
        functionPointer = nullptr;
    }
};


struct screenVariables {
    std::list<SDL_Texture*> textureList;
    std::list<element*>& elementList;
    SDL_Renderer* renderer;
    std::list<SDL_Surface*> surfaceList;
    screenVariables(std::list<SDL_Texture*> tex, std::list<element*> rec, SDL_Renderer* render,std::list<SDL_Surface*> surf) :
        textureList(tex),elementList(rec), renderer(render),surfaceList(surf) {};

};





class gameHandler{
private:
    SDL_Window* screen;
    SDL_Renderer* renderer;
    SDL_Texture* mainBlock;
    bool saveAvailable = false;
    bool quit = false;
    std::list<SDL_Texture*> textureList;
    std::list<element*> elementList;
    std::list<SDL_Surface*> surfaceList;
    screenVariables screenInfo{ textureList, elementList, renderer, surfaceList };

    void nothing() {};

    void continuePressed() {};

    void newGame() {};



 public:
     gameHandler() {
         SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS);
         TTF_Init();
         screen = SDL_CreateWindow("Game Window",
             SDL_WINDOWPOS_UNDEFINED,
             SDL_WINDOWPOS_UNDEFINED,
             1920, 1080,
             SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL);
         renderer = SDL_CreateRenderer(screen, -1, 0);
         mainBlock = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888,
             SDL_TEXTUREACCESS_TARGET, 1920, 1080);

     }

     //All methods that do operations on elements will operate on the LAST ADDED ELEMENT. Always create a new element and use push_back() to add it to the end.
//Everything commented out is not nessesary for reproduction, but 
//will be left for reference.
    /*bool showFirstElement(screenVariables& arg, const char* imgPath, SDL_Rect* area) {
        SDL_Renderer* renderRef = arg.renderer;
        //The following line means: end() returns an iterator, take the iterator and make it go back once, then deference it to get the value.
        //This gets the value of the last added surface.
        SDL_Surface* newSurface = *(--(arg.surfaceList.end()));
        newSurface = SDL_LoadBMP(imgPath);
        SDL_Texture* newTexture = *(--(arg.textureList.end()));
        newTexture = SDL_CreateTextureFromSurface(renderRef, newSurface);
        std::function<void()> nothingWrapper = [&]() { nothing(); };
        element* toBeModified = *(--(arg.elementList.end()));
        toBeModified->element::area = area;
        toBeModified->texture = newTexture;
        toBeModified->surface = newSurface;
        toBeModified->name = imgPath;
        toBeModified->functionPointer = nothingWrapper;
        arg.elementList.push_back(toBeModified);
        SDL_RenderCopy(renderRef, newTexture, NULL, area);
        return true;

    }

    bool textOnElement(screenVariables& arg, const char* text,int points, element* el) {
        SDL_Renderer* renderRef = arg.renderer;
        TTF_Font* font = NULL;
        SDL_Color textColor = { 0,0,0 };
        font = TTF_OpenFont("TravelingTypewriter.ttf", points);
        SDL_Surface* newSurface = *(--(arg.surfaceList.end()));
        newSurface = TTF_RenderText_Solid(font,text,textColor);
        SDL_Texture* newTexture = *(--(arg.textureList.end()));
        newTexture = SDL_CreateTextureFromSurface(renderRef, newSurface);
        el->surface = newSurface;
        el->texture = newTexture;
        SDL_RenderCopy(renderRef, newTexture, NULL, el->area);
        return true;

    }

    element* checkClickedElement(screenVariables& arg, SDL_Point pos) {
        for (element* i : arg.elementList) {
            if (SDL_PointInRect(&pos, i->area)) {
                return i;
            }
            return nullptr;
        }

    }
    bool fillWithColor(screenVariables& arg, Uint32 red, Uint32 green, Uint32 blue, Uint32 alpha) {
        SDL_Renderer* renderRef = arg.renderer;
        SDL_Surface* surface = SDL_CreateRGBSurface(0, 1920, 1080, 8, red, green, blue, alpha);
        SDL_Texture* texture = SDL_CreateTextureFromSurface(renderRef, surface);
        SDL_Rect fullScreen = { 1920,1080 };
        std::string name = "R" + std::to_string(red) + "G" + std::to_string(green) + "B" + std::to_string(blue);
        std::function<void()> nothingWrapper = [&]() { nothing(); };
        element newElement = element(&fullScreen, texture, surface, name, nothingWrapper);
        SDL_RenderCopy(renderRef, texture, NULL, NULL);
        return true;
    }

    bool fillElementPointer(screenVariables& arg, SDL_Point leftTop, SDL_Point rightBottom, std::function<void()> fp,std::string name,element* newElement) {
        SDL_Rect newRect;
        newRect.x = (leftTop.x + rightBottom.x) / 2;
        newRect.y = (leftTop.y + rightBottom.y) / 2;
        newRect.w = (rightBottom.x - leftTop.x);
        newRect.h = (leftTop.y - rightBottom.y);
        newElement = &element(&newRect, nullptr, nullptr, name, fp);
        arg.elementList.push_back(newElement);
        return true;
    }
    //This allows me to create pointers that will not go out of scope when methods return. Always use this method if the element you will create needs to presist through functions.
    element* createElementPointer(){
        element* newPointer = nullptr;
        return newPointer;
    }

    int showMenu(screenVariables& arg) {

        fillWithColor(arg, 255, 255, 255, 255);
        SDL_Point leftTop = { 200,700 };
        SDL_Point rightBottom = { 600,200 };
        std::function<void()> nothingWrapper = [&]() { nothing(); };
        element* titleText = createElementPointer();
        if (!fillElementPointer(screenInfo, leftTop, rightBottom, nothingWrapper, "titleText", titleText)) {
            std::cout << "createElement failed in showMenu()";
        }
        leftTop.y = 100;
        rightBottom.x = 0;
        element* continueOrStart = createElementPointer();
        if (saveAvailable) {
            std::function<void()> continueWrapper = [&]() { continuePressed(); };
            if (!fillElementPointer(screenInfo, leftTop, rightBottom, continueWrapper, "continueButton", continueOrStart)) {
                std::cout << "createElement failed in showMenu() saveAvailable.";
            }
            textOnElement(arg, "Continue", 16, continueOrStart);
        }
        else {
            std::function<void()> newGameWrapper = [&]() { newGame(); };
            if (!fillElementPointer(screenInfo, leftTop, rightBottom, newGameWrapper, "newGameButton", continueOrStart)) {
                std::cout << "createElement failed in showMenu() !saveAvailable.";
            }
            textOnElement(arg, "New Game", 16, continueOrStart);
        }

        return 0;





    }



    void mainLoop() {
        SDL_Event event;
        showMenu(screenInfo);
        while (!quit) {
            SDL_RenderClear(renderer);
            while (SDL_PollEvent(&event) != 0) {
                switch (event.type)
                {
                case SDL_MOUSEBUTTONDOWN:
                    if (event.button.button == SDL_BUTTON_LEFT) {
                        SDL_Point position = { event.button.x,event.button.y };
                        element* result = checkClickedElement(screenInfo, position);
                        if (result == nullptr) {
                            break;
                        }
                        else {
                            result->functionPointer();
                        }
                    }
                    break;

                case SDL_QUIT:
                    quit = true;
                    break;
                }
            }
            SDL_RenderPresent(renderer);
        }


    }
    void clearResources() {
        int index{ 0 };

        for (element* i : screenInfo.elementList) {
            delete i;
        }

        SDL_DestroyRenderer(renderer);

        SDL_Quit();
    } */



};

int main(int argc, char* argv[]) {
    gameHandler handler; //This alone makes my screen brighter.
    //Uncomment every function and let mainLoop() run, and it crashes.
    //Although many attempts at making this exception safe, it did not work.
    //handler.mainLoop();
    return 0;

}
...