2016-09-04 17 views
2

Я следил за учебником Lazy Foo для создания текста с использованием шрифта ttf, и все было хорошо, но мне нужно было создать несколько текстовых строк в разных местах с разными размерами и цветом шрифта, поэтому Я решил использовать вектор. Вот мой код TextTexture (в основном копии Ленивого Foo учебника):Текстуры SDL_ttf в векторе влияют на прямоугольник назначения другого

#ifndef TEXT_TEXTURE_HPP 
#define TEXT_TEXTURE_HPP 

#include "graphics.hpp" 
#include "vector2.hpp" 

#include <SDL2/SDL_ttf.h> 

#include <string> 

class TextTexture { 
public: 
    TextTexture(
     Graphics& graphics, 
     TTF_Font* font, 
     std::string textureText, 
     SDL_Color textColor, 
     Vector2 coordinates 
    ); 

    ~TextTexture(); 

    void draw(Graphics& graphics); 

private: 
    SDL_Texture* mTexture; 

    int mWidth; 
    int mHeight; 

    int mX; 
    int mY; 

}; 

#endif // TEXT_TEXTURE_HPP 

И .cpp файл для этого:

#include "text_texture.hpp" 
#include "vector2.hpp" 

#include <iostream> 
#include <unistd.h> 

TextTexture::TextTexture (
    Graphics& graphics, 
    TTF_Font* font, 
    std::string textureText, 
    SDL_Color textColor, 
    Vector2 coordinates 
) : 
    mTexture(NULL), 
    mWidth(0), 
    mHeight(0), 
    mX(0), 
    mY(0) 
{ 
    //Render temp surface 
    SDL_Surface* tempSurface = TTF_RenderUTF8_Blended (font, textureText.c_str(), textColor); 

    if (tempSurface == NULL) { 
     std::cout << "Unable to render text surface! SDL_ttf Error: " << TTF_GetError() << std::endl; 
    } else { 
     this -> mTexture = SDL_CreateTextureFromSurface(graphics.getRenderer(), tempSurface); 
     if (this -> mTexture == NULL) { 
      std::cout << "Unable to create texture from rendered text! SDL Error: " << SDL_GetError() << std::endl; 
     } else { 
      //Get image dimensions 
      mWidth = tempSurface -> w; 
      mHeight = tempSurface -> h; 
      // Get coordinates 
      this -> mX = coordinates.getX(); 
      this -> mY = coordinates.getY(); 
     } 
     SDL_FreeSurface (tempSurface); 
     tempSurface = NULL; 
    } 
} 

TextTexture::~TextTexture() { 
    //Free texture if it exists 
    if (mTexture != NULL) { 
     SDL_DestroyTexture(mTexture); 
    } 
    mTexture = NULL; 
    mWidth = 0; 
    mHeight = 0; 
} 

// FIXME somewhy affects previous dest rects 
void TextTexture::draw (Graphics& graphics) { 
    //Set rendering space and render to screen 
    SDL_Rect destinationRectangle = { mX, mY, this -> mWidth, this -> mHeight }; 
    //Render to screen 
    graphics.blitSurface(mTexture, NULL, &destinationRectangle); 
} 

Я создал простой текстовый менеджер для обработки текстов вектора:

#ifndef TEXT_MANAGER_HPP 
#define TEXT_MANAGER_HPP 

#include "graphics.hpp" 
#include "text_texture.hpp" 
#include "vector2.hpp" 

#include <string> 
#include <vector> 

enum fontSize { 
    SMALL = 16, 
    NORMAL = 32, 
    BIG = 48, 
    TITLE = 72 
}; 

enum fontColor { 
    WHITE, 
    ORANGE, 
    BLACK 
}; 

class TextManager { 
public: 
    TextManager(Graphics& graphics); 
    ~TextManager(); 

    void addText(std::string, fontSize, fontColor, Vector2); 
    void draw(); 
    void clearText(); 

private: 
    Graphics& graphics; 
    std::vector <TextTexture> gText; 
}; 

#endif // TEXT_MANAGER_HPP 

и .cpp файл:

#include "text_manager.hpp" 

#include <iostream> 

TextManager::TextManager(Graphics& graphics) : 
    graphics(graphics) 
{} 

TextManager::~TextManager() {} 

void TextManager::addText(std::string text, fontSize size, fontColor color, Vector2 coordinates) { 

    TTF_Font* tempFont = TTF_OpenFont("resources/fonts/pixel.ttf", fontSize::TITLE); 
    SDL_Color tempColor = { 255, 255, 255 }; 

    // Switch removed for shorter code 

    this -> gText.emplace_back(graphics, tempFont, text, tempColor, coordinates); 

    TTF_CloseFont(tempFont); 
    tempFont = NULL; 
} 
// FIXME 
void TextManager::draw() { 
    std::vector<TextTexture>::iterator it; 
    for(it = gText.begin(); it != gText.end(); ++it) { 
     it -> draw(graphics); 
    } 

} 

void TextManager::clearText() { 
    gText.clear(); 
} 

Но когда я запустить приложение, я вижу что-то вроде этого:

Second string is printed, but font and bonding rectangle of first line is saved, hovewer

Позже я добавил ввод обработчик, который добавил вторую строку текста после нажатия на кнопку, и, когда есть только одна строка текста, все отлично, но когда вы добавляете второй, начинается что-то странное - иногда первый текст исчезает, иногда «оба» из них запихиваются. Насколько я понимаю, вторая поверхность текста как-то влияет на первую, скопировав ее текстуру на место первого места назначения.

Вот мой graphics.blitSurface, если это поможет:

void Graphics::blitSurface(SDL_Texture* texture, SDL_Rect* sourceRectangle, SDL_Rect* destinationRectangle) 
{ 
    SDL_RenderCopy (this -> _renderer, texture, sourceRectangle, destinationRectangle); 
} 

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

+0

Ваш последний цикл «отключает» рисунок, потому что он копирует 'TextTexture', но у вас нет надлежащего копирования-конструктор. – tkausl

+0

Для вашего последнего редактирования: нет, версия без итератора использует временную переменную, и как только ее деструктор называется, вы уничтожаете свою текстуру. Что касается исходной проблемы, было бы проще, если бы вы описали ее лучше. Например. Я не вижу кода, который переключает шрифты в зависимости от переданного размера, но вы подразумеваете, что это должно произойти (также этот «ввод кода здесь» немного подозрительный, но я ожидаю, что это будет ошибка copypaste). – keltar

+0

О, это на самом деле имеет смысл. Спасибо! – SuperPrower

ответ