xcode 如何使用SDL2_TTF库在SDL窗口中显示经过的时间?

htzpubme  于 2023-05-01  发布在  其他
关注(0)|答案(1)|浏览(113)

我正在用C++中的SDL2库编写一个简单的基于窗口的游戏。在SDL2_ttf库的帮助下,我在SDL_Window上显示静态字体就像游戏的名称一样没有问题。但是我还想向用户显示他们有多少条命和他们的分数(这将是SDL窗口保持打开的持续时间)。
这是我的sdlGame。h和sdlGame。cpp文件:

#ifndef sdlGame_h
#define sdlGame_h
#include <SDL2/SDL.h>
#include <SDL2_image/SDL_image.h>
#include <SDL2_ttf/SDL_ttf.h>
/* FOR WINDOWS, UNCOMMENT THESE 3 LINES
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
 */
#include "Game.h"

class Image {

private:

    SDL_Surface * m_surface;
    SDL_Texture * m_texture;
    bool m_hasChanged;

public:
    Image () ;
    ~Image();
    void loadFromFile (const char* filename, SDL_Renderer * renderer);
    void loadFromCurrentSurface (SDL_Renderer * renderer);
    void draw (SDL_Renderer * renderer, int x, int y, int w=-1, int h=-1);
    SDL_Texture * getTexture() const;
    void setSurface(SDL_Surface * surf);
};

class SDLSimple {

private :

    Game game;

    SDL_Window * window;
    SDL_Renderer * renderer;

    TTF_Font * font;
    Image font_im,font_score,font_time;
    SDL_Color font_color;

    Image shipImg;
    Image astroImg;
    Image spaceImg;
    Image starImg;
    Image shieldImg;
    Image slowImg;
    Image clrImg;
    Image hpImg;
    Image im_fantome;

    bool mouse;
    bool key;
public :

    SDLSimple ();
    ~SDLSimple ();
    void sdlBoucle ();
    void sdlAff ();

};


#endif /* sdlGame_h */
#include <cassert>
#include <time.h>
#include "sdlGame.h"
#include <stdlib.h>
#include <string>

#include <iostream>
using namespace std;

const int TAILLE_SPRITE = 32;


float temps () {
    return float(SDL_GetTicks()) / CLOCKS_PER_SEC;  // conversion des ms en secondes en divisant par 1000
}

float timePassed = temps();

// ============= CLASS IMAGE =============== //

Image::Image () : m_surface(nullptr), m_texture(nullptr), m_hasChanged(false) {
}

Image::~Image()
{
    SDL_FreeSurface(m_surface);
    SDL_DestroyTexture(m_texture);

    m_surface = nullptr;
    m_texture = nullptr;
    m_hasChanged = false;
}

void Image::loadFromFile (const char* filename, SDL_Renderer * renderer) {
    m_surface = IMG_Load(filename);
    if (m_surface == nullptr) {
        string nfn = string("../") + filename;
        cout << "Error: cannot load "<< filename <<". Trying "<<nfn<<endl;
        m_surface = IMG_Load(nfn.c_str());
        if (m_surface == nullptr) {
            nfn = string("../") + nfn;
            m_surface = IMG_Load(nfn.c_str());
        }
    }
    if (m_surface == nullptr) {
        cout<<"Error: cannot load "<< filename <<endl;
        SDL_Quit();
        exit(1);
    }

    SDL_Surface * surfaceCorrectPixelFormat = SDL_ConvertSurfaceFormat(m_surface,SDL_PIXELFORMAT_ARGB8888,0);
    SDL_FreeSurface(m_surface);
    m_surface = surfaceCorrectPixelFormat;

    m_texture = SDL_CreateTextureFromSurface(renderer,surfaceCorrectPixelFormat);
    if (m_texture == NULL) {
        cout << "Error: problem to create the texture of "<< filename<< endl;
        SDL_Quit();
        exit(1);
    }
}

void Image::loadFromCurrentSurface (SDL_Renderer * renderer) {
    m_texture = SDL_CreateTextureFromSurface(renderer,m_surface);
    if (m_texture == nullptr) {
        cout << "Error: problem to create the texture from surface " << endl;
        SDL_Quit();
        exit(1);
    }
}

void Image::draw (SDL_Renderer * renderer, int x, int y, int w, int h) {
    int ok;
    SDL_Rect r;
    r.x = x;
    r.y = y;
    r.w = (w<0)?m_surface->w:w;
    r.h = (h<0)?m_surface->h:h;

    if (m_hasChanged) {
        ok = SDL_UpdateTexture(m_texture,nullptr,m_surface->pixels,m_surface->pitch);
        assert(ok == 0);
        m_hasChanged = false;
    }

    ok = SDL_RenderCopy(renderer,m_texture,nullptr,&r);
    assert(ok == 0);
}

SDL_Texture * Image::getTexture() const {return m_texture;}

void Image::setSurface(SDL_Surface * surf) {m_surface = surf;}







// ============= CLASS SDLJEU =============== //

SDLSimple::SDLSimple () : game() {
    // Initialisation de la SDL
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        cout << "Erreur lors de l'initialisation de la SDL : " << SDL_GetError() << endl;
        SDL_Quit();
        exit(1);
    }

    if (TTF_Init() != 0) {
        cout << "Erreur lors de l'initialisation de la SDL_ttf : " << TTF_GetError() << endl;
        SDL_Quit();
        exit(1);
    }

    int imgFlags = IMG_INIT_PNG | IMG_INIT_JPG;
    if( !(IMG_Init(imgFlags) & imgFlags)) {
        cout << "SDL_image could not initialize! SDL_image Error: " << IMG_GetError() << endl;
        SDL_Quit();
        exit(1);
    }

    int dimx, dimy;
    dimx = game.getTerrain().getDimX();
    dimy = game.getTerrain().getDimY();
    dimx = dimx * TAILLE_SPRITE;
    dimy = dimy * TAILLE_SPRITE;

    // Creation de la fenetre
    window = SDL_CreateWindow("Space Race", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 960, 960, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
    if (window == nullptr) {
        cout << "Erreur lors de la creation de la fenetre : " << SDL_GetError() << endl;
        SDL_Quit();
        exit(1);
    }

    renderer = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED);

    // IMAGES (filepaths are placeholders)
    shipImg.loadFromFile("filepath", renderer);
    astroImg.loadFromFile("filepath", renderer);
    hpImg.loadFromFile("/filepath", renderer);
    shieldImg.loadFromFile("filepath", renderer);
    spaceImg.loadFromFile("filepath", renderer);
    starImg.loadFromFile("filepath", renderer);
    slowImg.loadFromFile("filepath", renderer);
    clrImg.loadFromFile("filepath", renderer);

    // FONTS
    font = TTF_OpenFont("filepathforfont",50);
    if (font == nullptr)
        font = TTF_OpenFont("filepathforfont",50);
    if (font == nullptr) {
            cout << "Failed to load DejaVuSansCondensed.ttf! SDL_TTF Error: " << TTF_GetError() << endl;
            SDL_Quit();
            exit(1);
    }
    
    
    font_color.r = 255;font_color.g = 255;font_color.b = 255;
    font_im.setSurface(TTF_RenderText_Solid(font,"Space Race",font_color));
    font_score.setSurface(TTF_RenderText_Solid(font,"Score",font_color));
    font_time.setSurface(TTF_RenderText_Solid(font, timePassed, font_color));
    font_im.loadFromCurrentSurface(renderer);
    font_score.loadFromCurrentSurface(renderer);
    font_time.loadFromCurrentSurface(renderer);
}

SDLSimple::~SDLSimple () {
    TTF_CloseFont(font);
    TTF_Quit();
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
}

void SDLSimple::sdlAff () {
    SDL_SetRenderDrawColor(renderer, 230, 240, 255, 255);
    SDL_RenderClear(renderer);

    int x,y;
    const Terrain& ter = game.getTerrain();
    const Ship& ship = game.getShip();

    for (x=0;x<ter.getDimY();x++){
        for (y=0;y<ter.getDimX();y++){
            if (ter.getXYasChar(x,y)==' '){
                spaceImg.draw(renderer,x*TAILLE_SPRITE,y*TAILLE_SPRITE,TAILLE_SPRITE,TAILLE_SPRITE);
                
            }
            else if (ter.getXYasChar(x,y)=='*'){
                starImg.draw(renderer,x*TAILLE_SPRITE,y*TAILLE_SPRITE,TAILLE_SPRITE,TAILLE_SPRITE);
            }
            
            else if (ter.getXYType(x,y)==Terrain::ASTRO){
                spaceImg.draw(renderer,x*TAILLE_SPRITE,y*TAILLE_SPRITE,TAILLE_SPRITE,TAILLE_SPRITE);
                astroImg.draw(renderer,x*TAILLE_SPRITE,y*TAILLE_SPRITE,TAILLE_SPRITE,TAILLE_SPRITE);
            }
        }
        
    }

    // Afficher le sprite de Pacman
    shipImg.draw(renderer,ship.getX()*TAILLE_SPRITE,ship.getY()*TAILLE_SPRITE,TAILLE_SPRITE,TAILLE_SPRITE);

    // Ecrire un titre par dessus
    SDL_Rect positionTitre;
    SDL_Rect positionScore;
    SDL_Rect positionTime;
    positionTitre.x = 480;positionTitre.y = 0;positionTitre.w = 100;positionTitre.h = 30;
    positionScore.x = 0; positionScore.y = 0; positionScore.w = 100; positionScore.h = 30;
    positionTime.x = 0; positionTime.y = 30; positionTime.w = 100; positionTime.h = 23;
    SDL_RenderCopy(renderer,font_im.getTexture(),nullptr,&positionTitre);
    SDL_RenderCopy(renderer,font_score.getTexture(),nullptr,&positionScore);
    SDL_RenderCopy(renderer,font_time.getTexture(),nullptr,&positionTime);

}

void SDLSimple::sdlBoucle () {
    SDL_Event events;
    bool quit = false;

    Uint32 t = SDL_GetTicks(), nt;

    // tant que ce n'est pas la fin ...
    while (!quit) {

        nt = SDL_GetTicks();
        if (nt-t>500) {
            game.actionsAuto();
            t = nt;
        }

        // tant qu'il y a des évenements à traiter (cette boucle n'est pas bloquante)
        while (SDL_PollEvent(&events)) {
            if (events.type == SDL_QUIT) quit = true;           // Si l'utilisateur a clique sur la croix de fermeture
            else if (events.type == SDL_KEYDOWN) {              // Si une touche est enfoncee
                bool deleteAstroCollided = false;
                switch (events.key.keysym.scancode) {
                case SDL_SCANCODE_W:
                        deleteAstroCollided = game.keyboardListener('s');    // car Y inverse
                    break;
                case SDL_SCANCODE_S:
                        deleteAstroCollided = game.keyboardListener('w');    // car Y inverse
                    break;
                case SDL_SCANCODE_A:
                        deleteAstroCollided = game.keyboardListener('a');
                    break;
                case SDL_SCANCODE_D:
                        deleteAstroCollided = game.keyboardListener('d');
                    break;
                case SDL_SCANCODE_ESCAPE:
                case SDL_SCANCODE_Q:
                    quit = true;
                    break;
                default: break;
                }
            }
        }
        if(game.getShip().getLifeCount() == 0){
            quit = true;
        }

        // on affiche le jeu sur le buffer cach�
        sdlAff();

        // on permute les deux buffers (cette fonction ne doit se faire qu'une seule fois dans la boucle)
        SDL_RenderPresent(renderer);
    }
}

你可以看到在。h文件,我已经声明了一个名为“font_time”的字体来表示时间的ttf_font。
在.cpp文件中,我有一个名为“temps()”的全局函数,它返回使用SDL_GetTicks()花费的时间,并将其除以1000以获得以秒为单位的时间。我有一个名为“time Passed”的浮点数,它使用temps()函数来获取经过的时间。
在一行中,我试图像渲染其他字体一样渲染字体:

font_time.setSurface(TTF_RenderText_Solid(font, to_string(timePassed), font_color));

但是,我有一个错误说:没有匹配的函数用于调用'TTF_RenderText_Solid'
我阅读了文档,我看到第二个参数是指向文本的const char指针,但我认为它只适用于静态字符数组,因为当我将不是变量的字符串直接传递给代码时,它工作得很好。
有没有什么方法可以只使用SDL_ttf的成员函数在屏幕上显示动态文本?如果没有,我如何创建一个动态的文本类,使用SDL渲染等.?

egdjgwm8

egdjgwm81#

TTF_RenderText_Solid(font, to_string(timePassed), font_color)
                           ^^^^^^^^^^^^^^^^^^^^^ nope

TTF_RenderText_Solid()const char *作为第二个参数,而不是std::stringfloat

extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Solid(TTF_Font *font,
                const char *text, SDL_Color fg);

std::string中抓取一个C字符串,std::to_string()通过std::string::c_str()返回,并使用它:

TTF_RenderText_Solid(
    font,
    std::to_string(timePassed).c_str(),
    font_color)

相关问题