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 }