Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Raycasting problems

This thread is locked; no one can reply to it. rss feed Print
Raycasting problems
aybabtu
Member #2,891
November 2002

I just read part of the "Sin & Cos: The Programmer's Pals!" tutorial by amarillion. I previously didn't know how to apply these functions to movement, but I do now!! (BTW: Great tutorial!!!)

Well, after experimenting with them and making a simple "game" to test them out, I've decided to do a raycasting engine. I just want it simple like Wolfenstein 3D's engine. I've got some code "working", but there's a problem with the displaying of the level, it's really blocky, and it doesn't look like walls or anything, just big straight blocks. Ther is some difference in heights and such, but I can't figure out where corners are and stuff. Like I said, I'm new to using angles and sin&cos and stuff like that in my programs, so maybe that's one of the problems, too. Here's the display/casting code:

1/* The view variable is declared like this:
2 * int view[85], and when the rays are casted, the distances are stored here.
3 * The following code is the cast function, the
4 * raycasting handler function and the drawing.
5 */
6 
7int cast_ray(int x,int y,float a)
8{
9 int distance=0;
10 int the_x=x;
11 int the_y=y;
12 while(level[the_y/TILE][the_x/TILE]!=1)
13 {
14 the_x+=(int)cos(a);
15 the_y+=(int)sin(a);
16 distance++;
17 }
18 return distance;
19}
20 
21void do_raycasting()
22{
23 float angle=pa-42;
24 for(int i=0;i<85;i++)
25 {
26 view<i>=cast_ray(px,py,angle);
27 angle++;
28 }
29}
30 
31void draw_view()
32{
33 int tall=0; //Height of a line (represents distance of ray
34 int distance_from_top=0; //So it's centered.
35 int color=255; //This is for depth shading (not implemented yet)
36 for(int i=0;i<85;i++)
37 {
38 //This area is to calculate how tall the line should be
39 //There's probly an error here...
40 if(view<i><200) //This is so it has a distance limit
41 {
42 tall=200-view<i>;
43 distance_from_top=(200-tall)/2;
44 //This draws the line, I don't think this is a problem
45 line(front,i,distance_from_top,i,distance_from_top+tall,makecol(color,color,color));
46 }
47 }
48}

If that's not enough to find the problem, here's the whole program's code:

1#include <allegro.h>
2 
3#define TILE 64
4 
5int level[5][5]={
6{1,1,1,1,1},
7{1,0,0,0,1},
8{1,0,0,0,1},
9{1,0,0,0,1},
10{1,1,1,1,1}};
11 
12int view[85];
13 
14int px=160;
15int py=160;
16int ps=5;
17float pa=64.0;
18 
19BITMAP*front;
20 
21int cast_ray(int x,int y,float a);
22void draw_view();
23void do_raycasting();
24 
25 
26int main()
27{
28 allegro_init();
29 install_keyboard();
30 set_color_depth(16);
31 set_gfx_mode(GFX_AUTODETECT,320,200,0,0);
32 front=create_bitmap(320,200);
33 while(!key[KEY_ESC])
34 {
35 clear(front);
36 do_raycasting();
37 draw_view();
38 if(key[KEY_LEFT]) pa-=1;
39 if(key[KEY_RIGHT]) pa+=1;
40 if(pa<0) pa+=255;
41 if(pa>255) pa-=255;
42 if(key[KEY_UP])
43 {
44 px+=(int)(ps*cos(pa));
45 py+=(int)(ps*sin(pa));
46 }
47 if(key[KEY_DOWN])
48 {
49 px-=(int)(ps*cos(pa));
50 py-=(int)(ps*sin(pa));
51 }
52 line(front,100,100,100+(25*cos(pa)),100+(25*sin(pa)),makecol(255,255,255));
53 vsync();
54 blit(front,screen,0,0,0,0,320,200);
55 }
56 destroy_bitmap(front);
57 return 0;
58}
59 
60int cast_ray(int x,int y,float a)
61{
62 int distance=0;
63 int the_x=x;
64 int the_y=y;
65 while(level[the_y/TILE][the_x/TILE]!=1)
66 {
67 the_x+=(int)cos(a);
68 the_y+=(int)sin(a);
69 distance++;
70 }
71 return distance;
72}
73 
74void do_raycasting()
75{
76 float angle=pa-42;
77 for(int i=0;i<85;i++)
78 {
79 view<i>=cast_ray(px,py,angle);
80 angle++;
81 }
82}
83 
84void draw_view()
85{
86 int tall=0;
87 int distance_from_top=0;
88 int color=255;
89 for(int i=0;i<85;i++)
90 {
91 if(view<i><200)
92 {
93 tall=200-view<i>;
94 distance_from_top=(200-tall)/2;
95 line(front,i,distance_from_top,i,distance_from_top+tall,makecol(color,color,color));
96 }
97 }
98}

I'm almost certain it's a problem with the display or the casting function, but I'm not sure.

Thomas Harte
Member #33
April 2000
avatar

Quote:

the_x+=(int)cos(a);

This is equivalent to:

if(a == M_PI) x--;
if(!a) x++;

i.e. cos(a) only varies from -1 to +1, so the (int) essentially throws all the information away.

aybabtu
Member #2,891
November 2002

So do I need to have the x&y floats or fixeds or doubles? As I said all the movement and angle code worked in my other "game" test. Well, why would it matter? You can't put a point at a non-integer coordinate anyway, so I don't need that extra information, right?

Goodbytes
Member #448
June 2000
avatar

Yes, you have to have the x&y float or fixed or double. Trust us, it matters. :D

Think about it. cos(a) and sin(a) are going to be the same thing every time you calculate them. So, if your x increment for a particular ray is either -1, 0, or 1 all the time, and your y increment is either -1, 0, or 1 all the time, any rays you cast will automagically be clamped to 45 degree increments, which is definitely not what you want.

P.S. You can precalculate the values of cos(a) and sin(a) instead of calling those functions repeatedly in your raycasting loop. It will make for a huge speed increase.


--
~Goodbytes

aybabtu
Member #2,891
November 2002

So instead of haveing it shoot a ray out at 1 degree increments, it shoots them out a t 45 degree increments? That explains the blockyness of the output. So, I need to have the_x & the_y be floats, to get an accurate reading, right?

Quote:

You can precalculate the values of cos(a) and sin(a) instead of calling those functions repeatedly in your raycasting loop. It will make for a huge speed increase.

I think I'll probly do this later, but for now, I'll just call it every time. I don't think its a big problem, cuz it runs fine on my old 586 computer. But, how is this done? I'm guessing just by filling something like float sin_table[85] or something, right? How much would I increment it for each part of the table? 1 or .1 or somthing?

float sin_table[85];
for(int i=0;i<85;i++)
{
 sin_table<i>=sin(i);
}

?

amarillion
Member #940
January 2001
avatar

the allegro functions fixsin and fixcos are already implemented using tables.

Trust me, don't worry about optimization too much at first. Just get it working first, optimize later.

ROSTheFuture
Member #2,775
September 2002
avatar

If you aren't getting any compile errors or runtime errors, i would say try a different, more complicated level. Probably whats happening is that the level is too simple, so naturally all you see is blocks. [edit] or not :P I really need to speed up my typing [/edit]

Also what you might want to do is modify your code a bit so that walls can be different colour so that you can differentiate them. All that would take to do that would be to make your level array with different values that one, then you would change your ray casting code, and add another array parallel to 'view' which contains colour information:

1...
2int level[5][5] =
3{{ makecol(255, 255, 0), makecol(255, 0, 255), /* ... etc */ }};
4 
5int view[85];
6int colinfo[85];
7 
8...
9 
10int cast_ray(int *x,int *y,float a)
11{ /* ^ ^ */
12 ...
13 while(level[the_y/TILE][the_x/TILE]==0)
14 { /* ^ */
15 ...
16 }
17 
18 *x = (the_x/TILE); /* <-- */
19 *y = (the_y/TILE);
20 return distance;
21}
22void do_raycasting()
23{
24 float angle=pa-42;
25 for(int i=0;i<85;i++)
26 {
27 tx = px; ty = py;
28 view<i>=cast_ray(tx,ty,angle);
29 colinfo<i> = level[tx][ty];
30 angle++;
31 }
32}
33 
34void draw_view()
35{
36 ...
37 for(int i=0;i<85;i++)
38 {
39 if(view<i><200)
40 {
41 ...
42 line(front,i,distance_from_top,i,distance_from_top+tall,colinfo<i>);
43 }
44 }
45}

just a suggestion. I don't know how far you intended to go with this.

--------
RichOS is the operating system of the future - if for some reason everyone starts hating Window$ and Linux.

aybabtu
Member #2,891
November 2002

Image...
Yay! ;D

As you can see, I've got it displaying right (changed the_x&y to floats), and it has a primitive form of depth shading! (The line in the middle is just to show the direction you're facing.) Also, you'll notice that it's got that nasty curved effect. How do I fix that?

amarillion
Member #940
January 2001
avatar

Well, it is because raycasting doesn't work the way you think it works. It's hard to explain but you are in the wrong line of thinking. Try to see if you can find other raycasting tutorials.

aybabtu
Member #2,891
November 2002

What's wrong with my line of thinking?

Well, I've read another nice tutorial, and it says to fix the fishbowl effect, multiply the distance by cos(BETA) and beta is -30 (since I'm using the 255 degree circle, -21) for the left-most ray, and 30 (21) for the rightmost ray. I've solved this by doing distance*=cos(0-a); and it works. But, the angle should be between -21 and 21, but in reality, it can be anywhere between two numbers that are 42 different. SO, the effect I get is that when you turn 90 degrees (64 allegro-degrees) you get an incorrect reading! I think I'm stuck...

Zaphos
Member #1,468
August 2001

aybabtu: Try changing 0 to the direction you're facing so that 0-a is between -21 and 21 regardless of how offset a is. e.g. if you turn 64 alleg-degs then you multiply distance by cos(64-a).

Anyway, you should really try to get a grasp of the trig underlying what you're doing ...

I think this calls for some smiling art:
:-X:-X:-X:-X:-*:(
:-X:-X:-X:-*:-X:(
:-X:-X:-*:-X:-X:(
:-X:-*:-X:-X:-X:(
;D8-)8-)8-)8-):(

:-X == Whitespace
:-* == Distance you calculate
8-) == Distance you should calculate, also your line of sight
;D == You
:( == Wall

The size of each bit of wall you draw is determined by the distance parallel to your line of sight that you'd need to walk to get to that wall -- perpendicular distance should not "shrink" the wall. How do we find that parallel distance? Well, if we look at the diagram above as a right-triangle, we see that we already have the length of the hypotenuse and the angle, and we can apply simple trig to find that that parallel distance is hypot*cos(angle) ... exactly the formula you're using.

Niunio
Member #1,975
March 2002
avatar

Here you have a raycast tutorial. It explains what's happening with that nasty curved effect and how to prevent it.

Let me know when you release this project, please;).

-----------------
Current projects: Allegro.pas | MinGRo

amarillion
Member #940
January 2001
avatar

You see? That other tutorial is much better. You see, mine is not really intended as a raycasting tutorial, just a trig primer.

aybabtu
Member #2,891
November 2002

amarillion: Yeah, I know. I've learned a little trigonometry in my geometry class at school, but we never learned really how to apply it to a computer game :P! But, even though your tutorial is not for raycasting in particular, it was what I was missing to at least get started. After all, at least it's farther than I've ever gotten before.

Niuino: Yeah! That tutorial's great, it's the same one you linked to in my other raycasting thread. I'm trying to use that method, but it's not working very well. I've gotten rid of some of the fishbowl, but in some parts, it's actually reversed! Like, I'll look at a flat wall, and it will have slight curvature to it, but instead of the middle being larger, the ends are. Here's the code I'm using to "fix" the distance problem:

void do_raycasting()
{
 float angle=pa-21;
 for(int i=0;i<42;i++)
 {
  view<i>=cos(i-21)*cast_ray(px,py,angle);
  angle++;
 }
}

This is what the tutorial says to do, right?

The Tutorial said:

Thus to remove the viewing distortion, the resulting distance obtained from equations in Figure 17 must be multiplied by cos(BETA); where BETA is the angle of the ray that is being cast relative to the viewing angle. On the figure above, the viewing angle (ALPHA) is 90 degrees because the player is facing straight upward. Because we have 60 degrees field of view, BETA is 30 degrees for the leftmost ray and it is -30 degrees for the rightmost ray.
correct_distance=distorted_distance*cos(BETA);

Of course, I changed 30 degrees into it's equivalent (about 21) in allegro degrees.
Maybe I'm doing the formula wrong, but it seems it should work, I've even got it in the do_raycasting function, where the anlge measures are between -21 & 21.

Quote:

Let me know when you release this project, please.

Hmmm...I don't know even what I'm going to do with it yet! Probly a shooter like Wolfenstein, but between then and now, I've gotta get it working right! My next task is texture mapping. goes to the tutorial...

Niunio
Member #1,975
March 2002
avatar

   view<i> = cos (i-21) * cast_ray (px, py, angle);

That cos function, doesn't it get the angle in radians? But you're using binary angles (0-255), don't you? Try with fixcos or fcos, and do not forget to translate it to fixed point.

-----------------
Current projects: Allegro.pas | MinGRo

Trezker
Member #1,739
December 2001
avatar

If you go to http://www.neozones.com and search a bit, you'll find some raycasting tutorials, they're in qbasic but I've made some advancements in c++.

I attach my work and the original tutorials.
Enjoy!

Zaphos
Member #1,468
August 2001

Well, given that the cos has worked as well as it has, I'd guess that aybabtu hasn't #included math.h and the allegro functions are stepping in automatically, so that isn't the problem. However it would be a good idea to follow Niunio's advice all the same so that the eventual possible #include math.h won't break all your math.

Anyway, the function looks right too me, so if Niunio isn't on to something then all I can guess is that there's something minorly wrong with "cast_ray()" ... perhaps the your steps are too big so the granularity is causing some small error in the drawing? How significant is the distortion?

aybabtu
Member #2,891
November 2002

Here's a pic with my crappy texture mapping and distortion correction working:
[url http://www.angelfire.com/empire/jonhome/WOLF.gif]Image...[/url]

As you can see, there's a few problems in the texture mapping, but it's ok for now. But, you'll notice the distortion in that cube.

Niuino: As Zaphos said, I don't have math.h included, so allegro's helping me out! I could change them to radians, but this works. Later when I get all the bugs worked out of it, I'll make all the code "the way it should be".;D

Trezker: Yeah! Even if they're in QBASIC, I know enough (not a lot still) to see how they work, and implement that code in C.

Zaphos: Um...as for the distortion...it sorta looks like a reverse-fishbowl effect. Instead of the distortion being on the sides, it's in the middle. And, I think I may know the reason...maybe. Maybe because 30 degrees isn't exactly equal to 21 allegro degrees, but 21.25 rather. So, the view is being cut off by half a degree, possibly screwing it up. Actually, it shouldn't do that kind of damage, just make the screen smaller...oh well.
Here's the code for the program...
I've got the ability to switch on and off the texture mapping and distortion correction, as well as a custom circle function for the "compass"! (The circle function isn't the best, it's not the one from the tutorial, but it works, and it's neat to see it...you know...whatever...::))

#SelectExpand
1#include <allegro.h> 2 3#define TILE 64 4 5int level[9][9]={ 6{1,1,1,1,1,1,1,1,1}, 7{1,0,0,0,0,0,0,0,1}, 8{1,0,1,0,1,0,1,0,1}, 9{1,0,0,0,0,0,0,0,1}, 10{1,0,1,0,1,0,1,0,1}, 11{1,0,0,0,0,0,0,0,1}, 12{1,0,1,0,1,0,1,0,1}, 13{1,0,0,0,0,0,0,0,1}, 14{1,1,1,1,1,1,1,1,1}}; 15 16int view[42]; 17int texture_map[42]; 18 19int px=65; 20int py=65; 21int p_old_x=65; 22int p_old_y=65; 23int ps=5; 24float pa=32.0; 25 26bool fishbowl=false; 27bool textures_off=false; 28 29BITMAP*front; 30BITMAP*backdrop; 31BITMAP*texture; 32 33float cast_ray(int x,int y,float a); 34void draw_view(); 35void do_raycasting(); 36bool collisions(); 37void my_draw_circle(BITMAP*b,int x,int y,int radius,int color); 38 39int main() 40{ 41 allegro_init(); 42 install_keyboard(); 43 set_color_depth(24); 44 set_gfx_mode(GFX_AUTODETECT,320,200,0,0); 45 front=create_bitmap(320,200); 46 backdrop=create_bitmap(320,200); 47 for(int i=0;i<100;i++) hline(backdrop,0,i,320,makecol(200,200,255-i)); 48 rectfill(backdrop,0,100,320,200,makecol(0,100,0)); 49 text_mode(-1); 50 texture=load_bitmap("texture.bmp",NULL); 51 while(!key[KEY_ESC]) 52 { 53 clear(front); 54 blit(backdrop,front,0,0,0,0,320,200); 55 do_raycasting(); 56 draw_view(); 57 if(key[KEY_F]) fishbowl=true; 58 if(key[KEY_G]) fishbowl=false; 59 if(key[KEY_T]) textures_off=false; 60 if(key[KEY_R]) textures_off=true; 61 if(key[KEY_LEFT]) pa-=2; 62 if(key[KEY_RIGHT]) pa+=2; 63 if(key[KEY_UP]) 64 { 65 px+=(int)(ps*cos(pa)); 66 py+=(int)(ps*sin(pa)); 67 } 68 if(key[KEY_DOWN]) 69 { 70 px-=(int)(ps*cos(pa)); 71 py-=(int)(ps*sin(pa)); 72 } 73 if(collisions()==true) 74 { 75 px=p_old_x; 76 py=p_old_y; 77 } 78 else 79 { 80 p_old_x=px; 81 p_old_y=py; 82 } 83 if(pa<0) pa+=255; 84 if(pa>255) pa-=255; 85 line(front,160,100,160+(25*cos(pa)),100+(25*sin(pa)),makecol(0,0,255)); 86 line(front,160,100,160+(25*cos(pa-21)),100+(25*sin(pa-21)),makecol(255,255,0)); 87 line(front,160,100,160+(25*cos(pa+21)),100+(25*sin(pa+21)),makecol(255,255,0)); 88 my_draw_circle(front,160,100,25,makecol(255,0,0)); 89 textout_centre(front,font,"N",160,65,makecol(0,0,255)); 90 vsync(); 91 blit(front,screen,0,0,0,0,320,200); 92 if(key[KEY_S]) save_bitmap("wolf.pcx",front,NULL); 93 } 94 destroy_bitmap(front); 95 return 0; 96} 97 98int map_texture(int x,int y,float a) 99{ 100 float the_x=x; 101 float the_y=y; 102 bool ended_on_y=false; 103 while(level[(int)the_y/TILE][(int)the_x/TILE]==0) 104 { 105 the_x+=(float)cos(a); 106 if(level[(int)the_y/TILE][(int)the_x/TILE]!=0) 107 { 108 ended_on_y=true; 109 break; 110 } 111 the_y+=(float)sin(a); 112 if(level[(int)the_y/TILE][(int)the_x/TILE]!=0) 113 { 114 ended_on_y=false; 115 break; 116 } 117 } 118 if(ended_on_y==true) return (int)((int)the_y%TILE); 119 if(ended_on_y==false) return (int)((int)the_x%TILE); 120} 121 122float cast_ray(int x,int y,float a) 123{ 124 float distance=0; 125 float the_x=x; 126 float the_y=y; 127 while(level[(int)the_y/TILE][(int)the_x/TILE]==0) 128 { 129 the_x+=(float)cos(a); 130 the_y+=(float)sin(a); 131 distance++; 132 } 133 return distance; 134} 135 136void do_raycasting() 137{ 138 float angle=pa-21; 139 for(int i=0;i<42;i++) 140 { 141 if(fishbowl==false) view<i>=(int)(cos(i-21)*cast_ray(px,py,angle)); 142 if(fishbowl==true) view<i>=(int)cast_ray(px,py,angle); 143 texture_map<i>=map_texture(px,py,angle); 144 angle++; 145 } 146} 147 148void draw_view() 149{ 150 int tall=0; 151 int distance_from_top=0; 152 int color=255; 153 for(int i=0;i<42;i++) 154 { 155 if(view<i><200) 156 { 157 color=255-(view<i>); 158 tall=200-view<i>; 159 distance_from_top=(200-tall)/2; 160 if(textures_off==true) rectfill(front,(int)(i*(320/42.5))+1,distance_from_top,(int)(((320/42.5)*i)+(320/42.5)),distance_from_top+tall,makecol(color,color,color)); 161 if(textures_off==false) stretch_blit(texture,front,texture_map<i>,0,(int)(320/42.5),64,(int)(i*(320/42.5)),distance_from_top,((int)(320/42.5))+1,tall); 162 } 163 } 164} 165 166void my_draw_circle(BITMAP*b,int x,int y,int radius,int color) 167{ 168 float angle=0.0; 169 while(angle<255) 170 { 171 putpixel(b,x+(radius*cos(angle)),y+(radius*sin(angle)),color); 172 angle+=0.1; 173 } 174} 175 176bool collisions() 177{ 178 if(level[py/TILE][px/TILE]==0) return false; 179 else return true; 180}

(Note: if you want to compile this or anything, you need a 64x64 texture bitmap for the walls...duh!:P)

EDIT: In the files that Trezker attached, I found this:

#SelectExpand
1'----- CONSTRUCT THE VIEWFIX TABLE 2'----- NOTICE THAT z% GOES FROM -31 TO 32 BECAUSE OUR RAYCAST GOES FROM -31 TO 3'----- 32 4FOR z% = -31 TO 32 5 ViewFix(z%) = 1 / COS(z% * PI / 180) '----- HERE'S THE FORMULA FOR YOUR 6 '----- VIEWFIX TABLE 7NEXT z% 8 9//Later in the code... 10'***** This is where we cast out our ray. We add yy% by the rise, and xx% 11'***** by then run. But I subtract it so that angle 0 is infront of you. 12DO 13 'xx% = xx% - SinTable(a%) '----- IT USED TO BE 14 'yy% = yy% - CosTable(a%) '----- THIS, BUT 15 xx% = xx% - SinTable(a%) * ViewFix(z%) '----- NOW IT'S 16 yy% = yy% - CosTable(a%) * ViewFix(z%) '----- THIS, WE MULTIPLIED OUR STEP 17 '----- TABLES BY OUR VIEWFIX TABLE 18 '----- ACCORDING TO z%

So, I need to construct a table like ViewFix, then multiply the reading from cast_ray by that value that corresponds to the angle, right? Or is that exacly what I'm doing...?

Zaphos
Member #1,468
August 2001

I would actually suggest implementing the faster, more accurate method of detecting walls, explained on this page of Nuino's linked tutorial, as I think the distortion may be caused by your current distance calculations (which are only of mediocre accuracy ...)

aybabtu
Member #2,891
November 2002

Zaphos: Yup. I'm working on making it so that the do_raycasting fuction shoots out 320 rays, 1 for each pixel on the screen, which will eliminate all bugs in the texture mapping, and possibly fix some of the distortion. It shouldn't take too long...

BTW: That qbasic fix for the distortion didn't hardly help at all...:-/ just a little. Oh well...

Zaphos
Member #1,468
August 2001

Quote:

I'm working on making it so that the do_raycasting fuction shoots out 320 rays

I wasn't talking about that, but rather the way in which you calculate the distance, but then again for a large enough value of TILE using the method in that tutorial will probably be more of a speed boost than an accuracy one.

aybabtu
Member #2,891
November 2002

Perfect texture mapping, courtesy of 320 rays being cast:
[url http://www.angelfire.com/empire/jonhome/WOLF.gif]Image...[/url]

But, 320 rays is A LOT of math per frame!! If I hold down an arrow key, it's at least .75 seconds between frames/moves. How do I display the exact fps? I belive the floating point numbers are causing part of the slowdown (but fixed looks like it'd be too hard to convert to from it's current state...), but another problem is that it does a lot of math! That optimization that Zaphos showed me would be great, but I'm afraid I don't exactly understand it. I'll look at it some more, but any help would be greatly appreciated!

I modified the code a lot:

#SelectExpand
1#include <allegro.h> 2 3#define TILE 64 4 5int level[9][9]={ 6{1,1,1,1,1,1,1,1,1}, 7{1,0,0,0,0,0,0,0,1}, 8{1,0,1,0,1,0,1,0,1}, 9{1,0,0,0,0,0,0,0,1}, 10{1,0,1,0,1,0,1,0,1}, 11{1,0,0,0,0,0,0,0,1}, 12{1,0,1,0,1,0,1,0,1}, 13{1,0,0,0,0,0,0,0,1}, 14{1,1,1,1,1,1,1,1,1}}; 15 16int view[320]; 17int texture_map[320]; 18 19int px=65; 20int py=65; 21int p_old_x=65; 22int p_old_y=65; 23int ps=5; 24float pa=32.0; 25 26bool fishbowl=false; 27bool textures_off=false; 28 29BITMAP*front; 30BITMAP*backdrop; 31BITMAP*texture; 32 33float cast_ray(int x,int y,float a); 34void draw_view(); 35void do_raycasting(); 36bool collisions(); 37void my_draw_circle(BITMAP*b,int x,int y,int radius,int color); 38 39int main() 40{ 41 allegro_init(); 42 install_keyboard(); 43 set_color_depth(24); 44 set_gfx_mode(GFX_AUTODETECT,320,200,0,0); 45 front=create_bitmap(320,200); 46 backdrop=create_bitmap(320,200); 47 for(int i=0;i<100;i++) hline(backdrop,0,i,320,makecol(200,200,255-i)); 48 rectfill(backdrop,0,100,320,200,makecol(0,100,0)); 49 text_mode(-1); 50 texture=load_bitmap("texture.bmp",NULL); 51 while(!key[KEY_ESC]) 52 { 53 clear(front); 54 blit(backdrop,front,0,0,0,0,320,200); 55 do_raycasting(); 56 draw_view(); 57 if(key[KEY_F]) fishbowl=true; 58 if(key[KEY_G]) fishbowl=false; 59 if(key[KEY_T]) textures_off=false; 60 if(key[KEY_R]) textures_off=true; 61 if(key[KEY_A]) 62 { 63 px+=(int)(ps*cos(pa-64)); 64 py+=(int)(ps*sin(pa-64)); 65 } 66 if(key[KEY_D]) 67 { 68 px-=(int)(ps*cos(pa-64)); 69 py-=(int)(ps*sin(pa-64)); 70 } 71 if(key[KEY_LEFT]) pa-=2; 72 if(key[KEY_RIGHT]) pa+=2; 73 if(key[KEY_UP]) 74 { 75 px+=(int)(ps*cos(pa)); 76 py+=(int)(ps*sin(pa)); 77 } 78 if(key[KEY_DOWN]) 79 { 80 px-=(int)(ps*cos(pa)); 81 py-=(int)(ps*sin(pa)); 82 } 83 if(collisions()==true) 84 { 85 px=p_old_x; 86 py=p_old_y; 87 } 88 else 89 { 90 p_old_x=px; 91 p_old_y=py; 92 } 93 if(pa<0) pa+=255; 94 if(pa>255) pa-=255; 95 line(front,160,100,160+(25*cos(pa)),100+(25*sin(pa)),makecol(0,0,255)); 96 line(front,160,100,160+(25*cos(pa-21)),100+(25*sin(pa-21)),makecol(255,255,0)); 97 line(front,160,100,160+(25*cos(pa+21)),100+(25*sin(pa+21)),makecol(255,255,0)); 98 my_draw_circle(front,160,100,25,makecol(255,0,0)); 99 textout_centre(front,font,"N",160,65,makecol(0,0,255)); 100 vsync(); 101 blit(front,screen,0,0,0,0,320,200); 102 if(key[KEY_S]) save_bitmap("wolf.pcx",front,NULL); 103 } 104 destroy_bitmap(front); 105 destroy_bitmap(texture); 106 destroy_bitmap(backdrop); 107 return 0; 108} 109 110int map_texture(int x,int y,float a) 111{ 112 float distance=0.0; 113 float the_x=x; 114 float the_y=y; 115 bool ended_on_y=false; 116 while(level[(int)the_y/TILE][(int)the_x/TILE]==0) 117 { 118 the_x+=(float)cos(a); 119 if(level[(int)the_y/TILE][(int)the_x/TILE]!=0) 120 { 121 ended_on_y=true; 122 break; 123 } 124 the_y+=(float)sin(a); 125 if(level[(int)the_y/TILE][(int)the_x/TILE]!=0) 126 { 127 ended_on_y=false; 128 break; 129 } 130 distance++; 131 } 132 if(ended_on_y==true) return (int)((int)the_y%TILE); 133 if(ended_on_y==false) return (int)((int)the_x%TILE); 134} 135 136float cast_ray(int x,int y,float a) 137{ 138 float distance=0.0; 139 float the_x=x; 140 float the_y=y; 141 while(level[(int)the_y/TILE][(int)the_x/TILE]==0) 142 { 143 the_x+=(float)cos(a); 144 the_y+=(float)sin(a); 145 distance++; 146 } 147 return distance; 148} 149 150void do_raycasting() 151{ 152 float angle=pa-21.25; 153 for(int i=0;i<320;i++) 154 { 155 if(fishbowl==false) view<i>=(int)(cos((i/7.529411765)-21.25)*cast_ray(px,py,angle)); 156 if(fishbowl==true) view<i>=(int)cast_ray(px,py,angle); 157 texture_map<i>=map_texture(px,py,angle); 158 angle+=0.13125; 159 } 160} 161 162void draw_view() 163{ 164 int tall=0; 165 int distance_from_top=0; 166 int color=255; 167 for(int i=0;i<320;i++) 168 { 169 if(view<i><200) 170 { 171 color=255-(view<i>); 172 tall=200-view<i>; 173 distance_from_top=(200-tall)/2; 174 if(textures_off==true) rectfill(front,i+1,distance_from_top,i+2,distance_from_top+tall,makecol(color,color,color)); 175 if(textures_off==false) stretch_blit(texture,front,texture_map<i>,0,1,64,i,distance_from_top,1,tall); 176 } 177 } 178} 179 180void my_draw_circle(BITMAP*b,int x,int y,int radius,int color) 181{ 182 float angle=0.0; 183 while(angle<255) 184 { 185 putpixel(b,x+(radius*cos(angle)),y+(radius*sin(angle)),color); 186 angle+=0.1; 187 } 188} 189 190bool collisions() 191{ 192 if(level[py/TILE][px/TILE]==0) return false; 193 else return true; 194}

Ack...::)

EDIT: I have a theory about the distortion. It's compensating too much. Like I said, before, the middle was bulged out. Now, the middle is right, but the sides are bulged. This would lead me to belive that it's compensating too much for the distortion! Maybe:

int distance=(int)cast_ray(px,py,angle);
int compensated=distance*cos((i/7.529411765)-21.25);
int nice_distance=(compensated+distance)/2;

I know, this would give me the average. But, from what it looks lke, this would produce straight walls! I dunno, I'll try it...probly won't be the solution, though. But, hey! Anything's worth a try!

23yrold3yrold
Member #1,134
March 2001
avatar

Heh; that distortion is funny :) I stole your code, so I figure I give you a hand. FPS is pretty low for me too; less than 10fps. I notice it gets pretty fast when a wall is right in your face though, so maybe your engine is wasting its time finding far walls? Comment your code some and maybe I could understand it ;)

I'm going to play with it some; I'm bored ...

EDIT: The tutorial Niunio linked to states (correctly) that you can speed up calculations using bitshifts. A quick Find reveals you aren't doing any bitshifting in your engine; only multiplication and division ... I just tried it, and not much difference ...

EDIT2: I found a major problem; in map_texture(), these two lines:

    the_x += (float)cos(a);
    ....
    the_y += (float)sin(a);

Do you have any clue how you're inching along there? Those are small values; try this instead:

    the_x += (float)cos(a) * 64;
    ....
    the_y += (float)sin(a) * 64;

Not sure how correct that is, but it's a nice healthy speed boost ...

EDIT3: Eek! cast_ray() is pretty bodgy; I gotta figure out how to rewrite that (see Niunio's link again).

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

aybabtu
Member #2,891
November 2002

Quote:

Do you have any clue how you're inching along there? Those are small values; try this instead:

Okay! ;D
But, most of the values that come out of cos(a) are close to -1 or 1 ! So, multiplying by 64, wouldn't that give it less accuracy. But, I guess less accuracy is better than my 1 fps. Wait...I just did some math...
cos(-30)*64 is about 55.425, so isn't that a LARGE step? My math could be wrong. Did you actually try that *64 thing? If so, how does it work out for you?

EDIT: Commented code for 23:

#SelectExpand
1#include <allegro.h> 2 3#define TILE 64 //Block (tile) width,height,depth 4 5int level[9][9]={ //A level 6{1,1,1,1,1,1,1,1,1}, //A 1 is a wall, 0 is floor 7{1,0,0,0,0,0,0,0,1}, 8{1,0,1,0,1,0,1,0,1}, 9{1,0,0,0,0,0,0,0,1}, 10{1,0,1,0,1,0,1,0,1}, 11{1,0,0,0,0,0,0,0,1}, 12{1,0,1,0,1,0,1,0,1}, 13{1,0,0,0,0,0,0,0,1}, 14{1,1,1,1,1,1,1,1,1}}; 15 16int view[320]; //The wall slice distances 17int texture_map[320]; //X offests for texture map 18 19int px=65; //Player x 20int py=65; //Player y 21int p_old_x=65; //Player's old x (collision detection) 22int p_old_y=65; //Old y 23int ps=5; //Speed 24float pa=32.0; //Angle 25 26bool fishbowl=false; //So I can switch on/off distortion correction 27bool textures_off=false; //Same, but for textures 28 29BITMAP*front; //The buffer that's blit to screen 30BITMAP*backdrop; //Background image (sky and grass) 31BITMAP*texture; //Wall texture (64x64) 32 33float cast_ray(int x,int y,float a); //Casts a ray at a given angle, then returns distance 34void draw_view(); //Draws the view to screen according to view[320] 35void do_raycasting(); //Handles the raycasting 36bool collisions(); //Handles collisions 37void my_draw_circle(BITMAP*b,int x,int y,int radius,int color); //I wanted to make my own circle drawing function!! 38 39int main() 40{ 41 allegro_init(); 42 install_keyboard(); 43 set_color_depth(24); 44 set_gfx_mode(GFX_AUTODETECT,320,200,0,0); 45 front=create_bitmap(320,200); 46 backdrop=create_bitmap(320,200); 47 //Next few lines draw backdrop 48 for(int i=0;i<100;i++) hline(backdrop,0,i,320,makecol(200,200,255-i)); 49 rectfill(backdrop,0,100,320,200,makecol(0,100,0)); 50 text_mode(-1); 51 //Loads texture.bmp 52 texture=load_bitmap("texture.bmp",NULL); 53 while(!key[KEY_ESC]) 54 { 55 clear(front); //Clear the buffer 56 blit(backdrop,front,0,0,0,0,320,200); //draw bg 57 do_raycasting(); //Cast the rays 58 draw_view(); //Draw the view of the level 59 if(key[KEY_F]) fishbowl=true; //Switch stuff on/off 60 if(key[KEY_G]) fishbowl=false; 61 if(key[KEY_T]) textures_off=false; 62 if(key[KEY_R]) textures_off=true; 63 //Next six keys are movement 64 if(key[KEY_A]) //Strafe left 65 { 66 px+=(int)(ps*cos(pa-64)); 67 py+=(int)(ps*sin(pa-64)); 68 } 69 if(key[KEY_D]) //Strafe right 70 { 71 px-=(int)(ps*cos(pa-64)); 72 py-=(int)(ps*sin(pa-64)); 73 } 74 if(key[KEY_LEFT]) pa-=2; //Turn left 75 if(key[KEY_RIGHT]) pa+=2; //Turn right 76 if(key[KEY_UP]) //Move foward 77 { 78 px+=(int)(ps*cos(pa)); 79 py+=(int)(ps*sin(pa)); 80 } 81 if(key[KEY_DOWN]) //Move backward 82 { 83 px-=(int)(ps*cos(pa)); 84 py-=(int)(ps*sin(pa)); 85 } 86 if(collisions()==true) //check for collisions 87 { 88 px=p_old_x; 89 py=p_old_y; 90 } 91 else 92 { 93 p_old_x=px; 94 p_old_y=py; 95 } 96 if(pa<0) pa+=255; //Keep pa between 0-255 97 if(pa>255) pa-=255; 98 //Next few lines draw that compass thing 99 //Blue line is your angle, yellow is your fov 100 line(front,160,100,160+(25*cos(pa)),100+(25*sin(pa)),makecol(0,0,255)); 101 line(front,160,100,160+(25*cos(pa-21)),100+(25*sin(pa-21)),makecol(255,255,0)); 102 line(front,160,100,160+(25*cos(pa+21)),100+(25*sin(pa+21)),makecol(255,255,0)); 103 my_draw_circle(front,160,100,25,makecol(255,0,0)); 104 textout_centre(front,font,"N",160,65,makecol(0,0,255)); 105 vsync(); //Duh... 106 blit(front,screen,0,0,0,0,320,200); //Draw buffer to screen 107 if(key[KEY_S]) save_bitmap ("wolf.pcx",front,NULL); //Save screenshots 108 } 109 destroy_bitmap(front); 110 destroy_bitmap(texture); 111 destroy_bitmap(backdrop); 112 return 0; 113} 114 115//Gets the X offset for the texture 116int map_texture(int x,int y,float a) 117{ 118 float distance=0.0; 119 float the_x=x; //X of the ray's position 120 float the_y=y; //Y of the ray's postition 121 bool ended_on_y=false; //Check that it ends on a horizontal face or a vertical face of a block 122 while(level[(int)the_y/TILE][(int)the_x/TILE]==0) //Keeps going until a wall 123 { 124 the_x+=(float)cos(a); //Increase x 125 if(level[(int)the_y/TILE][(int)the_x/TILE]!=0) //Check to see if this movement caused a collision 126 { 127 ended_on_y=true; //If it did, it ended on a vertical face 128 break; // End the loop 129 } 130 the_y+=(float)sin(a); //If it's still going, increase y 131 if(level[(int)the_y/TILE][(int)the_x/TILE]!=0) //Once again, check collisions 132 { 133 ended_on_y=false; 134 break; 135 } 136 distance++; //Not used yet, but will be so if a ray doesn't hit a wall, it'll stop still 137 } 138 if(ended_on_y==true) return (int)((int)the_y%TILE); //The equation for finding the offset is different for a vertical face than a horizontal 139 if(ended_on_y==false) return (int)((int)the_x%TILE); 140} 141 142//Casts the ray, and returns the distance 143float cast_ray(int x,int y,float a) 144{ 145 float distance=0.0; 146 float the_x=x; // Ray x 147 float the_y=y; // Ray y 148 while(level[(int)the_y/TILE][(int)the_x/TILE]==0) //Keep going until a wall 149 { 150 the_x+=(float)cos(a); //Increase x 151 the_y+=(float)sin(a); //Increase y 152 distance++; //Increase distance 153 } 154 return distance; 155} 156 157void do_raycasting() 158{ 159 float angle=pa-21.25; //Start at the equivalent of -30 degrees 160 for(int i=0;i<320;i++) //Fill the view[] 161 { 162 //For some reason, this distortion correction doesn't help much... 163 // i/7.5... gets the angle i should be 164 // -21.25 because it'll be between 0-42.5 165 if(fishbowl==false) view<i>=(int)(cos((i/7.529411765)-21.25)*cast_ray(px,py,angle)); 166 if(fishbowl==true) view<i>=(int)cast_ray(px,py,angle); 167 texture_map<i>=map_texture(px,py,angle); //Get texture 168 angle+=0.13125; //Add the angle by 42/360 169 } 170} 171 172//Draws the wall slices 173void draw_view() 174{ 175 int tall=0; //How tall a slice is 176 int distance_from_top=0; //For it to be centered 177 int color=255; //For depth shading (no textures) 178 for(int i=0;i<320;i++) 179 { 180 if(view<i><200) //I need to fix this so I can display walls that are farther away 181 { 182 color=255-(view<i>); //Gets the color 183 tall=200-view<i>; //Gets the height 184 distance_from_top=(200-tall)/2; //Centers it 185 //If textures are off, it just uses rectfill 186 //These drawing functions are easy enough to understand... 187 if(textures_off==true) rectfill (front,i+1,distance_from_top,i+2,distance_from_top+tall,makecol(color,color,color)); 188 if(textures_off==false) stretch_blit(texture,front,texture_map<i>,0,1,64,i,distance_from_top,1,tall); 189 } 190 } 191} 192 193//Custom circle drawing function 194//Note that this doesn't contribute to the slowdown.... 195void my_draw_circle(BITMAP*b,int x,int y,int radius,int color) 196{ 197 float angle=0.0; 198 while(angle<255) 199 { 200 putpixel(b,x+(radius*cos(angle)),y+(radius*sin(angle)),color); 201 angle+=0.1; 202 } 203} 204 205bool collisions() 206{ 207 if(level[py/TILE][px/TILE]==0) return false; 208 else return true; 209}

23yrold3yrold
Member #1,134
March 2001
avatar

It worked well, actually. But I've been working on a "proper" version using the math on that site (thread bump is t3h win, btw) and here's my best effort so far. In the plus column, it's blazingly fast; in the minus column I think I'm screwing up the math and I'm too stupid to figure out where :P It looks like a mess if you try it, but actually about half the walls are being drawn correctly and the other half aren't. The program also tends to crash on me if the angle I pass to tan() is undesirably too close to a multiple of 90 degrees, which has a bad hack to fix. Anyone want to give us some pointers here?

#SelectExpand
1 2#include <math.h> 3#include <allegro.h> 4 5#define TILE 64 6#define TILESHIFT 6 7#define SCREENWIDTH 320 8#define SCREENHEIGHT 200 9#define M_PI 3.1415926535897932 10 11int level[9][9]={ 12{1,1,1,1,1,1,1,1,1}, 13{1,0,0,0,0,0,0,0,1}, 14{1,0,1,0,1,0,1,0,1}, 15{1,0,0,0,0,0,0,0,1}, 16{1,0,1,0,1,0,1,0,1}, 17{1,0,0,0,0,0,0,0,1}, 18{1,0,1,0,1,0,1,0,1}, 19{1,0,0,0,0,0,0,0,1}, 20{1,1,1,1,1,1,1,1,1}}; 21 22int view[320]; 23int texture_map[320]; 24int px = 65; 25int py = 65; 26int p_old_x = 65; 27int p_old_y = 65; 28int ps = 5; // player speed 29float pa = 1; // player angle 30bool fishbowl = false; 31bool textures_off = false; 32 33BITMAP* front; 34BITMAP* backdrop; 35BITMAP* texture; 36 37// float cast_ray(int x, int y, float a); 38float CastRay(int xpos, int ypos, double angle, int& t); 39void draw_view(); 40void do_raycasting(); 41bool collisions(); 42void my_draw_circle(BITMAP *b, int x, int y, int radius, int color); 43 44int main() 45{ 46 allegro_init(); 47 install_keyboard(); 48 set_color_depth(16); 49 set_gfx_mode(GFX_AUTODETECT, SCREENWIDTH, SCREENHEIGHT, 0, 0); 50 text_mode(-1); 51 52 front = create_bitmap(SCREENWIDTH, SCREENHEIGHT); 53 backdrop = create_bitmap(SCREENWIDTH, SCREENHEIGHT); 54 55 for(int i = 0 ; i < 100 ; ++i) hline(backdrop, 0, i, 320, makecol(200, 200, 255 - i)); 56 rectfill(backdrop, 0, 100, SCREENWIDTH, SCREENHEIGHT, makecol(0,100,0)); 57 texture = load_bitmap("texture.bmp",NULL); 58 59 while(!key[KEY_ESC]) 60 { 61 clear(front); 62 blit(backdrop,front,0,0,0,0,SCREENWIDTH,SCREENHEIGHT); 63 do_raycasting(); 64 draw_view(); 65 66 if(key[KEY_T]) textures_off = false; 67 if(key[KEY_R]) textures_off = true; 68 if(key[KEY_A]) 69 { 70 px += (int)(ps * cos(pa - M_PI / 2)); 71 py += (int)(ps * sin(pa - M_PI / 2)); 72 } 73 if(key[KEY_D]) 74 { 75 px -= (int)(ps * cos(pa - M_PI / 2)); 76 py -= (int)(ps * sin(pa - M_PI / 2)); 77 } 78 if(key[KEY_LEFT]) pa -= 0.1; 79 if(key[KEY_RIGHT]) pa += 0.1; 80 if(key[KEY_UP]) 81 { 82 px+=(int)(ps * cos(pa)); 83 py+=(int)(ps * sin(pa)); 84 } 85 if(key[KEY_DOWN]) 86 { 87 px-=(int)(ps * cos(pa)); 88 py-=(int)(ps * sin(pa)); 89 } 90 if(collisions()==true) 91 { 92 px=p_old_x; 93 py=p_old_y; 94 } 95 else 96 { 97 p_old_x=px; 98 p_old_y=py; 99 } 100 101 if(pa < 0) pa += M_PI * 2; 102 if(pa > M_PI * 2) pa -= M_PI * 2; 103 104 105 // draw the little compass/circle 106 line(front,160,100,160+(25*cos(pa)),100+(25*sin(pa)),makecol(0,0,255)); 107 line(front,160,100,160+(25*cos(pa-0.523598)),100+(25*sin(pa-0.523598)),makecol(255,255,0)); 108 line(front,160,100,160+(25*cos(pa+0.523598)),100+(25*sin(pa+0.523598)),makecol(255,255,0)); 109 my_draw_circle(front,160,100,25,makecol(255,0,0)); 110 textout_centre(front,font,"N",160,65,makecol(0,0,255)); 111 112 113 vsync(); 114 blit(front,screen,0,0,0,0,SCREENWIDTH, SCREENHEIGHT); 115 if(key[KEY_S]) save_bitmap("wolf.pcx",front,NULL); 116 } 117 118 destroy_bitmap(front); 119 destroy_bitmap(texture); 120 destroy_bitmap(backdrop); 121 122 return 0; 123} 124END_OF_MAIN() 125 126// called once from int main() 127void do_raycasting() 128{ 129 double angle = pa - 0.523598; 130 131 for(int i = 0 ; i < SCREENWIDTH ; ++i) 132 { 133 // get the distance of the ray 134 view<i> = (int)(cos(angle - pa) * CastRay(px, py, angle, texture_map<i>)); 135 136 // increment the angle 137 angle += 1.04719 / SCREENWIDTH; 138 } 139} 140 141// called once from int main() 142void draw_view() 143{ 144 int tall = 0; 145 int distance_from_top = 0; 146 147 for(int i = 0 ; i < SCREENWIDTH ; ++i) 148 { 149 tall = (int)(64.0 / view<i> * 277.0); 150 distance_from_top = (SCREENHEIGHT - tall) / 2; 151 stretch_blit(texture, front, texture_map<i>, 0, 1, 64, i, distance_from_top, 1, tall); 152 } 153} 154 155// trivial function called once fron int main() 156void my_draw_circle(BITMAP*b,int x,int y,int radius,int color) 157{ 158 float angle = 0.0; 159 160 while(angle < 360) 161 { 162 putpixel(b, x + (radius * cos(angle)), y + (radius * sin(angle)), color); 163 angle += 0.1; 164 } 165} 166 167// called once from int main() 168bool collisions() 169{ 170 // return (bool)level[py/TILE][px/TILE]; 171 return (bool)level[px >> TILESHIFT][py >> TILESHIFT]; 172} 173 174float CastRay(int xpos, int ypos, double angle, int& t) { 175 // initialize (X_Ycheck, X_Xcheck) with first vertical wall and 176 // (Y_Ycheck, Y_Xcheck) with the first horizontal one 177 float X_Ycheck, X_Xcheck, Y_Ycheck, Y_Xcheck; 178 float X_Yinc, X_Xinc, Y_Yinc, Y_Xinc; 179 180 // hacka hacka hacka .... 181 double tangent = tan(angle); 182 if(tangent >= 0.0 && tangent < 0.1) tangent = 0.1; 183 if(tangent <= 0.0 && tangent > -0.1) tangent = -0.1; 184 if(tangent > 9999) tangent = 9999; 185 if(tangent < -9999) tangent = -9999; 186 187 // sin(90) == 1; sin(270) == -1 188 if(sin(angle) > 0) // The y-values are increasing 189 { 190 Y_Ycheck = (ypos / 64) * 64 - 1; 191 Y_Xcheck = xpos + (ypos - Y_Ycheck) / tangent; 192 Y_Xinc = 64 / tangent; 193 Y_Yinc = -64; 194 } else { // The y-values are decreasing 195 Y_Ycheck = (ypos / 64) * 64 + 64; 196 Y_Xcheck = xpos + (ypos - Y_Ycheck) / tangent; 197 Y_Xinc = 64 / tangent; 198 Y_Yinc = 64; 199 } 200 201 // okay, let's check for a wall 202 while(level[(int)Y_Xcheck >> TILESHIFT][(int)Y_Ycheck >> TILESHIFT] == 0) 203 { 204 Y_Xcheck += Y_Xinc; 205 Y_Ycheck += Y_Yinc; 206 } 207 208 // cos(0) == 1; cos(180) == -1 209 if(cos(angle) > 0) // The x-values are increasing 210 { 211 X_Xcheck = (xpos / 64) * 64 + 64; 212 X_Ycheck = ypos + (xpos - X_Xcheck) * tangent; 213 X_Xinc = 64; 214 X_Yinc = 64 * tangent; 215 } 216 else // The x-values are decreasing 217 { 218 X_Xcheck = (xpos / 64) * 64 - 1; 219 X_Ycheck = ypos + (xpos - X_Xcheck) * tangent; 220 X_Xinc = -64; 221 X_Yinc = 64 * tangent; 222 } 223 224 // okay, let's check for a wall 225 while(level[(int)X_Xcheck >> TILESHIFT][(int)X_Ycheck >> TILESHIFT] == 0) 226 { 227 X_Xcheck += X_Xinc; 228 X_Ycheck += X_Yinc; 229 } 230 231 float xcheck = (X_Xcheck - xpos) * (X_Xcheck - xpos) + (X_Ycheck - ypos) * (X_Ycheck - ypos); 232 float ycheck = (Y_Xcheck - xpos) * (Y_Xcheck - xpos) + (Y_Ycheck - ypos) * (Y_Ycheck - ypos); 233 234 if(xcheck < ycheck) 235 { 236 t = (int)X_Ycheck % TILE; 237 return sqrt(xcheck); 238 } 239 else 240 { 241 t = (int)Y_Xcheck % TILE; 242 return sqrt(ycheck); 243 } 244}

Yeah, I know, it sucks :P I'm getting the math for CastRay() from [url http://www.permadi.com/tutorial/raycast/rayc7.html]here[/url], btw ...

EDIT: Found a bug and fixed it above, but still needs work; sucker's gone back to crashing depending on location and angle >_< I'm done with it for now ...

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.



Go to: