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 += 0.45; // slower gravity 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; // Add border using a slightly larger box behind var border = self.attachAsset('cupBottom', { anchorX: 0.5, anchorY: 0.5, width: cupGfx.width + 16, height: cupGfx.height + 16, color: 0x222222 }); self.setChildIndex(border, 0); 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; // Add border using a slightly larger box behind var border = self.attachAsset('cupTop', { anchorX: 0.5, anchorY: 0.5, width: cupGfx.width + 12, height: cupGfx.height + 12, color: 0x222222 }); self.setChildIndex(border, 0); 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; // Add border behind gate var borderColor = 0x111111; var borderAsset = self.attachAsset(type === 'mult' ? 'gateMult' : 'gateDiv', { anchorX: 0.5, anchorY: 0.5, width: 370, height: 120, color: borderColor }); // Place border at back self.setChildIndex(borderAsset, 0); 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); // For moving gates self.moveDir = Math.random() < 0.5 ? 1 : -1; self.moveSpeed = 2 + Math.random() * 1.5; self.moveRange = 220 + Math.random() * 80; self.baseX = self.x; self.t = Math.random() * 1000; }; // Move gates side to side self.update = function () { if (typeof self.baseX !== "number") return; self.t += self.moveSpeed; self.x = self.baseX + Math.sin(self.t / 120) * self.moveRange; }; 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 // Gates are now arranged in rows, each row has multiple gates side by side var GATE_ROW_COUNT = 3; var GATES_PER_ROW = 4; var GATE_MIN_Y = 700; var GATE_MAX_Y = GAME_HEIGHT - 600; var GATE_ROW_SPACING = (GATE_MAX_Y - GATE_MIN_Y) / (GATE_ROW_COUNT - 1); var GATE_TYPES = [{ type: 'mult', values: [2, 3] }, { type: 'div', values: [2, 3] }]; var GATE_CONFIGS = []; for (var row = 0; row < GATE_ROW_COUNT; row++) { var y = GATE_MIN_Y + row * GATE_ROW_SPACING; var rowGates = []; for (var col = 0; col < GATES_PER_ROW; col++) { // Alternate or randomize type and value var typeIdx = Math.floor(Math.random() * GATE_TYPES.length); var typeObj = GATE_TYPES[typeIdx]; var value = typeObj.values[Math.floor(Math.random() * typeObj.values.length)]; // Calculate x position for side by side layout var gateWidth = 350; var totalWidth = GATES_PER_ROW * gateWidth + (GATES_PER_ROW - 1) * 40; var startX = (GAME_WIDTH - totalWidth) / 2 + gateWidth / 2; var x = startX + col * (gateWidth + 40); rowGates.push({ type: typeObj.type, value: value, x: x, y: y }); } GATE_CONFIGS.push(rowGates); } // 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(); // Make the collector cup as wide as the screen cupBottom.width = GAME_WIDTH; cupBottom.height = 120; if (cupBottom.children && cupBottom.children.length > 0) { // Adjust graphics and border for (var i = 0; i < cupBottom.children.length; i++) { if (cupBottom.children[i].width) cupBottom.children[i].width = GAME_WIDTH; if (cupBottom.children[i].height) cupBottom.children[i].height = 120; } } cupBottom.x = GAME_WIDTH / 2; cupBottom.y = GAME_HEIGHT - 180; game.addChild(cupBottom); // Create gates (side by side in rows) for (var row = 0; row < GATE_CONFIGS.length; row++) { for (var col = 0; col < GATE_CONFIGS[row].length; col++) { var conf = GATE_CONFIGS[row][col]; var g = new Gate(); g.init(conf.type, conf.value); g.x = conf.x; g.y = conf.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 gates (for movement) for (var gidx = 0; gidx < gates.length; gidx++) { if (typeof gates[gidx].update === "function") { gates[gidx].update(); } } // Update balls // Show current number of balls in play (real time, not just collected) scoreTxt.setText('Balls: ' + (collectedCount + balls.length)); 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; // At end, show only collected balls as final score scoreTxt.setText('Balls: ' + collectedCount); 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
@@ -19,9 +19,9 @@
self.active = true;
self.update = function () {
if (!self.active) return;
// Simple gravity
- self.vy += 1.2;
+ self.vy += 0.45; // slower gravity
self.x += self.vx;
self.y += self.vy;
};
// Used to mark as collected or destroyed
@@ -81,8 +81,19 @@
self.label = null;
self.init = function (type, value) {
self.type = type;
self.value = value;
+ // Add border behind gate
+ var borderColor = 0x111111;
+ var borderAsset = self.attachAsset(type === 'mult' ? 'gateMult' : 'gateDiv', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: 370,
+ height: 120,
+ color: borderColor
+ });
+ // Place border at back
+ self.setChildIndex(borderAsset, 0);
if (type === 'mult') {
self.gfx = self.attachAsset('gateMult', {
anchorX: 0.5,
anchorY: 0.5
@@ -104,9 +115,21 @@
fill: 0xFFFFFF
});
self.label.anchor.set(0.5, 0.5);
self.addChild(self.label);
+ // For moving gates
+ self.moveDir = Math.random() < 0.5 ? 1 : -1;
+ self.moveSpeed = 2 + Math.random() * 1.5;
+ self.moveRange = 220 + Math.random() * 80;
+ self.baseX = self.x;
+ self.t = Math.random() * 1000;
};
+ // Move gates side to side
+ self.update = function () {
+ if (typeof self.baseX !== "number") return;
+ self.t += self.moveSpeed;
+ self.x = self.baseX + Math.sin(self.t / 120) * self.moveRange;
+ };
return self;
});
/****
@@ -183,8 +206,18 @@
cupTop.y = 250;
game.addChild(cupTop);
// Create bottom cup
cupBottom = new CupBottom();
+// Make the collector cup as wide as the screen
+cupBottom.width = GAME_WIDTH;
+cupBottom.height = 120;
+if (cupBottom.children && cupBottom.children.length > 0) {
+ // Adjust graphics and border
+ for (var i = 0; i < cupBottom.children.length; i++) {
+ if (cupBottom.children[i].width) cupBottom.children[i].width = GAME_WIDTH;
+ if (cupBottom.children[i].height) cupBottom.children[i].height = 120;
+ }
+}
cupBottom.x = GAME_WIDTH / 2;
cupBottom.y = GAME_HEIGHT - 180;
game.addChild(cupBottom);
// Create gates (side by side in rows)
@@ -279,8 +312,14 @@
ballsToDrop--;
dropTimer = BALL_DROP_INTERVAL;
}
}
+ // Update gates (for movement)
+ for (var gidx = 0; gidx < gates.length; gidx++) {
+ if (typeof gates[gidx].update === "function") {
+ gates[gidx].update();
+ }
+ }
// Update balls
// Show current number of balls in play (real time, not just collected)
scoreTxt.setText('Balls: ' + (collectedCount + balls.length));
for (var i = balls.length - 1; i >= 0; i--) {