SDL2 - Почему мигает текст, если мой цвет не инициализирован как частная переменная? - PullRequest
0 голосов
/ 25 мая 2020

Я пытаюсь представить текст следующим кодом:

void Text::display(SDL_Renderer *renderer, int x, int y) {
// pos is an SDL_Rect and font is a TTF_Font
    pos.x = pos.w = x;
    pos.y = pos.h = y;

    SDL_Surface *surface = TTF_RenderText_Solid(font, text.c_str(), color);
    SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
    SDL_QueryTexture(texture, NULL, NULL, &pos.w, &pos.h);
    SDL_RenderCopy(renderer, texture, NULL, &pos);

    SDL_FreeSurface(surface);
    SDL_DestroyTexture(texture);
}

В моем классе Text . Сначала у меня был неинициализированный SDL_Color color в моем методе Text::display(), который позволял мне отображать текст на экране. (renderer передается из основных + координат x,y). Но я решил вместо этого сделать свою SDL_Color color частной переменной в классе Text. И что для меня странно, так это то, что в качестве частной переменной текст мерцал, когда я его представил, но если я установил его как переменную publi c или поместил в метод, текст не мерцал. Или если бы я инициализировал его как частную переменную (SDL_Color color = {255, 255, 255}).

Мой вопрос: , если бы только чистая удача работала, когда color не был инициализирован как publi c или переменная метода или они по-разному трактуются? Когда я инициализировал цвет в конструкторе, он также мерцал, если цвет был частным.

Мой основной метод:

void fpsCap(Uint32 starting_tick) {
    if ((1000 / fps) > SDL_GetTicks() - starting_tick) {
        SDL_Delay(1000 / fps - (SDL_GetTicks() - starting_tick));
    }
}

int main(int argv, char** args) {

// Create renderer, window, etc

    while (true) {
        SDL_RenderClear(renderer);
        Text *txt = new Text("hello");
        txt->display(gui->getRenderer(), 0, 0);
        SDL_RenderPresent(renderer);
    }
}

1 Ответ

2 голосов
/ 26 мая 2020

Значение закрытого члена не инициализировано, поэтому оно получает случайное / мусорное значение. Когда вы выделяете новый экземпляр Text для каждого кадра. Вы выделяете память в куче (каждый раз в новом месте), так что это как бы гарантированно будет мусором.

Почему в других случаях он не мерцал?

  • Publi c member: я предполагаю, что вы также сделали это stati c? Переменные Stati c инициализируются нулем (в отличие от переменных-членов).

  • Локальная переменная: локальные переменные не обнуляются и считаются содержащими мусор, но поскольку они выделяются стеком , они, вероятно, получат одинаковый кусок мусора каждый раз в данном месте.

  • Частный член, назначенный в конструкторе: это неожиданно. Вы уверены, что на самом деле используется тот же конструктор? И что это была та же самая переменная? Возможно, какое-то затенение имени помешало значению попасть туда, где мы должны?

Tangential:

Вы пропускаете экземпляр Text каждые l oop. Вам следует delete каждый объект, созданный с помощью new, или лучше вообще избегать использования new. Вместо этого используйте unique_ptr / make_unique или просто локальные переменные (в данном случае гораздо лучше).

EDIT, чтобы ответить на вопросы о new:

В современном C ++ вам почти никогда не нужно использовать new.

  • Если у вас есть объект, который используется только во время выполнения функции, естественно, что нужно сохранить его напрямую (т.е. не через указатель), в этом case, определяющий переменную как

    Text txt("hello");
    

    Это идиома, аналогичная Java s Text txt = new Text("hello");, но результирующая переменная является самим экземпляром, а не ссылкой на него.

  • Если вы хотите создать экземпляр, который вы сразу передаете в качестве аргумента типа Text или const Text&, вы можете создать его как временный, например SomeFunction(Text("hello")) (обратите внимание на отсутствие new, это просто имя класса).
  • Если вам нужно распределение кучи, интеллектуальные указатели (std::unique_ptr и std::shared_ptr) создаются с помощью std::make_unique и std::make_shared настоятельно рекомендуются, поскольку они защищают от многих распространенных ошибок, таких как как утечки памяти и висячие указатели, по крайней мере до тех пор, пока вы удерживаете сам интеллектуальный указатель. std::shared_ptr, вероятно, ближе всего стандартному C ++ к ссылке Java, хотя это не сборщик мусора, поэтому, если вы сделаете их цикл, они никогда не будут освобождены.

    Вы можете заменить свой Text *txt = new Text("hello"); с

    auto txt = std::make_unique<Text>("hello");
    

    , чтобы получить такое же поведение, но с Text уничтожается и освобождается в конце блока.

...