home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / SVGALIB / SVGALIB1.TAR / svgalib / demos / fun.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-27  |  9.6 KB  |  497 lines

  1. /* Roaming-blobs-on-mars-collect-some-dust-on-a-tropical-island-and-go-pearl-
  2.    diving-before-population-goes-out-of-control. */
  3.  
  4. /* Each frame, a background virtual screen is copied to a virtual screen; */
  5. /* sprites (well, pixels) are written on that virtual screen; and the */
  6. /* virtual screen is copied to video memory. The background is updated as */
  7. /* appropriate. This simple animation technique works well for 320x200 */
  8. /* because it's so small. */
  9.  
  10.  
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <vga.h>
  14. #include <vgagl.h>
  15.  
  16.  
  17. /* This can be changed into any 256 color mode. */
  18. /* For planar 256 color modes, enable page flipping. */
  19. /* Even 16 color modes work (ugly colors). */
  20. #define VGAMODE G320x200x256
  21.  
  22. /* #define USE_PAGEFLIPPING */
  23.  
  24. /* #define USE_SMALLOC */
  25.  
  26. /* This is the size of the animated window. */
  27. #define MAPWIDTH 320
  28. #define MAPHEIGHT 190
  29.  
  30. #define MAXMOVERS 1000
  31. #define MAXCITIES 1000
  32. #define NUMBEROFCITIES 20
  33. #define NUMBEROFMOVERS 400
  34. #define MOVERTHRESHOLD 400
  35. #define MOVERLIFETIME 1000
  36. #define COLORTIME 2000
  37.  
  38. #define randomn( n ) (random() % n)
  39. #define red(x) (32 + x)
  40. #define green(x) (64 + x)
  41. #define yellow(x) (96 + x)
  42. #define blue(x) (128 + x)
  43. #define magenta(x) (160 + x)
  44. #define cyan(x) (192 + x)
  45. #define white(x) (224 + x)
  46.  
  47.  
  48. /* Data types */
  49.  
  50. typedef struct {
  51.     int x;
  52.     int y;
  53. } Position;
  54.  
  55. #define STAT_ACTIVE 1
  56.  
  57. typedef struct {
  58.     int stat;
  59.     int x;
  60.     int y;
  61.     int vx;
  62.     int vy;
  63.     int color;
  64.     int time;
  65. } Mover;
  66.  
  67. typedef struct {
  68.     int x;
  69.     int y;
  70.     int pop;
  71.     int hit;
  72. } City;
  73.  
  74. /* Global variables */
  75.  
  76. int map[MAPWIDTH][MAPHEIGHT];
  77. /* Map encoding i: */
  78. /* (0 - 0xffff    Mover number i) */
  79. /* 0x10000...    Part of city (i - 0x10000) */  
  80.  
  81. Mover mover[MAXMOVERS];
  82. int nu_movers = 0;
  83. City city[MAXCITIES];
  84. int nu_cities = 0;
  85. int time = 0;
  86. int pop = 0;
  87. int framerate, framecount, frameclock;
  88.  
  89. GraphicsContext *physicalscreen;
  90. GraphicsContext *backscreen;
  91. GraphicsContext *background;
  92.  
  93.  
  94. void error( char *s ) {
  95.     printf("%s\n", s);
  96.     vga_setmode(TEXT);
  97.     exit(0);
  98. }
  99.  
  100. void setcustompalette() {
  101.     /* colors 0-31 are a RGB mix (bits 0 and 1 red, 2 green, 3 and 4 blue) */
  102.     /* 32-63    black to red */
  103.     /* 64-95    black to green */
  104.     /* 96-127   black to yellow */
  105.     /* 128-159  black to blue */
  106.     /* 160-191  black to magenta */
  107.     /* 192-223  black to cyan */
  108.     /* 224-255  black to white */
  109.     Palette pal;
  110.     int i;
  111.     for (i = 0; i < 256; i++) {
  112.         int r, g, b;
  113.         r = g = b = 0;
  114.         if ((i & 32) > 0) r = (i & 31) << 1;
  115.         if ((i & 64) > 0) g = (i & 31) << 1;
  116.         if ((i & 128) > 0) b = (i & 31) << 1;
  117.         if (i < 32) {
  118.             r = (i & 3) << 4;   /* 2 bits */
  119.             g = (i & 4) << 3;   /* 1 bit */
  120.             b = (i & 24) << 1;  /* 2 bits */
  121.         }
  122.         pal.color[i].red = r;
  123.         pal.color[i].green = g;
  124.         pal.color[i].blue = b;
  125.     }
  126.     gl_setpalette(&pal);
  127. }
  128.  
  129. void initfont() {
  130.     void *font;
  131. #ifdef USE_SMALLOC
  132.     font = smalloc(256 * 8 * 8 * BYTESPERPIXEL);
  133. #else    
  134.     font = malloc(256 * 8 * 8 * BYTESPERPIXEL);
  135. #endif
  136.     gl_expandfont(8, 8, white(24), gl_font8x8, font);
  137.     gl_setfont(8, 8, font);
  138. }
  139.  
  140. int fsize( FILE *f ) {
  141.     int oldpos, size;
  142.     oldpos = ftell(f);
  143.     fseek(f, 0, SEEK_END);
  144.     size = ftell(f);
  145.     fseek(f, oldpos, SEEK_SET);
  146.     return size;
  147. }
  148.  
  149. void loadfile( char **buf, char *fname ) {
  150.     FILE *f;
  151.     int size;
  152.     f = fopen(fname, "rb");
  153.     size = fsize(f);
  154.     *buf = malloc(size);
  155.     fread(*buf, 1, size, f);
  156.     fclose(f);
  157. }
  158.  
  159.  
  160. /* Map */
  161.  
  162. void clearmap() {
  163.     int x, y;
  164.     for (y = 0; y < MAPHEIGHT; y++)
  165.         for (x = 0; x < MAPWIDTH; x++)
  166.             map[x][y] = 0;
  167. }
  168.  
  169. Position findfreeposition() {
  170.     int x, y;
  171.     Position p;
  172.     do {
  173.         x = randomn(MAPWIDTH);
  174.         y = randomn(MAPHEIGHT);
  175.     } while (map[x][y] != 0);
  176.     p.x = x;
  177.     p.y = y;
  178.     return p;
  179.  
  180.  
  181. /* Movers */
  182.  
  183. void initmovers() {
  184.     int i;
  185.     for (i = 0; i < MAXMOVERS; i++)
  186.         mover[i].stat = 0;
  187. }
  188.  
  189. int findfreemoverslot() {
  190.     int i;
  191.     for (i = 0; i < MAXMOVERS; i++)
  192.         if (!(mover[i].stat & STAT_ACTIVE))
  193.             return i;
  194.     error("Mover table overflow");
  195. }
  196.  
  197. void addrandommover() {
  198.     Position p = findfreeposition();
  199.     int i = findfreemoverslot();
  200.     int c;
  201.     mover[i].x = p.x;
  202.     mover[i].y = p.y;
  203.     do {
  204.         mover[i].vx = randomn(3) - 1;
  205.         mover[i].vy = randomn(3) - 1;
  206.     } while (mover[i].vx == 0 && mover[i].vy == 0);
  207.     mover[i].stat = STAT_ACTIVE;
  208.     switch (randomn(4)) {
  209.         case 0 :
  210.             c = blue(20); break;
  211.         case 1 :
  212.             c = green(20); break;
  213.         case 2 :
  214.             c = magenta(20); break;
  215.         case 3 :
  216.             c = cyan(20); break;
  217.     }
  218.     mover[i].time = 0;
  219.     mover[i].color = c;
  220.     nu_movers++;
  221. }
  222.  
  223. void killmover( int i ) {
  224.     mover[i].stat = 0;
  225.     nu_movers--;
  226. }
  227.  
  228. void drawmover( int i ) {
  229.     gl_setpixel(mover[i].x, mover[i].y, mover[i].color);
  230. }
  231.  
  232.  
  233. /* Cities */
  234.  
  235. void initcities() {
  236.     nu_cities = 0;
  237. }
  238.  
  239. void addcity( int x, int y ) {
  240.     int i = nu_cities++;
  241.     map[x][y] = i + 0x10000;
  242.     city[i].x = x;
  243.     city[i].y = y;
  244.     city[i].pop = 1;
  245.     city[i].hit = 0;
  246. }
  247.  
  248. int cityat( int x, int y ) {
  249.     if (map[x][y] >= 0x10000)
  250.         return map[x][y] - 0x10000;
  251.     else
  252.         return -1;
  253. }
  254.  
  255. int citycolor() {
  256. static int colortable[5] =
  257.     { yellow(31), blue(31), white(31), green(31), cyan(31) };
  258.     return colortable[(time / COLORTIME) % 5] 
  259.         - (time % COLORTIME) * 25 / COLORTIME;   
  260. }
  261.  
  262. void growcity( int cx, int cy, int x, int y, int ct ) {
  263. /* add city unit at (x, y) adjacent to city unit (cx, cy) */
  264.     int c;
  265.     map[x][y] = ct + 0x10000;
  266.     c = citycolor();
  267.     gl_setpixel(x, y, c);    
  268.     city[ct].pop++;
  269.     city[ct].hit = 20;
  270.     pop++;
  271. }
  272.  
  273.  
  274. /* Main components */
  275.  
  276. void createbackground() {
  277. /* Create fancy dark red background */
  278.     int x, y;
  279.     for (y = 0; y < MAPHEIGHT; y++)
  280.         for (x = 0; x < MAPWIDTH; x++) {
  281.             int i = 0;
  282.             int n = 0;
  283.             int c;
  284.             if (x > 0) {
  285.                 i += gl_getpixel(x - 1, y) - red(0);
  286.                 n++;
  287.             }
  288.             if (y > 0) {
  289.                 i += gl_getpixel(x, y - 1) - red(0);
  290.                 n++;
  291.             }
  292.             c = (i + randomn(16)) / (n + 1);
  293.             if (c > 9)
  294.                 c = 9;
  295.             gl_setpixel(x, y, red(0) + c);
  296.         }
  297. }
  298.  
  299. void drawbackground() {
  300. /* Build up background from map data */
  301.     int x, y;
  302.     gl_setcontext(background);
  303.     gl_clearscreen(0);
  304.     createbackground();
  305.     for (y = 0; y < MAPHEIGHT; y++)
  306.         for (x = 0; x < MAPWIDTH; x++) {
  307.             int c = cityat(x, y);
  308.             if (c != -1)
  309.                 gl_setpixel(x, y, citycolor());
  310.         }
  311. }
  312.  
  313. void createcities() {
  314.     int i;
  315.     for (i = 0; i < NUMBEROFCITIES; i++) {
  316.         Position p = findfreeposition();
  317.         addcity(p.x, p.y);
  318.     }
  319. }
  320.  
  321. void writestat() {
  322.     char s[41];
  323.     int i, x, y;
  324.     int maxpopcity, maxpop;
  325.     sprintf(s, "Pop %7d  Time %7d  Rate %5d.%d", pop, time,
  326.         framerate / 10, framerate % 10);
  327.     gl_setwritemode(WRITEMODE_OVERWRITE);
  328.     gl_write(0, HEIGHT - 8, s);
  329.     maxpop = -1;
  330.     for (i = 0; i < nu_cities; i++)
  331.         if (city[i].pop > maxpop) {
  332.             maxpop = city[i].pop;
  333.             maxpopcity = i;
  334.         }
  335.  
  336.     gl_enableclipping();
  337.     gl_circle(city[maxpopcity].x, city[maxpopcity].y, 10,
  338.         blue(31));
  339.     gl_disableclipping();
  340.  
  341.     gl_setwritemode(WRITEMODE_MASKED);
  342.     x = city[maxpopcity].x;
  343.     y = city[maxpopcity].y;
  344.     sprintf(s, "%d", maxpop);
  345.     /* clipping */
  346.     if (x + strlen(s) * 8 > MAPWIDTH)
  347.         x = MAPWIDTH - strlen(s) * 8;
  348.     if (y + 8 > MAPHEIGHT)
  349.         y = MAPHEIGHT - 8;
  350.     gl_write(x, y, s);
  351. }
  352.  
  353. void drawscreen() {
  354.     int i;
  355.     /* Copy background to backscreen. */
  356.     gl_setcontext(background);
  357.     gl_copyscreen(backscreen);
  358.     
  359.     /* Now draw the objects in backscreen. */
  360.     gl_setcontext(backscreen);
  361.  
  362.     for (i = 0; i < MAXMOVERS; i++)
  363.         if (mover[i].stat & STAT_ACTIVE) {
  364.             drawmover(i);
  365.         }
  366.  
  367.     writestat();
  368.  
  369.     /* Copy backscreen to physical screen. */     
  370.     gl_copyscreen(physicalscreen);
  371. }
  372.  
  373. void move() {
  374.     int i;
  375.     gl_setcontext(background);
  376.     for (i = 0; i < MAXMOVERS; i++)
  377.         if (mover[i].stat & STAT_ACTIVE) {
  378.             int nx, ny;
  379.             int c;
  380.             if (++mover[i].time == MOVERLIFETIME) {
  381.                 killmover(i);
  382.                 continue;
  383.             }
  384.             for (;;) {
  385.                 nx = mover[i].x + mover[i].vx;
  386.                 ny = mover[i].y + mover[i].vy;
  387.                 if (nx < 0 || nx >= MAPWIDTH) {
  388.                     mover[i].vx = -mover[i].vx;
  389.                     continue;
  390.                 }
  391.                 if (ny < 0 || ny >= MAPHEIGHT) {
  392.                     mover[i].vy = -mover[i].vy;
  393.                     continue;
  394.                 }
  395.                 break;
  396.             }
  397.             c = cityat(nx, ny);
  398.             if (c != -1) {        /* found city */
  399.                 killmover(i);
  400.                 growcity(nx, ny, mover[i].x, mover[i].y, c);
  401.                 continue;    /* next mover */    
  402.             }
  403.             mover[i].x = nx;
  404.             mover[i].y = ny;
  405.         }
  406.     if (pop >= MAPWIDTH * MAPHEIGHT * 255 / 256) {
  407.         /* start all over again */
  408.         printf("fun: new run.\n");
  409.         pop = 0;
  410.         time = 0;
  411.         clearmap();
  412.         initcities();
  413.         createcities();
  414.         drawbackground();
  415.     }
  416. }
  417.  
  418. void createmovers() {
  419.     int i;
  420.     for (i = 0; i < NUMBEROFMOVERS; i++)
  421.         addrandommover();
  422. }
  423.  
  424. void main() {
  425.     vga_init();
  426.  
  427.     clearmap();
  428.     initmovers();
  429.     createcities();
  430.     createmovers();
  431.  
  432.     vga_setmode(VGAMODE);
  433.     gl_setcontextvga(VGAMODE);
  434.     physicalscreen = gl_allocatecontext();
  435.     gl_getcontext(physicalscreen);
  436.  
  437. #ifdef USE_PAGEFLIPPING    
  438.     /* Try to enable page flipping. */
  439.     gl_enablepageflipping(&physicalscreen);
  440. #endif
  441.     setcustompalette();
  442.     /* initfont() here caused trouble with planar 256 color modes. */
  443.  
  444.     gl_setcontextvgavirtual(VGAMODE);
  445.     backscreen = gl_allocatecontext();
  446.     gl_getcontext(backscreen);
  447. #ifdef USE_SMALLOC
  448.     free(backscreen.vbuf);
  449.     backscreen.vbuf = smalloc(BYTEWIDTH * HEIGHT);
  450.     gl_setcontext(backscreen);
  451. #endif
  452.  
  453.     initfont();
  454.  
  455.     gl_setcontextvgavirtual(VGAMODE);
  456.     background = gl_allocatecontext();
  457.     gl_getcontext(background);
  458. #ifdef USE_SMALLOC    
  459.     free(background.vbuf);
  460.     background.vbuf = smalloc(BYTEWIDTH * HEIGHT);
  461.     gl_setcontext(background);
  462. #endif
  463.  
  464.     drawbackground();
  465.  
  466.     framerate = 0;
  467.     framecount = 0;
  468.     frameclock = clock();
  469.  
  470.     for (;;) {
  471.         int i;
  472.         drawscreen();
  473.         move();
  474.         for (i = 0; i < 4; i++)
  475.             if (nu_movers < MOVERTHRESHOLD)
  476.                 addrandommover();
  477.         time++;
  478.         /* Update frame rate every 3 seconds. */
  479.         framecount++;
  480.         if (clock() - frameclock >= 300) {
  481.             framerate = framecount * 1000 / (clock() - frameclock);
  482.             framecount = 0;
  483.             frameclock = clock();
  484.         }
  485.  
  486.     }
  487.  
  488. #ifndef USE_SMALLOC
  489.     freecontext(backscreen);
  490.     freecontext(background);
  491. #endif    
  492.  
  493.     vga_setmode(TEXT);    
  494.     exit(0);
  495. }
  496.