mirror of
https://github.com/AngelJumbo/lavat.git
synced 2025-04-23 15:16:56 +00:00
Compare commits
No commits in common. "v1.1.0" and "main" have entirely different histories.
68
README.md
68
README.md
@ -1,7 +1,7 @@
|
||||
# lavat
|
||||
|
||||
Little program that simulates a lava lamp in the terminal.
|
||||

|
||||

|
||||
## Installation
|
||||
|
||||
Requirements: A Unix-like system, a C compiler and make.
|
||||
@ -9,7 +9,7 @@ Requirements: A Unix-like system, a C compiler and make.
|
||||
```
|
||||
git clone https://github.com/AngelJumbo/lavat
|
||||
cd lavat
|
||||
make install
|
||||
sudo make install
|
||||
```
|
||||
|
||||
### Arch Linux
|
||||
@ -22,38 +22,74 @@ $ paru -S lavat-git
|
||||
```
|
||||
Usage: lavat [OPTIONS]
|
||||
OPTIONS:
|
||||
-c COLOR Set color. Available colours: red, blue, yellow, green, cyan and magenta.
|
||||
Besides those colors the default one is the normal foreground of your terminal.
|
||||
-s SPEED Set the speed, from 1 to 5. (default 1)
|
||||
-r RADIUS Set the radius of the metaballs, from 1 to 10. (default: 5)
|
||||
-R RIM Set a "rim" for each metaball, sizes from 1 to 5. (default: none)
|
||||
This option does not work with the default color
|
||||
-b NBALLS Set the number of metaballs in the simulation, from 2 to 20. (default: 10)
|
||||
-F CHARS Allows for a custom set of chars to be used
|
||||
-h Print help.
|
||||
-g Enable gradient mode with truecolor support.
|
||||
Changes how -c and -k options work.
|
||||
-c <COLOR> Set color. In normal mode, available colors are: red, blue, yellow, green, cyan, magenta, white, and black.
|
||||
In gradient mode (-g), use hex format: RRGGBB (e.g., FF0000 for red).
|
||||
-k <COLOR> Set the rim color. Same format options as -c.
|
||||
In gradient mode, this sets the second color for the gradient.
|
||||
-s <SPEED> Set the speed, from 1 to 10. (default 5)
|
||||
-r <RADIUS> Set the radius of the metaballs, from 1 to 10. (default: 5)
|
||||
-R <RIM> Set a rim for each metaball, sizes from 1 to 5.(default: none)
|
||||
This option does not work with the default color
|
||||
If you use Kitty or Alacritty you must use it with the -k option to see the rim.
|
||||
-b <NBALLS> Set the number of metaballs in the simulation, from 5 to 20. (default: 10)
|
||||
-F <CHARS> Allows for a custom set of chars to be used
|
||||
Only ascii symbols are supported for now, wide/unicode chars may appear broken.
|
||||
-C Retain the entire lava inside the terminal.
|
||||
It may not work well with a lot of balls or with a bigger radius than the default one.
|
||||
-p <MODE> PARTY!! THREE MODES AVAILABLE (p1, p2 and p3).
|
||||
-h Print help.
|
||||
RUNTIME CONTROLS:
|
||||
i Increase radius of the metaballs.
|
||||
d Decrease radius of the metaballs.
|
||||
shift i Increase rim of the metaballs.
|
||||
shift d Decrease rim of the metaballs.
|
||||
m Increase the number of metaballs.
|
||||
l Decrease the number metaballs.
|
||||
c Change the color of the metaballs.
|
||||
k Change the rim color of the metaballs.
|
||||
+ Increase speed.
|
||||
- Decrease speed.
|
||||
p TURN ON THE PARTY AND CYCLE THROUGH THE PARTY MODES (it can also turns off the party).
|
||||
(Tip: Zoom out in your terminal before running the program to get a better resolution of the lava).
|
||||
EXAMPLES:
|
||||
lavat -c green -k red Use named colors in normal mode
|
||||
lavat -g -c 00FF00 -k FF0000 Use hex colors in gradient mode
|
||||
```
|
||||
|
||||
## Demo
|
||||
|
||||
`lavat -p3`
|
||||
|
||||

|
||||
|
||||
PARTY MODE!!!
|
||||
|
||||
`lavat -c red -R 1`
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
`lavat -c cyan -R 4 -b 20 -r 2`
|
||||
|
||||

|
||||

|
||||
|
||||
If you send more than one character to the -F option you can have 3d-ish effect.
|
||||
|
||||
`lavat -c blue -R2 -F @:::::: -r10`
|
||||
`lavat -c blue -R2 -F @@:::::: -r10`
|
||||
|
||||

|
||||

|
||||
|
||||
For the Alacritty and Kitty users I know that the -R option haven't been working for you, but now you can set the color of the rim independently. Try:
|
||||
|
||||
`lavat -c yellow -R1 -k red`
|
||||
|
||||

|
||||
|
||||
(The colors depend on your color scheme.)
|
||||
|
||||
## Credits
|
||||
|
||||
- This program is made with [Termbox2](https://github.com/termbox/termbox2).
|
||||
- [Metaballs](https://en.wikipedia.org/wiki/Metaballs).
|
||||
- [Lava lamp in JavaScript](https://codeguppy.com/site/tutorials/lava-lamp.html)
|
||||
|
505
lavat.c
505
lavat.c
@ -1,4 +1,6 @@
|
||||
#define TB_IMPL
|
||||
#define TB_LIB_OPTS
|
||||
#define TB_OPT_TRUECOLOR
|
||||
|
||||
#include "termbox.h"
|
||||
#include <stdio.h>
|
||||
@ -6,33 +8,98 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <float.h>
|
||||
|
||||
#define MIN_NBALLS 5
|
||||
#define MAX_NBALLS 20
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
int dx;
|
||||
int dy;
|
||||
} Ball;
|
||||
|
||||
uintattr_t pallete[11];
|
||||
int baseColor[3];
|
||||
int baseColor2[3];
|
||||
short gradient1=0;
|
||||
short gradient2=0;
|
||||
|
||||
static char *custom = NULL;
|
||||
static short color = TB_DEFAULT;
|
||||
static char *custom2 = NULL;
|
||||
static short color = TB_WHITE;
|
||||
static short color2 = TB_WHITE;
|
||||
static short party = 0;
|
||||
static int nballs = 10;
|
||||
static short speedMult = 1;
|
||||
static short rim = 0;
|
||||
static float radius = 100;
|
||||
static short speedMult = 5;
|
||||
static short rim = 1;
|
||||
static short contained = 0;
|
||||
static float radiusIn = 110;
|
||||
static float radius;
|
||||
static int margin;
|
||||
static float sumConst;
|
||||
static float sumConst2;
|
||||
static int maxX, maxY;
|
||||
static int speed;
|
||||
static Ball balls[MAX_NBALLS] = {0};
|
||||
static struct tb_event event = {0};
|
||||
static short colors[]={TB_WHITE, TB_RED, TB_YELLOW, TB_BLUE, TB_GREEN, TB_MAGENTA, TB_CYAN, TB_BLACK };
|
||||
|
||||
void init_params();
|
||||
void event_handler();
|
||||
int parse_options(int argc, char *argv[]);
|
||||
void print_help();
|
||||
short next_color(short current);
|
||||
void fix_rim_color();
|
||||
void set_random_colors(short level);
|
||||
|
||||
void set_pallete();
|
||||
uintattr_t get_color(float val);
|
||||
void set_pallete2();
|
||||
|
||||
int set_color(short *var, int *baseColor, char *optarg, short useGradient) {
|
||||
if (useGradient) {
|
||||
// Parse hex color
|
||||
if (sscanf(optarg, "%02x%02x%02x", &baseColor[0], &baseColor[1], &baseColor[2]) == 3) {
|
||||
return 1;
|
||||
} else {
|
||||
printf("Invalid hex color format. Use format: RRGGBB\n");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
// Parse named color
|
||||
if (strcmp(optarg, "red") == 0) {
|
||||
*var = TB_RED;
|
||||
} else if (strcmp(optarg, "yellow") == 0) {
|
||||
*var = TB_YELLOW;
|
||||
} else if (strcmp(optarg, "blue") == 0) {
|
||||
*var = TB_BLUE;
|
||||
} else if (strcmp(optarg, "green") == 0) {
|
||||
*var = TB_GREEN;
|
||||
} else if (strcmp(optarg, "magenta") == 0) {
|
||||
*var = TB_MAGENTA;
|
||||
} else if (strcmp(optarg, "cyan") == 0) {
|
||||
*var = TB_CYAN;
|
||||
} else if (strcmp(optarg, "black") == 0) {
|
||||
*var = TB_BLACK;
|
||||
} else if (strcmp(optarg, "white") == 0) {
|
||||
*var = TB_WHITE;
|
||||
} else {
|
||||
printf("Unknown color: %s\n", optarg);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
if (!parse_options(argc, argv))
|
||||
return 0;
|
||||
|
||||
if (color == TB_DEFAULT)
|
||||
rim = 0;
|
||||
|
||||
time_t t;
|
||||
Ball *balls = malloc(sizeof(Ball) * nballs);
|
||||
|
||||
struct tb_event event = {0};
|
||||
// Ball *balls = malloc(sizeof(Ball) * nballs);
|
||||
|
||||
srand((unsigned)time(&t));
|
||||
|
||||
@ -40,29 +107,20 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
tb_hide_cursor();
|
||||
|
||||
int maxX = tb_width();
|
||||
int maxY = tb_height() * 2;
|
||||
int speed = (((1 / (float)(maxX + maxY)) * 5000000) + 50000) / speedMult;
|
||||
radius = radius / (float)(maxX * maxY); //(float)(maxX > maxY ? maxX : maxY);
|
||||
init_params();
|
||||
|
||||
float innerRadius = radius * (1 + (float)(0.25 * rim));
|
||||
|
||||
for (int i = 0; i < nballs; i++) {
|
||||
balls[i].x = rand() % maxX;
|
||||
balls[i].y = rand() % maxY;
|
||||
balls[i].dx = (rand() % 2 == 0) ? -1 : 1;
|
||||
balls[i].dy = (rand() % 2 == 0) ? -1 : 1;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
||||
// move balls
|
||||
for (int i = 0; i < nballs; i++) {
|
||||
|
||||
if (balls[i].x + balls[i].dx >= maxX || balls[i].x + balls[i].dx < 0)
|
||||
if (balls[i].x + balls[i].dx >= maxX - margin ||
|
||||
balls[i].x + balls[i].dx < margin)
|
||||
balls[i].dx *= -1;
|
||||
|
||||
if (balls[i].y + balls[i].dy >= maxY || balls[i].y + balls[i].dy < 0)
|
||||
if (balls[i].y + balls[i].dy >= maxY - margin ||
|
||||
balls[i].y + balls[i].dy < margin)
|
||||
balls[i].dy *= -1;
|
||||
|
||||
balls[i].x += balls[i].dx;
|
||||
@ -75,92 +133,267 @@ int main(int argc, char *argv[]) {
|
||||
// calculate the two halfs of the block at the same time
|
||||
float sum[2] = {0};
|
||||
|
||||
for (int j2 = 0; j2 < 2; j2++) {
|
||||
for (int j2 = 0; j2 < (!custom ? 2 : 1); j2++) {
|
||||
|
||||
for (int k = 0; k < nballs; k++) {
|
||||
int y = j * 2 + j2;
|
||||
sum[j2] += 1 / ((float)((i - balls[k].x) * (i - balls[k].x) +
|
||||
(y - balls[k].y) * (y - balls[k].y)));
|
||||
float dist_squared = (i - balls[k].x) * (i - balls[k].x) + (y - balls[k].y) * (y - balls[k].y);
|
||||
if (dist_squared == 0) {
|
||||
sum[j2] += FLT_MAX;
|
||||
} else {
|
||||
sum[j2] += (radius * radius) / dist_squared;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!custom) {
|
||||
if (sum[0] > radius) {
|
||||
if (sum[1] > radius) {
|
||||
tb_printf(i, j, color | TB_BOLD, 0, "█");
|
||||
} else {
|
||||
tb_printf(i, j, color | TB_BOLD, 0, "▀");
|
||||
}
|
||||
} else if (sum[1] > radius) {
|
||||
tb_printf(i, j, color | TB_BOLD, 0, "▄");
|
||||
}
|
||||
|
||||
if (rim) {
|
||||
if (sum[0] > innerRadius) {
|
||||
if (sum[1] > innerRadius) {
|
||||
tb_printf(i, j, color, 0, "█");
|
||||
if (!custom) {
|
||||
if(gradient1){
|
||||
if (sum[0] > sumConst) {
|
||||
if (sum[1] > sumConst) {
|
||||
tb_printf(i, j, get_color( sum[0]), get_color(sum[1]), "▀");
|
||||
} else {
|
||||
tb_printf(i, j, color | TB_BOLD, color, "▄");
|
||||
tb_printf(i, j, get_color( sum[0]), TB_TRUECOLOR_DEFAULT, "▀");
|
||||
}
|
||||
} else if (sum[1] > sumConst) {
|
||||
tb_printf(i, j,get_color( sum[1]),TB_TRUECOLOR_DEFAULT, "▄");
|
||||
}
|
||||
|
||||
}else{
|
||||
if (sum[0] > sumConst) {
|
||||
if (sum[1] > sumConst) {
|
||||
tb_printf(i, j, color2, 0, "█");
|
||||
} else {
|
||||
tb_printf(i, j, color2, 0, "▀");
|
||||
}
|
||||
} else if (sum[1] > sumConst) {
|
||||
tb_printf(i, j, color2, 0, "▄");
|
||||
}
|
||||
|
||||
if (rim) {
|
||||
if (sum[0] > sumConst2) {
|
||||
if (sum[1] > sumConst2) {
|
||||
tb_printf(i, j, color, 0, "█");
|
||||
} else {
|
||||
tb_printf(i, j, color2, color, "▄");
|
||||
}
|
||||
} else if (sum[1] > sumConst2) {
|
||||
tb_printf(i, j, color2, color, "▀");
|
||||
}
|
||||
} else if (sum[1] > innerRadius) {
|
||||
tb_printf(i, j, color | TB_BOLD, color, "▀");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (sum[0] > radius) {
|
||||
tb_printf(i, j, color | TB_BOLD, 0, custom);
|
||||
if (sum[0] > sumConst) {
|
||||
tb_printf(i, j, color2, 0, custom2);
|
||||
}
|
||||
|
||||
if (rim) {
|
||||
if (sum[0] > innerRadius) {
|
||||
if (sum[0] > sumConst2) {
|
||||
tb_printf(i, j, color, 0, custom);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (party>0){
|
||||
set_random_colors(party);
|
||||
}
|
||||
tb_present();
|
||||
usleep(speed);
|
||||
tb_clear();
|
||||
|
||||
tb_peek_event(&event, 10);
|
||||
if (event.key == TB_KEY_CTRL_C || event.key == TB_KEY_ESC ||
|
||||
event.ch == 'q' || event.ch == 'Q')
|
||||
break;
|
||||
|
||||
event_handler();
|
||||
}
|
||||
|
||||
tb_shutdown();
|
||||
|
||||
free(balls);
|
||||
// free(balls);
|
||||
}
|
||||
|
||||
void event_handler() {
|
||||
if (event.type == TB_EVENT_RESIZE) {
|
||||
do
|
||||
tb_peek_event(&event, 10);
|
||||
while (event.type == TB_EVENT_RESIZE);
|
||||
|
||||
init_params();
|
||||
} else if (event.type == TB_EVENT_KEY) {
|
||||
|
||||
if (event.key == TB_KEY_CTRL_C || event.key == TB_KEY_ESC) {
|
||||
tb_shutdown();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
switch (event.ch) {
|
||||
case '-':
|
||||
case '_':
|
||||
if (speedMult < 10) {
|
||||
speedMult++;
|
||||
speed = (((1 / (float)(maxX + maxY)) * 1000000) + 10000) * speedMult;
|
||||
}
|
||||
break;
|
||||
case '+':
|
||||
case '=':
|
||||
if (speedMult > 1) {
|
||||
speedMult--;
|
||||
speed = (((1 / (float)(maxX + maxY)) * 1000000) + 10000) * speedMult;
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
case 'M':
|
||||
if (nballs + 1 <= MAX_NBALLS) {
|
||||
nballs++;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
case 'L':
|
||||
if (nballs - 1 >= MIN_NBALLS) {
|
||||
nballs--;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
if (radiusIn + 5 <= 150) {
|
||||
radiusIn += 5;
|
||||
radius = (radiusIn * radiusIn + (float)(maxX * maxY)) / 15000;
|
||||
margin = contained ? radius * 10 : 0;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if (radiusIn - 5 >= 100) {
|
||||
radiusIn -= 5;
|
||||
radius = (radiusIn * radiusIn + (float)(maxX * maxY)) / 15000;
|
||||
margin = contained ? radius * 10 : 0;
|
||||
}
|
||||
break;
|
||||
case 'I':
|
||||
|
||||
if (color != TB_WHITE || custom || gradient1 )
|
||||
if (rim + 1 <= 5) {
|
||||
rim++;
|
||||
sumConst2 = sumConst * (1 + (float)(0.25 * rim));
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
|
||||
if (color != TB_WHITE || custom || gradient1)
|
||||
if (rim - 1 >= 0) {
|
||||
rim--;
|
||||
sumConst2 = sumConst * (1 + (float)(0.25 * rim));
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
color = next_color(color);
|
||||
fix_rim_color();
|
||||
break;
|
||||
case 'k':
|
||||
color2 = next_color(color2);
|
||||
fix_rim_color();
|
||||
break;
|
||||
case 'p':
|
||||
party = (party+1)%4;
|
||||
break;
|
||||
case 'q':
|
||||
case 'Q':
|
||||
tb_shutdown();
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void init_params() {
|
||||
|
||||
maxX = tb_width();
|
||||
maxY = tb_height() * 2;
|
||||
speedMult = 11 - speedMult;
|
||||
speed = (((1 / (float)(maxX + maxY)) * 1000000) + 10000) * speedMult;
|
||||
radius = (radiusIn * radiusIn + (float)(maxX * maxY)) / 15000;
|
||||
|
||||
margin = contained ? radius * 10 : 0;
|
||||
|
||||
sumConst = 0.0225;
|
||||
sumConst2 = sumConst * (1 + (float)(0.25 * rim));
|
||||
|
||||
custom2 = custom;
|
||||
|
||||
if (color2 == TB_WHITE || !rim)
|
||||
color2 = color | TB_BOLD;
|
||||
|
||||
if (custom && strlen(custom) > 1 && rim) {
|
||||
custom2 = custom + 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_NBALLS; i++) {
|
||||
balls[i].x = rand() % (maxX - 2 * margin) + margin;
|
||||
balls[i].y = rand() % (maxY - 2 * margin) + margin;
|
||||
balls[i].dx = (rand() % 2 == 0) ? -1 : 1;
|
||||
balls[i].dy = (rand() % 2 == 0) ? -1 : 1;
|
||||
}
|
||||
if(gradient1){
|
||||
tb_set_output_mode(TB_OUTPUT_TRUECOLOR);
|
||||
tb_set_clear_attrs(TB_TRUECOLOR_DEFAULT, TB_TRUECOLOR_DEFAULT);
|
||||
if(gradient2) set_pallete2();
|
||||
else set_pallete();
|
||||
}
|
||||
}
|
||||
|
||||
short next_color(short current){
|
||||
for(int i = 0; i<8; i++){
|
||||
if((current == colors[i])||(current == (colors[i] | TB_BOLD ))){
|
||||
return colors[(i+1)%8];
|
||||
}
|
||||
}
|
||||
return colors[0];
|
||||
}
|
||||
|
||||
void fix_rim_color(){
|
||||
if(color2 == color){
|
||||
color2 = color2 | TB_BOLD;
|
||||
}
|
||||
}
|
||||
|
||||
void set_random_colors( short level){
|
||||
if(level==1 || level==3) color = colors[ rand() % 7];
|
||||
if(level==2 || level==3) color2 = colors[ rand() % 7];
|
||||
fix_rim_color();
|
||||
}
|
||||
|
||||
int parse_options(int argc, char *argv[]) {
|
||||
if (argc == 1)
|
||||
return 1;
|
||||
|
||||
int c;
|
||||
while ((c = getopt(argc, argv, ":c:s:r:R:b:F:h")) != -1) {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
if (strcmp(optarg, "red") == 0) {
|
||||
color = TB_RED;
|
||||
} else if (strcmp(optarg, "yellow") == 0) {
|
||||
color = TB_YELLOW;
|
||||
} else if (strcmp(optarg, "blue") == 0) {
|
||||
color = TB_BLUE;
|
||||
} else if (strcmp(optarg, "green") == 0) {
|
||||
color = TB_GREEN;
|
||||
} else if (strcmp(optarg, "magenta") == 0) {
|
||||
color = TB_MAGENTA;
|
||||
} else if (strcmp(optarg, "cyan") == 0) {
|
||||
color = TB_CYAN;
|
||||
} else {
|
||||
printf("Unknown color\n");
|
||||
// First pass to check for gradient mode
|
||||
optind = 1; // Reset getopt
|
||||
while ((c = getopt(argc, argv, ":c:k:s:r:R:b:F:Cp:hg")) != -1) {
|
||||
if (c == 'g') {
|
||||
gradient1 = 1;
|
||||
if (!tb_has_truecolor()) {
|
||||
fprintf(stderr, "The terminal does not support truecolor\n");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset getopt for second pass
|
||||
optind = 1;
|
||||
while ((c = getopt(argc, argv, ":c:k:s:r:R:b:F:Cp:hg")) != -1) {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
if (!set_color(&color, baseColor, optarg, gradient1))
|
||||
return 0;
|
||||
break;
|
||||
case 'k':
|
||||
if (!set_color(&color2, baseColor2, optarg, gradient1))
|
||||
return 0;
|
||||
gradient2 = gradient1; // If we're using gradient, enable the second gradient too
|
||||
break;
|
||||
case 's':
|
||||
speedMult = atoi(optarg);
|
||||
if (speedMult > 5 || speedMult <= 0) {
|
||||
printf("Invalid speed, only values between 1 and 5 are allowed\n");
|
||||
if (speedMult > 10 || speedMult <= 0) {
|
||||
printf("Invalid speed, only values between 1 and 10 are allowed\n");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
@ -172,30 +405,42 @@ int parse_options(int argc, char *argv[]) {
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
radius = 50 + (11 - atoi(optarg)) * 10;
|
||||
if (radius > 150 || radius < 50) {
|
||||
radiusIn = 100 + atoi(optarg) * 5;
|
||||
if (radiusIn > 150 || radiusIn < 100) {
|
||||
printf("Invalid radius, only values between 1 and 10 are allowed\n");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
nballs = atoi(optarg);
|
||||
if (nballs > 20 || nballs < 2) {
|
||||
|
||||
printf("Invalid number of metaballs, only values between 2 and 20 are"
|
||||
"allowed\n");
|
||||
if (nballs > MAX_NBALLS || nballs < MIN_NBALLS) {
|
||||
printf("Invalid number of metaballs, only values between %i and %i are "
|
||||
"allowed\n",
|
||||
MIN_NBALLS, MAX_NBALLS);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
custom = optarg;
|
||||
break;
|
||||
case 'C':
|
||||
contained = 1;
|
||||
break;
|
||||
case 'p':
|
||||
party = atoi(optarg);
|
||||
if (party < 0 || party > 3) {
|
||||
printf("Invalid party mode, only values between 1 and 3 are allowed\n");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
print_help();
|
||||
return 0;
|
||||
break;
|
||||
case ':': /* -f or -o without operand */
|
||||
case 'g':
|
||||
// Already handled in first pass
|
||||
break;
|
||||
case ':':
|
||||
fprintf(stderr, "Option -%c requires an operand\n", optopt);
|
||||
return 0;
|
||||
break;
|
||||
@ -211,18 +456,98 @@ void print_help() {
|
||||
printf(
|
||||
"Usage: lavat [OPTIONS]\n"
|
||||
"OPTIONS:\n"
|
||||
" -c COLOR Set color. Available colours: red, blue, yellow, "
|
||||
"green, cyan and magenta. \n"
|
||||
" Besides those colors the default one is the normal "
|
||||
"foreground of your terminal.\n"
|
||||
" -s SPEED Set the speed, from 1 to 5. (default 1)\n"
|
||||
" -r RADIUS Set the radius of the metaballs, from 1 to 10. "
|
||||
" -g Enable gradient mode with truecolor support.\n"
|
||||
" Changes how -c and -k options work.\n"
|
||||
" -c <COLOR> Set color. In normal mode, available colors are: red, blue, yellow, "
|
||||
"green, cyan, magenta, white, and black.\n"
|
||||
" In gradient mode (-g), use hex format: RRGGBB (e.g., FF0000 for red).\n"
|
||||
" -k <COLOR> Set the rim color. Same format options as -c.\n"
|
||||
" In gradient mode, this sets the second color for the gradient.\n"
|
||||
" -s <SPEED> Set the speed, from 1 to 10. (default 5)\n"
|
||||
" -r <RADIUS> Set the radius of the metaballs, from 1 to 10. "
|
||||
"(default: 5)\n"
|
||||
" -R RIM Set a \"rim\" for each metaball, sizes from 1 to 5. "
|
||||
" -R <RIM> Set a rim for each metaball, sizes from 1 to 5."
|
||||
"(default: none)\n"
|
||||
" This option does not work with the default color\n"
|
||||
" -b NBALLS Set the number of metaballs in the simulation, from "
|
||||
"2 to 20. (default: 10)\n"
|
||||
" -F CHARS Allows for a custom set of chars to be used\n"
|
||||
" -h Print help.\n");
|
||||
" This option does not work with the default "
|
||||
"color\n"
|
||||
" If you use Kitty or Alacritty you must use it "
|
||||
"with the -k option to see the rim.\n"
|
||||
" -b <NBALLS> Set the number of metaballs in the simulation, "
|
||||
"from %i to %i. (default: 10)\n"
|
||||
" -F <CHARS> Allows for a custom set of chars to be used\n"
|
||||
" Only ascii symbols are supported for now, "
|
||||
"wide/unicode chars may appear broken.\n"
|
||||
" -C Retain the entire lava inside the terminal.\n"
|
||||
" It may not work well with a lot of balls or with"
|
||||
" a bigger radius than the default one.\n"
|
||||
" -p <MODE> PARTY!! THREE MODES AVAILABLE (p1, p2 and p3).\n"
|
||||
" -h Print help.\n"
|
||||
"RUNTIME CONTROLS:\n"
|
||||
" i Increase radius of the metaballs.\n"
|
||||
" d Decrease radius of the metaballs.\n"
|
||||
" shift i Increase rim of the metaballs.\n"
|
||||
" shift d Decrease rim of the metaballs.\n"
|
||||
" m Increase the number of metaballs.\n"
|
||||
" l Decrease the number metaballs.\n"
|
||||
" c Change the color of the metaballs.\n"
|
||||
" k Change the rim color of the metaballs.\n"
|
||||
" + Increase speed.\n"
|
||||
" - Decrease speed.\n"
|
||||
" p TURN ON THE PARTY AND CYCLE THROUGH THE PARTY MODES "
|
||||
"(it can also turns off the party).\n"
|
||||
"(Tip: Zoom out in your terminal before running the program to get a "
|
||||
"better resolution of the lava).\n"
|
||||
"EXAMPLES:\n"
|
||||
" lavat -c green -k red Use named colors in normal mode\n"
|
||||
" lavat -g -c 00FF00 -k FF0000 Use hex colors in gradient mode\n",
|
||||
MIN_NBALLS, MAX_NBALLS);
|
||||
}
|
||||
|
||||
void set_pallete(){
|
||||
int avgColor= (baseColor[0] + baseColor[1] + baseColor[2])/3;
|
||||
int blackfactor[5];
|
||||
int whitefactor[5];
|
||||
for(int i=1 ;i<6;i++){
|
||||
blackfactor[i-1]=(6-i)*avgColor/5;
|
||||
whitefactor[i-1]=i*(255-avgColor)/5;
|
||||
}
|
||||
|
||||
for(int i=0 ;i<5;i++){
|
||||
int r, g, b;
|
||||
float factor = (1 - ((float)blackfactor[i]/(avgColor)));
|
||||
r = baseColor[0]*factor;
|
||||
g = baseColor[1]*factor;
|
||||
b = baseColor[2]*factor;
|
||||
pallete[i]= (r << 16) | (g << 8) | b;
|
||||
r = baseColor[0] + (255-baseColor[0])*whitefactor[i]/(255-avgColor);
|
||||
g = baseColor[1] + (255-baseColor[1])*whitefactor[i]/(255-avgColor);
|
||||
b = baseColor[2] + (255-baseColor[2])*whitefactor[i]/(255-avgColor);
|
||||
pallete[i+6] = (r << 16) | (g << 8) | b;
|
||||
|
||||
}
|
||||
pallete[5]= (baseColor[0] << 16) | (baseColor[1] << 8) | baseColor[2];
|
||||
}
|
||||
|
||||
void set_pallete2() {
|
||||
for (int i = 0; i < 11; i++) {
|
||||
float t = (float)i / (11 - 1);
|
||||
|
||||
int r = (1 - t) * baseColor[0] + t * baseColor2[0];
|
||||
int g = (1 - t) * baseColor[1] + t * baseColor2[1];
|
||||
int b = (1 - t) * baseColor[2] + t * baseColor2[2];
|
||||
|
||||
pallete[i] = (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
|
||||
uintattr_t get_color(float val) {
|
||||
val = (val - sumConst)/(0.001*(rim+1));
|
||||
|
||||
if (val > 10) {
|
||||
return pallete[10];
|
||||
} else if (val < 0) {
|
||||
return pallete[0];
|
||||
}
|
||||
|
||||
return pallete[(int)val];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user