ZealOS/src/Demo/Games/Collision.ZC
2023-11-12 10:40:40 -05:00

166 lines
No EOL
4.3 KiB
HolyC
Executable file
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*Uses $LK,"fixed-point",A="FI:::/Demo/Lectures/FixedPoint.ZC"$ arithmetic
because it used to be faster than floating
point. See $LK,"::/Demo/Lectures/FixedPoint.ZC"$.
The decimal place is between
bits 31 and 32.
*/
#define BALLS_NUM 64
#define BALL_RADIUS 5
I64 ball_x[BALLS_NUM], ball_y[BALLS_NUM], ball_velocity_x[BALLS_NUM], ball_velocity_y[BALLS_NUM];
U0 DrawIt(CTask *, CDC *dc)
{
I64 i;
dc->color = RED;
for (i = 0; i < BALLS_NUM; i++)
GrCircle(dc, ball_x[i].i32[1], ball_y[i].i32[1], BALL_RADIUS);
}
/****
$SP,"",BI=1$
Initial and final velocity vects
with normal and tangential components.
All masses are ident, so they
have been dropped from the equations.
Conservation of Momentum:
V1$SY,3$it$SY,0$+V2$SY,3$it$SY,0$=V1$SY,3$ft$SY,0$+V2$SY,3$ft$SY,0$
V1$SY,3$in$SY,0$+V2$SY,3$in$SY,0$=V1$SY,3$fn$SY,0$+V2$SY,3$fn$SY,0$
Conservation of Energy:
|V1$SY,3$i$SY,0$|$SY,-3$2$SY,0$+|V2$SY,3$i$SY,0$|$SY,-3$2$SY,0$=|V1$SY,3$f$SY,0$|$SY,-3$2$SY,0$+|V2$SY,3$f$SY,0$|$SY,-3$2$SY,0$
****/
U0 AnimateTask(I64)
{
CTask *task = Fs->parent_task;
I64 i, j, h, v, distdist,
dia = (2 * BALL_RADIUS) << 32,
diadia = SqrI64(2 *BALL_RADIUS) << 32,
delta_x, delta_y, v_t1, v_n1, v_t2, v_n2;
F64 dist;
while (TRUE)
{
h = task->pix_width;
v = task->pix_height;
for (i = 0; i < BALLS_NUM; i++)
{
ball_x[i] += ball_velocity_x[i];
ball_y[i] += ball_velocity_y[i];
if (ball_x[i] < BALL_RADIUS << 32)
{
ball_velocity_x[i] *= -1;
ball_x[i] = BALL_RADIUS << 32;
}
if (ball_x[i] >= (h - BALL_RADIUS) << 32)
{
ball_velocity_x[i] *= -1;
ball_x[i] = (h - BALL_RADIUS) << 32;
}
if (ball_y[i] < BALL_RADIUS << 32)
{
ball_velocity_y[i] *= -1;
ball_y[i] = BALL_RADIUS << 32;
}
if (ball_y[i] >= (v - BALL_RADIUS) << 32)
{
ball_velocity_y[i] *= -1;
ball_y[i] = (v - BALL_RADIUS) << 32;
}
}
for (i = 0; i < BALLS_NUM; i++)
{
for (j = i + 1; j < BALLS_NUM; j++)
{
delta_x = ball_x[i] - ball_x[j];
delta_y = ball_y[i] - ball_y[j];
//We shift 16 because multiplying
//two 32 shifted would yield 64 shifted
//and we want a 32 shifted res.
distdist = SqrI64(delta_x >> 16) + SqrI64(delta_y >> 16);
//We work with square instead of sqrt
//to avoid unnecessarily calculating
//square heads (They are slow.)
if (distdist && distdist <= diadia)
{
dist = Sqrt(distdist); //shifted 16 bits
delta_x /= dist; //shifted 16
delta_y /= dist;
v_t1 = (ball_velocity_x[i] >> 16 * delta_y - ball_velocity_y[i] >> 16 * delta_x) >> 16;
v_n1 = (ball_velocity_x[i] >> 16 * delta_x + ball_velocity_y[i] >> 16 * delta_y) >> 16;
v_t2 = (ball_velocity_x[j] >> 16 * delta_y - ball_velocity_y[j] >> 16 * delta_x) >> 16;
v_n2 = (ball_velocity_x[j] >> 16 * delta_x + ball_velocity_y[j] >> 16 * delta_y) >> 16;
if (ball_velocity_x[i] >> 16 * ball_velocity_x[j] >> 16 +
ball_velocity_y[i] >> 16 * ball_velocity_y[j] >> 16 <= 0)
{
ball_velocity_x[i] = v_t1 * delta_y - v_n1 * delta_x;
ball_velocity_y[i] = -v_t1 * delta_x - v_n1 * delta_y;
ball_velocity_x[j] = v_t2 * delta_y - v_n2 * delta_x;
ball_velocity_y[j] = -v_t2 * delta_x - v_n2 * delta_y;
}
else
{
ball_velocity_x[i] = v_t1 * delta_y + v_n2 * delta_x;
ball_velocity_y[i] = -v_t1 * delta_x + v_n2 * delta_y;
ball_velocity_x[j] = v_t2 * delta_y + v_n1 * delta_x;
ball_velocity_y[j] = -v_t2 * delta_x + v_n1 * delta_y;
}
//Correct for overlap
dist = 0x10000 + (dia / 0x10000 - dist) / 2;
ball_x[i] += dist * delta_x;
ball_y[i] += dist * delta_y;
ball_x[j] -= dist * delta_x;
ball_y[j] -= dist * delta_y;
}
}
}
Sleep(1);
}
}
U0 Init()
{
I64 i;
for (i = 0; i < BALLS_NUM; i++)
{
ball_x[i] = (RandU16 % (Fs->pix_width - BALL_RADIUS * 2) + BALL_RADIUS) << 32;
ball_y[i] = (RandU16 % (Fs->pix_height - BALL_RADIUS * 2) + BALL_RADIUS) << 32;
ball_velocity_x[i] = RandI32 / 4;
ball_velocity_y[i] = RandI32 / 4;
}
}
U0 Collision()
{
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
Init;
Fs->animate_task = Spawn(&AnimateTask, NULL, "Animate",, Fs);
DocCursor;
DocClear;
Fs->draw_it = &DrawIt;
CharGet;
SettingsPop;
}
Collision;
Wd   ÇrîΦ   rÉ ê   v_tÉv_n