C 为什么';SDL2渲染器没有在我的窗口中绘制任何内容吗?
我目前正在使用C语言编写一个Chip-8解释器。对于渲染,我使用SDL2库。问题是我不能在屏幕上画矩形。SDL_RenderClear功能也不起作用。可能是Makefile,但我已经尝试将链接器中的console标志更改为windows。有人能帮我吗 我的代码: main.cC 为什么';SDL2渲染器没有在我的窗口中绘制任何内容吗?,c,sdl-2,C,Sdl 2,我目前正在使用C语言编写一个Chip-8解释器。对于渲染,我使用SDL2库。问题是我不能在屏幕上画矩形。SDL_RenderClear功能也不起作用。可能是Makefile,但我已经尝试将链接器中的console标志更改为windows。有人能帮我吗 我的代码: main.c #include "chip.h" #define NO_ROM_INSERTED 1 const int PIXEL_SIZE = 20; const int CHIP_WIDTH = 64; const int C
#include "chip.h"
#define NO_ROM_INSERTED 1
const int PIXEL_SIZE = 20;
const int CHIP_WIDTH = 64;
const int CHIP_HEIGHT = 32;
const int SCREEN_WIDTH = CHIP_WIDTH * PIXEL_SIZE;
const int SCREEN_HEIGHT = CHIP_HEIGHT * PIXEL_SIZE;
int main(int argc, char **argv)
{
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Event event;
int quit = 0;
Chip *chip = (Chip*)malloc(sizeof(Chip));
chipInitialize(chip);
chip->gfx[23] = 0x01;
/*Checks if a ROM file is inserted by an argument*/
if(argc < 2)
{
printf("Error, no Rom inserted");
return NO_ROM_INSERTED;
}
else
{
printf("\n%s loaded into memory\n", argv[argc-1]);
}
loadProgramInMemory(chip, "./Roms/TETRIS");
if(!init(window, renderer, SCREEN_WIDTH, SCREEN_HEIGHT))
{
printf( "Failed to initialize!\n" );
}
else
{
while(!quit)
{
while(SDL_PollEvent(&event) != 0)
{
if(event.type == SDL_QUIT)
{
quit = 1;
}
}
// Clear screen
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0xFF, 0xFF);
SDL_RenderClear(renderer);
for(int i = 0; i < CHIP_HEIGHT; i++)
{
for(int j = 0; j < CHIP_WIDTH; j++)
{
if(chip->gfx[i * CHIP_WIDTH + j] > 0x00) //Translates the one dimensional gfx to two dimensional screen
{
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF);
SDL_Rect fillRect = {CHIP_WIDTH * i, CHIP_HEIGHT * j, PIXEL_SIZE, PIXEL_SIZE};
SDL_RenderFillRect(renderer, &fillRect);
}
}
}
// Update screen
SDL_RenderPresent(renderer);
}
}
close(window, renderer);
free(chip);
return 0;
}
#include "chip.h"
void chipInitialize(Chip *chip)
{
chip->pc = 0x200; // Set program counter to 0x200
chip->opcode = 0x0000; // Reset current opcode
chip->I = 0x0000; // Reset index register
chip->sp = 0x0000; // Reset stack pointer
chip->delayTimer = 0x00; // Reset delay timer
chip->soundTimer = 0x00; // Reset sound timer
for(int i = 0; i < 64 * 32; i++) // Reset the graphics
chip->gfx[i] = 0x00;
for(int i = 0; i < 16; i++) // Reset the stack
chip->stack[i] = 0x0000;
for(int i = 0; i < 4069; i++) // Reset memory
chip->memory[i] = 0x00;
for(int i = 0; i < 16; i++) // Reset registers
chip->V[i] = 0x00;
loadFontInMemory(chip); // Loads the font-set into memory
}
void loadProgramInMemory(Chip *chip, char *program)
{
int bufferSize = 0xFFF - 0x200; // Size of the memory which is reserved for the program
unsigned char buffer[bufferSize];
FILE *ptr;
ptr = fopen(program, "rb");
fread(buffer, bufferSize, 1, ptr);
for(int i = 0; i < bufferSize; i++)
chip->memory[i + 512] = buffer[i]; // Reads in the program and stores it in memory at location 0x200 or 512
}
void loadFontInMemory(Chip *chip)
{
// Zero // Six // C
chip->memory[0x000] = 0xF0; chip->memory[0x01E] = 0xF0; chip->memory[0x03C] = 0xF0;
chip->memory[0x001] = 0x90; chip->memory[0x01F] = 0x80; chip->memory[0x03D] = 0x80;
chip->memory[0x002] = 0x90; chip->memory[0x020] = 0xF0; chip->memory[0x03E] = 0x80;
chip->memory[0x003] = 0x90; chip->memory[0x021] = 0x90; chip->memory[0x03F] = 0x80;
chip->memory[0x004] = 0xF0; chip->memory[0x022] = 0xF0; chip->memory[0x040] = 0xF0;
// One // Seven // D
chip->memory[0x005] = 0x20; chip->memory[0x023] = 0xF0; chip->memory[0x041] = 0xE0;
chip->memory[0x006] = 0x60; chip->memory[0x024] = 0x10; chip->memory[0x042] = 0x90;
chip->memory[0x007] = 0x20; chip->memory[0x025] = 0x20; chip->memory[0x043] = 0x90;
chip->memory[0x008] = 0x20; chip->memory[0x026] = 0x40; chip->memory[0x044] = 0x90;
chip->memory[0x009] = 0x70; chip->memory[0x027] = 0x40; chip->memory[0x045] = 0xE0;
// Two // Eight // E
chip->memory[0x00A] = 0xF0; chip->memory[0x028] = 0xF0; chip->memory[0x046] = 0xF0;
chip->memory[0x00B] = 0x10; chip->memory[0x029] = 0x90; chip->memory[0x047] = 0x80;
chip->memory[0x00C] = 0xF0; chip->memory[0x02A] = 0xF0; chip->memory[0x048] = 0xF0;
chip->memory[0x00D] = 0x80; chip->memory[0x02B] = 0x90; chip->memory[0x049] = 0x80;
chip->memory[0x00E] = 0xF0; chip->memory[0x02C] = 0xF0; chip->memory[0x04A] = 0xF0;
// Three // Nine // F
chip->memory[0x00F] = 0xF0; chip->memory[0x02D] = 0xF0; chip->memory[0x04B] = 0xF0;
chip->memory[0x010] = 0x10; chip->memory[0x02E] = 0x90; chip->memory[0x04C] = 0x80;
chip->memory[0x011] = 0xF0; chip->memory[0x02F] = 0xF0; chip->memory[0x04D] = 0xF0;
chip->memory[0x012] = 0x10; chip->memory[0x030] = 0x10; chip->memory[0x04E] = 0x80;
chip->memory[0x013] = 0xF0; chip->memory[0x031] = 0xF0; chip->memory[0x04F] = 0x80;
// Four // A
chip->memory[0x014] = 0x90; chip->memory[0x032] = 0xF0;
chip->memory[0x015] = 0x90; chip->memory[0x033] = 0x90;
chip->memory[0x016] = 0xF0; chip->memory[0x034] = 0xF0;
chip->memory[0x017] = 0x10; chip->memory[0x035] = 0x90;
chip->memory[0x018] = 0x10; chip->memory[0x036] = 0x90;
// Five // B
chip->memory[0x019] = 0xF0; chip->memory[0x037] = 0xE0;
chip->memory[0x01A] = 0x80; chip->memory[0x038] = 0x90;
chip->memory[0x01B] = 0xF0; chip->memory[0x039] = 0xE0;
chip->memory[0x01C] = 0x10; chip->memory[0x03A] = 0x90;
chip->memory[0x01D] = 0xF0; chip->memory[0x03B] = 0xE0;
}
#include "window.h"
int init(SDL_Window *window, SDL_Renderer *renderer, const
int width, const int height)
{
//Initialization flag
int success = 1;
//Initialize SDL
if( SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
success = 0;
}
else
{
//Create window
window = SDL_CreateWindow( "Chip-8 Emulator", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN );
if( window == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError());
success = 0;
}
else
{
renderer = SDL_CreateRenderer(window, -1, 0);
if(renderer == NULL)
{
printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
success = 0;
}
else
{
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0xFF, 0xFF);
}
}
}
return success;
}
void close(SDL_Window *window, SDL_Renderer* renderer)
{
//Destroy window
SDL_DestroyWindow( window );
window = NULL;
SDL_DestroyRenderer(renderer);
renderer = NULL;
//Quit SDL subsystems
SDL_Quit();
}
chip.c
#include "chip.h"
#define NO_ROM_INSERTED 1
const int PIXEL_SIZE = 20;
const int CHIP_WIDTH = 64;
const int CHIP_HEIGHT = 32;
const int SCREEN_WIDTH = CHIP_WIDTH * PIXEL_SIZE;
const int SCREEN_HEIGHT = CHIP_HEIGHT * PIXEL_SIZE;
int main(int argc, char **argv)
{
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Event event;
int quit = 0;
Chip *chip = (Chip*)malloc(sizeof(Chip));
chipInitialize(chip);
chip->gfx[23] = 0x01;
/*Checks if a ROM file is inserted by an argument*/
if(argc < 2)
{
printf("Error, no Rom inserted");
return NO_ROM_INSERTED;
}
else
{
printf("\n%s loaded into memory\n", argv[argc-1]);
}
loadProgramInMemory(chip, "./Roms/TETRIS");
if(!init(window, renderer, SCREEN_WIDTH, SCREEN_HEIGHT))
{
printf( "Failed to initialize!\n" );
}
else
{
while(!quit)
{
while(SDL_PollEvent(&event) != 0)
{
if(event.type == SDL_QUIT)
{
quit = 1;
}
}
// Clear screen
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0xFF, 0xFF);
SDL_RenderClear(renderer);
for(int i = 0; i < CHIP_HEIGHT; i++)
{
for(int j = 0; j < CHIP_WIDTH; j++)
{
if(chip->gfx[i * CHIP_WIDTH + j] > 0x00) //Translates the one dimensional gfx to two dimensional screen
{
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF);
SDL_Rect fillRect = {CHIP_WIDTH * i, CHIP_HEIGHT * j, PIXEL_SIZE, PIXEL_SIZE};
SDL_RenderFillRect(renderer, &fillRect);
}
}
}
// Update screen
SDL_RenderPresent(renderer);
}
}
close(window, renderer);
free(chip);
return 0;
}
#include "chip.h"
void chipInitialize(Chip *chip)
{
chip->pc = 0x200; // Set program counter to 0x200
chip->opcode = 0x0000; // Reset current opcode
chip->I = 0x0000; // Reset index register
chip->sp = 0x0000; // Reset stack pointer
chip->delayTimer = 0x00; // Reset delay timer
chip->soundTimer = 0x00; // Reset sound timer
for(int i = 0; i < 64 * 32; i++) // Reset the graphics
chip->gfx[i] = 0x00;
for(int i = 0; i < 16; i++) // Reset the stack
chip->stack[i] = 0x0000;
for(int i = 0; i < 4069; i++) // Reset memory
chip->memory[i] = 0x00;
for(int i = 0; i < 16; i++) // Reset registers
chip->V[i] = 0x00;
loadFontInMemory(chip); // Loads the font-set into memory
}
void loadProgramInMemory(Chip *chip, char *program)
{
int bufferSize = 0xFFF - 0x200; // Size of the memory which is reserved for the program
unsigned char buffer[bufferSize];
FILE *ptr;
ptr = fopen(program, "rb");
fread(buffer, bufferSize, 1, ptr);
for(int i = 0; i < bufferSize; i++)
chip->memory[i + 512] = buffer[i]; // Reads in the program and stores it in memory at location 0x200 or 512
}
void loadFontInMemory(Chip *chip)
{
// Zero // Six // C
chip->memory[0x000] = 0xF0; chip->memory[0x01E] = 0xF0; chip->memory[0x03C] = 0xF0;
chip->memory[0x001] = 0x90; chip->memory[0x01F] = 0x80; chip->memory[0x03D] = 0x80;
chip->memory[0x002] = 0x90; chip->memory[0x020] = 0xF0; chip->memory[0x03E] = 0x80;
chip->memory[0x003] = 0x90; chip->memory[0x021] = 0x90; chip->memory[0x03F] = 0x80;
chip->memory[0x004] = 0xF0; chip->memory[0x022] = 0xF0; chip->memory[0x040] = 0xF0;
// One // Seven // D
chip->memory[0x005] = 0x20; chip->memory[0x023] = 0xF0; chip->memory[0x041] = 0xE0;
chip->memory[0x006] = 0x60; chip->memory[0x024] = 0x10; chip->memory[0x042] = 0x90;
chip->memory[0x007] = 0x20; chip->memory[0x025] = 0x20; chip->memory[0x043] = 0x90;
chip->memory[0x008] = 0x20; chip->memory[0x026] = 0x40; chip->memory[0x044] = 0x90;
chip->memory[0x009] = 0x70; chip->memory[0x027] = 0x40; chip->memory[0x045] = 0xE0;
// Two // Eight // E
chip->memory[0x00A] = 0xF0; chip->memory[0x028] = 0xF0; chip->memory[0x046] = 0xF0;
chip->memory[0x00B] = 0x10; chip->memory[0x029] = 0x90; chip->memory[0x047] = 0x80;
chip->memory[0x00C] = 0xF0; chip->memory[0x02A] = 0xF0; chip->memory[0x048] = 0xF0;
chip->memory[0x00D] = 0x80; chip->memory[0x02B] = 0x90; chip->memory[0x049] = 0x80;
chip->memory[0x00E] = 0xF0; chip->memory[0x02C] = 0xF0; chip->memory[0x04A] = 0xF0;
// Three // Nine // F
chip->memory[0x00F] = 0xF0; chip->memory[0x02D] = 0xF0; chip->memory[0x04B] = 0xF0;
chip->memory[0x010] = 0x10; chip->memory[0x02E] = 0x90; chip->memory[0x04C] = 0x80;
chip->memory[0x011] = 0xF0; chip->memory[0x02F] = 0xF0; chip->memory[0x04D] = 0xF0;
chip->memory[0x012] = 0x10; chip->memory[0x030] = 0x10; chip->memory[0x04E] = 0x80;
chip->memory[0x013] = 0xF0; chip->memory[0x031] = 0xF0; chip->memory[0x04F] = 0x80;
// Four // A
chip->memory[0x014] = 0x90; chip->memory[0x032] = 0xF0;
chip->memory[0x015] = 0x90; chip->memory[0x033] = 0x90;
chip->memory[0x016] = 0xF0; chip->memory[0x034] = 0xF0;
chip->memory[0x017] = 0x10; chip->memory[0x035] = 0x90;
chip->memory[0x018] = 0x10; chip->memory[0x036] = 0x90;
// Five // B
chip->memory[0x019] = 0xF0; chip->memory[0x037] = 0xE0;
chip->memory[0x01A] = 0x80; chip->memory[0x038] = 0x90;
chip->memory[0x01B] = 0xF0; chip->memory[0x039] = 0xE0;
chip->memory[0x01C] = 0x10; chip->memory[0x03A] = 0x90;
chip->memory[0x01D] = 0xF0; chip->memory[0x03B] = 0xE0;
}
#include "window.h"
int init(SDL_Window *window, SDL_Renderer *renderer, const
int width, const int height)
{
//Initialization flag
int success = 1;
//Initialize SDL
if( SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
success = 0;
}
else
{
//Create window
window = SDL_CreateWindow( "Chip-8 Emulator", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN );
if( window == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError());
success = 0;
}
else
{
renderer = SDL_CreateRenderer(window, -1, 0);
if(renderer == NULL)
{
printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
success = 0;
}
else
{
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0xFF, 0xFF);
}
}
}
return success;
}
void close(SDL_Window *window, SDL_Renderer* renderer)
{
//Destroy window
SDL_DestroyWindow( window );
window = NULL;
SDL_DestroyRenderer(renderer);
renderer = NULL;
//Quit SDL subsystems
SDL_Quit();
}
让我从一个建议开始——如果你对一个答案感兴趣,请不要让回答你的问题变得比需要的更难。想想它对其他人的看法——一些大量的代码,问题似乎在于没有画任何东西;为什么这个示例必须有6个文件?为什么它依赖于我们没有的外部文件,因此根本无法验证?当然,只要使用init和render,就可以将其压缩到30行的单个文件——实际上,SDL2的任何“hello world”都可以。当它起作用而你的代码不起作用时,你就开始检查有什么不同 现在谈谈你的问题。无法从主循环中绘制任何内容,因为此处的
窗口
和渲染器
为空-它已初始化为空,并且从未设置为任何其他内容。似乎您对函数参数的工作方式有误解-在C中,函数参数是按值传递的,对该值的任何修改都是对本地函数副本进行的。当您传递一个int时,函数将获取该int的副本,并且不会将任何更改推回。如果传递SDL_Window*
,则传递该指针的值(在本例中为NULL
);当您执行SDL\u CreateWindow
时,您将其分配给局部变量,一旦angain无法将其返回给调用者,调用者将保持空值。因此,所有渲染调用都将NULL作为渲染器传递,这自然不是有效的渲染器
在您的关闭中也会出现同样的情况-您试图将传递的副本重置为NULL,但这没有意义,因为您不能修改外部值,只能修改函数本地副本
编程课程经常教授“按值传递”和“按引用传递”,我想这是造成这种混乱的原因之一。我更愿意说,在C中并没有通过引用传递,你们总是传递值,但指针也是一个值。为了能够修改数据,我们传递指向该数据的指针;要改变int,您可以传递int*
,但要改变SDL\u窗口*
,您需要获得指向该指针的指针-SDL\u窗口**
。看看SDL本身是如何做到这一点的:
因此,简而言之,将您的init
设置为intinit(SDL\u窗口**窗口,SDL\u渲染器**渲染器,int宽度,int高度)代码>(此处也不需要const int
,因为它们是宽度和高度的副本),并相应地修改其代码。并在调用后检查window
和renderer
的值(调试器、debug printf、if(window==NULL)
任何事情都会发生)init
可以是
int init(SDL_Window **owindow, SDL_Renderer **orenderer,
int width, int height)
{
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
//Initialization flag
int success = 1;
//Initialize SDL
if( SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
success = 0;
}
else
{
//Create window
window = SDL_CreateWindow( "Chip-8 Emulator", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN );
if( window == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError());
success = 0;
}
else
{
renderer = SDL_CreateRenderer(window, -1, 0);
if(renderer == NULL)
{
printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
success = 0;
}
else
{
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0xFF, 0xFF);
}
}
}
*owindow = window;
*orenderer = renderer;
return success;
}
int init(SDL_窗口**owindow,SDL_渲染器**或渲染器,
整数宽度,整数高度)
{
SDL_Window*Window=NULL;
SDL_渲染器*渲染器=NULL;
//初始化标志
int成功=1;
//初始化SDL
if(SDL_Init(SDL_Init_视频)<0)
{
printf(“SDL无法初始化!SDL_错误:%s\n”,SDL_GetError());
成功=0;
}
其他的
{
//创建窗口
window=SDL_CreateWindow(“芯片8模拟器”,SDL_WINDOWPOS_未定义,SDL_WINDOWPOS_未定义,显示宽度、高度、SDL_窗口);
如果(窗口==NULL)
{
printf(“无法创建窗口!SDL_错误:%s\n”,SDL_GetError());
成功=0;
}
其他的
{
渲染器=SDL_CreateRenderer(窗口,-1,0);
if(渲染器==NULL)
{
printf(“无法创建渲染器!SDL错误:%s\n”,SDL_GetError());
成功=0;
}
其他的
{
SDL_SetRenderDrawColor(渲染器,0xFF,0x00,0xFF,0xFF);
}
}
}
*owindow=窗口;
*Orender=渲染器;
回归成功;
}
当然,对init
的调用必须修改为init(&window,&renderer,SCREEN\u WIDTH,SCREEN\u HEIGHT)
当我们在做的时候,还有两件事:
- 头文件应该有,否则,如果您多次(直接或间接)包含它,将导致问题
- 永远不要调用函数
close
。它将在linux/UNIX系统上崩溃(没有任何可能)。想想另一个没有被广泛使用的操作系统保留的名字
并且不要使用-w
编译器标志。它会抑制所有警告,防止编译器提示您可能的错误,您需要更多的警告(从-Wall
开始),而不是更少。