Welcome to Code Forum!

Join a community that supports you and your coding journey from day one. We strive to be a friendly, supportive community that empowers everyone to be better developers. By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
  • Guest, before posting your code please take these rules into consideration:
    • It is required to use our BBCode feature to display your code. While within the editor click < / > or >_ and place your code within the BB Code prompt. This helps others with finding a solution by making it easier to read and easier to copy.
    • You can also use markdown to share your code. When using markdown your code will be automatically converted to BBCode. For help with markdown check out the markdown guide.
    • Don't share a wall of code. All we want is the problem area, the code related to your issue.

    GIF shows where to locate </> in the thread and or post editor toolbar.
    To learn more about how to use our BBCode feature, review our "How to post your code into threads" here.

    Thank you, Code Forum.

particle collider prototype won't time step.

eMonolith

Coder
Hello all. My graphics don't step through time like it should. I am trying to write a simple particle sim and I just get a still frame.

C:
#include <X11/Xlib.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h> // Include for usleep

#define WIDTH 1024
#define HEIGHT 1024
#define N 20 // Number of particles
#define RADIUS 512 // Radius of the circular area
#define PARTICLE_RADIUS 5 // Radius of each particle

typedef struct {
    double x, y;
    double angle;
} Particle;

void initialize_particles(Particle particles[], int n) {
    for (int i = 0; i < n; i++) {
        particles[i].angle = (double)rand() / RAND_MAX * 2 * M_PI;
        particles[i].x = WIDTH / 2 + RADIUS * cos(particles[i].angle);
        particles[i].y = HEIGHT / 2 + RADIUS * sin(particles[i].angle);
    }
}

void update_particles(Particle particles[], int n) {
    for (int i = 0; i < n; i++) {
        particles[i].angle += (double)rand() / RAND_MAX * 0.1 - 0.05; // Random angle change
        double new_x = WIDTH / 2 + RADIUS * cos(particles[i].angle);
        double new_y = HEIGHT / 2 + RADIUS * sin(particles[i].angle);
        
        if (sqrt(pow(new_x - WIDTH / 2, 2) + pow(new_y - HEIGHT / 2, 2)) <= RADIUS - PARTICLE_RADIUS) {
            particles[i].x = new_x;
            particles[i].y = new_y;
        }

        for (int j = 0; j < n; j++) {
            if (i != j) {
                double distance = sqrt(pow(particles[i].x - particles[j].x, 2) + pow(particles[i].y - particles[j].y, 2));
                if (distance < 2 * PARTICLE_RADIUS) {
                    double angle = atan2(particles[j].y - particles[i].y, particles[j].x - particles[i].x);
                    particles[i].x -= cos(angle) * 0.5;
                    particles[i].y -= sin(angle) * 0.5;
                }
            }
        }
    }
}

int main() {
    Display *display;
    Window window;
    GC gc;
    Particle particles[N];

    srand(time(NULL));
    initialize_particles(particles, N);

    display = XOpenDisplay(NULL);
    window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, WIDTH, HEIGHT, 0, 0, 0);
    XSelectInput(display, window, ExposureMask | KeyPressMask);
    XMapWindow(display, window);
    gc = XCreateGC(display, window, 0, NULL);

    while (1) {
        XEvent event;
        while (XPending(display)) {
            XNextEvent(display, &event);
            if (event.type == KeyPress) break;
        }

        XClearWindow(display, window);
        XSetForeground(display, gc, 0xFF00FF);
        for (int i = 0; i < N; i++) {
            XDrawArc(display, window, gc, particles[i].x - PARTICLE_RADIUS, particles[i].y - PARTICLE_RADIUS,
                      2 * PARTICLE_RADIUS, 2 * PARTICLE_RADIUS, 0, 360 * 64);
        }
        update_particles(particles, N);
        
        usleep(16666); // Sleep for approximately 60 frames per second
    }

    XFreeGC(display, gc);
    XDestroyWindow(display, window);
    XCloseDisplay(display);
    return 0;
}
 
Last edited:
Hey — looks like your code’s not stepping through frames 'cause you're drawing before the window's actually ready.

You need to wait for the first Expose event before starting your draw loop, otherwise you're basically drawing to nothing. Also, you’re not flushing the display — so nothing gets shown even when you are drawing.

Here’s the fix:
Code:
// Wait until window is ready to draw
XEvent event;
do {
    XNextEvent(display, &event);
} while (event.type != Expose);

And slap in an XFlush(display); after your drawing code so the frame actually gets pushed to the screen.

Also, might be worth flipping your while (1) into something like int running = 1; and set that to 0 on keypress, just so it's a bit cleaner.

Once you do that, should be golden. Particles will actually move instead of sitting there like lemons.
 
You're not getting animation because the main loop exits immediately after the first key press.
Fix: Move the break into a flag or add proper event handling.
Code:
int running = 1;
while (running) {
    while (XPending(display)) {
        XNextEvent(display, &event);
        if (event.type == KeyPress) running = 0;
    }

    XClearWindow(display, window);
    XSetForeground(display, gc, 0xFF00FF);
    for (int i = 0; i < N; i++) {
        XDrawArc(display, window, gc, particles[i].x - PARTICLE_RADIUS, particles[i].y - PARTICLE_RADIUS,
                  2 * PARTICLE_RADIUS, 2 * PARTICLE_RADIUS, 0, 360 * 64);
    }
    update_particles(particles, N);

    usleep(16666); // ~60 FPS
}
 
You're not getting animation because the main loop exits immediately after the first key press.
Fix: Move the break into a flag or add proper event handling.
Code:
int running = 1;
while (running) {
    while (XPending(display)) {
        XNextEvent(display, &event);
        if (event.type == KeyPress) running = 0;
    }

    XClearWindow(display, window);
    XSetForeground(display, gc, 0xFF00FF);
    for (int i = 0; i < N; i++) {
        XDrawArc(display, window, gc, particles[i].x - PARTICLE_RADIUS, particles[i].y - PARTICLE_RADIUS,
                  2 * PARTICLE_RADIUS, 2 * PARTICLE_RADIUS, 0, 360 * 64);
    }
    update_particles(particles, N);

    usleep(16666); // ~60 FPS
}
I did

Code:
int running = 1;
while (running) {
    while (XPending(display)) {
    XEvent event;
        XNextEvent(display, &event);
        if (event.type == KeyPress) running = 0;
    }

    XClearWindow(display, window);
    XSetForeground(display, gc, 0xFF00FF);
    for (int i = 0; i < N; i++) {
        XDrawArc(display, window, gc, particles[i].x - PARTICLE_RADIUS, particles[i].y - PARTICLE_RADIUS,
                  2 * PARTICLE_RADIUS, 2 * PARTICLE_RADIUS, 0, 360 * 64);
    }
    update_particles(particles, N);

    usleep(16666); // ~60 FPS
}

I still have the same proplem, nothing has changed.

I haven't worked on this prog for at least a week. I am giving up until I learn more about xlib and this needed while loop.
 

Buy us a coffee!

Buy me a coffee.
Back
Top Bottom