Share Pastebin
Guest
Public paste!

Untitled

By: a guest | Mar 17th, 2010 | Syntax: C | Size: 13.14 KB | Hits: 35 | Expires: Never
Copy text to clipboard
  1. #include <stdio.h>
  2.  
  3. #include <stdlib.h>
  4.  
  5. #include <SDL/SDL.h>
  6.  
  7. #include <SDL/SDL_ttf.h>
  8.  
  9.  
  10.  
  11. #include "snake.h"
  12.  
  13. #include "game.h"
  14.  
  15. #include "constants.h"
  16.  
  17.  
  18.  
  19. int startMenu(SDL_Surface* screen)
  20.  
  21. {
  22.  
  23.     int go = 1; /* 0 = the game doesn't start and we quit the game */
  24.  
  25.     SDL_Event event; /* catch an event (keyboard or mouse) */
  26.  
  27.  
  28.  
  29.     /* create the surface for the "welcome image" */
  30.  
  31.     SDL_Surface *background = NULL;
  32.  
  33.     /* the image's position on the screen */
  34.  
  35.     SDL_Rect positionBackground;
  36.  
  37.     /* Load it and give its position */
  38.     background = SDL_LoadBMP("snake_start.bmp");
  39.  
  40.     positionBackground.x = 0;
  41.  
  42.     positionBackground.y = 0;
  43.  
  44.  
  45.  
  46.     /* clean the screen */
  47.  
  48.     SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 111, 55, 0));
  49.  
  50.     /* display the image on the screen */
  51.  
  52.     SDL_BlitSurface(background, NULL, screen, &positionBackground);
  53.  
  54.     SDL_Flip(screen);
  55.  
  56.  
  57.  
  58.     do {
  59.  
  60.         SDL_WaitEvent(&event); /* waiting for an event */
  61.  
  62.  
  63.  
  64.         if (event.type == SDL_QUIT)
  65.  
  66.             go = 0;
  67.  
  68.     } while (event.type != SDL_KEYDOWN && event.type != SDL_QUIT);
  69.  
  70.  
  71.  
  72.     /* we don't need the image anymore */
  73.  
  74.     SDL_FreeSurface(background);
  75.  
  76.  
  77.  
  78.     return go;
  79.  
  80. }
  81.  
  82.  
  83.  
  84. void play(SDL_Surface* screen)
  85.  
  86. {
  87.  
  88.     /* the snake in game */
  89.  
  90.     Snake s = NULL;
  91.  
  92.     Snake tmpSnake = NULL;
  93.  
  94.  
  95.  
  96.     /* we'll use surfaces SDL type to represent everything :
  97.  
  98.     snake, target, menu, game screen, .. */
  99.  
  100.     SDL_Surface *menu = NULL;
  101.  
  102.     SDL_Surface *head = NULL; /* snake's head */
  103.  
  104.     SDL_Surface *body = NULL; /* snake's body */
  105.  
  106.     SDL_Surface *apple = NULL;
  107.  
  108.  
  109.  
  110.     SDL_Rect positionApple; /* contains the (x;y) current apple's position */
  111.  
  112.     SDL_Rect positionMenu = {0,(WINDOW_HEIGHT-MENU_HEIGHT)}; /* contains the (x;y) menu's position */
  113.  
  114.  
  115.  
  116.     /* catch an event (keyboard or mouse) */
  117.  
  118.     SDL_Event event;
  119.  
  120.  
  121.  
  122.     int keepgoing; /* 1: the game continuer, 0: byebye */
  123.  
  124.     int retry = 1; /* game can restart if the user loses */
  125.  
  126.     int direction = 0; /* give the new/current snake's direction (UP here, see the enum in game.h) */
  127.  
  128.     int score = 0; /* number of points */
  129.  
  130.     int games = 0; /* number of games */
  131.  
  132.     int timer = 100; /* time between 2 flips in ms */
  133.  
  134.  
  135.  
  136.     /* help us to calculate the time between 2 flips */
  137.  
  138.     int previousTime = 0;
  139.  
  140.     int currentTime = 0;
  141.  
  142.  
  143.  
  144.     /* the surface are created and filled with the appropriate colors */
  145.  
  146.     menu = SDL_CreateRGBSurface(SDL_HWSURFACE, MENU_WIDTH, MENU_HEIGHT, 32, 0, 0, 0, 0);
  147.  
  148.     SDL_FillRect(menu, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
  149.  
  150.  
  151.  
  152.     head = SDL_CreateRGBSurface(SDL_HWSURFACE, SNAKE_WIDTH, SNAKE_HEIGHT, 32, 0, 0, 0, 0);
  153.  
  154.     SDL_FillRect(head, NULL, SDL_MapRGB(screen->format, 0, 80, 0));
  155.  
  156.  
  157.  
  158.     body = SDL_CreateRGBSurface(SDL_HWSURFACE, SNAKE_WIDTH, SNAKE_HEIGHT, 32, 0, 0, 0, 0);
  159.  
  160.     SDL_FillRect(body, NULL, SDL_MapRGB(screen->format, 0, 100, 0));
  161.  
  162.  
  163.  
  164.     apple = SDL_LoadBMP("apple.bmp");
  165.  
  166.     /*apple = SDL_CreateRGBSurface(SDL_HWSURFACE, SNAKE_WIDTH, SNAKE_HEIGHT, 32, 0, 0, 0, 0);
  167.  
  168.     SDL_FillRect(apple, NULL, SDL_MapRGB(screen->format, 170, 0, 0));*/
  169.  
  170.  
  171.  
  172.     /* the (x;y) apples' position are initialized.
  173.  
  174.     (0;0) means there isn't an apple in the game */
  175.  
  176.     positionApple.x = 0;
  177.  
  178.     positionApple.y = 0;
  179.  
  180.  
  181.  
  182.     /* the main loop */
  183.  
  184.     while (retry) {
  185.  
  186.  
  187.  
  188.         keepgoing = 1; /* .. until we lose.. */
  189.  
  190.         /* the new snake is created */
  191.  
  192.         s = initializeSnake(s,5);
  193.  
  194.         direction = 2;
  195.  
  196.  
  197.         /* display number of games and score. it'll be updated when snake eats an apple */
  198.  
  199.         games = games+1;
  200.  
  201.         score = 0;
  202.  
  203.         *menu = scoreTTF(menu, games, score);
  204.  
  205.  
  206.  
  207.         timer = 100;
  208.  
  209.  
  210.  
  211.         /* the game loop, game takes place in */
  212.  
  213.         while (keepgoing) {
  214.  
  215.  
  216.  
  217.             /* if there isn't an apple, we generate a new position for the new apple */
  218.  
  219.             if (positionApple.x == 0 && positionApple.y == 0) {
  220.  
  221.                 positionApple = generateApplePosition(s);
  222.  
  223.             }
  224.  
  225.  
  226.  
  227.             /* if the snake eats an apple... */
  228.  
  229.             if ((s->position).x == positionApple.x && (s->position).y == positionApple.y) {
  230.  
  231.                 positionApple.x = 0;
  232.  
  233.                 positionApple.y = 0;
  234.  
  235.  
  236.  
  237.                 /* ...  it grows up */
  238.  
  239.                 s = addBodyPart2SnakeTail(s);
  240.  
  241.                 score = score+1;
  242.  
  243.                 *menu = scoreTTF(menu, games, score);
  244.  
  245.  
  246.  
  247.                 timer = timer-2; /* speed increases too */
  248.  
  249.             }
  250.  
  251.  
  252.  
  253.             /* make a pause between 2 flips (2 updates of the screen) */
  254.  
  255.             currentTime = SDL_GetTicks();
  256.  
  257.             if (currentTime - previousTime > timer) { /* value in ms */
  258.                 /* to continue, user hasn't to close the window and snake has to be still alive */
  259.                 keepgoing = verifyGame(s,direction) && keepgoing;
  260.  
  261.                 if (keepgoing) /* if everything is ok, the game continue and snake can move */
  262.  
  263.                     s = moveSnake(s, direction); /* see snake.c */
  264.  
  265.                 previousTime = currentTime;
  266.  
  267.             }
  268.  
  269.             else {
  270.  
  271.                 SDL_Delay(timer - (currentTime - previousTime));
  272.  
  273.             }
  274.  
  275.  
  276.  
  277.             /* the screen is filled, so everything disappear (snake, apple, ..) */
  278.  
  279.             SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 111, 55, 0));
  280.  
  281.  
  282.  
  283.             /* surfaces are blitting on screen */
  284.  
  285.             SDL_BlitSurface(apple, NULL, screen, &positionApple);
  286.  
  287.  
  288.  
  289.             /* we traverse the linked list and we also blit each body parts */
  290.  
  291.             tmpSnake = s->next;
  292.  
  293.             while (tmpSnake != NULL) {
  294.  
  295.                 SDL_BlitSurface(body, NULL, screen, &tmpSnake->position);
  296.  
  297.                 tmpSnake = tmpSnake->next;
  298.  
  299.             }
  300.  
  301.  
  302.  
  303.             /* for the snake's head */
  304.  
  305.             SDL_BlitSurface(head, NULL, screen, &s->position);
  306.  
  307.  
  308.  
  309.             /* for the game menu */
  310.  
  311.             SDL_BlitSurface(menu, NULL, screen, &positionMenu);
  312.  
  313.  
  314.  
  315.             /* the the screen is updated */
  316.  
  317.             SDL_Flip(screen);
  318.  
  319.  
  320.  
  321.             /* if an event (from the keyboard or the mouse) is sent by the
  322.  
  323.             gamer/user we take it */
  324.  
  325.             SDL_PollEvent(&event);
  326.  
  327.  
  328.  
  329.             /* in the first case, we test the event and we use it to... */
  330.  
  331.             switch (event.type) {
  332.  
  333.                 /* ... close the window */
  334.  
  335.                 case SDL_QUIT:
  336.  
  337.                     keepgoing = 0;
  338.  
  339.                     retry = 0;
  340.  
  341.                     break;
  342.  
  343.                 /* ... change the snake's position */
  344.  
  345.                 case SDL_KEYDOWN:
  346.  
  347.                     direction = newDirection(event, direction);
  348.  
  349.                     break;
  350.  
  351.                 default:
  352.  
  353.                     break;
  354.  
  355.             }
  356.  
  357.         }
  358.  
  359.  
  360.  
  361.         /* done for this party! */
  362.  
  363.         s = deleteSnake(s); /* free all the snake's parts */
  364.  
  365.  
  366.  
  367.         if (retry == 0) {
  368.  
  369.             /* the gamer clicked to close the window, the game have to stop right now */
  370.  
  371.         }
  372.  
  373.         else {
  374.  
  375.             /* case where the gamer lost his party, may be he want to retry */
  376.  
  377.             retry = retryGame(screen);
  378.  
  379.         }
  380.  
  381.     }
  382.  
  383.  
  384.  
  385.     /* end of the game, we can free the surfaces */
  386.  
  387.     SDL_FreeSurface(head);
  388.  
  389.     SDL_FreeSurface(body);
  390.  
  391.     SDL_FreeSurface(apple);
  392.  
  393. }
  394.  
  395.  
  396. /* make the bottom menu : use font and SDL ttf to display score and other information */
  397.  
  398. SDL_Surface scoreTTF(SDL_Surface* menu, int games, int score)
  399.  
  400. {
  401.  
  402.     /* the font used */
  403.  
  404.     TTF_Font *font = NULL;
  405.  
  406.  
  407.  
  408.     /* the surface and its position for the text */
  409.  
  410.     SDL_Surface* text;
  411.  
  412.     SDL_Rect positionText;
  413.  
  414.  
  415.  
  416.     SDL_Color colorFont = {255, 255, 255}; /* text's color */
  417.  
  418.     SDL_Color colorBack = {0, 0, 0}; /* background's color of the text */
  419.  
  420.  
  421.  
  422.     /* this string will give the text to write on screen */
  423.  
  424.     char string[20] = "";
  425.  
  426.     sprintf(string, "Game #%d  Score %d ", games, score);
  427.  
  428.  
  429.  
  430.     font = TTF_OpenFont("font.ttf", 30); /* load the font */
  431.  
  432.  
  433.  
  434.     /* write the text on the surface menu */
  435.  
  436.     text = TTF_RenderText_Shaded(font, string, colorFont, colorBack);
  437.  
  438.     positionText.x = 10;
  439.  
  440.     positionText.y = (MENU_HEIGHT/2)-(text->h/2);
  441.  
  442.     SDL_BlitSurface(text, NULL, menu, &positionText);
  443.  
  444.  
  445.  
  446.     /* update menu */
  447.  
  448.     SDL_Flip(menu);
  449.  
  450.  
  451.  
  452.     TTF_CloseFont(font);
  453.  
  454.  
  455.  
  456.     return *menu;
  457.  
  458. }
  459.  
  460.  
  461. /* Not bored yet? */
  462.  
  463. int retryGame(SDL_Surface* screen)
  464.  
  465. {
  466.  
  467.     SDL_Event eventRetry;
  468.  
  469.  
  470.  
  471.     /* retry? */
  472.  
  473.     do {
  474.  
  475.         SDL_WaitEvent(&eventRetry); /* waiting for an event */
  476.  
  477.  
  478.  
  479.         if (eventRetry.type == SDL_QUIT)
  480.  
  481.             return 0; /* don't retry the game */
  482.  
  483.     } while (eventRetry.type != SDL_KEYDOWN);
  484.  
  485.  
  486.  
  487.     return 1; /* ok, retry! */
  488.  
  489. }
  490.  
  491.  
  492.  
  493. /* set up as many as body parts asked for the snake, at least 3 */
  494.  
  495. Snake initializeSnake(Snake s, int nbParts)
  496.  
  497. {
  498.  
  499.     int i; /* just use for the loop */
  500.  
  501.     SDL_Rect positionSnake; /* contains the position of a snake's body part */
  502.  
  503.  
  504.  
  505.     /* At least 3 parts in the beginning */
  506.  
  507.     if (nbParts < 3)
  508.  
  509.         nbParts = 3;
  510.  
  511.  
  512.  
  513.     /* the head is in the middle of the screen */
  514.  
  515.     positionSnake.x = (WINDOW_WIDTH/2)-(SNAKE_WIDTH/2);
  516.  
  517.     positionSnake.x = positionSnake.x + positionSnake.x%(SNAKE_WIDTH);
  518.  
  519.     positionSnake.x = positionSnake.x - nbParts*SNAKE_WIDTH; /* because we'll add in head */
  520.  
  521.  
  522.  
  523.     positionSnake.y = (WINDOW_HEIGHT/2)-(SNAKE_HEIGHT/2);
  524.  
  525.     positionSnake.y = positionSnake.y + positionSnake.y%(SNAKE_HEIGHT);
  526.  
  527.  
  528.  
  529.     /* we add nbParts of byd parts to our snake */
  530.  
  531.     for (i = 0 ; i < nbParts ; i = i+1) {
  532.  
  533.         s = addBodyPart2SnakeHead(s, positionSnake);
  534.  
  535.         positionSnake.x += SNAKE_WIDTH; /* on the left */
  536.  
  537.     }
  538.  
  539.  
  540.  
  541.     return s;
  542.  
  543. }
  544.  
  545.  
  546. /* return the new direction if the user changes it or the old one */
  547.  
  548. int newDirection(SDL_Event event, int direction)
  549.  
  550. {
  551.  
  552.     switch(event.key.keysym.sym) {
  553.  
  554.         case SDLK_UP: /* key UP was pressed */
  555.  
  556.             /* direction changes if snake doesn't go in a reverse direction */
  557.  
  558.             if (direction != DOWN)
  559.  
  560.                 direction = UP;
  561.  
  562.             break;
  563.  
  564.             /* same for others */
  565.  
  566.         case SDLK_DOWN:
  567.  
  568.             if (direction != UP)
  569.  
  570.             direction = DOWN;
  571.  
  572.             break;
  573.  
  574.         case SDLK_RIGHT:
  575.  
  576.             if (direction != LEFT)
  577.  
  578.             direction = RIGHT;
  579.  
  580.             break;
  581.  
  582.         case SDLK_LEFT:
  583.  
  584.             if (direction != RIGHT)
  585.  
  586.             direction = LEFT;
  587.  
  588.             break;
  589.  
  590.         default:
  591.  
  592.             /* nothing */
  593.  
  594.             break;
  595.  
  596.     }
  597.  
  598.  
  599.  
  600.     return direction;
  601.  
  602. }
  603.  
  604.  
  605.  
  606. /* generate a position (x;y) for a new apple */
  607.  
  608. SDL_Rect generateApplePosition(Snake s)
  609.  
  610. {
  611.  
  612.     Snake tmpSnake = NULL;
  613.  
  614.     SDL_Rect positionApple; /* will contains (x;y) */
  615.  
  616.  
  617.  
  618.     /* we use rand() to generate "random" numbers.
  619.  
  620.     the cartesian coordinates of the apple must not be the
  621.  
  622.     same as those of a snake's part */
  623.  
  624.  
  625.  
  626.     int ok;
  627.  
  628.  
  629.  
  630.     /* to solve this problem, in the first time, we generate a x
  631.  
  632.     which is different from all the x of the snake's parts */
  633.  
  634.     do {
  635.  
  636.         ok = 0;
  637.  
  638.         positionApple.x = (rand()%((WINDOW_WIDTH)-(SNAKE_WIDTH))); /* the apple must be on the game screen... */
  639.  
  640.         positionApple.x = positionApple.x - positionApple.x%(SNAKE_WIDTH);
  641.  
  642.         tmpSnake = s;
  643.  
  644.         while (tmpSnake != NULL && ok == 0) {
  645.  
  646.             if (tmpSnake->position.x == positionApple.x)
  647.  
  648.                 ok = 1;
  649.  
  650.             tmpSnake = tmpSnake->next;
  651.  
  652.         }
  653.  
  654.     } while(ok);
  655.  
  656.  
  657.  
  658.  
  659.  
  660.     /* we do the same for y */
  661.  
  662.     do {
  663.  
  664.         ok = 0;
  665.  
  666.         positionApple.y = (rand()%((WINDOW_HEIGHT)-(SNAKE_HEIGHT+MENU_HEIGHT))); /* the apple must be on the game screen... */
  667.  
  668.         positionApple.y = positionApple.y - positionApple.y%(SNAKE_HEIGHT);
  669.  
  670.         tmpSnake = s;
  671.  
  672.         while (tmpSnake != NULL && ok == 0) {
  673.  
  674.             if (tmpSnake->position.y == positionApple.y)
  675.  
  676.                 ok = 1;
  677.  
  678.             tmpSnake = tmpSnake->next;
  679.  
  680.         }
  681.  
  682.     } while(ok);
  683.  
  684.  
  685.  
  686.     /* we have the new position */
  687.  
  688.     return positionApple;
  689.  
  690. }
  691.  
  692.  
  693.  
  694. int verifyGame(Snake s, int direction)
  695.  
  696. {
  697.  
  698.     Snake tmpSnake;
  699.  
  700.     int ok = 1; /* 1 means everything is ok */
  701.  
  702.  
  703.  
  704.     /* just in case */
  705.  
  706.     if (s == NULL)
  707.  
  708.         return ok;
  709.  
  710.  
  711.  
  712.     /* test collisions with the borders/edges */
  713.  
  714.     if ((s->position.x <= 0 && direction == LEFT) || (s->position.x >= (WINDOW_WIDTH-SNAKE_WIDTH) && direction == RIGHT) || (s->position.y <= 0 && direction == UP) || (s->position.y >= (WINDOW_HEIGHT-MENU_HEIGHT-SNAKE_HEIGHT) && direction == DOWN))
  715.  
  716.         ok = 0;
  717.  
  718.  
  719.  
  720.     /* test collision of the head with the body */
  721.  
  722.     tmpSnake = s->next;
  723.  
  724.     while (tmpSnake != NULL && ok == 1) {
  725.  
  726.         /* it means 2 snake's parts have the same (x;y) positions */
  727.  
  728.         if (tmpSnake->position.x == s->position.x && tmpSnake->position.y == s->position.y)
  729.  
  730.             ok = 0;
  731.  
  732.         tmpSnake = tmpSnake->next;
  733.  
  734.     }
  735.  
  736.  
  737.  
  738.     return ok;
  739.  
  740. }