2

所以,我正在开发一个命令提示符游戏,现在我从小处着手。我已经了解了慢速打印文本系统的基础知识,但是我遇到了一个我不确定如何解决的问题。

基本上; 文本拉伸以适合预定义的框: 预习 预定义框是指我定义为 srcrect 和 dstrect 的 SDL_Rect。

现在,一个解决方案是简单地扩展 SDL_Rect 以适合我的文本,并且由于我使用的是等宽字体,这将相当容易。但我只是在想;“一定会有更好的办法!”。

最后,如果您需要,这是我的代码:

#include<iostream>
#include<SDL.h>
#include<string>
#include<SDL_ttf.h>

std::string text = "";
std::string textToAdd = "Hello there, how are you doing?";
int pos = 0;

void handleEvents(SDL_Event e, bool* quit){
    while(SDL_PollEvent(&e) > 0){
        if(e.type == SDL_QUIT){
            *quit = true;
        }
    }
}

void render(SDL_Renderer* renderer, SDL_Texture* textToRender, SDL_Rect srcrect, SDL_Rect dstrect){
    SDL_RenderClear(renderer);

    SDL_RenderCopy(renderer, textToRender, &srcrect, &dstrect);

    SDL_RenderPresent(renderer);
}

Uint32 calcText(Uint32 interval, void *param){
    if(pos < textToAdd.length()){
        text = text + textToAdd[pos];
        pos++;
    }
    return interval;
}

int main( int argc, char *argv[] ) {
    SDL_Init(SDL_INIT_EVERYTHING);
    TTF_Init();
    SDL_Window* window = SDL_CreateWindow("Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 600, 600, SDL_RENDERER_ACCELERATED);
    SDL_Renderer* renderer = SDL_CreateRenderer(window, 0, 0);

    bool quit = false;
    SDL_Event e;

    SDL_TimerID repeatText = SDL_AddTimer(70, calcText, NULL);

    TTF_Font* font = TTF_OpenFont("Hack-Regular.ttf", 28);
    SDL_Color color = {255, 255, 255};
    SDL_Surface* textSurface;
    SDL_Texture* textTexture;

    SDL_Rect srcrect;
    SDL_Rect dstrect;

    srcrect.x = 0;
    srcrect.y = 0;
    srcrect.w = 580;
    srcrect.h = 32;
    dstrect.x = 10;
    dstrect.y = 10;
    dstrect.w = 580;
    dstrect.h = 32;

    while(!quit){
        handleEvents(e, &quit);
        render(renderer, textTexture, srcrect, dstrect);



        textSurface = TTF_RenderText_Solid(font, text.c_str(), color);
        textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
    }

    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(renderer);

    window = NULL;
    renderer = NULL;
    TTF_Quit();
    SDL_Quit();
    return 0;
}
4

1 回答 1

1

我使用了一些不同的方法。首先,我建议您阅读本教程: http: //lazyfoo.net/tutorials/SDL/index.php。其次:尝试在关键点使用初始化检查,如下例所示:

//...
if (!myInitFunction())
{
    //error message and quit without crash
}
else
{
    //continue game
}
//...

让我们回到你的问题:

是的,有可能,你想要什么,dstrect.wsurface->w. 但并非如此简单。因为在第一次运行 while 循环时,如果我们这样做,我们就会崩溃,dstrect.w = surcface->h然后你的游戏就会崩溃。为什么?因为字符串不等于任何内容:""

为避免这种情况,您应该简单地以空格字符串开头或'H'在开始之前将字符放入字符串中。(实际上我是用另一种方式制作的,SDL_TimerID但我不想让它复杂化。)

此外,您应该遵循“订单规则”:INPUT >>> HANDLING >>> RENDER.

所以你的代码应该是这样的:

//...
std::string text = "H";
std::string textToAdd = "ello there, how are you doing?";
//...
while(!quit)
{
    handleEvents(e, &quit);

    textSurface = TTF_RenderText_Solid(font, text.c_str(), color);
    dstrect.w = textSurface->w; //change the width of rectangle
    textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);

    render(renderer, textTexture, srcrect, dstrect);
}
//...

另一个建议是尝试泛化此渲染方法,如果您还没有这样做,请尝试在控制台应用程序中进行。

重要编辑:我让它重复文本,它变慢了。我意识到有内存泄漏!因此,在使用后或重新创建表面之前,您必须使用删除它SDL_FreeSurface并使用删除纹理SDL_DestroyTexture

编辑 2:因此,回复您的评论,这是您的 while 循环:

{
handleEvents(e, &quit);

if (textSurface != NULL)
{
    SDL_FreeSurface(textSurface);
    //textSurface = NULL; //optional
}
textSurface = TTF_RenderText_Solid(font, text.c_str(), color);
dstrect.w = textSurface->w; //change the width of rectangle

if (textTexture != NULL)
{
SDL_DestroyTexture(textTexture);
//textTexture = NULL;
}
textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);

render(renderer, textTexture, srcrect, dstrect);
}

注意:您必须将指针声明为 NULL,以便 if 部分可以工作SurfaceTexture

于 2015-11-07T08:26:21.307 回答