C ++ SDL2,如何定期更新渲染的文本? (ttf) [英] C++ SDL2, How to regularly update a renderered text? (ttf)
问题描述
所以在过去的6个小时里,我一直在练习/制作一款快速游戏,但后来我感到有些困惑. 游戏中有一个整数,分数,每当弹药击中一个外星人时,该分数就会与一个整数相加.
So I've been practicing/making a quick game for the past 6 hours, then something stumped me. The game had an integer, Score, which would be added up with one every time an ammo hits an alien.
int Score;
stringstream sstr;
sstr << Score;
string str1 = sstr.str();
TTF_Font* Sans = NULL;
Sans = TTF_OpenFont("Sans.ttf", 24);
SDL_Color White = {255, 255, 255};
SDL_Surface* surfaceMessage = NULL;
surfaceMessage = TTF_RenderText_Solid(Sans, str1.c_str(), White);
SDL_Texture* Message = NULL;
Message = SDL_CreateTextureFromSurface(renderer, surfaceMessage);
SDL_Rect Message_rect;
Message_rect.x = 0;
Message_rect.y = 0;
Message_rect.w = 100;
Message_rect.h = 100;
//UPDATE/GAMELOOP AREA, I DIDN'T REALLY PASTE THE WHOLE PART
SDL_RenderCopy(renderer, Message, NULL, &Message_rect);
现在,我一直在尝试不同的环形交叉路口,以了解如何更新纹理消息. 我进行了一次检查,以检查我是否确实击中了外星人,并且我当前的得分是多少,它看起来还不错,但是渲染的纹理消息"不会从0开始移动.
Now I've been trying different roundabouts as to how to update the texture, Message. I made a cout check to check if I did hit an alien and what my current score is, it appears perfectly fine, but the rendered texture, Message won't move from 0.
我从表面(消息)创建了一个纹理,因为我最喜欢纹理,并且我没有任何表面,因为根据我目前的知识,您至少需要一个可以对其进行闪电化处理的填充表面
I created a texture from the surface (the message) because I mostly prefer textures and I don't have any surface since in my current knowledge, you'd at least need a filled surface where you could blitz this
还有一个问题,我打算进行一场对话式的沉重游戏,是否还有另一种方法来编写文本?我有一种很强烈的感觉,那就是我做错了.
And another question, I'm planning to make a dialogue heavy game, is there another way of doing the texts? I've got a strong feeling that I'm doing it wrong.
推荐答案
最小的可运行示例
计数器每秒更新一次.
Ubuntu 16.10,SDL 2.0.4:
Ubuntu 16.10, SDL 2.0.4:
sudo apt-get install libsdl2-dev libsdl2-ttf-dev
./main /path/to/my.ttf
此方法易于集成,但效率不高,因为它一直在重新栅格化并重新创建纹理.如果您还想提高效率,请参阅:使用SDL2有效地渲染字体和文本我得到4k FPS,因此对于简单的应用程序可能会很好.
This method is easy to integrate, but not very efficient as it re-rasters and re-creates textures all the time. If you also want efficiency, see: Rendering fonts and text with SDL2 efficiently I get 4k FPS, so it might be fine for simple applications.
GitHub上游,带有ttf文件进行测试: https ://github.com/cirosantilli/cpp-cheat/blob/d36527fe4977bb9ef4b885b1ec92bd0cd3444a98/sdl/ttf.c :
GitHub upstream with a ttf file to test with: https://github.com/cirosantilli/cpp-cheat/blob/d36527fe4977bb9ef4b885b1ec92bd0cd3444a98/sdl/ttf.c:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#define COMMON_COLOR_MAX 255
#define COMMON_WINDOW_WIDTH 500
#define COMMON_WINDOW_HEIGHT (COMMON_WINDOW_WIDTH)
double common_get_secs(void) {
struct timespec ts;
timespec_get(&ts, TIME_UTC);
return ts.tv_sec + (1e-9 * ts.tv_nsec);
}
const double COMMON_FPS_GRANULARITY_S = 0.5;
double common_fps_last_time_s;
unsigned int common_fps_nframes;
void common_fps_init() {
common_fps_nframes = 0;
common_fps_last_time_s = common_get_secs();
}
void common_fps_update_and_print() {
double dt, current_time_s;
current_time_s = common_get_secs();
common_fps_nframes++;
dt = current_time_s - common_fps_last_time_s;
if (dt > COMMON_FPS_GRANULARITY_S) {
printf("FPS = %f\n", common_fps_nframes / dt);
common_fps_last_time_s = current_time_s;
common_fps_nframes = 0;
}
}
#define MAX_STRING_LEN 4
/*
- x, y: upper left corner of string
- rect output Width and height contain rendered dimensions.
*/
void render_text(
SDL_Renderer *renderer,
int x,
int y,
const char *text,
TTF_Font *font,
SDL_Rect *rect,
SDL_Color *color
) {
SDL_Surface *surface;
SDL_Texture *texture;
surface = TTF_RenderText_Solid(font, text, *color);
texture = SDL_CreateTextureFromSurface(renderer, surface);
rect->x = x;
rect->y = y;
rect->w = surface->w;
rect->h = surface->h;
/* This is wasteful for textures that stay the same.
* But makes things less stateful and easier to use.
* Not going to code an atlas solution here... are we? */
SDL_FreeSurface(surface);
SDL_RenderCopy(renderer, texture, NULL, rect);
SDL_DestroyTexture(texture);
}
int main(int argc, char **argv) {
SDL_Color color;
SDL_Event event;
SDL_Rect rect;
SDL_Renderer *renderer;
SDL_Window *window;
char *font_path, text[MAX_STRING_LEN];
/* CLI arguments. */
if (argc == 1) {
font_path = "FreeSans.ttf";
} else if (argc == 2) {
font_path = argv[1];
} else {
fprintf(stderr, "error: too many arguments\n");
exit(EXIT_FAILURE);
}
/* initialize variables. */
color.r = COMMON_COLOR_MAX;
color.g = COMMON_COLOR_MAX;
color.b = COMMON_COLOR_MAX;
color.a = COMMON_COLOR_MAX;
/* Init window. */
SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer(
COMMON_WINDOW_WIDTH,
COMMON_WINDOW_WIDTH,
0,
&window,
&renderer
);
/* Init TTF. */
TTF_Init();
TTF_Font *font = TTF_OpenFont(font_path, 24);
if (font == NULL) {
fprintf(stderr, "error: font not found\n");
exit(EXIT_FAILURE);
}
/* Main loop. */
common_fps_init();
while (1) {
if (SDL_PollEvent(&event) && event.type == SDL_QUIT) {
break;
}
/* Use TTF. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
render_text(renderer, 0, 0, "hello", font, &rect, &color);
render_text(renderer, 0, rect.y + rect.h, "world", font, &rect, &color);
snprintf(text, MAX_STRING_LEN, "%u", (unsigned int)(time(NULL) % 1000));
render_text(renderer, 0, rect.y + rect.h, text, font, &rect, &color);
SDL_RenderPresent(renderer);
common_fps_update_and_print();
}
/* Cleanup. */
TTF_Quit();
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
}
这篇关于C ++ SDL2,如何定期更新渲染的文本? (ttf)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!