[英]Not able to draw an array of squares in SDL2 in C
我正在为 C 使用 SDL2,以根据数组(地形 [something] [something])绘制出不同颜色的正方形。 但是当我运行它时,会发生一个红色方块被绘制在左上方,然后 window 停止响应。
基本上我正在做的是通过数组使用几个for循环到go,并根据给定元素的值,它每次都会在不同的position处绘制一个不同颜色的正方形。 我实际上不确定当我绘制下一个时我绘制的东西是否会自动清除,因为我使用的是相同的矩形结构。
int terrain_print()
{
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
{
printf("Error initializing SDL: %s\n", SDL_GetError());
return 0;
}
SDL_Window* wind = SDL_CreateWindow("Terrain Generator",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
WIDTH, HEIGHT, 0);
if (!wind)
{
printf("Error creating window: %s\n", SDL_GetError());
SDL_Quit();
return 0;
}
Uint32 render_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;
SDL_Renderer* rend = SDL_CreateRenderer(wind, -1, render_flags);
if (!rend)
{
printf("Error creating renderer: %s\n", SDL_GetError());
SDL_DestroyWindow(wind);
SDL_Quit();
return 0;
}
bool running = true;
float x_pos = 0, y_pos = 0;
SDL_Rect rect = { (int)x_pos, (int)y_pos, PIXELSIZE, PIXELSIZE };
SDL_Event event;
while (running)
{
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
running = false;
break;
}
}
for (int i = ARRAYH - 1; i >= 0; i--)
{
for (int j = 0; j < ARRAYW; j++)
{
switch (terrain[i][j])
{
case air:
SDL_SetRenderDrawColor(rend, 75, 163, 255, 255);
case grass:
SDL_SetRenderDrawColor(rend, 0, 181, 16, 255);
case dirt:
SDL_SetRenderDrawColor(rend, 74, 26, 0, 255);
case stone:
SDL_SetRenderDrawColor(rend, 85, 85, 85, 255);
}
SDL_SetRenderDrawColor(rend, 255, 0, 0, 255);
SDL_RenderFillRect(rend, &rect);
SDL_RenderPresent(rend);
SDL_Delay(1000 / FPS);
x_pos += PIXELSIZE;
}
y_pos += PIXELSIZE;
}
}
SDL_DestroyRenderer(rend);
SDL_DestroyWindow(wind);
SDL_Quit();
return 0;
}
正如其他人在评论部分已经指出的那样,您的一个switch
语句中可能缺少break
语句。 但是,即使您有这些break
语句,整个switch
语句的内容也会通过在以下行中将颜色更改回红色来覆盖:
SDL_SetRenderDrawColor(rend, 255, 0, 0, 255);
此外,您必须更新rect.x
和rect.y
,而不是更新x_pos
和y_pos
。 否则,您将始终覆盖同一个矩形。
另一个问题可能是,根据SDL_RenderPresent
的官方文档,建议在开始每个新帧的绘制之前调用SDL_RenderClear
。 该文档指出,当您开始绘制下一帧时,您不应依赖仍存在于后备缓冲区中的前一帧内容。 但是,您似乎依赖于此。 即使您的程序在没有调用SDL_RenderClear
的情况下在您的计算机上运行,当您更改配置或在不同平台上运行程序时,它也可能停止工作。 我认为这个警告被放入文档中是有充分理由的。 因此,您可能希望更改算法以在一帧中渲染所有内容,或者,如果您希望保持一帧中添加的新矩形的外观,则在新帧中渲染前一帧中的所有矩形。 或者,您可以使用SDL_SetRenderTarget
渲染到SDL_Texture
而不是直接渲染到屏幕,这样您就可以确保内容永远不会丢失。
然后 window 停止响应。
这并不奇怪。 您为每个terrain
元素调用一次SDL_RenderPresent
和SDL_Delay
,即每个最内层循环迭代一次。 每一帧的渲染之间有1000 / FPS
毫秒的暂停。 根据terrain
数组的大小(您未在发布的代码中显示),渲染所有这些帧的总时间可能是几秒。 在此期间,您不处理事件。 只要您不处理事件,您的 window 就会无响应。 在整个terrain
阵列被渲染之后,您才在外循环中再次开始处理事件。
我建议您使用SDL_AddTimer
SDL_Delay
这样,在渲染下一帧时将调用回调 function。 同时,您可以处理事件,您的 window 将做出响应。 我建议您的回调SDL_PushEvent
应该只使用应用程序定义的事件(使用SDL_RegisterEvents
注册)调用 SDL_PushEvent ,而您的主线程正在使用SDL_WaitEvent
等待这些和其他可能的事件。
或者,在帧之间调用SDL_PumpEvents
应该足以保持 window 响应。 但是如果您希望能够响应事件,则上一段中提到的解决方案更干净。
另一种选择是使用 function SDL_PollEvent
隐式调用SDL_PumpEvents
并允许您在不阻塞的情况下检查新事件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.