Annotation of froggix/src/froggix.c, revision 1.6
1.1 nick 1: /*
2: * Froggix
3: *
4: * Nicholas DeClario 2009
5: * <nick@declario.com>
6: *
7: * This program is distributed under the GNU Public License
8: * <Insert GNU license blurb here>
9: */
10:
11:
12: /*
13: * Our pretty standard includes
14: */
15: #include <stdio.h>
16: #include <stdlib.h>
17: #include <unistd.h>
18: #include <time.h>
19:
20: #include <SDL.h>
21: #include <SDL_mixer.h>
22: #include <SDL_image.h>
23: #include <SDL_ttf.h>
24:
25: /*
26: * Set some basic definitions
27: */
1.6 ! nick 28: #define VER "$Id: froggix.c,v 1.5 2009-04-11 13:01:54 nick Exp $"
1.1 nick 29: #define TITLE "Froggix"
30: #define SCREEN_WIDTH 640
31: #define SCREEN_HEIGHT 480
32: #define FALSE 0
33: #define TRUE 1
34: #define LIVES 3
35: #define COLORKEY 255, 0, 255
36: #define BGCOLOR 0, 0, 0
37: #define FROGGER_START_X 290
38: #define FROGGER_START_Y 425
39: #define UP 1
40: #define DOWN 2
41: #define LEFT 3
42: #define RIGHT 4
43: #define X 0
44: #define Y 1
45: #define FRAME 24
46: #define HFRAME 12
47: #define HOP_DISTANCE 30
48: #define HOP_SPEED 3
49: #define ROW_BASE 425
50: #define LEFT_SIDE 115
51: #define RIGHT_SIDE 525
52: #define SPLASH 1 /* Death types */
53: #define SPLAT 2
54:
55: /* Point table */
56: #define SCORE_HOP 10
57: #define SCORE_GOAL 50
58: #define SCORE_LEVEL 1000
59: #define SCORE_FLY 150
60: #define SCORE_PINK 200
61: #define SCORE_SECONDS 10
62: #define HIGH_SCORE 4630
1.4 nick 63: #define SCORE_FREE_FROG 2000
1.1 nick 64:
65: /* The green game timer */
66: #define MAX_TIMER 350
67: #define TIMER_SIZE 150
68: #define TIMER_COLOR 32, 211, 0
69: #define TIMER_LOW_COLOR 255, 0, 0
1.3 nick 70: #define FLY_MAX_TIME 50
1.4 nick 71: #define GATOR_MAX_TIME 70
1.1 nick 72:
73: /* baddies */
74: #define VEHICLE 0
75: #define LOG 1
76: #define TURTLE 2
77: #define GATOR 3
78: #define SNAKE 4
79: #define BEAVER 5
80:
81: /* Goal areas */
82: #define MAX_GOALS 5
83:
84: /* logs */
85: #define SHORT_LOG 4
86: #define MEDIUM_LOG 6
87: #define LONG_LOG 9
88: #define MAX_WOOD 7
89:
90: /* Turtles */
91: #define DIVE_START_TIME 50
92: #define DIVE_PHASE_TIME 20
93: #define MAX_TURTLES 9
94: #define TURTLE_ANIM_TIME 5
95:
96: /* Vehicles */
97: #define MAX_VEHICLES 40
98:
99:
100: /*
101: * Froggers dstruct
102: */
103: typedef struct {
104: int placement[2];
105: int oldPlacement[2];
106: int direction;
107: int location;
108: int hopCount;
109: int currentRow;
110: int alive;
111: int riding;
112: int ridingIdx;
113: int ridingType;
114: int frogger; /* Are we frogger or bonus frog */
115: int deathType;
116: int deathCount;
117:
118: SDL_Rect src;
119: SDL_Rect dst;
120:
121: Mix_Chunk *s_hop;
122: Mix_Chunk *s_squash;
123: Mix_Chunk *s_splash;
124: Mix_Chunk *s_extra;
125: } froggerObj;
126:
127: /*
128: * Goals
129: */
130: typedef struct {
131: int x, y, w, h;
132: int occupied;
133: int fly;
134: int gator;
135: } goalObj;
136:
137: /*
138: * Vehicles
139: */
140: typedef struct {
141: int placement[2];
142: int oldPlacement[2];
143: int direction; // LEFT or RIGHT
144: int row; // row
145: int speed; // How fast are we traveling
146: int level; // Must be >= this level to display
147:
148: SDL_Rect src;
149: } vehicleObj;
150:
151: /*
152: * It's Log!
153: */
154: typedef struct {
155: int placement[2];
156: int oldPlacement[2];
157: int row; /* Current row we are in */
158: int type; /* SHORT, MEDIUM, or LONG */
159: int speed; /* What speed does the log move at */
160: int hasPink; // Is bonus frog riding
1.4 nick 161: int isGator; /* Are we a gator? if > 1 we have an open mouth */
1.1 nick 162:
163: SDL_Rect src;
164: } logObj;
165:
166: /*
167: * Turtles
168: */
169: typedef struct {
170: int placement[2];
171: int oldPlacement[2];
172: int row; /* Which row are the turtles in? */
173: int count; /* How many turtles in this group? */
174: int speed; /* How fast are they swimming */
175: int canDive; /* Can this group dive */
176: int diveStep; /* If they can dive, what diving step are then in */
177: int diveTime; /* Current dive time */
178: int animStep; /* Current animation frame */
179: int animDelay; /* The number of ticks to wait between frames */
180:
181: SDL_Rect src;
182: } turtleObj;
183:
184: int keyEvents( SDL_Event event );
185: int mySDLInit( void );
186: void beginGame( void );
187: int loadMedia( void );
188: int heartbeat( void );
189: int updateGameState( void );
1.4 nick 190: void checkFly( void );
191: void checkGator( void );
1.1 nick 192: void configGameScreen( void );
193: void drawGameScreen( void );
194: void drawBackground( void );
195: int getRowPixel ( int row );
196: int collisionRow ( void );
197: int freeFrog( int score );
198: int collideFrogger ( int x, int y, int h, int w );
199: void checkFroggerBorder( void );
200: void levelUp( void );
201: int checkGoals( void );
202: void froggerReset( void );
203: logObj setWood( int type, int speed, int row, int startX );
204: turtleObj setTurtle( int dive, int diveTimer, int speed, int row, int startX, int count );
205: vehicleObj setVehicle( int row, int startX, int speed, int level );
206: goalObj setGoal( int x, int y, int w, int h );
207: void moveFrogger( void );
208: void ridingFrogger( );
209: void drawTitleScreen( void );
210: void drawPauseScreen( void );
211: void drawGameOver( void );
212: int drawDeathSequence( int deathType );
213: int checkTimer( void );
214: void drawScore( int high, int score );
215: void drawNumbers( int num, int x, int y );
216: void drawGoals( void );
217: void drawTimer( int length );
218: void drawLives( int lives );
219: void drawLevel( int level );
220: void drawWood( void );
221: void drawTurtles( void );
222: void drawVehicles( void );
223: void drawImage(SDL_Surface *srcimg, int sx, int sy, int sw, int sh, SDL_Surface *dstimg, int dx, int dy, int alpha );
224: void playSound( Mix_Chunk *sound );
225: void setFullScreenMode( void );
226:
1.3 nick 227: int flyTimer = 0;
1.4 nick 228: int gatorTimer = 0;
1.1 nick 229: int level = 0;
230: int playing = 0;
231: int lives = 0;
232: int players = 0;
233: int score = 0;
234: int givenFreeFrog = 0;
235: int hScore = HIGH_SCORE;
236: int redraw_all = 0;
237: int fullscreen = 0;
238: int drawBG = 0;
239: int goDelay;
240: float timeLeft;
241: froggerObj frogger;
242: logObj wood[MAX_WOOD];
243: turtleObj turtle[MAX_TURTLES];
244: vehicleObj vehicle[MAX_VEHICLES];
245: goalObj goals[MAX_GOALS];
246:
247: Mix_Chunk *s_freeFrog;
248: SDL_Surface *gfx;
249: SDL_Surface *background; // This is the frogger back drop
250: SDL_Rect backgroundRect;
251: SDL_Surface *titleSurface; // Title 'Froggix' image
252: SDL_Surface *screen; //This pointer will reference the backbuffer
253: SDL_Rect leftBorderRect;
254: SDL_Rect rightBorderRect;
255: TTF_Font *font;
256:
257: int debugBorder = 0;
258:
259: /*
260: * int mySDLInit(void);
261: *
262: * This starts the basic SDL initialization for everything we'll need
263: *
264: */
265: int mySDLInit( void ) {
266: int result = 1;
267:
268: if( SDL_Init( SDL_INIT_VIDEO ) != 0 ) {
269: fprintf( stderr, "Warning: Unable to initialize video: %s\n", SDL_GetError( ) );
270: result--;
271: }
272:
273: if( TTF_Init( ) == -1 ) {
274: fprintf( stderr, "Warning: Unable to initialize font engine: %s\n", TTF_GetError( ) );
275: result--;
276: }
277:
278: if( SDL_Init( SDL_INIT_AUDIO ) != 0 ) {
279: fprintf( stderr, "Warning: Unable to initialize audio: %s\n", SDL_GetError( ) );
280: result--;
281: }
282:
283: if( Mix_OpenAudio( 11025, AUDIO_S16, 2, 512 ) < 0 ) {
284: fprintf( stderr, "Warning: Audio set failed: %s\n", SDL_GetError( ) );
285: result--;
286: }
287:
288: screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, 16, SDL_HWSURFACE );
289:
290: if ( screen == NULL ) {
291: fprintf( stderr, "Error: Unable to set video mode: %s\n", SDL_GetError( ) );
292: result--;
293: }
294:
295: SDL_WM_SetCaption( TITLE, NULL );
296:
297: return result;
298: }
299:
300: /*
301: * void beginGame( void );
302: *
303: * Main game routine
304: */
305: void beginGame( void ) {
306: float next_heartbeat = 0;
307: SDL_Event event;
308: int done = 0;
309:
310: printf ( "D: Starting main game loop\n" );
311:
312: if ( loadMedia( ) <= 0 ) {
313: fprintf( stderr, "Error: Failed to load graphics and audio!\n" );
314: return;
315: }
316:
317: drawBackground( );
318:
319: while( ! done ) {
320: while( SDL_PollEvent( &event ) ) {
321: done = keyEvents( event );
322: }
323:
324: /* Check the heartbeat to see if we're ready */
325: if ( SDL_GetTicks( ) >= next_heartbeat ) {
326: next_heartbeat = SDL_GetTicks( ) + heartbeat( );
327: }
328: SDL_Delay( 30 );
329: }
330:
331: SDL_FreeSurface( gfx );
332: }
333:
334: int loadMedia( void ) {
335: int result = 1;
336:
337: /*
338: * Load frogger's textures and sounds
339: */
340: gfx = IMG_Load( "images/frogger.png" );
341: if ( gfx == NULL ) {
342: fprintf( stderr, "Error: 'images/frogger.bmp' could not be open: %s\n", SDL_GetError( ) );
343: result--;
344: }
345:
346: if ( SDL_SetColorKey( gfx, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB( gfx->format, COLORKEY ) ) == -1 )
347: fprintf( stderr, "Warning: colorkey will not be used, reason: %s\n", SDL_GetError( ) );
348:
349: background = IMG_Load( "images/gameboard.png" );
350:
351: if ( gfx == NULL ) {
352: fprintf( stderr, "Error: 'images/gameboard.png' could not be open: %s\n", SDL_GetError( ) );
353: result--;
354: }
355:
356: titleSurface = IMG_Load( "images/froggix-title.png" );
357: if ( titleSurface == NULL ) {
358: fprintf( stderr, "Error: 'images/froggix-title.png' could not be open: %s\n", SDL_GetError( ) );
359: result--;
360: }
361:
362: font = TTF_OpenFont( "fonts/CourierNew-Bold.ttf", 22 );
363: if ( font == NULL ) {
364: printf( "TTF_OpenFont: %s\n", TTF_GetError( ) );
365: result--;
366: }
367:
368: frogger.s_hop = Mix_LoadWAV( "sounds/froggix-hop.wav" );
369:
370: if ( frogger.s_hop == NULL )
371: fprintf( stderr, "Warning: dp_frogger_hop.wav could not be opened: %s\n", SDL_GetError( ) );
372:
373: frogger.s_squash = Mix_LoadWAV( "sounds/dp_frogger_squash.wav" );
374: if ( frogger.s_squash == NULL )
375: fprintf( stderr, "Warning: dp_frogger_plunk could not be opened %s\n", SDL_GetError( ));
376:
377: frogger.s_splash = Mix_LoadWAV( "sounds/dp_frogger_plunk.wav" );
378: if ( frogger.s_splash == NULL )
379: fprintf( stderr, "Warning: dp_frogger_splash could not be opened %s\n", SDL_GetError( ));
380:
381: s_freeFrog = Mix_LoadWAV( "sounds/dp_frogger_extra.wav" );
382: if ( s_freeFrog == NULL )
383: fprintf( stderr, "Warning: dp_frogger_extra could not be opened %s\n", SDL_GetError( ));
384:
385: return result;
386: }
387:
388: /*
389: * void keyEvents( void );
390: *
391: * Process the incoming keyboard and mouse events
392: *
393: */
394: int keyEvents( SDL_Event event ) {
395: int done = 0;
396:
397: /* Always check for shutdown */
398: switch( event.type ) {
399: case SDL_QUIT:
400: done = 1;
401: break;
402: case SDL_KEYDOWN:
403: /* printf( "Found key: %i\n", event.key.keysym.sym );*/
404: switch( event.key.keysym.sym ) {
405: case SDLK_ESCAPE:
406: done = 1;
407: break;
408: case 102:
409: setFullScreenMode( );
410: break;
411: default:
412: break;
413: }
414: break;
415: default:
416: break;
417: }
418: /* We are playing the game */
419: if ( level ) {
420: /* Main game playing input */
421: if ( playing ) {
422: if ( event.type == SDL_KEYDOWN && frogger.alive ) {
423: switch( event.key.keysym.sym ) {
424: case SDLK_UP:
425: if ( ! frogger.direction ) {
426: frogger.hopCount = 0;
427: frogger.direction = UP;
428: frogger.currentRow++;
429: playSound( frogger.s_hop );
430: }
431: break;
432: case SDLK_DOWN:
433: if ( ! frogger.direction ) {
434: frogger.hopCount = 0;
435: frogger.direction = DOWN;
436: frogger.currentRow--;
437: playSound( frogger.s_hop );
438: }
439: break;
440: case SDLK_LEFT:
441: if ( ! frogger.direction ) {
442: frogger.hopCount = 0;
443: frogger.direction = LEFT;
444: playSound( frogger.s_hop );
445: }
446: break;
447: case SDLK_RIGHT:
448: if ( ! frogger.direction ) {
449: frogger.hopCount = 0;
450: frogger.direction = RIGHT;
451: playSound( frogger.s_hop );
452: }
453: break;
454: case 108:
455: levelUp( );
456: fprintf( stderr, "Increase level to %i.\n", level );
457: break;
458: default:
459: break;
460: }
1.3 nick 461: /* Uncomment for positioning debug information
1.1 nick 462: printf( "x,y,d => %i,%i,%i,%i\n", frogger.placement[X],
463: frogger.placement[Y],
464: frogger.direction,
465: frogger.currentRow );
1.3 nick 466: */
1.1 nick 467: }
468: /* Game over man, game over! */
469: if ( ! lives ) {
470:
471: }
472: }
473: /* we're at the pause screen */
474: else {
475:
476: }
477: }
478: /* Main intro screen input */
479: else {
480: if ( event.type == SDL_KEYUP ) {
481: switch( event.key.keysym.sym ) {
482: case SDLK_ESCAPE:
483: done = 1;
484: break;
485: case SDLK_1:
486: printf( "D: Starting single player game\n" );
487: level = 1;
488: lives = LIVES;
489: playing = TRUE;
490: score = 0;
491: players = 1;
492: redraw_all = 1;
493: break;
494: default:
495: break;
496: }
497: }
498: }
499:
500: return done;
501: }
502:
503: int updateGameState( void ) {
1.2 nick 504: int i;
505:
1.1 nick 506: if ( ! drawBG ) configGameScreen( );
507:
508: if ( lives <= 0 ) {
509: goDelay++;
510: drawGameOver( );
511: /* Display game over screen for 50 ticks before returning
512: * to the main screen */
513: if ( goDelay > 7 ) {
514: playing = 0;
515: lives = 0;
516: level = 0;
1.2 nick 517: score = 0;
518: givenFreeFrog = 0;
519: drawBG = 0;
520: for ( i = 0; i < MAX_GOALS; i++ ) { goals[i].occupied = 0; }
521:
1.1 nick 522: }
523: return 500;
524: }
525:
526: drawGameScreen( );
527:
528: return 50;
529: }
530:
531: logObj setWood( int type, int speed, int row, int startX ) {
532: logObj tempWood;
533: int imgPixelSrc = 0;
534:
535: switch( type ) {
536: case LONG_LOG:
537: imgPixelSrc = 0;
538: break;
539: case MEDIUM_LOG:
540: imgPixelSrc = FRAME * LONG_LOG;
541: break;
542: case SHORT_LOG:
543: imgPixelSrc = FRAME * ( LONG_LOG + MEDIUM_LOG );
544: break;
545: }
546:
547: tempWood.row = row;
548: tempWood.type = type;
549: tempWood.speed = speed;
550: tempWood.hasPink = 0;
551: tempWood.placement[X] = LEFT_SIDE + startX;
552: tempWood.placement[Y] = getRowPixel( row );
553: tempWood.oldPlacement[X] = LEFT_SIDE + startX;
554: tempWood.oldPlacement[Y] = getRowPixel( row );
555: tempWood.src.y = FRAME;
556: tempWood.src.x = imgPixelSrc;
557: tempWood.src.w = FRAME * tempWood.type;
558: tempWood.src.h = FRAME;
1.4 nick 559: tempWood.isGator = 0;
1.1 nick 560:
561: return tempWood;
562: }
563:
564: turtleObj setTurtle( int dive, int diveTimer, int speed, int row, int startX, int count ) {
565: turtleObj tt;
566:
567: tt.row = row;
568: tt.canDive = dive;
569: tt.diveStep = 0;
570: tt.diveTime = diveTimer;
571: tt.animStep = 0;
572: tt.animDelay = 0;
573: tt.speed = speed;
574: tt.count = count;
575: tt.placement[X] = LEFT_SIDE + startX;
576: tt.placement[Y] = getRowPixel( row );
577: tt.oldPlacement[X] = tt.placement[X];
578: tt.oldPlacement[Y] = tt.placement[Y];
579: tt.src.y = FRAME * 2;
580: tt.src.x = 0;
581: tt.src.w = FRAME;
582: tt.src.h = FRAME;
583:
584: return tt;
585: }
586:
587:
588: vehicleObj setVehicle( int row, int startX, int speed, int level ) {
589: vehicleObj v;
590:
591: v.direction = ( row % 2 ) ? LEFT : RIGHT; /* Odd rows travel left, evens go right */
592: v.row = row;
593: v.speed = speed;
594: v.level = level;
595: v.placement[X] = LEFT_SIDE + startX;
596: v.placement[Y] = getRowPixel( row );
597: v.oldPlacement[X] = v.placement[X];
598: v.oldPlacement[Y] = v.placement[Y];
599: v.src.y = FRAME * 2;
600: v.src.x = FRAME * ( 4 + row );
601: v.src.w = ( row == 5 ) ? FRAME * 2 : FRAME; /* Are we a truck? */
602: v.src.h = FRAME;
603:
604: return v;
605: }
606:
607: goalObj setGoals( int x, int y, int w, int h ) {
608: goalObj g;
609:
610: g.x = x;
611: g.y = y;
612: g.w = w;
613: g.h = h;
614: g.occupied = 0;
615: g.fly = 0;
616: g.gator = 0;
617:
618: return g;
619: }
620:
621: void configGameScreen( void ) {
622: drawBG = 1;
623:
624: /*
625: * Draw background map
626: */
627: //drawBackground( );
628: drawImage( background, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, screen, 0, 0, 255 );
629:
630: /* Cars drive on rows 1 - 5
631: * Logs are on rows 8, 9 and 11, 8 = short, 9 long, 11 medium
632: * Turtles are on rows 7, 10
633: * Frogger starts on Row 0,
634: * Sidewalk is row 6
635: * and the goal is row 12
636: */
637:
638: /* I MUST figure out a better way to handle the logs, turtles and cars */
639:
640: /* Set up the LONG logs on row 9 first */
641: wood[0] = setWood( LONG_LOG, 3, 9, 0 );
642: wood[1] = setWood( LONG_LOG, 3, 9, 305 );
643: wood[2] = setWood( SHORT_LOG, 2, 8, 25 );
644: wood[3] = setWood( SHORT_LOG, 2, 8, 160 );
645: wood[4] = setWood( SHORT_LOG, 2, 8, 380 );
646: wood[5] = setWood( MEDIUM_LOG, 4, 11, 140 );
647: wood[6] = setWood( MEDIUM_LOG, 4, 11, 440 );
648:
649: drawWood( );
650:
651: /* Configure our turtles */
652: turtle[0] = setTurtle( FALSE, 0, 1, 7, 0, 3 );
653: turtle[1] = setTurtle( TRUE, 0, 1, 7, 125, 3 );
654: turtle[2] = setTurtle( FALSE, 0, 1, 7, 250, 3 );
655: turtle[3] = setTurtle( TRUE, 30, 1, 7, 375, 3 );
656: turtle[4] = setTurtle( FALSE, 0, 2, 10, 100, 2 );
657: turtle[5] = setTurtle( TRUE, 50, 2, 10, 200, 2 );
658: turtle[6] = setTurtle( FALSE, 0, 2, 10, 300, 2 );
659: turtle[7] = setTurtle( TRUE, 10, 2, 10, 400, 2 );
660: turtle[8] = setTurtle( FALSE, 0, 2, 10, 500, 2 );
661:
662: drawTurtles( );
663:
664: /* Configure vehicles */
665: /* row, X, speed */
666: /* Row 1 -- yellow car */
667: vehicle[0] = setVehicle( 1, 0, 1, 1 );
668: vehicle[1] = setVehicle( 1, 100, 1, 3 );
669: vehicle[2] = setVehicle( 1, 200, 1, 1 );
670: vehicle[3] = setVehicle( 1, 300, 1, 1 );
671: // /* Row 2 -- tractor */
672: vehicle[4] = setVehicle( 2, 0, 3, 1 );
673: vehicle[5] = setVehicle( 2, 100, 3, 2 );
674: vehicle[6] = setVehicle( 2, 200, 3, 1 );
675: vehicle[7] = setVehicle( 2, 300, 3, 3 );
676: // /* Row 3 -- pink car */
677: vehicle[8] = setVehicle( 3, 75, 2,1 );
678: vehicle[9] = setVehicle( 3, 150, 2, 3 );
679: vehicle[10] = setVehicle( 3, 225, 2, 1 );
680: vehicle[11] = setVehicle( 3, 375, 2, 2 );
681: // /* Row 4 -- white car */
682: vehicle[12] = setVehicle( 4, 75, 5, 1 );
683: vehicle[13] = setVehicle( 4, 150, 5, 3 );
684: vehicle[14] = setVehicle( 4, 225, 5, 2 );
685: vehicle[15] = setVehicle( 4, 375, 5, 3 );
686: // /* Row 5 -- Trucks */
687: vehicle[16] = setVehicle( 5, 30, 3, 1 );
688: vehicle[17] = setVehicle( 5, 150, 3, 1 );
689: vehicle[18] = setVehicle( 5, 250, 3, 1 );
690: vehicle[19] = setVehicle( 5, 350, 3, 3 );
691:
692: drawVehicles( );
693:
694: /* Configure the goals for frogger */
695: goals[0] = setGoals( LEFT_SIDE + 3, 55, 43, 35 );
696: goals[1] = setGoals( LEFT_SIDE + 91, 55, 43, 35 );
697: goals[2] = setGoals( LEFT_SIDE + 179, 55, 43, 35 );
698: goals[3] = setGoals( LEFT_SIDE + 267, 55, 43, 35 );
699: goals[4] = setGoals( LEFT_SIDE + 355, 55, 43, 35 );
700:
701: /*
702: * Configure the left and right side black borders to conceal logs,
703: * turtles, cars, etc. that go past their boundries
704: */
705: leftBorderRect.x = 0;
706: leftBorderRect.y = 0;
707: leftBorderRect.w = LEFT_SIDE;
708: leftBorderRect.h = SCREEN_HEIGHT;
709:
710: rightBorderRect.x = RIGHT_SIDE;
711: rightBorderRect.y = 0;
712: rightBorderRect.w = SCREEN_WIDTH - RIGHT_SIDE;
713: rightBorderRect.h = SCREEN_HEIGHT;
714:
1.3 nick 715: /*
716: * We reset the flyTimer since this may not be the first game played
717: */
718: flyTimer = 0;
1.1 nick 719:
720: /*
721: * Draw frogger in starting position
722: */
723: froggerReset( );
724: }
725:
726: void drawGameScreen( void ) {
727: /*
728: * Update frogger
729: */
730: if ( frogger.direction ) moveFrogger( );
731: if ( frogger.riding ) ridingFrogger( );
732:
733: /* Check for collisions with frogger */
734: if ( frogger.alive ) {
735: if ( frogger.currentRow > 6 && frogger.currentRow < 12 ) {
736: if ( ( ! collisionRow( ) ) || ( frogger.riding == FALSE ) ) {
737: playSound( frogger.s_splash );
738: frogger.deathType = SPLASH;
739: fprintf( stderr, "D: Frog in water!!\n" );
740: frogger.alive = FALSE;
741: }
742: }
743: else if ( frogger.currentRow == 12 ) {
744: if ( collisionRow( ) ) {
745: playSound( frogger.s_squash );
746: frogger.deathType = SPLAT;
747: fprintf( stderr, "D: Frog in thorn bushes!\n" );
748: frogger.alive = FALSE;
749: }
750: }
751: else if( collisionRow( ) ) {
752: playSound( frogger.s_squash );
753: frogger.deathType = SPLAT;
754: fprintf( stderr, "D: Frog Squashed!\n" );
755: frogger.alive = FALSE;
756: }
757: }
758:
759: /*
760: * Update and draw everthing else
761: */
1.3 nick 762: checkFly( );
1.4 nick 763: checkGator( );
1.1 nick 764: drawImage( background, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, screen, 0, 0, 255 );
765: drawScore( 0, score );
766: drawScore( 1, hScore );
767: drawGoals( );
768: drawLives( lives );
769: drawLevel( level );
770: drawWood( );
771: drawTurtles( );
772: drawVehicles( );
773:
774: if ( frogger.alive == FALSE ) {
1.2 nick 775: frogger.riding = FALSE;
1.1 nick 776: if ( ! drawDeathSequence( frogger.deathType ) ) {
777: lives--;
778: if ( lives < 0 ) { drawGameOver( ); }
779: else { froggerReset( ); }
780: }
781: }
782:
783: if ( frogger.alive ) {
784: frogger.alive = checkTimer( );
785: drawImage( gfx, frogger.src.x, frogger.src.y, frogger.src.w,
786: frogger.src.h, screen, frogger.dst.x, frogger.dst.y, 255 );
787: }
788: if ( ! debugBorder ) {
789: SDL_FillRect( screen, &leftBorderRect, SDL_MapRGB( screen->format, BGCOLOR ) );
790: SDL_FillRect( screen, &rightBorderRect, SDL_MapRGB( screen->format, BGCOLOR ) );
791: }
792:
793: SDL_Flip( screen );
794: }
795:
796: void drawBackground( void ) {
797: /*
798: * Draw background map
799: */
800: backgroundRect.x = 0;
801: backgroundRect.y = 0;
802: SDL_BlitSurface( background, NULL, screen, &backgroundRect );
803: SDL_UpdateRect( screen, 0, 0, 0, 0 );
804: }
805:
806: /*
807: * This calculates the pixel top of the requested row
808: */
809: int getRowPixel ( int row ) {
810: return ROW_BASE - ( row * HOP_DISTANCE );
811: }
812:
813: /*
1.3 nick 814: * Check our fly timers to determine if we need to display or
815: * remove a fly from the goal area
816: */
1.4 nick 817: void checkFly ( void ) {
1.3 nick 818: int i;
819:
820: for ( i = 0; i < MAX_GOALS; i++ ) {
821: if ( goals[i].fly ) {
822: goals[i].fly++;
823: if ( goals[i].fly > FLY_MAX_TIME ) {
824: goals[i].fly = 0;
825: flyTimer = 0;
826: }
827:
1.4 nick 828: return;
1.3 nick 829: }
830: }
831:
832: flyTimer++;
833:
834: if ( flyTimer > ( FLY_MAX_TIME ) ) {
835: int randGoal = ( ( int ) timeLeft % 10 );
836: if ( ( goals[randGoal].gator == 0 ) &&
837: ( goals[randGoal].occupied == 0 ) ) {
838: printf( "Displaying fly in goal %i\n", randGoal );
839: goals[randGoal].fly = 1;
840: }
841: }
842:
1.4 nick 843: return;
844: }
845:
846: /*
847: * Check our gator timers. Similiar to fly timers above, however, the gator
848: * has an extra stage as it enters in to the goal area.
849: */
850: void checkGator ( void ) {
851: int i;
852:
853: for( i = 0; i < MAX_GOALS; i++ ) {
854: if ( goals[i].gator ) {
855: goals[i].gator++;
856: if ( goals[i].gator > GATOR_MAX_TIME ) {
857: goals[i].gator = 0;
858: gatorTimer = 0;
859: }
860:
861: return;
862: }
863: }
864:
865: gatorTimer++;
866:
867: if ( gatorTimer > GATOR_MAX_TIME ) {
868: int randGoal = ( ( int ) ( timeLeft * 2 ) % 10 );
869: if ( ( goals[randGoal].fly == 0 ) &&
870: ( goals[randGoal].occupied == 0 ) ) {
871: printf( "Displaying gator in goal %i\n", randGoal );
872: goals[randGoal].gator = 1;
873: }
874: }
875:
876: return;
1.3 nick 877: }
878:
879: /*
1.1 nick 880: * This does collision detection based on the row frogger
881: * is in to help reduce overhead
882: */
883: int collisionRow ( void ) {
884: int i;
885:
886: if ( frogger.currentRow <= 0 ) return 0;
887:
888: /* Check collision with cars */
889: if ( frogger.currentRow < 6 ) {
890: for( i = 0; i < MAX_VEHICLES; i++ ) {
891: if ( level >= vehicle[i].level ) {
892: int length = ( vehicle[i].row == 5 ) ? FRAME * 2 : FRAME; /* Trucks */
893: if ( collideFrogger( vehicle[i].placement[X],
894: vehicle[i].placement[Y], FRAME,
895: length ) ) {
896: return 1;
897: }
898: }
899: }
900: return 0;
901: }
902: /* check for collisions with turtles, logs, etc.. */
903: else if ( frogger.currentRow > 6 && frogger.currentRow < 12 ) {
904: /* here a collision is good, else death */
905: for( i = 0; i < MAX_TURTLES; i++ ) {
906: if ( collideFrogger( turtle[i].placement[X],
907: turtle[i].placement[Y], FRAME,
908: FRAME * turtle[i].count ) ) {
909: frogger.riding = ( turtle[i].diveStep == 3 ) ? FALSE : LEFT;
910: frogger.ridingIdx = i;
911: frogger.ridingType = TURTLE;
912: return 1;
913: }
914: }
915: for( i = 0; i < MAX_WOOD; i++ ) {
916: if ( collideFrogger( wood[i].placement[X],
917: wood[i].placement[Y], FRAME,
918: FRAME * wood[i].type ) ) {
919: frogger.riding = RIGHT;
920: frogger.ridingIdx = i;
921: frogger.ridingType = LOG;
922: return 1;
923: }
924: }
925: }
926: /* We're on the path, if the snake is active, check that */
927: else if ( frogger.currentRow == 6 ) {
928: frogger.riding = FALSE; /*in case we hopped off a turtle */
929: }
930: /* This leaves the goal area only */
931: else {
932: for ( i = 0; i < MAX_GOALS; i++ ) {
933: if ( collideFrogger( goals[i].x, goals[i].y, goals[i].w, goals[i].h ) ) {
934: if ( goals[i].occupied ) return 1;
935: goals[i].occupied++;
1.3 nick 936: if ( goals[i].fly ) {
937: goals[i].fly = 0;
938: flyTimer = 0;
939: score += SCORE_FLY;
940: }
1.1 nick 941: /* playSound( s_goal ); */
942: score += SCORE_GOAL;
943: score += ( ( int ) ( timeLeft / 10 ) ) * 10;
944: lives += freeFrog( score );
945: froggerReset( );
946: if ( checkGoals( ) ) levelUp( );
947: return 0;
948: }
949: }
950: return 1;
951: }
952:
953: return 0;
954: }
955:
956: /* If the player gets enough points, award them a free frog */
957: int freeFrog ( int score ) {
958: if ( givenFreeFrog ) return 0;
959: if ( score >= SCORE_FREE_FROG ) {
960: givenFreeFrog++;
961: playSound( s_freeFrog );
962: return 1;
963: }
964: return 0;
965: }
966:
967: /* Check what frogger is colliding with */
968: int collideFrogger ( int x, int y, int h, int w ) {
969: h++; w++;
970:
971: if ( ( frogger.placement[Y] >= ( y + h ) ) ||
972: ( frogger.placement[X] >= ( x + w ) ) ||
973: ( y >= ( frogger.placement[Y] + FRAME ) ) ||
974: ( x >= ( frogger.placement[X] + FRAME ) ) ) {
975: return( 0 );
976: }
977: return( 1 );
978: }
979:
980: /* Check left and right borders */
981: void checkFroggerBorder( void ) {
982: if ( frogger.placement[Y] - 5 >= getRowPixel( 0 ) ) {
983: frogger.placement[Y] = frogger.oldPlacement[Y];
984: frogger.currentRow = 0;
985: }
986:
987: if ( ( frogger.placement[X] <= LEFT_SIDE ) ||
988: ( frogger.placement[X] + frogger.src.w >= RIGHT_SIDE ) ) {
989: if ( ( frogger.currentRow == 0 ) ||
990: ( frogger.currentRow == 6 ) ) {
991: frogger.placement[X] = frogger.oldPlacement[X];
992: }
993: else {
994: frogger.alive = FALSE;
995: }
996: }
997: }
998:
999: void levelUp ( void ) {
1000: int i;
1001:
1002: fprintf ( stderr, "Level %i beat! ", level );
1003:
1004: level++;
1005: score += SCORE_LEVEL;
1006: lives += freeFrog( score );
1007: froggerReset( );
1008: /* Play sounds */
1009:
1010: /* Empty goals */
1011: for ( i = 0; i < MAX_GOALS; i++ ) goals[i].occupied = 0;
1012:
1013: /* Speed things up */
1014: vehicle[0].speed = level;
1015: vehicle[1].speed = level;
1016: vehicle[2].speed = level;
1017: vehicle[3].speed = level;
1018:
1019: fprintf (stderr, "Starting level %i!\n", level );
1020: }
1021:
1022: int checkGoals ( void ) {
1023: int savedFrogs = 0;
1024: int i;
1025:
1026: for ( i = 0; i < MAX_GOALS; i++ ) {
1027: if ( goals[i].occupied ) savedFrogs++;
1028: }
1029:
1030: drawGoals( );
1031:
1032: return ( savedFrogs >= 5 ) ? 1 : 0;
1033: }
1034:
1035: void froggerReset ( void ) {
1036: timeLeft = MAX_TIMER;
1037:
1038: frogger.placement[X] = FROGGER_START_X;
1039: frogger.placement[Y] = FROGGER_START_Y;
1040: frogger.oldPlacement[X] = FROGGER_START_X;
1041: frogger.oldPlacement[Y] = FROGGER_START_Y;
1042: frogger.hopCount = 0;
1043: frogger.direction = 0;
1044: frogger.currentRow = 0;
1045: frogger.alive = TRUE;
1046: frogger.riding = FALSE;
1047: frogger.deathType = 0; /* Death type SPLAT or SPLASH */
1048: frogger.deathCount = 0; /* death animation timer */
1049:
1050: frogger.src.y = 0;
1051: frogger.src.x = 0;
1052: frogger.src.w = FRAME;
1053: frogger.src.h = FRAME;
1054: frogger.dst.y = frogger.placement[Y];
1055: frogger.dst.x = frogger.placement[X];
1056:
1057: drawImage( gfx, frogger.src.x, frogger.src.y, frogger.src.w,
1058: frogger.src.h, screen, frogger.dst.x, frogger.dst.y, 255 );
1059: }
1060:
1061: /*
1062: * This actually moves frogger... I need to come up with a better
1063: * algorithm for calculating the distance and time
1064: */
1065: void moveFrogger( void ) {
1066: int x = 0;
1067: int y = 0;
1068: int h = FRAME;
1069: int w = FRAME;
1070:
1071: frogger.oldPlacement[Y] = frogger.placement[Y];
1072: frogger.oldPlacement[X] = frogger.placement[X];
1073:
1074: switch( frogger.direction ) {
1075: case UP:
1.5 nick 1076: x = FRAME;
1.1 nick 1077: frogger.placement[Y] -= ( HOP_DISTANCE / HOP_SPEED );
1078: break;
1079: case DOWN:
1.5 nick 1080: x = ( 5 * FRAME );
1.1 nick 1081: frogger.placement[Y] += ( HOP_DISTANCE / HOP_SPEED );
1082: break;
1083: case LEFT:
1.5 nick 1084: x = ( 7 * FRAME );
1.1 nick 1085: frogger.placement[X] -= ( HOP_DISTANCE / HOP_SPEED );
1086: break;
1087: case RIGHT:
1.5 nick 1088: x = ( 3 * FRAME );
1.1 nick 1089: frogger.placement[X] += ( HOP_DISTANCE / HOP_SPEED );
1090: break;
1091: }
1092:
1093: checkFroggerBorder( );
1094:
1095: /* select the frame to display */
1096: frogger.src.y = y;
1097: frogger.src.x = x;
1098: frogger.src.w = w;
1099: frogger.src.h = h;
1100:
1101: /* Set the old place to be erased */
1102: frogger.dst.y = frogger.oldPlacement[Y];
1103: frogger.dst.x = frogger.oldPlacement[X];
1104:
1105: SDL_FillRect( screen, NULL, SDL_MapRGB( screen->format, BGCOLOR ) );
1106:
1107: /* Place the new position */
1108: frogger.dst.y = frogger.placement[Y];
1109: frogger.dst.x = frogger.placement[X];
1110:
1111: frogger.hopCount++;
1112:
1113: if ( frogger.hopCount >= HOP_SPEED ) {
1114: frogger.hopCount = 0;
1115: frogger.direction = FALSE;
1116: score += SCORE_HOP;
1117: lives += freeFrog( score );
1.5 nick 1118: frogger.src.x -= FRAME;
1.1 nick 1119: }
1120: }
1121:
1122: void ridingFrogger( void ) {
1123: int speed = 0;
1124:
1125: if ( frogger.hopCount > 0 ) return;
1126:
1127: switch( frogger.ridingType ) {
1128: case LOG:
1129: speed = wood[frogger.ridingIdx].speed;
1130: break;
1131: case TURTLE:
1132: speed = turtle[frogger.ridingIdx].speed + 2;
1133: break;
1134: }
1135:
1136: switch( frogger.riding ) {
1137: case LEFT:
1138: frogger.oldPlacement[X] = frogger.placement[X];
1139: frogger.placement[X] -= speed;
1140: frogger.dst.x = frogger.placement[X];
1141: break;
1142: case RIGHT:
1143: frogger.oldPlacement[X] = frogger.placement[X];
1144: frogger.placement[X] += speed;
1145: frogger.dst.x = frogger.placement[X];
1146: break;
1147: }
1148:
1149: checkFroggerBorder( );
1150: }
1151:
1152: void drawTitleScreen( void ) {
1153: SDL_Surface *introText;
1154: SDL_Color fontColor = { 123, 158, 53, 255 };
1155: int center = ( SCREEN_WIDTH / 2 ) - ( titleSurface->w / 2 );
1156: int i;
1157: char *txt[] = { "Press 1 for single player game",
1158: "Press 2 for two player games",
1159: "Press F for full screen mode",
1160: "Press ESC to quit" };
1161:
1162: // drawBackground( );
1163:
1164: drawImage( titleSurface, 0, 0, titleSurface->w,
1165: titleSurface->h, screen, center, 100, 255 );
1166:
1167: for( i = 0; i <= 3; i++ ) {
1168: introText = TTF_RenderText_Solid( font, txt[i], fontColor );
1169: drawImage( introText, 0, 0, introText->w, introText->h, screen,
1170: 140, 300 + ( i * introText->h ), 255 );
1171: }
1172:
1173: SDL_Flip( screen );
1174: }
1175:
1176: void drawPauseScreen( void ) {
1177: printf( "D: Draw Pause Screen\n" );
1178:
1179: }
1180:
1181: void drawGameOver( void ) {
1182: printf( "D: Game Over\n" );
1183: }
1184:
1185: void playSound( Mix_Chunk *sound ) {
1186: Mix_PlayChannel( -1, sound, 0 );
1187: }
1188:
1189: void setFullScreenMode( void ) {
1190: /* Lets give fullscreen mode a try */
1191: if ( ! fullscreen ) {
1192: screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, 16, SDL_HWSURFACE | SDL_FULLSCREEN );
1193: fullscreen = TRUE;
1194: }
1195: /* Switch back to window mode */
1196: else {
1197: screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, 16, SDL_HWSURFACE );
1198: fullscreen = FALSE;
1199: }
1200:
1201: printf( "D: Fullscreen : %i\n", fullscreen );
1202: }
1203:
1204: int drawDeathSequence( int deathType ) {
1205: int animDelay = 55;
1206: int animOffset = ( deathType == SPLAT ) ? 8 : 11;
1207: int dFrame = 0;
1208:
1209: if ( frogger.deathCount < 7 ) dFrame = 0;
1210: if ( frogger.deathCount >= 7 ) dFrame = 1;
1211: if ( frogger.deathCount >= 14) dFrame = 2;
1212: if ( frogger.deathCount > 20 ) animOffset = 12;
1213:
1214: frogger.deathCount++;
1215: if ( frogger.deathCount >= animDelay )
1216: return 0; /* we're done with death */
1217:
1218: drawImage( gfx, FRAME * ( animOffset + dFrame ), 0, FRAME, FRAME,
1219: screen, frogger.placement[X], frogger.placement[Y], 255 );
1220:
1221: return 1;
1222: }
1223:
1224: /* draw green timer and return 0 if out of time */
1225: int checkTimer( void ) {
1226: float lvl = level;
1227: int step = ( int ) ( lvl / 2 );
1228: if ( step < 1 ) step = 1;
1229: if ( step > 3 ) step = 3;
1230: timeLeft -= step;
1231:
1232: drawTimer( (int) ( ( timeLeft / MAX_TIMER ) * TIMER_SIZE ) );
1233:
1234: if ( timeLeft <= 0 ) return 0;
1235: return 1;
1236: }
1237:
1238: void drawScore( int high, int score ) {
1239: int x = 169;
1240: int y = 14;
1241:
1242: if ( score > hScore ) hScore = score;
1243: if ( high ) x = 260;
1244:
1245: drawNumbers( score, x, y );
1246: }
1247:
1248: void drawNumbers( int num, int x, int y ) {
1249: char numStr[6] = "00000";
1250: int i;
1251:
1252: /* Assume anything less than 50 pixels location is a score and
1253: * pad with '0'.
1254: */
1255: if ( y <= 15 ) sprintf( numStr, "%05i", num );
1256: else sprintf( numStr, "%i", num );
1257:
1258: for ( i = 0; i <= 4; i++ ) {
1259: char c = numStr[i];
1260: int n = atoi( &c );
1261:
1262: drawImage( gfx, n * HFRAME, FRAME * 3 , HFRAME, FRAME,
1263: screen, x + ( i * HFRAME ) + 2, y, 255 );
1264: }
1265: }
1266:
1267: /* Normally this functions manages and draws the flys, gators and saved frogs
1268: * but if drawDebugRect below is turned on it will draw the rectangle
1269: * used for collision detectiong for debuggin purposes in timer green
1270: */
1271: void drawGoals( void ) {
1272: int drawDebugRect = 0;
1273: int i;
1.3 nick 1274:
1.1 nick 1275: for ( i = 0; i < MAX_GOALS; i++ ) {
1276: if ( drawDebugRect ) {
1277: SDL_Rect d;
1278: d.x = goals[i].x;
1279: d.y = goals[i].y;
1280: d.w = goals[i].w;
1281: d.h = goals[i].h;
1282:
1283: SDL_FillRect( screen, &d, SDL_MapRGB( screen->format, TIMER_COLOR ) );
1284: }
1285:
1286: if ( goals[i].occupied )
1287: drawImage( gfx, FRAME * 15, 0, FRAME, FRAME,
1288: screen, goals[i].x + 13, goals[i].y + 5, 255 );
1.3 nick 1289: if( goals[i].fly ) {
1.6 ! nick 1290: drawImage( gfx, FRAME * 17, 0, FRAME, FRAME,
1.3 nick 1291: screen, goals[i].x + 13, goals[i].y + 5, 255 );
1292: }
1.4 nick 1293: if( goals[i].gator ) {
1.6 ! nick 1294: int frame = 18;
! 1295: int diff = 10;
1.4 nick 1296:
1297: if ( goals[i].gator > ( ( int ) GATOR_MAX_TIME / 2 ) )
1.6 ! nick 1298: diff = 0;
1.4 nick 1299:
1.6 ! nick 1300: drawImage( gfx, FRAME * frame + diff, 0, FRAME, FRAME,
1.4 nick 1301: screen, goals[i].x + 13, goals[i].y + 5, 255 );
1302: }
1.1 nick 1303: }
1304: }
1305:
1306: void drawTimer( int length ) {
1307: SDL_Rect timerRect;
1308:
1309: timerRect.x = RIGHT_SIDE - 60 - length;
1310: timerRect.y = 465;
1311: timerRect.w = length;
1312: timerRect.h = 15;
1313:
1314: SDL_FillRect( screen, &timerRect, SDL_MapRGB( screen->format, TIMER_COLOR ) );
1315: }
1316:
1317: void drawLives( int lives ) {
1318: int i;
1319: int lifeFroggerSize = 16;
1320:
1321: for( i = 0; i <= lives - 2; i++ ) {
1322: drawImage( gfx, FRAME * 11, FRAME * 2, lifeFroggerSize, FRAME,
1323: screen, LEFT_SIDE + ( lifeFroggerSize * i ), 450, 255 );
1324: }
1325: }
1326:
1327: void drawLevel( int level ) {
1328: int i;
1329: int levelImageSize = 12;
1330:
1331: for( i = 0; i <= level - 1; i++ ) {
1332: drawImage( gfx, FRAME * 12, FRAME * 2, levelImageSize, FRAME,
1333: screen, RIGHT_SIDE - levelImageSize - ( levelImageSize * i ), 450, 255 );
1334: }
1335: }
1336:
1337: void drawWood ( void ) {
1338: int i;
1339:
1340: for ( i = 0; i < MAX_WOOD; i++ ) {
1341: if ( wood[i].placement[X] > ( RIGHT_SIDE + 5 ) )
1342: wood[i].placement[X] = LEFT_SIDE - wood[i].src.w - 5;
1343: wood[i].placement[X] += wood[i].speed;
1344: drawImage( gfx, wood[i].src.x, wood[i].src.y,
1345: wood[i].src.w, wood[i].src.h,
1346: screen, wood[i].placement[X],
1347: wood[i].placement[Y], 255 );
1348: }
1349: }
1350:
1351: void drawTurtles ( void ) {
1352: int i = 0;
1353: int n = 0;
1354: int animFrame = 0;
1355:
1356: for ( i = 0; i < MAX_TURTLES; i++ ) {
1357: /* This managed the turtles basic 3 frames of animation */
1358: animFrame = turtle[i].animStep;
1359: if ( turtle[i].animDelay >= TURTLE_ANIM_TIME ) {
1360: turtle[i].animDelay = 0;
1361: turtle[i].animStep++;
1362: if ( turtle[i].animStep > 2 ) turtle[i].animStep = 0;
1363: }
1364: else {
1365: turtle[i].animDelay++;
1366: }
1367:
1368: /* If a set of turtles have dive capability, this enables that */
1369: if ( turtle[i].canDive ) {
1370: turtle[i].diveTime++;
1371: /* Check if turtle is diving */
1372: if ( turtle[i].diveStep > 0 ) {
1373: switch( turtle[i].diveStep ) {
1374: case 1:
1375: animFrame = 3;
1376: break;
1377: case 2:
1378: animFrame = 4;
1379: break;
1380: case 4:
1381: animFrame = 4;
1382: break;
1383: case 5:
1384: animFrame = 3;
1385: break;
1386: case 6:
1387: turtle[i].diveStep = 0;
1388: turtle[i].diveTime = 0;
1389: break;
1390: default:
1391: animFrame = 4;
1392: break;
1393: }
1394:
1395: if ( turtle[i].diveTime > DIVE_START_TIME + ( DIVE_PHASE_TIME * turtle[i].diveStep ) )
1396: turtle[i].diveStep++;
1397:
1398: }
1399: else {
1400: if ( turtle[i].diveTime > DIVE_START_TIME )
1401: turtle[i].diveStep++;
1402: }
1403: }
1404:
1405: /* Display out turtles */
1406: for ( n = 0; n <= ( turtle[i].count - 1 ); n++ ) {
1407: turtle[i].placement[X] -= turtle[i].speed;
1408: if ( turtle[i].placement[X] <= LEFT_SIDE - ( turtle[i].count * FRAME ) + 10 )
1409: turtle[i].placement[X] = RIGHT_SIDE + 10;
1410: if ( turtle[i].diveStep != 4 )
1411: drawImage( gfx, turtle[i].src.x + ( FRAME * animFrame ),
1412: turtle[i].src.y, turtle[i].src.w, turtle[i].src.h,
1413: screen, turtle[i].placement[X] + ( ( FRAME + 3 ) * n ),
1414: turtle[i].placement[Y], 255 );
1415: }
1416: }
1417: }
1418:
1419: void drawVehicles ( void ) {
1420: int i;
1421:
1422: for ( i = 0; i < MAX_VEHICLES; i++ ) {
1423: if ( vehicle[i].direction == RIGHT ) {
1424: if ( vehicle[i].placement[X] > ( RIGHT_SIDE + 5 ) )
1425: vehicle[i].placement[X] = LEFT_SIDE - vehicle[i].src.w - 5;
1426: vehicle[i].placement[X] += vehicle[i].speed;
1427: }
1428: else {
1429: if ( vehicle[i].placement[X] < ( LEFT_SIDE - 5 ) )
1430: vehicle[i].placement[X] = RIGHT_SIDE + vehicle[i].src.w + 5;
1431: vehicle[i].placement[X] -= vehicle[i].speed;
1432: }
1433:
1434: if ( level >= vehicle[i].level )
1435: drawImage( gfx, vehicle[i].src.x, vehicle[i].src.y,
1436: vehicle[i].src.w, vehicle[i].src.h,
1437: screen, vehicle[i].placement[X],
1438: vehicle[i].placement[Y], 255 );
1439: }
1440: }
1441:
1442: void drawImage( SDL_Surface *srcimg, int sx, int sy, int sw, int sh,
1443: SDL_Surface *dstimg, int dx, int dy, int alpha ) {
1444: if ((!srcimg) || (alpha == 0)) return;
1445: SDL_Rect src, dst;
1446:
1447: src.x = sx; src.y = sy; src.w = sw; src.h = sh;
1448: dst.x = dx; dst.y = dy; dst.w = src.w; dst.h = src.h;
1449:
1450: if (alpha != 255) SDL_SetAlpha(srcimg, SDL_SRCALPHA, alpha);
1451: SDL_BlitSurface(srcimg, &src, dstimg, &dst);
1452: }
1453:
1454: int heartbeat ( void ) {
1455: int ticks;
1456: if ( level ) {
1457: if ( playing ) {
1458: ticks = updateGameState( );
1459: if ( ticks <= 0 ) ticks = 50;
1460: return ticks;
1461: }
1462: else {
1463: drawPauseScreen( );
1464: return 500;
1465: }
1466: }
1467: else {
1468: drawTitleScreen( );
1469: return 500;
1470: }
1471:
1472: return 50;
1473: }
1474:
1475: /*
1476: * Main program starts here. We'll init the video and audio
1477: * and then begin our main program loop here
1478: *
1479: */
1480: int main ( int argc, char **argv ) {
1481: if ( mySDLInit( ) <= 0 ) {
1482: fprintf( stderr, "Failure to start froggix\n" );
1483: return 255;
1484: }
1485:
1486: beginGame( );
1487:
1488: SDL_Quit( );
1489:
1490: return 0;
1491: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>