繁体   English   中英

无法在 C 的 SDL2 中绘制正方形数组

[英]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.xrect.y ,而不是更新x_posy_pos 否则,您将始终覆盖同一个矩形。

另一个问题可能是,根据SDL_RenderPresent的官方文档,建议在开始每个新帧的绘制之前调用SDL_RenderClear 该文档指出,当您开始绘制下一帧时,您不应依赖仍存在于后备缓冲区中的前一帧内容。 但是,您似乎依赖于此。 即使您的程序在没有调用SDL_RenderClear的情况下在您的计算机上运行,当您更改配置或在不同平台上运行程序时,它也可能停止工作。 我认为这个警告被放入文档中是有充分理由的。 因此,您可能希望更改算法以在一帧中渲染所有内容,或者,如果您希望保持一帧中添加的新矩形的外观,则在新帧中渲染前一帧中的所有矩形。 或者,您可以使用SDL_SetRenderTarget渲染到SDL_Texture而不是直接渲染到屏幕,这样您就可以确保内容永远不会丢失。


然后 window 停止响应。

这并不奇怪。 您为每个terrain元素调用一次SDL_RenderPresentSDL_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM