gpt4 book ai didi

c++ - 来自多线程 SDL 应用程序的 InvalidCursor 错误

转载 作者:行者123 更新时间:2023-11-30 03:06:02 24 4
gpt4 key购买 nike

我重写了 Lode's raycasting tutorial代码使其在单独的线程中处理事件。我发现任何调用 xlib 函数的 SDL 调用都需要是主线程,所以在这段代码中所有依赖 xlib 的函数都在主线程中。

这是我仍然随机从应用程序中得到的错误:

X Error of failed request:  BadCursor (invalid Cursor parameter)
Major opcode of failed request: 95 (X_FreeCursor)
Resource id in failed request: 0x4a0000b
Serial number of failed request: 108
Current serial number in output stream: 107

有时当我运行它时我会得到这个错误,但如果我再次运行它就会工作。

我不确定我还需要如何更改代码,因为所有图形处理都在主线程中进行,单独的线程只处理事件处理。有人知道我做错了什么吗?

raycaster.cpp

#include <iostream>
#include <cmath>

#include "SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_ttf.h"

#include "game.hpp"

using std::cout;

static int SCREENW = 500;
static int SCREENH = 500;
static int BPP = 32;

int events_loop(void* data);

int main(int argc, char** argv) {
SDL_Init(SDL_INIT_EVERYTHING | SDL_INIT_EVENTTHREAD);
TTF_Init();

SDL_Thread* events;
Game_state* gs = new Game_state();
events = SDL_CreateThread(events_loop, (void*)gs);

SDL_Surface* screen = SDL_SetVideoMode(SCREENW, SCREENH, BPP, SDL_SWSURFACE);
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
SDL_WM_SetCaption("Raycaster (non-textured)", NULL);

Game* game = new Game(screen, SCREENW, SCREENH, BPP);

//BEGIN GAME VARIABLES
//game map
int map[Game::MAP_WIDTH][Game::MAP_WIDTH] = {
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 4, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 4, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1 },
{ 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
};

//direction variables
double pos_x = Game::PLAYER_START_X;
double pos_y = Game::PLAYER_START_Y;
double dir_x = -1; double old_dir_x;
double dir_y = 0;
int map_x, map_y;

//timing variables
double start_ticks = 0;
double end_ticks = 0;
double frame_time = 0;

//camera varibales
double camera_x;
double ray_pos_x, ray_pos_y;
double ray_dir_x, ray_dir_y;
double plane_x = 0; double plane_y = Game::FOV; double old_plane_x;
int line_height;

//DDA variables
double side_dist_x, side_dist_y;
double delta_dist_x, delta_dist_y;
double perpen_wall_dist;
int step_x, step_y;
bool EW_side; //east west side hit, negative implies north south side
bool hit = false;

//drawing variables
int draw_low_y, draw_high_y;
int r, g, b;

//movement variables
double move_speed, rotation_speed;

//BEGIN RENDERING LOGIC
while(gs->over == false) {
start_ticks = SDL_GetTicks();

//lock screen to modify its pixels
/*if(SDL_MUSTLOCK(screen)) {
SDL_LockSurface(screen);
}*/

game->clear_screen();

//BEGIN DRAWING PIXELS
for(int x = 0; x < SCREENW; x++) {
//set up camera
camera_x = 2 * x / (double(SCREENW) - 1);
ray_pos_x = pos_x; ray_pos_y = pos_y;

ray_dir_x = dir_x + plane_x * camera_x;
ray_dir_y = dir_y + plane_y * camera_x;

delta_dist_x = sqrt(1 + (ray_dir_y * ray_dir_y) / (ray_dir_x * ray_dir_x));
delta_dist_y = sqrt(1 + (ray_dir_x * ray_dir_x) / (ray_dir_y * ray_dir_y));

//what box are we in?
map_x = int(ray_pos_x); map_y = int(ray_pos_y);

//calculate step and side_dist
if(ray_dir_x < 0) {
step_x = -1;
side_dist_x = (ray_pos_x - map_x) * delta_dist_x;
}
else {
step_x = 1;
side_dist_x = (map_x + 1.0 - ray_pos_x) * delta_dist_x;
}

if(ray_dir_y < 0) {
step_y = -1;
side_dist_y = (ray_pos_y - map_y) * delta_dist_y;
}
else {
step_y = 1;
side_dist_y = (map_y + 1.0 - ray_pos_y) * delta_dist_y;
}

//step using DDA until a wall is hit
hit = false;
while(hit == false) {
if(side_dist_x < side_dist_y) {
side_dist_x += delta_dist_x;
map_x += step_x;
EW_side = false;
}
else {
side_dist_y += delta_dist_y;
map_y += step_y;
EW_side = true;
}

if(map[map_x][map_y] > 0) { hit = true; }
}

//calculate dist from camera to wall that was hit
if(EW_side == false) {
perpen_wall_dist = fabs((map_x - ray_pos_x + (1 - step_x) / 2) / ray_dir_x);
}
else {
perpen_wall_dist = fabs((map_y - ray_pos_y + (1 - step_y) / 2) / ray_dir_y);
}

//calculate line height from perpendicular wall distance
line_height = abs(int(SCREENH / perpen_wall_dist));

//calculate how high to draw the line
draw_high_y = -line_height / 2 + SCREENH / 2;
if(draw_high_y < 0) { draw_high_y = 0; }

draw_low_y = line_height / 2 + SCREENH / 2;
if(draw_low_y >= SCREENH) { draw_low_y = SCREENH - 1; }
if(draw_low_y < 0) { draw_low_y = 0; } //added (shouldn't need to be here)

//finally draw the line
game->draw_line(x, draw_low_y, draw_high_y, map[map_x][map_y], EW_side);
}

//unlock screen for blitting
/*if(SDL_MUSTLOCK(screen)) {
SDL_UnlockSurface(screen);
}*/

//calculate timing and print the FPS
end_ticks = SDL_GetTicks();
frame_time = (end_ticks - start_ticks) / 1000.0;

game->blit_fps(frame_time);
game->blit_location(map_x, map_y);

if(SDL_Flip(screen) != 0) {
cout << "ERROR: couldn't draw to the screen <" << SDL_GetError() << ">\n";
}

//BEGIN CALCULATING NEXT STEP
//calculate new direction based on frames drawn
move_speed = frame_time * Game_state::MOVEMENT_MULTIPLIER;
rotation_speed = frame_time * Game_state::ROTATION_MULTIPLIER;

//process movement for next frame
if(gs->movement_forward == Game_state::MOVE_UP) {
if(map[int(pos_x + dir_x * move_speed)][int(pos_y)] == 0) { pos_x += dir_x * move_speed; }
if(map[int(pos_x)][int(pos_y + dir_y * move_speed)] == 0) { pos_y += dir_y * move_speed; }
}
else if(gs->movement_forward == Game_state::MOVE_DOWN) {
if(map[int(pos_x - dir_x * move_speed)][int(pos_y)] == 0) { pos_x -= dir_x * move_speed; }
if(map[int(pos_x)][int(pos_y - dir_y * move_speed)] == 0) { pos_y -= dir_y * move_speed; }
}

if(gs->movement_side == Game_state::MOVE_RIGHT) {
old_dir_x = dir_x;
dir_x = dir_x * cos(-rotation_speed) - dir_y * sin(-rotation_speed);
dir_y = old_dir_x * sin(-rotation_speed) + dir_y * cos(-rotation_speed);

old_plane_x = plane_x;
plane_x = plane_x * cos(-rotation_speed) - plane_y * sin(-rotation_speed);
plane_y = old_plane_x * sin(-rotation_speed) + plane_y * cos(-rotation_speed);
}
else if(gs->movement_side == Game_state::MOVE_LEFT) {
old_dir_x = dir_x;
dir_x = dir_x * cos(rotation_speed) - dir_y * sin(rotation_speed);
dir_y = old_dir_x * sin(rotation_speed) + dir_y * cos(rotation_speed);

old_plane_x = plane_x;
plane_x = plane_x * cos(rotation_speed) - plane_y * sin(rotation_speed);
plane_y = old_plane_x * sin(rotation_speed) + plane_y * cos(rotation_speed);
}
}

delete gs;
delete game;

return 0;
}

int events_loop(void* data) {
Game_state* gs = (Game_state*)data;

SDL_Event evt;
while(1) {
while(SDL_PollEvent(&evt)) {
if(evt.type == SDL_QUIT) { gs->over = true; cout << "quit\n"; return 0; }
else if(evt.type == SDL_KEYDOWN) {
if(evt.key.keysym.sym == SDLK_w) {
gs->move(Game_state::MOVE_UP);
}
else if(evt.key.keysym.sym == SDLK_s) {
gs->move(Game_state::MOVE_DOWN);
}
else if(evt.key.keysym.sym == SDLK_a) {
gs->move(Game_state::MOVE_LEFT);
}
else if(evt.key.keysym.sym == SDLK_d) {
gs->move(Game_state::MOVE_RIGHT);
}
else if(evt.key.keysym.sym == SDLK_ESCAPE) { gs->over = true; cout << "escape\n"; return 0; }
}
else if(evt.type == SDL_KEYUP) {
if(evt.key.keysym.sym == SDLK_w) {
gs->stop_move(Game_state::MOVE_UP);
}
else if(evt.key.keysym.sym == SDLK_s) {
gs->stop_move(Game_state::MOVE_DOWN);
}
else if(evt.key.keysym.sym == SDLK_a) {
gs->stop_move(Game_state::MOVE_LEFT);
}
else if(evt.key.keysym.sym == SDLK_d) {
gs->stop_move(Game_state::MOVE_LEFT);
}
}
else { /* ignore */ }
}
}
}

游戏.cpp

#include <iostream>

#include "game.hpp"

using std::cout; using std::endl;

Game_state::Game_state() {
movement_forward = NO_MOVE;
movement_side = NO_MOVE;
over = false;
}

void Game_state::move(int direction) {
switch(direction) {
case NO_MOVE:
break;

case MOVE_UP:
if(movement_forward == MOVE_DOWN) { movement_forward = NO_MOVE; }
else { movement_forward = MOVE_UP; }
break;

case MOVE_DOWN:
if(movement_forward == MOVE_UP) { movement_forward = NO_MOVE; }
else { movement_forward = MOVE_DOWN; }
break;

case MOVE_LEFT:
if(movement_side == MOVE_RIGHT) { movement_side = NO_MOVE; }
else { movement_side = MOVE_LEFT; }
break;

case MOVE_RIGHT:
if(movement_side == MOVE_LEFT) { movement_side = NO_MOVE; }
else { movement_side = MOVE_RIGHT; }
break;

default:
cout << "ERROR: invalid movement in Game_state::move() at time " << SDL_GetTicks() << endl;
break;
}
}

void Game_state::stop_move(int direction) {
switch(direction) {
case NO_MOVE:
break;

case MOVE_UP:
case MOVE_DOWN:
movement_forward = NO_MOVE;
break;

case MOVE_RIGHT:
case MOVE_LEFT:
movement_side = NO_MOVE;
break;

default:
cout << "ERROR: invalid movement in Game_state::stop_move() at time " << SDL_GetTicks() << endl;
break;
}
}

Game::Game(SDL_Surface* scr, int w, int h, int b) {
screen = scr;
scr_w = w; scr_h = h; bpp = b;

//fps printing vars
fps_location.x = 0; fps_location.y = 0;
fps_font = TTF_OpenFont("/usr/share/fonts/truetype/ttf-liberation/LiberationMono-Regular.ttf", 24);
fps_color.r = 0; fps_color.g = 0; fps_color.b = 255; //blue

//location printing vars
location_font = TTF_OpenFont("/usr/share/fonts/truetype/ttf-liberation/LiberationMono-Regular.ttf", 18);

//determine how high the font surface should be from the bottom
location_color.r = 0; location_color.g = 90; location_color.b = 240;
location_surface = TTF_RenderText_Solid(location_font, location_buffer, location_color);
location_location.x = 0; location_location.y = scr_h - location_surface->clip_rect.h;

//set up the wall colors
wall_color[OUTSIDE_WALL].r = 255; wall_color[OUTSIDE_WALL].g = 255; wall_color[OUTSIDE_WALL].b = 255;
wall_color[RED_WALL].r = 255; wall_color[RED_WALL].g = 0; wall_color[RED_WALL].b = 0;
wall_color[GRAY_WALL].r = 160; wall_color[GRAY_WALL].g = 160; wall_color[GRAY_WALL].b = 160;
wall_color[GOLD_WALL].r = 232; wall_color[GOLD_WALL].g = 211; wall_color[GOLD_WALL].g = 34;
}

void Game::clear_screen() {
SDL_FillRect(screen, &screen->clip_rect, SDL_MapRGB(screen->format, 0, 0, 0));
}

void Game::blit_fps(double frame_time) {
sprintf(fps_buffer, "FPS: %3.3f", 1.0 / frame_time);
fps_surface = TTF_RenderText_Solid(fps_font, fps_buffer, fps_color);
if(SDL_BlitSurface(fps_surface, NULL, screen, &fps_location) != 0) {
cout << "ERROR: couldn't blit the FPS surface <" << SDL_GetError() << ">\n";
}
}

void Game::blit_location(int x, int y) {
sprintf(location_buffer, "location: %d, %d", x, y);
location_surface = TTF_RenderText_Solid(location_font, location_buffer, location_color);
if(SDL_BlitSurface(location_surface, NULL, screen, &location_location) != 0) {
cout << "ERROR: couldn't blit the location surface <" << SDL_GetError() << ">\n";
}
}

//high_y means the y coord closest to the top of the screen
void Game::draw_line(int x, int low_y, int high_y, int wall_type, bool EW_side) {
//cout << "high_y = " << high_y << " low_y = " << low_y << endl;
int r = wall_color[wall_type].r;
int g = wall_color[wall_type].g;
int b = wall_color[wall_type].b;
if(EW_side == true) { r /= 2; g /= 2; b /= 2; }
//cout << "r = " << r << " g = " << g << " b = " << b << "\n";

//draw ceiling
/*for(int y = 0; y < high_y - 1; y++) {
put_pixel(x, y, 0, 255, 90);
}*/

for(int y = high_y; y <= low_y; y++) {
put_pixel(x, y, r, g, b);
}

//draw floor (checkered)
/*for(int y = low_y + 1; y <= scr_h; y++) {
if(x % 20 > 10 && y % 20 > 10) {
put_pixel(x, y, 255, 255, 255);
}
}*/
}

void Game::put_pixel(int x, int y, int r, int g, int b) {
int bpp = screen->format->BytesPerPixel;
Uint8* p = (Uint8*)screen->pixels + y * screen->pitch + x * bpp;
Uint32 pixel = SDL_MapRGB(screen->format, r, g, b);

switch(bpp) {
case 1:
*p = pixel;
break;

case 2:
*(Uint16*)p = pixel;
break;

case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
}
else {
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;

case 4:
*(Uint32*)p = pixel;
break;
}
}

游戏.hpp

#include "SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_ttf.h"

class Game_state {
public:
//movement statics
static const int NO_MOVE = 0;
static const int MOVE_UP = 1;
static const int MOVE_DOWN = 2;
static const int MOVE_LEFT = 3;
static const int MOVE_RIGHT = 4;
static const double MOVEMENT_MULTIPLIER = 5.0;
static const double ROTATION_MULTIPLIER = 3.0;

int movement_forward;
int movement_side;
bool over;

Game_state();
void move(int direction);
void stop_move(int direction);
};

class Game {
private:
//fps vars
char fps_buffer[50];
TTF_Font* fps_font;
SDL_Surface* fps_surface;
SDL_Rect fps_location;
SDL_Color fps_color;

//location vars
char location_buffer[24];
TTF_Font* location_font;
SDL_Surface* location_surface;
SDL_Rect location_location;
SDL_Color location_color;

void put_pixel(int x, int y, int r, int g, int b);

public:
//game statics
static const int MAP_WIDTH = 20;
static const int MAP_HEIGHT = 20;
static const double FOV = 0.66;
static const int PLAYER_START_X = 1;
static const int PLAYER_START_Y = 1;

//wall options
static const int FLOOR = 0;
static const int OUTSIDE_WALL = 1;
static const int RED_WALL = 2;
static const int GRAY_WALL = 3;
static const int GOLD_WALL = 4;

//game variables
SDL_Surface* screen;
int scr_w;
int scr_h;
int bpp;

SDL_Color wall_color[5];

Game(SDL_Surface* scr, int w, int h, int b);
void clear_screen();
void blit_fps(double frame_time);
void blit_location(int x, int y);
void draw_line(int x, int low_y, int high_y, int wall_type, bool EW_side);
};

最佳答案

SDL_PollEvent documentation states (至少对于 SDL 1.2 来说很明显)它应该只从设置视频模式的同一线程调用。

关于c++ - 来自多线程 SDL 应用程序的 InvalidCursor 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7155276/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com