matrix-coderain-cli/coderain.c

191 lines
3.9 KiB
C

#include <ncurses.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <stdbool.h>
#define CHAR_COUNT 17
#define COLOR_LIGHT_GREEN 8
#define COLOR_MID_GREEN 9
#define COLOR_DARK_GREEN 10
#define COLOR_BLACK_GREEN 11
#define WHITE 1
#define LIGHT_GREEN 2
#define MID_GREEN 3
#define DARK_GREEN 4
#define BLACK_GREEN 5
const char CHARS[] = "!$%&?#@Y0123456789";
struct Cursor {
int x;
int y;
int speed;
int length;
char string[256];
bool is_expanding;
bool is_active;
};
int get_random_number(int max_number)
{
double index = (rand() / (double)RAND_MAX) * max_number;
return (int)index % max_number;
}
char get_random_char()
{
return CHARS[get_random_number(CHAR_COUNT)];
}
void generate_random_string(char * string, int length)
{
int index = 0;
for (int c = 0; c < length; c++) {
string[c] = get_random_char();
index = c;
}
string[index + 1] = '\0';
}
void print_with_color(char c, int x, int y, int color_pair)
{
attron(COLOR_PAIR(color_pair));
mvaddch(y, x, c);
attroff(COLOR_PAIR(color_pair));
}
void draw_cursor(struct Cursor * cursor, int * screen_height)
{
print_with_color(cursor->string[cursor->y], cursor->x, cursor->y, WHITE);
if (cursor->y > 0) {
print_with_color(cursor->string[cursor->y - 1], cursor->x, cursor->y - 1, LIGHT_GREEN);
}
++cursor->y;
/*
if (cursor->y > 4 && cursor->length > 4 && get_random_number(100) > 90) {
char random_char = get_random_char();
int char_index = cursor->y - get_random_number(cursor->length - 4);
cursor->string[char_index] = random_char;
}
*/
if (cursor->is_expanding) {
++cursor->length;
if (cursor->length > *screen_height * 0.1) {
cursor->is_expanding = get_random_number(10) > 1;
}
} else {
mvaddch(cursor->y - cursor->length - 4, cursor->x, ' ');
print_with_color(cursor->string[cursor->y - cursor->length - 3], cursor->x, cursor->y - cursor->length - 3, BLACK_GREEN);
print_with_color(cursor->string[cursor->y - cursor->length - 2], cursor->x, cursor->y - cursor->length - 2, DARK_GREEN);
print_with_color(cursor->string[cursor->y - cursor->length - 1], cursor->x, cursor->y - cursor->length - 1, MID_GREEN);
}
if (cursor->y > *screen_height + cursor->length + 3) {
cursor->length = 0;
cursor->y = 0;
cursor->is_active = false;
cursor->is_expanding = true;
}
}
void control_cursor(struct Cursor * cursor, int * screen_height)
{
if (cursor->is_active) {
draw_cursor(cursor, screen_height);
} else {
cursor->is_active = get_random_number(*screen_height) > *screen_height * 0.5;
if (cursor->is_active) {
generate_random_string(cursor->string, *screen_height + 4);
}
}
}
int main()
{
int screen_width = 0;
int screen_height = 0;
srand(time(NULL));
initscr();
if (!has_colors()) {
printf("Your shell does not support colors!\n");
return 1;
}
getmaxyx(stdscr, screen_height, screen_width);
struct Cursor cursors[screen_width];
for (int c = 0; c < screen_width; c++) {
struct Cursor cursor;
cursor.x = c;
cursor.y = -1 * get_random_number(screen_height);
cursor.speed = 0;
cursor.length = 0;
cursor.is_active = false;
cursor.is_expanding = true;
cursors[c] = cursor;
}
cbreak();
curs_set(0);
noecho();
keypad(stdscr, 1);
start_color();
init_color(COLOR_WHITE, 1000, 1000, 1000);
init_color(COLOR_BLACK, 0, 0, 0);
init_color(COLOR_LIGHT_GREEN, 500, 1000, 500);
init_color(COLOR_MID_GREEN, 0, 600, 0);
init_color(COLOR_DARK_GREEN, 0, 200, 0);
init_color(COLOR_BLACK_GREEN, 0, 50, 0);
init_pair(WHITE, COLOR_WHITE, COLOR_BLACK);
init_pair(LIGHT_GREEN, COLOR_LIGHT_GREEN, COLOR_BLACK);
init_pair(MID_GREEN, COLOR_MID_GREEN, COLOR_BLACK);
init_pair(DARK_GREEN, COLOR_DARK_GREEN, COLOR_BLACK);
init_pair(BLACK_GREEN, COLOR_DARK_GREEN, COLOR_BLACK);
while (true) {
for (int c = 0; c < screen_width; c++) {
control_cursor(&cursors[c], &screen_height);
}
refresh();
usleep(90000);
}
endwin();
return 0;
}