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 / ;
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.