在尝试渲染一些纹理时,我遇到了一些非常奇怪的行为 . 我'm using a custom Texture warper based on Lazy Foo'的教程(http://lazyfoo.net/tutorials/SDL/43_render_to_texture/index.php)名为Texture, Build 在SDL 's texture class SDL_Texture. Usually when I create a texture using my default constructor 1119151 , and then try to render it to the screen, everything works as intended. However on 3 separate occasions now I'之上,得到了非常奇怪的行为 . 在问题的情况下,它经常从一个不同的对象中绘制一个纹理并且它变得扭曲,有时候它很简单,如果我将对象设置为指针并使用_1119152实例化它,一切都完全正常 .
幸运的是,我已经找到了使用指针解决问题的方法,但我可以想象只有三个方面中的一个导致这个问题:SDL2库中存在一个错误(不太可能),我的Texture类中有一个错误,或者我遗漏了关于如何在C中处理对象的一些非常基本的概念 . 在任何一种情况下,如果我试图忽略它,它会回来咬我 .
我正在开发Linux(Ubuntu 16.04)并使用G编译 .
我将在下面的一个问题实例中包含一些代码 . 在这种情况下,我创建了一个“HistoryEntry”类,它可以获取一些属性并将其自身绘制为任意的X和Y.除了timeText之外的所有HistoryEntry属性Texture对象都搞砸了,当它们绘制时它们似乎绘制了一个扭曲的版本timeText的纹理 . 它几乎看起来像他们保持自己的宽度和高度值,但当我加载timeText时,他们的纹理已被覆盖 . 但是,根据我的理解,构造函数将始终生成一个全新的对象,如果只复制其中的某些属性,则会特别奇怪 . 如果我将所有属性Texture对象更改为指向所述Texture对象的指针,则一切都会顺利运行 .
纹理构造函数和加载函数:
Texture::Texture()
{
//Initialize
mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
bool Texture::loadText( std::string textureText, SDL_Color textColor, TTF_Font* gFont)
{
//Get rid of preexisting texture
free();
//Render text surface
SDL_Surface* textSurface = TTF_RenderText_Blended( gFont, textureText.c_str(), textColor );
if( textSurface == NULL )
{
printf( "Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError() );
}
else
{
//Create texture from surface pixels
mTexture = SDL_CreateTextureFromSurface( getRenderer(), textSurface );
if( mTexture == NULL )
{
printf( "Unable to create texture from rendered text! SDL Error: %s\n", SDL_GetError() );
}
else
{
//Get image dimensions
mWidth = textSurface->w;
mHeight = textSurface->h;
}
//Get rid of old surface
SDL_FreeSurface( textSurface );
}
//Return success
return mTexture != NULL;
}
纹理渲染方法:
void Texture::render( int x, int y, int anchor, SDL_Rect* clip )
{
SDL_Rect renderQuad;
//Set rendering space and render to screen
if(anchor == MIDDLE_CENTER){
renderQuad = { x - mWidth/2, y - mHeight/2, mWidth, mHeight };
}else if(anchor == MIDDLE_LEFT){
renderQuad = { x, y - mHeight/2, mWidth, mHeight };
}else if(anchor == MIDDLE_RIGHT){
renderQuad = { x - mWidth, y - mHeight/2, mWidth, mHeight };
}else{
renderQuad = { x, y, mWidth, mHeight };
}
//Set clip rendering dimensions
if( clip != NULL )
{
renderQuad.w = clip->w;
renderQuad.h = clip->h;
}
//Render to screen
SDL_RenderCopy( getRenderer(), mTexture, clip, &renderQuad );
}
HistoryEntry类:
#include <SDL.h>
#include <SDL_image.h>
#include <string>
#include "auxx.h"
#include "texture.h"
#include "history_entry.h"
HistoryEntry::HistoryEntry(){
}
// Constructor for notifications
HistoryEntry::HistoryEntry(int t, std::string n, std::string v)
{
//Atributes
type = t;
eventTime = GetTimer();
name = Texture();
name.loadText(n, defaultColor, defaultFont);
value = Texture();
value.loadText(v, defaultColor, defaultFont);
//code = Texture();
//code.loadText(c, defaultColor, defaultFontSmall);
//icon = i;
timeText = Texture();
}
// Constuctor for error and warnings
HistoryEntry::HistoryEntry(int t, std::string n, std::string c, Texture i)
{
//Atributes
type = t;
eventTime = GetTimer();
name = Texture();
name.loadText(n, defaultColor, defaultFont);
//value = Texture();
//value.loadText(v, defaultColor, defaultFont);
code = Texture();
code.loadText(c, defaultColor, defaultFontSmall);
icon = i;
timeText = Texture();
}
void HistoryEntry::draw(SDL_Renderer* renderer, int x, int y){
if(type == NOTIFICATION_ENTRY){
name.render(x + 7, y + 15);
value.render(x + 620, y + 15);
// Set up time text
// Seconds
if(timeSince() < 60){
timeBuff = std::to_string(timeSince()) + " sec ago";
timeText.loadText(timeBuff , defaultColor, defaultFont);
}
// Minutes
else{
timeBuff = std::to_string(timeSince()/60) + " min ago";
timeText.loadText(timeBuff , defaultColor, defaultFont);
}
timeText.render(x + 440, y + 15);
}else{
icon.render(x + 3, y + 13);
name.render(x + 44, y + 15);
code.render(x + 44, y + 45);
//value.render(x + 620, y + 15);
// Set up time text
// Seconds
if(timeSince() < 60){
timeBuff = std::to_string(timeSince()) + " sec ago";
timeText.loadText(timeBuff , defaultColor, defaultFont);
}
// Minutes
else{
timeBuff = std::to_string(timeSince()/60) + " min ago";
timeText.loadText(timeBuff , defaultColor, defaultFont);
}
timeText.render(x + 440, y + 15);
}
}
int HistoryEntry::getHeight(){
if(type = NOTIFICATION_ENTRY){
return 63;
}else{
return 89;
}
}
int HistoryEntry::timeSince(){
return GetTimePassedSeconds(eventTime);
}
调用绘图的部分显示功能:
void DrawGraphics()
{
SDL_Renderer *renderer = getRenderer();
//Clear screen
SDL_SetRenderDrawColor( renderer, 0xFF, 0xFF, 0xFF, 0xFF );
SDL_RenderClear( renderer );
...
// Draw history if it is active
if(history_active){
historyBackground.render(480, 79);
}
// Y position of first history entry
int rowY = 134;
// Draw history entries
if(history_active){
// Set color for history lines
SDL_SetRenderDrawColor(renderer, 52, 64, 79, 0);
for(int i = 0; i < history.size(); i++){
history[i].draw(renderer, 495, rowY);
// Increment the y value based on entry size
if(history[i].type == NOTIFICATION_ENTRY){
rowY += 63;
}else{
rowY += 89;
}
// Draw lines
SDL_RenderDrawLine(renderer, 495, rowY - 1, 1287, rowY - 1);
}
}
//Update screen
SDL_RenderPresent( renderer );
}