我正在关注 Pikuma 的这篇教程,了解如何设置基本的 C/SDL2 游戏循环,一切都运行得非常好。我能够完成教程并且我的程序运行良好。
当我尝试将代码拆分为多个文件时,问题出现了(在教程中,除了一些常量声明之外,他在主函数中执行了所有操作)
我仍然可以创建窗口并删除它,并且仍然可以调用渲染函数。但渲染函数无法识别我的渲染器。它本来应该在灰色背景中绘制一条简单的红线,但自从我将函数分成不同的文件后,它就不再工作了。
这是我的文件和代码的排列方式:
main.c
#include <stdio.h>
#include <SDL2/SDL.h>
#include "./constants.h"
#include "./init_and_destroy.h"
#include "./render.h"
//globals
int game_is_running = FALSE;
SDL_Window* my_window = NULL;
SDL_Renderer* my_renderer = NULL;
int last_frame_time = 0;
void setup() {
}
void process_input() {
SDL_Event event;
SDL_PollEvent(&event); //reference to event
switch (event.type) {
case SDL_QUIT:
game_is_running = FALSE;
break;
case SDL_KEYDOWN:
if(event.key.keysym.sym == SDLK_ESCAPE)
game_is_running = FALSE;
break;
}
}
void update() {
//---------------------------------FPS AND DELTA_TIME LOGIC---------------------------------------
//caping frame rate
int time_to_wait = FRAME_TARGET_TIME - (SDL_GetTicks() - last_frame_time);
if (time_to_wait > 0 && time_to_wait <= FRAME_TARGET_TIME) {
SDL_Delay(time_to_wait);
}
//delta time in seconds
float delta_time = (SDL_GetTicks() - last_frame_time) / 1000.0f;
last_frame_time = SDL_GetTicks();
//------------------------------------------------------------------------------------------------
//UPDATE LOGIC GOES HERE
}
int main() {
game_is_running = initialize_window(my_window, my_renderer);
setup();
while(game_is_running) {
process_input();
update();
render(my_renderer);
}
destroy_window(my_window, my_renderer);
return 0;
}
init_and_destroy.c
#include <stdio.h>
#include <SDL2/SDL.h>
#include "./constants.h"
#include "./init_and_destroy.h"
int initialize_window(SDL_Window* window, SDL_Renderer* renderer) {
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
fprintf(stderr, "Error initializing SDL.\n");
return FALSE;
}
window = SDL_CreateWindow(
"My Window",
SDL_WINDOWPOS_CENTERED, //x position
SDL_WINDOWPOS_CENTERED, //y position
WINDOW_WIDTH,
WINDOW_HEIGHT,
0
);
if(!window) {
fprintf(stderr, "Error creating SDL Window.\n");
return FALSE;
}
renderer = SDL_CreateRenderer(window, -1, 0);
if(!renderer) {
fprintf(stderr, "Error creating SDL Renderer.\n");
return FALSE;
}
return TRUE;
}
void destroy_window(SDL_Window* window, SDL_Renderer* renderer) {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
渲染.c
#include <stdio.h>
#include <SDL2/SDL.h>
#include "./constants.h"
#include "./render.h"
void render(SDL_Renderer* renderer) {
SDL_SetRenderDrawColor(renderer, 50, 50, 50, 255);
SDL_RenderClear(renderer);
//draw a red line
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
for(int i = 0; i < WINDOW_WIDTH; i++) {
SDL_RenderDrawPoint(renderer, i, i);
}
SDL_RenderPresent(renderer); //swap buffer
}
和我的头文件:
渲染.h
#ifndef RENDER
#define RENDER
void render(SDL_Renderer* renderer);
#endif
init_and_destroy.h
#ifndef INIT_AND_DESTROY
#define INIT_AND_DESTROY
int initialize_window(SDL_Window* window, SDL_Renderer* renderer);
void destroy_window(SDL_Window* window, SDL_Renderer* renderer);
#endif
我尝试只声明渲染函数而不传递任何参数,现在我尝试将 SDL_Renderer 作为参数传递,但仍然没有任何作用,我只能看到一个黑色的窗口。
问题是您将
SDL_Window*
和 SDL_Renderer*
发送到 initialize_window
。为了让您在 main
中定义的变量分配 initialize_window
中的值,您需要将 pointers 发送到这些指针,以便您分配的内容在调用站点可用。
示例:
init_and_destroy.h
:
int initialize_window(SDL_Window** window, SDL_Renderer** renderer);
// ^^ ^^
void destroy_window(SDL_Window* window, SDL_Renderer* renderer);
init_and_destroy.c
:
int initialize_window(SDL_Window** window, SDL_Renderer** renderer) {
// ^^ ^^
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
fprintf(stderr, "Error initializing SDL.\n");
return FALSE;
}
*window = SDL_CreateWindow(
// ^
"My Window",
SDL_WINDOWPOS_CENTERED, //x position
SDL_WINDOWPOS_CENTERED, //y position
WINDOW_WIDTH,
WINDOW_HEIGHT,
0
);
if(!*window) {
// ^
fprintf(stderr, "Error creating SDL Window.\n");
return FALSE;
}
*renderer = SDL_CreateRenderer(*window, -1, 0);
// ^
if(!*renderer) {
// ^
fprintf(stderr, "Error creating SDL Renderer.\n");
return FALSE;
}
return TRUE;
}
main.c
:
int main() {
SDL_Window* my_window = NULL; // no reason to have these global
SDL_Renderer* my_renderer = NULL;
game_is_running = initialize_window(&my_window, &my_renderer);
// ^ ^
//...
}