使用Vs Code调试C SDL2游戏,如何在运行时加断点?

Using Vs Code to debug a C SDL2 Game, how do I add breakpoints while running?

我正在使用 Vs Code 作为我的 IDE。

我已经想出如何添加断点并让调试器命中它们,但前提是它们是在编译之前添加的。在其他游戏开发环境中,我习惯于在我想停止游戏并检查时添加断点。

我的游戏在运行时有什么方法可以添加断点吗?


这是我正在 运行 构建我的游戏的命令。

gcc -std=c17 main.c -g -I "C:\Program Files\clib\SDL2\include" -L "C:\Program Files\clib\SDL2\lib" -Wall -lmingw32 -lSDL2main -lSDL2 -o game

这是我从互联网上复制粘贴的小“游戏”,以防有助于提供上下文。它是一个可以移动和跳跃的红色小方块。

#include <stdio.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
#define WIDTH 640
#define HEIGHT 480
#define SIZE 200
#define SPEED 600
#define GRAVITY 60
#define FPS 60
#define JUMP -1200

int main(int argc, char *argv[])
{
    /* Initializes the timer, audio, video, joystick,
    haptic, gamecontroller and events subsystems */
    if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
    {
        printf("Error initializing SDL: %s\n", SDL_GetError());
        return 0;
    }

    /* Create a window */
    SDL_Window *wind = SDL_CreateWindow(
        "Hello Platformer!",
        SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED,
        WIDTH, 
        HEIGHT, 
        0
    );

    if (!wind)
    {
        printf("Error creating window: %s\n", SDL_GetError());
        SDL_Quit();
        return 0;
    }

    /* Create a renderer */
    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;
    }

    /* Main loop */
    bool running = true, 
        jump_pressed = false, 
        can_jump = true, 
        left_pressed = false, 
        right_pressed = false;

    float x_pos = (WIDTH - SIZE) / 2, y_pos = (HEIGHT - SIZE) / 2, x_vel = 0, y_vel = 0;
    SDL_Rect rect = {(int)x_pos, (int)y_pos, SIZE, SIZE};
    SDL_Event event;

    while (running)
    {
        /* Process events */
        while (SDL_PollEvent(&event))
        {
            switch (event.type)
            {
            case SDL_QUIT:
                running = false;
                break;
            case SDL_KEYDOWN:
                switch (event.key.keysym.scancode)
                {
                case SDL_SCANCODE_SPACE:
                    jump_pressed = true;
                    break;
                case SDL_SCANCODE_A:
                case SDL_SCANCODE_LEFT:
                    left_pressed = true;
                    break;
                case SDL_SCANCODE_D:
                case SDL_SCANCODE_RIGHT:
                    right_pressed = true;
                    break;
                default:
                    break;
                }
                break;
            case SDL_KEYUP:
                switch (event.key.keysym.scancode)
                {
                case SDL_SCANCODE_SPACE:
                    jump_pressed = false;
                    break;
                case SDL_SCANCODE_A:
                case SDL_SCANCODE_LEFT:
                    left_pressed = false;
                    break;
                case SDL_SCANCODE_D:
                case SDL_SCANCODE_RIGHT:
                    right_pressed = false;
                    break;
                default:
                    break;
                }
                break;
            default:
                break;
            }
        }
        
        /* Clear screen */
        SDL_SetRenderDrawColor(rend, 0, 0, 0, 255);
        SDL_RenderClear(rend);
        
        /* Move the rectangle */
        x_vel = (right_pressed - left_pressed) * SPEED;
        y_vel += GRAVITY;
        
        if (jump_pressed && can_jump)
        {
            can_jump = false;
            y_vel = JUMP;
        }
        
        x_pos += x_vel / 60;
        y_pos += y_vel / 60;
        
        if (x_pos <= 0) x_pos = 0;
        if (x_pos >= WIDTH - rect.w) x_pos = WIDTH - rect.w;
        if (y_pos <= 0) y_pos = 0;
        if (y_pos >= HEIGHT - rect.h)
        {
            y_vel = 0;
            y_pos = HEIGHT - rect.h;
            if (!jump_pressed)
                can_jump = true;
        }

        rect.x = (int)x_pos;
        rect.y = (int)y_pos;

        /* Draw the rectangle */
        SDL_SetRenderDrawColor(rend, 255, 0, 0, 255);
        SDL_RenderFillRect(rend, &rect);

        /* Draw to window and loop */
        SDL_RenderPresent(rend);
        SDL_Delay(1000 / FPS);
    }
    
    /* Release resources */
    SDL_DestroyRenderer(rend);
    SDL_DestroyWindow(wind);
    SDL_Quit();
    return 0;
}

添加检查点后,您需要在其终端中按 CtrlC 向您的程序发送 SIGINT。

这将暂停程序。使用调试器恢复它后,任何先前设置的检查点都将起作用。

我没有使用普通 C++ 扩展的经验,但至少在 Native Debug 扩展中,您需要将 "windows": {"terminal": ""}, 添加到 launch.json 中的当前配置,以获取您的应用程序的专用终端。