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

Quote:

As of the last bit of code you posted ... no.

Oh. That's not the latest code. I changed it so I have an X_Inc and Y_Inc variable like you do, which is calculated before it enters the actual casting loop. the_x and the_y are just incremented by that.

MindCode
Member #2,031
March 2002
avatar

I've tried looking for my old DOS raycaster, but I think it got junked on one of my many memory purges. I've tried to recreate some of the source code too but, needles to say, I don't have such a great memory. It looks more like a scaled down version of what you guys already did.

1#define SCREEN_W (320)
2#define SCREEN_H (240)
3#define FOV (64)
4#define FOV_DIV2 (FOV/2)
5#define FOV_INCR ((FOV/SCREEN_W) << FIX_SHIFT)
6#define FIX_SHIFT (16)
7#define EMPTY (0)
8 
9typedef signed long fixed;
10typedef unsigned char angle;
11 
12// I'll pretend these are filled already.
13 
14fixed fix_cos[256];
15fixed fix_sin[256];
16 
17int map_data[32][32];
18 
19// I'll also pretend that I change these with user input
20 
21fixed player_x_pos;
22fixed player_y_pos;
23angle player_dir;
24 
25 
26fixed x_pos = player_x_pos;
27fixed y_pos = player_y_pos;
28fixed ray = (player_dir - FOV_DIV2) << FIX_SHIFT;
29 
30// this will be the core renderer
31 
32for(int w = 0; w < SCREEN_W; w++)
33{
34 int distance = 0;
35 
36 ray += FOV_INCR;
37 
38 fixed x = x_pos;
39 fixed y = y_pos;
40 
41 while(map_data[x >> FIX_SHIFT][y >> FIX_SHIFT] == EMTPY)
42 {
43 x += fix_cos[ray];
44 y += fix_sin[ray];
45 distance++;
46 }
47 
48 // this fixes the "fisheye" effect
49 distance *= fix_cos[player_dir];
50 
51 // use your imagination with this function
52 verticle_line(w, distance);
53}

I think you guys inspired me enough to rewrite the whole thing. This means I'll have to install allegro again.

______________________________________
Frag The Planet

lambik
Member #899
January 2001
avatar

I was just curious so I compiled the code posted
aybabtu: don't forget END_OF_MAIN()
23yrold3yrold: your code crashes as soon as I try to move to the right. I can rotate left for a while but then it crashes too. Which would suggest there is value getting out of bounds somewhere.
Fun stuff, I'll look into it some more. I might just stumble over your bug..

Ace
Member #1,781
December 2001
avatar

aybabtu: Yeah, the player will be searching through a "dungeon." Though I'm not sure what they're going to be doing yet. I hope I'll be able to add enemies and such, but if I run out of time, I'll just make it so they have to find their way out of a maze. Mwahahahahhaaha.

- Ace

aybabtu
Member #2,891
November 2002

Quote:

aybabtu: don't forget END_OF_MAIN()

If I do, the program doesn't compile! I had to remove it from 23's go get it compile. Maybe it's a DJGPP thing.

I got the FPS of my engine (It needs lots of optimation!):
Standing: 4
Walking: 3
Close to a wall: 6

Need more speed!!

23yrold3yrold
Member #1,134
March 2001
avatar

Quote:

If I do, the program doesn't compile!

I had to add it to get to compile ...

Quote:

I had to remove it from 23's go get it compile. Maybe it's a DJGPP thing.

Oh right; you use DJGPP and Allegro -2.0 ;)

lambik: Yes, I know, it crashes and I hate it. My code logs values to a file and constrains the crap out of tan(angle) in CastRay() but I still can't see the problem :-/ I hate math, math is 3vil ...

EDIT: Aaaaaaaaand the GameDevers were useless ::) Yeah, like I'm getting lots of help here ;)

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

MindCode
Member #2,031
March 2002
avatar

Quote:

I hate math, math is 3vil ...

You kind of picked the wrong hobby eh?

______________________________________
Frag The Planet

aybabtu
Member #2,891
November 2002

Quote:

Oh right; you use DJGPP and Allegro -2.0

Yeah. ;D I'm suprised my version even has blit...:P::)

Carrus85
Member #2,633
August 2002
avatar

You know, if you really want to get highly optimized code, It might be worth it to look at the FAT (Fixed Angle Texturing) engine developed by Thomas Nussambamer of TICT.ticalc.org. It has to be quit optimized, right? I mean, if you are able to run a raycaster on a graphing calculator, you should be able to optimize it to run on a regular computer, right?

At least the source could provide some insights. It is extremely optimized though, using some 68k ASM. I can't help you in understanding it... I kinda suck at ASM...

Well, Give it a Try...

Here is a link to the supposed "FAT" rendering engine SDK... I'm not sure exactly what it contains... might contain useful source, might not. But somebody should at least take a look at it.

FAT engine SDK
TICT Web Site

Sure hope this helps... It might just complicate things, though...
::):-/

23yrold3yrold
Member #1,134
March 2001
avatar

Quote:

It might just complicate things, though...

That's almost guarenteed. What; no one has the answer? Spellcaster? Thomas Harte? Bob? Anyone? Is this thing on?

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

Carrus85
Member #2,633
August 2002
avatar

I'm dumb! 23...

Looking at the FAT engine code probably would only prove useful in the final optimization stages though. It is pretty amazing though, you can get fairly decent framerates on the TI-89. (Considering the TI-89 has approximately a 5mhz processor, and less then 1MB of RAM)

Thomas Harte
Member #33
April 2000
avatar

I have to admit, I haven't really grasped everything that's been said in this thread, because it is just so expansive, but here are a few things I expect to have come up:

- the Wolfenstein optimisation of using a tile based map is very important for speed purposes
- as is the decision to use a predetermined texturing density

And two things which I think may not have done:

- the Allegro software bitmap scaler is the worst possible choice for a ray casting engine
- a polygon filler for rectangles which form walls in the style of Wolfenstein or Doom may be written without any divides whatsoever. Doom uses one, and this is where even people who know the engine sometimes claim that Doom has a ray casting step (BIG HINT)

Given this second point, there are very many situations broadly in the style of a ray caster (i.e. same height walls, all perfectly vertical) where a 2 dimensional portal or BSP approach will be faster - but with the benefit of any angled walls. Especially if you have 100s of kbs for levels rather than 10s.

aybabtu
Member #2,891
November 2002

How much faster is fixed than float?

Thomas Harte
Member #33
April 2000
avatar

Quote:

How much faster is fixed than float?

On a 386 or 486SX, a fixed is several orders of magnitude faster than a float. On a 486DX a fixed is substantially faster than a float. On Pentiums, the fixed is certainly faster than the float for addition/subtraction, but they probably draw about equal for division/multiplication. Somewhere around Pentium 2/3s, fixeds become slower than floats for multiplication/division operations and the two become equal for addition/subtraction.

Naturally there are many situations for which one type or the other simply isn't suitable - in which case that type is much faster than the other.

aybabtu
Member #2,891
November 2002

I'm gonna change some/most of the math and stuff in the do_raycasting function to fixed. I've gotta get this thing going faster! :P

23yrold3yrold
Member #1,134
March 2001
avatar

Mine flies, but I still have the errors. C'mon, where's that math whiz ...

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

aybabtu
Member #2,891
November 2002

On my programming computer, 23, I'm sorry to say that yours isn't much faster than mine. It is, but not a whole lot. What's your FPS?
Is it just the casting of the rays? Whatever...

23yrold3yrold
Member #1,134
March 2001
avatar

Keep in mine my last posted code does constant file IO to log values 320 times a logic cycle. That slows it down a bloody lot. Take it out and it's lightning.

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

aybabtu
Member #2,891
November 2002

Oh. ::)
Mine's so slow, you can see the FPS counting up.
FPS: 0 ... FPS: 1 ... FPS: 2 ... FPS: 3 ... FPS: 0 ...
Blah.:P:-/::)

Ace
Member #1,781
December 2001
avatar

23yrold3yrold: I've noticed that the angle between the two crash points is about 180 degrees. I haven't had the chance to look at your code, but I do know that tangent is undefined when cosine is equal to 0. cosine is 0 at 90 degrees (PI/2 radians). That should have something to do with the crashing since cosine and sine are continuous.

I'll check your example out some more.

- Ace

23yrold3yrold
Member #1,134
March 2001
avatar

I've looked into that and it's not really crashing anymore; it may be the cause but I'm a little more interested in the graphical glitches.

EDIT: I fixed the major wall glitch with two negative signs; why exactly this worked I'm not sure :P There's still a minor glitch in the texture mapping though :-/ Newest code (minus the file IO) follows. Slows down when you get close to a wall, so it seems the drawing is the slowest part of the engine right now :)

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

Comments?

PS: I have the vague suspicion that my bodgy way of dealing with the crashing is causing the glitch, but I can't check it since whenever I remove those bits and try to look in the direction of the glitch it - you guessed it - crashes ::)

EDIT3: Okay, I think I've ironed out most of it, and I'm going to start a fresh thread so someone may actually notice, but I just realized something. Aybabtu, why did you write your my_draw_circle() function? It does exactly what Allegro's circle function does (only much slower)?

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

Johnny13
Member #805
October 2000
avatar

aybabtu: found it,u asked this kind of question lastyear!:P

23: it still crash(and its not valid C code,plenty of error!:P),
try modify this 2 lines:

while((int)X_Xcheck>>6<9&&(int)X_Ycheck>>6<9&&!level[(int)X_Xcheck>>6][(int)X_Ycheck>>6]) {X_Xcheck+=X_Xinc; X_Ycheck+=X_Yinc;}
while((int)X_Xcheck>>6<9&&(int)X_Ycheck>>6<9&&!level[(int)X_Xcheck>>6][(int)X_Ycheck>>6]) {X_Xcheck+=X_Xinc; X_Ycheck+=X_Yinc;}

shouldn't crash anymore…

Alg3D Praise my Games!!<code>#define SPAMMER (post>=666&&postperday>=6)</code><Mr.spellcaster>What post? <Mr.spellcaster>A useful post by me.

23yrold3yrold
Member #1,134
March 2001
avatar

Yeah, I think I've already figured it all out (including that) but it still seems hackish. I wish I knew how to do it right. Oh well, it doesn't seem to be crashing anymore, at least.

Anyway, since J13 gave me a bump, here's my best shot now. It works, but my rounding of the tangent values makes some walls look choppy if you stand beside it and look down it. It's acceptable though. I'm getting 60 fps if my face is in a wall, and well over 100fps otherwise.

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

Only problem now is that player movement at odd angles is a little "off", but making the player's position floats instead of ints should help that (EDIT: yup, that did it). I ought to add joystick code so I can move more accurately using analog joysticks and L/R strafe buttons ;D

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

Thomas Harte
Member #33
April 2000
avatar

Have you seen this?

23yrold3yrold
Member #1,134
March 2001
avatar

I've only been pimping that site all thread, TH :P If I fixed my math correctly, then that site has some math errors on it ...

EDIT: Actually, I think I'm right; that site does have an error, in that it doesn't negate the tangent value if a ray is going in certian directions. Anyway, it's pretty much perfect now ... I just need to figure out how to call tan() without having it crash. The fix I'm using right now produces minor texture problems ...

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



Go to: