lavat

Un fork de lavat pour pouvoir y ajouter des titres - retour accueil

git clone git://bebou.netlib.re/lavat
Log | Files | Refs | README | LICENSE |

lavat.c (11528B)


      1 #define TB_IMPL
      2 
      3 #include "termbox.h"
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <string.h>
      7 #include <time.h>
      8 #include <unistd.h>
      9 
     10 #define MIN_NBALLS 5
     11 #define MAX_NBALLS 20
     12 
     13 typedef struct {
     14   int x;
     15   int y;
     16   int dx;
     17   int dy;
     18 } Ball;
     19 
     20 static char *custom = NULL;
     21 static char *custom2 = NULL;
     22 static short color = TB_WHITE;
     23 static short color2 = TB_WHITE;
     24 static short party = 0;
     25 static int nballs = 10;
     26 static short speedMult = 5;
     27 static short rim = 1;
     28 static short contained = 0;
     29 static float radiusIn = 100;
     30 static float radius;
     31 static int margin;
     32 static float sumConst;
     33 static float sumConst2;
     34 static int maxX, maxY;
     35 static int speed;
     36 static Ball balls[MAX_NBALLS] = {0};
     37 static struct tb_event event = {0};
     38 static short colors[]={TB_WHITE, TB_RED, TB_YELLOW, TB_BLUE, TB_GREEN, TB_MAGENTA, TB_CYAN, TB_BLACK };
     39 
     40 void init_params();
     41 void event_handler();
     42 int parse_options(int argc, char *argv[]);
     43 void print_help();
     44 short next_color(short current);
     45 void fix_rim_color();
     46 void set_random_colors(short level);
     47 
     48 int main(int argc, char *argv[]) {
     49 
     50   if (!parse_options(argc, argv))
     51     return 0;
     52 
     53   time_t t;
     54   // Ball *balls = malloc(sizeof(Ball) * nballs);
     55 
     56   srand((unsigned)time(&t));
     57 
     58   tb_init();
     59 
     60   tb_hide_cursor();
     61 
     62   init_params();
     63 
     64   while (1) {
     65 
     66     // move balls
     67     for (int i = 0; i < nballs; i++) {
     68 
     69       if (balls[i].x + balls[i].dx >= maxX - margin ||
     70           balls[i].x + balls[i].dx < margin)
     71         balls[i].dx *= -1;
     72 
     73       if (balls[i].y + balls[i].dy >= maxY - margin ||
     74           balls[i].y + balls[i].dy < margin)
     75         balls[i].dy *= -1;
     76 
     77       balls[i].x += balls[i].dx;
     78       balls[i].y += balls[i].dy;
     79     }
     80 
     81 	int w=tb_width();
     82 	int h=tb_height();
     83 
     84 	insert_here
     85 
     86     // render
     87     for (int i = 0; i < maxX; i++) {
     88       for (int j = 0; j < maxY / 2; j++) {
     89         // calculate the two halfs of the block at the same time
     90         float sum[2] = {0};
     91 
     92         for (int j2 = 0; j2 < (!custom ? 2 : 1); j2++) {
     93 
     94           for (int k = 0; k < nballs; k++) {
     95             int y = j * 2 + j2;
     96             sum[j2] += (radius * radius) /
     97                        ((float)((i - balls[k].x) * (i - balls[k].x) +
     98                                 (y - balls[k].y) * (y - balls[k].y)));
     99           }
    100         }
    101 
    102         if (!custom) {
    103           if (sum[0] > sumConst) {
    104             if (sum[1] > sumConst) {
    105               tb_printf(i, j, color2, 0, "█");
    106             } else {
    107               tb_printf(i, j, color2, 0, "▀");
    108             }
    109           } else if (sum[1] > sumConst) {
    110             tb_printf(i, j, color2, 0, "▄");
    111           }
    112 
    113           if (rim) {
    114             if (sum[0] > sumConst2) {
    115               if (sum[1] > sumConst2) {
    116                 tb_printf(i, j, color, 0, "█");
    117               } else {
    118                 tb_printf(i, j, color2, color, "▄");
    119               }
    120             } else if (sum[1] > sumConst2) {
    121               tb_printf(i, j, color2, color, "▀");
    122             }
    123           }
    124         } else {
    125           if (sum[0] > sumConst) {
    126             tb_printf(i, j, color2, 0, custom2);
    127           }
    128 
    129           if (rim) {
    130             if (sum[0] > sumConst2) {
    131               tb_printf(i, j, color, 0, custom);
    132             }
    133           }
    134         }
    135       }
    136     }
    137     if (party>0){
    138       set_random_colors(party);
    139     }
    140     tb_present();
    141     usleep(speed);
    142     tb_clear();
    143 
    144     tb_peek_event(&event, 10);
    145 
    146     event_handler();
    147   }
    148 
    149   tb_shutdown();
    150 
    151   // free(balls);
    152 }
    153 
    154 void event_handler() {
    155   if (event.type == TB_EVENT_RESIZE) {
    156     do
    157       tb_peek_event(&event, 10);
    158     while (event.type == TB_EVENT_RESIZE);
    159 
    160     init_params();
    161   } else if (event.type == TB_EVENT_KEY) {
    162 
    163     if (event.key == TB_KEY_CTRL_C || event.key == TB_KEY_ESC) {
    164       tb_shutdown();
    165       exit(0);
    166     }
    167 
    168     switch (event.ch) {
    169     case '-':
    170     case '_':
    171       if (speedMult < 10) {
    172         speedMult++;
    173         speed = (((1 / (float)(maxX + maxY)) * 1000000) + 10000) * speedMult;
    174       }
    175       break;
    176     case '+':
    177     case '=':
    178       if (speedMult > 1) {
    179         speedMult--;
    180         speed = (((1 / (float)(maxX + maxY)) * 1000000) + 10000) * speedMult;
    181       }
    182       break;
    183     case 'm':
    184     case 'M':
    185       if (nballs + 1 <= MAX_NBALLS) {
    186         nballs++;
    187       }
    188       break;
    189     case 'l':
    190     case 'L':
    191       if (nballs - 1 >= MIN_NBALLS) {
    192         nballs--;
    193       }
    194       break;
    195     case 'i':
    196       if (radiusIn + 10 <= 150) {
    197         radiusIn += 10;
    198         radius = (radiusIn * radiusIn + (float)(maxX * maxY)) / 15000;
    199         margin = contained ? radius * 10 : 0;
    200       }
    201       break;
    202     case 'd':
    203       if (radiusIn - 10 >= 50) {
    204         radiusIn -= 10;
    205         radius = (radiusIn * radiusIn + (float)(maxX * maxY)) / 15000;
    206         margin = contained ? radius * 10 : 0;
    207       }
    208       break;
    209     case 'I':
    210 
    211       if (color != TB_WHITE || custom)
    212         if (rim + 1 <= 5) {
    213           rim++;
    214           sumConst2 = sumConst * (1 + (float)(0.25 * rim));
    215         }
    216       break;
    217     case 'D':
    218 
    219       if (color != TB_WHITE || custom)
    220         if (rim - 1 >= 0) {
    221           rim--;
    222           sumConst2 = sumConst * (1 + (float)(0.25 * rim));
    223         }
    224       break;
    225     case 'c':
    226       color = next_color(color);
    227       fix_rim_color();
    228       break;
    229     case 'k':
    230       color2 = next_color(color2);
    231       fix_rim_color();
    232       break;
    233     case 'p':
    234       party = (party+1)%4;
    235       break;
    236     case 'q':
    237     case 'Q':
    238       tb_shutdown();
    239       exit(0);
    240       break;
    241     }
    242   }
    243 }
    244 
    245 void init_params() {
    246 
    247   maxX = tb_width();
    248   maxY = tb_height() * 2;
    249   speedMult = 11 - speedMult;
    250   speed = (((1 / (float)(maxX + maxY)) * 1000000) + 10000) * speedMult;
    251   radius = (radiusIn * radiusIn + (float)(maxX * maxY)) / 15000;
    252 
    253   margin = contained ? radius * 10 : 0;
    254 
    255   sumConst = 0.0225;
    256   sumConst2 = sumConst * (1 + (float)(0.25 * rim));
    257 
    258   custom2 = custom;
    259 
    260   if (color2 == TB_WHITE || !rim)
    261     color2 = color | TB_BOLD;
    262 
    263   if (custom && strlen(custom) > 1 && rim) {
    264     custom2 = custom + 1;
    265   }
    266 
    267   for (int i = 0; i < MAX_NBALLS; i++) {
    268     balls[i].x = rand() % (maxX - 2 * margin) + margin;
    269     balls[i].y = rand() % (maxY - 2 * margin) + margin;
    270     balls[i].dx = (rand() % 2 == 0) ? -1 : 1;
    271     balls[i].dy = (rand() % 2 == 0) ? -1 : 1;
    272   }
    273 }
    274 
    275 short next_color(short current){
    276   for(int i = 0; i<8; i++){
    277     if((current == colors[i])||(current == (colors[i] | TB_BOLD ))){
    278       return colors[(i+1)%8];
    279     }
    280   }
    281   return colors[0];
    282 }
    283 
    284 void fix_rim_color(){
    285   if(color2 == color){
    286     color2 = color2 | TB_BOLD;
    287   }
    288 }
    289 
    290 void set_random_colors( short level){
    291   if(level==1 || level==3) color = colors[ rand() % 7];
    292   if(level==2 || level==3) color2 = colors[ rand() % 7];
    293   fix_rim_color();
    294 }
    295 
    296 int set_color(short *var, char *optarg) {
    297 
    298   if (strcmp(optarg, "red") == 0) {
    299     *var = TB_RED;
    300   } else if (strcmp(optarg, "yellow") == 0) {
    301     *var = TB_YELLOW;
    302   } else if (strcmp(optarg, "blue") == 0) {
    303     *var = TB_BLUE;
    304   } else if (strcmp(optarg, "green") == 0) {
    305     *var = TB_GREEN;
    306   } else if (strcmp(optarg, "magenta") == 0) {
    307     *var = TB_MAGENTA;
    308   } else if (strcmp(optarg, "cyan") == 0) {
    309     *var = TB_CYAN;
    310   } else if (strcmp(optarg, "black") == 0) {
    311     *var = TB_BLACK;
    312   } else if (strcmp(optarg, "white") == 0) {
    313     *var = TB_WHITE;
    314   } else {
    315     printf("Unknown color: %s\n", optarg);
    316     return 0;
    317   }
    318   return 1;
    319 }
    320 
    321 int parse_options(int argc, char *argv[]) {
    322   if (argc == 1)
    323     return 1;
    324   int c;
    325   while ((c = getopt(argc, argv, ":c:k:s:r:R:b:F:Cp:h")) != -1) {
    326     switch (c) {
    327     case 'c':
    328       if (!set_color(&color, optarg))
    329         return 0;
    330       break;
    331     case 'k':
    332       if (!set_color(&color2, optarg))
    333         return 0;
    334       break;
    335     case 's':
    336       speedMult = atoi(optarg);
    337       if (speedMult > 10 || speedMult <= 0) {
    338         printf("Invalid speed, only values between 1 and 10 are allowed\n");
    339         return 0;
    340       }
    341       break;
    342     case 'R':
    343       rim = atoi(optarg);
    344       if (rim > 5 || rim < 1) {
    345         printf("Invalid rim, only values between 1 and 5 are allowed\n");
    346         return 0;
    347       }
    348       break;
    349     case 'r':
    350       radiusIn = 50 + atoi(optarg) * 10;
    351       if (radiusIn > 150 || radiusIn < 50) {
    352         printf("Invalid radius, only values between 1 and 10 are allowed\n");
    353         return 0;
    354       }
    355       break;
    356 
    357     case 'b':
    358       nballs = atoi(optarg);
    359       if (nballs > MAX_NBALLS || nballs < MIN_NBALLS) {
    360 
    361         printf("Invalid number of metaballs, only values between %i and %i are"
    362                "allowed\n",
    363                MIN_NBALLS, MAX_NBALLS);
    364         return 0;
    365       }
    366       break;
    367     case 'F':
    368       custom = optarg;
    369       break;
    370     case 'C':
    371       contained = 1;
    372       break;
    373     case 'p':
    374       party = atoi(optarg);
    375       if (party < 0 || party > 3 ) {
    376         printf("Invalid party mode, only values between 1 and 3 are allowed\n");
    377         return 0;
    378       }
    379       break;
    380     case 'h':
    381       print_help();
    382       return 0;
    383       break;
    384     case ':':
    385       fprintf(stderr, "Option -%c requires an operand\n", optopt);
    386       return 0;
    387       break;
    388     case '?':
    389       fprintf(stderr, "Unrecognized option: -%c\n", optopt);
    390       return 0;
    391     }
    392   }
    393   return 1;
    394 }
    395 
    396 void print_help() {
    397   printf(
    398       "Usage: lavat [OPTIONS]\n"
    399       "OPTIONS:\n"
    400       "  -c <COLOR>          Set color. Available colours: red, blue, yellow, "
    401       "green, cyan, magenta, white and black. \n"
    402       "  -s <SPEED>          Set the speed, from 1 to 10. (default 5)\n"
    403       "  -r <RADIUS>         Set the radius of the metaballs, from 1 to 10. "
    404       "(default: 5)\n"
    405       "  -R <RIM>            Set a rim for each metaball, sizes from 1 to 5."
    406       "(default: none)\n"
    407       "                      This option does not work with the default "
    408       "color\n"
    409       "                      If you use Kitty or Alacritty you must use it "
    410       "with the -k option to see the rim.\n"
    411       "  -k <COLOR>          Set the color of the rim if there is one."
    412       " Available colours: red, blue, yellow, green, cyan, magenta, white and black. \n"
    413       "  -b <NBALLS>         Set the number of metaballs in the simulation, "
    414       "from %i to %i. (default: 10)\n"
    415       "  -F <CHARS>          Allows for a custom set of chars to be used\n"
    416       "                      Only ascii symbols are supported for now, "
    417       "wide/unicode chars may appear broken.\n"
    418       "  -C                  Retain the entire lava inside the terminal.\n"
    419       "                      It may not work well with a lot of balls or with"
    420       " a bigger radius than the default one.\n"
    421       "  -p <MODE>           PARTY!! THREE MODES AVAILABLE (p1, p2 and p3).\n"
    422       "  -h                  Print help.\n"
    423       "RUNTIME CONTROLS:\n"
    424       "  i                   Increase radius of the metaballs.\n"
    425       "  d                   Decrease radius of the metaballs.\n"
    426       "  shift i             Increase rim of the metaballs.\n"
    427       "  shift d             Decrease rim of the metaballs.\n"
    428       "  m                   Increase the number of metaballs.\n"
    429       "  l                   Decrease the number metaballs.\n"
    430       "  c                   Change the color of the metaballs.\n"
    431       "  k                   Change the rim color of the metaballs.\n"
    432       "  +                   Increase speed.\n"
    433       "  -                   Decrease speed.\n"
    434       "  p                   TURN ON THE PARTY AND CYCLE THROUGH THE PARTY MODES "
    435       "(it can also turns off the party).\n"
    436       "(Tip: Zoom out in your terminal before running the program to get a "
    437       "better resolution of the lava).\n",
    438       MIN_NBALLS, MAX_NBALLS);
    439 }