Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6375479
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 25, 20262026-05-25T01:37:14+00:00 2026-05-25T01:37:14+00:00

I rewrote Lode’s raycasting tutorial code to make it process events in a separate

  • 0

I rewrote Lode’s raycasting tutorial code to make it process events in a separate thread. I found out that any SDL calls that call xlib functions need to be the main thread, so in this code all functions that rely on xlib are in the main thread.

This is the error I still get randomly from the application:

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

Sometimes when I run it I’ll get this error, but if I run it again it will work.

I’m not for sure how else I need to change the code because all of the graphics processing is in the main thread, the separate thread only deals with events processing. Does anybody know what I’m doing wrong?

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 */ }
        }
    }
}

game.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;
    }
}

game.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);
};
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-25T01:37:14+00:00Added an answer on May 25, 2026 at 1:37 am

    SDL_PollEvent documentation states (clearly for SDL 1.2 at least) that it should only be called from the same thread that set the video mode.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

EDIT: rewrote this to be html only In the following code, why is the
I rewrote some of the code to implement the two answers below, and low
So getting into the new millenia I rewrote my c++ code with: int main(int
UPDATE (2010-12-21): Completely rewrote this question based on tests that I've been doing. Also,
Here's what I got so far. I rewrote the code to simplify things a
I am in the process of modernizing a classic asp application that uses a
I rewrite my old code in new style, like below: #old style open(FD,file); #new
Rewrote the question completely. Please, read it carefully Single note to not confuse you:
I rewrote my config from .ini to .xml and I've got a problem with
Eclipse is warning that I'm using a deprecated method: eventDay = event.getEvent_s_date().getDate(); So I

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.