summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Anthony <sam@samanthony.xyz>2024-09-19 20:11:32 -0400
committerSam Anthony <sam@samanthony.xyz>2024-09-19 20:11:32 -0400
commitd439ed77546a00929ddd55bf44d65b448d9d520c (patch)
treecf1070d32e766c0fe5d753aebee840f0be67756f
parent8944ad075c6b12bbda1273ec31efade801892c19 (diff)
downloadballs-d439ed77546a00929ddd55bf44d65b448d9d520c.zip
pretty good collisions
-rw-r--r--balls.c52
-rw-r--r--balls.h14
-rw-r--r--collision.c4
-rw-r--r--mkfile5
-rw-r--r--vec.c16
5 files changed, 45 insertions, 46 deletions
diff --git a/balls.c b/balls.c
index c2ce030..b284492 100644
--- a/balls.c
+++ b/balls.c
@@ -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
diff --git a/balls.h b/balls.h
index 0fa93a7..8e66ae0 100644
--- a/balls.h
+++ b/balls.h
@@ -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
diff --git a/mkfile b/mkfile
index f5c1922..e43c880 100644
--- a/mkfile
+++ b/mkfile
@@ -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
diff --git a/vec.c b/vec.c
index ba8edfa..b03a03f 100644
--- a/vec.c
+++ b/vec.c
@@ -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);
}