Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- autowatch = 1;
- outlets = 3;
- 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: 8,
- numBalls: 12,
- gravity: 0.4,
- spinspeed: -0.4,
- cooldownTime: 300,
- damping: 0.05,
- ballSize: 0.01,
- shapeSize: 0.9
- };
- 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 = {};
- 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: config.ballSize,
- 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 hslToRgb(h, s, l) {
- var r, g, b;
- if (s == 0) {
- r = g = b = l;
- } else {
- function hue2rgb(p, q, t) {
- if (t < 0) t += 1;
- if (t > 1) t -= 1;
- if (t < 1/6) return p + (q - p) * 6 * t;
- if (t < 1/2) return q;
- if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
- return p;
- }
- var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
- var p = 2 * l - q;
- r = hue2rgb(p, q, h + 1/3);
- g = hue2rgb(p, q, h);
- b = hue2rgb(p, q, h - 1/3);
- }
- return [r, g, b];
- }
- function drawShapeOutline() {
- var angleStep = (2 * Math.PI) / config.sides;
- var radius = config.shapeSize;
- 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);
- // Calculate flash color using HSL
- var hue = i / config.sides;
- var flashColor = hslToRgb(0.75-hue*0.75, 0.8, 0.6);
- // Interpolate between grey (0.8) and flash color based on hit intensity
- var r = 0.8 * (1 - hitIntensity) + flashColor[0] * hitIntensity;
- var g = 0.8 * (1 - hitIntensity) + flashColor[1] * hitIntensity;
- var b = 0.8 * (1 - hitIntensity) + flashColor[2] * hitIntensity;
- mgraphics.set_source_rgba(r, g, b, 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 + (-0.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 * -0.0001;
- ball.position[0] += ball.velocity[0];
- ball.position[1] += ball.velocity[1];
- checkEdgeCollisions(ball, i);
- if (Math.abs(ball.position[0]) > 1 || Math.abs(ball.position[1]) > 1) {
- ball.position = [0, 0];
- ball.velocity = [Math.random() * 0.006 - 0.003, Math.random() * 0.006 - 0.003];
- // post("Ball " + i + " escaped - resetting to center\n");
- }
- }
- 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] > config.cooldownTime) {
- // post("Ball " + ballIndex + " hit edge between vertices " + i + " and " + ((i + 1) % config.sides) + "\n");
- outlet(0, ballIndex);
- outlet(1, i);
- outlet(2, ball.position[0]);
- 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.025) {
- var boostFactor = 1.1 + Math.random() * 0.2;
- ball.velocity[0] *= boostFactor;
- ball.velocity[1] *= boostFactor;
- } else {
- ball.velocity[0] *= (1 - 0.2*config.damping);
- ball.velocity[1] *= (1 - 0.2*config.damping);
- }
- }
- }
- }
- }
- function anything() {
- var a = arrayfromargs(messagename, arguments);
- if (a.length < 2) {
- post("Error: Not enough arguments for parameter adjustment\n");
- return;
- }
- var param = a[0];
- var value = parseFloat(a[1]);
- // Helper function to check if a number is an integer
- function isInteger(n) {
- return Math.floor(n) === n;
- }
- switch(param) {
- case "sides":
- if (isInteger(value) && value >= 3) {
- config.sides = value;
- // Reset edge hit times array for new number of sides
- edgeHitTimes = [];
- for (var i = 0; i < config.sides; i++) {
- edgeHitTimes.push(0);
- }
- } else {
- post("Error: sides must be an integer >= 3\n");
- }
- break;
- case "numBalls":
- if (isInteger(value) && value > 0) {
- config.numBalls = value;
- // Adjust number of balls
- while (balls.length > value) {
- balls.pop();
- }
- while (balls.length < value) {
- balls.push(createBall());
- }
- } else {
- post("Error: numBalls must be a positive integer\n");
- }
- break;
- case "gravity":
- config.gravity = value;
- break;
- case "ballSize":
- config.ballSize = value/100;
- bang();
- break;
- case "shapeSize":
- config.shapeSize = value;
- break;
- case "spinspeed":
- config.spinspeed = value;
- break;
- case "cooldownTime":
- config.cooldownTime = value;
- break;
- case "damping":
- config.damping = value;
- break;
- case "getconfig":
- post("Current configuration:\n");
- post("sides: " + config.sides + "\n");
- post("numBalls: " + config.numBalls + "\n");
- post("gravity: " + config.gravity + "\n");
- post("spinspeed: " + config.spinspeed + "\n");
- post("cooldownTime: " + config.cooldownTime + "\n");
- post("damping: " + config.damping + "\n");
- break;
- default:
- post("Unknown parameter: " + param + "\n");
- post("Available parameters: sides, numBalls, gravity, spinspeed, getconfig\n");
- break;
- }
- // Redraw the scene after any parameter change
- mgraphics.redraw();
- }
- function bang() {
- balls = [];
- for (var i = 0; i < config.numBalls; i++) {
- balls.push(createBall());
- }
- collisionCooldowns = {};
- edgeHitTimes = [];
- for (var i = 0; i < config.sides; i++) {
- edgeHitTimes.push(0);
- }
- mgraphics.redraw();
- }
- 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