Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ── bouncing discs: random diameters, floor bounce, side ejection ───────────
- // 5 discs always active. They fall with gravity, bounce on the ground, collide
- // with each other, and can be kicked sideways. If a disc exits left/right,
- // it respawns at the top with a new random size/color/velocity.
- static uint8_t demoBouncingDiscs(coord cx, coord cy, coord tScale, bool reinit) {
- static constexpr uint8_t kN = 6;
- static coord px[kN], py[kN], vx[kN], vy[kN], rad[kN];
- static uint8_t hue[kN];
- static const coord kGravity = coord::from_raw(5898); // 0.09 px/frame^2
- static const coord kAirDampX = coord::from_raw(64880); // ~0.99
- static const coord kAirDampY = coord::from_raw(65405); // ~0.998
- static const coord kGroundBounce= coord::from_raw(52429); // 0.80
- static const coord kCollMix = coord::from_raw(49152); // 0.75
- static const coord kRollDamp = coord::from_raw(64225); // ~0.98
- const coord xLeft = coord::from_raw(0);
- const coord xRight = coord::from_raw((int32_t)(kMatrixWidth - 1) << 16);
- const coord yGround= coord::from_raw((int32_t)(kMatrixHeight - 1) << 16);
- auto spawn = [&](uint8_t i) {
- // Radius in [1.0 .. 2.8] px (random diameter)
- rad[i] = coord::from_raw(130000 + (int32_t)(random8() & 0x7F) * 921);
- // Spawn at random X, slightly above top
- px[i] = coord::from_raw((int32_t)(random8() % kMatrixWidth) << 16);
- py[i] = coord::from_raw(-rad[i].raw() - ((int32_t)(random8() & 0x1F) << 10));
- // Small random initial velocities
- vx[i] = coord::from_raw(((int32_t)(int8_t)random8()) * 320); // about ±0.6 px/frame
- vy[i] = coord::from_raw(9830 + (int32_t)(random8() & 0x3F) * 120); // ~0.15..0.27 down
- hue[i] = random8();
- };
- if (reinit) {
- for (uint8_t i = 0; i < kN; ++i) spawn(i);
- }
- // Integrate + ground bounce + side-exit recycle
- for (uint8_t i = 0; i < kN; ++i) {
- vy[i] = (vy[i] + kGravity) * kAirDampY;
- vx[i] = vx[i] * kAirDampX;
- px[i] = px[i] + vx[i];
- py[i] = py[i] + vy[i];
- // Ground bounce
- coord floorY = yGround - rad[i];
- if (py[i] > floorY) {
- py[i] = floorY;
- if (vy[i].raw() > 0) vy[i] = coord::from_raw(-vy[i].raw()) * kGroundBounce;
- vx[i] = vx[i] * kRollDamp;
- if (vy[i].raw() > -2500 && vy[i].raw() < 2500) vy[i] = coord{}; // settle tiny jitter
- }
- // If disc is kicked fully out of screen to either side -> respawn from top
- if (px[i] < xLeft - rad[i] * coord(2) || px[i] > xRight + rad[i] * coord(2)) {
- spawn(i);
- }
- }
- // Disc-disc collisions (biased to create sideways kick-outs)
- for (uint8_t i = 0; i < kN; ++i) {
- for (uint8_t j = i + 1; j < kN; ++j) {
- int32_t dx = px[j].raw() - px[i].raw();
- int32_t dy = py[j].raw() - py[i].raw();
- int32_t adx = dx < 0 ? -dx : dx;
- int32_t ady = dy < 0 ? -dy : dy;
- int32_t sumR = (rad[i] + rad[j]).raw();
- if (adx < sumR && ady < sumR) {
- int32_t overlapX = sumR - adx;
- if (overlapX < 0) overlapX = 0;
- // Separate mostly along X so contacts eject sideways
- int32_t push = (overlapX >> 1) + 256;
- if (dx >= 0) {
- px[i] = coord::from_raw(px[i].raw() - push);
- px[j] = coord::from_raw(px[j].raw() + push);
- } else {
- px[i] = coord::from_raw(px[i].raw() + push);
- px[j] = coord::from_raw(px[j].raw() - push);
- }
- // Size-weighted horizontal impulse (smaller discs get kicked more)
- int32_t mi = rad[i].raw();
- int32_t mj = rad[j].raw();
- int32_t denom = mi + mj;
- if (denom <= 0) denom = 1;
- coord dvx = (vx[j] - vx[i]) * kCollMix;
- coord wi = coord::from_raw((int32_t)((int64_t)mj * 65536 / denom));
- coord wj = coord::from_raw((int32_t)((int64_t)mi * 65536 / denom));
- vx[i] = vx[i] + dvx * wi;
- vx[j] = vx[j] - dvx * wj;
- // Extra lateral kick from compression
- int32_t kickRaw = overlapX * 2;
- if (kickRaw > 65536) kickRaw = 65536;
- coord kick = coord::from_raw(kickRaw);
- if (dx >= 0) {
- vx[i] = vx[i] - kick;
- vx[j] = vx[j] + kick;
- } else {
- vx[i] = vx[i] + kick;
- vx[j] = vx[j] - kick;
- }
- // Light vertical damping to avoid explosive stacks
- vy[i] = vy[i] * coord::from_raw(64225); // ~0.98
- vy[j] = vy[j] * coord::from_raw(64225);
- }
- }
- }
- // Draw
- for (uint8_t i = 0; i < kN; ++i) {
- hue[i] += 1;
- coord sx = cx + (px[i] - cx) * tScale;
- coord sy = cy + (py[i] - cy) * tScale;
- drawDisc(sx, sy, rad[i] * tScale, CHSV(hue[i], 220, 255));
- }
- return 255;
- }
Advertisement
Add Comment
Please, Sign In to add comment