User prompt
Add borders to make the balls follow a path the ro gates
User prompt
Make division max 2 and make multiply max 5
User prompt
Every restart gates should randomized both in position and modifiers
User prompt
Add more variety modifiers to the gates
User prompt
If two gates crashes with each other, make the go opposite directions
User prompt
Make the balls go slower and balls can spread after passing the gate
User prompt
On side of the gates, add physical borders
User prompt
Make the bottom gate as wide as the screen
User prompt
Add more gates
User prompt
Make the gates move side to side but they shouldnt overlap with each other
User prompt
Gates shouldnt collide with each other
User prompt
Make the balls go slower and gates can move side to side, add physical borders to the gates. The collecter cup needs to be as big as the screen from side to side
User prompt
Make the gates side by side and add more gates
User prompt
Gates needs to be bigger and the collective cups needs to have a border
User prompt
The gates needs to be positioned randomly
User prompt
As the balls multiply, show it in real time
Code edit (1 edits merged)
Please save this source code
User prompt
Cup Drop Multiplier
Initial prompt
I have cup in my hand and I empty the cup from top of the screen, Balls should be exiting from that cup in flow. I can select where I can empty the cup from top of the screen. As the balls are going down, they are passing from gates that multiplies or divides the number of the balls. At the bottom of the screen make another cup that collects the balls afterwards. Count all the balls
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Ball class var Ball = Container.expand(function () { var self = Container.call(this); var ballGfx = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); self.radius = ballGfx.width / 2; self.vx = 0; self.vy = 0; self.active = true; self.update = function () { if (!self.active) return; // Simple gravity self.vy += 1.2; self.x += self.vx; self.y += self.vy; }; // Used to mark as collected or destroyed self.deactivate = function () { self.active = false; }; return self; }); // Bottom cup class (collector) var CupBottom = Container.expand(function () { var self = Container.call(this); var cupGfx = self.attachAsset('cupBottom', { anchorX: 0.5, anchorY: 0.5 }); self.width = cupGfx.width; self.height = cupGfx.height; return self; }); // Top cup class (movable) var CupTop = Container.expand(function () { var self = Container.call(this); var cupGfx = self.attachAsset('cupTop', { anchorX: 0.5, anchorY: 0.5 }); self.width = cupGfx.width; self.height = cupGfx.height; return self; }); // Gate class (multiplier or divider) var Gate = Container.expand(function () { var self = Container.call(this); self.type = 'mult'; // 'mult' or 'div' self.value = 2; // e.g. 2x or /2 self.width = 180; self.height = 40; self.gfx = null; self.label = null; self.init = function (type, value) { self.type = type; self.value = value; if (type === 'mult') { self.gfx = self.attachAsset('gateMult', { anchorX: 0.5, anchorY: 0.5 }); } else { self.gfx = self.attachAsset('gateDiv', { anchorX: 0.5, anchorY: 0.5 }); } var txt = ''; if (type === 'mult') { txt = 'x' + value; } else { txt = '÷' + value; } self.label = new Text2(txt, { size: 60, fill: 0xFFFFFF }); self.label.anchor.set(0.5, 0.5); self.addChild(self.label); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222b3a }); /**** * Game Code ****/ // Divider gate // Multiplier gate // Ball // Bottom cup (where balls are collected) // Top cup (where balls are dropped from) // Game constants var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var BALL_DROP_COUNT = 10; var BALL_DROP_INTERVAL = 8; // frames between balls var GATE_CONFIGS = [{ type: 'mult', value: 2, y: 900 }, { type: 'div', value: 2, y: 1400 }, { type: 'mult', value: 3, y: 1900 }]; // Game state var cupTop, cupBottom; var balls = []; var gates = []; var dropping = false; var dropTimer = 0; var ballsToDrop = 0; var scoreTxt, infoTxt; var collectedCount = 0; var gatePassed = {}; // ball.id -> {gateIndex: true} var ballIdCounter = 0; var dragNode = null; // Create top cup cupTop = new CupTop(); cupTop.x = GAME_WIDTH / 2; cupTop.y = 250; game.addChild(cupTop); // Create bottom cup cupBottom = new CupBottom(); cupBottom.x = GAME_WIDTH / 2; cupBottom.y = GAME_HEIGHT - 180; game.addChild(cupBottom); // Create gates for (var i = 0; i < GATE_CONFIGS.length; i++) { var g = new Gate(); g.init(GATE_CONFIGS[i].type, GATE_CONFIGS[i].value); g.x = GAME_WIDTH / 2; g.y = GATE_CONFIGS[i].y; game.addChild(g); gates.push(g); } // Score text (balls collected) scoreTxt = new Text2('Balls: 0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Info text (instructions) infoTxt = new Text2('Drag cup & tap to drop balls!', { size: 60, fill: 0xFFFFFF }); infoTxt.anchor.set(0.5, 0); LK.gui.top.addChild(infoTxt); // Position GUI elements scoreTxt.y = 120; infoTxt.y = 260; // Helper: spawn a single ball at cupTop function spawnBall(x, y, vx, vy) { var b = new Ball(); b.x = x; b.y = y; b.vx = vx || 0; b.vy = vy || 0; b.id = ++ballIdCounter; balls.push(b); game.addChild(b); gatePassed[b.id] = {}; return b; } // Start dropping balls function startDrop() { if (dropping) return; dropping = true; ballsToDrop = BALL_DROP_COUNT; dropTimer = 0; infoTxt.setText('Balls dropping...'); } // Handle drag/move of cup function handleMove(x, y, obj) { if (dragNode) { // Clamp cup within screen, avoid top left 100x100 var minX = 150 + dragNode.width / 2; var maxX = GAME_WIDTH - dragNode.width / 2 - 50; dragNode.x = Math.max(minX, Math.min(maxX, x)); } } // Touch/drag events game.down = function (x, y, obj) { // If touch is on cupTop, start drag var local = cupTop.toLocal(game.toGlobal({ x: x, y: y })); if (local.x > -cupTop.width / 2 && local.x < cupTop.width / 2 && local.y > -cupTop.height / 2 && local.y < cupTop.height / 2) { dragNode = cupTop; } }; game.move = function (x, y, obj) { handleMove(x, y, obj); }; game.up = function (x, y, obj) { dragNode = null; // If not dragging, and not dropping, start drop on tap if (!dropping) { startDrop(); } }; // Main update loop game.update = function () { // Handle dropping balls if (dropping && ballsToDrop > 0) { dropTimer--; if (dropTimer <= 0) { // Drop a ball from cupTop center, with small random vx var vx = (Math.random() - 0.5) * 6; var b = spawnBall(cupTop.x, cupTop.y + cupTop.height / 2 + 10, vx, 0); ballsToDrop--; dropTimer = BALL_DROP_INTERVAL; } } // Update balls for (var i = balls.length - 1; i >= 0; i--) { var b = balls[i]; b.update(); // Check for gate collisions for (var gidx = 0; gidx < gates.length; gidx++) { var g = gates[gidx]; // Only process if not already passed if (!gatePassed[b.id][gidx]) { // Simple AABB collision if (b.x + b.radius > g.x - g.width / 2 && b.x - b.radius < g.x + g.width / 2 && b.y + b.radius > g.y - g.height / 2 && b.y - b.radius < g.y + g.height / 2) { // Mark as passed gatePassed[b.id][gidx] = true; // Apply gate effect if (g.type === 'mult') { // Multiply: spawn (value-1) new balls at same position for (var m = 1; m < g.value; m++) { var nb = spawnBall(b.x, b.y, (Math.random() - 0.5) * 8, b.vy * 0.7); // Copy gatePassed so new balls don't re-trigger previous gates for (var k in gatePassed[b.id]) { gatePassed[nb.id][k] = true; } } } else if (g.type === 'div') { // Divide: only keep 1/value balls, remove others // Remove this ball if Math.random() > 1/value if (Math.random() > 1 / g.value) { b.deactivate(); } } } } } // Remove deactivated balls if (!b.active) { b.destroy(); balls.splice(i, 1); continue; } // Check for collection in bottom cup if (b.y + b.radius > cupBottom.y - cupBottom.height / 2 && b.x > cupBottom.x - cupBottom.width / 2 && b.x < cupBottom.x + cupBottom.width / 2 && b.y < cupBottom.y + cupBottom.height / 2) { // Collected! collectedCount++; scoreTxt.setText('Balls: ' + collectedCount); b.deactivate(); b.destroy(); balls.splice(i, 1); continue; } // Remove balls that fall off screen if (b.y - b.radius > GAME_HEIGHT + 100) { b.deactivate(); b.destroy(); balls.splice(i, 1); continue; } } // End condition: all balls dropped and none left in play if (dropping && ballsToDrop === 0 && balls.length === 0) { dropping = false; infoTxt.setText('Final: ' + collectedCount + ' balls!\nTap to play again'); // Show game over (will reset game) LK.setScore(collectedCount); LK.showGameOver(); } }; // Reset state on game restart game.on('reset', function () { // Remove all balls for (var i = 0; i < balls.length; i++) { balls[i].destroy(); } balls = []; gatePassed = {}; ballIdCounter = 0; collectedCount = 0; dropping = false; ballsToDrop = 0; dropTimer = 0; scoreTxt.setText('Balls: 0'); infoTxt.setText('Drag cup & tap to drop balls!'); // Reset cup positions cupTop.x = GAME_WIDTH / 2; cupTop.y = 250; cupBottom.x = GAME_WIDTH / 2; cupBottom.y = GAME_HEIGHT - 180; });
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,325 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Ball class
+var Ball = Container.expand(function () {
+ var self = Container.call(this);
+ var ballGfx = self.attachAsset('ball', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = ballGfx.width / 2;
+ self.vx = 0;
+ self.vy = 0;
+ self.active = true;
+ self.update = function () {
+ if (!self.active) return;
+ // Simple gravity
+ self.vy += 1.2;
+ self.x += self.vx;
+ self.y += self.vy;
+ };
+ // Used to mark as collected or destroyed
+ self.deactivate = function () {
+ self.active = false;
+ };
+ return self;
+});
+// Bottom cup class (collector)
+var CupBottom = Container.expand(function () {
+ var self = Container.call(this);
+ var cupGfx = self.attachAsset('cupBottom', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = cupGfx.width;
+ self.height = cupGfx.height;
+ return self;
+});
+// Top cup class (movable)
+var CupTop = Container.expand(function () {
+ var self = Container.call(this);
+ var cupGfx = self.attachAsset('cupTop', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = cupGfx.width;
+ self.height = cupGfx.height;
+ return self;
+});
+// Gate class (multiplier or divider)
+var Gate = Container.expand(function () {
+ var self = Container.call(this);
+ self.type = 'mult'; // 'mult' or 'div'
+ self.value = 2; // e.g. 2x or /2
+ self.width = 180;
+ self.height = 40;
+ self.gfx = null;
+ self.label = null;
+ self.init = function (type, value) {
+ self.type = type;
+ self.value = value;
+ if (type === 'mult') {
+ self.gfx = self.attachAsset('gateMult', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ } else {
+ self.gfx = self.attachAsset('gateDiv', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ }
+ var txt = '';
+ if (type === 'mult') {
+ txt = 'x' + value;
+ } else {
+ txt = '÷' + value;
+ }
+ self.label = new Text2(txt, {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ self.label.anchor.set(0.5, 0.5);
+ self.addChild(self.label);
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
+ backgroundColor: 0x222b3a
+});
+
+/****
+* Game Code
+****/
+// Divider gate
+// Multiplier gate
+// Ball
+// Bottom cup (where balls are collected)
+// Top cup (where balls are dropped from)
+// Game constants
+var GAME_WIDTH = 2048;
+var GAME_HEIGHT = 2732;
+var BALL_DROP_COUNT = 10;
+var BALL_DROP_INTERVAL = 8; // frames between balls
+var GATE_CONFIGS = [{
+ type: 'mult',
+ value: 2,
+ y: 900
+}, {
+ type: 'div',
+ value: 2,
+ y: 1400
+}, {
+ type: 'mult',
+ value: 3,
+ y: 1900
+}];
+// Game state
+var cupTop, cupBottom;
+var balls = [];
+var gates = [];
+var dropping = false;
+var dropTimer = 0;
+var ballsToDrop = 0;
+var scoreTxt, infoTxt;
+var collectedCount = 0;
+var gatePassed = {}; // ball.id -> {gateIndex: true}
+var ballIdCounter = 0;
+var dragNode = null;
+// Create top cup
+cupTop = new CupTop();
+cupTop.x = GAME_WIDTH / 2;
+cupTop.y = 250;
+game.addChild(cupTop);
+// Create bottom cup
+cupBottom = new CupBottom();
+cupBottom.x = GAME_WIDTH / 2;
+cupBottom.y = GAME_HEIGHT - 180;
+game.addChild(cupBottom);
+// Create gates
+for (var i = 0; i < GATE_CONFIGS.length; i++) {
+ var g = new Gate();
+ g.init(GATE_CONFIGS[i].type, GATE_CONFIGS[i].value);
+ g.x = GAME_WIDTH / 2;
+ g.y = GATE_CONFIGS[i].y;
+ game.addChild(g);
+ gates.push(g);
+}
+// Score text (balls collected)
+scoreTxt = new Text2('Balls: 0', {
+ size: 120,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Info text (instructions)
+infoTxt = new Text2('Drag cup & tap to drop balls!', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+infoTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(infoTxt);
+// Position GUI elements
+scoreTxt.y = 120;
+infoTxt.y = 260;
+// Helper: spawn a single ball at cupTop
+function spawnBall(x, y, vx, vy) {
+ var b = new Ball();
+ b.x = x;
+ b.y = y;
+ b.vx = vx || 0;
+ b.vy = vy || 0;
+ b.id = ++ballIdCounter;
+ balls.push(b);
+ game.addChild(b);
+ gatePassed[b.id] = {};
+ return b;
+}
+// Start dropping balls
+function startDrop() {
+ if (dropping) return;
+ dropping = true;
+ ballsToDrop = BALL_DROP_COUNT;
+ dropTimer = 0;
+ infoTxt.setText('Balls dropping...');
+}
+// Handle drag/move of cup
+function handleMove(x, y, obj) {
+ if (dragNode) {
+ // Clamp cup within screen, avoid top left 100x100
+ var minX = 150 + dragNode.width / 2;
+ var maxX = GAME_WIDTH - dragNode.width / 2 - 50;
+ dragNode.x = Math.max(minX, Math.min(maxX, x));
+ }
+}
+// Touch/drag events
+game.down = function (x, y, obj) {
+ // If touch is on cupTop, start drag
+ var local = cupTop.toLocal(game.toGlobal({
+ x: x,
+ y: y
+ }));
+ if (local.x > -cupTop.width / 2 && local.x < cupTop.width / 2 && local.y > -cupTop.height / 2 && local.y < cupTop.height / 2) {
+ dragNode = cupTop;
+ }
+};
+game.move = function (x, y, obj) {
+ handleMove(x, y, obj);
+};
+game.up = function (x, y, obj) {
+ dragNode = null;
+ // If not dragging, and not dropping, start drop on tap
+ if (!dropping) {
+ startDrop();
+ }
+};
+// Main update loop
+game.update = function () {
+ // Handle dropping balls
+ if (dropping && ballsToDrop > 0) {
+ dropTimer--;
+ if (dropTimer <= 0) {
+ // Drop a ball from cupTop center, with small random vx
+ var vx = (Math.random() - 0.5) * 6;
+ var b = spawnBall(cupTop.x, cupTop.y + cupTop.height / 2 + 10, vx, 0);
+ ballsToDrop--;
+ dropTimer = BALL_DROP_INTERVAL;
+ }
+ }
+ // Update balls
+ for (var i = balls.length - 1; i >= 0; i--) {
+ var b = balls[i];
+ b.update();
+ // Check for gate collisions
+ for (var gidx = 0; gidx < gates.length; gidx++) {
+ var g = gates[gidx];
+ // Only process if not already passed
+ if (!gatePassed[b.id][gidx]) {
+ // Simple AABB collision
+ if (b.x + b.radius > g.x - g.width / 2 && b.x - b.radius < g.x + g.width / 2 && b.y + b.radius > g.y - g.height / 2 && b.y - b.radius < g.y + g.height / 2) {
+ // Mark as passed
+ gatePassed[b.id][gidx] = true;
+ // Apply gate effect
+ if (g.type === 'mult') {
+ // Multiply: spawn (value-1) new balls at same position
+ for (var m = 1; m < g.value; m++) {
+ var nb = spawnBall(b.x, b.y, (Math.random() - 0.5) * 8, b.vy * 0.7);
+ // Copy gatePassed so new balls don't re-trigger previous gates
+ for (var k in gatePassed[b.id]) {
+ gatePassed[nb.id][k] = true;
+ }
+ }
+ } else if (g.type === 'div') {
+ // Divide: only keep 1/value balls, remove others
+ // Remove this ball if Math.random() > 1/value
+ if (Math.random() > 1 / g.value) {
+ b.deactivate();
+ }
+ }
+ }
+ }
+ }
+ // Remove deactivated balls
+ if (!b.active) {
+ b.destroy();
+ balls.splice(i, 1);
+ continue;
+ }
+ // Check for collection in bottom cup
+ if (b.y + b.radius > cupBottom.y - cupBottom.height / 2 && b.x > cupBottom.x - cupBottom.width / 2 && b.x < cupBottom.x + cupBottom.width / 2 && b.y < cupBottom.y + cupBottom.height / 2) {
+ // Collected!
+ collectedCount++;
+ scoreTxt.setText('Balls: ' + collectedCount);
+ b.deactivate();
+ b.destroy();
+ balls.splice(i, 1);
+ continue;
+ }
+ // Remove balls that fall off screen
+ if (b.y - b.radius > GAME_HEIGHT + 100) {
+ b.deactivate();
+ b.destroy();
+ balls.splice(i, 1);
+ continue;
+ }
+ }
+ // End condition: all balls dropped and none left in play
+ if (dropping && ballsToDrop === 0 && balls.length === 0) {
+ dropping = false;
+ infoTxt.setText('Final: ' + collectedCount + ' balls!\nTap to play again');
+ // Show game over (will reset game)
+ LK.setScore(collectedCount);
+ LK.showGameOver();
+ }
+};
+// Reset state on game restart
+game.on('reset', function () {
+ // Remove all balls
+ for (var i = 0; i < balls.length; i++) {
+ balls[i].destroy();
+ }
+ balls = [];
+ gatePassed = {};
+ ballIdCounter = 0;
+ collectedCount = 0;
+ dropping = false;
+ ballsToDrop = 0;
+ dropTimer = 0;
+ scoreTxt.setText('Balls: 0');
+ infoTxt.setText('Drag cup & tap to drop balls!');
+ // Reset cup positions
+ cupTop.x = GAME_WIDTH / 2;
+ cupTop.y = 250;
+ cupBottom.x = GAME_WIDTH / 2;
+ cupBottom.y = GAME_HEIGHT - 180;
});
\ No newline at end of file