ref: 796572b18e177f129778b68460a2618de881a624
dir: /dino.c/
#include <assert.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <time.h> #include <errno.h> #include <fcntl.h> #include <local/colors.h> #include <signal.h> #include <sys/ioctl.h> #define DINASOUR_HEIGHT 15 #define DINASOUR_WIDTH 15 #define SUN_HEIGHT 5 #define SUN_WIDTH 5 #define DELAY 60000 #define TREE_HEIGHT 7 #define TREE_WIDTH 7 void die(const char *msg) { perror(msg); exit(EXIT_FAILURE); } char *colors[] = { // black_fg, red_fg, // green_fg , yellow_fg, // blue_fg , // magenta_fg, // cyan_fg , // white_fg , }; char *fbuffer = NULL; // should be point_t* buffer uint64_t fbuffer_size = 0; static volatile int cursor = 0; int max_y; int max_x; static volatile bool resize = false; typedef struct { bool *matrix; int height; int width; int x; int y; bool visible; } shape_t; // a hash tables suits better no? // keys will be memory address of shapes. // and vals will be the number of times they collided // and um, we also need to store coordinates of collisions? // maybe we can use an observer pattern here!\ // each shape subscribes to collisions,... typedef struct collision_t { shape_t *shape; struct collision_t *next; } collision_t; typedef struct { char *escapes; char charachter; // collision_t collisions; // it's actually better to have a global collisions // (hash table or linked list and update it every tflush()). int x; int y; bool written; } point_t; void alloc_fbuf(); void gotoxy(int x, int y) { if (x >= max_x || y >= max_y) return; int new_cursor = (max_x * y) + x; cursor = (max_x * y) + x; } void _gotoxy(int x, int y) { printf("%c[%d;%df", 0x1B, y, x); } void max_xy(int signo) { (void)signo; struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); max_x = w.ws_col; max_y = w.ws_row; resize = true; // alloc_fbuf(); } void tprint(const char c) { if (cursor >= fbuffer_size || cursor < 0) return; fbuffer[cursor++] = c; } void draw_line(point_t a, point_t b) { // int slope = (a.y - b.y) / (a.x - b.x); int dy = b.y - a.y; int dx = b.x - a.x; while (true) { int newx = a.x + dx; int newy = a.y + dy; if (newx == b.x && newy == b.y) break; gotoxy(a.x + dx, a.y + dy); tprint('*'); } } void draw_shape(shape_t *shape, const char *color) { if (shape->visible) { // FIXME : idk why this happens. return; } bool print_newline = false; // gotoxy(shape->x, shape->y); for (int i = 0; i < shape->height; i++) { gotoxy(shape->x, shape->y + i); for (int j = 0; j < shape->width; j++) { if (shape->matrix[i * shape->height + j]) { print_newline = true; // printf("%s%s%s", inverse_off , color, " " reset ); tprint('*'); } else { // printf(" "); tprint(' '); } } if (print_newline) printf("\r"); // fbuffer[cursor] = '\n' tprint('\n'); } } shape_t *init_shape(int width, int height) { shape_t *ret = calloc(width * height, sizeof(bool)); return ret; } void free_shape(shape_t *shape) { free(shape); } void tflush() { for (uint64_t row = 0; row < max_y; ++row) { printf("\n"); for (uint64_t col = 0; col < max_x; ++col) { if (fbuffer[row * max_x + col] == '*') { _gotoxy(col, row); // printf("%s%s %s",inverse, colors[rand() % // sizeof(colors)/sizeof(*colors)], reset); printf("%s%c%s", reset inverse, /*fbuffer[row * max_x + col]*/ ' ', reset); } else printf(reset " " reset); } } // write(STDOUT_FILENO, fbuffer, max_x * max_y); // drawing will be very // smooth this way. } void alloc_fbuf() { if (max_x * max_y > fbuffer_size) { fbuffer_size = max_y * max_x; //* sizeof(char); fbuffer = realloc(fbuffer, fbuffer_size); assert(fbuffer); } } bool dinasour_frame1[DINASOUR_WIDTH][DINASOUR_HEIGHT] = { {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0}, {1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0}, {1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0}, {1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0}, {1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0}, }; bool dinasour_frame2[DINASOUR_WIDTH][DINASOUR_HEIGHT] = { {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0}, {1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0}, {1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0}, {1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0}, {1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, }; bool dinasour_frame3[DINASOUR_WIDTH][DINASOUR_HEIGHT] = { {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0}, {1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0}, {1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0}, {1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0}, {1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, }; bool tree_1[TREE_WIDTH][TREE_HEIGHT] = { {1, 1, 1, 0, 0, 1, 1}, {1, 0, 1, 0, 1, 0, 1}, {1, 0, 0, 1, 0, 0, 1}, {0, 1, 0, 0, 0, 1, 0}, {0, 0, 1, 0, 1, 0, 0}, {0, 0, 1, 0, 1, 0, 0}, {0, 0, 1, 1, 1, 0, 0}, }; void clear_screen() { memset(fbuffer, 0, fbuffer_size); printf("\033c"); } int main(int argc, char *argv[]) { max_xy(0); alloc_fbuf(); shape_t dinasour_f1 = {.matrix = &dinasour_frame1[0][0], .width = DINASOUR_WIDTH, .height = DINASOUR_HEIGHT, .x = 10, .y = 10}; shape_t dinasour_f2 = {.matrix = &dinasour_frame2[0][0], .height = DINASOUR_HEIGHT, .width = DINASOUR_WIDTH, .x = 10, .y = 10}; shape_t dinasour_f3 = { .matrix = &dinasour_frame3[0][0], .height = DINASOUR_HEIGHT, .width = DINASOUR_WIDTH, .x = 10, .y = 10, }; shape_t dinasour2_f1 = {.matrix = &dinasour_frame1[0][0], .width = DINASOUR_WIDTH, .height = DINASOUR_HEIGHT, .x = 10, .y = 10, .visible = true}; shape_t dinasour2_f2 = {.matrix = &dinasour_frame2[0][0], .height = DINASOUR_HEIGHT, .width = DINASOUR_WIDTH, .x = 10, .y = 10, .visible = true}; shape_t dinasour2_f3 = {.matrix = &dinasour_frame3[0][0], .height = DINASOUR_HEIGHT, .width = DINASOUR_WIDTH, .x = 10, .y = 10 + DINASOUR_HEIGHT + 2, .visible = true}; bool sun_matrix[SUN_HEIGHT][SUN_WIDTH] = { {0, 0, 1, 0, 0}, {0, 1, 0, 1, 0}, {1, 0, 0, 0, 1}, {0, 1, 0, 1, 0}, {0, 0, 1, 0, 0}, }; shape_t sun = {.matrix = &sun_matrix[0][0], .height = SUN_HEIGHT, .width = SUN_WIDTH, .x = (float)max_x / 2, .y = 10}; shape_t tree = {.matrix = &tree_1[0][0], .height = TREE_HEIGHT, .width = TREE_WIDTH, .x = 50, .y = 10 + DINASOUR_HEIGHT - TREE_HEIGHT}; struct sigaction sa; sa.sa_handler = max_xy; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); // sigaction(SIGWINCH, &sa, NULL); int randx = 0; int randy = 0; clear_screen(); shape_t *arr[3] = {&dinasour_f1, &dinasour_f2, &dinasour_f3}; shape_t *arr2[3] = {&dinasour2_f1, &dinasour2_f2, &dinasour2_f3}; unsigned int index = 0; srand(time(NULL)); unsigned int t = 1; shape_t *current_tree = malloc(sizeof(shape_t)); assert(current_tree); current_tree = malloc(sizeof(shape_t)); current_tree->matrix = &tree_1[0][0]; current_tree->x = max_x; current_tree->y = 10 + DINASOUR_HEIGHT - TREE_HEIGHT; current_tree->height = TREE_HEIGHT; current_tree->width = TREE_WIDTH; current_tree->visible = false; shape_t *next_tree = NULL; while (true) { shape_t *ptr = arr[++index % 3]; draw_shape(ptr, white_bg); if (current_tree) draw_shape(current_tree, white_bg); if (next_tree) { draw_shape(next_tree, white_bg); } // printf("\nptr->x = %d, ptr->y = %d\n", ptr->x, ptr->y); // printf("max_x = %d, max_y = %d\n", max_x, max_y); // printf("fbuffer = %#X, fbuffer_size=%PRlu64\n", (unsigned int)fbuffer, // fbuffer_size); printf("fbuffer = %#X, fbuffer_size=%llu, cursor = %d\n", // fbuffer, fbuffer_size, cursor); draw_shape(&sun, yellow_bg); // draw_shape(ptr2, yellow_bg); tflush(); usleep(DELAY); /*for (int i = 0; i < 3; ++i) { arr[i]->x = (arr[i]->x + rand()) % max_x; arr2[i]->x = (arr[i]->x + rand()) % max_x; //arr[i]->y = (arr[i]->x - 1) % (max_y - DINASOUR_HEIGHT); arr[i]->y = rand() % (max_y - DINASOUR_HEIGHT); arr2[i]->x = (arr[i]->x + rand()) % (max_x - DINASOUR_HEIGHT); arr2[i]->y = (arr[i]->y + rand()) % (max_y - DINASOUR_HEIGHT); } */ /*for (int i = 0; i < 3; i++) { arr[i]->x = (arr[i]->x + 1) % max_x; }*/ if (next_tree) --next_tree->x; if (current_tree && --current_tree->x == max_x / 2) { // tree.visible = true; // free(current_tree); // current_tree = NULL; // current_tree = next_tree; next_tree = malloc(sizeof(shape_t)); assert(next_tree); next_tree->matrix = &tree_1[0][0]; next_tree->x = max_x - TREE_WIDTH; next_tree->y = 10 + DINASOUR_HEIGHT - TREE_HEIGHT; next_tree->height = TREE_HEIGHT; next_tree->width = TREE_WIDTH; next_tree->visible = false; } if (current_tree && current_tree->x == 10) { free(current_tree); current_tree = next_tree; next_tree = NULL; } // collisions(); assert(cursor <= fbuffer_size + 1); /*if (resize) { alloc_fbuf(); resize = false; }*/ clear_screen(); } free(fbuffer); return 0; }