1 /*
2  * Shotgun Debugger
3  * Copyright 2005 Game Creation Society
4  *
5  * Programmed by Matt Sarnoff
6  * http://www.contrib.andrew.cmu.edu/~msarnoff
7  * http://www.gamecreation.org
8  *
9  * sdb.h - main header file
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25 
26 #ifndef _SDB_H_
27 #define _SDB_H_
28 
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <stdarg.h>
32 #include <math.h>
33 #include <string.h>
34 #include <sys/stat.h>
35 #include <vector>
36 #include <fstream>
37 #include <iostream>
38 
39 #ifndef __APPLE__
40 #include <SDL/SDL.h>
41 #include <SDL/SDL_image.h>
42 #include <SDL/SDL_mixer.h>
43 #include <GL/gl.h>
44 #include <GL/glu.h>
45 #else
46 #include </sw/include/SDL/SDL.h>
47 #include </sw/include/SDL/SDL_image.h>
48 #include </sw/include/SDL/SDL_mixer.h>
49 #include </System/Library/Frameworks/OpenGL.framework/Headers/gl.h>
50 #include </System/Library/Frameworks/OpenGL.framework/Headers/glu.h>
51 #endif
52 
53 // Includes for timing functions
54 #ifdef _WIN32
55 #include <windows.h>
56 #else
57 #include <sys/time.h>
58 #endif
59 
60 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
61 #define MD2_SUFFIX ".md2b"
62 #else
63 #define MD2_SUFFIX ".md2"
64 #endif
65 
66 using namespace std;
67 
68 // compensate for Microsoft's stupidity
69 #ifdef _WIN32
70 #define CALLBACK __stdcall
71 #else
72 #define CALLBACK
73 #endif
74 
75 #define GAME_TITLE   "Shotgun Debugger"
76 #define GAME_VERSION "1.0.2"
77 #define GAME_AUTHOR  "Matt Sarnoff"
78 #define GAME_DATE    "June 10, 2005"
79 
80 #define DATA_DIRECTORY "/.sdb/"
81 #define CONFIG_FILE "preferences.txt"
82 #define PLAYER_DATA_FILE "player.dat"
83 
84 #define NEXT_TOK  nextToken(line, start, end)
85 #define S2F(x)    strtof(x.c_str(), NULL)
86 #define S2I(x)    strtol(x.c_str(), NULL, 10)
87 
88 #define X  0
89 #define Y  1
90 #define Z  2
91 
92 #define USE_ALPHA -3.0
93 
94 #define PI        3.14159265359
95 #define PIOVER180 0.01745329252
96 #define I80OVERPI 57.2957795131
97 #define PIOVER2   1.57079632679
98 #define SQRT2     1.41421356237
99 #define torad(x)  x*PIOVER180
100 #define todeg(x)  x*I80OVERPI
101 #define sign(x)   ((x != 0) ? ((x < 0) ? -1.0 : 1.0) : 0.0)
102 #define MAX(x,y)  ((x > y) ? x : y)
103 #define MIN(x,y)  ((x < y) ? x : y)
104 
105 #define ACCEL_GRAVITY 32.1740485564 // feet per second squared
106 
107 #define SCREEN_QUAKE_DECAY      10.0
108 #define SCREEN_BLUR_DECAY       1.0
109 #define MESSAGE_DELAY_TIME      2.0
110 
111 #define PLAYER_OBJECT currLevelObjs[0]
112 
113 #define NUM_PARTICLES 2000
114 #define NUM_BULLETS 2000
115 #define NUM_LASERS 50
116 #define NUM_FORCES 500
117 #define NUM_SHOCKWAVES 200
118 #define NUM_TRIGGERS 64
119 #define NUM_BLUR_TEXTURES 8
120 
121 #define BLUR_TEXTURE_WIDTH  128
122 #define BLUR_TEXTURE_HEIGHT 128
123 #define BLUR_DELAY          0.1
124 
125 #define LEVEL_PREFIX       "/usr/local/share/sdb/levels/level"
126 #define LEVEL_INTRO_PREFIX "/usr/local/share/sdb/levels/leveltext"
127 #define NUM_LEVELS 8
128 
129 #define LEVEL_QUIT 0
130 #define LEVEL_LOSE 1
131 #define LEVEL_WIN  2
132 
133 #define LAUNCH_MULTI_PARTICLES(num,tp,x,y,ht,ang,al,sp) for (int pt = 0; pt < num; pt++) \
134   launchParticle(tp, x, y, ht, ang, al, sp)
135 
136 #define LAUNCH_MULTI_PARTICLES_C(num,tp,x,y,ht,ang,al,sp,cr,cg,cb) for (int pt = 0; pt < num; pt++) \
137   launchParticle(tp, x, y, ht, ang, al, sp, cr, cg, cb)
138 
139 #define HAS_KEY(x,y)    (x & 1 << y-1)
140 #define HAS_WEAPON(x,y) (x & 1 << y)
141 
142 #define DEFAULT_SURFACE_FRICTION  0.3
143 #define DEFAULT_SURFACE_HEALTH    0
144 #define DEFAULT_ARCH_HEIGHT       6.5
145 #define COLLIDE_OBJECT  1
146 #define COLLIDE_BULLET  2
147 #define RICOCHET_BULLET 4
148 
149 #define OBJECT_CD_THRESHOLD   1600
150 #define OBJECT_DRAW_THRESHOLD 3600
151 
152 #define MESSAGE_LENGTH 128
153 
154 #define SCREENSHOT_CHECK if (keystate[SDLK_F5]) { \
155   if (!screenshotKeyPressed) \
156   { takeScreenshot(); screenshotKeyPressed = true; } \
157 } else screenshotKeyPressed = false;
158 
159 // Cheats
160 #define CHEAT_INVUL   "invul"
161 #define CHEAT_WEAPONS "weapons"
162 #define CHEAT_AMMO    "ammo"
163 #define CHEAT_KEYS    "keys"
164 #define CHEAT_NOAI    "noai"
165 #define CHEAT_NOMASKS "nomasks"
166 #define CHEAT_ZOOM    "zoom"
167 #define CHEAT_SKIP    "levelskip"
168 #define CHEAT_ALL     "all"
169 
170 #define NO_KEY 0
171 #define IS_MOUSE_AXIS(x)   (x <= -100)
172 #define IS_MOUSE_BUTTON(x) (x <= -1 && x >= -5)
173 #define MOUSE_X_POS      -101
174 #define MOUSE_X_NEG      -100
175 #define MOUSE_Y_POS      -201
176 #define MOUSE_Y_NEG      -200
177 #define MOUSE_BUTTON_1   -1
178 #define MOUSE_BUTTON_2   -2
179 #define MOUSE_BUTTON_3   -3
180 
181 typedef unsigned char byte;
182 
183 enum TEXTURE_NAMES {
184 // Fonts
185 TEX_FONT,
186 
187 // Effects
188 TEX_SHADOW, TEX_LIGHT, TEX_SCANLINES, TEX_MF_RIFLE, TEX_MF_SHOTGUN,
189 TEX_EXPLOSION1, TEX_EXPLOSION2, TEX_EXPLOSION3, TEX_EXPLOSION4,
190 TEX_SMOKE, TEX_BEAM1, TEX_BEAM2, TEX_LASER_GLOW, TEX_ESG_CHARGE,
191 TEX_BORDER, TEX_TERMINAL_BG, TEX_BIT,
192 
193 // Box
194 TEX_BOX_NORMAL, TEX_BARREL_NORMAL, TEX_STEELBOX_NORMAL,
195 
196 // Particles
197 TEX_PARTICLE, TEX_PARTICLE_BLOOD, TEX_PARTICLE_SLIME, TEX_PARTICLE_SPARK, TEX_PARTICLE_ENERGY,
198 TEX_PARTICLE_WOOD, TEX_PARTICLE_METAL, TEX_PARTICLE_GLOW, TEX_HEPA_SPARK, TEX_LASER_SPARK1, TEX_LASER_SPARK2,
199 TEX_ESG_SHOCKWAVE,
200 TEX_EXPLOSIONPART, TEX_RIFLE_SHELL, TEX_SHOTGUN_SHELL,
201 
202 // Powerups
203 TEX_POWERUP_HEALTH, TEX_POWERUP_ENERGY_CLIP, TEX_POWERUP_SHOTGUN_AMMO, TEX_POWERUP_HEPA_CLIP,
204 TEX_POWERUP_LASER_CELL, TEX_POWERUP_ESG_BATTERY,
205 TEX_POWERUP_KEY1, TEX_POWERUP_KEY2, TEX_POWERUP_KEY3,
206 TEX_WEAPON_RIFLE, TEX_WEAPON_SHOTGUN, TEX_WEAPON_HEPA, TEX_WEAPON_LASER, TEX_WEAPON_ESG,
207 
208 // Bullets
209 TEX_BLT_RIFLE, TEX_BLT_SHOTGUN, TEX_BLT_GRENADE, TEX_BLT_SHRAPNEL, TEX_BLT_BLASTER,
210 
211 // Weapons
212 TEX_WPN_RIFLE, TEX_WPN_SHOTGUN, TEX_WPN_HEPA, TEX_WPN_GRENADE, TEX_WPN_LASER, TEX_WPN_ESG,
213 
214 // Others
215 TEX_TITLE_BG, TEX_BG2, TEX_HEX1, TEX_HEX2,
216 
217 
218 // Model textures
219 MTEX_PLAYER,
220 MTEX_PLAYER2,
221 MTEX_BARREL,
222 MTEX_TURRET,
223 MTEX_MIB,
224 MTEX_UNARMED_GUARD,
225 MTEX_ARMED_DRONE,
226 MTEX_HUNTER,
227 MTEX_GLADIATOR,
228 MTEX_FADE,
229 NUM_TEXTURES};
230 
231 enum MODEL_NAMES {
232 MDL_PLAYER_LEGS,
233 MDL_PLAYER_TORSO,
234 MDL_PLAYER_TORSO2,
235 MDL_BOX,
236 MDL_BARREL,
237 MDL_STEELBOX,
238 MDL_TURRET,
239 MDL_MIB,
240 MDL_UNARMED_GUARD,
241 MDL_ARMED_DRONE,
242 MDL_HUNTER,
243 MDL_GLADIATOR,
244 MDL_ZERO,
245 MDL_ONE,
246 NUM_MODELS};
247 
248 
249 enum SOUND_NAMES {
250 // Weapons
251 SND_WPN_RIFLE, SND_WPN_SHOTGUN, SND_WPN_HEPA, SND_WPN_LASER, SND_WPN_LASER2, SND_WPN_ESG, SND_GRENADE_BOUNCE,
252 
253 // Environment
254 SND_DOOR_OPEN, SND_DOOR_CLOSE, SND_DOOR_UNLOCK,
255 SND_EXPLOSION, SND_HEPA_EXPLOSION, SND_GRENADE_EXPLOSION, SND_BULLET_HIT_HARD, SND_BULLET_HIT_SOFT,
256 SND_PICKUP_HEALTH, SND_PICKUP_ITEM,
257 
258 // Player
259 SND_JUMP, SND_LAND, SND_RELOAD, SND_CHANGE_WEAPON,
260 SND_EXPLODE, SND_FALL, SND_HEAL, SND_HURT1, SND_HURT2, SND_HURTSURFACE, SND_KILLED,
261 
262 // Enemies
263 SND_ROBOT_SEES, SND_ROBOT_DEATH, SND_ROBOT_PARALYZE, SND_ROBOT_ALERT,
264 
265 SND_TERM_MOVE, SND_TERM_SELECT, SND_TERM_CLEAR, SND_LAUNCH, SND_LAUNCH2, SND_BUTTON, SND_ALARM,
266 SND_LASER_CHARGE, SND_LASER_CHARGE_LOOP,
267 NUM_SOUNDS};
268 
269 
270 enum SONG_NAMES {
271 MUS_TITLE, MUS_DD2, MUS_END,
272 NUM_SONGS};
273 
274 enum TRIGGER_TYPES { TRIG_NORMAL=0, TRIG_EVERY=1, TRIG_ONCE=2, TRIG_ADD=4, TRIG_SOUND1=8, TRIG_SOUND2=16, TRIG_WHENSHOT=32, MAX_TRIGTYPE=52 };
275 
276 enum MA_TYPES { MA_IDLE, MA_STAND, MA_WALK, MA_RUN, MA_SHORT, MA_LONG, MA_FLINCH, MA_KNOCK, MA_DIE, MA_DEAD, MA_DIEBACK, MA_DEADBACK, MA_SPECIAL1, MA_SPECIAL2, MA_SPECIAL3, NUM_MA_TYPES };
277 
278 //enum MA_TYPES { MA_STAND, MA_RUN, MA_ATTACK, MA_PAIN1, MA_PAIN2, MA_DIE1, MA_DIE2, MA_DIE3, MA_SPECIAL1, MA_SPECIAL2, MA_SPECIAL3, NUM_MA_TYPES };
279 
280 enum MA_PLAYER_LEG_TYPES { MA_PL_STAND, MA_PL_FWD, MA_PL_BACK, MA_PL_RIGHT, MA_PL_LEFT, MA_PL_JUMP, MA_PL_DIESOFT, MA_PL_DEADSOFT, MA_PL_DIEHARD, MA_PL_DEADHARD, MA_PL_FWDRIGHT, MA_PL_FWDLEFT, NUM_MA_PLAYER_LEG_TYPES };
281 
282 enum MA_PLAYER_TORSO_TYPES { MA_PT_STAND, MA_PT_RUN, MA_PT_PALMSHOOT, MA_PT_GRENADE, MA_PT_PISTOL, MA_PT_PISTOLRUN, MA_PT_PISTOLSHOOT, MA_PT_PISTOLGRENADE, MA_PT_PISTOLRELOAD, MA_PT_RIFLE, MA_PT_RIFLERUN, MA_PT_RIFLESHOOT, MA_PT_RIFLEGRENADE, MA_PT_RIFLERELOAD, MA_PT_HEPA, MA_PT_HEPARUN, MA_PT_HEPASHOOT, MA_PT_HEPARELOAD, MA_PT_DIESOFT, MA_PT_DEADSOFT, MA_PT_DIEHARD, MA_PT_DEADHARD, NUM_MA_PLAYER_TORSO_TYPES };
283 
284 float frand();
285 float lerp(float a0, float a1, float t);
286 
287 class Configuration
288 {
289   public:
Configuration()290     Configuration() { defaults(); }
defaults()291     void defaults() { set(1024, 768, 32, true, true, true, true, true, true, 0, 20, true, false, 0, "", false, false, false, false, false, false, false, false, false, false, false,  false); cheat_all = false; defaultKeys(); }
defaultKeys()292     void defaultKeys() { setKeymapping(SDLK_LEFT, SDLK_RIGHT, SDLK_w, SDLK_s, SDLK_a, SDLK_d, SDLK_SPACE, SDLK_LCTRL, SDLK_q, SDLK_r, SDLK_TAB, SDLK_v, SDLK_z); }
293     void loadFromFile(char *filename);
294     void writeToFile(char *filename);
set(int x,int y,int d,bool f,bool a,bool bl,bool snd,bool mus,bool fx,int mt,int ms,bool mg,bool fp,int fc,string dl,bool n,bool p,bool i,bool c,bool ci,bool cw,bool ca,bool ck,bool cna,bool cnm,bool cls,bool cz)295     void set(int x, int y, int d, bool f, bool a, bool bl, bool snd, bool mus, bool fx, int mt, int ms, bool mg, bool fp, int fc, string dl, bool n, bool p, bool i, bool c, bool ci, bool cw, bool ca, bool ck, bool cna, bool cnm, bool cls, bool cz)
296     { xres = x; yres = y; depth = d; fullscreen = f; antialias = a; blur = bl;
297     use_sound = snd; music = mus; sfx = fx; mthresh = mt; msense = ms; mgrab = mg; fps = fp; framecap = fc; defaultLevel = dl; normals = n; paths = p; info = i; culling = c;
298     cheat_invul = ci; cheat_weapons = cw; cheat_ammo = ca; cheat_keys = ck; cheat_noai = cna; cheat_nomasks = cnm; cheat_skip = cls; cheat_zoom = cz; }
setKeymapping(SDLKey nkleft,SDLKey nkright,SDLKey nkfwd,SDLKey nkback,SDLKey nkstrl,SDLKey nkstrr,SDLKey nkjump,SDLKey nkfire,SDLKey nkgren,SDLKey nkrel,SDLKey nksww,SDLKey nkswv,SDLKey nkzoom)299     void setKeymapping(SDLKey nkleft, SDLKey nkright, SDLKey nkfwd, SDLKey nkback, SDLKey nkstrl,
300                        SDLKey nkstrr, SDLKey nkjump, SDLKey nkfire, SDLKey nkgren, SDLKey nkrel,
301                        SDLKey nksww, SDLKey nkswv, SDLKey nkzoom)
302   { keys[0] = nkleft; keys[1] = nkright; keys[2] = nkfwd; keys[3] = nkback; keys[4] = nkstrl; keys[5] = nkstrr;
303   keys[6] = nkjump; keys[7] = nkfire; keys[8] = nkgren; keys[9] = nkrel; keys[10] = nksww; keys[11] = nkswv; keys[12] = nkzoom; }
setDefaultLevel(char * level)304     void setDefaultLevel(char *level) { defaultLevel = level; }
cheating()305     bool cheating() { return cheat_invul||cheat_weapons||cheat_ammo||cheat_keys||cheat_skip||cheat_zoom; }
306     int xres;
307     int yres;
308     int depth;
309     bool fullscreen;
310     bool antialias;
311     bool blur;
312     bool use_sound;
313     bool music;
314     bool sfx;
315     int mthresh;
316     int msense;
317     bool mgrab;
318     bool fps;
319     int framecap;
320     string defaultLevel;
321     bool normals;
322     bool paths;
323     bool info;
324     bool culling;
325 
326     SDLKey keys[13];
327 
328     bool cheat_all;
329     bool cheat_invul;
330     bool cheat_weapons;
331     bool cheat_ammo;
332     bool cheat_keys;
333     bool cheat_noai;
334     bool cheat_nomasks;
335     bool cheat_skip;
336     bool cheat_zoom;
337 };
338 
339 class Trigger
340 {
341   public:
Trigger()342     Trigger() { hit = false; hitsRequired = hits = 0; }
343     bool hit;
344     int hitsRequired;
345     int hits;
346 };
347 
348 class RGBAColor
349 {
350   public:
RGBAColor(float nr,float ng,float nb,float na)351     RGBAColor(float nr, float ng, float nb, float na) :
352       r(nr), g(ng), b(nb), a(na) {}
RGBAColor()353     RGBAColor() { zero(); }
set(float nr,float ng,float nb,float na)354     void set(float nr, float ng, float nb, float na) { set(nr, ng, nb); a = na; }
set(float nr,float ng,float nb)355     void set(float nr, float ng, float nb) { r = nr; g = ng; b = nb; }
356     void blend(RGBAColor c, float amountOfNew);
print()357     void print() { printf("[R%0.3f G%0.3f B%0.3f A%0.3f]\n", r, g, b, a); }
zero()358     void zero() { set(0, 0, 0, 0); }
white()359     void white() { set(1, 1, 1, 1); }
apply()360     void apply() { glColor4f(r, g, b, a); }
361 
362     float r, g, b, a;
363 };
364 
365 // A 2D vector, backed by an array for convenience. Z coordinate is a dummy, because some OpenGL functions
366 // require ordered triples.
367 class Vector2D
368 {
369   public:
Vector2D()370     Vector2D() { set(0.0, 0.0); }
371     //Vector2D(Vector2D v) { set(v.c[X], v.c[Y]); }
Vector2D(float nx,float ny)372     Vector2D(float nx, float ny) { set(nx, ny); }
set(float nx,float ny)373     void set(float nx, float ny) { c[X] = nx; c[Y] = ny; c[Z] = 0; }
apply()374     void apply() { glVertex3fv(c); }
print()375     void print() { printf("(%f, %f)\n", c[X], c[Y]); }
376     Vector2D operator = (Vector2D v) { c[X] = v.c[X]; c[Y] = v.c[Y]; }
377     void operator += (Vector2D v) { c[X] += v.c[X]; c[Y] += v.c[Y]; }
378     void operator -= (Vector2D v) { c[X] -= v.c[X]; c[Y] -= v.c[Y]; }
379     void operator += (float s) { c[X] += s; c[Y] += s; }
380     void operator -= (float s) { c[X] -= s; c[Y] -= s; }
381     bool operator == (Vector2D v) { return c[X] == v.c[X] && c[Y] == v.c[Y]; }
382 
383     Vector2D operator + (Vector2D v) { return Vector2D(c[X]+v.c[X], c[Y]+v.c[Y]); }
384     Vector2D operator + (float s)    { return Vector2D(c[X]+s, c[Y]+s); }
385     Vector2D operator - (Vector2D v) { return Vector2D(c[X]-v.c[X], c[Y]-v.c[Y]); }
386 
387     // dot product
388     float operator * (Vector2D v) { return c[X]*v.c[X] + c[Y]*v.c[Y]; }
389 
390     void operator *= (float s) { c[X] *= s; c[Y] *= s; }
391     void operator /= (float s) { c[X] /= s; c[Y] /= s; }
392     Vector2D operator * (float s) { return Vector2D(c[X]*s, c[Y]*s); }
393     Vector2D operator / (float s) { return Vector2D(c[X]/s, c[Y]/s); }
394 
395     // interpolate between two vectors
interpolate(Vector2D v,float t)396     Vector2D interpolate(Vector2D v, float t) { return Vector2D(lerp(c[X], v.c[X], t), lerp(c[Y], v.c[Y], t)); }
397 
mag()398     float mag() { return sqrt((c[X]*c[X]) + (c[Y]*c[Y])); }
normalize()399     void normalize() { if (mag() != 0) { *this /= mag(); } else set(0,0); }
neg()400     void neg() { c[X] = -c[X]; c[Y] = -c[Y]; }
401 
402     float c[3];
403 };
404 
405 // A 2D vector backed by an array of doubles.
406 // we need this for floor polygons because OpenGL absolutely refuses
407 // to properly tessellate a concave polygon if its vertices are not doubles.
408 // (We want to keep everything else as floats, though.)
409 class Vector2Dd
410 {
411   public:
Vector2Dd()412     Vector2Dd() { set(0.0, 0.0); }
Vector2Dd(GLdouble nx,GLdouble ny)413     Vector2Dd(GLdouble nx, GLdouble ny) { set(nx, ny); }
set(GLdouble nx,GLdouble ny)414     void set(GLdouble nx, GLdouble ny) { c[X] = nx; c[Y] = ny; c[Z] = 0; }
apply()415     void apply() { glVertex3dv(c); }
v2D()416     Vector2D v2D() { return Vector2D(c[X], c[Y]); }
417     GLdouble c[3];
418 };
419 
420 class Line
421 {
422   public:
Line()423     Line() {}
Line(Vector2D n1,Vector2D n2)424     Line(Vector2D n1, Vector2D n2) { p1 = n1; p2 = n2;  normal = findNormal(); }
Line(float p1x,float p1y,float p2x,float p2y)425     Line(float p1x, float p1y, float p2x, float p2y) { setCoords(p1x, p1y, p2x, p2y); }
setCoords(float p1x,float p1y,float p2x,float p2y)426     void setCoords(float p1x, float p1y, float p2x, float p2y) { p1.set(p1x, p1y); p2.set(p2x, p2y); }
set(Vector2D n1,Vector2D n2)427     void set(Vector2D n1, Vector2D n2) { p1 = n1; p2 = n2;  normal = findNormal(); }
midpoint()428     Vector2D midpoint() { return Vector2D((p1.c[X]+p2.c[X])/2, (p1.c[Y]+p2.c[Y])/2); }
findNormal()429     Vector2D findNormal() { Vector2D d=p2-p1; return Vector2D(d.c[Y]/d.mag(), -d.c[X]/d.mag()); }
430     bool intersection(Vector2D a, Vector2D b, Vector2D *p);
431     Vector2D p1, p2, normal;
432 };
433 
434 class BoundingBox
435 {
436   public:
BoundingBox()437     BoundingBox() { reset(); }
BoundingBox(vector<Vector2D> points)438     BoundingBox(vector<Vector2D> points) { calculate(points); }
reset()439     void reset() { pointsAdded = false; }
440     void addPoint(Vector2D point);
set(Vector2D nmin,Vector2D nmax)441     void set(Vector2D nmin, Vector2D nmax) { min = nmin; max = nmax; pointsAdded = true; center = (min+max)*0.5;}
442     void calculate(vector<Vector2D> points);
443     void rotate(float angle);
444     bool pointInBB(Vector2D point);
445     bool intersectBB(BoundingBox bb);
446     Vector2D min, max, center;
447   private:
448     bool pointsAdded;
449 };
450 
451 class Timer
452 {
453   public:
Timer()454     Timer() { dt = 0.0; start = 0.0; fpsCache = 0.0; fpsCount = 0; }
reset()455     void reset() { start = timerFunc(); }
456     void update();
dT()457     double dT() { return dt; }
FPS()458     int FPS() { return fps; }
459     double dt;
460     int fps;
461   private:
462     double timerFunc();
463     double start;
464     double fpsCache;
465     int fpsCount;
466 };
467 
468 class BitmapFont
469 {
470   public:
BitmapFont()471     BitmapFont() {}
BitmapFont(int index)472     BitmapFont(int index) { create(index); }
473     void create(int index);
474     void drawChar(char c);
475     void print(float x, float y, float scaleX, float scaleY, float spacing, char *text);
476     void printf(float x, float y, float scaleX, float scaleY, char *fmt, ...);
477     void LEDprintf(float x, float y, float xscale, float yscale, char *fmt, ...);
478     void vprintf(float x, float y, float scaleX, float scaleY, char *fmt, va_list ap);
479   private:
480     SDL_Surface *charMap;
481     int texIndex;
482     float lastY;
483     float lastYScale;
484 };
485 
486 ////
487 
488 // game.cpp prototypes
489 float distSquared(Vector2D a, Vector2D b);
490 float dist(Vector2D a, Vector2D b);
491 bool hasLineOfSight(Vector2D start, Vector2D end, bool includeDoors);
492 float rayCircleIntersection(Vector2D rayOrigin, Vector2D rayDisplacement, Vector2D circleCtr, float circleRad);
493 bool circleSegmentIntersection(Vector2D c, float r, Vector2D p1, Vector2D p2, Vector2D *intersect);
494 string nextToken(string line, int &start, int &end);
495 string getLevelFileName(int levelNum);
496 string getLevelIntroFileName(int levelNum);
497 void gameWelcomeMessage();
498 void gameInitSDL();
499 void gameInitOpenGL();
500 void gameSetVideoMode(int width, int height, int depth, int fullscreen);
501 void gameSetAntialiasing(bool set);
502 void gameSetPerspectiveMode();
503 void gameSetOrthoMode(float r);
504 void gameInitTessellator();
505 void gameLoadSprites();
506 void gameLoadModels();
507 void gameLoadSounds();
508 void gameLoadMusic();
509 void gameDestroySprites();
510 void gameDestroySounds();
511 void gameDestroyMusic();
512 void gameShutdown();
513 
514 void loadAI();
515 void destroyAI();
516 
517 void launchParticle(int typ, float x, float y, float height, float head, float alph, int sprite);
518 void launchParticle(int typ, float x, float y, float height, float head, float alph, int sprite, float r, float g, float b);
519 void killParticle(int index);
520 void launchBullet(int own, int typ, float x, float y, float height, float head);
521 void killBullet(int index);
522 void launchLaser(int typ, float x, float y, float height, float head);
523 void killLaser(int index);
524 void addForce(int obj, float dur, float a, float b, bool mode);
525 void addInstantForce(int obj, float a, float b, bool mode);
526 void killForce(int index);
527 void addShockwave(float x, float y, float ir, float irs, float otr, float ors, float dur, float frc, float hlth, bool ag=true);
528 void killShockwave(int index);
529 void setScreenQuake(float amt);
530 void setBlur(float amt, float r, float g, float b);
531 void addBlur(float amt, float r, float g, float b);
532 void setTrigger(int t);
533 void incrementTrigger(int t);
534 void setMessage(const char *fmt, ...);
535 
536 void playSound(int sound, int channel);
537 void playSoundLooped(int sound, int channel);
538 void stopSound(int channel);
539 void startMusic(int song);
540 void stopMusic();
541 void fadeOutMusic(int ms);
542 void fadeInMusic(int song, int ms);
543 
544 int playCurrentLevel(bool playInSequence);
545 void game(string levelToPlay, bool playInSequence);
546 void drawScene(BoundingBox viewRegion);
547 void drawObjectShadows(int cMinX, int cMinY, int cMaxX, int cMaxY);
548 bool lineSegmentIntersection(Vector2D a, Vector2D b, Vector2D c, Vector2D d, Vector2D *p);
549 
550 // misc. prototypes
551 void CALLBACK tcbBegin(GLenum prim);
552 void CALLBACK tcbEnd();
553 void CALLBACK tcbCombine (GLdouble c[3], void *d[4], GLfloat w[4], void **out);
554 void CALLBACK tcbError(GLenum errnum);
555 
556 #include "bitmapfont.h"
557 #include "levelobjects.h"
558 #include "md2.h"
559 #include "weapons.h"
560 #include "objects.h"
561 #include "enemies.h"
562 #include "level.h"
563 #include "camera.h"
564 #include "input.h"
565 #include "player.h"
566 #include "interface.h"
567 
568 extern SDL_Surface *texdata[NUM_TEXTURES];
569 extern GLuint textures[NUM_TEXTURES];
570 
571 extern unsigned int *blurdata[NUM_BLUR_TEXTURES];
572 extern GLuint blurTextures[NUM_BLUR_TEXTURES];
573 
574 extern Model models[NUM_MODELS];
575 extern Mix_Chunk *snddata[NUM_SOUNDS];
576 extern Mix_Music *musicdata[NUM_SONGS];
577 
578 extern Configuration config;
579 extern bool GFXMODE_ISACTIVE;
580 
581 extern float SCREEN_TOP;
582 extern float SCREEN_CENTER;
583 extern float SCREEN_ASPECT;
584 
585 extern BitmapFont font;
586 extern GLUtesselator *tess;
587 extern vector<GLdouble *> tessAllocatedVertices;
588 extern MD2Loader modelLoader;
589 extern Timer timer;
590 
591 extern SDL_Event event;
592 extern Uint8 *keystate;
593 extern SDLMod modstate;
594 extern int mouse_dX;
595 extern int mouse_dY;
596 extern Uint8 mouseButtons;
597 // Global variables which store the state of the current
598 // level and its objects. The player object is always index 0
599 // in the currLevelObjs array.
600 
601 extern char message[MESSAGE_LENGTH];
602 extern float messageTime;
603 
604 extern bool winLevel;
605 extern Level currLevel;
606 extern Player P;
607 extern vector<Object *> currLevelObjs;
608 extern vector<AI *> currLevelEnemies;
609 extern Particle particles[NUM_PARTICLES];
610 extern int liveParticles;
611 extern Bullet bullets[NUM_BULLETS];
612 extern int liveBullets;
613 extern Laser lasers[NUM_LASERS];
614 extern int liveLasers;
615 extern Force forces[NUM_FORCES];
616 extern int liveForces;
617 extern Shockwave shockwaves[NUM_SHOCKWAVES];
618 extern int liveShockwaves;
619 extern Trigger triggers[NUM_TRIGGERS];
620 
621 extern int screenshotCount;
622 extern bool screenshotKeyPressed;
623 #endif
624