Thread: Raycasting

  1. #1
    Registered User
    Join Date
    Nov 2004
    Posts
    2

    Smile Raycasting

    Hello all, I am new to the forums. I basically need help with my code. A while back I started to create a simple non-textured raycaster which I am failing. I read a few tutorials (no-code) and I got a great understanding of the Raycasting theory however I lack skill in my trigonometry which has made my end result look poor. Before I post my source code I will explain the modules. (Don't worry they are small) I basically have 3 modules.

    1) Hero.h (which contains my Hero class, short for now)
    2) Globals.h (just global data, screen_height, FOV etc)
    3) cast.cpp (main source, where my bugs are)

    I am programming in C++ and using the Allegro game library.

    Problems i'm having:
    1) walking, sometimes walls don't change in height however turning seems ok.

    2) I'm not sure how to correctly cast my rays (checking grid intersections) so my code might be skipping walls.

    3) please point out the rest.

    OK, here is the code...

    HERO.H
    Code:
    class Player
    {
      public:
        Player( ):posX(128),  
                  posY(128),                       // grid (1,1)
                  facing_direction(90.0f)     // facing 90* degrees
                  {}
        // use default destructor for now
    
        // data members
        int posX;
        int posY;
        float facing_direction;
    };
    GLOBALS.H
    Code:
    typedef unsigned short USHORT;
    
    const USHORT WALL = 1;
    const USHORT MOVE = 4; // number of units to move in a given direction
    
    const USHORT SCREEN_WIDTH  = 640;
    const USHORT SCREEN_HEIGHT = 480;
    const USHORT HALF_SCREEN_HEIGHT = 240;
    
    const USHORT GRID_SIZE = 64;
    
    const float FOV = 60.0f;
    
    int wall_distance[SCREEN_WIDTH];
    
    float angle[SCREEN_WIDTH];
    
    // 1 = wall
    // 0 = no wall
    
    int map[6][6] = {{ 1, 1, 1, 1, 1, 1 },
                     { 1, 0, 0, 0, 0, 1 },
                     { 1, 0, 0, 0, 0, 1 },
                     { 1, 0, 0, 0, 0, 1 },
                     { 1, 0, 0, 0, 0, 1 },
                     { 1, 1, 1, 1, 1, 1 }};
    CAST.CPP
    Code:
    #include <math.h>
    #include <allegro.h>
    #include <cstdlib>
    #include "globals.h"
    #include "hero.h"
    
    BITMAP *buffer;
    
    // prototypes
    void calculateAngles(Player & ref);
    void castRays(Player & ref);
    void drawScene(void);
    // end of prototypes
    
    int main(void)
    {
      // setup
      allegro_init();
      install_keyboard();
      set_color_depth(16);
      set_gfx_mode(GFX_AUTODETECT, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
      buffer = create_bitmap(SCREEN_WIDTH, SCREEN_HEIGHT);
      for(int i=0;i<SCREEN_WIDTH;i++)
        wall_distance[i] = 0;
      // end of setup
    
      // instantiation
      Player Hero;
      Player & HeroRef = Hero;
      // end of instantiation
    
      // main loop
      while(!key[KEY_ESC])
      {
        _sleep(2); // free some CPU time 
    
        // check for movements
        if(key[KEY_RIGHT])
        {
          Hero.facing_direction += 0.10f;
        }
        if(key[KEY_LEFT])
        {
          Hero.facing_direction -= 0.10f;
        }
        if(key[KEY_DOWN])
        {
          Hero.posY++;
        }
        if(key[KEY_UP])
        {
          Hero.posY--;
        }
    
        // calculate ray angles to later cast
        calculateAngles(HeroRef);
    
        // cast rays based on calculated angles
        castRays(HeroRef);
    
        // draw vertical line slices to the buffer based on wall distance
        drawScene();
    
        // show buffer to the screen
        acquire_screen();
        blit(buffer, screen, 0, 0, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
        release_screen();
        clear_bitmap(buffer);
    
        // reset wall_distance
        for(int i=0;i<SCREEN_WIDTH;i++)
          wall_distance[i] = 0;
      }
    
      // clean up
      destroy_bitmap(buffer);
      // end of clean up
      return(0);
    }
    END_OF_MAIN();
    
    // function definitions
    void calculateAngles(Player & ref)
    {
      for(int i=0;i<SCREEN_WIDTH;i++)
      {
        angle[i] = ref.facing_direction + (( i * (FOV / 320.0f)) - (FOV / 2.0f));
    
        if(angle[i] < 0.0f)
          angle[i] += 360.0f;
        if(angle[i] >= 360.0f)
          angle[i] -= 360.0f;
      }
    }
    END_OF_FUNCTION(calculateAngles(Player & ref));
    
    void castRays(Player & ref)
    {
      int ray_x;
      int ray_y;
    
      for(int i=0;i<SCREEN_WIDTH;i++)
      {
        ray_x = ref.posX;
        ray_y = ref.posY;
    
        // allow ray to travel until a wall is found
        while(map[ray_x/GRID_SIZE][ray_y/GRID_SIZE] != WALL)
        {
          ray_x =  int(GRID_SIZE/4 * cos(angle[i] * M_PI / 180.0f));
          ray_y = -int(GRID_SIZE/4 * sin(angle[i] * M_PI / 180.0f)); 
        }
    
        // wall found, calculate the distance from the player 
        wall_distance[i] = abs((ray_y - ref.posY) / sin(ref.facing_direction));
      }
    }
    END_OF_FUNCTION(castRays(Player & ref));
    
    void drawScene(void)
    {
      // draw vertical lines
      for(int i=0;i<SCREEN_WIDTH;i++)
      {
        vline(buffer, i, HALF_SCREEN_HEIGHT-(wall_distance[i]/2), wall_distance[i], makecol(3, 170, 218));
      }
    }
    END_OF_FUNCTION(drawScene(void));
    I have tried to give as much information I can but if i'm missing something please let me know. Thanks for reading this.

    Damien
    Last edited by damien_casaveli; 11-26-2004 at 02:29 AM.

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Raycasting can be done several ways.

    1. Tan(theta)=opp/adj. Split rays into x and y components. So on a grid 100x100 narrow the intersections test down to 10 per axis instead of 100x100.

    2. Use Bresehnam's line algorithm to trace your ray through the map.
    3. Find left and right extents of raycast and linear interpolate from left to right for distance steps.

  3. #3
    Registered User
    Join Date
    Nov 2004
    Posts
    2
    So it's best not to use cos and sin? Where can I find that Algorithm?

    Damien

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Look up PXDTUT7 - if I recall the number correctly. It's over at www.programmersheaven.com

    Also you may want to go to this site. www.peroxide.dk. They were creating Ultima 1: A Legend is Reborn and at one time it was sanctioned by Origin. However that has since fallen through and they have renamed the project Era. You may be able to email Telemachos asking for the previous tutorials he put out. It seems that one's earlier than PXDTUT9 are no longer available on his site.
    Last edited by VirtualAce; 11-28-2004 at 08:34 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Raycasting code
    By BMJ in forum Game Programming
    Replies: 2
    Last Post: 09-07-2004, 03:26 PM
  2. Doors in a raycasting engine
    By lmaster in forum Game Programming
    Replies: 3
    Last Post: 06-09-2004, 11:57 PM
  3. raycasting sprites
    By lmaster in forum Game Programming
    Replies: 1
    Last Post: 12-22-2003, 12:34 AM
  4. raycasting
    By Nat_the_Gnat in forum Game Programming
    Replies: 3
    Last Post: 04-15-2002, 09:04 AM
  5. Raycasting Tutorials??..?.?.//.?>?
    By kaygee in forum Game Programming
    Replies: 9
    Last Post: 01-26-2002, 06:06 PM