frist commit

This commit is contained in:
overflowerror 2021-05-10 19:17:33 +02:00
commit b64dc43112
13 changed files with 1246 additions and 0 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
/obj/**
gravity
bars
font

41
Makefile Normal file
View file

@ -0,0 +1,41 @@
CC = gcc
CFLAGS = -std=c99 -Wall -D_POSIX_C_SOURCE=201112L -D_XOPEN_SOURCE=500 -D_GNU_SOURCE -static -g
LD = gcc
LDFLAGS = -lm
COMMON = obj/common/graphics.o\
obj/common/compat.o\
obj/common/utils.o
DEPS = $(OBJS:%.o=%.d)
all: bars gravity font
bars: obj/bars.o $(COMMON)
$(LD) -o $@ $^ $(LDFLAGS)
gravity: obj/gravity.o $(COMMON)
$(LD) -o $@ $^ $(LDFLAGS)
font: obj/font.o $(COMMON)
$(LD) -o $@ $^ $(LDFLAGS)
test: obj/test.o $(COMMON)
$(LD) -o $@ $^ $(LDFLAGS)
-include $(DEPS)
obj/%.o: src/%.c obj
$(CC) $(CFLAGS) -MMD -c -o $@ $<
obj:
@mkdir -p obj/common/
clean:
@echo "Cleaning up..."
@rm -f obj/*.o
@rm -f obj/*.d
@rm -f obj/*/*.o
@rm -f obj/*/*.d
@rm -f bars
@rm -f gravity
@rm -f font

0
obj/common/.gitkeep Normal file
View file

136
src/bars.c Normal file
View file

@ -0,0 +1,136 @@
#include <locale.h>
#include <stdbool.h>
#include <unistd.h>
#include <wchar.h>
#include "common/compat.h"
#include "common/graphics.h"
#include "common/utils.h"
#define WIDTH (40)
#define NUMBER_OF_CHARACTERS (8)
#define NUMBER_OF_BLOCKS (20)
#define SLEEP_TIME (50000l)
#define NO_CHARACTER (-1)
wchar_t chars[] = {
0x258F,
0x258E,
0x258D,
0x258C,
0x258B,
0x258A,
0x2589,
0x2588
};
enum direction {
left, right
};
struct block {
enum direction direction;
int character;
float position;
float speed;
};
struct buffer {
int characters[WIDTH];
};
struct block randomBlock() {
return (struct block){
direction: (randomInt() % 2) ? left : right,
character: (randomInt() % NUMBER_OF_CHARACTERS),
position: (randomInt() % WIDTH),
speed: 1
};
}
void printBuffer(struct buffer* buffer) {
for (int i = 0; i < WIDTH; i++) {
if (buffer->characters[i] < 0) {
cprintf(" ");
} else {
cprintf("%lc", chars[buffer->characters[i]]);
}
}
}
void clearBuffer(struct buffer* buffer) {
for (int i = 0; i < WIDTH; i++) {
buffer->characters[i] = -1;
}
}
void applyBlockToBuffer(struct block* block, struct buffer* buffer) {
if (buffer->characters[(int) block->position] <= block->character)
buffer->characters[(int) block->position] = block->character;
}
void tickBlock(struct block* block) {
if (block->direction == right) {
block->position += block->speed;
if (block->position >= WIDTH - 1) {
block->position = WIDTH - 1;
block->direction = left;
}
} else {
block->position -= block->speed;
if (block->position <= 0) {
block->position = 0;
block->direction = right;
}
}
}
void doTick(struct block blocks[]) {
struct buffer buffer;
clearBuffer(&buffer);
moveCursorRelative(- (WIDTH + 2), 0);
eraseLine();
for (int i = 0; i < NUMBER_OF_BLOCKS; i++) {
tickBlock(&(blocks[i]));
applyBlockToBuffer(&(blocks[i]), &buffer);
}
cprintf("[");
printBuffer(&buffer);
cprintf("]");
}
void makeBlocks(struct block blocks[]) {
for (int i = 0; i < NUMBER_OF_BLOCKS; i++) {
blocks[i] = randomBlock();
}
}
int main() {
setlocale(LC_CTYPE, "");
enable_compat_mode(PRINT_WCHAR);
initRandom();
hideCursor();
struct block blocks[NUMBER_OF_BLOCKS];
makeBlocks(blocks);
while (true) {
doTick(blocks);
fflush(stdout);
usleep(SLEEP_TIME);
}
cprintf("\n");
}

42
src/common/compat.c Normal file
View file

@ -0,0 +1,42 @@
#include "compat.h"
#include <stdio.h>
#include <wchar.h>
#include <stdarg.h>
#include <stdlib.h>
int compat_mode = 0;
void enable_compat_mode(int mode) {
compat_mode |= mode;
}
void disable_compat_mode(int mode) {
compat_mode &= ~(mode);
}
int cfprintf(FILE* file, char* format, ...) {
va_list(args);
int result;
va_start(args, format);
if (compat_mode & PRINT_WCHAR) {
size_t size = mbstowcs(NULL, format, 0) + 1;
wchar_t* buffer = malloc(size * sizeof(wchar_t));
if (buffer == NULL) {
return -1;
}
mbstowcs(buffer, format, size);
result = vfwprintf(file, buffer, args);
free(buffer);
} else {
result = vfprintf(file, format, args);
}
va_end(args);
return result;
}

20
src/common/compat.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef COMPAT_H
#define COMPAT_H
#include <stdio.h>
#define PRINT_WCHAR (1<<0)
void enable_compat_mode(int);
void disable_compat_mode(int);
int cfprintf(FILE* file, char* format, ...);
#define cprintf(...) cfprintf(stdout, __VA_ARGS__)
#ifdef SUBSTITUDE_PRINTS
#define printf(...) cprintf(__VA_ARGS__)
#define fprintf(...) cfprintf(__VA_ARGS__)
#endif
#endif

67
src/common/graphics.c Normal file
View file

@ -0,0 +1,67 @@
#include "graphics.h"
#include "compat.h"
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void moveCursorRelative(int x, int y) {
if (x < 0) {
cprintf("\033[%dD", -x);
} else if (x > 0) {
cprintf("\033[%dC", x);
}
if (y < 0) {
cprintf("\033[%dA", -x);
} else if (y > 0) {
cprintf("\033[%dB", x);
}
}
void moveCursorAbsolute(int x, int y) {
cprintf("\033[%d;%dH", y + 1, x + 1);
}
void eraseLine() {
cprintf("\033[K");
}
void eraseScreen() {
cprintf("\033[2J");
}
void hideCursor() {
cprintf("\033[?25l");
}
void showCursor() {
cprintf("\033[?25h");
}
struct dimensions getScreenSize() {
moveCursorAbsolute(999, 999);
cprintf("\033[6n");
char buffer[12];
int i = 0;
while (true) {
cprintf("--\n");
int m = fread(&(buffer[i++]), 1, 1, stdin);
cprintf("%d\n", m);
cprintf("%c\n", buffer[i - 1]);
if (buffer[i - 1] == 'R')
break;
}
buffer[i] = '\0';
struct dimensions d;
char* endptr = &(buffer[2]);
int tmp = strtol(endptr, &endptr, 10);
d.width = tmp;
tmp = strtol(endptr, &endptr, 10);
d.height = tmp;
return d;
}

19
src/common/graphics.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef GRAPHICS_H
#define GRAPHICS_H
struct dimensions {
int width;
int height;
};
void moveCursorRelative(int x, int y);
void moveCursorAbsolute(int x, int y);
void eraseLine();
void eraseScreen();
void hideCursor();
void showCursor();
struct dimensions getScreenSize();
#endif

16
src/common/utils.c Normal file
View file

@ -0,0 +1,16 @@
#include "utils.h"
#include <time.h>
#include <stdlib.h>
void initRandom() {
srandom(time(NULL));
}
int randomInt() {
return random();
}
float randomFloat() {
return random() * 1.0 / RAND_MAX;
}

19
src/common/utils.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef UTILS_H
#define UTILS_H
#include "compat.h"
#include <stdio.h>
#include <stdlib.h>
void initRandom();
int randomInt();
float randomFloat();
#ifndef EXIT_PANIC
#define EXIT_PANIC (1)
#endif
#define panic(format, ...) { cfprintf(stderr, "panic: " format "\n", #__VA_ARGS__); exit(EXIT_PANIC ); }
#endif

545
src/font.c Normal file
View file

@ -0,0 +1,545 @@
#include <locale.h>
#include <math.h>
#include <stdbool.h>
#include <unistd.h>
#include <wchar.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include "common/graphics.h"
#include "common/utils.h"
#define SUBSTITUDE_PRINTS
#include "common/compat.h"
#define MAX_VELOCITY (3)
#define ANIMATION_SLEEP_TIME (100000)
#define SCATTER_SLEEP_TIME (2000000)
#define OFFSET_X (-50)
#define OFFSET_Y (-15)
#define SCREEN_WIDTH (100)
#define SCREEN_HEIGHT (30)
#define ASPECT_RATIO (3.0/2.0)
#define FACTOR_X (1.0)
#define FACTOR_Y (FACTOR_X * ASPECT_RATIO)
#define BRAILLE_PREFIX (0x2800)
#define BRAILLE_TOP_LEFT (0x01)
#define BRAILLE_MIDDLE_LEFT (0x02)
#define BRAILLE_BOTTOM_LEFT (0x04)
#define BRAILLE_TOP_RIGHT (0x08)
#define BRAILLE_MIDDLE_RIGHT (0x10)
#define BRAILLE_BOTTOM_RIGHT (0x20)
struct vector {
float x;
float y;
};
struct point {
struct vector position;
struct vector source;
struct vector target;
};
float distance(struct vector a, struct vector b) {
float dx = b.x - a.x;
float dy = b.y - a.y;
return sqrt((dx * dx) + (dy * dy));
}
struct vector direction(struct vector a, struct vector b) {
float dx = b.x - a.x;
float dy = b.y - a.y;
float r = sqrt((dx * dx) + (dy * dy));
return (struct vector) {
x: dx / r,
y: dy / r
};
}
void zeroVector(struct vector* vector) {
vector->x = 0;
vector->y = 0;
}
struct patternAtom {
int x; // 0-1
int y; // 0-2
};
wchar_t getPattern(struct patternAtom atoms[], int number) {
if (number == 0) {
return L' ';
}
wchar_t result = BRAILLE_PREFIX;
for (int i = 0; i < number; i++) {
if (atoms[i].x == 0) {
if (atoms[i].y == 0) {
result |= BRAILLE_TOP_LEFT;
} else if (atoms[i].y == 1) {
result |= BRAILLE_MIDDLE_LEFT;
} else {
result |= BRAILLE_BOTTOM_LEFT;
}
} else {
if (atoms[i].y == 0) {
result |= BRAILLE_TOP_RIGHT;
} else if (atoms[i].y == 1) {
result |= BRAILLE_MIDDLE_RIGHT;
} else {
result |= BRAILLE_BOTTOM_RIGHT;
}
}
}
return result;
}
struct point randomPoint() {
struct point p = {
source: {
x: randomFloat() * 20 - 10,
y: randomFloat() * 20 - 10
},
target: {
x: randomFloat() * 20 - 10,
y: randomFloat() * 20 - 10
}
};
p.position = p.source;
return p;
}
void initPoints(struct point points[], int number) {
for (int i = 0; i < number; i++) {
points[i] = randomPoint();
}
}
float velocity(float x) {
if (x > 1.0) {
return MAX_VELOCITY * (-0.2)*(x - 1);
} else if (x > 0.5) {
return MAX_VELOCITY * (-2)*(x - 1);
} else {
return MAX_VELOCITY * 2*x + 0.2;
}
}
bool tickPoint(struct point* p) {
struct vector d = direction(p->position, p->target);
float x = distance(p->source, p->target);
if (fabs(x) < 0.01) {
x = 1.0;
} else {
x = distance(p->source, p->position) / x;
}
float v = fabs(velocity(x));
if (fabs(1 - x) < 0.01) {
p->position = p->target;
return true;
} else {
p->position.x += d.x * v;
p->position.y += d.y * v;
return false;
}
}
bool tickPoints(struct point points[], int number) {
bool finished = true;
for (int i = 0; i < number; i++) {
if (!tickPoint(&(points[i])))
finished = false;
}
return finished;
}
struct screenCell {
struct patternAtom* atoms;
int number;
};
void displayPoints(struct point points[], int number) {
struct screenCell screen[SCREEN_WIDTH][SCREEN_HEIGHT];
for (int x = 0; x < SCREEN_WIDTH; x++) {
for (int y = 0; y < SCREEN_HEIGHT; y++) {
screen[x][y].atoms = NULL;
screen[x][y].number = 0;
}
}
for (int i = 0; i < number; i++) {
struct point p = points[i];
float x = p.position.x * FACTOR_X - OFFSET_X;
float y = p.position.y * FACTOR_Y - OFFSET_Y;
int screenX = floor(x);
int screenY = floor(y);
if (screenX < 0 || screenX >= SCREEN_WIDTH) {
continue;
}
if (screenY < 0 || screenY >= SCREEN_HEIGHT) {
continue;
}
struct patternAtom atom = {
x: floor((x - screenX) * 2),
y: floor((y - screenY) * 3)
};
struct screenCell* cell = &(screen[screenX][screenY]);
cell->atoms = realloc(cell->atoms, ++cell->number * sizeof(struct patternAtom));
if (cell->atoms == NULL) {
panic("couldn't allocate screen buffer: %s", strerror(errno));
}
cell->atoms[cell->number - 1] = atom;
}
for (int x = 0; x < SCREEN_WIDTH + 2; x++) {
cprintf("-");
}
cprintf("\n");
for (int y = 0; y < SCREEN_HEIGHT; y++) {
cprintf("|");
for (int x = 0; x < SCREEN_WIDTH; x++) {
cprintf("%lc", getPattern(screen[x][y].atoms, screen[x][y].number));
}
cprintf("|\n");
}
for (int x = 0; x < SCREEN_WIDTH + 2; x++) {
cprintf("-");
}
cprintf("\n");
}
void createPoint(struct point points[], int i, struct vector position) {
if (points == NULL)
return;
struct vector source = {
x: randomFloat() * SCREEN_WIDTH - SCREEN_WIDTH / 2,
y: (randomFloat() * SCREEN_HEIGHT - SCREEN_HEIGHT / 2) / ASPECT_RATIO
};
points[i] = (struct point) {
target: position,
source: source,
position: source
};
}
struct vector add(struct vector vector, float x, float y) {
return (struct vector) {
x: vector.x + x,
y: (vector.y + y) / ASPECT_RATIO
};
}
int char2points(char c, struct point points[], struct vector position) {
int i = 0;
switch(c) {
case 'A':
createPoint(points, i++, add(position, 1.0, 0.0));
createPoint(points, i++, add(position, 1.5, 0.0));
createPoint(points, i++, add(position, 1.0, 0.4));
createPoint(points, i++, add(position, 1.5, 0.4));
createPoint(points, i++, add(position, 0.5, 0.7));
createPoint(points, i++, add(position, 2.0, 0.7));
createPoint(points, i++, add(position, 0.0, 1.0));
createPoint(points, i++, add(position, 0.5, 1.0));
createPoint(points, i++, add(position, 2.0, 1.0));
createPoint(points, i++, add(position, 2.5, 1.0));
createPoint(points, i++, add(position, 0.0, 1.4));
createPoint(points, i++, add(position, 0.5, 1.4));
createPoint(points, i++, add(position, 1.0, 1.4));
createPoint(points, i++, add(position, 1.5, 1.4));
createPoint(points, i++, add(position, 2.0, 1.4));
createPoint(points, i++, add(position, 2.5, 1.4));
createPoint(points, i++, add(position, 0.0, 1.7));
createPoint(points, i++, add(position, 0.5, 1.7));
createPoint(points, i++, add(position, 1.0, 1.7));
createPoint(points, i++, add(position, 1.5, 1.7));
createPoint(points, i++, add(position, 2.0, 1.7));
createPoint(points, i++, add(position, 2.5, 1.7));
createPoint(points, i++, add(position, 0.0, 2.0));
createPoint(points, i++, add(position, 0.5, 2.0));
createPoint(points, i++, add(position, 2.0, 2.0));
createPoint(points, i++, add(position, 2.5, 2.0));
createPoint(points, i++, add(position, 0.0, 2.4));
createPoint(points, i++, add(position, 0.5, 2.4));
createPoint(points, i++, add(position, 2.0, 2.4));
createPoint(points, i++, add(position, 2.5, 2.4));
createPoint(points, i++, add(position, 0.0, 2.7));
createPoint(points, i++, add(position, 0.5, 2.7));
createPoint(points, i++, add(position, 2.0, 2.7));
createPoint(points, i++, add(position, 2.5, 2.7));
return i;
case 'C':
return i;
case 'D':
return i;
case 'E':
return i;
case 'F':
return i;
case 'G':
return i;
case 'H':
createPoint(points, i++, add(position, 0.0, 0.0));
createPoint(points, i++, add(position, 0.0, 0.4));
createPoint(points, i++, add(position, 0.0, 0.7));
createPoint(points, i++, add(position, 0.0, 1.0));
createPoint(points, i++, add(position, 0.0, 1.4));
createPoint(points, i++, add(position, 0.0, 1.7));
createPoint(points, i++, add(position, 0.0, 2.0));
createPoint(points, i++, add(position, 0.0, 2.4));
createPoint(points, i++, add(position, 0.0, 2.7));
createPoint(points, i++, add(position, 0.5, 0.0));
createPoint(points, i++, add(position, 0.5, 0.4));
createPoint(points, i++, add(position, 0.5, 0.7));
createPoint(points, i++, add(position, 0.5, 1.0));
createPoint(points, i++, add(position, 0.5, 1.4));
createPoint(points, i++, add(position, 0.5, 1.7));
createPoint(points, i++, add(position, 0.5, 2.0));
createPoint(points, i++, add(position, 0.5, 2.4));
createPoint(points, i++, add(position, 0.5, 2.7));
createPoint(points, i++, add(position, 1.0, 1.0));
createPoint(points, i++, add(position, 1.0, 1.4));
createPoint(points, i++, add(position, 1.0, 1.7));
createPoint(points, i++, add(position, 1.5, 1.0));
createPoint(points, i++, add(position, 1.5, 1.4));
createPoint(points, i++, add(position, 1.5, 1.7));
createPoint(points, i++, add(position, 2.0, 0.0));
createPoint(points, i++, add(position, 2.0, 0.4));
createPoint(points, i++, add(position, 2.0, 0.7));
createPoint(points, i++, add(position, 2.0, 1.0));
createPoint(points, i++, add(position, 2.0, 1.4));
createPoint(points, i++, add(position, 2.0, 1.7));
createPoint(points, i++, add(position, 2.0, 2.0));
createPoint(points, i++, add(position, 2.0, 2.4));
createPoint(points, i++, add(position, 2.0, 2.7));
createPoint(points, i++, add(position, 2.5, 0.0));
createPoint(points, i++, add(position, 2.5, 0.4));
createPoint(points, i++, add(position, 2.5, 0.7));
createPoint(points, i++, add(position, 2.5, 1.0));
createPoint(points, i++, add(position, 2.5, 1.4));
createPoint(points, i++, add(position, 2.5, 1.7));
createPoint(points, i++, add(position, 2.5, 2.0));
createPoint(points, i++, add(position, 2.5, 2.4));
createPoint(points, i++, add(position, 2.5, 2.7));
return i;
case 'I':
return i;
case 'J':
return i;
case 'K':
return i;
case 'L':
createPoint(points, i++, add(position, 0.0, 0.0));
createPoint(points, i++, add(position, 0.0, 0.4));
createPoint(points, i++, add(position, 0.0, 0.7));
createPoint(points, i++, add(position, 0.0, 1.0));
createPoint(points, i++, add(position, 0.0, 1.4));
createPoint(points, i++, add(position, 0.0, 1.7));
createPoint(points, i++, add(position, 0.0, 2.0));
createPoint(points, i++, add(position, 0.0, 2.4));
createPoint(points, i++, add(position, 0.0, 2.7));
createPoint(points, i++, add(position, 0.5, 0.0));
createPoint(points, i++, add(position, 0.5, 0.4));
createPoint(points, i++, add(position, 0.5, 0.7));
createPoint(points, i++, add(position, 0.5, 1.0));
createPoint(points, i++, add(position, 0.5, 1.4));
createPoint(points, i++, add(position, 0.5, 1.7));
createPoint(points, i++, add(position, 0.5, 2.0));
createPoint(points, i++, add(position, 0.5, 2.4));
createPoint(points, i++, add(position, 0.5, 2.7));
createPoint(points, i++, add(position, 1.0, 2.4));
createPoint(points, i++, add(position, 1.0, 2.7));
createPoint(points, i++, add(position, 1.5, 2.4));
createPoint(points, i++, add(position, 1.5, 2.7));
createPoint(points, i++, add(position, 2.0, 2.4));
createPoint(points, i++, add(position, 2.0, 2.7));
createPoint(points, i++, add(position, 2.5, 2.4));
createPoint(points, i++, add(position, 2.5, 2.7));
return i;
case 'M':
return i;
case 'N':
return i;
case 'O':
createPoint(points, i++, add(position, 0.5, 0.0));
createPoint(points, i++, add(position, 1.0, 0.0));
createPoint(points, i++, add(position, 1.5, 0.0));
createPoint(points, i++, add(position, 2.0, 0.0));
createPoint(points, i++, add(position, 0.0, 0.4));
createPoint(points, i++, add(position, 0.5, 0.4));
createPoint(points, i++, add(position, 1.0, 0.4));
createPoint(points, i++, add(position, 1.5, 0.4));
createPoint(points, i++, add(position, 2.0, 0.4));
createPoint(points, i++, add(position, 2.5, 0.4));
createPoint(points, i++, add(position, 0.0, 0.7));
createPoint(points, i++, add(position, 0.5, 0.7));
createPoint(points, i++, add(position, 1.0, 0.7));
createPoint(points, i++, add(position, 1.5, 0.7));
createPoint(points, i++, add(position, 2.0, 0.7));
createPoint(points, i++, add(position, 2.5, 0.7));
createPoint(points, i++, add(position, 0.0, 1.0));
createPoint(points, i++, add(position, 0.5, 1.0));
createPoint(points, i++, add(position, 2.0, 1.0));
createPoint(points, i++, add(position, 2.5, 1.0));
createPoint(points, i++, add(position, 0.0, 1.4));
createPoint(points, i++, add(position, 0.5, 1.4));
createPoint(points, i++, add(position, 2.0, 1.4));
createPoint(points, i++, add(position, 2.5, 1.4));
createPoint(points, i++, add(position, 0.0, 1.7));
createPoint(points, i++, add(position, 0.5, 1.7));
createPoint(points, i++, add(position, 2.0, 1.7));
createPoint(points, i++, add(position, 2.5, 1.7));
createPoint(points, i++, add(position, 0.0, 2.0));
createPoint(points, i++, add(position, 0.5, 2.0));
createPoint(points, i++, add(position, 1.0, 2.0));
createPoint(points, i++, add(position, 1.5, 2.0));
createPoint(points, i++, add(position, 2.0, 2.0));
createPoint(points, i++, add(position, 2.5, 2.0));
createPoint(points, i++, add(position, 0.0, 2.4));
createPoint(points, i++, add(position, 0.5, 2.4));
createPoint(points, i++, add(position, 1.0, 2.4));
createPoint(points, i++, add(position, 1.5, 2.4));
createPoint(points, i++, add(position, 2.0, 2.4));
createPoint(points, i++, add(position, 2.5, 2.4));
createPoint(points, i++, add(position, 0.5, 2.7));
createPoint(points, i++, add(position, 1.0, 2.7));
createPoint(points, i++, add(position, 1.5, 2.7));
createPoint(points, i++, add(position, 2.0, 2.7));
return i;
case 'P':
return i;
case 'Q':
return i;
case 'R':
return i;
case 'S':
return i;
case 'T':
return i;
case 'U':
return i;
case 'V':
return i;
case 'W':
return i;
case 'X':
return i;
case 'Y':
return i;
case 'Z':
return i;
default:
return i;
}
}
void string2points(const char* string, struct point points[]) {
int length = strlen(string);
struct vector position = (struct vector) {
x: -(length * 4 / 2),
y: -2
};
int index = 0;
for (int i = 0; i < length; i++) {
index += char2points(string[i], &(points[index]), position);
position.x += 4;
}
}
int numberPoints(const char* string) {
int sum = 0;
int length = strlen(string);
for (int i = 0; i < length; i++) {
sum += char2points(string[i], NULL, (struct vector) {0, 0});
}
return sum;
}
void scatter(struct point points[], int number) {
for (int i = 0; i < number; i++) {
points[i].source = points[i].position;
float phi = randomFloat() * M_PI * 2;
float r = sqrt(SCREEN_WIDTH * SCREEN_WIDTH + SCREEN_HEIGHT * SCREEN_HEIGHT) / 2;
points[i].target = (struct vector) {
x: r * cos(phi),
y: r * sin(phi)
};
}
}
int main() {
setlocale(LC_CTYPE, "");
enable_compat_mode(PRINT_WCHAR);
initRandom();
const char* string = "HALLO";
int number = numberPoints(string);
struct point* points = malloc(number * sizeof(struct point));
if (points == NULL)
panic("could allocate point array: %s", strerror(errno));
string2points(string, points);
hideCursor();
eraseScreen();
bool scattered = false;
while(true) {
moveCursorAbsolute(0, 0);
displayPoints(points, number);
//fflush(stdout);
usleep(ANIMATION_SLEEP_TIME);
if (tickPoints(points, number)) {
if (scattered) {
return 0;
} else {
scatter(points, number);
scattered = true;
moveCursorAbsolute(0, 0);
displayPoints(points, number);
usleep(SCATTER_SLEEP_TIME);
}
}
}
}

320
src/gravity.c Normal file
View file

@ -0,0 +1,320 @@
#include <locale.h>
#include <math.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <wchar.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include "common/graphics.h"
#include "common/utils.h"
#define SUBSTITUDE_PRINTS
#include "common/compat.h"
#define G (10.0)
#define OFFSET_X (-50)
#define OFFSET_Y (-15)
#define SCREEN_WIDTH (100)
#define SCREEN_HEIGHT (30)
#define NUMBER_OF_POINTS (2)
#define TERMINAL_VELOCITY (100.0)
#define ASPECT_RATIO (3.0/2.0)
#define FACTOR_X (1.0)
#define FACTOR_Y (FACTOR_X * ASPECT_RATIO)
#define SLEEP_TIME (100000)
#define TICKS_PER_TIME (1)
#define BRAILLE_PREFIX (0x2800)
#define BRAILLE_TOP_LEFT (0x01)
#define BRAILLE_MIDDLE_LEFT (0x02)
#define BRAILLE_BOTTOM_LEFT (0x04)
#define BRAILLE_TOP_RIGHT (0x08)
#define BRAILLE_MIDDLE_RIGHT (0x10)
#define BRAILLE_BOTTOM_RIGHT (0x20)
struct vector {
float x;
float y;
};
struct point {
struct vector position;
struct vector velocity;
struct vector force;
float radius;
float mass;
};
float distance(struct point* a, struct point* b) {
float dx = b->position.x - a->position.x;
float dy = b->position.y - a->position.y;
return sqrt((dx * dx) + (dy * dy));
}
struct vector direction(struct point* a, struct point* b) {
float dx = b->position.x - a->position.x;
float dy = b->position.y - a->position.y;
float r = sqrt((dx * dx) + (dy * dy));
return (struct vector) {
x: dx / r,
y: dy / r
};
}
void tickPoint(struct point* point) {
float factor = SLEEP_TIME / 1000000.0 * TICKS_PER_TIME;
point->position.x += point->velocity.x * factor;
point->position.y += point->velocity.y * factor;
}
void zeroVector(struct vector* vector) {
vector->x = 0;
vector->y = 0;
}
void merge(struct point* a, struct point* b) {
a->position.x = (a->position.x + b->position.x) / 2;
a->position.y = (a->position.y + b->position.y) / 2;
b->position.x = a->position.x;
b->position.y = a->position.y;
a->velocity.x = (a->velocity.x * a->mass + b->velocity.x * b->mass) / (a->mass + b->mass);
a->velocity.y = (a->velocity.y * a->mass + b->velocity.y * b->mass) / (a->mass + b->mass);
b->velocity.x = a->velocity.x;
b->velocity.y = a->velocity.y;
}
void applyGravityToForce(struct point* a, struct point* b) {
float r = distance(a, b);
cprintf("%f, ", r);
if (r <= a->radius + b->radius) {
//merge(a, b);
return;
}
float f = G * (a->mass * b->mass) / (r * r);
struct vector directionAtoB = direction(a, b);
a->force.x += f * directionAtoB.x;
a->force.y += f * directionAtoB.y;
b->force.x += f * directionAtoB.x * (-1);
b->force.y += f * directionAtoB.y * (-1);
//cprintf("%f, %f\n", a->force.x, a->force.y);
}
void applyForceToVelocity(struct point* point) {
point->velocity.x += point->force.x / point->mass;
point->velocity.y += point->force.y / point->mass;
float scalarVelocity = sqrt(point->velocity.x * point->velocity.x + point->velocity.y * point->velocity.y);
if (scalarVelocity > TERMINAL_VELOCITY) {
float capFactor = TERMINAL_VELOCITY / scalarVelocity;
point->velocity.x *= capFactor;
point->velocity.y *= capFactor;
}
zeroVector(&(point->force));
}
struct patternAtom {
int x; // 0-1
int y; // 0-2
};
wchar_t getPattern(struct patternAtom atoms[], int number) {
if (number == 0) {
return L' ';
}
wchar_t result = BRAILLE_PREFIX;
for (int i = 0; i < number; i++) {
if (atoms[i].x == 0) {
if (atoms[i].y == 0) {
result |= BRAILLE_TOP_LEFT;
} else if (atoms[i].y == 1) {
result |= BRAILLE_MIDDLE_LEFT;
} else {
result |= BRAILLE_BOTTOM_LEFT;
}
} else {
if (atoms[i].y == 0) {
result |= BRAILLE_TOP_RIGHT;
} else if (atoms[i].y == 1) {
result |= BRAILLE_MIDDLE_RIGHT;
} else {
result |= BRAILLE_BOTTOM_RIGHT;
}
}
}
return result;
}
struct point randomPoint() {
return (struct point) {
position: {
x: randomFloat() * 20 - 10,
y: randomFloat() * 20 - 10
},
velocity: {
x: (randomFloat() - 0.5) / 1000,
y: (randomFloat() - 0.5) / 1000
},
force: {
x: 0,
y: 0
},
radius: 0.1,
mass: randomFloat() + 0.1
};
}
void initPoints(struct point points[]) {
for (int i = 0; i < NUMBER_OF_POINTS; i++) {
points[i] = randomPoint();
}
}
void tickPoints(struct point points[]) {
for (int i = 0; i < NUMBER_OF_POINTS; i++) {
for (int j = 0; j < NUMBER_OF_POINTS; j++) {
if (i == j)
continue;
applyGravityToForce(&(points[i]), &(points[j]));
}
}
for (int i = 0; i < NUMBER_OF_POINTS; i++) {
applyForceToVelocity(&(points[i]));
tickPoint(&(points[i]));
}
}
struct screenCell {
struct patternAtom* atoms;
int number;
};
void displayPoints(struct point points[]) {
struct screenCell screen[SCREEN_WIDTH][SCREEN_HEIGHT];
for (int x = 0; x < SCREEN_WIDTH; x++) {
for (int y = 0; y < SCREEN_HEIGHT; y++) {
screen[x][y].atoms = NULL;
screen[x][y].number = 0;
}
}
for (int i = 0; i < NUMBER_OF_POINTS; i++) {
struct point p = points[i];
float x = p.position.x * FACTOR_X - OFFSET_X;
float y = p.position.y * FACTOR_Y - OFFSET_Y;
int screenX = floor(x);
int screenY = floor(y);
if (screenX < 0 || screenX >= SCREEN_WIDTH) {
continue;
}
if (screenY < 0 || screenY >= SCREEN_HEIGHT) {
continue;
}
struct patternAtom atom = {
x: floor((x - screenX) * 2),
y: floor((y - screenY) * 3)
};
struct screenCell* cell = &(screen[screenX][screenY]);
cell->atoms = realloc(cell->atoms, ++cell->number * sizeof(struct patternAtom));
if (cell->atoms == NULL) {
panic("couldn't allocate screen buffer: %s", strerror(errno));
}
cell->atoms[cell->number - 1] = atom;
}
for (int y = 0; y < SCREEN_HEIGHT; y++) {
for (int x = 0; x < SCREEN_WIDTH; x++) {
cprintf("%lc", getPattern(screen[x][y].atoms, screen[x][y].number));
}
cprintf("\n");
}
}
int main() {
setlocale(LC_CTYPE, "");
enable_compat_mode(PRINT_WCHAR);
initRandom();
struct point points[NUMBER_OF_POINTS];
//initPoints(points);
// hardcoded points to test orbit example
points[0] = (struct point) {
position: {
x: 0,
y: 0
},
velocity: {
x: 0,
y: 0
},
force: {
x: 0,
y: 0
},
radius: 0.1,
mass: 5
};
points[1] = (struct point) {
position: {
x: 10,
y: 0
},
velocity: {
x: 0,
y: 10
},
force: {
x: 0,
y: 0
},
radius: 0.1,
mass: 0.1
};
hideCursor();
eraseScreen();
while(true) {
moveCursorAbsolute(0, 0);
displayPoints(points);
//fflush(stdout);
usleep(SLEEP_TIME);
for (int i = 0; i < TICKS_PER_TIME; i++)
tickPoints(points);
}
}

17
src/test.c Normal file
View file

@ -0,0 +1,17 @@
#include "common/compat.h"
#include "common/graphics.h"
#include "common/utils.h"
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
if (setvbuf(stdin, NULL, _IONBF, 0) != 0) {
panic("can't set buffer for stdin: %s", strerror(errno));
}
struct dimensions d = getScreenSize();
cprintf("%d, %d\n", d.width, d.height);
}