Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // TOMBOLA SEQUENCER V1.0
- // (c) Ben Johnson 2024
- // Licensed with CC BY 4.0 - reuse, remix, whatever, but pls credit me!
- // Functionality to add: params visibility; respawning
- autowatch = 1;
- outlets = 2;
- mgraphics.init();
- mgraphics.relative_coords = 1;
- mgraphics.autofill = 0;
- var window_width = box.rect[2] - box.rect[0];
- var window_height = box.rect[3] - box.rect[1];
- var config = {
- sides: 5,
- numBalls: 5,
- gravity: -0.00005,
- spinspeed: 0.01
- };
- var rotationAngle = 0;
- var refreshRate = 60;
- var balls = [];
- var edgeHitTimes = [];
- for (var i = 0; i < config.sides; i++) {
- edgeHitTimes.push(0);
- }
- var vertices = [];
- // New: Collision report cooldown
- var collisionCooldowns = {};
- var cooldownTime = 500; // milliseconds
- function createBall() {
- var r = Math.random() * 0.3;
- var angle = Math.random() * 2 * Math.PI;
- return {
- position: [r * Math.cos(angle), r * Math.sin(angle)],
- velocity: [Math.random() * 0.006 - 0.003, Math.random() * 0.006 - 0.003],
- radius: 0.01,
- color: [Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 1]
- };
- }
- for (var i = 0; i < config.numBalls; i++) {
- balls.push(createBall());
- }
- var rotateTask = new Task(updateScene, this);
- rotateTask.interval = 1000 / refreshRate;
- rotateTask.repeat();
- function paint() {
- with (mgraphics) {
- set_source_rgba(0.2, 0.2, 0.2, 1);
- paint();
- drawShapeOutline();
- drawBalls();
- }
- }
- function drawShapeOutline() {
- var angleStep = (2 * Math.PI) / config.sides;
- var radius = 0.8;
- var cosA = Math.cos(rotationAngle);
- var sinA = Math.sin(rotationAngle);
- vertices = [];
- for (var i = 0; i < config.sides; i++) {
- var angle = i * angleStep;
- var x = radius * Math.cos(angle);
- var y = radius * Math.sin(angle);
- vertices.push([x * cosA - y * sinA, x * sinA + y * cosA]);
- }
- for (var i = 0; i < config.sides; i++) {
- var p1 = vertices[i];
- var p2 = vertices[(i + 1) % config.sides];
- if (!p1 || !p2) {
- post("Error: Undefined vertex at index " + i + "\n");
- continue;
- }
- var timeSinceHit = Date.now() - edgeHitTimes[i];
- var hitIntensity = Math.max(0, 1 - timeSinceHit / 500);
- mgraphics.set_source_rgba(0.8 + 0.2 * hitIntensity, 0.8 * (1 - hitIntensity), 0.8 * (1 - hitIntensity), 1);
- var lineWidth = 0.005 + 0.05 * hitIntensity;
- mgraphics.set_line_width(lineWidth);
- mgraphics.move_to(p1[0], p1[1]);
- mgraphics.line_to(p2[0], p2[1]);
- mgraphics.stroke();
- }
- }
- function drawBalls() {
- for (var i = 0; i < balls.length; i++) {
- var ball = balls[i];
- mgraphics.set_source_rgba(ball.color[0], ball.color[1], ball.color[2], ball.color[3]);
- mgraphics.ellipse(ball.position[0] - ball.radius, ball.position[1] - ball.radius, ball.radius * 2, ball.radius * 2);
- mgraphics.fill();
- }
- }
- function updateScene() {
- rotationAngle = (rotationAngle + (2 * Math.PI * config.spinspeed) / refreshRate) % (2 * Math.PI);
- for (var i = 0; i < balls.length; i++) {
- var ball = balls[i];
- ball.velocity[1] += config.gravity;
- ball.position[0] += ball.velocity[0];
- ball.position[1] += ball.velocity[1];
- checkEdgeCollisions(ball, i);
- }
- mgraphics.redraw();
- }
- function checkEdgeCollisions(ball, ballIndex) {
- if (vertices.length !== config.sides) {
- post("Error: Mismatch between config.sides and vertices.length\n");
- return;
- }
- for (var i = 0; i < config.sides; i++) {
- var p1 = vertices[i];
- var p2 = vertices[(i + 1) % config.sides];
- if (!p1 || !p2) {
- post("Error: Undefined vertex at index " + i + " or " + ((i + 1) % config.sides) + "\n");
- continue;
- }
- var edge = [p2[0] - p1[0], p2[1] - p1[1]];
- var edgeLength = Math.sqrt(edge[0] * edge[0] + edge[1] * edge[1]);
- var edgeUnit = [edge[0] / edgeLength, edge[1] / edgeLength];
- var normal = [-edgeUnit[1], edgeUnit[0]];
- var relativePosition = [ball.position[0] - p1[0], ball.position[1] - p1[1]];
- var distanceToEdge = Math.abs(relativePosition[0] * normal[0] + relativePosition[1] * normal[1]);
- if (distanceToEdge < ball.radius) {
- var dotProduct = relativePosition[0] * edgeUnit[0] + relativePosition[1] * edgeUnit[1];
- if (dotProduct >= 0 && dotProduct <= edgeLength) {
- edgeHitTimes[i] = Date.now();
- // Check cooldown before reporting collision
- var cooldownKey = ballIndex + "-" + i;
- var currentTime = Date.now();
- if (!collisionCooldowns[cooldownKey] || currentTime - collisionCooldowns[cooldownKey] > cooldownTime) {
- // post("Ball " + ballIndex + " hit edge between vertices " + i + " and " + ((i + 1) % config.sides) + "\n");
- outlet(0, ballIndex);
- outlet(1, i);
- collisionCooldowns[cooldownKey] = currentTime;
- }
- var velocityDotNormal = ball.velocity[0] * normal[0] + ball.velocity[1] * normal[1];
- ball.velocity[0] -= 2 * velocityDotNormal * normal[0];
- ball.velocity[1] -= 2 * velocityDotNormal * normal[1];
- var penetrationDepth = ball.radius - distanceToEdge;
- ball.position[0] += normal[0] * penetrationDepth;
- ball.position[1] += normal[1] * penetrationDepth;
- if (Math.random() < 0.05) {
- var boostFactor = 1.1 + Math.random() * 0.2;
- ball.velocity[0] *= boostFactor;
- ball.velocity[1] *= boostFactor;
- } else {
- ball.velocity[0] *= 0.99;
- ball.velocity[1] *= 0.99;
- }
- }
- }
- }
- }
- function forcesize(w,h) {
- if (w != h) {
- w = h;
- box.size(w,h);
- }
- }
- forcesize.local = 1;
- function onresize(w,h) {
- forcesize(w,h);
- window_width = box.rect[2] - box.rect[0];
- window_height = box.rect[3] - box.rect[1];
- mgraphics.redraw();
- }
- onresize.local = 1;
Advertisement
Add Comment
Please, Sign In to add comment