User prompt
make particules bigger
User prompt
make background is dark black
User prompt
make particules more faster
User prompt
make follow more faster
User prompt
particules are following mouse with like a snake
User prompt
make a better optimization
User prompt
fix the fps problem
User prompt
make all particles same color and color are always changing
User prompt
add it more shapes
User prompt
make particles cant get out of the screen
User prompt
solve the fps problem
User prompt
add more particles and make physics
Code edit (1 edits merged)
Please save this source code
User prompt
Million Particle Swarm
Initial prompt
make a particles game and make it million particles are following mouse and being cool shapes
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Particle class: represents a single particle in the swarm.
var Particle = Container.expand(function () {
var self = Container.call(this);
// Attach the particle asset, centered
var gfx = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
// Particle properties
self.vx = 0;
self.vy = 0;
self.tx = 0; // target x
self.ty = 0; // target y
self.speed = 0.12 + Math.random() * 0.08; // slightly varied speed for organic look
self.color = 0xffffff;
// Assign a random color on creation
function randomColor() {
// Generate a random pastel color
var r = 180 + Math.floor(Math.random() * 75);
var g = 180 + Math.floor(Math.random() * 75);
var b = 180 + Math.floor(Math.random() * 75);
return r << 16 | g << 8 | b;
}
self.color = randomColor();
gfx.tint = self.color;
// Animate color change
self.setColor = function (newColor) {
var startColor = gfx.tint;
tween(gfx, {
tint: newColor
}, {
duration: 800,
easing: tween.cubicOut
});
self.color = newColor;
};
// Update method: move towards target
self.update = function () {
// Move towards target (tx, ty) with some inertia
var dx = self.tx - self.x;
var dy = self.ty - self.y;
self.vx += dx * self.speed * 0.05;
self.vy += dy * self.speed * 0.05;
// --- Simple physics additions ---
// Gravity (downwards)
self.vy += 0.02;
// Repulsion from nearby particles (very basic, only for a few neighbors for perf)
// This is a naive O(N) approach, but we only check a few random neighbors for speed
var repulsionStrength = 0.2;
var neighborCount = 3;
for (var n = 0; n < neighborCount; n++) {
var idx = (self._particleIndex + n * 997) % PARTICLE_COUNT; // pseudo-random neighbor
if (typeof particles !== "undefined" && particles[idx] && particles[idx] !== self) {
var other = particles[idx];
var rx = self.x - other.x;
var ry = self.y - other.y;
var distSq = rx * rx + ry * ry;
if (distSq < 400) {
// Only if very close
var dist = Math.sqrt(distSq) + 0.01;
var force = repulsionStrength / dist;
self.vx += rx / dist * force;
self.vy += ry / dist * force;
}
}
}
// Damping for smoothness
self.vx *= 0.85;
self.vy *= 0.85;
self.x += self.vx;
self.y += self.vy;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181830 // Deep dark blue for contrast
});
/****
* Game Code
****/
// We'll use the tween plugin for smooth color transitions.
// We'll use simple colored ellipses for particles, and a background color for the game.
// Number of particles: balance between performance and visual density
var PARTICLE_COUNT = 10000; // Increased to 10,000 for a denser, more impressive effect
// Particle storage
var particles = [];
// Swarm target position (where particles move towards)
var swarmTarget = {
x: 1024,
y: 1366
}; // Start at center
// Shape morphing: list of shape functions
var shapes = [
// Circle
function (i, N) {
var angle = i / N * Math.PI * 2;
var radius = 600;
return {
x: 1024 + Math.cos(angle) * radius,
y: 1366 + Math.sin(angle) * radius
};
},
// Horizontal wave
function (i, N) {
var x = 300 + i / N * 1448;
var y = 1366 + Math.sin(i / N * Math.PI * 4 + LK.ticks * 0.01) * 400;
return {
x: x,
y: y
};
},
// Heart shape
function (i, N) {
var t = i / N * Math.PI * 2;
var scale = 400;
var x = 1024 + scale * 16 * Math.pow(Math.sin(t), 3);
var y = 1200 - scale * (13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t));
return {
x: x,
y: y
};
},
// Spiral
function (i, N) {
var t = i / N * Math.PI * 8;
var r = 80 + 500 * (i / N);
var x = 1024 + Math.cos(t) * r;
var y = 1366 + Math.sin(t) * r;
return {
x: x,
y: y
};
},
// Random cloud
function (i, N) {
var angle = i / N * Math.PI * 2;
var radius = 400 + Math.sin(LK.ticks * 0.01 + i) * 120 + Math.random() * 40;
return {
x: 1024 + Math.cos(angle) * radius,
y: 1366 + Math.sin(angle) * radius
};
}];
// Current shape index and morph progress
var currentShape = 0;
var nextShape = 1;
var morphProgress = 0; // 0 to 1
// Morph every X seconds
var MORPH_TIME = 240; // frames (4 seconds)
var morphTimer = 0;
// Precompute target positions for shapes
var shapeTargets = [[], []];
// Initialize particles
for (var i = 0; i < PARTICLE_COUNT; i++) {
var p = new Particle();
// Start at random position near center
p.x = 1024 + (Math.random() - 0.5) * 200;
p.y = 1366 + (Math.random() - 0.5) * 200;
p.tx = p.x;
p.ty = p.y;
p._particleIndex = i; // Assign index for neighbor repulsion
particles.push(p);
game.addChild(p);
}
// Function to update shape targets
function updateShapeTargets() {
var N = PARTICLE_COUNT;
for (var s = 0; s < 2; s++) {
var shapeFn = shapes[s === 0 ? currentShape : nextShape];
for (var i = 0; i < N; i++) {
shapeTargets[s][i] = shapeFn(i, N);
}
}
}
updateShapeTargets();
// Touch/mouse handling
var isTouching = false;
var lastTouch = {
x: 1024,
y: 1366
};
// Move handler: update swarm target to touch position
function handleMove(x, y, obj) {
// Clamp to game area
if (x < 0) x = 0;
if (x > 2048) x = 2048;
if (y < 0) y = 0;
if (y > 2732) y = 2732;
swarmTarget.x = x;
swarmTarget.y = y;
lastTouch.x = x;
lastTouch.y = y;
isTouching = true;
}
game.move = handleMove;
// Down handler: start following touch
game.down = function (x, y, obj) {
handleMove(x, y, obj);
isTouching = true;
};
// Up handler: stop following touch, revert to shape morphing
game.up = function (x, y, obj) {
isTouching = false;
};
// Animate color palette on each morph
function morphColors() {
for (var i = 0; i < particles.length; i++) {
var p = particles[i];
// Assign a new random pastel color
var newColor = function () {
var r = 180 + Math.floor(Math.random() * 75);
var g = 180 + Math.floor(Math.random() * 75);
var b = 180 + Math.floor(Math.random() * 75);
return r << 16 | g << 8 | b;
}();
p.setColor(newColor);
}
}
// Main update loop
game.update = function () {
// Shape morphing logic
morphTimer++;
if (morphTimer >= MORPH_TIME) {
morphTimer = 0;
currentShape = nextShape;
nextShape = (nextShape + 1) % shapes.length;
morphProgress = 0;
updateShapeTargets();
morphColors();
}
if (!isTouching) {
morphProgress += 1 / MORPH_TIME;
if (morphProgress > 1) morphProgress = 1;
} else {
morphProgress = 0;
}
// For each particle, set its target
for (var i = 0; i < particles.length; i++) {
var p = particles[i];
if (isTouching) {
// Swarm follows finger/touch, with some spread
var angle = i / particles.length * Math.PI * 2;
var spread = 80 + Math.sin(LK.ticks * 0.01 + i) * 30;
p.tx = swarmTarget.x + Math.cos(angle) * spread;
p.ty = swarmTarget.y + Math.sin(angle) * spread;
} else {
// Morph between shapes
var t0 = shapeTargets[0][i];
var t1 = shapeTargets[1][i];
var t = morphProgress;
p.tx = t0.x * (1 - t) + t1.x * t;
p.ty = t0.y * (1 - t) + t1.y * t;
}
p.update();
}
};
// No GUI or score, as this is a pure interactive art experience. ===================================================================
--- original.js
+++ change.js
@@ -48,8 +48,31 @@
var dx = self.tx - self.x;
var dy = self.ty - self.y;
self.vx += dx * self.speed * 0.05;
self.vy += dy * self.speed * 0.05;
+ // --- Simple physics additions ---
+ // Gravity (downwards)
+ self.vy += 0.02;
+ // Repulsion from nearby particles (very basic, only for a few neighbors for perf)
+ // This is a naive O(N) approach, but we only check a few random neighbors for speed
+ var repulsionStrength = 0.2;
+ var neighborCount = 3;
+ for (var n = 0; n < neighborCount; n++) {
+ var idx = (self._particleIndex + n * 997) % PARTICLE_COUNT; // pseudo-random neighbor
+ if (typeof particles !== "undefined" && particles[idx] && particles[idx] !== self) {
+ var other = particles[idx];
+ var rx = self.x - other.x;
+ var ry = self.y - other.y;
+ var distSq = rx * rx + ry * ry;
+ if (distSq < 400) {
+ // Only if very close
+ var dist = Math.sqrt(distSq) + 0.01;
+ var force = repulsionStrength / dist;
+ self.vx += rx / dist * force;
+ self.vy += ry / dist * force;
+ }
+ }
+ }
// Damping for smoothness
self.vx *= 0.85;
self.vy *= 0.85;
self.x += self.vx;
@@ -70,9 +93,9 @@
****/
// We'll use the tween plugin for smooth color transitions.
// We'll use simple colored ellipses for particles, and a background color for the game.
// Number of particles: balance between performance and visual density
-var PARTICLE_COUNT = 1200; // For MVP, 1200 is performant and visually rich
+var PARTICLE_COUNT = 10000; // Increased to 10,000 for a denser, more impressive effect
// Particle storage
var particles = [];
// Swarm target position (where particles move towards)
var swarmTarget = {
@@ -146,8 +169,9 @@
p.x = 1024 + (Math.random() - 0.5) * 200;
p.y = 1366 + (Math.random() - 0.5) * 200;
p.tx = p.x;
p.ty = p.y;
+ p._particleIndex = i; // Assign index for neighbor repulsion
particles.push(p);
game.addChild(p);
}
// Function to update shape targets