~ubuntu-branches/ubuntu/hardy/orbital-eunuchs-sniper/hardy

« back to all changes in this revision

Viewing changes to src/snipe2d.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-05-29 09:32:48 UTC
  • mfrom: (1.1.1 upstream) (2.1.2 gutsy)
  • Revision ID: james.westby@ubuntu.com-20070529093248-laj1bsm2dffohdf9
Tags: 1.30+svn20070601-1
Fix broken "upstream" rule to generate correctly versioned orig.tar.gz
to avoid native package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
///////////////////////////////////////////////
 
2
// 
 
3
//  Snipe2d ludum dare 48h compo entry
 
4
//
 
5
//  Jari Komppa aka Sol 
 
6
//  http://iki.fi/sol
 
7
// 
 
8
///////////////////////////////////////////////
 
9
// License
 
10
///////////////////////////////////////////////
 
11
// 
 
12
//     This software is provided 'as-is', without any express or implied
 
13
//     warranty.    In no event will the authors be held liable for any damages
 
14
//     arising from the use of this software.
 
15
// 
 
16
//     Permission is granted to anyone to use this software for any purpose,
 
17
//     including commercial applications, and to alter it and redistribute it
 
18
//     freely, subject to the following restrictions:
 
19
// 
 
20
//     1. The origin of this software must not be misrepresented; you must not
 
21
//        claim that you wrote the original software. If you use this software
 
22
//        in a product, an acknowledgment in the product documentation would be
 
23
//        appreciated but is not required.
 
24
//     2. Altered source versions must be plainly marked as such, and must not be
 
25
//        misrepresented as being the original software.
 
26
//     3. This notice may not be removed or altered from any source distribution.
 
27
// 
 
28
// (eg. same as ZLIB license)
 
29
//
 
30
///////////////////////////////////////////////
 
31
//
 
32
// Houses are taken from a satellite picture of glasgow.
 
33
//
 
34
// The sources are a mess, as I didn't even try to do anything
 
35
// really organized here.. and hey, it's a 48h compo =)
 
36
//
 
37
 
 
38
#include "snipe2d.h"
 
39
//#include <getopt.h>
 
40
#include "binds.h"
 
41
 
 
42
PREFS gPrefs;
 
43
 
 
44
typedef struct oes_joy_t {
 
45
  int style;    /* axis style: rel (game) or abs (mousepad) */ //not used yet
 
46
  float scale;  /* scaling factor. */
 
47
  int interval; /* handling interval, in milliseconds. */
 
48
 
 
49
  int time;  /* timestamp of last handling. */
 
50
  int axes;  /* number of axes */
 
51
  int buttons;  /* number of buttons. */
 
52
  int state;    /* joy shifter state. */
 
53
  float x;   /* X axis. */
 
54
  float y;   /* Y axis. */
 
55
  float z;   /* throttle? */
 
56
  SDL_Joystick* sdljoy;  /* SDL Joystick handle. */
 
57
#if 0
 
58
  /* bindings for 32 axes and 32 buttons. */
 
59
  oesbind_t axis[32];
 
60
  oesbind_t button[32];
 
61
#endif /* 0 */
 
62
} oes_joy_t;
 
63
 
 
64
oes_joy_t oesjoy = { 0, };
 
65
 
 
66
 
 
67
struct keymarkers_t {
 
68
  int mousex;
 
69
  int mousey;
 
70
  int mouse0;
 
71
  int axis1;
 
72
  int joy1;
 
73
} keymarkers;
 
74
 
 
75
 
 
76
ORBITALSNIPER Game;
 
77
 
 
78
 
 
79
//char *mediaPath;
 
80
 
 
81
//int gPlaySound = 0;
 
82
int screen_shot_number=1;
 
83
char *invocation;
 
84
 
 
85
#if 0
 
86
BUTTONS gButton;
 
87
#endif /* 0 */
 
88
 
 
89
static const char *crosshairs_xpm[] = {
 
90
  "    16    16        3            1",
 
91
  "X c #000000",
 
92
  ". c #ffffff",
 
93
  "  c None",
 
94
  "               ",
 
95
  "       .       ",
 
96
  "     .....     ",
 
97
  "    .  .  .    ",
 
98
  "   .   .   .   ",
 
99
  "  .         .  ",
 
100
  "  .         .  ",
 
101
  " ....  .  .... ",
 
102
  "  .         .  ",
 
103
  "  .         .  ",
 
104
  "   .   .   .   ",
 
105
  "    .  .  .    ",
 
106
  "     .....     ",
 
107
  "       .       ",
 
108
  "               ",
 
109
  "               ",
 
110
  "8,8"
 
111
};
 
112
 
 
113
#if 0
 
114
//SDL_AudioSpec *gAudioSpec = NULL;
 
115
Mix_Chunk *gAudioZoomSample = NULL;
 
116
Mix_Chunk *gAudioFireSample = NULL;
 
117
Mix_Chunk *gAudioZoomOut = NULL;
 
118
Mix_Chunk *gAudioZoomIn = NULL;
 
119
Mix_Chunk *gAudioFire = NULL;
 
120
//Mix_Music *gAudioBGM = NULL;
 
121
int gAudioZoomSampleLen = 0;
 
122
int gAudioZoomOutLen = 0;
 
123
int gAudioZoomInLen = 0;
 
124
int gAudioZoomOfs = 0;
 
125
int gAudioFireOfs = 0;
 
126
int gAudioFireSampleLen = 0;
 
127
int gAudioFireLen = 0;
 
128
#endif /* 0 */
 
129
 
 
130
 
 
131
const char *usage = \
 
132
"Usage: %s [OPTIONS]...\n\
 
133
Overhead shooting game; kill red marks, protect blue marks, avoid white marks.\n\
 
134
\n\
 
135
Orbital Eunuchs Sniper recognizes the following command parameters:\n\
 
136
  -a       | --audio             Start with sound\n\
 
137
  -n       | --noaudio           Start without sound\n\
 
138
  -f       | --fullscreen        Start in fullscreen mode\n\
 
139
  -w       | --window            Start in a window\n\
 
140
  -1       | --diff1             Difficulty 1 (Easy)\n\
 
141
  -2       | --diff2             Difficulty 2 (Medium)\n\
 
142
  -3       | --diff3             Difficulty 3 (Hard)\n\
 
143
  -h       | --help              Display this help message and exit\n\
 
144
\n\
 
145
Orbital Eunuchs Sniper is licensed under the same terms as the ZLIB license.\n\
 
146
\n";
 
147
/*  -d 1|2|3 | --difficulty 1|2|3  Set difficulty level (1 is easiest)\n\ */
 
148
 
 
149
 
 
150
/* Set SDL cursor. */
 
151
void
 
152
oes_cursor ()
 
153
{
 
154
        int i, row, col;
 
155
        Uint8 data[4*16];
 
156
        Uint8 mask[4*16];
 
157
        int hot_x, hot_y;
 
158
        const char **image;
 
159
        SDL_Cursor *cursor;
 
160
    
 
161
        image = crosshairs_xpm;
 
162
        i = -1;
 
163
        for ( row=0; row<16; ++row ) {
 
164
                for ( col=0; col<16; ++col ) {
 
165
                        if ( col % 8 ) {
 
166
                                data[i] <<= 1;
 
167
                                mask[i] <<= 1;
 
168
                        } else {
 
169
                                ++i;
 
170
                                data[i] = mask[i] = 0;
 
171
                        }
 
172
                        switch (image[4+row][col]) {
 
173
                        case 'X':
 
174
                                data[i] |= 0x01;
 
175
                                mask[i] |= 0x01;
 
176
                                break;
 
177
                        case '.':
 
178
                                mask[i] |= 0x01;
 
179
                                break;
 
180
                        case ' ':
 
181
                                break;
 
182
                        }
 
183
                }
 
184
        }
 
185
        sscanf(image[4+row], "%d,%d", &hot_x, &hot_y);
 
186
        cursor = SDL_CreateCursor(data, mask, 16, 16, hot_x, hot_y);
 
187
        SDL_SetCursor (cursor);
 
188
}
 
189
 
 
190
 
 
191
 
 
192
 
 
193
 
 
194
 
 
195
/********************/
 
196
/* Background Music */
 
197
/********************/
 
198
 
 
199
 
 
200
/* Function for SDL_mixer */
 
201
static void oes_bgm_loop()
 
202
{
 
203
  sniperbgm_loop(Game.BGM);
 
204
}
 
205
 
 
206
 
 
207
sniperbgm_t *
 
208
sniperbgm_init (sniperbgm_t *self)
 
209
{
 
210
  if (!self)
 
211
      self = (sniperbgm_t*)calloc(1, sizeof(*self));
 
212
  self->BGM = NULL;
 
213
  self->playp = 0;
 
214
  self->pausep = 0;
 
215
  return self;
 
216
}
 
217
 
 
218
sniperbgm_t *
 
219
sniperbgm_init_music (sniperbgm_t *self, Mix_Music *m)
 
220
{
 
221
  if ((self = sniperbgm_init(self)))
 
222
    {
 
223
//      SniperBGM();
 
224
      self->BGM = m;
 
225
    }
 
226
  return self;
 
227
}
 
228
 
 
229
void
 
230
sniperbgm_delete (sniperbgm_t *self)
 
231
{
 
232
  sniperbgm_stop(self);  /* Don't wait for fadeout to finish. */
 
233
  Mix_FreeMusic(self->BGM);
 
234
  free(self);
 
235
}
 
236
 
 
237
Mix_Music *
 
238
sniperbgm_music (sniperbgm_t *self)
 
239
{
 
240
  return self->BGM;
 
241
}
 
242
 
 
243
int
 
244
sniperbgm_use (sniperbgm_t *self, Mix_Music *m)
 
245
{
 
246
  if (!m) return 0;
 
247
  self->BGM = m;
 
248
  return 1;
 
249
}
 
250
 
 
251
void
 
252
sniperbgm_start (sniperbgm_t *self)
 
253
{
 
254
  if (self->BGM)
 
255
    {
 
256
      if (Mix_PlayMusic(self->BGM, 0))
 
257
          printf("Mix_PlayMusic: %s\n", Mix_GetError());
 
258
    }
 
259
  Mix_HookMusicFinished(oes_bgm_loop);
 
260
  self->playp = 1;
 
261
  self->time_start = SDL_GetTicks();
 
262
}
 
263
 
 
264
void
 
265
sniperbgm_stimulate (sniperbgm_t *self)
 
266
{
 
267
  if (self->playp) return;
 
268
  if (Mix_FadeInMusic(self->BGM, 0, sniperbgm_FadeInTime))
 
269
      printf("Mix_PlayMusic: %s\n", Mix_GetError());
 
270
  Mix_HookMusicFinished(oes_bgm_loop);
 
271
  self->playp = 1;
 
272
  self->time_start = SDL_GetTicks();
 
273
}
 
274
 
 
275
void
 
276
sniperbgm_depress (sniperbgm_t *self)
 
277
{
 
278
  Mix_HookMusicFinished(NULL);
 
279
  if (!Mix_FadeOutMusic(sniperbgm_FadeOutTime))
 
280
      Mix_HaltMusic();
 
281
  self->playp = 0;
 
282
}
 
283
 
 
284
void
 
285
sniperbgm_stop (sniperbgm_t *self)
 
286
{
 
287
  Mix_HaltMusic();
 
288
  Mix_HookMusicFinished(NULL);
 
289
  self->playp = 0;
 
290
}
 
291
 
 
292
void
 
293
sniperbgm_pause (sniperbgm_t *self, int newstate)
 
294
{
 
295
  switch (newstate)
 
296
    {
 
297
      case 0: /* pause */
 
298
        Mix_PauseMusic();
 
299
        self->pausep = 1;
 
300
        break;
 
301
      case 1: /* resume */
 
302
        Mix_ResumeMusic();
 
303
        self->pausep = 0;
 
304
        break;
 
305
      default: /* toggle */
 
306
        if (self->pausep) Mix_ResumeMusic(); else Mix_PauseMusic();
 
307
        self->pausep = !self->pausep;
 
308
        break;
 
309
    }
 
310
}
 
311
 
 
312
void
 
313
sniperbgm_jumpto (sniperbgm_t *self, float pos)
 
314
{
 
315
  Mix_SetMusicPosition(pos);
 
316
}
 
317
 
 
318
void
 
319
sniperbgm_rewind (sniperbgm_t *self)
 
320
{
 
321
  Mix_RewindMusic();
 
322
}
 
323
 
 
324
void
 
325
sniperbgm_loop (sniperbgm_t *self)
 
326
{
 
327
  sniperbgm_start(self);
 
328
  sniperbgm_jumpto(self, sniperbgm_RepeatJumpPos);
 
329
}
 
330
 
 
331
void
 
332
sniperbgm_release (sniperbgm_t *self)
 
333
{
 
334
  /* Prepare for release of sound device. */
 
335
  /* Figure out where in the BGM we currently are. */
 
336
  self->time_stop = SDL_GetTicks();
 
337
  self->bookmark = (self->time_stop - self->time_start) / 1000.0;
 
338
  sniperbgm_stop(self);
 
339
}
 
340
 
 
341
void
 
342
sniperbgm_grab (sniperbgm_t *self)
 
343
{
 
344
  /* Try to resume BGM after reopening sound device. */
 
345
  sniperbgm_start(self);
 
346
  sniperbgm_jumpto(self, self->bookmark);
 
347
  self->time_start -= (int)(self->bookmark * 1000); /* For next pause. */
 
348
}
 
349
 
 
350
 
 
351
 
 
352
 
 
353
 
 
354
/******************/
 
355
/* Options parser */
 
356
/******************/
 
357
 
 
358
static int
 
359
parse_option (PETOPT *pp, PETOPTS *pov, const char *arg)
 
360
{
 
361
        switch (pov->s) {
 
362
                case 'n': // no audio
 
363
                        gPrefs.audio = 0;
 
364
                        break;
 
365
                case 'f': // fullscreen
 
366
                        gPrefs.fullscreen = 1;
 
367
                        break;
 
368
                case 'w': // window
 
369
                        gPrefs.fullscreen = 0;
 
370
                        break;
 
371
                case 'a': // audio
 
372
                        gPrefs.audio = 1;
 
373
                        break;
 
374
                case '1':
 
375
                        gPrefs.difficulty = 1;
 
376
                        break;
 
377
                case '2':
 
378
                        gPrefs.difficulty = 2;
 
379
                        break;
 
380
                case '3':
 
381
                        gPrefs.difficulty = 3;
 
382
                        break;          
 
383
                case 'h':
 
384
                        fprintf (stderr, usage, invocation);
 
385
                        exit (0);
 
386
                        break;
 
387
        }
 
388
    return 1;
 
389
}
 
390
 
 
391
void parse_args(int argc, char **argv)
 
392
{
 
393
        int fs, au, ds, petopt_err;
 
394
        PETOPTS pov[] = {
 
395
        { 'n',  POF_BOOL,       "noaudio",      &au,    "Disable Audio" },
 
396
        { 'f',  POF_BOOL,       "fullscreen",   &fs,    "Enable Fullscreen" },
 
397
        { 'w',  POF_BOOL,       "windowed",     &fs,    "Disable Fullscreen" },
 
398
        { 'a',  POF_BOOL,       "audio",        &au,    "Enable Audio" },
 
399
        { '1',  POF_OPT|POF_INT,"diff1",        &ds,    "Difficulty Setting 1" },
 
400
        { '2',  POF_OPT|POF_INT,"diff2",        &ds,    "Difficulty Setting 2" },
 
401
        { '3',  POF_OPT|POF_INT,"diff3",        &ds,    "Difficulty Setting 3" },
 
402
        { 'h',  0,              "help",         NULL,   "Extended mode" },
 
403
        { -1,   0,              0,              NULL,   NULL },
 
404
        };
 
405
 
 
406
        PETOPT *pop;
 
407
 
 
408
        petopt_err = petopt_setup (&pop, 0, argc, argv, pov, parse_option, NULL);
 
409
        if (petopt_err > 0) {
 
410
                fprintf (stderr, "Unable to initialise petopt: %s\n", strerror(petopt_err));
 
411
                exit (1);
 
412
        }
 
413
        petopt_err = petopt_parse (pop, &argc, &argv);
 
414
        if (petopt_err > 0) {
 
415
                fprintf(stderr, "petopt_parse_all: %s\n", strerror(petopt_err));
 
416
                exit(1);
 
417
        }
 
418
        petopt_cleanup (pop);
 
419
        
 
420
        return;
 
421
}
 
422
 
 
423
 
 
424
 
 
425
 
 
426
 
 
427
 
 
428
/***************/
 
429
/* Audio stuff */
 
430
/***************/
 
431
 
 
432
#if 0
 
433
void audiomixer(void *userdata, Uint8 *stream, int len)
 
434
{
 
435
    int l = len / 2;
 
436
    short * buf = (short*)stream;
 
437
    memset(stream,0,len);
 
438
    if (gPlaySound & (1<<1))
 
439
    {
 
440
        gPlaySound &= ~(1<<1);
 
441
        Game.AudioZoom.ofs = 0;
 
442
        Game.AudioZoom.data = Game.AudioZoomOut.data;
 
443
        Game.AudioZoom.len = Game.AudioZoomOut.len;
 
444
    }
 
445
    if (gPlaySound & (1<<2))
 
446
    {
 
447
        gPlaySound &= ~(1<<2);
 
448
        Game.AudioZoom.ofs = 0;
 
449
        Game.AudioZoom.data = Game.AudioZoomIn.data;
 
450
        Game.AudioZoom.len = Game.AudioZoomIn.len;
 
451
    }
 
452
    if (gPlaySound & (1<<3))
 
453
    {
 
454
        gPlaySound &= ~(1<<3);
 
455
        Game.AudioFireSample.ofs = 0;
 
456
        Game.AudioFireSample.data = Game.AudioFire.data;
 
457
        Game.AudioFireSample.len = Game.AudioFire.len;
 
458
    }
 
459
    if (Game.AudioZoom.data != NULL)
 
460
    {
 
461
        int n = l;
 
462
        if (n + Game.AudioZoom.ofs > Game.AudioZoom.len)
 
463
            n = Game.AudioZoom.len - Game.AudioZoom.ofs;
 
464
        int i;
 
465
        for (i = 0; i < n; i++)
 
466
            buf[i] = Game.AudioZoom.data[i + Game.AudioZoom.ofs] / 2;
 
467
        Game.AudioZoom.ofs += n;
 
468
        if (l != n)
 
469
        {
 
470
            Game.AudioZoom.data = NULL;
 
471
        }
 
472
    }
 
473
    if (Game.AudioFireSample != NULL)
 
474
    {
 
475
        int n = l;
 
476
        if (n + Game.AudioFireSample.ofs > Game.AudioFireSample.len)
 
477
            n = Game.AudioFireSample.len - Game.AudioFireSample.ofs;
 
478
        int i;
 
479
        for (i = 0; i < n; i++)
 
480
            buf[i] += Game.AudioFireSample.data[i + Game.AudioFireSample.ofs] / 2;
 
481
        Game.AudioFireSample.ofs += n;
 
482
        if (l != n)
 
483
        {
 
484
            Game.AudioFireSample.data = NULL;
 
485
        }
 
486
    }    
 
487
}
 
488
#endif /* 0 */
 
489
 
 
490
/* Sillily expensive, but faster. */
 
491
char chanuse[16];
 
492
 
 
493
void oes_sound_finish (int chan)
 
494
{
 
495
  chanuse[chan] = 0;
 
496
}
 
497
 
 
498
void oes_sound_play (int aSound)
 
499
{
 
500
    int chan;
 
501
    if (!gPrefs.audio)
 
502
        return;
 
503
//    SDL_LockAudio();
 
504
//    gPlaySound |= 1 << aSound;
 
505
//    SDL_UnlockAudio();
 
506
    /* Find a free channel. */
 
507
    for (chan = 0; (chan < 16) && (chanuse[chan]); chan++);
 
508
    if (chan >= 16) return; /* out of channels. */
 
509
    chanuse[chan] = 1;
 
510
    switch (aSound) {
 
511
        case 1:
 
512
            Mix_PlayChannel(chan, Game.AudioZoomOut, 0);
 
513
            break;
 
514
        case 2:
 
515
            Mix_PlayChannel(chan, Game.AudioZoomIn, 0);
 
516
            break;
 
517
        case 3:
 
518
            Mix_PlayChannel(chan, Game.AudioFire, 0);
 
519
            break;
 
520
    }
 
521
}
 
522
 
 
523
int oes_audio_open ()
 
524
{
 
525
#ifdef PLAY_AUDIO
 
526
    if (gPrefs.audio)
 
527
        {
 
528
#if 1
 
529
            /* XXX: take settings from prefs. */
 
530
            if (Mix_OpenAudio(44100, AUDIO_S16, 2, 4096)) {
 
531
                printf("Mix_OpenAudio(): %s\n", Mix_GetError());
 
532
            }
 
533
            Mix_AllocateChannels(17);
 
534
            Mix_ChannelFinished(oes_sound_finish);
 
535
#else
 
536
            SDL_AudioSpec *as = (SDL_AudioSpec*)malloc(sizeof(SDL_AudioSpec));
 
537
            as->freq = 44100;
 
538
            as->format = AUDIO_S16;
 
539
            as->channels = 2;
 
540
            as->samples = 4096;
 
541
            as->callback = audiomixer;
 
542
            as->userdata = NULL;
 
543
            if (SDL_OpenAudio(as, NULL) < 0)
 
544
                {
 
545
                    fprintf(stderr, "Unable to init SDL audio: %s\n", SDL_GetError());
 
546
                    exit(1);
 
547
                }
 
548
            Game.sdlaudio = as;
 
549
#endif /* 0 */
 
550
        }
 
551
#endif
 
552
  return 0;
 
553
}
 
554
 
 
555
int oes_audio_close ()
 
556
{
 
557
  Mix_CloseAudio();
 
558
  return 0;
 
559
}
 
560
 
 
561
 
 
562
 
 
563
 
 
564
 
 
565
 
 
566
/*****************************/
 
567
/* Game and system resources */
 
568
/*****************************/
 
569
 
 
570
 
 
571
/* initialize game data. */
 
572
ORBITALSNIPER *
 
573
oes_game_init (ORBITALSNIPER *self)
 
574
{
 
575
  int i;
 
576
  int tick;
 
577
 
 
578
  if (!self)
 
579
      self = (ORBITALSNIPER*)calloc(1, sizeof(ORBITALSNIPER));
 
580
 
 
581
  tick = SDL_GetTicks();
 
582
  self->MouseX = 0;
 
583
  self->MouseY = 0;
 
584
  self->MouseZ = 1.0f;
 
585
  self->CoordScale = 1.0f;
 
586
  self->WobbleX = 0;
 
587
  self->WobbleY = 0;
 
588
  self->CenterX = 0;
 
589
  self->CenterY = 0;
 
590
  self->ControlState = 0;
 
591
  self->Reloading = 0;
 
592
  self->Score = 0;
 
593
  self->vip.count = 0;
 
594
  self->baddy.count = 0;
 
595
  self->WobbleIndex = 0;
 
596
  self->vip.goal = 0;
 
597
  self->pedestrian.dead = 0;
 
598
  self->baddy.dead = 0;
 
599
  self->SightedCharacter = NULL;
 
600
 
 
601
  if (oesjoy.sdljoy) {
 
602
      SDL_JoystickClose(oesjoy.sdljoy);
 
603
      oesjoy.sdljoy = NULL;
 
604
  }
 
605
  oesjoy.x = 0;  oesjoy.y = 0;  oesjoy.z = 0;  oesjoy.state = 0;
 
606
  oesjoy.axes = 0;  oesjoy.buttons = 0;
 
607
  if (gPrefs.joystick) {
 
608
      /* want to use joystick. */
 
609
//printf("Detected %d joysticks\n", SDL_NumJoysticks());
 
610
      if ((oesjoy.sdljoy = SDL_JoystickOpen(gPrefs.joystick - 1))) { /* off-by-one */
 
611
          oesjoy.axes = SDL_JoystickNumAxes(oesjoy.sdljoy);
 
612
          oesjoy.buttons = SDL_JoystickNumButtons(oesjoy.sdljoy);
 
613
      }
 
614
  }
 
615
 
 
616
  for (i = 0; i < self->num_characters; i++)
 
617
  {
 
618
      self->characters[i].mType = -1;
 
619
  }
 
620
  for (i = 0; i < (int)(self->num_characters * 0.75f); i++)
 
621
  {
 
622
      int id = spawn_ai(2);
 
623
      int j;
 
624
      for (j = 0; j < 1000; j++) // Run 1000 physics loops for all pedestrians..
 
625
          handle_ai(self->characters[id]);
 
626
  }
 
627
  self->vip.time = 2000;
 
628
  self->vip.period = 20000;
 
629
  self->baddy.time = 3000;
 
630
  self->baddy.period = 8000;
 
631
  self->WobbleIndex = 0;
 
632
  self->StartTick = tick;
 
633
  self->FrameCount = 0;
 
634
  self->LastTick = tick;
 
635
  self->GameState = 1;
 
636
  self->GameStartTick = tick;
 
637
  SDL_ShowCursor (0);
 
638
 
 
639
  return self;
 
640
}
 
641
 
 
642
 
 
643
/* One-time setup at start. */
 
644
int
 
645
oes_setup ()
 
646
{
 
647
/* load audio, load images, load models(?), allocate objects. */
 
648
  int i;
 
649
  const char *city_img = "citee2.png";
 
650
  const char *charseq_img = "charseq.png";
 
651
  const char *aimap_img = "aimap.png";
 
652
  const char *font_img = "font4x6.png";
 
653
  const char *zoomin_snd = "camera_in.wav";
 
654
  const char *zoomout_snd = "camera_out.wav";
 
655
  const char *boing_snd = "twang.wav";
 
656
  const char *bgmusic = "oes.ogg";
 
657
 
 
658
//  char path[ strlen(mediaPath) + 1 + 30 + 1 ];
 
659
//  path = (char*)calloc(strlen(mediaPath) + 1 + 30 + 1, sizeof(char));
 
660
  char *path;
 
661
  /* free on function exit. */
 
662
  path = (char*)alloca((strlen(Game.mediaPath) + 1 + 30 + 1) * sizeof(char));
 
663
 
 
664
 
 
665
  /* Configure difficulty. */
 
666
  configure_difficulty();
 
667
  /* Initialise high scores. */
 
668
  init_hiscores();
 
669
    
 
670
  /* Initialise SDL */
 
671
    //if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0 ) 
 
672
//    if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) 
 
673
  if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0 )
 
674
    {
 
675
      fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
 
676
      exit(1);
 
677
    }
 
678
    
 
679
  atexit(SDL_Quit);
 
680
    
 
681
  //gScreen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE); 
 
682
#ifdef OSX_SUX
 
683
  Game.Screen = SDL_SetVideoMode(640, 480, 16, (gPrefs.fullscreen ? SDL_FULLSCREEN : 0) | SDL_SWSURFACE);
 
684
#else
 
685
  Game.Screen = SDL_SetVideoMode(640, 480, 16, (gPrefs.fullscreen ? SDL_FULLSCREEN : 0) | SDL_SWSURFACE | SDL_DOUBLEBUF);
 
686
#endif
 
687
  SDL_WM_SetCaption("ORBITAL EUNUCHS SNIPER", "ORBITAL_EUNUCHS_SNIPER");
 
688
  if (Game.Screen == NULL) 
 
689
    {
 
690
      fprintf(stderr, "Unable to set 640x480 video: %s\n", SDL_GetError());
 
691
      exit(1);
 
692
    }
 
693
  /* Cursor */
 
694
  oes_cursor();
 
695
//  init_logoscreen();
 
696
    
 
697
  oes_audio_open();
 
698
 
 
699
 
 
700
  Game.BGM = sniperbgm_init(Game.BGM);
 
701
 
 
702
  sprintf(path, "%s/%s", Game.mediaPath, city_img);
 
703
  SDL_Surface *temp = IMG_Load(path);
 
704
  if (!temp) {
 
705
    fprintf(stderr, "Unable to load city map from '%s'\n",path);
 
706
    exit(1);
 
707
  }
 
708
  Game.Map = SDL_ConvertSurface(temp, Game.Screen->format,SDL_SWSURFACE);
 
709
  SDL_FreeSurface(temp);
 
710
    
 
711
  sprintf(path, "%s/%s", Game.mediaPath, charseq_img);
 
712
  temp = IMG_Load(path);
 
713
  if (!temp) {
 
714
    fprintf(stderr, "Unable to load character image from '%s'\n",path);
 
715
    exit(1);
 
716
  }
 
717
  Game.CharSprite = SDL_ConvertSurface(temp, Game.Screen->format,SDL_SWSURFACE);
 
718
  SDL_FreeSurface(temp);
 
719
 
 
720
  sprintf(path, "%s/%s", Game.mediaPath, aimap_img);
 
721
  Game.AIMap = IMG_Load(path);
 
722
  if (!temp) {
 
723
    fprintf(stderr, "Unable to load AI map from '%s'\n",path);
 
724
    exit(1);
 
725
  }
 
726
    
 
727
  // Okay, this is ugly. Load font several times & change the color of each.
 
728
    
 
729
  for (i = 0; i < 5; i++)
 
730
  {
 
731
      sprintf(path, "%s/%s", Game.mediaPath, font_img);
 
732
      Game.Font[i] = IMG_Load(path);
 
733
      if (!Game.Font[i]) {
 
734
        fprintf(stderr, "Unable to load font %d from '%s'\n",i,path);
 
735
        exit(1);
 
736
      }
 
737
      SDL_SetColorKey(Game.Font[i],SDL_SRCCOLORKEY,1); // set color index 1 (black) transparent
 
738
  }
 
739
  *(int*)&(Game.Font[0]->format->palette->colors[0]) = 0x000000; // black
 
740
  *(int*)&(Game.Font[1]->format->palette->colors[0]) = 0xffffff; // white
 
741
  *(int*)&(Game.Font[2]->format->palette->colors[0]) = 0x00ff00; // green
 
742
  *(int*)&(Game.Font[3]->format->palette->colors[0]) = 0x00ffff; // yellow
 
743
  *(int*)&(Game.Font[4]->format->palette->colors[0]) = 0x0000ff; // red
 
744
    
 
745
  precalc_ai();
 
746
    
 
747
  Game.num_characters = 2048;
 
748
  Game.characters = (CHARACTER*)calloc(Game.num_characters, sizeof(CHARACTER));
 
749
 
 
750
#ifdef PLAY_AUDIO
 
751
  if (gPrefs.audio)
 
752
    {
 
753
      sprintf(path, "%s/%s", Game.mediaPath, zoomin_snd);
 
754
      Game.AudioZoomIn = Mix_LoadWAV(path);
 
755
      if (!Game.AudioZoomIn) {
 
756
        fprintf(stderr, "Unable to load zoom in sound from '%s'\n",path);
 
757
        exit(1);
 
758
      }
 
759
      sprintf(path, "%s/%s", Game.mediaPath, zoomout_snd);
 
760
      Game.AudioZoomOut = Mix_LoadWAV(path);
 
761
      if (!Game.AudioZoomOut) {
 
762
        fprintf(stderr, "Unable to load zoom out sound from '%s'\n",path);
 
763
        exit(1);
 
764
      }
 
765
      sprintf(path, "%s/%s", Game.mediaPath, boing_snd);
 
766
      Game.AudioFire = Mix_LoadWAV(path);
 
767
      if (!Game.AudioFire) {
 
768
        fprintf(stderr, "Unable to load fire sound from '%s'\n",path);
 
769
        exit(1);
 
770
      }
 
771
      sprintf(path, "%s/%s", Game.mediaPath, bgmusic);
 
772
//      Game.BGM = Mix_LoadMUS(path);
 
773
      if (!sniperbgm_use(Game.BGM, Mix_LoadMUS(path))) {
 
774
        fprintf(stderr, "Unable to load background music from '%s'\n",path);
 
775
        exit(1);
 
776
      }
 
777
 
 
778
//      SDL_PauseAudio(0); // let it play
 
779
    }
 
780
#endif
 
781
 
 
782
  oes_game_init(&Game);
 
783
  return 0;
 
784
}
 
785
 
 
786
/* One-time teardown at exit. */
 
787
void
 
788
oes_teardown ()
 
789
{
 
790
  if (oesjoy.sdljoy)
 
791
    {
 
792
      SDL_JoystickClose(oesjoy.sdljoy);
 
793
      oesjoy.sdljoy = NULL;
 
794
    }
 
795
}
 
796
 
 
797
/* Temporarily release system resources. */
 
798
int
 
799
oes_suspend ()
 
800
{
 
801
  if (Game.GameState != OESGAME_PLAY) return 0;
 
802
  sniperbgm_release(Game.BGM);
 
803
  oes_audio_close();
 
804
  SDL_WM_GrabInput(SDL_GRAB_OFF);
 
805
  SDL_ShowCursor(1);
 
806
  Game.GameState = OESGAME_PAUSED;
 
807
  return 0;
 
808
}
 
809
 
 
810
/* Reassert system resources that were temporarily released. */
 
811
int
 
812
oes_resume ()
 
813
{
 
814
  if (Game.GameState != OESGAME_PAUSED) return 0;
 
815
  if (Game.GrabP)
 
816
    {
 
817
      SDL_ShowCursor(0);
 
818
      SDL_WM_GrabInput(SDL_GRAB_ON);
 
819
    }
 
820
  oes_audio_open();
 
821
  sniperbgm_grab(Game.BGM);
 
822
  Game.GameState = OESGAME_UNPAUSED;
 
823
  return 0;
 
824
}
 
825
 
 
826
 
 
827
 
 
828
 
 
829
 
 
830
 
 
831
/**************/
 
832
/* Game logic */
 
833
/**************/
 
834
 
 
835
#define PHYSICS_MS 10
 
836
// 10ms physics loops == 100 loops per sec, 'should be enough'..
 
837
 
 
838
void oes_reindeer()
 
839
{
 
840
    Game.SightedCharacter = NULL;
 
841
    int tick = SDL_GetTicks();    
 
842
    Game.FrameCount++;
 
843
    if (Game.Reloading)
 
844
    {
 
845
        Game.Reloading -= tick - Game.LastTick;
 
846
        if (Game.Reloading < 0)
 
847
            Game.Reloading = 0;
 
848
    }
 
849
    
 
850
    Game.CenterX = (640.0f - 640.0f * Game.CoordScale) / 2;
 
851
    Game.CenterY = (480.0f - 480.0f * Game.CoordScale) / 2;
 
852
    Game.WobbleX = (float)(sin(Game.WobbleIndex * 0.000654387) + 
 
853
        sin(Game.WobbleIndex * 0.000547867)*2 + 
 
854
        sin(Game.WobbleIndex * 0.000700133)) * (WOBBLE / 4.0f);
 
855
    Game.WobbleY = (float)(sin(Game.WobbleIndex * 0.000537234) + 
 
856
        sin(Game.WobbleIndex * 0.000732897) + 
 
857
        sin(Game.WobbleIndex * 0.000600613)*2) * (WOBBLE / 4.0f);
 
858
    
 
859
    
 
860
    
 
861
#ifdef UNREAL_DITHER
 
862
    zoom_unreal(Game.Map, Game.MouseX + Game.CenterX + Game.WobbleX, Game.MouseY + Game.CenterY + Game.WobbleY, Game.CoordScale);    
 
863
#else
 
864
    zoom(Game.Map, Game.MouseX + Game.CenterX + Game.WobbleX, Game.MouseY + Game.CenterY + Game.WobbleX, Game.CoordScale);    
 
865
#endif   
 
866
    
 
867
    int i;
 
868
    int physics_loops = (tick - Game.LastTick) / PHYSICS_MS;
 
869
    int j;
 
870
    for (i = 0; i < Game.num_characters; i++)
 
871
    {
 
872
        for (j = 0; j < physics_loops; j++)
 
873
            handle_ai(Game.characters[i]);
 
874
        if (!Game.GameState)
 
875
            return;
 
876
        drawCharacter(Game.characters[i]);
 
877
    }
 
878
    
 
879
    target();
 
880
    
 
881
    for (j = 0; j < physics_loops; j++)
 
882
    {
 
883
        int physicstick = Game.LastTick - Game.GameStartTick;
 
884
        Game.WobbleIndex += PHYSICS_MS;
 
885
        
 
886
        // spawn VIPs
 
887
        if (physicstick >= Game.vip.time)
 
888
        {
 
889
            
 
890
            if (Game.vip.count == 2 && rand() < 2048)
 
891
                spawn_ai(1);
 
892
            if (Game.vip.count == 1 && rand() < 8192)
 
893
                spawn_ai(1);
 
894
            if (Game.vip.count == 0)            
 
895
                spawn_ai(1);
 
896
            Game.vip.time += (int)Game.vip.period;
 
897
        }
 
898
        // spawn baddies
 
899
        if (physicstick >= Game.baddy.time)
 
900
        {
 
901
            spawn_ai(0);
 
902
            Game.baddy.time += (int)Game.baddy.period;
 
903
        }
 
904
        if (((Game.LastTick / PHYSICS_MS) & 3) == 0) 
 
905
            Game.baddy.period--;
 
906
        
 
907
        if (Game.baddy.period < 3000)
 
908
            Game.baddy.period = 3000; // Eventually it will be impossible to kill all bad guys.
 
909
        
 
910
        Game.LastTick += PHYSICS_MS;     
 
911
    }
 
912
    
 
913
    
 
914
    SDL_Flip(Game.Screen);    
 
915
}
 
916
 
 
917
 
 
918
int oes_game_state (int newstate)
 
919
{
 
920
        switch ((Game.GameState = newstate)) {
 
921
        case 0:
 
922
                /* need init */
 
923
                break;
 
924
        case 1:
 
925
                /* main game state. */
 
926
                break;
 
927
        case 2:
 
928
                /* paused state. */
 
929
                break;
 
930
        case 3:
 
931
                /* just unpaused.  Need re-init, transit to 1. */
 
932
                break;
 
933
        }
 
934
    return Game.GameState;
 
935
}
 
936
 
 
937
/*
 
938
Alter input grab state.
 
939
0 = try to release
 
940
1 = try to grab
 
941
-1 = toggle whatever it is.
 
942
*/
 
943
int oes_game_grab (int newstate)
 
944
{
 
945
        int tryGrabState;
 
946
 
 
947
        if (SDL_GetVideoSurface()->flags & SDL_FULLSCREEN) {
 
948
                /* Don't release grab in fullscreen. */
 
949
                SDL_WM_GrabInput(SDL_GRAB_ON);
 
950
                SDL_ShowCursor(0);
 
951
                Game.GrabP = 1;
 
952
                return 0;
 
953
        }
 
954
        tryGrabState = (newstate == -1) ? !Game.GrabP : newstate;
 
955
        switch (tryGrabState) {
 
956
        case 0:
 
957
                SDL_WM_GrabInput(SDL_GRAB_OFF);
 
958
                Game.GrabP = 0;
 
959
                SDL_ShowCursor(1);
 
960
                break;
 
961
        case 1:
 
962
                SDL_ShowCursor(0);
 
963
                SDL_WM_GrabInput(SDL_GRAB_ON);
 
964
                Game.GrabP = 1;
 
965
                break;
 
966
        }
 
967
        return Game.GrabP;
 
968
}
 
969
 
 
970
int oes_game_zoom (float amt)
 
971
{
 
972
        float oldcoord = Game.CoordScale;
 
973
 
 
974
        Game.MouseZ += amt;
 
975
        if (Game.MouseZ > 1.25) Game.MouseZ = 1.25;
 
976
        if (Game.MouseZ < 0.05f) Game.MouseZ = 0.05f;
 
977
#ifndef CAMERA_STEPS
 
978
        Game.CoordScale = Game.MouseZ;
 
979
#else /* CAMERA_STEPS */
 
980
        Game.CoordScale = ((int)(Game.MouseZ * 4)) / 4.0f;
 
981
        if (Game.CoordScale < 0.05f) Game.CoordScale = 0.05f;
 
982
#endif /* CAMERA_STEPS */
 
983
        if (oldcoord < Game.CoordScale)
 
984
                oes_sound_play(1);
 
985
        if (oldcoord > Game.CoordScale)
 
986
                oes_sound_play(2);
 
987
        return 0;
 
988
}
 
989
 
 
990
/*
 
991
Set paused state.
 
992
0 = force play/resume
 
993
1 = force pause
 
994
-1 = toggle paused state
 
995
*/
 
996
int oes_game_pause (int newstate)
 
997
{
 
998
  int tryPause;
 
999
  int tick;
 
1000
 
 
1001
  tryPause = newstate;
 
1002
  if (newstate == -1)
 
1003
    {
 
1004
      if (Game.GameState == OESGAME_PAUSED)
 
1005
          tryPause = 0;
 
1006
      else
 
1007
          tryPause = 1;
 
1008
    }
 
1009
  tick = SDL_GetTicks();
 
1010
  switch (tryPause)
 
1011
    {
 
1012
      case 0:
 
1013
        if (Game.GameState == OESGAME_PAUSED)
 
1014
          {
 
1015
//printf("UNPAUSING\n");
 
1016
            /* resume */
 
1017
            oes_resume();  /* regain system resources. */
 
1018
            Game.AfterPauseTick = tick;
 
1019
            Game.GameStartTick += Game.AfterPauseTick - Game.BeforePauseTick;
 
1020
            Game.GameState = OESGAME_PLAY;
 
1021
            break;
 
1022
          }
 
1023
        break;
 
1024
      case 1:
 
1025
        if (Game.GameState == OESGAME_PLAY)
 
1026
          {
 
1027
            /* go to pause */
 
1028
//printf("Pausing\n");
 
1029
            Game.BeforePauseTick = tick;
 
1030
            oes_suspend();  /* release system resources. */
 
1031
            Game.GameState = OESGAME_PAUSED;
 
1032
          }
 
1033
        break;
 
1034
    }
 
1035
  return tryPause;
 
1036
}
 
1037
 
 
1038
/* Boss event. */
 
1039
int
 
1040
oes_game_hide (int newstate)
 
1041
{
 
1042
  SDL_WM_IconifyWindow();
 
1043
  oes_game_pause(1);
 
1044
  return 1;
 
1045
}
 
1046
 
 
1047
 
 
1048
 
 
1049
 
 
1050
 
 
1051
 
 
1052
/******************/
 
1053
/* OES Game Binds */
 
1054
/******************/
 
1055
 
 
1056
 
 
1057
/* No-operation */
 
1058
int oes_bind_nop (int val)
 
1059
{
 
1060
  /* do-nothing */
 
1061
  return 0;
 
1062
}
 
1063
 
 
1064
 
 
1065
/* On-release-only binds */
 
1066
 
 
1067
int oes_bind_grab (int val)
 
1068
{
 
1069
        if (val) return 0;
 
1070
        return oes_game_grab(-1);
 
1071
}
 
1072
 
 
1073
/* toggle fullscreen... on key release */
 
1074
int oes_bind_fullscreen (int val)
 
1075
{
 
1076
        if (val) return 0;  /* toggle on release. */
 
1077
 
 
1078
        gPrefs.fullscreen = !gPrefs.fullscreen;
 
1079
        if (((Game.Screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) ^ (gPrefs.fullscreen)) {
 
1080
                SDL_WM_ToggleFullScreen(Game.Screen);
 
1081
        }
 
1082
//      SDL_WM_ToggleFullScreen(Game.Screen);
 
1083
//      gPrefs.fullscreen = !gPrefs.fullscreen;
 
1084
        return 0;
 
1085
}
 
1086
 
 
1087
/* Boss Key */
 
1088
int oes_bind_hide (int val)
 
1089
{
 
1090
        if (val) return 0; /* trigger on release */
 
1091
        oes_game_hide(1);
 
1092
        return 0;
 
1093
}
 
1094
 
 
1095
/* Forceful end of game. */
 
1096
int
 
1097
oes_bind_abandon (int pressed)
 
1098
{
 
1099
        if (pressed) return 0;
 
1100
        oes_resume();
 
1101
        Game.GameOverReason = OESREASON_AWOL;
 
1102
        return 0;
 
1103
}
 
1104
 
 
1105
 
 
1106
/* On-press binds */
 
1107
 
 
1108
/* paused mode. */
 
1109
int oes_bind_pause (int val)
 
1110
{
 
1111
        if (!val) return 0;
 
1112
        return oes_game_pause(-1);
 
1113
}
 
1114
 
 
1115
/* the extra information around the targeting reticles */
 
1116
int oes_bind_verbosity (int val)
 
1117
{
 
1118
        if (!val) return 0;
 
1119
        Game.verbosity = (Game.verbosity + 1) % 3;
 
1120
        gPrefs.verbose = Game.verbosity;
 
1121
        return 0;
 
1122
}
 
1123
 
 
1124
/* save screenshot */
 
1125
int oes_bind_screenshot (int val)
 
1126
{
 
1127
        if (!val) return 0;
 
1128
        SDL_SaveBMP(SDL_GetVideoSurface(),"screenshot.bmp");
 
1129
        screen_shot_number++;
 
1130
        return 0;
 
1131
}
 
1132
 
 
1133
int oes_bind_fire (int val)
 
1134
{
 
1135
        if (!val) return 0;
 
1136
        if (Game.GameState == OESGAME_PLAY) {
 
1137
                if (!Game.Reloading) {
 
1138
                        oes_sound_play(3);
 
1139
                        shoot();
 
1140
                }
 
1141
        } else if (Game.GameState == OESGAME_PAUSED) {
 
1142
                if (Game.LastTick - Game.SemiPause < 500) {
 
1143
//                      Game.GameState = OESGAME_UNPAUSED;
 
1144
                        oes_game_pause(0);
 
1145
                } else {
 
1146
                        Game.SemiPause = Game.LastTick;
 
1147
                }
 
1148
        }
 
1149
    return val;
 
1150
}
 
1151
 
 
1152
/* zooming mode */
 
1153
int oes_bind_zoom (int val)
 
1154
{
 
1155
        Game.ControlState = val ? 1 : 0;
 
1156
    return Game.ControlState;
 
1157
}
 
1158
 
 
1159
/* Zoom in */
 
1160
int oes_bind_zoomin (int val)
 
1161
{
 
1162
        if (!val) return 0;
 
1163
        if (Game.GameState != OESGAME_PLAY) return 1;
 
1164
        oes_game_zoom(-0.20f);
 
1165
        return val;
 
1166
}
 
1167
 
 
1168
/* Zoom out */
 
1169
int oes_bind_zoomout (int val)
 
1170
{
 
1171
        if (!val) return 0;
 
1172
        if (Game.GameState != OESGAME_PLAY) return 1;
 
1173
        oes_game_zoom(0.20f);
 
1174
        return val;
 
1175
}
 
1176
 
 
1177
 
 
1178
 
 
1179
/* Continuous-value binds */
 
1180
 
 
1181
/* Mouse motion, horizontal */
 
1182
int oes_bind_mhoriz (int val)
 
1183
{
 
1184
        if (!Game.GrabP) {
 
1185
                /* A little confusing if not grabbed... */
 
1186
                return 1;
 
1187
        }
 
1188
        if (Game.GameState != OESGAME_PLAY) return 1;
 
1189
        if (Game.ControlState == 0) {
 
1190
                Game.MouseX += val * Game.CoordScale;
 
1191
                if (Game.MouseX < -320) Game.MouseX = -320;
 
1192
                if (Game.MouseX > (800 -320)) Game.MouseX = (800 - 320);
 
1193
        } else {
 
1194
                /* nothing on horizontal while zoomshift */
 
1195
        }
 
1196
        return 0;
 
1197
}
 
1198
 
 
1199
/* Mouse motion, vertical */
 
1200
int oes_bind_mvert (int val)
 
1201
{
 
1202
        if (!Game.GrabP) {
 
1203
                /* A little confusing if not grabbed... */
 
1204
                return 1;
 
1205
        }
 
1206
        if (Game.GameState != OESGAME_PLAY) return 1;
 
1207
        if (Game.ControlState == 0) {
 
1208
                Game.MouseY += val * Game.CoordScale;
 
1209
                if (Game.MouseY < -240) Game.MouseY = -240;
 
1210
                if (Game.MouseY > (600 - 240)) Game.MouseY = (600 - 240);
 
1211
        } else {
 
1212
                oes_game_zoom (val * 0.005f);
 
1213
        }
 
1214
        return 0;
 
1215
}
 
1216
 
 
1217
/* Axis, horizontal */
 
1218
int oes_bind_jhoriz (int val)
 
1219
{
 
1220
        if (!Game.GrabP) return 1;
 
1221
        if (Game.GameState != OESGAME_PLAY) return 1;
 
1222
        oesjoy.x = (val * oesjoy.scale) / 32767.0;
 
1223
        return val;
 
1224
}
 
1225
 
 
1226
/* Axis, vertical */
 
1227
int oes_bind_jvert (int val)
 
1228
{
 
1229
        if (!Game.GrabP) return 1;
 
1230
        if (Game.GameState != OESGAME_PLAY) return 1;
 
1231
        oesjoy.y = (val * oesjoy.scale) / 32767.0;
 
1232
        return val;
 
1233
}
 
1234
 
 
1235
/* Axis, depth (zoom) */
 
1236
int oes_bind_jdeep (int val)
 
1237
{
 
1238
        float joyz;
 
1239
 
 
1240
        if (!Game.GrabP) return 1;
 
1241
        if (Game.GameState != OESGAME_PLAY) return 1;
 
1242
        oesjoy.z = val;
 
1243
/* XXX: what about going backwards? */
 
1244
        /*                    out     in  */
 
1245
        /* map oes.joyz from 1.25 to 0.05 */
 
1246
        /*                    0     32767 */
 
1247
        /* deltas: 1.20 : 32767 */
 
1248
//      joyz = (oesjoy.z * 1.20 / 32767.0) + 0.05;
 
1249
        joyz = 1.25 - (oesjoy.z * 1.20 / 32767.0);
 
1250
        Game.MouseZ = joyz;
 
1251
        oes_game_zoom(0);
 
1252
 
 
1253
        return val;
 
1254
}
 
1255
 
 
1256
 
 
1257
 
 
1258
 
 
1259
 
 
1260
 
 
1261
 
 
1262
 
 
1263
 
 
1264
/* After binds. */
 
1265
 
 
1266
 
 
1267
 
 
1268
/* game binding names (from config file) */
 
1269
oes_xlat_t oesxlat[] = {
 
1270
 { "mousex", oes_bind_mhoriz },
 
1271
 { "mousey", oes_bind_mvert },
 
1272
 { "joyx", oes_bind_jhoriz },
 
1273
 { "joyy", oes_bind_jvert },
 
1274
 { "joyz", oes_bind_jdeep },
 
1275
 { "fire", oes_bind_fire },
 
1276
 { "zoom", oes_bind_zoom },
 
1277
 { "zoomin", oes_bind_zoomin },
 
1278
 { "zoomout", oes_bind_zoomout },
 
1279
 { "verbosity", oes_bind_verbosity },
 
1280
 { "screenshot", oes_bind_screenshot },
 
1281
 { "fullscreen", oes_bind_fullscreen },
 
1282
 { "hide", oes_bind_hide },
 
1283
 { "abandon", oes_bind_abandon },
 
1284
 { "pause", oes_bind_pause },
 
1285
 { "grab", oes_bind_grab },
 
1286
 { 0, 0 },
 
1287
};
 
1288
 
 
1289
 
 
1290
 
 
1291
 
 
1292
/*******************/
 
1293
/* Events handling */
 
1294
/*******************/
 
1295
 
 
1296
 
 
1297
/* Called at intervals, handling joystick axes. */
 
1298
int oes_game_joystick (int ticks)
 
1299
{
 
1300
/* Joystick axes handling. */
 
1301
        int joyx, joyy;
 
1302
        if (!oesjoy.sdljoy) return 0;
 
1303
        if (ticks > oesjoy.time + oesjoy.interval) {
 
1304
//printf("JOY HANDLE\n");
 
1305
                joyx = (int)(oesjoy.x);
 
1306
                joyy = (int)(oesjoy.y);
 
1307
                switch (oesjoy.state) {
 
1308
                case 0: /* normal */
 
1309
                        oes_bind_mhoriz(joyx);
 
1310
                        oes_bind_mvert(joyy);
 
1311
                        break;
 
1312
                case 1: /* shifted 1 */
 
1313
                        oes_game_zoom(joyy * 0.005);
 
1314
                        break;
 
1315
                }
 
1316
                oesjoy.time = ticks;
 
1317
        }
 
1318
    return 1;
 
1319
}
 
1320
 
 
1321
 
 
1322
int oes_game_events ()
 
1323
{
 
1324
  SDL_Event event;
 
1325
  int kmod;
 
1326
  int oeskey;
 
1327
  oesbind_t binding; /* function pointer */
 
1328
 
 
1329
  while (SDL_PollEvent(&event))
 
1330
    {
 
1331
      switch (event.type)
 
1332
        {
 
1333
          case SDL_KEYDOWN:
 
1334
            binding = NULL;
 
1335
            kmod = SDL_GetModState();
 
1336
            oeskey = event.key.keysym.sym;
 
1337
            switch (event.key.keysym.sym)
 
1338
              {
 
1339
                /* Rebindable keys */
 
1340
                default:
 
1341
                  binding = oeskeymap_get(&oeskeymap, oeskey);
 
1342
                  break;
 
1343
              }
 
1344
            if (binding)
 
1345
                binding(1);
 
1346
            break;
 
1347
          case SDL_KEYUP:
 
1348
            binding = NULL;
 
1349
            kmod = SDL_GetModState();
 
1350
            oeskey = event.key.keysym.sym;
 
1351
            switch (event.key.keysym.sym)
 
1352
              {
 
1353
                /* Hard-coded keys */
 
1354
                case SDLK_F12: /* failsafe */
 
1355
                  exit(69);
 
1356
                  break;
 
1357
                case SDLK_F4: /* failsafe */
 
1358
                  if (kmod & KMOD_ALT) exit(69);
 
1359
                  break;
 
1360
                case SDLK_RETURN:
 
1361
                  if (kmod & KMOD_ALT)
 
1362
                    {
 
1363
                      binding = oes_bind_fullscreen;
 
1364
                    }
 
1365
                  break;
 
1366
                case SDLK_z:
 
1367
                  if (kmod & KMOD_CTRL)
 
1368
                    {
 
1369
                      binding = oes_bind_hide;
 
1370
                    }
 
1371
                  break;
 
1372
                case SDLK_g:
 
1373
                  if (kmod & KMOD_CTRL)
 
1374
                    {
 
1375
                      binding = oes_bind_grab;
 
1376
                    }
 
1377
                  break;
 
1378
                /* Rebindable keys */
 
1379
                default:
 
1380
                  binding = oeskeymap_get(&oeskeymap, oeskey);
 
1381
                  break;
 
1382
              }
 
1383
            if (binding)
 
1384
                binding(0);
 
1385
            break;
 
1386
          case SDL_MOUSEMOTION:
 
1387
//            binding = oeskeymap_get(&oeskeymap, oeskeymap_resolve("MOUSEX"));
 
1388
            binding = oeskeymap_get(&oeskeymap, keymarkers.mousex);
 
1389
            if (binding)
 
1390
                binding(event.motion.xrel);
 
1391
            binding = oeskeymap_get(&oeskeymap, keymarkers.mousey);
 
1392
            if (binding)
 
1393
                binding(event.motion.yrel);
 
1394
//            oes_bind_mhoriz(event.motion.xrel);
 
1395
//            oes_bind_mvert(event.motion.yrel);
 
1396
            break;
 
1397
          case SDL_MOUSEBUTTONDOWN:
 
1398
//            oeskey = oeskeymap_resolve("MOUSE0") + event.button.button;
 
1399
            oeskey = keymarkers.mouse0 + event.button.button;
 
1400
            binding = oeskeymap_get(&oeskeymap, oeskey);
 
1401
            if (binding)
 
1402
                binding(1);
 
1403
            break;
 
1404
          case SDL_MOUSEBUTTONUP:
 
1405
            oeskey = keymarkers.mouse0 + event.button.button;
 
1406
            binding = oeskeymap_get(&oeskeymap, oeskey);
 
1407
            if (binding)
 
1408
                binding(0);
 
1409
            break;
 
1410
          case SDL_JOYAXISMOTION:
 
1411
//            oeskey = oeskeymap_resolve("AXIS1") + event.jaxis.axis;
 
1412
            oeskey = keymarkers.axis1 + event.jaxis.axis;
 
1413
            binding = oeskeymap_get(&oeskeymap, oeskey);
 
1414
            if (binding)
 
1415
              {
 
1416
                binding(event.jaxis.value);
 
1417
              }
 
1418
            break;
 
1419
          case SDL_JOYBUTTONDOWN:
 
1420
//            oeskey = oeskeymap_resolve("JOY1") + event.jbutton.button;
 
1421
            oeskey = keymarkers.joy1 + event.jbutton.button;
 
1422
            binding = oeskeymap_get(&oeskeymap, oeskey);
 
1423
            if (binding)
 
1424
                binding(1);
 
1425
            break;
 
1426
          case SDL_JOYBUTTONUP:
 
1427
            oeskey = keymarkers.joy1 + event.jbutton.button;
 
1428
            binding = oeskeymap_get(&oeskeymap, oeskey);
 
1429
            if (binding)
 
1430
                binding(0);
 
1431
            break;
 
1432
          case SDL_QUIT:
 
1433
            Game.GameOverReason = OESREASON_QUIT;
 
1434
            return 1;
 
1435
            break;
 
1436
          default:
 
1437
            break;
 
1438
        } //switch event.type
 
1439
    } //while SDL_PollEvent
 
1440
 
 
1441
  if (Game.GameState == OESGAME_PAUSED)
 
1442
    {  /* Don't hog CPU when paused. */
 
1443
      SDL_Delay(100);
 
1444
    }
 
1445
  return 0;
 
1446
}
 
1447
 
 
1448
 
 
1449
/* Main game stub. */
 
1450
int
 
1451
oes_game ()
 
1452
{
 
1453
  int tick;
 
1454
 
 
1455
  oesjoy.time = Game.LastTick;
 
1456
  Game.GameStartTick = SDL_GetTicks();
 
1457
  Game.LastTick = Game.GameStartTick;
 
1458
  sniperbgm_stimulate(Game.BGM);
 
1459
  Game.GameOverReason = OESREASON_NONE;
 
1460
 
 
1461
  oes_game_grab(1);
 
1462
  while (Game.GameOverReason == OESREASON_NONE)
 
1463
    {
 
1464
      tick = SDL_GetTicks();
 
1465
      switch (Game.GameState)
 
1466
        {
 
1467
          case OESGAME_CHAOS:
 
1468
            oes_game_init(&Game);
 
1469
            sniperbgm_stimulate(Game.BGM);
 
1470
            Game.GameState = OESGAME_PLAY;
 
1471
            break;
 
1472
          case OESGAME_PLAY:
 
1473
            oes_reindeer();
 
1474
            break;
 
1475
          case OESGAME_PAUSED:
 
1476
            Game.LastTick = tick;
 
1477
            break;
 
1478
          case OESGAME_UNPAUSED:
 
1479
            oes_game_pause(0);
 
1480
            break;
 
1481
          default:
 
1482
            Game.GameState = OESGAME_CHAOS;
 
1483
            break;
 
1484
        }
 
1485
            
 
1486
      /* SDL events. */
 
1487
      oes_game_events();
 
1488
      /* joystick-interval handling. */
 
1489
      oes_game_joystick(tick);
 
1490
    }
 
1491
  Game.GameOverTicks = SDL_GetTicks();
 
1492
  oes_game_grab(0);
 
1493
  sniperbgm_depress(Game.BGM);
 
1494
  Game.GameState = OESGAME_CHAOS;
 
1495
 
 
1496
  if (Game.GameOverReason == OESREASON_QUIT)
 
1497
      return 0;
 
1498
  return 1;
 
1499
}
 
1500
 
 
1501
 
 
1502
/* Launche web browser to point to a URI. */
 
1503
int
 
1504
oes_web (const char *uri)
 
1505
{
 
1506
  char cmd[256];
 
1507
 
 
1508
/* Don't check URI protocol.  Assume browser understands all. */
 
1509
  oes_game_hide(1);
 
1510
  snprintf(cmd, sizeof(cmd), "%s \"%s\"", gPrefs.wwwbrowser, uri);
 
1511
  return system(cmd);
 
1512
}
 
1513
 
 
1514
 
 
1515
/* Widget signal fallback (unhandled/unblocked widget signals) */
 
1516
//int oes_uisignal (oesui_t *gui, const char *signame)
 
1517
int
 
1518
oes_uisignal (oesui_t *gui, oesui_signal_t *sig)
 
1519
{
 
1520
  const char *signame;
 
1521
  SDL_Rect r;
 
1522
 
 
1523
  signame = UISIG_NAME(sig);
 
1524
  if (0);
 
1525
  else if (0 == strcmp(signame, "start-game"))
 
1526
    {
 
1527
      oesui_event(gui, OESUI_CLOSE, 0);
 
1528
      if (oes_game())
 
1529
          oesui_open(gui, "gameover");
 
1530
      else
 
1531
          gui->retcode = 1;
 
1532
      return 1;
 
1533
    }
 
1534
  else if (0 == strcmp(signame, "go-main"))
 
1535
    {
 
1536
      oesui_open(gui, "main");
 
1537
      return 1;
 
1538
    }
 
1539
  else if (0 == strcmp(signame, "go-prefs"))
 
1540
    {
 
1541
      oesui_open(gui, "prefs");
 
1542
      return 1;
 
1543
    }
 
1544
  else if (0 == strcmp(signame, "go-scores"))
 
1545
    {
 
1546
      oesui_open(gui, "highscores");
 
1547
      return 1;
 
1548
    }
 
1549
  else if (0 == strcmp(signame, "frob-fullscreen"))
 
1550
    {
 
1551
      oes_bind_fullscreen(0);
 
1552
      oesui_event(gui, OESUI_UPDATE, 0);
 
1553
      return 1;
 
1554
    }
 
1555
  else if (0 == strcmp(signame, "frob-audio"))
 
1556
    {
 
1557
      gPrefs.audio = !gPrefs.audio;
 
1558
      oesui_event(gui, OESUI_UPDATE, 0);
 
1559
      return 1;
 
1560
    }
 
1561
  else if (0 == strcmp(signame, "frob-skill"))
 
1562
    {
 
1563
      gPrefs.difficulty++;
 
1564
      if (gPrefs.difficulty > 3)
 
1565
          gPrefs.difficulty = 1;
 
1566
      oesui_event(gui, OESUI_UPDATE, 0);
 
1567
      return 1;
 
1568
    }
 
1569
  else if (0 == strcmp(signame, "highscores"))
 
1570
    {
 
1571
      r.x = UISIG_ARG(sig, 1).i;
 
1572
      r.y = UISIG_ARG(sig, 2).i;
 
1573
      r.w = UISIG_ARG(sig, 3).i;
 
1574
      r.h = UISIG_ARG(sig, 4).i;
 
1575
      draw_hiscores(gui->screen, &r);
 
1576
    }
 
1577
  else if (0 == strcmp(signame, "gameover"))
 
1578
    {
 
1579
      r.x = UISIG_ARG(sig, 1).i;
 
1580
      r.y = UISIG_ARG(sig, 2).i;
 
1581
      r.w = UISIG_ARG(sig, 3).i;
 
1582
      r.h = UISIG_ARG(sig, 4).i;
 
1583
      draw_gameover(gui->screen, &r);
 
1584
    }
 
1585
  else if (0 == strcmp(signame, "quit"))
 
1586
    {
 
1587
      gui->retcode = 1;
 
1588
      return 1;
 
1589
    }
 
1590
  else if (0 == strcmp(signame, "url-oes"))
 
1591
    {
 
1592
#define WEBBROWSER mozilla
 
1593
      /* http://www.icculus.org/oes/ */
 
1594
      oes_web("http://www.icculus.org/oes/");
 
1595
    }
 
1596
  else if (0 == strcmp(signame, "url-os"))
 
1597
    {
 
1598
      /* http://www.iki.fi/sol/ */
 
1599
      oes_web("http://www.iki.fi/sol/");
 
1600
    }
 
1601
  else if (0 == strcmp(signame, "url-td"))
 
1602
    {
 
1603
      /* http://www.timedoctor.org/ */
 
1604
      oes_web("http://www.timedoctor.org/");
 
1605
    }
 
1606
  else if (0 == strcmp(signame, "url-io"))
 
1607
    {
 
1608
      /* http://www.icculus.org/ */
 
1609
      oes_web("http://www.icculus.org/");
 
1610
    }
 
1611
  else if (0 == strcmp(signame, "url-ov"))
 
1612
    {
 
1613
      /* http://www.vorbis.com/ */
 
1614
      oes_web("http://www.vorbis.com/");
 
1615
    }
 
1616
  return 0;
 
1617
}
 
1618
 
 
1619
 
 
1620
int
 
1621
oes_binds_init ()
 
1622
{
 
1623
/* TODO: bind map */
 
1624
/* sane joystick defaults. */
 
1625
    oesjoy.style = 0;
 
1626
    oesjoy.scale = 10.0f;
 
1627
    oesjoy.interval = 20;
 
1628
#if 0
 
1629
    oesjoy.axis[0] = oes_bind_jhoriz;
 
1630
    oesjoy.axis[1] = oes_bind_jvert;
 
1631
    oesjoy.axis[2] = oes_bind_jdeep;
 
1632
    oesjoy.button[0] = oes_bind_fire;
 
1633
    oesjoy.button[1] = oes_bind_zoom;
 
1634
    oesjoy.button[2] = oes_bind_zoomout;
 
1635
    oesjoy.button[3] = oes_bind_zoomin;
 
1636
#endif /* 0 */
 
1637
 
 
1638
  oeskeymap_init(&oeskeymap);
 
1639
  oeskeymap_load(&oeskeymap, gPrefs.bindpath);
 
1640
//  oeskeymap_set(&oeskeymap, SDLK_a, oes_bind_fire); //test
 
1641
  oeskeymap_set(&oeskeymap, SDLK_v, oes_bind_verbosity, 1);
 
1642
  oeskeymap_set(&oeskeymap, SDLK_p, oes_bind_pause, 1);
 
1643
  oeskeymap_set(&oeskeymap, SDLK_s, oes_bind_screenshot, 1);
 
1644
  oeskeymap_set(&oeskeymap, SDLK_ESCAPE, oes_bind_abandon, 1);
 
1645
  oeskeymap_set(&oeskeymap, oeskeymap_resolve("MOUSEX"), oes_bind_mhoriz, 1);
 
1646
  oeskeymap_set(&oeskeymap, oeskeymap_resolve("MOUSEY"), oes_bind_mvert, 1);
 
1647
  oeskeymap_set(&oeskeymap, oeskeymap_resolve("MOUSE1"), oes_bind_fire, 1);
 
1648
  oeskeymap_set(&oeskeymap, oeskeymap_resolve("MOUSE2"), oes_bind_zoom, 1);
 
1649
  oeskeymap_set(&oeskeymap, oeskeymap_resolve("MOUSE4"), oes_bind_zoomin, 1);
 
1650
  oeskeymap_set(&oeskeymap, oeskeymap_resolve("MOUSE5"), oes_bind_zoomout, 1);
 
1651
  oeskeymap_set(&oeskeymap, oeskeymap_resolve("JOY1"), oes_bind_fire, 1);
 
1652
  oeskeymap_set(&oeskeymap, oeskeymap_resolve("JOY2"), oes_bind_zoom, 1);
 
1653
  oeskeymap_set(&oeskeymap, oeskeymap_resolve("JOY3"), oes_bind_zoomin, 1);
 
1654
  oeskeymap_set(&oeskeymap, oeskeymap_resolve("JOY4"), oes_bind_zoomout, 1);
 
1655
  oeskeymap_set(&oeskeymap, oeskeymap_resolve("AXIS1"), oes_bind_jhoriz, 10);
 
1656
  oeskeymap_set(&oeskeymap, oeskeymap_resolve("AXIS2"), oes_bind_jvert, 10);
 
1657
  oeskeymap_set(&oeskeymap, oeskeymap_resolve("AXIS3"), oes_bind_jdeep, 10);
 
1658
  keymarkers.mousex = oeskeymap_resolve("MOUSEX");
 
1659
  keymarkers.mousey = oeskeymap_resolve("MOUSEY");
 
1660
  keymarkers.mouse0 = oeskeymap_resolve("MOUSE0");
 
1661
  keymarkers.axis1 = oeskeymap_resolve("AXIS1");
 
1662
  keymarkers.joy1 = oeskeymap_resolve("JOY1");
 
1663
 
 
1664
  return 0;
 
1665
}
 
1666
 
 
1667
 
 
1668
int main(int argc, char *argv[])
 
1669
{
 
1670
    oesui_t *gui;
 
1671
 
 
1672
    srand(SDL_GetTicks());
 
1673
   
 
1674
    /*
 
1675
    Game.mediaPath = (char*)calloc(strlen(argv[0]), sizeof(char));
 
1676
//   invocation = (char*)malloc(strlen(argv[0]) + 1); memcpy(invocation, argv[0], strlen(argv[0]));
 
1677
    invocation = strdup(argv[0]);
 
1678
    sprintf(Game.mediaPath, "%s", dirname(invocation));
 
1679
    free(invocation);
 
1680
    */
 
1681
    Game.mediaPath = strdup(GAMEDATADIR);
 
1682
    invocation = argv[0];
 
1683
 
 
1684
    /* Load Preferences. */
 
1685
    prefs_init(&gPrefs);
 
1686
    prefs_load(&gPrefs);
 
1687
    Game.verbosity = gPrefs.verbose;
 
1688
 
 
1689
    /* Parse options, which may override saved preferences. */
 
1690
    parse_args(argc, argv);
 
1691
 
 
1692
    oes_binds_init();
 
1693
    oes_setup ();  /* prefs initialized in here */
 
1694
 
 
1695
 
 
1696
    gui = oesui_init_surface(NULL, Game.Screen);  /* initialise gui */
 
1697
    oesui_load(gui, "menus.cfg");  /* Load gui data */
 
1698
    oesui_sighandle(gui, oes_uisignal);  /* widget signal handler */
 
1699
    oesui_open(gui, "main");  /* Main menu */
 
1700
    oesui_loop(gui);  /* Main UI loop */
 
1701
 
 
1702
 
 
1703
    oes_teardown ();
 
1704
//    delete[] mediaPath;
 
1705
    free(Game.mediaPath);
 
1706
 
 
1707
//    oes_audio_close();
 
1708
    return 0;
 
1709
}
 
1710
 
 
1711
 
 
1712
void configure_difficulty()
 
1713
{
 
1714
    gPrefs.difficulty = (gPrefs.difficulty < 1 ? 1 : gPrefs.difficulty);
 
1715
    gPrefs.difficulty = (gPrefs.difficulty > 3 ? 3 : gPrefs.difficulty);
 
1716
    switch (gPrefs.difficulty)
 
1717
        {
 
1718
        case 1:
 
1719
            Game.ReloadTime = 1500;
 
1720
            Game.ScoreMod = 1.5;
 
1721
            break;
 
1722
        case 2:
 
1723
            Game.ReloadTime = 3000;
 
1724
            Game.ScoreMod = 1.0;
 
1725
            break;
 
1726
        case 3:
 
1727
            Game.ReloadTime = 4000;
 
1728
            Game.ScoreMod = 0.5;
 
1729
            break;
 
1730
        }
 
1731
}
 
1732
 
 
1733
#if 0
 
1734
void draw_button (SDL_Surface *b, int x, int y)
 
1735
{
 
1736
    SDL_Rect d;
 
1737
 
 
1738
    d.x = x;
 
1739
    d.y = y;
 
1740
    d.h = 32;
 
1741
    d.w = 196;
 
1742
 
 
1743
    SDL_BlitSurface (b, NULL, Game.Screen, &d);
 
1744
}
 
1745
#endif /* 0 */
 
1746
 
 
1747
SDL_Surface *oes_load_img (const char *path)
 
1748
{
 
1749
    SDL_Surface *sfc = NULL;
 
1750
    char lpath[PATH_MAX];
 
1751
    snprintf (lpath, PATH_MAX, "%s/%s", Game.mediaPath, path);
 
1752
    sfc = IMG_Load (lpath);
 
1753
    if (!sfc) {
 
1754
        fprintf(stderr,"Unable to load image '%s': %s\n",lpath,SDL_GetError());
 
1755
        exit (1);
 
1756
    }
 
1757
    return sfc;
 
1758
}
 
1759
 
 
1760
#if 0
 
1761
bool hovering (int x, int y, int w, int h)
 
1762
{
 
1763
    int lx, ly;
 
1764
    SDL_GetMouseState (&lx, &ly);
 
1765
    if ((lx > x) && (ly > y) &&
 
1766
        (lx < x + w) && (ly < y + h))
 
1767
        return true;
 
1768
    return false;
 
1769
}
 
1770
#endif /* 0 */