Annotation of froggix/src/froggix.c, revision 1.5

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.5     ! nick       28: #define VER "$Id: froggix.c,v 1.4 2009-04-07 04:16:45 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 ) {
                   1290:                        drawImage( gfx, FRAME * 16, 0, FRAME, FRAME, 
                   1291:                                   screen, goals[i].x + 13, goals[i].y + 5, 255 );
                   1292:                }
1.4       nick     1293:                if( goals[i].gator ) {
                   1294:                        int frame = 17;
                   1295: 
                   1296:                        if ( goals[i].gator > ( ( int ) GATOR_MAX_TIME / 2 ) )
                   1297:                                frame++;
                   1298:                        
                   1299:                        drawImage( gfx, FRAME * frame, 0, FRAME, FRAME, 
                   1300:                                   screen, goals[i].x + 13, goals[i].y + 5, 255 );
                   1301:                }               
1.1       nick     1302:        }
                   1303: }
                   1304: 
                   1305: void drawTimer( int length ) {
                   1306:        SDL_Rect timerRect;
                   1307: 
                   1308:        timerRect.x = RIGHT_SIDE - 60 - length;
                   1309:        timerRect.y = 465;
                   1310:        timerRect.w = length;
                   1311:        timerRect.h = 15;
                   1312: 
                   1313:        SDL_FillRect( screen, &timerRect,  SDL_MapRGB( screen->format, TIMER_COLOR ) );
                   1314: }
                   1315: 
                   1316: void drawLives( int lives ) {
                   1317:        int i;
                   1318:        int lifeFroggerSize = 16;
                   1319: 
                   1320:        for( i = 0; i <= lives - 2; i++ ) {
                   1321:                drawImage( gfx, FRAME * 11, FRAME * 2, lifeFroggerSize, FRAME,
                   1322:                           screen, LEFT_SIDE + ( lifeFroggerSize * i ), 450, 255 );
                   1323:        }
                   1324: }
                   1325: 
                   1326: void drawLevel( int level ) {
                   1327:        int i;
                   1328:        int levelImageSize = 12;
                   1329: 
                   1330:        for( i = 0; i <= level - 1; i++ ) {
                   1331:                drawImage( gfx, FRAME * 12, FRAME * 2, levelImageSize, FRAME,
                   1332:                           screen, RIGHT_SIDE - levelImageSize - ( levelImageSize * i ),                           450, 255 );
                   1333:        }
                   1334: }
                   1335: 
                   1336: void drawWood ( void ) {
                   1337:        int i;
                   1338: 
                   1339:         for ( i = 0; i < MAX_WOOD; i++ ) {
                   1340:                if ( wood[i].placement[X] > ( RIGHT_SIDE + 5 ) )
                   1341:                        wood[i].placement[X] = LEFT_SIDE - wood[i].src.w - 5;
                   1342:                wood[i].placement[X] += wood[i].speed;
                   1343:                drawImage( gfx, wood[i].src.x, wood[i].src.y,
                   1344:                        wood[i].src.w, wood[i].src.h,
                   1345:                        screen, wood[i].placement[X],
                   1346:                        wood[i].placement[Y], 255 );
                   1347:         }
                   1348: }
                   1349: 
                   1350: void drawTurtles ( void ) {
                   1351:        int i = 0;
                   1352:        int n = 0;
                   1353:        int animFrame = 0;
                   1354: 
                   1355:        for ( i = 0; i < MAX_TURTLES; i++ ) {
                   1356:                /* This managed the turtles basic 3 frames of animation */
                   1357:                animFrame = turtle[i].animStep;
                   1358:                if ( turtle[i].animDelay >= TURTLE_ANIM_TIME ) {        
                   1359:                        turtle[i].animDelay = 0;
                   1360:                        turtle[i].animStep++;
                   1361:                        if ( turtle[i].animStep > 2 ) turtle[i].animStep = 0;
                   1362:                }
                   1363:                else {
                   1364:                        turtle[i].animDelay++;
                   1365:                }
                   1366: 
                   1367:                /* If a set of turtles have dive capability, this enables that */
                   1368:                if ( turtle[i].canDive ) {
                   1369:                        turtle[i].diveTime++;
                   1370:                        /* Check if turtle is diving */
                   1371:                        if ( turtle[i].diveStep > 0 ) {
                   1372:                                switch( turtle[i].diveStep ) {
                   1373:                                        case 1:
                   1374:                                                animFrame = 3;
                   1375:                                                break;
                   1376:                                        case 2: 
                   1377:                                                animFrame = 4;
                   1378:                                                break;
                   1379:                                        case 4: 
                   1380:                                                animFrame = 4;
                   1381:                                                break;
                   1382:                                        case 5: 
                   1383:                                                animFrame = 3;  
                   1384:                                                break;
                   1385:                                        case 6:
                   1386:                                                turtle[i].diveStep = 0;
                   1387:                                                turtle[i].diveTime = 0;
                   1388:                                                break;
                   1389:                                        default:
                   1390:                                                animFrame = 4;
                   1391:                                                break;
                   1392:                                }
                   1393:                        
                   1394:                                if ( turtle[i].diveTime > DIVE_START_TIME + ( DIVE_PHASE_TIME * turtle[i].diveStep ) )
                   1395:                                        turtle[i].diveStep++;
                   1396:        
                   1397:                        }
                   1398:                        else {
                   1399:                                if ( turtle[i].diveTime > DIVE_START_TIME ) 
                   1400:                                        turtle[i].diveStep++;
                   1401:                        }
                   1402:                }
                   1403: 
                   1404:                /* Display out turtles */
                   1405:                for ( n = 0; n <= ( turtle[i].count - 1 ); n++ ) {
                   1406:                        turtle[i].placement[X] -= turtle[i].speed;
                   1407:                        if ( turtle[i].placement[X] <= LEFT_SIDE - ( turtle[i].count * FRAME ) + 10 ) 
                   1408:                                turtle[i].placement[X] = RIGHT_SIDE + 10;
                   1409:                        if ( turtle[i].diveStep != 4 ) 
                   1410:                                drawImage( gfx, turtle[i].src.x + ( FRAME * animFrame ), 
                   1411:                                   turtle[i].src.y, turtle[i].src.w, turtle[i].src.h,
                   1412:                                   screen, turtle[i].placement[X] + ( ( FRAME + 3 ) * n ),
                   1413:                                   turtle[i].placement[Y], 255 );
                   1414:                }
                   1415:        }
                   1416: }
                   1417: 
                   1418: void drawVehicles ( void ) {
                   1419:        int i;
                   1420: 
                   1421:         for ( i = 0; i < MAX_VEHICLES; i++ ) {
                   1422:                if ( vehicle[i].direction == RIGHT ) {  
                   1423:                        if ( vehicle[i].placement[X] > ( RIGHT_SIDE + 5 ) )
                   1424:                                vehicle[i].placement[X] = LEFT_SIDE - vehicle[i].src.w - 5;
                   1425:                        vehicle[i].placement[X] += vehicle[i].speed;
                   1426:                }
                   1427:                else {  
                   1428:                        if ( vehicle[i].placement[X] < ( LEFT_SIDE - 5 ) )
                   1429:                                vehicle[i].placement[X] = RIGHT_SIDE + vehicle[i].src.w + 5;
                   1430:                        vehicle[i].placement[X] -= vehicle[i].speed;
                   1431:                }
                   1432: 
                   1433:                if ( level >= vehicle[i].level )
                   1434:                        drawImage( gfx, vehicle[i].src.x, vehicle[i].src.y,
                   1435:                                vehicle[i].src.w, vehicle[i].src.h,
                   1436:                                screen, vehicle[i].placement[X],
                   1437:                                vehicle[i].placement[Y], 255 );
                   1438:         }
                   1439: }
                   1440: 
                   1441: void drawImage( SDL_Surface *srcimg, int sx, int sy, int sw, int sh, 
                   1442:                SDL_Surface *dstimg, int dx, int dy, int alpha ) {
                   1443:   if ((!srcimg) || (alpha == 0)) return; 
                   1444:   SDL_Rect src, dst;        
                   1445: 
                   1446:   src.x = sx;  src.y = sy;  src.w = sw;     src.h = sh;
                   1447:   dst.x = dx;  dst.y = dy;  dst.w = src.w;  dst.h = src.h;
                   1448: 
                   1449:   if (alpha != 255) SDL_SetAlpha(srcimg, SDL_SRCALPHA, alpha); 
                   1450:   SDL_BlitSurface(srcimg, &src, dstimg, &dst);                
                   1451: }
                   1452: 
                   1453: int heartbeat ( void ) {
                   1454:        int ticks;
                   1455:        if ( level ) {
                   1456:                if ( playing ) {
                   1457:                        ticks = updateGameState( );
                   1458:                        if ( ticks <= 0 ) ticks = 50;
                   1459:                        return ticks;           
                   1460:                }
                   1461:                else {
                   1462:                        drawPauseScreen( );
                   1463:                        return 500;
                   1464:                }
                   1465:        }
                   1466:        else {
                   1467:                drawTitleScreen( );
                   1468:                return 500;
                   1469:        }
                   1470: 
                   1471:        return 50;
                   1472: }
                   1473: 
                   1474: /*
                   1475:  * Main program starts here.  We'll init the video and audio
                   1476:  * and then begin our main program loop here
                   1477:  *
                   1478:  */
                   1479: int main ( int argc, char **argv ) {
                   1480:        if ( mySDLInit( ) <= 0 ) {
                   1481:                fprintf( stderr, "Failure to start froggix\n" );
                   1482:                return 255;
                   1483:        }
                   1484: 
                   1485:        beginGame( );
                   1486: 
                   1487:        SDL_Quit( );
                   1488:        
                   1489:        return 0;
                   1490: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>