|
|
| 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: 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
|
I see no picture. Does this mean your columns are 1 pixel wide instead of 2 now? -- |
|
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
|
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:
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. -- |
|
aybabtu
Member #2,891
November 2002
|
Alright...I'll try that rotate 90 degrees thing. |
|
23yrold3yrold
Member #1,134
March 2001
|
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 I'd still love to have my math problems magically disappear. Until then, I'm potentially optimising my errors, and that's no fun -- |
|
Bob
Free Market Evangelist
September 2000
|
Quote: Oooohh! Is that because of cache missing or whatever you call it?
Yep -- |
|
aybabtu
Member #2,891
November 2002
|
Arg. Could someone help me understand it?:-/ |
|
23yrold3yrold
Member #1,134
March 2001
|
1) Basically, by rounding to the nearest 64 for one coordinate, then by using the tangent of the angle to get the other coordinate. I still don't quite understand tan() enough to explain it. If it's not in amarillion's tutorial, it should be -- |
|
aybabtu
Member #2,891
November 2002
|
I'm okay with tan: |
|
Thomas Harte
Member #33
April 2000
|
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 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. [My site] [Tetrominoes] |
|
aybabtu
Member #2,891
November 2002
|
That's neat...seems more complex than raycasting, though...:) EDIT: 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
|
Yeah, textures are pretty easy. Just use different numbers in the array 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 -- |
|
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
|
Quote: I just downloaded that FAT engine SDK What's this now? What does it do that that site doesn't teach? -- |
|
Thomas Harte
Member #33
April 2000
|
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). [My site] [Tetrominoes] |
|
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
|
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
|
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? |
|
23yrold3yrold
Member #1,134
March 2001
|
The Wolfenstein textures are as ugly as I remember 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 ... -- |
|
Johnny13
Member #805
October 2000
|
23:'for'loop initial declaration used outside C99 mode Quote: // check for the walls you still checking the level[] boundary? use getpixel in Mypost!:P and test the FPS yourself:
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
|
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. - Ace |
|
23yrold3yrold
Member #1,134
March 2001
|
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 -- |
|
|
|