c++ - 如何将 SDL 窗口与终端同步?
问题描述
我正在尝试制作一个响应控制台输入的 SDL 窗口。我读了这个问题,以下是我到目前为止所尝试的。
/* g++ test.cpp -o test -lSDL2 */
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>
#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>
#include <SDL2/SDL_render.h>
using namespace std;
const int width = 160;
const int height = 144;
static int inputThread(void *a)
{
int in;
cout << ">> ";
cin >> in;
return in;
}
int main()
{
std::srand(unsigned(std::time(NULL)));
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* window = SDL_CreateWindow(
"SDL2",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
width * 3, height * 3,
SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(
window,
-1,
SDL_RENDERER_ACCELERATED);
SDL_Texture* texture = SDL_CreateTexture(
renderer,
SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING,
width, height);
vector<uint8_t> pixels(width * height * 4, 0);
cout << "0 - rerender; 1 - quit the program" << endl;
while(true)
{
// get input
SDL_Thread *thread = SDL_CreateThread(inputThread, "InputThread", (void *) NULL);
int cmd;
if (thread == NULL) {
printf("SDL_CreateThread failed: %s\n", SDL_GetError());
}
SDL_WaitThread(thread, &cmd);
if (cmd == 0) // rerender
{
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
// splat down some random pixels
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int offset = i * width * 4 + j * 4;
int r = std::rand() % 256;
int g = std::rand() % 256;
int b = std::rand() % 256;
pixels[offset] = b;
pixels[offset + 1] = g;
pixels[offset + 2] = r;
pixels[offset + 3] = 255;
}
}
SDL_UpdateTexture(
texture,
NULL,
&pixels[0],
width * 4);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
else if (cmd == 1) // quit
{
break;
}
}
SDL_DestroyRenderer(renderer);
renderer = NULL;
SDL_DestroyWindow(window);
window = NULL;
SDL_Quit();
return 0;
}
当我运行程序时,SDL 窗口没有响应,有时会崩溃。有什么办法可以改进我的程序,使控制台和 SDL 窗口相互同步而不会出现问题?
解决方案
- 您必须将线程创建排除在循环之外
- 在(渲染)循环中,不要等待线程完成/终止(阻塞,无响应窗口)
- 建立一个全局变量,将从主线程读取并由输入线程写入
- 因此我们必须同步两个线程
- 这里我们使用原子变量,或者我们可以使用互斥锁
为简单起见,代码被缩短:
SDL_atomic_t active;
int inputThread(void *a)
{
int in;
//read from cin into in
//we will set the global var only if in equals to zero
if (in == 0)
SDL_AtomicSet(&active, 0);
return in;
}
int main()
{
//initial stuff
SDL_AtomicSet(&active, 1);
SDL_CreateThread(inputThread, "InputThread", (void*) NULL);
while (SDL_AtomicGet(&active)) {
//listen to and process sdl events
//render
}
//cleanup
return 0;
}
推荐阅读
- google-cloud-platform - 调整谷歌计算引擎的带宽限制
- c# - Parallel.For 在接近尾声时变成单线程
- regex - 交互式查找和替换所有文件,包括使用 Vim 的子目录中的文件
- c# - 如何评估一个数字是否是立方体
- php - 使用一个项目的数据库的现有表到 Laravel 中的另一个项目
- reactjs - Cookie 被传递给客户端,但未保存在浏览器中
- javascript - 如何在 cytoscape 动画结束后执行函数?
- c# - 父母和孩子之间的关系不工作
- html - 如果标签浏览器会拒绝非数字输入吗?
- swift - 必须实现 numberOfItemsInComboBox: 和 comboBox:objectValueForItemAtIndex: