2

それで、私はコマンド プロンプト ゲームに取り組んでいて、今は小さなものから始めています。遅い印刷テキスト システムの基本を理解しましたが、修正方法がわからない問題に遭遇しました。

基本的; テキストは定義済みのボックスに収まるように伸びます: プレビュー 定義済みのボックスとは、srcrect と dstrect として定義した SDL_Rect を意味します。

さて、解決策は、テキストに合わせて SDL_Rect を単純に拡張することです。Monospaced フォントを使用しているので、これはかなり簡単です。しかし、私は考えたままです。「もっといい方法があるに違いない!」

最後に、必要に応じて私のコードを次に示します。

#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.wですsurface->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);
}
//...

もう 1 つの提案は、この render メソッドを一般化して、まだ行っていない場合はコンソール アプリケーションで実行することです。

重要な編集:テキストを繰り返すようにしましたが、速度が低下しました。メモリリークがあることに気づきました!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);
}

Surface注: if 部分が機能するように、Textureポインタを NULL として宣言する必要があります。

于 2015-11-07T08:26:21.307 に答える