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);
}

Attachment: makefile
Description: Binary data

Reply via email to