1 /*
2 * This code is released under the GNU General Public License.  See COPYING for
3 * details.  Copyright 2003 John Spray: spray_john@users.sourceforge.net
4 */
5 
6 
7 #include "Arena.h"
8 #include "Vector.h"
9 
10 #include "Particle.h" //for debugging markers in collision
11 #include "Visual.h"
12 #include <string.h>
13 
Arena(Game * newgame)14 Arena::Arena(Game* newgame){
15 	halfwidth=300;
16 	wallheight=50;
17 	game=newgame;
18 	lastquad=NULL;
19 }
20 
~Arena()21 Arena::~Arena(){
22 }
23 
Blocked(Vector s,float radius)24 int Arena::Blocked(Vector s,float radius)
25 {
26 	LListItem<Obstacle>* item;
27 	item=obstaclelist.head;
28 	while(item){
29 		if(s.x>item->data.s.x-radius&&s.x<item->data.s.x+item->data.w.x+radius)
30 			if(s.z>item->data.s.z-radius&&s.z<item->data.s.z+item->data.w.z+radius)
31 			  if(s.y>item->data.s.y-radius&&s.y<item->data.s.y+item->data.w.y+radius)
32 				return 1;
33 		item=item->next;
34 	}
35 
36 	if(s.x>halfwidth-radius||s.x<-halfwidth+radius||s.z>halfwidth-radius||s.z<-halfwidth+radius)
37 		return 1;
38 
39 	return 0;
40 }
41 
Collision(Vector s,float r)42 int Arena::Collision(Vector s,float r)
43 {
44 
45 	//return 1 for 'out of bounds'
46 	//this is necessary if something gets wanged over the walls
47 	//OutOfBounds sets lastquad to a big virtualquad off in -y
48 	if(OutOfBounds(s))
49 		return 1;
50 
51 	Vector p1,p2;
52 	Vector temp;
53 
54 	LListItem<Quad> *item;
55 
56 	item=geomlist.head;
57 	while(item){
58 		p1=s-item->data.n*r;
59 		p2=s+item->data.n*r;
60 		if(item->data.PlaneIntersection2Way(p1,p2)){
61 			temp=item->data.PlaneIntersectionPoint(p1,p2);
62 			if(item->data.IsInside(temp)){
63 				lastquad=&item->data;
64 				return 1;
65 			}
66 		}
67 		item=item->next;
68 	}
69 	return 0;
70 }
71 
Collision(Vector p1,Vector p2)72 int Arena::Collision(Vector p1,Vector p2)
73 {
74 	Vector temp;
75 	LListItem<Quad> *item;
76 
77 	//return 1 for 'out of bounds'
78 	//this is necessary if something gets wanged over the walls
79 	//OutOfBounds sets lastquad to a big virtualquad off in -y
80 	if(OutOfBounds(p1) || OutOfBounds(p2))
81 		return 1;
82 
83 	item=geomlist.head;
84 	while(item){
85 		if(item->data.PlaneIntersection(p1,p2)){
86 			temp=item->data.PlaneIntersectionPoint(p1,p2);
87 			if(item->data.IsInside(temp)){
88 				lastquad=&item->data;
89 				return 1;
90 			}
91 		}
92 		item=item->next;
93 	}
94 	return 0;
95 }
96 
97 //surface collision (1 way ray p1->p2), returns closest collision point to p1
CollisionNearest(Vector p1,Vector p2)98 Vector Arena::CollisionNearest(Vector p1,Vector p2)
99 {
100 	Vector temp,temprel,retval,retvalrel;
101 	retval=999999.0f;//ie infinity
102   retvalrel=999999.9f;
103 	LListItem<Quad> *item;
104 
105 	item=geomlist.head;
106 	while(item){
107 		if(item->data.PlaneIntersection(p1,p2)){
108 			temp=item->data.PlaneIntersectionPoint(p1,p2);
109 			if(item->data.IsInside(temp)){
110         temprel=temp-p1;
111 				if(temprel.Mag2()<retvalrel.Mag2()){
112 					retval=temp;
113           retvalrel=temprel;
114 					lastquad=&item->data;
115 				}
116 			}
117 		}
118 		item=item->next;
119 	}
120 
121 	return retval;
122 
123 }
124 
125 //collide a moving (p1->p2) sphere of radius r
Collision(Vector p1,Vector p2,float r)126 int Arena::Collision(Vector p1,Vector p2,float r)
127 {
128 	//return 1 for 'out of bounds'
129 	//this is necessary if something gets wanged over the walls
130 	//OutOfBounds sets lastquad to a big virtualquad off in -y
131 	if(OutOfBounds(p1) || OutOfBounds(p2))
132 		return 1;
133 
134 	Vector v; //direction of motion
135 	Vector temp;
136 	Vector c1,c2; //centres of spheres : p[12] will become ends of ray
137 	Vector r1,r2; //edges of spheres, along a diameter parallel to the quad's normal
138 	LListItem<Quad> *item;
139 
140 	c1=p1;c2=p2;
141 
142 	v=p2-p1;
143 	v.Unitize();
144 	p1-=v*r;
145 	p2+=v*r;
146 
147 	item=geomlist.head;
148 	while(item){
149 		if(item->data.PlaneIntersection(p1,p2)){
150 			temp=item->data.PlaneIntersectionPoint(p1,p2);
151 			if(item->data.IsInside(temp)){
152 				lastquad=&item->data;
153 				return 1;
154 			}
155 		}
156 
157 
158 		r1=c1-item->data.n*r;
159 		r2=c1+item->data.n*r;
160 		if((item->data.n|v)<0 && item->data.PlaneIntersection2Way(r1,r2)){
161 			temp=item->data.PlaneIntersectionPoint(p1,p2);
162 			if(item->data.IsInside(temp)&&temp.InCube(r1,r2)){
163 				lastquad=&item->data;
164 				return 1;
165 			}
166 		}
167 
168 
169 		r1=c2-item->data.n*r;
170 		r2=c2+item->data.n*r;
171 		if((item->data.n|v)<0 && item->data.PlaneIntersection2Way(r1,r2)){
172 			temp=item->data.PlaneIntersectionPoint(p1,p2);
173 			if(item->data.IsInside(temp)&&temp.InCube(r1,r2)){
174 				lastquad=&item->data;
175 				return 1;
176 			}
177 		}
178 
179 		item=item->next;
180 	}
181 
182 	return 0;
183 }
184 
185 //is it really far away from the origin?
OutOfBounds(Vector s)186 int Arena::OutOfBounds(Vector s)
187 {
188 	//if(s.Mag2()>(halfwidth*4)*(halfwidth*4)){
189 	if(s.Mag2()>(halfwidth)*(halfwidth)*16.0f){
190 		virtualquad.n.Set3f(0.0f,1.0f,0.0f);
191 		virtualquad.v1.Set3f(-halfwidth*4,-halfwidth*4,-halfwidth*4);
192 		virtualquad.v2.Set3f(halfwidth*4,-halfwidth*4,-halfwidth*4);
193 		virtualquad.v3.Set3f(halfwidth*4,-halfwidth*4,halfwidth*4);
194 		virtualquad.v4.Set3f(-halfwidth*4,-halfwidth*4,halfwidth*4);
195 		lastquad=&virtualquad;
196 		return 1;
197 	}
198 
199 	return 0;
200 }
201 
202 
MakeObstacles()203 void Arena::MakeObstacles()
204 {
205 	Vector place;
206 	Obstacle newobst;
207 //	int placed=0;
208 	float x;
209 	float y;
210 
211 	place.y=0;
212 	newobst.w=50.0f;
213   newobst.w.y=50.0f;
214 
215   for(x=-halfwidth;x<halfwidth;x+=100.0f){
216   for(y=-halfwidth;y<halfwidth;y+=100.0f){
217 //		x=y=50.0f;
218 		place.x=x;
219 		place.z=y;
220 		place.x+=((float)rand()/RAND_MAX)*40.0f;
221 		place.z+=((float)rand()/RAND_MAX)*40.0f;
222 		newobst.s=place;
223 		obstaclelist.Add(&newobst);
224 	}
225 	}
226 }
227 
GenerateGeometry()228 void Arena::GenerateGeometry()
229 {
230 	geomlist.Flush();
231 	Quad newquad;
232 
233 	//floor:
234 	newquad.v1.x=-halfwidth;
235 	newquad.v1.y=0.0f;
236 	newquad.v1.z=-halfwidth;
237 	newquad.v2.x=-halfwidth;
238 	newquad.v2.y=0.0f;
239 	newquad.v2.z=halfwidth;
240 	newquad.v3.x=halfwidth;
241 	newquad.v3.y=0.0f;
242 	newquad.v3.z=halfwidth;
243 	newquad.v4.x=halfwidth;
244 	newquad.v4.y=0.0f;
245 	newquad.v4.z=-halfwidth;
246 	newquad.n.x=0.0f;
247 	newquad.n.y=1.0f;
248 	newquad.n.z=0.0f;
249 	geomlist.Add(&newquad);
250 
251 	//arena walls:
252 
253 	newquad.v1.Set3f(halfwidth,0.0f,halfwidth);
254 	newquad.v2.Set3f(halfwidth,wallheight,halfwidth);
255 	newquad.v3.Set3f(halfwidth,wallheight,-halfwidth);
256 	newquad.v4.Set3f(halfwidth,0.0f,-halfwidth);
257 	newquad.n.Set3f(-1.0f,0.0f,0.0f);
258 	geomlist.Add(&newquad);
259 
260 	newquad.v1.Set3f(-halfwidth,0.0f,halfwidth);
261 	newquad.v2.Set3f(-halfwidth,0.0f,-halfwidth);
262 	newquad.v3.Set3f(-halfwidth,wallheight,-halfwidth);
263 	newquad.v4.Set3f(-halfwidth,wallheight,halfwidth);
264 	newquad.n.Set3f(1.0f,0.0f,0.0f);
265 	geomlist.Add(&newquad);
266 
267 	newquad.v1.Set3f(halfwidth,0.0f,-halfwidth);
268 	newquad.v2.Set3f(halfwidth,wallheight,-halfwidth);
269 	newquad.v3.Set3f(-halfwidth,wallheight,-halfwidth);
270 	newquad.v4.Set3f(-halfwidth,0.0f,-halfwidth);
271 	newquad.n.Set3f(0.0f,0.0f,1.0f);
272 	geomlist.Add(&newquad);
273 
274 	newquad.v1.Set3f(halfwidth,0.0f,halfwidth);
275 	newquad.v2.Set3f(-halfwidth,0.0f,halfwidth);
276 	newquad.v3.Set3f(-halfwidth,wallheight,halfwidth);
277 	newquad.v4.Set3f(halfwidth,wallheight,halfwidth);
278 	newquad.n.Set3f(0.0f,0.0f,-1.0f);
279 	geomlist.Add(&newquad);
280 
281 	//buildings:
282 	LListItem<Obstacle>* item;
283 	Obstacle* obstacle;
284 	item=obstaclelist.head;
285 	while(item){
286 		obstacle=&item->data; //just to make the rest not have to do item->data
287   	newquad.v1.Set3f(obstacle->s.x,obstacle->s.y,obstacle->s.z);
288   	newquad.v2.Set3f(obstacle->s.x,obstacle->s.y+obstacle->w.y,obstacle->s.z);
289   	newquad.v3.Set3f(obstacle->s.x+obstacle->w.x,obstacle->s.y+obstacle->w.y,obstacle->s.z);
290   	newquad.v4.Set3f(obstacle->s.x+obstacle->w.x,obstacle->s.y,obstacle->s.z);
291 		newquad.n.Set3f(0.0f,0.0f,-1.0f);
292 		geomlist.Add(&newquad);
293 
294   	newquad.v1.Set3f(obstacle->s.x,obstacle->s.y,obstacle->s.z+obstacle->w.z);
295   	newquad.v2.Set3f(obstacle->s.x+obstacle->w.x,obstacle->s.y,obstacle->s.z+obstacle->w.z);
296   	newquad.v3.Set3f(obstacle->s.x+obstacle->w.x,obstacle->s.y+obstacle->w.y,obstacle->s.z+obstacle->w.z);
297   	newquad.v4.Set3f(obstacle->s.x,obstacle->s.y+obstacle->w.y,obstacle->s.z+obstacle->w.z);
298 		newquad.n.Set3f(0.0f,0.0f,1.0f);
299 		geomlist.Add(&newquad);
300 
301   	newquad.v1.Set3f(obstacle->s.x,obstacle->s.y,obstacle->s.z);
302   	newquad.v2.Set3f(obstacle->s.x,obstacle->s.y,obstacle->s.z+obstacle->w.z);
303   	newquad.v3.Set3f(obstacle->s.x,obstacle->s.y+obstacle->w.y,obstacle->s.z+obstacle->w.z);
304   	newquad.v4.Set3f(obstacle->s.x,obstacle->s.y+obstacle->w.y,obstacle->s.z);
305 		newquad.n.Set3f(-1.0f,0.0f,0.0f);
306 		geomlist.Add(&newquad);
307 
308   	newquad.v1.Set3f(obstacle->s.x+obstacle->w.x,obstacle->s.y,obstacle->s.z);
309   	newquad.v2.Set3f(obstacle->s.x+obstacle->w.x,obstacle->s.y+obstacle->w.y,obstacle->s.z);
310   	newquad.v3.Set3f(obstacle->s.x+obstacle->w.x,obstacle->s.y+obstacle->w.y,obstacle->s.z+obstacle->w.z);
311   	newquad.v4.Set3f(obstacle->s.x+obstacle->w.x,obstacle->s.y,obstacle->s.z+obstacle->w.z);
312 		newquad.n.Set3f(1.0f,0.0f,0.0f);
313 		geomlist.Add(&newquad);
314 
315 		item=item->next;
316 	}
317 }
318 
GetLastQuad()319 Quad* Arena::GetLastQuad()
320 {
321 	return lastquad;
322 }
323 
324