使用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
中的当前配置,以获取您的应用程序的专用终端。
我正在使用 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
中的当前配置,以获取您的应用程序的专用终端。