home *** CD-ROM | disk | FTP | other *** search
/ Revista do CD-ROM 123 / cdrom123.iso / edu / tux / Tuxtype2-1.5.3-installer.exe / src / snow.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-01-21  |  6.7 KB  |  273 lines

  1. /***************************************************************************
  2.  -  file: snow.c
  3.  -  description: this file contains snow for the cascade game
  4. -------------------
  5. begin                : March 12, 2003
  6. copyright            : (C) 2003 Jesse Andrews
  7. email                : tuxtype-dev@tux4kids.net
  8. ***************************************************************************/
  9.  
  10. /***************************************************************************
  11. *                                                                         *
  12. *   This program is free software; you can redistribute it and/or modify  *
  13. *   it under the terms of the GNU General Public License as published by  *
  14. *   the Free Software Foundation; either version 2 of the License, or     *
  15. *   (at your option) any later version.                                   *
  16. *                                                                         *
  17. ***************************************************************************/
  18.  
  19. #include <stdlib.h>
  20. #include "SDL.h"
  21.  
  22. /* while it looks like you can just
  23.  * change the number of planes, flakes,
  24.  * etc and it will work alright, it is not
  25.  * true.  Do not fidle with number unless you
  26.  * change the rest of the code to be the same!
  27.  */
  28.  
  29. #define NUM_PLANES 3
  30.  
  31. extern SDL_Surface *screen;
  32. extern SDL_Surface *bkg;
  33.  
  34. Uint16 snow_color;
  35.  
  36. int wind=0;
  37. int SNOW_on = 0;
  38.  
  39. int NUM_FLAKES = 300;
  40. int PER_PLANE = 100; // should equal NUM_FLAKES/NUM_PLANES
  41.  
  42. /* to get the real x location divide by 8 (>>3)
  43.  */
  44. struct {
  45.     int x;
  46.     int y;
  47. } flake[300];
  48.  
  49. /* used for the SDL_UpdateRects */
  50. SDL_Rect SNOW_rects[1000];
  51.  
  52. /* pass add_wind +/- 1 --- it just adds a fraction in that direction! */
  53. void add_wind( int dir ) {
  54.  
  55.     /* don't let the wind blow too hard */
  56.     if ( wind * dir > 16 )
  57.         return;
  58.     
  59.     if (dir > 0)
  60.         wind++;
  61.     else
  62.         wind--;
  63. }
  64.  
  65. /* ### INTERNAL FUNCTION ### 
  66.  * move_snow: updates the location of the flakes
  67.  * based upon the wind and different "planes"
  68.  * of the flakes
  69.  */
  70. void move_snow(void) {
  71.     int i;
  72.     static int slowframe=1;
  73.     int ws=wind;
  74.  
  75.     slowframe = !slowframe;
  76.     /* even though we only move the "slowest" every other frame,
  77.      * the code is still updating them every single frame!!!
  78.      * the SNOW_Rect data structure will need to be updated to fix this!
  79.      * slowframe just cycles between updating the slowest and not!
  80.      */
  81.     if (slowframe) {
  82.         for (i = 0; i<PER_PLANE; i++) {
  83.             flake[i].x += ws;
  84.             flake[i].y ++;
  85.         }
  86.     }
  87.  
  88.     for (i = PER_PLANE; i<PER_PLANE<<1; i++) {
  89.         flake[i].x += ws;
  90.         flake[i].y += 1;
  91.     }
  92.  
  93.     ws<<=1;
  94.     for (i = PER_PLANE<<1; i<NUM_FLAKES; i++) {
  95.         flake[i].x += ws;
  96.         flake[i].y += 2;
  97.     } 
  98.  
  99.     for (i = 0; i<NUM_FLAKES; i++) {
  100.         /* if a flake hits the bottom, move to top randomly */
  101.         if (flake[i].y >= 478) {
  102.             flake[i].y = 0;
  103.             flake[i].x = (int)(8*639.0*rand()/(RAND_MAX+1.0));
  104.         }
  105.  
  106.         /* if a flake hists the edge, move to the other edge randomly */
  107.         if (flake[i].x >= 638<<3) {
  108.             flake[i].x = 0;
  109.             flake[i].y = (int)(478.0*rand()/(RAND_MAX+1.0));
  110.         } else if (flake[i].x < 0) {
  111.             flake[i].x = 8*637;
  112.             flake[i].y = (int)(478.0*rand()/(RAND_MAX+1.0));
  113.         }
  114.  
  115.         /* the first NUM_FLAKES are for erasing the last frame's FLAKES */
  116.         SNOW_rects[i].x = SNOW_rects[NUM_FLAKES+i].x;
  117.         SNOW_rects[i].y = SNOW_rects[NUM_FLAKES+i].y;
  118.         /* the next NUM_FLAKES are for bliting the new positions this frame */
  119.         SNOW_rects[NUM_FLAKES+i].x = flake[i].x>>3;
  120.         SNOW_rects[NUM_FLAKES+i].y = flake[i].y;
  121.     }
  122. }
  123.  
  124. /* SNOW_draw: updates the screen surface
  125.  * with the new flake pixels
  126.  * note: y<<9 + y<<7 is short for y*640
  127.  */
  128. void SNOW_draw(void) {
  129.     int i;
  130.     Uint16 *to;
  131.  
  132.     /* we only draw if we are on and haven't toggled (see SNOW_Erase for more info */
  133.     if (SNOW_on!=1)
  134.         return;
  135.  
  136.     for (i=0; i<NUM_FLAKES; i++) {
  137.         to = screen->pixels;
  138.         to += (SNOW_rects[NUM_FLAKES+i].y<<9) + (SNOW_rects[NUM_FLAKES+i].y<<7) + SNOW_rects[NUM_FLAKES+i].x;
  139.         *to = snow_color;
  140.         to += 1;
  141.         *to = snow_color;
  142.         to += 640;
  143.         *to = snow_color;
  144.         to -= 1;
  145.         *to = snow_color;
  146.     }
  147. }
  148.  
  149. /* SNOW_erase: updates the screen surface
  150.  * by replacing the previous flakes with
  151.  * the background image (set via SNOW_setBkg).
  152.  * This should be run before bliting any
  153.  * graphics to the screen so you don't over-
  154.  * write good images with background!
  155.  *
  156.  * note: y<<9 + y<<7 is short for y*640
  157.  */
  158. void SNOW_erase(void) {
  159.     int i;
  160.     Uint16 *from, *to;
  161.  
  162.     if (!SNOW_on)
  163.         return;
  164.  
  165.     /* SNOW_on isn't a boolean variable, it is really
  166.      * holding the state:
  167.      *  0 means no snow
  168.      *  1 means snow
  169.      *  2 means the user has requested snowing to stop
  170.      *          we cannot just stop snowing since we
  171.      *          need to erase the previous frames snow
  172.      *  3 means have erased the snow during the previous
  173.      *          frame and can go back to waiting for
  174.      *          snow to be turned on
  175.      */
  176.     if (SNOW_on>1) {
  177.         if (SNOW_on == 3)
  178.             SNOW_on = 0;
  179.         else
  180.             SNOW_on++;
  181.     }
  182.  
  183.     for (i=0; i<NUM_FLAKES; i++) {
  184.         to = screen->pixels;
  185.         from = bkg->pixels;
  186.         to += (SNOW_rects[i].y<<9) + (SNOW_rects[i].y<<7) + SNOW_rects[i].x;
  187.         from += (SNOW_rects[i].y<<9) + (SNOW_rects[i].y<<7) + SNOW_rects[i].x;
  188.         *to = *from;
  189.         to += 1;
  190.         from += 1;
  191.         *to = *from;
  192.         to += 640;
  193.         from += 640;
  194.         *to = *from;
  195.         to -= 1;
  196.         from -= 1;
  197.         *to = *from;
  198.     }
  199. }
  200.  
  201. /* SNOW_setBkg: we need to have the  background
  202.  * to erase snow flakes every frame
  203.  */
  204. void SNOW_setBkg( SDL_Surface *img ) {
  205.     bkg = img;
  206. }
  207.  
  208. /* SNOW_add: this adds the other rectangles that we need 
  209.  * to update on the screen to the list and returns
  210.  * the total number of items on the complete list
  211.  * (flakes & regular stuff)
  212.  */
  213. int SNOW_add( SDL_Rect *rs, int num ){
  214.     int i;
  215.     for (i=0; i<num; i++) {
  216.         SNOW_rects[(NUM_FLAKES<<1)+i].x = rs[i].x;
  217.         SNOW_rects[(NUM_FLAKES<<1)+i].y = rs[i].y;
  218.         SNOW_rects[(NUM_FLAKES<<1)+i].w = rs[i].w;
  219.         SNOW_rects[(NUM_FLAKES<<1)+i].h = rs[i].h;
  220.     }
  221.     return num + (NUM_FLAKES<<1);
  222. }
  223.  
  224. /* SNOW_init: initing the snow "library" envoles
  225.  * seting up the color for the snow, the inital
  226.  * locations for the flakes and the size of the
  227.  * snow rectangles
  228.  */
  229. void SNOW_init( void ) {
  230.  
  231.     int i;
  232.  
  233.     snow_color = SDL_MapRGB( screen->format, 255, 255, 255 );
  234.     for (i=0; i<NUM_FLAKES; i++) {
  235.         flake[i].x = (int)(8*638.0*rand()/(RAND_MAX+1.0));
  236.         flake[i].y = (int)(480.0*rand()/(RAND_MAX+1.0));
  237.     }
  238.     for (i=0; i<2*NUM_FLAKES; i++) {
  239.         SNOW_rects[i].w = 2;
  240.         SNOW_rects[i].h = 2;
  241.     }
  242. }
  243.  
  244. /* SNOW_toggle: toggles the snow on and off.
  245.  * see SNOW_erase for a discription of what
  246.  * SNOW_on means
  247.  */
  248. void SNOW_toggle( void ) {
  249.     SNOW_on ++;
  250. }
  251.  
  252. /* SNOW_update: update the wind with
  253.  * a 10% prob of blowing further left
  254.  * a 10% prob of blowing further right
  255.  * and 80% of not changing.
  256.  * AFTER updating the wind, we move all
  257.  * the snow
  258.  */
  259. void SNOW_update( void ) {
  260.     int rand_tmp = (int)(10.0*rand()/(RAND_MAX+1.0));
  261.  
  262.     if (!SNOW_on)
  263.         return;
  264.  
  265.     if (rand_tmp == 0)
  266.         add_wind(-1);
  267.     else if (rand_tmp == 1)
  268.         add_wind(+1);
  269.     
  270.     move_snow();
  271. }
  272.  
  273.