xboxscene.org forums

Author Topic: Wrote This Xbox Raycaster Example Code. (here Is Both Source And Xbe)  (Read 266 times)

miker00lz

  • Archived User
  • Newbie
  • *
  • Posts: 4

CODE
#include
#include
#include
#include "hal/fileio.h"
#include

#include "string.h"
#include "stdio.h"
#include
#include

unsigned char *fb;
unsigned char *pb;
int width = 640;
int height = 480;
int bpp = 32; //should work with either 24 or 32 bit mode
int pixmulty;
int pixmultx;

#define mapWidth 24
#define mapHeight 24

int worldMap[mapWidth][mapHeight]=
{
  {1,1,1,1,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,0,0,0,0,1},
  {1,0,0,0,0,0,0,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,0,0,0,0,1},
  {1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1},
  {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1},
  {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1},
  {1,0,0,0,0,0,0,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,0,0,0,0,1},
  {1,0,0,0,0,0,0,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,0,0,0,0,1},
  {1,0,0,0,0,0,0,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,0,0,0,0,1},
  {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  {1,4,4,4,4,4,4,4,4,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,1,1,1,1}
};

void XPlot(int xp, int yp, BYTE r, BYTE g, BYTE b) {
    pb[(yp*pixmulty)+(xp*pixmultx)] = b;
    pb[(yp*pixmulty)+(xp*pixmultx)+1] = g;
    pb[(yp*pixmulty)+(xp*pixmultx)+2] = r;
}

void XBoxStartup(void) {
    int lastTickCount;
    int passedMilliseconds;

    pixmulty = width * (bpp / 8);
    pixmultx = bpp / 8;

        XInput_Init();

    int padnum = 0;

    debugPrint("\n\n    XCast: A simple raycaster example for the Microsoft XBOX.\n");
    debugPrint("    Written and compiled on 1/24/2010.\n");
    debugPrint("    Created by Mike Chambers [[email protected]]\n\n\n\n\n");
    debugPrint("    Controls: Just use the d-pad to move around the map.\n");
    debugPrint("              To reboot your XBOX, press start + back.\n\n");
    debugPrint("    Press start now to begin...");
    
    int breakloop = 0;
    while (breakloop==0) {
      //twiddle thumbs here...
      XInput_GetEvents();
      if (g_Pads[padnum].PressedButtons.usDigitalButtons & XPAD_START) breakloop = 1;
    }
    

    VIDEO_MODE current;
    current = XVideoGetMode();
    int i;
    int j;
    int vstep = 1;
    BOOL result;
    result = XVideoSetMode(width, height, bpp, 60);
    if (result==FALSE) {
      debugPrint("There was an error setting the video mode! Reboot in 5 seconds...");
      XSleep(5000);
      XReboot();
    }

    fb = XVideoGetFB(); //get pointer to beginning of xbox video memory
    pb = malloc(width*height*pixmultx); //allocate a full video buffer so we dont draw directly.
                                        //it will look sexier this way.
    int x, y;

  double posX = 22, posY = 12;  //x and y start position
  double dirX = -1, dirY = 0; //initial direction vector
  double planeX = 0, planeY = 0.66; //the 2d raycaster version of camera plane
  
  double time = 0; //time of current frame
  double oldTime = 0; //time of previous frame
  int stopcast = 0;

  while(stopcast==0) {
    lastTickCount = XGetTickCount();
    for(x = 0; x < width; x++)
    {
      //calculate ray position and direction
      double cameraX = 2 * x / (double)width - 1; //x-coordinate in camera space
      double rayPosX = posX;
      double rayPosY = posY;
      double rayDirX = dirX + planeX * cameraX;
      double rayDirY = dirY + planeY * cameraX;

      //which box of the map we're in  
      int mapX = (int)rayPosX;
      int mapY = (int)rayPosY;
      
      //length of ray from current position to next x or y-side
      double sideDistX;
      double sideDistY;
      
       //length of ray from one x or y-side to next x or y-side
      double deltaDistX = sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX));
      double deltaDistY = sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY));
      double perpWallDist;
      
      //what direction to step in x or y-direction (either +1 or -1)
      int stepX;
      int stepY;

      int hit = 0; //was there a wall hit?
      int side; //was a NS or a EW wall hit?

      //calculate step and initial sideDist
      if (rayDirX < 0)
      {
        stepX = -1;
        sideDistX = (rayPosX - mapX) * deltaDistX;
      }
      else
      {
        stepX = 1;
        sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX;
      }
      if (rayDirY < 0)
      {
        stepY = -1;
        sideDistY = (rayPosY - mapY) * deltaDistY;
      }
      else
      {
        stepY = 1;
        sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY;
      }

      //perform DDA
      while (hit == 0)
      {
        //jump to next map square, OR in x-direction, OR in y-direction
        if (sideDistX < sideDistY)
        {
          sideDistX += deltaDistX;
          mapX += stepX;
          side = 0;
        }
        else
        {
          sideDistY += deltaDistY;
          mapY += stepY;
          side = 1;
        }
        //Check if ray has hit a wall
        if (worldMap[mapX][mapY] > 0) hit = 1;
      }

      //Calculate distance projected on camera direction (oblique distance will give fisheye effect!)
      if (side == 0)
      perpWallDist = fabs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX);
      else
      perpWallDist = fabs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY);

      //Calculate height of line to draw on screen
      int lineHeight = abs((int)(height / perpWallDist));
      
      //calculate lowest and highest pixel to fill in current stripe
      int drawStart = -lineHeight / 2 + height / 2;
      if(drawStart < 0)drawStart = 0;
      int drawEnd = lineHeight / 2 + height / 2;
      if(drawEnd >= height)drawEnd = height - 1;

      //choose wall color
      BYTE cr;
      BYTE cg;
      BYTE cb;
      switch(worldMap[mapX][mapY])
      {
        case 1:
          cr = 255; //red
          cg = 0;
          cb = 0;
          break;
        case 2:
          cr = 0; //green
          cg = 255;
          cb = 0;
          break;
        case 3:
          cr = 0; //blue
          cg = 0;
          cb = 255;
          break;
        case 4:
          cr = 255; //white
          cg = 255;
          cb = 255;
          break;
        default:
          cr = 0; //yellow
          cg = 255;
          cb = 255;
      }
      
      //give x and y sides different brightness
      if (side == 1) {
        cr = (BYTE)(cr / 2);
        cg = (BYTE)(cg / 2);
        cb = (BYTE)(cb / 2);
      }

      //draw the pixels of the stripe as a vertical line
      int tmpy;
      for (tmpy=0; tmpy      for (tmpy=drawStart; tmpy      for (tmpy=drawEnd; tmpy
    }
    memcpy(fb, pb, width*height*pixmultx); //do the actual copy of video buffer to screen

// NOW lets do the input functions...

    XInput_GetEvents();
    passedMilliseconds = XGetTickCount() - lastTickCount;
    lastTickCount = XGetTickCount();
    if (passedMilliseconds < 10) passedMilliseconds = 10;

    //speed modifiers
    double moveSpeed = passedMilliseconds * 0.005; //the constant value is in squares/second
    double rotSpeed = passedMilliseconds * 0.0015; //the constant value is in radians/second

      if(g_Pads[padnum].CurrentButtons.usDigitalButtons & XPAD_DPAD_UP) {
            if(worldMap[(int)(posX + dirX * moveSpeed)][(int)(posY)] == false) posX += dirX * moveSpeed;
            if(worldMap[(int)(posX)][(int)(posY + dirY * moveSpeed)] == false) posY += dirY * moveSpeed;
      }
  
      if(g_Pads[padnum].CurrentButtons.usDigitalButtons & XPAD_DPAD_DOWN) {
            if(worldMap[(int)(posX - dirX * moveSpeed)][(int)(posY)] == false) posX -= dirX * moveSpeed;
            if(worldMap[(int)(posX)][(int)(posY - dirY * moveSpeed)] == false) posY -= dirY * moveSpeed;
      }

      if(g_Pads[padnum].CurrentButtons.usDigitalButtons & XPAD_DPAD_LEFT) {
            //both camera direction and camera plane must be rotated
            double oldDirX = dirX;
            dirX = dirX * cos(rotSpeed) - dirY * sin(rotSpeed);
            dirY = oldDirX * sin(rotSpeed) + dirY * cos(rotSpeed);
            double oldPlaneX = planeX;
            planeX = planeX * cos(rotSpeed) - planeY * sin(rotSpeed);
            planeY = oldPlaneX * sin(rotSpeed) + planeY * cos(rotSpeed);
      }

      if(g_Pads[padnum].CurrentButtons.usDigitalButtons & XPAD_DPAD_RIGHT) {
            //both camera direction and camera plane must be rotated
            double oldDirX = dirX;
            dirX = dirX * cos(-rotSpeed) - dirY * sin(-rotSpeed);
            dirY = oldDirX * sin(-rotSpeed) + dirY * cos(-rotSpeed);
            double oldPlaneX = planeX;
            planeX = planeX * cos(-rotSpeed) - planeY * sin(-rotSpeed);
            planeY = oldPlaneX * sin(-rotSpeed) + planeY * cos(-rotSpeed);
      }

      if(g_Pads[padnum].CurrentButtons.usDigitalButtons & XPAD_START && g_Pads[padnum].CurrentButtons.usDigitalButtons & XPAD_BACK)
      {
        stopcast = 1;
        XReboot();
      }

  }
}


i'd love to get feedback on it, especially regarding optimization. i need to sit down and have a real good look at it all again and see if i can squeeze some extra speed out of it. this runs very fast, but adding textures will for sure have a big impact. i'm still a C newbie really.
Logged