heading out of library hey here is the nonworking c code i tried write this is the farthest i've gotten on a particle system in probably over a decade! i made them for fun when i was a kid in the 90s.
#include <stddef.h>
struct disp
{
int ttyfd;
size_t width, height;
float logical_left, logical_top;
float logical_width, logical_height;
char * buf;
size_t _size;
};
#define _GNU_SOURCE
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
struct disp disp_alloc(float logical_left, float logical_top, float logical_width, float logical_height, char const * ttyfn, size_t width, size_t height)
{
struct disp result = {
.ttyfd = open(ttyfn, O_WRONLY),
.width = width,
.height = height,
.logical_left = logical_left,
.logical_top = logical_top,
.logical_width = logical_width,
.logical_height = logical_height,
.buf = malloc(width*height),
._size = width * height
};
if (result.ttyfd == -1) {
perror("opening tty");
exit(errno);
}
memset(result.buf, ' ', result._size);
return result;
}
void get_environment_width_height(size_t * width, size_t * height)
{
*width = atol(getenv("COLUMNS"));
*height = atol(getenv("LINES"));
}
void disp_free(struct disp * d)
{
close(d->ttyfd);
free(d->buf);
memset(d, 0, sizeof(*d));
}
int disp_blit(struct disp * d)
{
int status = write(d->ttyfd, d->buf, d->_size);
fsync(d->ttyfd);
return status;
}
void disp_plot_term(struct disp * d, size_t x, size_t y, char ch)
{
d->buf[y*d->width+x] = ch;
}
void disp_plot_logic(struct disp * d, float x, float y, char ch)
{
disp_plot_term(
d,
(size_t)((x - d->logical_left) * (d->width-1) / d->logical_width),
(size_t)((y - d->logical_top) * (d->height-1) / d->logical_height),
ch
);
}
void disp_clear(struct disp * d, char ch)
{
memset(d->buf, ch, d->_size);
}
struct particl
{
float x, y;
float xv, yv;
float xa, ya;
float spawn_time;
//float life;
};
void particl_update(struct particl * p, float time)
{
p->x += p->xv * time;
p->y += p->yv * time;
p->xv += p->xa * time;
p->yv += p->ya * time;
//p->life -= time;
//return p->life > 0;
}
#include <stdint.h>
float randf(float min, float max)
{
uint32_t rmax = mrand48();
uint32_t rmin = 0xffffffff ^ rmax;
return (rmin * min + rmax * max) / 0xffffffff;
}
long int randi(long int start, long int end)
{
long int size = end - start;
assert(size <= 0xffffffff);
// to preserve uniform distribution, retry if greater than rand_max
uint32_t rand_max = 0xffffffff - (0xffffffff % size);
uint32_t r;
do {
r = mrand48();
} while (r >= rand_max);
return start + (r % size);
}
#include <time.h>
struct time
{
float diff;
float now;
struct timespec _tp_start;
struct timespec _tp_now;
};
struct time time_create()
{
struct time result = {.diff=0,.now=0};
int status = clock_gettime(CLOCK_MONOTONIC_RAW, &result._tp_start);
assert(status == 0);
result._tp_now = result._tp_start;
return result;
}
void time_update(struct time * time)
{
struct timespec tp;
int status = clock_gettime(CLOCK_MONOTONIC_RAW, &tp);
assert(status == 0);
unsigned long diff_nanos = (tp.tv_sec - time->_tp_now.tv_sec) * 1000000000UL +
tp.tv_nsec - time->_tp_now.tv_nsec;
time->_tp_now = tp;
time->diff = diff_nanos / 1000000000.f;
time->now = tp.tv_sec - time->_tp_start.tv_sec + (tp.tv_nsec - (float)time->_tp_start.tv_nsec) / 1000000000;
}
#include <math.h>
int main()
{
struct particl particls[100];
size_t cli_width, cli_height;
float gravity = 0.1;
float spawn_x = 0, spawn_y = 0;
float spawn_speed = 1;
float spawn_angle = M_PI_4;
struct time time = time_create();
struct disp display;
get_environment_width_height(&cli_width, &cli_height);
display = disp_alloc(-1, 1, 2, -2, "/dev/tty", cli_width, cli_height);
int n_particl = 0, n_particls = 0;
float spawn_period = 1;
float next_particl_time = time.now;
while ("user lets particls run") {
while (time.now >= next_particl_time) {
float angle = randf(-spawn_angle, spawn_angle);
particls[n_particl] = (struct particl){
.x = spawn_x,
.y = spawn_y,
.xv = spawn_speed * cos(angle),
.yv = spawn_speed * sin(angle),
.xa = 0,
.ya = -gravity,
.spawn_time = time.now
};
if (n_particls < sizeof(particls) / sizeof(particls[0])) {
++ n_particls;
}
n_particl = (n_particl+1)%(sizeof(particls)/sizeof(particls[0]));
next_particl_time += spawn_period;
}
disp_clear(&display, ' ');
for (size_t n = 0; n < n_particls; ++ n) {
particl_update(&particls[n], time.diff);
disp_plot_logic(&display, particls[n].x, particls[n].y, '*');
}
disp_blit(&display);
}
disp_free(&display);
}
makefile
Description: Binary data
