Achtung!

WolFICstein 3D: Código fuente

Rayc.java

  1 // Raycasting technical demo
  2 
  3 // Modified by Raziel
  4 // Original version by F. Permadi: http://www.permadi.com/java/rayc/index.html
  5 
  6 // Improvements made by Raziel:
  7 //    Minimap supports scrolling
  8 //    Collision detection
  9 //    Basic HUD support
 10 //    Textured walls
 11 //    Animated walls
 12 //    Variable resolution
 13 //    Bang!
 14 
 15 
 16 // Original version disclaimer:
 17 //********************************************************************//
 18 //* F. PERMADI MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE      *//
 19 //* SUITABILITY OF                                                   *//
 20 //* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT       *//
 21 //* LIMITED                                                          *//
 22 //* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A      *//
 23 //* PARTICULAR PURPOSE                                               *//
 24 //********************************************************************//
 25 
 26 
 27 import java.awt.*;
 28 import java.awt.event.*;
 29 import java.applet.*;
 30 
 31 
 32 public class Rayc extends Applet implements Runnable, KeyListener {
 33 
 34 
 35 	Thread fThread;
 36 	volatile boolean stop;
 37 
 38 
 39 	static final int TILE_SIZE = 64;
 40 	static final int PROJECTIONPLANEWIDTH = 320;
 41 	static final int PROJECTIONPLANEHEIGHT = 200;
 42 
 43 	static final int ANGLE60 = PROJECTIONPLANEWIDTH;
 44 	static final int ANGLE30 = (ANGLE60/2);
 45 	static final int ANGLE15 = (ANGLE30/2);
 46 	static final int ANGLE90 = (ANGLE30*3);
 47 	static final int ANGLE180 = (ANGLE90*2);
 48 	static final int ANGLE270 = (ANGLE90*3);
 49 	static final int ANGLE360 = (ANGLE60*6);
 50 	static final int ANGLE0 = 0;
 51 	static final int ANGLE5 = (ANGLE30/6);
 52 	static final int ANGLE10 = (ANGLE5*2);
 53 
 54 	// trigonometric tables
 55 	float fSinTable[];
 56 	float fISinTable[];
 57 	float fCosTable[];
 58 	float fICosTable[];
 59 	float fTanTable[];
 60 	float fITanTable[];
 61 	float fFishTable[];
 62 	float fXStepTable[];
 63 	float fYStepTable[];
 64 
 65 	// offscreen buffer
 66 	Image fOffscreenImage;
 67 	Graphics fOffscreenGraphics;
 68 
 69 	Image weapon;
 70 	Image walls[][];
 71 	Image band[][];
 72 
 73 	// player's attributes
 74 	int fPlayerX = 285;
 75 	int fPlayerY = 160;
 76 	int fPlayerArc = ANGLE90;
 77 	int fPlayerDistanceToTheProjectionPlane = 277;
 78 	int fPlayerHeight =32;
 79 	int fPlayerSpeed = 16;
 80 	int fProjectionPlaneYCenter = PROJECTIONPLANEHEIGHT/2;
 81 	// the following variables are used to keep the player coordinate in the overhead map
 82 	int fPlayerMapX, fPlayerMapY;
 83 	int fMinimapWidth = 5;
 84 	int mapOffsetY = 0;
 85 
 86 	// movement flag
 87 	boolean fKeyUp=false;
 88 	boolean fKeyDown=false;
 89 	boolean fKeyLeft=false;
 90 	boolean fKeyRight=false;
 91 
 92 	final int maxRes = 10;
 93 	final int minRes = 1;
 94 	int resolution = minRes;
 95 
 96 	// For Amusement Only
 97 	int fBang=-1;
 98 	Color fBangC;
 99 	int fBangX, fBangY;
100 	int fBand = 0;
101 	java.util.Random rnd;
102 
103 
104 	static byte fMap[] = {
105 		1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,
106 		1,0,0,5,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,5,0,0,1,
107 		1,0,0,1,0,6,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,
108 		1,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,1,1,1,
109 		1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,0,0,1,
110 		1,0,0,5,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,5,0,0,1,
111 		1,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,1,1,1,
112 		1,0,0,5,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,5,0,0,1,
113 		1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,5,0,0,1,
114 		1,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,3,1,1,
115 		1,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,1,
116 		1,0,0,5,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,
117 		1,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,2,1,1,
118 		1,0,0,5,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,5,0,0,1,
119 		1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,0,0,1,
120 		1,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,1,1,1,
121 		1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,0,0,1,
122 		1,0,0,5,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,5,0,0,1,
123 		1,1,1,1,0,1,0,0,0,3,0,3,0,3,0,0,0,1,0,1,1,1,1,
124 		1,0,0,5,0,1,1,1,1,1,0,0,0,1,1,1,1,1,0,5,0,0,1,
125 		1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,
126 		1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,
127 		1,0,0,1,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,1,0,0,1,
128 		1,0,0,5,0,1,0,0,5,0,0,0,0,0,0,0,0,1,0,5,0,0,1,
129 		1,1,1,1,0,1,0,0,1,0,0,0,0,0,1,0,0,1,0,1,1,1,1,
130 		1,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,0,1,0,5,0,0,1,
131 		7,0,0,1,0,1,0,0,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,
132 		1,1,1,1,4,1,1,1,1,1,6,1,0,1,1,1,1,1,4,1,1,1,1,
133 
134 		0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
135 		0,0,0,0,0,0,0,0,4,0,0,0,0,0,4,0,0,0,0,0,0,0,0,
136 		0,0,0,0,0,0,0,0,4,0,0,0,0,0,4,0,0,0,0,0,0,0,0,
137 
138 		1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,
139 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
140 		1,1,1,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,1,1,1,
141 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
142 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
143 		1,1,1,1,1,1,5,1,1,0,0,0,0,0,1,1,5,1,1,1,1,1,1,
144 		1,0,0,0,0,0,0,1,7,0,0,0,0,0,7,1,0,0,0,0,0,0,1,
145 		1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,
146 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
147 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,6,0,0,0,0,0,0,0,1,
148 		1,0,0,0,0,0,0,0,6,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
149 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
150 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
151 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
152 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
153 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
154 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
155 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,6,0,0,0,0,0,0,0,1,
156 		1,0,0,0,0,0,0,0,6,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
157 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
158 		1,1,1,1,1,1,1,1,2,0,0,0,0,0,2,1,1,1,1,1,1,1,1,
159 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
160 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,6,0,0,0,0,0,0,0,1,
161 		1,0,0,0,0,0,0,0,6,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
162 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
163 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
164 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
165 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
166 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
167 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
168 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
169 		1,0,0,0,0,0,0,0,6,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
170 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
171 		1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,
172 
173 		0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,1, 0,0,0,0,
174 		0,0,0,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,3, 0,0,0,0,
175 		0,0,0,1,0,0,1,0,2,0,0,0,0,0,0,0,0,0,8, 0,0,0,0,
176 		0,0,0,1,0,0,5,0,1,0,0,0,0,0,0,0,0,0,9, 0,0,0,0,
177 		0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,12,0,0,0,0,
178 		0,0,0,1,1,1,1,1,7,0,0,0,0,0,0,0,0,0,13,0,0,0,0,
179 		0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,14,0,0,0,0,
180 		0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,11,0,0,0,0,
181 		0,0,0,1,0,0,1,0,2,0,0,0,0,0,0,0,0,0,10,0,0,0,0,
182 		0,0,0,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,3, 0,0,0,0,
183 		0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,1, 0,0,0,0,
184 
185 		1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,
186 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
187 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
188 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,6,0,0,0,0,0,0,0,1,
189 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
190 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
191 		1,0,0,0,0,0,0,0,6,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
192 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,0,1,
193 		1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,
194 		1,0,0,0,0,0,0,0,2,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
195 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,6,0,0,0,0,0,0,0,1,
196 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
197 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
198 		1,0,0,0,0,0,0,0,6,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
199 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,0,1,
200 		1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,
201 		1,0,0,0,0,0,0,0,2,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
202 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,6,0,0,0,0,0,0,0,1,
203 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
204 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
205 		1,0,0,0,0,0,0,0,6,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
206 		1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,
207 		1,1,1,1,1,1,1,1,1,1,4,2,4,1,1,1,1,1,1,1,1,1,1
208 	};
209 
210 	static final int MAP_WIDTH = 23;
211 	static final int MAP_HEIGHT = fMap.length/MAP_WIDTH;
212 
213 
214 	float arcToRad(float arcAngle) {
215 		return ((float)(arcAngle*Math.PI)/(float)ANGLE180);    
216 	}
217 
218 
219 	// Creates tigonometric values to speed up the engine
220 	public void createTables() {
221 
222 		int i;
223 		float radian;
224 		fSinTable   = new float[ANGLE360+1];
225 		fISinTable  = new float[ANGLE360+1];
226 		fCosTable   = new float[ANGLE360+1];
227 		fICosTable  = new float[ANGLE360+1];
228 		fTanTable   = new float[ANGLE360+1];
229 		fITanTable  = new float[ANGLE360+1];
230 		fFishTable  = new float[ANGLE60+1];
231 		fXStepTable = new float[ANGLE360+1];
232 		fYStepTable = new float[ANGLE360+1];
233 
234 		for (i=0; i<=ANGLE360; i++) {
235 
236 			// get the radian value (the last addition is to avoid division by 0, try removing
237 			// that and you'll see a hole in the wall when a ray is at 0, 90, 180, or 270 degree)
238 
239 			radian = arcToRad(i) + (float)(0.0001);
240 			fSinTable[i]=(float)Math.sin(radian);
241 			fISinTable[i]=(1.0F/(fSinTable[i]));
242 			fCosTable[i]=(float)Math.cos(radian);
243 			fICosTable[i]=(1.0F/(fCosTable[i]));
244 			fTanTable[i]=(float)Math.tan(radian);
245 			fITanTable[i]=(1.0F/fTanTable[i]);
246 
247 
248 			//  you can see that the distance between xi is the same
249 			//  if we know the angle
250 			//  _____|_/next xi______________
251 			//       |
252 			//  ____/|next xi_________   slope = tan = height / dist between xi's
253 			//     / |
254 			//  __/__|_________  dist between xi = height/tan where height=tile size
255 			// old xi|
256 			//                  distance between xi = x_step[view_angle];
257 			//
258 			//
259 
260 
261 			// facing left
262 			if (i>=ANGLE90 && i<ANGLE270) {
263 				fXStepTable[i] = (float)(TILE_SIZE/fTanTable[i]);
264 				if (fXStepTable[i]>0)
265 					fXStepTable[i]=-fXStepTable[i];
266 			}
267 
268 			// facing right
269 			else {
270 				fXStepTable[i] = (float)(TILE_SIZE/fTanTable[i]);
271 				if (fXStepTable[i]<0)
272 					fXStepTable[i]=-fXStepTable[i];
273 			}
274 
275 			// facing down
276 			if (i>=ANGLE0 && i<ANGLE180) {
277 				fYStepTable[i] = (float)(TILE_SIZE*fTanTable[i]);
278 				if (fYStepTable[i]<0)
279 					fYStepTable[i]=-fYStepTable[i];
280 			}
281 
282 			// facing up
283 			else {
284 				fYStepTable[i] = (float)(TILE_SIZE*fTanTable[i]);
285 				if (fYStepTable[i]>0)
286 					fYStepTable[i]=-fYStepTable[i];
287 			}
288 
289 		}
290 
291 		for (i=-ANGLE30; i<=ANGLE30; i++) {
292 			radian = arcToRad(i);
293 			// we don't have negative angle, so make it start at 0
294 			// this will give range 0 to 320
295 			fFishTable[i+ANGLE30] = (float)(1.0F/Math.cos(radian));
296 		}
297 
298 	}
299 
300 
301 	void loadBitmaps() {
302 		
303 		weapon = getImage(getClass().getResource("images/gun.png"));
304 		prepareImage(weapon, this);
305 
306 		final int nWalls = 15;
307 
308 		walls = new Image[nWalls][2];
309 		walls[0][0] = null;
310 		walls[0][1] = null;
311 		walls[1][0] = getImage(getClass().getResource("images/cath01.png"));
312 		walls[1][1] = getImage(getClass().getResource("images/cath01d.png"));
313 		walls[2][0] = getImage(getClass().getResource("images/cath04.png"));
314 		walls[2][1] = getImage(getClass().getResource("images/cath04d.png"));
315 		walls[3][0] = getImage(getClass().getResource("images/cath03.png"));
316 		walls[3][1] = getImage(getClass().getResource("images/cath03d.png"));
317 		walls[4][0] = getImage(getClass().getResource("images/window.png"));
318 		walls[4][1] = walls[4][0];
319 		walls[5][0] = getImage(getClass().getResource("images/door1.png"));
320 		walls[5][1] = getImage(getClass().getResource("images/door1d.png"));
321 		walls[6][0] = getImage(getClass().getResource("images/door2.png"));
322 		walls[6][1] = walls[6][0];
323 		walls[7][0] = getImage(getClass().getResource("images/elev.png"));
324 		walls[7][1] = getImage(getClass().getResource("images/elevd.png"));
325 
326 
327 		// Band (lol)
328 		band = new Image[4][2];
329 		band[0][0] = getImage(getClass().getResource("images/band00.png"));
330 		band[0][1] = getImage(getClass().getResource("images/band01.png"));
331 		band[1][0] = getImage(getClass().getResource("images/band10.png"));
332 		band[1][1] = getImage(getClass().getResource("images/band11.png"));
333 		band[2][0] = getImage(getClass().getResource("images/band20.png"));
334 		band[2][1] = getImage(getClass().getResource("images/band21.png"));
335 		band[3][0] = getImage(getClass().getResource("images/band30.png"));
336 		band[3][1] = getImage(getClass().getResource("images/band31.png"));
337 		walls[8][1] = band[0][0];
338 		walls[9][1] = band[1][0];
339 		walls[10][1] = band[2][0];
340 		walls[11][1] = band[3][0];
341 		walls[12][1] = getImage(getClass().getResource("images/rocks1.png"));
342 		walls[13][1] = getImage(getClass().getResource("images/rocks2.png"));
343 		walls[14][1] = getImage(getClass().getResource("images/rocks3.png"));
344 		
345 		for (int i=1; i<nWalls; i++) {
346 			prepareImage(walls[i][0], this);
347 			prepareImage(walls[i][1], this);
348 		}
349 		for (int i=0; i<4; i++)
350 			prepareImage(band[i][1], this);
351 
352 	}
353 
354 
355 	public void start() {
356 		this.addKeyListener(this);
357 
358 		createTables();
359 		loadBitmaps();
360 
361 		rnd = new java.util.Random();
362 		fThread = new Thread(this);
363 		fThread.start();
364 	}
365 
366 
367 	public void run() {
368 
369         requestFocus();
370 
371         // create offscreen buffer
372 		fOffscreenImage=createImage(getSize().width, getSize().height);
373 		fOffscreenGraphics=fOffscreenImage.getGraphics();
374 
375 		bigFatLoop();
376 		
377 	}
378 
379 
380 	public void stop() {
381         if((fThread != null) && fThread.isAlive())
382 			stop = true;
383 	}
384 
385 
386 	public void paint(Graphics g) {
387 		if (fOffscreenImage!=null)
388 			g.drawImage(fOffscreenImage, 0, 0, this);
389 	}
390 
391 
392 	public void keyPressed(KeyEvent e) {
393 
394 		switch (e.getKeyCode())
395 			{
396 			case KeyEvent.VK_UP:
397 			case KeyEvent.VK_W:
398 				fKeyUp=true;
399 				break;
400 			case KeyEvent.VK_DOWN:
401 			case KeyEvent.VK_S:
402 				fKeyDown=true;
403 				break;
404 			case KeyEvent.VK_LEFT:
405 			case KeyEvent.VK_A:
406 				fKeyLeft=true;
407 				break;
408 			case KeyEvent.VK_RIGHT:
409 			case KeyEvent.VK_D:
410 				fKeyRight=true;
411 				break;
412 
413 			case KeyEvent.VK_SPACE:
414 				fBang=5;
415 				fBangX = rnd.nextInt()%50 - 15;
416 				fBangY = rnd.nextInt()%40 - 10;
417 				fBangC = new Color(rnd.nextFloat(), rnd.nextFloat(), rnd.nextFloat());
418 				break;
419 
420 			case KeyEvent.VK_R:
421 				if (resolution > minRes)
422 					--resolution;
423 				break;
424 			case KeyEvent.VK_F:
425 				if (resolution < maxRes)
426 					++resolution;
427 				break;
428 
429 			default:
430 			}
431 
432 	}
433 
434 	public void keyReleased(KeyEvent e) {
435 
436 		switch (e.getKeyCode())
437 			{
438 			case KeyEvent.VK_UP:
439 			case KeyEvent.VK_W:
440 				fKeyUp=false;
441 				break;
442 			case KeyEvent.VK_DOWN:
443 			case KeyEvent.VK_S:
444 				fKeyDown=false;
445 				break;
446 			case KeyEvent.VK_LEFT:
447 			case KeyEvent.VK_A:
448 				fKeyLeft=false;
449 				break;
450 			case KeyEvent.VK_RIGHT:
451 			case KeyEvent.VK_D:
452 				fKeyRight=false;
453 				break;
454 			default:
455 			}
456 
457 	}
458 		
459 	public void keyTyped(KeyEvent e) {}
460 
461 
462 	private void bigFatLoop() {
463 
464 		while(!stop) {
465 			// rotate left
466 			if (fKeyLeft) {
467 				if ((fPlayerArc-=ANGLE10) < ANGLE0)
468 					fPlayerArc+=ANGLE360;
469 			}
470 
471 			// rotate right
472 			else if (fKeyRight) {
473 				if ((fPlayerArc+=ANGLE10) >= ANGLE360)
474 					fPlayerArc-=ANGLE360;
475 			}
476 
477 			//  _____     _
478 			// |\ arc     |
479 			// |  \       y
480 			// |    \     |
481 			//            -
482 			// |--x--|  
483 			//
484 			//  sin(arc)=y/diagonal
485 			//  cos(arc)=x/diagonal   where diagonal=speed
486 
487 			float playerXDir = fCosTable[fPlayerArc];
488 			float playerYDir = fSinTable[fPlayerArc];
489 			float playerXMargin = 5*playerXDir;
490 			float playerYMargin = 5*playerYDir;
491 
492 			// move forward
493 			if (fKeyUp) {
494 				int fPlayerXinc = fPlayerX + (int)(playerXDir*fPlayerSpeed);
495 				int fPlayerYinc = fPlayerY + (int)(playerYDir*fPlayerSpeed);
496 				if (fMap[(int)((fPlayerXinc+playerXMargin)/TILE_SIZE)
497 						 + MAP_WIDTH * (int)((fPlayerY+playerYMargin)/TILE_SIZE)] == 0)
498 					fPlayerX = fPlayerXinc;
499 				if (fMap[(int)((fPlayerX+playerXMargin)/TILE_SIZE)
500 						 + MAP_WIDTH * (int)((fPlayerYinc+playerYMargin)/TILE_SIZE)] == 0)
501 					fPlayerY = fPlayerYinc;
502 			}
503 
504 			// move backward
505 			else if (fKeyDown) {
506 				int fPlayerXinc = fPlayerX - (int)(playerXDir*fPlayerSpeed);
507 				int fPlayerYinc = fPlayerY - (int)(playerYDir*fPlayerSpeed);
508 				if (fMap[(int)((fPlayerXinc-playerXMargin)/TILE_SIZE)
509 						 + MAP_WIDTH * (int)((fPlayerY-playerYMargin)/TILE_SIZE)] == 0)
510 					fPlayerX = fPlayerXinc;
511 				if (fMap[(int)((fPlayerX-playerXMargin)/TILE_SIZE)
512 						 + MAP_WIDTH * (int)((fPlayerYinc-playerYMargin)/TILE_SIZE)] == 0)
513 					fPlayerY = fPlayerYinc;
514 			}
515 
516 			// Band stuff
517 			switch (fBand++) {
518 			case 0:
519 				walls[9][1] = band[1][0];
520 				walls[11][1] = band[3][0];
521 				break;
522 
523 			case 1:
524 				walls[8][1] = band[0][0];
525 				walls[10][1] = band[2][0];
526 				break;
527 
528 			case 3:
529 				walls[8][1] = band[0][1];
530 				walls[10][1] = band[2][1];
531 				break;
532 
533 			case 4:
534 				walls[9][1] = band[1][1];
535 				walls[11][1] = band[3][1];
536 				break;
537 
538 			case 6:
539 				fBand = -1;
540 				break;
541 
542 			default:
543 				break;
544 			}
545 
546 
547 			render();
548 
549 			try {
550 				Thread.sleep(50);
551 			} catch (Exception sleepProblem) {
552 				showStatus("Insomnia");
553 			}
554 		}
555 
556 	}
557 
558 
559 
560 	private void drawBackground() {
561 
562 		/*
563 		// sky
564 		int c=25;
565 		int r;
566 		for (r=0; r<PROJECTIONPLANEHEIGHT/2; r+=10) {
567 		fOffscreenGraphics.setColor(new Color(c, 125, 225));
568 		fOffscreenGraphics.fillRect(0, r, PROJECTIONPLANEWIDTH, 10);
569 		c+=20;
570 		}
571 
572 		// ground
573 		c=22;
574 		for (; r<PROJECTIONPLANEHEIGHT; r+=15) {
575 		fOffscreenGraphics.setColor(new Color(c, 20, 20));
576 		fOffscreenGraphics.fillRect(0, r, PROJECTIONPLANEWIDTH, 15);
577 		c+=15;
578 		}
579 		*/
580 
581 		fOffscreenGraphics.setColor(Color.gray);
582 		fOffscreenGraphics.fillRect(0, 0,
583 									PROJECTIONPLANEWIDTH, PROJECTIONPLANEHEIGHT/2);
584 		fOffscreenGraphics.setColor(Color.darkGray);
585 		fOffscreenGraphics.fillRect(0, PROJECTIONPLANEHEIGHT/2,
586 									PROJECTIONPLANEWIDTH, PROJECTIONPLANEHEIGHT/2);
587 
588 	}
589 
590 
591 
592 	private void drawOverheadMap() {
593 
594 		fPlayerMapX=PROJECTIONPLANEWIDTH+(int)(((float)fPlayerX/(float)TILE_SIZE) * fMinimapWidth);
595 		fPlayerMapY=(int)(((float)fPlayerY/(float)TILE_SIZE) * fMinimapWidth);
596 
597 		int plrOffsetY = fPlayerMapY/fMinimapWidth;
598 		int mapTilesY = PROJECTIONPLANEHEIGHT/fMinimapWidth;
599 
600 		if (plrOffsetY <= mapTilesY/2)
601 			mapOffsetY = 0;
602 		else if (plrOffsetY >= MAP_HEIGHT - (mapTilesY/2))
603 			mapOffsetY = MAP_HEIGHT - mapTilesY;
604 		else
605 			mapOffsetY = plrOffsetY - (mapTilesY/2);
606 
607 		for (int u=0; u<MAP_WIDTH; u++) {
608 			for (int v=0; v<mapTilesY; v++) {
609 				if (fMap[(v+mapOffsetY)*MAP_WIDTH+u] != 0) {
610 					fOffscreenGraphics.setColor(Color.cyan);
611 				} else {
612 					fOffscreenGraphics.setColor(Color.black);
613 				}
614 				fOffscreenGraphics.fillRect(PROJECTIONPLANEWIDTH+(u*fMinimapWidth), (v*fMinimapWidth),
615 											fMinimapWidth, fMinimapWidth);
616 			}
617 		}
618         
619 	}
620 
621 
622 
623 	private void drawRayOnOverheadMap(float x, float y) {
624 
625         // draw line from the player position to the position where the ray
626         // intersect with wall
627         fOffscreenGraphics.setColor(Color.yellow);
628         fOffscreenGraphics.drawLine(fPlayerMapX,
629 									fPlayerMapY - mapOffsetY * fMinimapWidth,
630 									(int)(PROJECTIONPLANEWIDTH
631 										  + ((float)(x * fMinimapWidth)/(float)TILE_SIZE)),
632 									(int)(((float)(y * fMinimapWidth)/(float)TILE_SIZE)
633 										  - mapOffsetY * fMinimapWidth));
634 
635         // draw a red line indication the player's direction
636         fOffscreenGraphics.setColor(Color.red);
637 		fOffscreenGraphics.drawLine(fPlayerMapX,
638 									fPlayerMapY - mapOffsetY * fMinimapWidth,
639 									(int)(fPlayerMapX + fCosTable[fPlayerArc]*10),
640 									(int)((fPlayerMapY + fSinTable[fPlayerArc]*10)
641 										  - mapOffsetY * fMinimapWidth));
642 	}
643 
644 	private void drawHUD() {
645 
646 		// Weapon
647 		fOffscreenGraphics.drawImage(weapon,
648 									 (PROJECTIONPLANEWIDTH-weapon.getWidth(this))/2,
649 									 (PROJECTIONPLANEHEIGHT-weapon.getHeight(this)),
650 									 this);
651 
652 		if (fBang > 0) {
653 			// Alright, it's kinda dirty, but who cares?
654 			--fBang;
655 			fOffscreenGraphics.setColor(fBangC);
656 			fOffscreenGraphics.setFont(new Font("Monospaced", Font.BOLD|Font.CENTER_BASELINE, 20));
657 			fOffscreenGraphics.drawString("*Bang!*", PROJECTIONPLANEWIDTH/2-22 + fBangX,
658 										  PROJECTIONPLANEHEIGHT*3/4 + fBangY);
659 		}
660 
661 	}
662 
663 
664 	public void render() {
665 
666         drawBackground();
667 		drawOverheadMap();
668 
669 		int verticalGrid;                        // horizotal or vertical coordinate of intersection
670 		int horizontalGrid;                      // theoritically, this will be multiple of TILE_SIZE
671 		                                         // , but some trick did here might cause
672 		                                         // the values off by 1
673 		int distToNextVerticalGrid;              // how far to the next bound (this is multiple of
674 		int distToNextHorizontalGrid;            // tile size)
675 		float xIntersection;                     // x and y intersections
676 		float yIntersection;
677 		float distToNextXIntersection;
678 		float distToNextYIntersection;
679 
680 		int xGridIndex;                          // the current cell that the ray is in
681 		int yGridIndex;
682 
683 		float distToVerticalGridBeingHit;        // the distance of the x and y ray intersections from
684 		float distToHorizontalGridBeingHit;      // the viewpoint
685 
686 		int castArc, castColumn;
687 
688 		float dist;
689 		int slice, material, wallColor;
690 
691 
692         // Field of view is 60 degree with the point of view
693 		// (player's direction in the middle)
694         //   30   30
695         //      ^
696         //    \ | /
697         //     \|/
698         //      v
699         // We will trace the rays starting from the leftmost ray
700 
701 
702 		castArc = fPlayerArc - ANGLE30;
703 
704 		if (castArc < 0)
705 			castArc += ANGLE360;
706 
707 
708 		for (castColumn=0; castColumn<PROJECTIONPLANEWIDTH; castColumn+=resolution) {
709 
710 			/* Horizontal Collision */
711 
712 			// Ray is facing down
713 			if (castArc > ANGLE0 && castArc < ANGLE180) {
714 				horizontalGrid = (fPlayerY/TILE_SIZE) * TILE_SIZE + TILE_SIZE;
715 				distToNextHorizontalGrid = TILE_SIZE;
716 
717 				xIntersection = (fITanTable[castArc] * (horizontalGrid - fPlayerY)) + fPlayerX;
718 			}
719 
720 			// Ray is facing up
721 			else {
722 				horizontalGrid = (fPlayerY/TILE_SIZE) * TILE_SIZE;
723 				distToNextHorizontalGrid = -TILE_SIZE;
724 
725 				xIntersection = (fITanTable[castArc] * (horizontalGrid - fPlayerY)) + fPlayerX;
726 
727 				--horizontalGrid;
728 			}
729 
730 
731 			// Looking for horizontal wall
732 			if ((castArc == ANGLE0) || (castArc == ANGLE180)) {
733 				distToHorizontalGridBeingHit = Float.MAX_VALUE;
734 
735 			} else {
736 
737 				distToNextXIntersection = fXStepTable[castArc];
738 
739 				while (true) {
740 
741 					xGridIndex = (int)(xIntersection/TILE_SIZE);
742 					// in the picture, yGridIndex will be 1
743 					yGridIndex = (horizontalGrid/TILE_SIZE);
744 
745 					if ((xGridIndex >= MAP_WIDTH) ||
746 						(yGridIndex >= MAP_HEIGHT) ||
747 						(xGridIndex < 0) ||
748 						(yGridIndex < 0)) {
749 						distToHorizontalGridBeingHit = Float.MAX_VALUE;
750 						break;
751 
752 					} else if ((fMap[yGridIndex*MAP_WIDTH+xGridIndex]) != 0) {
753 						distToHorizontalGridBeingHit  = (xIntersection-fPlayerX)*fICosTable[castArc];
754 						break;
755 
756 					} else {
757 						xIntersection += distToNextXIntersection;
758 						horizontalGrid += distToNextHorizontalGrid;
759 					}
760 
761 				}
762 			}
763 
764 
765 
766 			/* Vertical Collision */
767 
768 			// Ray facing right
769 			if (castArc < ANGLE90 || castArc > ANGLE270) {
770 
771 				verticalGrid = TILE_SIZE + (fPlayerX/TILE_SIZE) * TILE_SIZE;
772 				distToNextVerticalGrid = TILE_SIZE;
773 
774 				yIntersection = (fTanTable[castArc] * (verticalGrid - fPlayerX)) + fPlayerY;
775 				
776 			}
777 
778 			// Ray facing left
779 			else {
780 
781 				verticalGrid = (fPlayerX/TILE_SIZE) * TILE_SIZE;
782 				distToNextVerticalGrid = -TILE_SIZE;
783 
784 				yIntersection = (fTanTable[castArc] * (verticalGrid - fPlayerX)) + fPlayerY;
785 
786 				verticalGrid--;
787 
788 			}
789 
790 			// Looking for vertical wall
791 			if ((castArc == ANGLE90) || (castArc == ANGLE270)) {
792 
793 				distToVerticalGridBeingHit = Float.MAX_VALUE;
794 
795 			} else {
796 
797 				distToNextYIntersection = fYStepTable[castArc];
798 
799 				while (true) {
800 
801 					// compute current map position to inspect
802 					xGridIndex = (verticalGrid/TILE_SIZE);
803 					yGridIndex = (int)(yIntersection/TILE_SIZE);
804 
805 					if ((xGridIndex >= MAP_WIDTH) ||
806 						(yGridIndex >= MAP_HEIGHT) ||
807 						(xGridIndex < 0) ||
808 						(yGridIndex < 0)) {
809 						distToVerticalGridBeingHit = Float.MAX_VALUE;
810 						break;
811 
812 					} else if ((fMap[yGridIndex*MAP_WIDTH+xGridIndex]) != 0) {
813 						distToVerticalGridBeingHit = (yIntersection-fPlayerY) * fISinTable[castArc];
814 						break;
815 
816 					} else {
817 						yIntersection += distToNextYIntersection;
818 						verticalGrid += distToNextVerticalGrid;
819 					}
820 
821 				}
822 			}
823 
824 
825 
826 			/* Drawing the wall slice */
827 
828 
829 			// Determining which ray strikes a closer wall.
830 
831 			if (distToHorizontalGridBeingHit < distToVerticalGridBeingHit) {
832 				drawRayOnOverheadMap(xIntersection, horizontalGrid);
833 				dist = distToHorizontalGridBeingHit;
834 				material = fMap[(int)((int)(xIntersection/TILE_SIZE)
835 									  + MAP_WIDTH * (int)(horizontalGrid/TILE_SIZE))];
836 				slice = (int)(xIntersection % TILE_SIZE);
837 				wallColor = 0;
838 			} else {
839 				drawRayOnOverheadMap(verticalGrid, yIntersection);
840 				dist = distToVerticalGridBeingHit;
841 				material = fMap[(int)((int)(verticalGrid/TILE_SIZE)
842 									  + MAP_WIDTH * (int)(yIntersection/TILE_SIZE))];
843 				slice = (int)(yIntersection % TILE_SIZE);
844 				wallColor = 1;
845 			}
846 
847 			// Fishbown effect compensation
848 			dist /= fFishTable[castColumn];
849 
850 			int projectedWallHeight = (int)(TILE_SIZE*(float)fPlayerDistanceToTheProjectionPlane/dist);
851 			int topOfWall = fProjectionPlaneYCenter - (int)(projectedWallHeight*0.5F);
852 			int bottomOfWall = fProjectionPlaneYCenter + (int)(projectedWallHeight*0.5F);
853 			
854 			fOffscreenGraphics.drawImage(walls[material][wallColor],
855 										 castColumn, topOfWall,
856 										 castColumn+resolution, bottomOfWall,
857 										 slice, 0,
858 										 slice+1, 64,
859 										 this);
860 			// 			
861 			// Next ray
862 			castArc += resolution;
863 			if (castArc >= ANGLE360)
864 				castArc -= ANGLE360;
865 
866 		}
867 
868 		drawHUD();
869 
870 		paint(getGraphics());
871 
872 	}
873 
874 	
875 }


syntax highlighted by Code2HTML, v. 0.9.1