This set of programs were origionaly meant to be written in java to go with the whole web-based project theme, but java is too slow, and too unfamiliar... so pick your OS and download the thing.

angular momentum

My crowning achevement! The only thing missing is "shocks" to damped the springs. But this at least demonstrates conservation of mechanical energy. it won't stop shaking!

Download source code and executable:  Windows   Linux


In reading the source code, know that this is the only function to be concerned about understanding. The other functions are only init and helper functions

void MoveSprites(SDL_Surface *screen, Uint32 background)
{
        static int old = 0;           <----
        static int newx = 1;        <----      new and old frames.. acceleration is based on an instant of a neighboring nodes, x/y variables
        float force;                     <--- scalar value of  the sum of all the spring forces for a node
        float dx, dy, d;                <--- sin, cos and hypot
        int l;                                <--loop counter
        int sumx = 0;                   <---sum of y forces
        int sumy = 0;                     <----sum of x forces
        int i, nupdates;
        SDL_Rect area;
        SDL_Rect *dstrect = NULL;     <-- ignore

        nupdates = 0;


        SDL_FillRect(screen, dstrect, 0);  <--  ignore


        /* Move the sprite, bounce at the wall, and draw */
        for ( i=0; i<numsprites; ++i ) {
                for(l = 0; l<8 && nodes[i].neigbor[l] != NULL;l++) {
                        dx = nodes[i].neigbor[l]->x[old] - nodes[i].x[old];
                        dy = nodes[i].neigbor[l]->y[old] - nodes[i].y[old];

                        if((dx == 0.0f)&&(dy == 0.0f))
                                d = 0;
                        else if (dx == 0.0f) {
                                d = fabsf(dy);
                                dy=dy/d;
                        }
                        else if (dy == 0.0f) {
                                d = fabsf(dx);
                                dx=dx/d;
                        }
                        else {
                        d = sqrt(float(dx*dx)+(dy*dy)); //pythagorean distance
                        dx /= d;
                        dy /= d;
                        }
                        d -= nodes[i].ne[l]; //get distance relative to equalibrium
                        force = (200.0*d);
         if ( force > 0 )
            force -= 10;
         //   printf( "positive\n" );
         else
            force += 10;
         //   printf( "negative\n" );
                        sumx += dx*force; //cos*k*d
                        sumy += dy*force; //sin*k*d
                }
                nodes[i].vx += (sumx*time_elapsed) + right * 0.1;
                nodes[i].vy += (sumy*time_elapsed) + down * 0.1;
                nodes[i].x[newx] = nodes[i].x[old] + (nodes[i].vx*time_elapsed);
                nodes[i].y[newx] = nodes[i].y[old] + (nodes[i].vy*time_elapsed);

                if (nodes[i].x[newx] < sprite_w/2) {
                        nodes[i].x[newx] = sprite_w/2;
         nodes[i].vx *= 0.0;
                //      nodes[i].vx = -nodes[i].vx;
                }
                if (nodes[i].x[newx] > (screen->w - sprite_w/2)) {
                        nodes[i].x[newx] = screen->w - sprite_w/2;
         nodes[i].vx *= 0.0;
                //      nodes[i].vx = -nodes[i].vx;
                }
                if (nodes[i].y[newx] < sprite_w/2) {
                        nodes[i].y[newx] = sprite_w/2;
         nodes[i].vy *= 0.0;
                //      nodes[i].vy = -nodes[i].vy;
                }
                if (nodes[i].y[newx] > (screen->h - sprite_w/2)) {
                        nodes[i].y[newx] = screen->h - sprite_w/2;
         nodes[i].vy *= -0.0;
         //     nodes[i].vy = -nodes[i].vy;
                }

                sumx = 0;
                sumy = 0;
        }
        for ( i=0; i<numsprites; i+=2 ) {

                for(l = 0; l<8 && nodes[i].neigbor[l] != NULL; l++) {
                        drawline(screen, (int)nodes[i].neigbor[l]->x[newx], (int)nodes[i].neigbor[l]->y[newx], (int)nodes[i].x[newx], (int)nodes[i].y[newx]);
                }
        }
        for ( i=0; i<numsprites; ++i ) {


                area.x = (int)nodes[i].x[newx] - sprite_w/2;
                area.y = (int)nodes[i].y[newx] - sprite_w/2;

                SDL_BlitSurface(sprite, NULL, screen, &area);
                sprite_rects[nupdates++] = area;
        }
        i = old;
        old = newx;
        newx = i;
        SDL_UpdateRect(screen, 0, 0, 0, 0);

        /* Update the screen! */
        if ( (screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
                SDL_Flip(screen);
        } else {
                SDL_UpdateRects(screen, nupdates, sprite_rects);
        }

}