Code edit (1 edits merged)
Please save this source code
User prompt
implement //Based on intersectedBubblePos calculate the absolute row and column numbers to insert the current moving bubble to attach it to the grid
Code edit (3 edits merged)
Please save this source code
User prompt
fix any spelling errors in the source code
Code edit (3 edits merged)
Please save this source code
User prompt
implement self.findBubbleRowAndColumn = function (bubble) {};
Code edit (1 edits merged)
Please save this source code
User prompt
implement //Calculate the offset from the intersectedBubble to insert the bubble. Use angular math to determine the row / colum offset of where to insert the bubble.
Code edit (4 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: this.calculateInsertionPoint is not a function. (In 'this.calculateInsertionPoint(intersectedBubble, bubble)', 'this.calculateInsertionPoint' is undefined)' in or related to this line: 'var insertionPoint = this.calculateInsertionPoint(intersectedBubble, bubble);' Line Number: 293
User prompt
implement //We have a bubble we just intersected with. We want to know where to insert this bubble into the grid. Use the intersectedBubble position in the grid as the starting point for this calculation.
Code edit (4 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'currentBubble = hintBubbles[hintBubbleOffset] = new HintBubble();' Line Number: 463
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
implement //Calculate position that the bubble would snap into if it was part of the grid.
Code edit (20 edits merged)
Please save this source code
User prompt
Find //Calculate position that the bubble would snap into if it was part of the grid. and implement that
Code edit (1 edits merged)
Please save this source code
Code edit (20 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'bobble.y += launcher.y - self.y;' Line Number: 275
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (13 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'var dist = bubble.y - nextYx - self.x;' Line Number: 243
/****
* Classes
****/
var Barrier = Container.expand(function () {
var self = Container.call(this);
var barrierGraphics = self.attachAsset('barrier', {
anchorX: .5,
anchorY: .5
});
});
var Bubble = Container.expand(function (max_types) {
var self = Container.call(this);
var bubbleGraphics = self.attachAsset('bubble', {
anchorX: 0.5,
anchorY: 0.5
});
var state = 0;
var targetX = 0;
var targetY = 0;
var isAttached = true;
var speedX = 0;
var speedY = 0;
self.setPos = function (x, y) {
self.x = targetX = x;
self.y = targetY = y;
};
max_types = max_types || 3;
self.type = Math.floor(Math.random() * max_types);
bubbleGraphics.tint = bubbleColors[self.type];
self.detatch = function () {
game.addChild(self);
self.y += grid.y;
isAttached = false;
speedX = Math.random() * 40 - 20;
speedY = -Math.random() * 30;
self.down = undefined;
};
self.update = function () {
if (!isAttached) {
self.x += speedX;
self.y += speedY;
speedY += 1.5;
if (self.x < self.width / 2 && speedX < 0 || self.x > game.width - self.width / 2 && speedX > 0) {
speedX = -speedX;
}
// Check for collision with barriers
for (var i = 0; i < barriers.length; i++) {
var barrier = barriers[i];
var dx = self.x - barrier.x;
var dy = self.y - barrier.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var minDist = self.width / 2 + barrier.width / 2;
if (distance < minDist) {
// Calculate the angle of the collision
var angle = Math.atan2(dy, dx);
// Calculate the new speed based on the angle of collision, treating the barrier as a static billiard ball
var newSpeed = Math.sqrt(speedX * speedX + speedY * speedY);
speedX = Math.cos(angle) * newSpeed * .7;
speedY = Math.sin(angle) * newSpeed * .7;
// Move the bubble back to the point where it just touches the barrier
var overlap = minDist - distance;
self.x += overlap * Math.cos(angle);
self.y += overlap * Math.sin(angle);
}
}
// Remove unattached bubbles that fall below 2732 - 500
if (self.y > 2732 - 400) {
self.destroy();
scoreMultipliers[Math.floor(self.x / (2048 / 5))].applyBubble(self);
}
}
};
});
var BubbleRemoveParticle = Container.expand(function () {
var self = Container.call(this);
var particle = self.attachAsset('removebubbleeffect', {
anchorX: 0.5,
anchorY: 0.5
});
particle.blendMode = 1;
self.scale.set(.33, .33);
var cscale = .5;
self.update = function () {
cscale += .02;
self.scale.set(cscale, cscale);
self.alpha = 1 - (cscale - .5) * 1.5;
if (self.alpha < 0) {
self.destroy();
}
};
});
var Grid = Container.expand(function () {
var self = Container.call(this);
var rows = [];
self.container = self.addChild(new Container());
var rowCount = 0;
function insertRow() {
var row = [];
var rowWidth = rowCount % 2 == 0 ? 13 : 12;
for (var a = 0; a < rowWidth; a++) {
var bubble = new Bubble();
bubble.setPos((2048 - bubble.width * rowWidth) / 2 + bubble.width * a + bubble.width / 2, -rowCount * (1.7320508076 * bubble.height) / 2);
self.container.addChild(bubble);
row.push(bubble);
/*bubble.down = function () {
var bubbles = self.getConnectedBubbles(this);
self.removeBubbles(bubbles);
var disconnected = self.getDetachedBubbles();
self.removeBubbles(disconnected);
};*/
}
rows.push(row);
rowCount++;
}
//Method that removes an array of bubbles from the rows array.
self.removeBubbles = function (bubbles) {
for (var i = 0; i < bubbles.length; i++) {
var bubble = bubbles[i];
var bubbleIndex = this.findBubbleIndex(bubble);
if (bubbleIndex) {
rows[bubbleIndex.row][bubbleIndex.col] = null;
bubble.detatch();
}
}
};
self.getConnectedBubbles = function (bubble, ignoreType) {
var connectedBubbles = [];
var queue = [bubble];
var visited = [];
while (queue.length > 0) {
var currentBubble = queue.shift();
if (visited.indexOf(currentBubble) === -1) {
visited.push(currentBubble);
connectedBubbles.push(currentBubble);
var neighbors = self.getNeighbors(currentBubble);
for (var i = 0; i < neighbors.length; i++) {
var neighbor = neighbors[i];
if (neighbor && (neighbor.type === bubble.type || ignoreType)) {
queue.push(neighbor);
}
}
}
}
return connectedBubbles;
};
//Get a list of bubbles that are not connected to the top row, or to a chain of bubbles connected to the top row.
self.getDetachedBubbles = function () {
var detachedBubbles = [];
var connectedToTop = [];
// Mark all bubbles connected to the bottom row
var lastRowIndex = rows.length - 1;
for (var i = 0; i < rows[lastRowIndex].length; i++) {
if (rows[lastRowIndex][i] !== null) {
var bottomConnected = self.getConnectedBubbles(rows[lastRowIndex][i], true);
connectedToTop = connectedToTop.concat(bottomConnected);
}
}
// Mark all bubbles as visited or not
var visited = connectedToTop.filter(function (bubble) {
return bubble != null;
});
// Find all bubbles that are not visited and not connected to the top
for (var row = 0; row < rows.length - 1; row++) {
for (var col = 0; col < rows[row].length; col++) {
var bubble = rows[row][col];
if (bubble !== null && visited.indexOf(bubble) == -1) {
detachedBubbles.push(bubble);
}
}
}
return detachedBubbles;
};
self.getNeighbors = function (bubble) {
var neighbors = [];
var bubbleIndex = this.findBubbleIndex(bubble);
var directions = [[-1, 0], [1, 0],
// left and right
[0, -1], [0, 1],
// above and below
[-1, -1], [1, -1] // diagonals for even rows
];
if (bubbleIndex.row % 2 === 1) {
// Adjust diagonals for odd rows
directions[4] = [-1, 1];
directions[5] = [1, 1];
}
for (var i = 0; i < directions.length; i++) {
var dir = directions[i];
var newRow = bubbleIndex.row + dir[0];
var newCol = bubbleIndex.col + dir[1];
if (newRow >= 0 && newRow < rows.length && newCol >= 0 && newCol < rows[newRow].length) {
neighbors.push(rows[newRow][newCol]);
}
}
return neighbors;
};
self.findBubbleIndex = function (bubble) {
for (var row = 0; row < rows.length; row++) {
var col = rows[row].indexOf(bubble);
if (col !== -1) {
return {
row: row,
col: col
};
}
}
return null;
};
// Method to calculate path of movement based on angle and starting point
//TODO: MAKE THIS MUCH FASTER!
self.calculatePath = function (startPoint, angle) {
var path = [];
var currentPoint = {
x: startPoint.x,
y: startPoint.y
};
var radians = angle;
var stepSize = 4;
var hitBubble = false;
while (currentPoint.y > 0 && !hitBubble) {
// Calculate next point
var nextX = currentPoint.x + stepSize * Math.cos(radians);
var nextY = currentPoint.y + stepSize * Math.sin(radians);
// Check for wall collisions
if (nextX < 150 / 2 || nextX > 2048 - 150 / 2) {
radians = Math.PI - radians; // Reflect angle
nextX = currentPoint.x + stepSize * Math.cos(radians); // Recalculate nextX after reflection
}
// Check for bubble collisions
outer: for (var row = 0; row < rows.length; row++) {
for (var col = 0; col < rows[row].length; col++) {
var bubble = rows[row][col];
if (bubble) {
var dist = Math.sqrt(Math.pow(bubble.y - nextY, 2) + Math.pow(bubble.x - self.x, 2));
if (dist > 145 || dist < -145) {
continue outer;
}
var dx = nextX - bubble.x - self.x;
var dy = nextY - bubble.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 70 + bubble.width / 2) {
hitBubble = true;
bubble.alpha = Math.random();
break;
}
}
}
if (hitBubble) {
break;
}
}
// Add point to path and update currentPoint
path.push({
x: nextX,
y: nextY
});
currentPoint.x = nextX;
currentPoint.y = nextY;
}
return path;
};
insertRow();
insertRow();
insertRow();
insertRow();
insertRow();
insertRow();
insertRow();
insertRow();
insertRow();
insertRow();
insertRow();
});
var HintBubble = Container.expand(function () {
var self = Container.call(this);
var bubble = self.attachAsset('hintbubble', {
anchorX: 0.5,
anchorY: 0.5
});
});
var Launcher = Container.expand(function () {
var self = Container.call(this);
var bubble = self.addChild(new Bubble(3));
});
var ScoreIndicatorLabel = Container.expand(function (score, type) {
var self = Container.call(this);
var label = new Text2(score, {
size: 100,
fill: "#" + bubbleColors[type].toString(16).padStart(6, '0'),
font: "Impact"
});
label.anchor.set(0.5, 0);
self.addChild(label);
self.update = function () {
self.y -= 7;
self.alpha -= .05;
if (self.alpha <= 0) {
self.destroy();
increaseScore(score);
}
};
});
var ScoreMultipliers = Container.expand(function (baseValue) {
var self = Container.call(this);
// Create a score label text string for ScoreMultipliers
var scoreMultiplierLabel = new Text2(baseValue, {
size: 100,
fill: "#2035bd",
font: "Impact"
});
scoreMultiplierLabel.anchor.set(0.5, 0);
self.addChild(scoreMultiplierLabel);
self.applyBubble = function (bubble) {
var scoreIndicator = game.addChild(new ScoreIndicatorLabel(baseValue, bubble.type));
scoreIndicator.x = self.x;
scoreIndicator.y = self.y;
var particle = game.addChildAt(new BubbleRemoveParticle(), particleInjectionZIndex);
particle.x = bubble.x;
particle.y = self.y + 100;
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x010c42
});
/****
* Game Code
****/
// Function to increase game score and update score label
function increaseScore(amount) {
var currentScore = LK.getScore();
var newScore = currentScore + amount;
LK.setScore(newScore); // Update the game score using LK method
scoreLabel.setText(newScore.toString()); // Update the score label with the new score
}
//Game size 2048x2732
/*
Todo:
[ ] Make sure empty rows are removed from the array
[ ] Make sure we GC nodes that drop of screen
*/
var bubbleColors = [0xff0000, 0x00ff00, 0x0000ff, 0xff00ff, 0xffff00, 0x00ffff, 0xffffff];
var barriers = [];
for (var a = 0; a < 4; a++) {
for (var b = 0; b < 3; b++) {
var barrier = game.addChild(new Barrier());
barrier.y = 2732 - 500 + b * 25;
barrier.x = 2048 / 5 * a + 2048 / 5;
barriers.push(barrier);
}
}
// Create a score label
var scoreLabel = new Text2('0', {
size: 120,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 15,
font: "Impact"
});
scoreLabel.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreLabel);
var scoreMultipliers = [];
var baseScores = [100, 250, 500, 250, 100];
for (var a = 0; a < 5; a++) {
var sm = new ScoreMultipliers(baseScores[a]);
sm.x = 2048 / 5 * a + 2048 / 10;
sm.y = 2300;
scoreMultipliers.push(sm);
game.addChild(sm);
}
var particleInjectionZIndex = game.children.length;
var grid = game.addChild(new Grid());
grid.y = 1300;
var launcher = game.addChild(new Launcher());
launcher.x = game.width / 2;
launcher.y = game.height - 180;
var hintBubbleCache = [];
var hintBubbles = [];
var isValid = false;
var path = [];
game.move = function (x, y, obj) {
var ox = x - launcher.x;
var oy = y - launcher.y;
var angle = Math.atan2(oy, ox);
isValid = angle < -.3 && angle > -Math.PI + .3;
if (isValid) {
path = grid.calculatePath(launcher, angle);
}
};
game.update = function () {
if (isValid) {
var distanceSinceLastDot = 0;
var hintBubbleOffset = 0;
var lastPoint = path[0];
for (var a = 1; a < path.length; a++) {
var p2 = path[a];
var ox = p2.x - lastPoint.x;
var oy = p2.y - lastPoint.y;
var dist = Math.sqrt(ox * ox + oy * oy);
distanceSinceLastDot += dist;
if (distanceSinceLastDot >= 100) {
var amountOver = distanceSinceLastDot - 100;
var angle = Math.atan2(oy, ox);
var currentBubble = hintBubbles[hintBubbleOffset];
if (!currentBubble) {
currentBubble = hintBubbles[hintBubbleOffset] = new HintBubble();
game.addChild(currentBubble);
}
currentBubble.x = lastPoint.x - Math.cos(angle) * amountOver;
currentBubble.y = lastPoint.y - Math.sin(angle) * amountOver;
hintBubbleOffset++;
distanceSinceLastDot = 0;
lastPoint = currentBubble;
} else {
lastPoint = p2;
}
}
}
};
Circular white gradient circle on black background. Gradient from white on the center to black on the outer edge all around.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Soft straight Long red paint on black background. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Fire ball. Bubble shooter game. Thin black outline.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
green notification bubble. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.