User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded' in or related to this line: 'return {' Line Number: 199
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Ball class: bounces, shrinks on hit, rebounds off everything
var Ball = Container.expand(function () {
var self = Container.call(this);
// Ball type: 'red' or 'green'
self.type = 'red';
self.radius = 90; // initial radius
self.minRadius = 40; // minimum radius after shrinking
self.shrinkAmount = 18; // how much to shrink per hit
// Attach asset
self.asset = null;
self.setType = function (type) {
self.type = type;
if (self.asset) self.removeChild(self.asset);
var assetId = type === 'red' ? 'ballRed' : 'ballGreen';
self.asset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5,
width: self.radius * 2,
height: self.radius * 2
});
};
// Set initial type
self.setType(self.type);
// Physics
self.vx = 0;
self.vy = 0;
self.bounce = 0.98; // energy loss on bounce
self.gravity = 1.2;
// For collision detection
self.getRadius = function () {
return self.radius;
};
// Shrink ball
self.shrink = function () {
if (self.radius > self.minRadius) {
self.radius -= self.shrinkAmount;
if (self.radius < self.minRadius) self.radius = self.minRadius;
// Animate shrink
tween(self.asset, {
width: self.radius * 2,
height: self.radius * 2
}, {
duration: 180,
easing: tween.easeOut
});
}
};
// Update per frame
self.update = function () {
// Move
self.x += self.vx;
self.y += self.vy;
// Gravity
self.vy += self.gravity;
// Bounce off walls
if (self.x - self.radius < 0) {
self.x = self.radius;
self.vx = -self.vx * self.bounce;
}
if (self.x + self.radius > 2048) {
self.x = 2048 - self.radius;
self.vx = -self.vx * self.bounce;
}
// Bounce off floor/ceiling
if (self.y - self.radius < 0) {
self.y = self.radius;
self.vy = -self.vy * self.bounce;
}
if (self.y + self.radius > 2732) {
self.y = 2732 - self.radius;
self.vy = -self.vy * self.bounce;
}
};
return self;
});
// Chain class: fires in direction, stops at collision or edge
var Chain = Container.expand(function () {
var self = Container.call(this);
// Chain is a series of segments
self.segments = [];
self.segmentLength = 64;
self.maxSegments = 32;
self.dirX = 0;
self.dirY = 0;
self.originX = 0;
self.originY = 0;
self.active = true;
// For collision
self.getTip = function () {
if (self.segments.length === 0) return {
x: self.originX,
y: self.originY
};
var last = self.segments[self.segments.length - 1];
return {
x: last.x,
y: last.y
};
};
// Initialize chain
self.fire = function (originX, originY, dirX, dirY) {
self.originX = originX;
self.originY = originY;
self.dirX = dirX;
self.dirY = dirY;
self.segments = [];
self.active = true;
// Remove old children
while (self.children.length) self.removeChild(self.children[0]);
// Add first segment
var seg = LK.getAsset('chain', {
anchorX: 0.5,
anchorY: 0.5
});
seg.x = originX;
seg.y = originY;
self.addChild(seg);
self.segments.push(seg);
};
// Update per frame
self.update = function () {
if (!self.active) return;
// Add new segment in direction
var last = self.segments[self.segments.length - 1];
var nx = last.x + self.dirX * self.segmentLength;
var ny = last.y + self.dirY * self.segmentLength;
// Stop if out of bounds
if (nx < 0 || nx > 2048 || ny < 0 || ny > 2732) {
self.active = false;
return;
}
// Add new segment
var seg = LK.getAsset('chain', {
anchorX: 0.5,
anchorY: 0.5
});
seg.x = nx;
seg.y = ny;
self.addChild(seg);
self.segments.push(seg);
// Limit length
if (self.segments.length > self.maxSegments) {
self.active = false;
}
};
// Remove all segments
self.clear = function () {
while (self.children.length) self.removeChild(self.children[0]);
self.segments = [];
self.active = false;
};
return self;
});
// Robot class: moves left/right, fires chain
var Robot = Container.expand(function () {
var self = Container.call(this);
self.asset = self.attachAsset('robot', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = self.asset.width;
self.height = self.asset.height;
// For movement
self.speed = 0;
self.maxSpeed = 32;
self.targetX = 1024;
// For collision
self.getBounds = function () {
// Return the bounding box of the robot based on its current position and size
return {
left: self.x - self.width / 2,
right: self.x + self.width / 2,
top: self.y - self.height / 2,
bottom: self.y + self.height / 2
};
};
// Update per frame
self.update = function () {
// Move towards targetX
var dx = self.targetX - self.x;
if (Math.abs(dx) > 8) {
self.speed = Math.max(-self.maxSpeed, Math.min(self.maxSpeed, dx * 0.25));
self.x += self.speed;
} else {
self.x = self.targetX;
self.speed = 0;
}
// Clamp to screen
if (self.x < self.width / 2) self.x = self.width / 2;
if (self.x > 2048 - self.width / 2) self.x = 2048 - self.width / 2;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// Aiming line: white box (thin, will be scaled)
// Chain: yellow box (thin)
// Ball: green
// Ball: red
// Robot: blue box
// --- Game variables ---
var robot = new Robot();
var balls = [];
var chain = new Chain();
var aimLine = null;
var isAiming = false;
var aimStart = {
x: 0,
y: 0
};
var aimEnd = {
x: 0,
y: 0
};
var canFire = true;
var fireCooldown = 18; // frames between shots
var fireTimer = 0;
var score = 0;
var scoreTxt = null;
// --- Add robot ---
robot.x = 1024;
robot.y = 2732 - 120;
game.addChild(robot);
// --- Add balls ---
var ball1 = new Ball();
ball1.setType('red');
ball1.radius = 90;
ball1.asset.width = ball1.radius * 2;
ball1.asset.height = ball1.radius * 2;
ball1.x = 600;
ball1.y = 800;
ball1.vx = 18;
ball1.vy = -22;
balls.push(ball1);
game.addChild(ball1);
var ball2 = new Ball();
ball2.setType('green');
ball2.radius = 90;
ball2.asset.width = ball2.radius * 2;
ball2.asset.height = ball2.radius * 2;
ball2.x = 1448;
ball2.y = 900;
ball2.vx = -16;
ball2.vy = -18;
balls.push(ball2);
game.addChild(ball2);
// --- Add chain (hidden at start) ---
game.addChild(chain);
// --- Score text ---
scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// --- Aiming line ---
function updateAimLine() {
if (!aimLine) {
aimLine = LK.getAsset('aimLine', {
anchorX: 0,
anchorY: 0.5
});
aimLine.alpha = 0.5;
game.addChild(aimLine);
}
var dx = aimEnd.x - aimStart.x;
var dy = aimEnd.y - aimStart.y;
var len = Math.sqrt(dx * dx + dy * dy);
if (len < 80) len = 80; // minimum length
aimLine.x = aimStart.x;
aimLine.y = aimStart.y;
aimLine.width = len;
aimLine.height = 16;
aimLine.rotation = Math.atan2(dy, dx);
aimLine.visible = true;
}
function hideAimLine() {
if (aimLine) aimLine.visible = false;
}
// --- Input handling ---
game.down = function (x, y, obj) {
// Only allow aiming if touch is in lower 1/3 of screen
if (y > 2732 - 600) {
isAiming = true;
aimStart.x = robot.x;
aimStart.y = robot.y - robot.height / 2;
aimEnd.x = x;
aimEnd.y = y;
updateAimLine();
}
};
game.move = function (x, y, obj) {
if (isAiming) {
// Update aim direction
aimEnd.x = x;
aimEnd.y = y;
updateAimLine();
} else {
// Move robot left/right only
robot.targetX = x;
}
};
game.up = function (x, y, obj) {
if (isAiming && canFire) {
// Fire chain in direction
var dx = aimEnd.x - aimStart.x;
var dy = aimEnd.y - aimStart.y;
var len = Math.sqrt(dx * dx + dy * dy);
if (len > 80) {
var dirX = dx / len;
var dirY = dy / len;
chain.clear();
chain.fire(aimStart.x, aimStart.y, dirX, dirY);
canFire = false;
fireTimer = fireCooldown;
}
}
isAiming = false;
hideAimLine();
};
// --- Ball-ball collision ---
function ballsCollide(b1, b2) {
var dx = b1.x - b2.x;
var dy = b1.y - b2.y;
var dist = Math.sqrt(dx * dx + dy * dy);
return dist < b1.radius + b2.radius;
}
function resolveBallCollision(b1, b2) {
var dx = b1.x - b2.x;
var dy = b1.y - b2.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist === 0) return;
var overlap = b1.radius + b2.radius - dist;
if (overlap > 0) {
// Push balls apart
var nx = dx / dist;
var ny = dy / dist;
b1.x += nx * (overlap / 2);
b1.y += ny * (overlap / 2);
b2.x -= nx * (overlap / 2);
b2.y -= ny * (overlap / 2);
// Exchange velocities (elastic)
var tx = nx;
var ty = ny;
var v1 = b1.vx * tx + b1.vy * ty;
var v2 = b2.vx * tx + b2.vy * ty;
var m1 = b1.radius;
var m2 = b2.radius;
var newV1 = (v1 * (m1 - m2) + 2 * m2 * v2) / (m1 + m2);
var newV2 = (v2 * (m2 - m1) + 2 * m1 * v1) / (m1 + m2);
b1.vx += (newV1 - v1) * tx;
b1.vy += (newV1 - v1) * ty;
b2.vx += (newV2 - v2) * tx;
b2.vy += (newV2 - v2) * ty;
}
}
// --- Ball-robot collision ---
function ballHitsRobot(ball, robot) {
var bounds = robot.getBounds();
// Closest point on robot to ball center
var cx = Math.max(bounds.left, Math.min(ball.x, bounds.right));
var cy = Math.max(bounds.top, Math.min(ball.y, bounds.bottom));
var dx = ball.x - cx;
var dy = ball.y - cy;
var dist = Math.sqrt(dx * dx + dy * dy);
return dist < ball.radius;
}
function resolveBallRobotCollision(ball, robot) {
var bounds = robot.getBounds();
var cx = Math.max(bounds.left, Math.min(ball.x, bounds.right));
var cy = Math.max(bounds.top, Math.min(ball.y, bounds.bottom));
var dx = ball.x - cx;
var dy = ball.y - cy;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist === 0) return;
var overlap = ball.radius - dist;
if (overlap > 0) {
// Push ball out
var nx = dx / dist;
var ny = dy / dist;
ball.x += nx * overlap;
ball.y += ny * overlap;
// Reflect velocity
var dot = ball.vx * nx + ball.vy * ny;
ball.vx -= 2 * dot * nx;
ball.vy -= 2 * dot * ny;
ball.vx *= 0.9;
ball.vy *= 0.9;
}
}
// --- Chain-ball collision ---
function chainHitsBall(chain, ball) {
// Check each segment
for (var i = 0; i < chain.segments.length; ++i) {
var seg = chain.segments[i];
var dx = seg.x - ball.x;
var dy = seg.y - ball.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < ball.radius) {
return true;
}
}
return false;
}
// --- Chain stops at first collision with ball or wall ---
function updateChainCollisions() {
if (!chain.active) return;
for (var i = 0; i < balls.length; ++i) {
if (chainHitsBall(chain, balls[i])) {
balls[i].shrink();
score += 1;
scoreTxt.setText(score);
// Flash ball
LK.effects.flashObject(balls[i], 0xffff00, 200);
chain.active = false;
break;
}
}
}
// --- Game update loop ---
game.update = function () {
// Update robot
robot.update();
// Update balls
for (var i = 0; i < balls.length; ++i) {
balls[i].update();
}
// Ball-ball collision
if (balls.length >= 2) {
if (ballsCollide(balls[0], balls[1])) {
resolveBallCollision(balls[0], balls[1]);
}
}
// Ball-robot collision
for (var i = 0; i < balls.length; ++i) {
if (ballHitsRobot(balls[i], robot)) {
resolveBallRobotCollision(balls[i], robot);
// Game over
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
// Update chain
if (chain.active) {
chain.update();
updateChainCollisions();
}
// Fire cooldown
if (!canFire) {
fireTimer--;
if (fireTimer <= 0) {
canFire = true;
}
}
}; ===================================================================
--- original.js
+++ change.js