diff options
| author | Sam Anthony <sam@samanthony.xyz> | 2024-09-19 20:11:32 -0400 |
|---|---|---|
| committer | Sam Anthony <sam@samanthony.xyz> | 2024-09-19 20:11:32 -0400 |
| commit | d439ed77546a00929ddd55bf44d65b448d9d520c (patch) | |
| tree | cf1070d32e766c0fe5d753aebee840f0be67756f | |
| parent | 8944ad075c6b12bbda1273ec31efade801892c19 (diff) | |
| download | balls-d439ed77546a00929ddd55bf44d65b448d9d520c.zip | |
pretty good collisions
| -rw-r--r-- | balls.c | 52 | ||||
| -rw-r--r-- | balls.h | 14 | ||||
| -rw-r--r-- | collision.c | 4 | ||||
| -rw-r--r-- | mkfile | 5 | ||||
| -rw-r--r-- | vec.c | 16 |
5 files changed, 45 insertions, 46 deletions
@@ -7,6 +7,8 @@ #define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) +#define G 0.25 + enum { BG = DWhite, WALLS = DBlack, @@ -19,9 +21,8 @@ enum { DEFAULT_NBALLS = 3, - VMAX = 5, - G = 1, - MASS = 1, + VMAX = 3, + MASS = 10, FPS = 60, NS_PER_SEC = 1000000000, @@ -172,17 +173,11 @@ spawnballs(int n) { } for (i = 0; i < n; i++) { - for (j = 0; j < n; j++) - printf("%16p ", cs[i][j]); - printf("\n\n"); - } - - for (i = 0; i < n; i++) { if ((arg = malloc(sizeof(BallArg))) == nil) sysfatal("failed to allocate ball"); arg->b.p = ps[i]; - arg->b.v = V(randint(-VMAX, VMAX+1), randint(-VMAX, VMAX+1)); + arg->b.v = V((double) randint(-VMAX, VMAX+1), (double) randint(-VMAX, VMAX+1)); arg->b.m = MASS; arg->color = ballcolors[randint(0, NELEMS(ballcolors))]; @@ -192,18 +187,11 @@ spawnballs(int n) { if ((arg->in = malloc((n-1)*sizeof(Channel *))) == nil) sysfatal("failed to allocate array of incoming channels"); mcopycolskip(arg->in, cs, n, i, i); - printf("%d in:\n", i); - for (j = 0; j < n-1; j++) - printf("%16p ", arg->in[j]); - printf("\n"); if ((arg->out = malloc((n-1)*sizeof(Channel *))) == nil) sysfatal("failed to allocate array of outgoing channels"); vcopyskip(arg->out, cs[i], n, i); - printf("%d: out\n", i); - for (j = 0; j < n-1; j++) - printf("%16p ", arg->out[j]); - printf("\n\n"); + arg->nothers = n-1; threadcreate(ball, arg, mainstacksize); @@ -297,7 +285,7 @@ ball(void *arg) { Ball other; Point midpoint; Vec d, n; - int magnitude; + double magnitude; int t; barg = (BallArg *) arg; @@ -315,7 +303,7 @@ ball(void *arg) { p = ptaddv(p, v); - printf("(%d,%d) %d %d\n", p.x, p.y, v.x, v.y); + printf("(%d,%d) %f %f\n", p.x, p.y, v.x, v.y); /* check for wall collision */ if (p.x < bounds.min.x+RADIUS || p.x > bounds.max.x-RADIUS) { @@ -332,18 +320,24 @@ ball(void *arg) { /* check for ball collision */ for (i = 0; i < barg->nothers; i++) { - printf("recv %16p\n", barg->in[i]); recv(barg->in[i], &other); if (iscollision(p, other.p)) { midpoint = divpt(addpt(p, other.p), 2); - d = Vpt(p, other.p); - p = ptaddv(midpoint, vmuls(unitnorm(d), -RADIUS)); + d = Vpt(other.p, p); + p = ptaddv(midpoint, vmuls(unitnorm(d), RADIUS)); + + printf("collision (%d,%d), (%d,%d)\n", p.x, p.y, other.p.x, other.p.y); + + printf("oldv: (%2.2f,%2.2f\n", v.x, v.y); n = unitnorm(Vpt(other.p, p)); - magnitude = 2*vdot(v, n) / (m + other.m); - v = vsub(v, vmuls( - vsub(vmuls(n, m), vmuls(n, other.m)), - magnitude)); + magnitude = 2*(vdot(v, n) - vdot(other.v, n)) / (m + other.m); + + printf("n: (%2.2f,%2.2f), magnitude: %2.2f\n", n.x, n.y, magnitude); + + v = vsub(v, vmuls(n, magnitude * m)); + + printf("newv: (%2.2f,%2.2f)\n", v.x, v.y); } } @@ -396,10 +390,8 @@ max(int a, int b) { void broadcast(Point p, Channel *cs[], int n) { - while (n-- > 0) { - printf("send %16p\n", cs[n]); + while (n-- > 0) send(cs[n], &p); - } } void @@ -8,7 +8,7 @@ enum { }; typedef struct { - int x, y; + double x, y; } Vec; typedef struct { @@ -18,17 +18,17 @@ typedef struct { typedef struct { Point p; /* position */ Vec v; /* velocity */ - int m; /* mass */ + double m; /* mass */ } Ball; Vec vsub(Vec v1, Vec v2); -Vec vmuls(Vec v, int a); -Vec vdivs(Vec v, int a); -int vdot(Vec v1, Vec v2); -int vlen(Vec v); +Vec vmuls(Vec v, double a); +Vec vdivs(Vec v, double a); +double vdot(Vec v1, Vec v2); +double vlen(Vec v); Vec unitnorm(Vec v); Point ptaddv(Point p, Vec v); -Vec V(int x, int y); +Vec V(double x, double y); Vec Vpt(Point p, Point q); int iscollision(Point p, Point q);
\ No newline at end of file diff --git a/collision.c b/collision.c index d377d39..334256e 100644 --- a/collision.c +++ b/collision.c @@ -5,8 +5,8 @@ iscollision(Point p, Point q) { int dx, dy; dx = p.x - q.x; - dy = p.y-q.y; - return (dx*dx + dy*dy) < 4*RADIUS*RADIUS; + dy = p.y - q.y; + return (dx*dx + dy*dy) <= 4*RADIUS*RADIUS; } /* TODO: remove @@ -1,14 +1,17 @@ CC=9c LD=9l O=o +LDFLAGS= OBJ = balls.$O vec.$O collision.$O balls: $OBJ - $LD -o balls $OBJ + $LD -o balls $OBJ $LDFLAGS %.$O: %.c $CC $CFLAGS $stem.c +OBJ: balls.h + clean:V: rm -f ./*.$O balls
\ No newline at end of file @@ -6,23 +6,23 @@ vsub(Vec v1, Vec v2) { } Vec -vmuls(Vec v, int a) { +vmuls(Vec v, double a) { return V(v.x*a, v.y*a); } Vec -vdivs(Vec v, int a) { +vdivs(Vec v, double a) { if (a == 0) return V(0, 0); return V(v.x/a, v.y/a); } -int +double vdot(Vec v1, Vec v2) { return v1.x*v2.x + v1.y*v2.y; } -int +double vlen(Vec v) { return sqrt(v.x*v.x + v.y*v.y); } @@ -40,12 +40,16 @@ ptaddv(Point p, Vec v) { } Vec -V(int x, int y) { +V(double x, double y) { Vec v = {x, y}; return v; } Vec Vpt(Point p, Point q) { - return V(p.x-q.x, p.y-q.y); + double dx, dy; + + dx = (double) q.x - (double) p.x; + dy = (double) q.y - (double) p.y; + return V(dx, dy); } |