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 tried some tables and such, but it didn't make a difference. It's because of allegro stepping in to help speed up sin&cos with it's tables. Very nice of it, really.:P

EDIT: Screw allegro's "help"!! I #included <math.h>, then made a macro to convert degrees (0-360) to radians, and used the sin & cos functions without allegro's help. I got the idea after I RTFM and it said that it's sin and cos tables weren't very accurate. Well, guess what? IT'S BEAUTIFUL!!!! Here's a screenie:
[url http://www.angelfire.com/empire/jonhome/wolf3.gif]Image...[/url]
Here's the latest code:
(I know I overuse the DEG_TO_RAD() macro, but it's easier this way. Also, notice the DrawSlice() function, made by 23, and it gives me an extra FPS. Also, I used those shift operators to do division, and that gave me another FPS! Also, you can now control it by the mouse...controls are shown...)

#SelectExpand
1/* Raycasting engine 2 * June 2003 3 * < Controls > 4 * Mouse: 5 * Foward.........Right Button 6 * Turn Left......Move Left 7 * Turn Right.....Move Right 8 * Shoot..........Left Button 9 * Aim Up.........Move Foward 10 * Aim Down.......Move Backward 11 * Keyboard: 12 * Foward.........W Key 13 * Backward.......S Key 14 * Strafe Left....A Key 15 * Strafe Right...D Key 16 * Aim Up.........Up Arrow 17 * Aim Down.......Down Arrow 18 * Turn Left......Left Arrow 19 * Turn Right.....Right Arrow 20 * Shoot..........Spacebar 21 * Center Aim.....Q Key 22 */ 23 24#include <allegro.h> 25#include <math.h> 26 27#define TILE 64 28#define TILE_SHIFT 6 29 30#define MOUSE_CONTROL_SPEED 4 31 32#define DEG_TO_RAD(x) ((x)*0.0174532925) 33 34int level[9][9]={ 35{1,1,1,1,1,1,1,1,1}, 36{1,0,0,0,0,0,0,0,1}, 37{1,0,1,0,1,0,1,0,1}, 38{1,0,0,0,0,0,0,0,1}, 39{1,0,1,0,1,0,1,0,1}, 40{1,0,0,0,0,0,0,0,1}, 41{1,0,1,0,1,0,1,0,1}, 42{1,0,0,0,0,0,0,0,1}, 43{1,1,1,1,1,1,1,1,1}}; 44 45int view[320]; 46int texture_map[320]; 47 48int px=70; 49int py=70; 50int p_old_x=70; 51int p_old_y=70; 52int p_turn_s=3; 53int p_walk_s=7; 54float pa=1; 55 56int mouse_move_x=0; 57int mouse_move_y=0; 58int crosshairs_y=100; 59 60int fps=0; 61int max_fps=0; 62 63volatile int timer=0; 64void inc_timer() 65{ 66 timer++; 67}END_OF_FUNCTION(inc_timer); 68 69BITMAP*front; 70BITMAP*backdrop; 71BITMAP*texture; 72 73void draw_view(); 74void do_raycasting(); 75bool collisions(); 76void fill_tables(); 77 78void DrawSlice(BITMAP*texture,BITMAP*buffer,int xoff,int x,int y,int tall); 79 80int main() 81{ 82 allegro_init(); 83 install_timer(); 84 install_mouse(); 85 install_keyboard(); 86 set_color_depth(16); 87 set_gfx_mode(GFX_AUTODETECT,320,200,0,0); 88 front=create_bitmap(320,200); 89 backdrop=create_bitmap(320,200); 90 for(int i=0;i<100;i++) hline(backdrop,0,i,320,makecol(200,200,255-i)); 91 for(int i=200;i>100;i--) hline(backdrop,0,i,320,makecol(0,i,0)); 92 texture=load_bitmap("texture.bmp",NULL); 93 LOCK_VARIABLE(timer); 94 LOCK_FUNCTION(inc_timer); 95 install_int_ex(inc_timer,SECS_TO_TIMER(1)); 96 int da_fps=0; 97 while(!key[KEY_ESC]) 98 { 99 if(timer>0) 100 { 101 da_fps=fps; 102 fps=0; 103 timer=0; 104 } 105 else fps++; 106 if(max_fps<fps) max_fps=fps; 107 blit(backdrop,front,0,0,0,0,320,200); 108 do_raycasting(); 109 draw_view(); 110 111 get_mouse_mickeys(&mouse_move_x,&mouse_move_y); 112 crosshairs_y+=(int)(mouse_move_y/MOUSE_CONTROL_SPEED); 113 pa+=(int)(mouse_move_x/MOUSE_CONTROL_SPEED); 114 if(key[KEY_P]) save_bitmap("wolf.pcx",front,NULL); 115 if(key[KEY_A]) 116 { 117 px+=(int)(p_walk_s*cos(DEG_TO_RAD(pa-90))); 118 py+=(int)(p_walk_s*sin(DEG_TO_RAD(pa-90))); 119 } 120 if(key[KEY_D]) 121 { 122 px-=(int)(p_walk_s*cos(DEG_TO_RAD(pa-90))); 123 py-=(int)(p_walk_s*sin(DEG_TO_RAD(pa-90))); 124 } 125 if(key[KEY_Q]) crosshairs_y=100; 126 if(key[KEY_LEFT]) pa-=p_turn_s; 127 if(key[KEY_RIGHT]) pa+=p_turn_s; 128 if(key[KEY_UP]) crosshairs_y-=5; 129 if(key[KEY_DOWN]) crosshairs_y+=5; 130 if(key[KEY_W]||mouse_b&2) 131 { 132 px+=(int)(p_walk_s*cos(DEG_TO_RAD(pa))); 133 py+=(int)(p_walk_s*sin(DEG_TO_RAD(pa))); 134 } 135 if(key[KEY_S]) 136 { 137 px-=(int)(p_walk_s*cos(DEG_TO_RAD(pa))); 138 py-=(int)(p_walk_s*sin(DEG_TO_RAD(pa))); 139 } 140 141 if(collisions()==true) 142 { 143 px=p_old_x; 144 py=p_old_y; 145 } 146 else 147 { 148 p_old_x=px; 149 p_old_y=py; 150 } 151 if(pa<0) pa+=360; 152 if(pa>360) pa-=360; 153 textprintf(front,font,0,0,makecol(255,255,255),"FPS: %i Max: %i",da_fps,max_fps); 154 textprintf(front,font,0,8,makecol(255,255,255),"X: %i Y: %i A: %i",px,py,(int)pa); 155 textprintf(front,font,0,16,makecol(255,255,255),"tX: %i tY: %i",px/TILE,py/TILE); 156 hline(front,150,crosshairs_y,170,makecol(150,255,150)); 157 vline(front,160,crosshairs_y-10,crosshairs_y+10,makecol(150,255,150)); 158 vsync(); 159 blit(front,screen,0,0,0,0,320,200); 160 } 161 destroy_bitmap(front); 162 destroy_bitmap(texture); 163 destroy_bitmap(backdrop); 164 return 0; 165} 166 167void do_raycasting() 168{ 169 float x_inc; 170 float y_inc; 171 int distance=0; 172 float the_x=px; 173 float the_y=py; 174 float angle=DEG_TO_RAD(pa-30); 175 bool ended_on_y=false; 176 for(int i=0;i<320;i++) 177 { 178 x_inc=cos(angle)*3; 179 y_inc=sin(angle)*3; 180 while(level[(int)the_y>>TILE_SHIFT][(int)the_x>>TILE_SHIFT]==0) 181 { 182 the_x+=x_inc; 183 if(level[(int)the_y>>TILE_SHIFT][(int)the_x>>TILE_SHIFT]!=0) 184 { 185 ended_on_y=true; 186 break; 187 } 188 the_y+=y_inc; 189 if(level[(int)the_y>>TILE_SHIFT][(int)the_x>>TILE_SHIFT]!=0) 190 { 191 ended_on_y=false; 192 break; 193 } 194 distance+=3; 195 } 196 if(ended_on_y==true) texture_map<i>=(int)((int)the_y%TILE); 197 if(ended_on_y==false) texture_map<i>=(int)((int)the_x%TILE); 198 view<i>=(int)(cos(angle-DEG_TO_RAD(pa))*distance); 199 angle+=DEG_TO_RAD(0.1875); 200 distance=0; 201 the_x=px; 202 the_y=py; 203 } 204} 205 206void draw_view() 207{ 208 int tall=0; 209 int distance_from_top=0; 210 for(int i=0;i<320;i++) 211 { 212 tall=(int)(64.0/view<i>*277.0); 213 distance_from_top=(200-tall)/2; 214 //23yrold3yrold's faster stretching: 215 DrawSlice(texture,front,texture_map<i>,i,distance_from_top,tall); 216 //Old method of drawing slices: 217 //stretch_blit(texture,front,texture_map<i>,0,1,texture->w,i,distance_from_top,1,tall); 218 } 219} 220 221bool collisions() 222{ 223 if(level[py>>TILE_SHIFT][px>>TILE_SHIFT]!=0) return true; 224 if(level[(py+5)>>TILE_SHIFT][(px+5)>>TILE_SHIFT]!=0) return true; 225 if(level[(py+5)>>TILE_SHIFT][(px-5)>>TILE_SHIFT]!=0) return true; 226 if(level[(py-5)>>TILE_SHIFT][(px-5)>>TILE_SHIFT]!=0) return true; 227 if(level[(py-5)>>TILE_SHIFT][(px+5)>>TILE_SHIFT]!=0) return true; 228 return false; 229} 230 231void DrawSlice(BITMAP*texture,BITMAP*buffer,int xoff,int x,int y,int tall) 232{ 233 int srcy=0, num=0; 234 for(int i=y;i<y+tall;i++) 235 { 236 num+=64; 237 while(num>=tall) 238 { 239 num-=tall; 240 srcy++; 241 } 242 if(i<0) continue; 243 if(srcy>=64||i>=buffer->h) return; 244 ((short*)buffer->line<i>)[x]=((short*)texture->line[srcy])[xoff]; 245 } 246}

Pretty kewl...;D

23yrold3yrold
Member #1,134
March 2001
avatar

I see no picture. Does this mean your columns are 1 pixel wide instead of 2 now?

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

aybabtu
Member #2,891
November 2002

I just uploaded the pic, so you should see it now...sorry!

Yup. 1 pixel! And the textures look way nicer, too! (Notice the left-most wall in this one, then compare it to the "NO DISTORTIONS" screenshot...pretty nice!)

Bob
Free Market Evangelist
September 2000
avatar

It'll run a lot faster if you rotate your texture by 90 degrees so that you read the X coord instead of the Y coord.

Untested code:

1void DrawSlice(BITMAP*texture,BITMAP*buffer,int xoff,int x,int y,int tall)
2{
3 int srcy=0, num=0;
4 for(int i=y;i<y+tall;i++)
5 {
6 num+=64;
7 while(num>=tall)
8 {
9 num-=tall;
10 srcy++;
11 }
12 if(i<0) continue;
13 if(srcy>=64||i>=buffer->h) return;
14 ((short*)buffer->line<i>)[x]=((short*)texture->line[xoff])[srcy];
15 }
16}

Replacing that while loop by a bunch of adds will also make it run a lot faster. If possible, see if you can drop those if statements from the inner loop too.

--
- Bob
[ -- All my signature links are 404 -- ]

aybabtu
Member #2,891
November 2002

Alright...I'll try that rotate 90 degrees thing.

23yrold3yrold
Member #1,134
March 2001
avatar

Quote:

It'll run a lot faster if you rotate your texture by 90 degrees so that you read the X coord instead of the Y coord.

Oooohh! Is that because of cache missing or whatever you call it? Okay, I understand now ;D I'll have to play with this now ...

I'd still love to have my math problems magically disappear. Until then, I'm potentially optimising my errors, and that's no fun :P ...

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

Bob
Free Market Evangelist
September 2000
avatar

Quote:

Oooohh! Is that because of cache missing or whatever you call it?

Yep :)

--
- Bob
[ -- All my signature links are 404 -- ]

aybabtu
Member #2,891
November 2002

Arg.
To make it look even nicer, I have to take out some code that makes it run faster. What it does is multiplies the x_inc and y_inc by 3, and adds 3 to distance every step. But, this of course makes it innaccurate, and produces larger (3-4) pixel blocks close to the player. I've gotta learn how that thing on page 7 of that tutorial works. I understand it...sorta. I have two problems:
1) How do I get that first intersection?
2) Why does it separate the horizontal and vertical intersections?

Could someone help me understand it?:-/

23yrold3yrold
Member #1,134
March 2001
avatar

1) Basically, by rounding to the nearest 64 for one coordinate, then by using the tangent of the angle to get the other coordinate.
2) Because stepping through them seperately is a lot easier than going through them together. Look at how easy it is to just add twice every loop. Can only do that if they're checked seperately.

I still don't quite understand tan() enough to explain it. If it's not in amarillion's tutorial, it should be ;)

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

aybabtu
Member #2,891
November 2002

I'm okay with tan:
Tangent(angle)=opposite side/adjacent side
I also think I'm getting this thing...I'm going to go work on it now...

Thomas Harte
Member #33
April 2000
avatar

Going slightly off topic into the 'not raycasting' ideas I posted earlier, I've come up with a knockup of such an implementation (see attachment for code & screenshot) and am convinced that it is a 'better than raycasting' implementation. The technique uses a combination of the following:

- front to back (zero overdraw) portal based rendering
- one divide per column texture mapping (same as normal ray casting)

The FPS doesn't seem to be the astronomic figure I'd expected, but to put things in perspective, here are the top four time consuming functions from a profile build:

        Func          Func+Child           Hit
        Time   %         Time      %      Count  Function
---------------------------------------------------------
    2471.277  33.0     2471.277  33.0      686 _rectfill (alld40.dll)
     944.485  12.6     1258.176  16.8   109713 DrawSlither(struct BITMAP *,struct Texture *,int,int,int,int) (main.obj)
     774.079  10.3     1192.259  15.9   589954 _fmul (main.obj)
     740.479   9.9     2330.742  31.1     1904 AddWall(struct Wall *,unsigned int,long,long,int,int) (main.obj)

So, the bottleneck is clearly video memory access (i.e. drawing, not calculating), which is exactly the same cost as raycasting. Therefore I am confident that with properly optimised drawing code the same sorts of frame rates as ray casting could be seen.

With respect to fmul versus AddWall, fmul is used four times per wall (unless the wall is a reverse face - then just twice) and a further three times per slither if that slither actually appears on the screen. For slithers which do not appear on screen due to being obscured, no fmuls will usually be performed, however for areas where the wall would appear on screen were it longer (and retained the same orientation), one fmul will be performed per slither.

I know that the display sometimes flickers. I'm not sure if this is a buffer bug I've added or the usual array of incompatibilities between Allegro and Windows 2000.

AddWall becomes substantially faster as the screen fills up. Many more sectors would not substantially increase calculation costs.

A screenshot is only attached as I couldn't find anywhere to upload it in order to show it inline. Similarly Allegro.cc would not let me post the code inline due to length.

aybabtu
Member #2,891
November 2002

That's neat...seems more complex than raycasting, though...:)

EDIT:
New stuff for the raycaster:
Multiple textures. (I've got three coded in...I need to make a level editor!)
Sped it up and kept it nice looking...I'm getting 9-12 FPS walking...
Looking up and down, looking and rotating is really nice when controled by the mouse (i.e. smooth/cool!)
Heh...I've even got a gun in there now (I'm going to make it a fps.) It's the PPK from GoldenEye. The "Z" Key switches modes for the gun. This gun switches between silenced and not silenced. It's pretty cool.

EDIT 2: I just downloaded that FAT engine SDK...you must get it! What I think's cool is that it's got ALL the textures from Wolfenstein! Plus, they're 64x64 px, all aranged on a 640x384 sheet. Its cool!

23yrold3yrold
Member #1,134
March 2001
avatar

Yeah, textures are pretty easy. Just use different numbers in the array ;D

I'm going to add that other stuff too, but not until I've gotten rid of those texture problems. I'll keep that in the other thread though. Until then, it's back to my game ...

Guess I'll check out TH's code too :)

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

aybabtu
Member #2,891
November 2002

23 (and anyone else who's interested): I'm attaching a sheet with all the Wolfenstein textures!

23yrold3yrold
Member #1,134
March 2001
avatar

Quote:

I just downloaded that FAT engine SDK

What's this now? What does it do that that site doesn't teach?

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

Thomas Harte
Member #33
April 2000
avatar

Quote:

That's neat...seems more complex than raycasting, though...

Not really - the guts of the thing are within AddWall, and that is really nothing more than a ray caster which only considers one wall (and makes a few arrangements prior to drawing in order to pretend that the wall is axis aligned).

aybabtu
Member #2,891
November 2002

Quote:

What's this now? What does it do that that site doesn't teach?

It's that TICL thing that Carrus posted. It doesn't really teach anything new. But, it's got the wolfenstein textures, and the brown-suited enemies from wolfenstein.

I tried my hand at getting that better way to cast the rays to work...of course it didn't...oh well. I just can't get it to work. I don't even know if I want to get it to work. To be honest, 23, that bug in yours, which is probly caused by the tangent or something, makes that method very unappealing. Maybe I can be enlightened from that java source code...idunno. But, for now, I can make the detail level adjustable. Basically, I can multiply teh x_inc and y_inc, and distance by a number, which makes it go much faster. Of course, you lose accuracy, but even when you multiply it by 5, you can get more than 10 more fps, and the output is still acceptable. Some of the smaller lines and details are lost somewhat, but it's not a problem. I'll just have the detail level adjustable.

TH: Could you compile it into a binary? My DJGPP complains about MANY "errors". I tried fixing some, but I just gave up. How smooth is it? Would you think that you were in a raycaster when you're running it? What is a 2D portal engine?

Carrus85
Member #2,633
August 2002
avatar

The TICT FAT engine doesn't really assist you in doing things directly. However, it might prove more useful to look at the forum under FAT SDK. The optimizations neccesarry to get a Raycaster to work on a graphing calculator are drastic, maybe you could implement some of them.

The current engine also has built in support for sprites (similar to wolf3d, blake stone, etc.), Moving walls for those secret passages, doors, etc.

However, once again I must reiterate the fact that it will only prove useful for opimizition, if at all.

aybabtu
Member #2,891
November 2002

Hey...I think I should put depth shading in...how should I do it? Use a blending function or something? If so, I've never used one before...are they slow?

Zaphos
Member #1,468
August 2001

aybabtu: On TH's: my compiler and updated allegro only gave one error, which was fixed by renaming the variable "Texture Texture" in the wall struct to "Texture texture" then searching through the file to find all instances in which (somewallvariable)->Texture was being used, and fixed the variable name. For your outdated as anything setup, however, I'm afraid there might be more errors, which is entirely your fault. Update your software.

Goodbytes
Member #448
June 2000
avatar

TH, I think the word you're looking for is sliver, not slither.

aybabtu: nice textures! The art for Wolfenstein is a lot nicer than I had thought it was... as for lighting, it depends on whether you're using 8-bit colour or hi-colour/true-colour modes. If you're using 8-bit colour, you have to use palette tricks of some sort, and the fastest way is to use a lookup table. If you're using a higher colour depth, you use a lighting function... which are you using?


--
~Goodbytes

23yrold3yrold
Member #1,134
March 2001
avatar

The Wolfenstein textures are as ugly as I remember :P Anyway, I think I may have licked the crashing someone else was getting, and I changed my DrawSlice() function so now it doesn't dip down to 14 fps if you're up against a wall. Now it stays over 90 at all times, but the texture is a little messed up (I think my math needs a little work). At least the texture doesn't reverse anymore (aybabtu, use a texture with a word on it and see if any of your walls come out with the word backwards). And I can still see slivers of perpendicular walls sticking through some other walls. I would post this in my thread, but it's a day old with the last post being mine, so no one would see it ;) So, here's my latest:

#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 240 8#define M_PI 3.1415926535897932 9#define MAPWIDTH 20 10#define MAPHEIGHT 10 11 12char level[MAPWIDTH][MAPHEIGHT]={ 13{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 14{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 15{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 16{1, 0, 0, 0, 0, 0, 0, 0, 1, 1}, 17{1, 0, 0, 1, 1, 1, 1, 1, 1, 1}, 18{1, 0, 0, 0, 1, 0, 0, 0, 0, 1}, 19{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 20{1, 1, 0, 0, 0, 0, 0, 0, 0, 1}, 21{1, 1, 1, 1, 1, 1, 1, 0, 0, 1}, 22{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 23{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 24{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 25{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 26{1, 0, 0, 0, 1, 1, 0, 0, 0, 1}, 27{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 28{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 29{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 30{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 31{1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 32{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}; 33 34int view[SCREENWIDTH]; 35int texture_map[SCREENWIDTH]; 36float px = 65; 37float py = 65; 38float p_old_x = 65; 39float p_old_y = 65; 40int ps = 2; // player speed 41float pa = 1; // player angle 42 43BITMAP* front; 44BITMAP* backdrop; 45BITMAP* texture; 46 47volatile int game_time = 0; 48volatile int fps_timer = 0; 49int fps = 0; 50int num_frames_drawn = 0; 51 52// Timer functions 53void Timer() { 54 ++game_time; 55}END_OF_FUNCTION(Timer); // end Timer() 56 57void FPSTimer() { 58 ++fps_timer; 59}END_OF_FUNCTION(FPSTimer); // end Timer() 60 61// float cast_ray(int x, int y, float a); 62float CastRay(int xpos, int ypos, double angle, int& t); 63void draw_view(); 64void do_raycasting(); 65bool collisions(); 66void DrawSlice(BITMAP* buffer, BITMAP* texture, int xoff, int x, int y, int tall); 67 68int main() 69{ 70 allegro_init(); 71 install_keyboard(); 72 set_color_depth(16); 73 set_gfx_mode(GFX_AUTODETECT, SCREENWIDTH, SCREENHEIGHT, 0, 0); 74 text_mode(-1); 75 76 LOCK_VARIABLE(game_time); 77 LOCK_VARIABLE(fps_timer); 78 LOCK_FUNCTION((void*)Timer); 79 LOCK_FUNCTION((void*)FPSTimer); 80 install_int_ex(Timer, BPS_TO_TIMER(120)); 81 install_int_ex(FPSTimer, BPS_TO_TIMER(1)); 82 83 front = create_bitmap(SCREENWIDTH, SCREENHEIGHT); 84 backdrop = create_bitmap(SCREENWIDTH, SCREENHEIGHT); 85 86 for(int i = 0 ; i < SCREENHEIGHT / 2 ; ++i) hline(backdrop, 0, i, SCREENWIDTH, makecol(200, 200, 255 - i)); 87 rectfill(backdrop, 0, SCREENHEIGHT / 2, SCREENWIDTH, SCREENHEIGHT, makecol(0,100,0)); 88 BITMAP* temp = load_bitmap("texture.bmp", NULL); 89 texture = create_bitmap(64, 64); 90 rotate_sprite(texture, temp, 0, 0, itofix(192)); 91 destroy_bitmap(temp); 92 93 while(!key[KEY_ESC]) 94 { 95 // clear(front); 96 blit(backdrop, front, 0, 0, 0, 0, SCREENWIDTH, SCREENHEIGHT); 97 do_raycasting(); 98 draw_view(); 99 100 /* 101 // draw the little compass/circle 102 line(front, 160, 120, 160 + (int)(25 * cos(pa)), 120 + (int)(25 * sin(pa)), makecol(0, 0, 255)); 103 line(front, 160, 120, 160 + (int)(25 * cos(pa - 0.523598)), 120 + (int)(25 * sin(pa - 0.523598)), makecol(255, 255, 0)); 104 line(front, 160, 120, 160 + (int)(25 * cos(pa + 0.523598)), 120 + (int)(25 * sin(pa + 0.523598)), makecol(255, 255, 0)); 105 circle(front, 160, 120, 25, makecol(255, 0, 0)); 106 textout_centre(front, font, "N", 160, 85, makecol(0, 0, 255)); 107 */ 108 109 ++num_frames_drawn; 110 if(fps_timer) 111 { 112 fps = num_frames_drawn; 113 fps_timer = num_frames_drawn = 0; 114 } 115 116 textprintf(front, font, 15, 5, makecol(0,0,255), "FPS: %d", fps); 117 118 // vsync(); 119 blit(front, screen, 0, 0, 0, 0, SCREENWIDTH, SCREENHEIGHT); 120 121 while(game_time > 0) 122 { 123 if(key[KEY_A]) 124 { 125 px -= (ps * cos(pa - M_PI / 2)); 126 py -= (ps * sin(pa - M_PI / 2)); 127 } 128 if(key[KEY_D]) 129 { 130 px += (ps * cos(pa - M_PI / 2)); 131 py += (ps * sin(pa - M_PI / 2)); 132 } 133 if(key[KEY_LEFT]) pa += 0.02; 134 if(key[KEY_RIGHT]) pa -= 0.02; 135 if(key[KEY_UP]) 136 { 137 px += (ps * cos(pa)); 138 py += (ps * sin(pa)); 139 } 140 if(key[KEY_DOWN]) 141 { 142 px -= (ps * cos(pa)); 143 py -= (ps * sin(pa)); 144 } 145 if(collisions() == true) 146 px = p_old_x, py = p_old_y; 147 148 p_old_x = px, p_old_y = py; 149 150 if(pa < 0) pa += M_PI * 2; 151 if(pa > M_PI * 2) pa -= M_PI * 2; 152 153 --game_time; 154 } 155 } 156 157 destroy_bitmap(front); 158 destroy_bitmap(texture); 159 destroy_bitmap(backdrop); 160 161 return 0; 162} 163END_OF_MAIN() 164 165void do_raycasting() 166{ 167 double angle = pa + 0.523598; 168 169 for(int i = 0 ; i < SCREENWIDTH ; ++i) 170 { 171 // get the distance of the ray 172 view<i> = (int)(cos(angle - pa) * CastRay((int)px, (int)py, angle, texture_map<i>)); 173 if(!view<i>) view<i> = 1; 174 175 // increment the angle 176 angle -= 1.04719 / SCREENWIDTH; 177 if(angle < 0) angle += M_PI * 2; 178 } 179} 180 181void draw_view() 182{ 183 int tall = 0; 184 185 for(int i = 0 ; i < SCREENWIDTH ; ++i) 186 { 187 tall = (int)(64.0 / view<i> * 277.0); // * (SCREENHEIGHT / 320); 188 // stretch_blit(texture, front, texture_map<i>, 0, 1, 64, i, (SCREENHEIGHT - tall) / 2, 1, tall); 189 DrawSlice(front, texture, texture_map<i>, i, (SCREENHEIGHT - tall) / 2, tall); 190 } 191} 192 193bool collisions() 194{ 195 return (bool)level[(int)px >> TILESHIFT][(int)py >> TILESHIFT]; 196} 197 198float CastRay(int xpos, int ypos, double angle, int& t) { 199 // initialize (X_Ycheck, X_Xcheck) with first vertical wall and 200 // (Y_Ycheck, Y_Xcheck) with the first horizontal one 201 float X_Ycheck, X_Xcheck, Y_Ycheck, Y_Xcheck; 202 float X_Yinc, X_Xinc, Y_Yinc, Y_Xinc; 203 204 // hacka hacka hacka .... 205 // if(angle < 0.01 && angle > 0) angle = 0.01; 206 // if(angle < M_PI + 0.01 && angle > M_PI) angle = M_PI + 0.01; 207 // if(angle < M_PI && angle > M_PI - 0.01) angle = M_PI - 0.01; 208 209 double tangent = tan(angle); 210 if(tangent >= 0.0 && tangent < 0.004) tangent = 0.004; 211 if(tangent <= 0.0 && tangent > -0.004) tangent = -0.004; 212 // if(tangent > 9999) tangent = 9999; 213 // if(tangent < -9999) tangent = -9999; 214 215 // sin(90) == 1; sin(270) == -1 216 if(sin(angle) > 0) // The y-values are increasing 217 // if(angle > 0 && angle < M_PI) 218 { 219 Y_Ycheck = (ypos / 64) * 64 + 64; 220 Y_Xcheck = xpos + (Y_Ycheck - ypos) / tangent; 221 Y_Yinc = 64; 222 Y_Xinc = 64 / tangent; 223 } else { // The y-values are decreasing 224 Y_Ycheck = (ypos / 64) * 64 - 1; 225 Y_Xcheck = xpos + (Y_Ycheck - ypos) / tangent; 226 Y_Yinc = -64; 227 Y_Xinc = -64 / tangent; 228 } 229 230 // check for the walls 231 while(((int)Y_Xcheck >> 6 < MAPWIDTH) && 232 ((int)Y_Ycheck >> 6 < MAPHEIGHT) && 233 ((int)Y_Xcheck >> 6 >= 0) && 234 ((int)Y_Ycheck >> 6 >= 0) && 235 level[(int)Y_Xcheck >> TILESHIFT][(int)Y_Ycheck >> TILESHIFT] == 0) 236 { 237 Y_Xcheck += Y_Xinc; 238 Y_Ycheck += Y_Yinc; 239 } 240 241 // cos(0) == 1; cos(180) == -1 242 // if(cos(angle) > 0) // The x-values are increasing 243 if(angle < M_PI / 2 || angle > M_PI + M_PI / 2) // The x-values are increasing 244 { 245 X_Xcheck = (xpos / 64) * 64 + 64; 246 X_Ycheck = ypos + (X_Xcheck - xpos) * tangent; 247 X_Xinc = 64; 248 X_Yinc = 64 * tangent; 249 } 250 else // The x-values are decreasing 251 { 252 X_Xcheck = (xpos / 64) * 64 - 1; 253 X_Ycheck = ypos + (X_Xcheck - xpos) * tangent; 254 X_Xinc = -64; 255 X_Yinc = -64 * tangent; 256 } 257 258 // check for the walls 259 while(((int)X_Xcheck >> 6 < MAPWIDTH) && 260 ((int)X_Ycheck >> 6 < MAPHEIGHT) && 261 ((int)X_Xcheck >> 6 >= 0) && 262 ((int)X_Ycheck >> 6 >= 0) && 263 level[(int)X_Xcheck >> TILESHIFT][(int)X_Ycheck >> TILESHIFT] == 0) 264 { 265 X_Xcheck += X_Xinc; 266 X_Ycheck += X_Yinc; 267 } 268 269 float xcheck = (X_Xcheck - xpos) * (X_Xcheck - xpos) + (X_Ycheck - ypos) * (X_Ycheck - ypos); 270 float ycheck = (Y_Xcheck - xpos) * (Y_Xcheck - xpos) + (Y_Ycheck - ypos) * (Y_Ycheck - ypos); 271 272 // the ?: stuff in here is to make sure the right texture coordinate is 273 // returned; otherwise, half the textures in the game are reversed 274 if(xcheck < ycheck) 275 { 276 t = (angle < M_PI / 2 || angle > M_PI + M_PI / 2) ? (int)X_Ycheck % TILE : 63 - ((int)X_Ycheck % TILE); 277 return sqrt(xcheck); 278 } 279 else 280 { 281 t = (angle > M_PI) ? (int)Y_Xcheck % TILE : 63 - ((int)Y_Xcheck % TILE); 282 return sqrt(ycheck); 283 } 284} 285 286void DrawSlice(BITMAP* buffer, BITMAP* texture, int xoff, int x, int y, int tall) 287{ 288 int srcy = 0, num = 0; 289 290 // skip down until we hit the top of the screen (for very close walls) 291 if(tall > SCREENHEIGHT) 292 { 293 num = 32 * (tall - SCREENHEIGHT); 294 295 if(num >= tall) 296 { 297 srcy = num / tall; 298 num = num % 64; 299 } 300 301 y = 0; 302 } 303 304 for(int i = y ; i < y + tall ; ++i) 305 { 306 num += 64; 307 308 while(num >= tall) 309 { 310 num -= tall; 311 ++srcy; 312 } 313 314 // if(i < 0) continue; 315 if(srcy >= 64 || i >= buffer->h) return; 316 317 // this assumes the texture is rotated (otherwise it's slower due to cache missing) 318 // ((short *)buffer->line<i>)[x] = (((short*)texture->line[xoff])[srcy] >> 1 & 0x7BEF); 319 ((short *)buffer->line<i>)[x] = ((short*)texture->line[xoff])[srcy]; 320 } 321}

I made a little test for shading the walls and it barely affected the FPS, so I'll probably give depth shading a shot soon ...

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

Johnny13
Member #805
October 2000
avatar

23:'for'loop initial declaration used outside C99 mode

Quote:

// check for the walls
while(((int)X_Xcheck >> 6 < MAPWIDTH) &&
((int)X_Ycheck >> 6 < MAPHEIGHT)

you still checking the level[] boundary? use getpixel in Mypost!:P
and plz shorten your code or Attach it! your codebox is now 9.9k! sp4mm3r!;)

and test the FPS yourself:

while(!key[KEY_ESC])
{if(key[KEY_1])mode=0;if(key[KEY_2])mode=1;
 if(mode) for(i=0;i<H;i++)hline(front,0,i,W,(i<H/2)?MC(133,160,255-i):MC(i,i,i));
 else blit(backdrop,front,0,0,0,0,W,H);

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

Ace
Member #1,781
December 2001
avatar

23yrold3yrold: It's not crashing for me anymore (yay!), but it does drop below 90 when I'm next to a wall. To about 60 fps. ;) Maybe my computer is being weird.

- Ace

23yrold3yrold
Member #1,134
March 2001
avatar

Quote:

23:'for'loop initial declaration used outside C99 mode

C++ coders care. ;)

Quote:

you still checking the level[] boundary?

Hell yes! Much faster than getpixel(). What would using getpixel() get me anyway?

Quote:

and plz shorten your code or Attach it! your codebox is now 9.9k!

Is that why your code has almost 0 whitespace?

And I am testing the fps myself (or was that directed at aybabtu?) ...

Ace: Cool 8-)

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



Go to: