Code edit (1 edits merged)
Please save this source code
User prompt
add icon to normal ball upgrade button
User prompt
normal ball power up icon should be white
User prompt
normal ball icon should be white
User prompt
normal ball should be white
User prompt
make all text black in the game
User prompt
change button and turn them just into clickable blocks
User prompt
move ball icon in buttons 50 pixels down
User prompt
Buy ball buttons should have an icon on top of them
User prompt
delete icons for ball buy button
User prompt
Make sure ball icons in ball purchase button are visible in the button and, not covered by it.
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'hud.addChild(button);' Line Number: 361
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'hud.addChild(button);' Line Number: 361
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'hud.addChild(button);' Line Number: 361
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'hud.addChild(button);' Line Number: 361
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'hud.addChild(button);' Line Number: 361
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'hud.addChild(button);' Line Number: 361
User prompt
Make sure buttons are the first thing to be rendered in the game
User prompt
Make sure buttons are design like bricks to have elements and text displayed in them
User prompt
click damage button is not associated to any tier
User prompt
clickdame button should be purchaseable if there is nenought money
User prompt
Click damage button should alway be active as long as there is money to buy it. should not have any other constraint
User prompt
Click x 1" Upgrade Problem: The clickDamage upgrade button wasn't handling its type correctly in the update state function Added special case handling for clickDamage since it doesn't have a corresponding ball type Fixed the logic to enable/disable the button correctly
User prompt
Button Layering Problems: Your original implementation was attaching content directly to button assets using button.addChild() and button.attachAsset(), which can cause layering issues The fix creates a Container first, adds the button as the first child (background), and then adds the text and icons as siblings on top
/**** * Plugins ****/ var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Ball = Container.expand(function () { var self = Container.call(this); var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'normal'; var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); ballGraphics.tint = type === 'splash' ? 0xff3366 : type === 'sniper' ? 0x00ff00 : type === 'scatter' ? 0xffff00 : type === 'smallScatter' ? 0xffff00 : 0xffffff; self.type = type; self.speed = type === 'splash' ? upgrades.splashSpeed : type === 'sniper' ? upgrades.sniperSpeed : type === 'scatter' ? upgrades.scatterSpeed : type === 'smallScatter' ? upgrades.scatterSpeed * 0.8 : upgrades.normalSpeed; self.power = type === 'splash' ? upgrades.splashPower : type === 'sniper' ? upgrades.sniperPower : type === 'scatter' ? upgrades.scatterPower : type === 'smallScatter' ? Math.max(1, Math.floor(upgrades.scatterPower * 0.5)) : upgrades.normalPower; self.direction = { x: 1, y: -1 }; self.update = function () { var gridSize = levelConfig[level] ? levelConfig[level].gridSize : 200; var stepSize = self.speed; if (self.type === 'sniper') { var nearestBrick = findNearestBrick(self.x, self.y); if (nearestBrick) { var dx = nearestBrick.x - self.x; var dy = nearestBrick.y - self.y; var magnitude = Math.sqrt(dx * dx + dy * dy); self.direction.x = dx / magnitude; self.direction.y = dy / magnitude; } } var dx = self.direction.x * stepSize; var dy = self.direction.y * stepSize; self.x += dx; self.y += dy; if (self.x <= BALL_RADIUS || self.x >= GAME_WIDTH - BALL_RADIUS) { self.direction.x *= -1; self.x = Math.max(BALL_RADIUS, Math.min(GAME_WIDTH - BALL_RADIUS, self.x)); } if (self.y <= BALL_RADIUS || self.y >= GAME_HEIGHT - BALL_RADIUS) { self.direction.y *= -1; self.y = Math.max(BALL_RADIUS, Math.min(GAME_HEIGHT - BALL_RADIUS, self.y)); } if (!isNearBricks(self.x, self.y)) { return; } var gridXMin = Math.floor((self.x - BALL_RADIUS) / gridSize); var gridXMax = Math.floor((self.x + BALL_RADIUS) / gridSize); var gridYMin = Math.floor((self.y - BALL_RADIUS) / gridSize); var gridYMax = Math.floor((self.y + BALL_RADIUS) / gridSize); var hasCollided = false; for (var gx = gridXMin; gx <= gridXMax && !hasCollided; gx++) { for (var gy = gridYMin; gy <= gridYMax && !hasCollided; gy++) { var gridKey = "".concat(gx, ",").concat(gy); var cellBricks = brickGrid[gridKey]; if (!cellBricks || cellBricks.length === 0) { continue; } for (var j = cellBricks.length - 1; j >= 0; j--) { var brick = cellBricks[j]; if (!brick || brick.health <= 0 || !self.intersects(brick)) { continue; } handleBallBrickCollision(self, brick); brick.hit(self.power); if (self.type === 'splash' && brick.health > 0) { applySplashDamage(brick, gridSize); } else if (self.type === 'scatter') { scatterOnImpact(self); self.destroy(); balls.splice(balls.indexOf(self), 1); hasCollided = true; break; } if (brick.health <= 0) { cellBricks.splice(j, 1); } hasCollided = true; break; } } } }; }); var Brick = Container.expand(function () { var self = Container.call(this); var brickGraphics = self.attachAsset('brick', { anchorX: 0.5, anchorY: 0.5 }); self.health = 1; self.maxHealth = 1; self.healthText = new Text2(self.health.toString(), { size: 50, fill: 0x000000 }); self.healthText.anchor.set(0.5, 0.5); self.addChild(self.healthText); self.updateTint = function () { var healthPercent = self.health / self.maxHealth; var colorIndex = Math.min(Math.floor((1 - healthPercent) * LEVEL_COLORS.length), LEVEL_COLORS.length - 1); brickGraphics.tint = LEVEL_COLORS[colorIndex]; }; self.updateTint(); self.hit = function () { var damage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; self.health -= damage; if (self.health <= 0) { score += Math.max(1, Math.floor(self.maxHealth * 0.5)); scoreTxt.setText('$' + score.toString()); storage.score = score; var brickIndex = bricks.indexOf(self); if (brickIndex !== -1) { bricks.splice(brickIndex, 1); } self.destroy(); } else { self.healthText.setText(self.health.toString()); self.updateTint(); } }; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x3b9c9c }); /**** * Game Code ****/ function _toConsumableArray2(r) { return _arrayWithoutHoles2(r) || _iterableToArray2(r) || _unsupportedIterableToArray2(r) || _nonIterableSpread2(); } function _nonIterableSpread2() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray2(r, a) { if (r) { if ("string" == typeof r) { return _arrayLikeToArray2(r, a); } var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray2(r, a) : void 0; } } function _iterableToArray2(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) { return Array.from(r); } } function _arrayWithoutHoles2(r) { if (Array.isArray(r)) { return _arrayLikeToArray2(r); } } function _arrayLikeToArray2(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) { n[e] = r[e]; } return n; } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) { return _arrayLikeToArray(r, a); } var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) { return Array.from(r); } } function _arrayWithoutHoles(r) { if (Array.isArray(r)) { return _arrayLikeToArray(r); } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) { n[e] = r[e]; } return n; } var GAME_WIDTH = 2048; var GAME_HEIGHT = 2632; var BALL_RADIUS = 50; var BRICK_WIDTH = 300; var BRICK_HEIGHT = 99; var BALL_COST = 50; var LEVEL_COLORS = [0xff00ff, 0x00ffcc, 0xccff00, 0xff6600, 0x66ffff, 0xff3366, 0xffcc00, 0x9966ff, 0x33cc33, 0xff0000]; var levelConfig = { 1: { totalBricks: 30, hitpoints: 1, gridSize: 400, pattern: 'grid' }, 2: { totalBricks: 50, hitpoints: 2, gridSize: 360, pattern: 'staggered' }, 3: { totalBricks: 70, hitpoints: 3, gridSize: 320, pattern: 'clustered' }, 4: { totalBricks: 90, hitpoints: 4, gridSize: 280, pattern: 'diagonal' }, 5: { totalBricks: 110, hitpoints: 5, gridSize: 240, pattern: 'sparse' } }; var upgrades = { normalSpeed: 1, normalPower: 1, splashSpeed: 1, splashPower: 1, sniperSpeed: 1.5, sniperPower: 2, scatterSpeed: 1, scatterPower: 1, clickDamage: 1, normalSpeedCost: 50, normalPowerCost: 75, splashSpeedCost: 50, splashPowerCost: 75, sniperSpeedCost: 75, sniperPowerCost: 100, scatterSpeedCost: 50, scatterPowerCost: 75, clickCost: 25, splashBallCost: 100, sniperBallCost: 150, scatterBallCost: 125 }; var balls = []; var bricks = []; var brickGrid = {}; var score = 10000; var level = storage.level || 1; var brickGridBounds = null; var unlockedTiers = storage.unlockedTiers || { normal: true, splash: false, sniper: false, scatter: false }; function clearLocalStorage() { storage.score = 0; storage.level = 1; storage.unlockedTiers = { normal: true, splash: false, sniper: false, scatter: false }; score = 0; level = 1; unlockedTiers = Object.assign({}, storage.unlockedTiers); scoreTxt.setText('$' + score.toString()); levelTxt.setText('Level: ' + level); updateButtonStates(); } var ballButtons = {}; function createBallButton(type, x, cost, asset, prevTier) { var button = LK.getAsset('button', { size: 80, fill: 0xFFFFFF, anchorX: 0.5, anchorY: 0, y: 50, x: x }); var contentContainer = new Container(); button.addChild(contentContainer); var ballIcon = button.attachAsset('ball', { anchorX: 0.5, anchorY: -0.5, scaleX: 0.6, scaleY: 0.6, y: -10, tint: type === 'splash' ? 0xff3366 : type === 'sniper' ? 0x00ff00 : type === 'scatter' ? 0xffff00 : 0xffffff }); contentContainer.addChild(ballIcon); var typeText = new Text2(type.charAt(0).toUpperCase() + type.slice(1), { size: 30, fill: 0x000000 }); typeText.anchor.set(0.5, 0); typeText.y = -50; button.addChild(typeText); var costText = new Text2('$' + cost, { size: 50, fill: 0x000000 }); costText.anchor.set(0.5, 0); costText.y = 100; button.addChild(costText); button.interactive = true; button.down = function () { if (score < cost) { return; } score -= cost; scoreTxt.setText('$' + score.toString()); createBall(type); if (!unlockedTiers[type]) { unlockedTiers[type] = true; storage.unlockedTiers = Object.assign({}, unlockedTiers); updateButtonStates(); } }; button.updateState = function () { var isEnabled = (prevTier ? unlockedTiers[prevTier] : true) && score >= cost && (type !== 'splash' || balls.some(function (b) { return b.type === 'normal'; })); button.tint = isEnabled ? 0xFFFFFF : 0x666666; button.interactive = isEnabled; }; hud.addChild(button); ballButtons[type] = button; } createBallButton('normal', -400, BALL_COST, 'ball', null); createBallButton('splash', -280, upgrades.splashBallCost, 'splashBall', 'normal'); createBallButton('sniper', -160, upgrades.sniperBallCost, 'sniperBall', 'splash'); createBallButton('scatter', -40, upgrades.scatterBallCost, 'scatterBall', 'sniper'); var clearStorageButton = LK.getAsset('button', { size: 80, fill: 0xFFFFFF, anchorX: 0.5, anchorY: 0, x: scoreTxt.width + 200, y: 0 }); var clearStorageText = new Text2('Reset', { size: 50, fill: 0x000000 }); clearStorageText.anchor.set(0.5, 0); clearStorageText.y = 100; clearStorageButton.addChild(clearStorageText); clearStorageButton.down = clearLocalStorage; hud.addChild(clearStorageButton); var powerupContainer = new Container(); powerupContainer.y = 1800; powerupContainer.visible = false; game.addChild(powerupContainer); var bottomHud = new Container(); bottomHud.y = GAME_HEIGHT - 200; game.addChild(bottomHud); var upgradeButtons = {}; function createUpgradeButton(labelPrefix, x, costKey, upgradeKey, baseCost, iconType, prevTier) { var button = LK.getAsset('powerupbutton', { size: 150, fill: 0xFFFFFF, anchorX: 0.5, anchorY: 0, x: x, y: 0 }); var contentContainer = new Container(); button.addChild(contentContainer); if (iconType) { var icon = button.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5, y: 40, tint: iconType === 'splashBall' ? 0xff3366 : iconType === 'sniperBall' ? 0x00ff00 : iconType === 'scatterBall' ? 0xffff00 : 0xcccccc }); contentContainer.addChild(icon); } var labelText = new Text2("".concat(labelPrefix, " x").concat(upgrades[upgradeKey]), { size: 30, fill: 0x000000 }); labelText.anchor.set(0.5, 0); labelText.y = 100; button.addChild(labelText); var costText = new Text2('$' + (baseCost * upgrades[upgradeKey]).toString(), { size: 40, fill: 0x000000 }); costText.anchor.set(0.5, 0); costText.y = 140; button.addChild(costText); button.interactive = true; button.down = function () { var cost = baseCost * upgrades[upgradeKey]; var ballType = upgradeKey.split('Speed')[0].split('Power')[0]; if (!unlockedTiers[ballType] || score < cost) { return; } score -= cost; upgrades[upgradeKey]++; costText.setText('$' + (baseCost * upgrades[upgradeKey]).toString()); labelText.setText("".concat(labelPrefix, " x").concat(upgrades[upgradeKey])); scoreTxt.setText('$' + score.toString()); balls.forEach(function (b) { if (b.type === 'normal' && upgradeKey.includes('normal')) { b[upgradeKey.includes('Speed') ? 'speed' : 'power'] = upgrades[upgradeKey]; } else if (b.type === 'splash' && upgradeKey.includes('splash')) { b[upgradeKey.includes('Speed') ? 'speed' : 'power'] = upgrades[upgradeKey]; } else if (b.type === 'sniper' && upgradeKey.includes('sniper')) { b[upgradeKey.includes('Speed') ? 'speed' : 'power'] = upgrades[upgradeKey]; } else if ((b.type === 'scatter' || b.type === 'smallScatter') && upgradeKey.includes('scatter')) { b[upgradeKey.includes('Speed') ? 'speed' : 'power'] = upgrades[upgradeKey]; } }); if (upgradeKey === 'clickDamage') { upgrades.clickDamage = upgrades[upgradeKey]; } }; button.updateState = function () { var ballType = upgradeKey.split('Speed')[0].split('Power')[0]; var isEnabled = (upgradeKey === 'clickDamage' || unlockedTiers[ballType] && (prevTier ? unlockedTiers[prevTier] : true)) && score >= baseCost * upgrades[upgradeKey]; button.tint = isEnabled ? 0xFFFFFF : 0x666666; button.interactive = isEnabled; }; powerupContainer.addChild(button); upgradeButtons[upgradeKey] = button; } var buttonWidth = 150; var spacing = 50; var totalButtons = 9; var totalWidth = totalButtons * buttonWidth + (totalButtons - 1) * spacing; var startX = (GAME_WIDTH - totalWidth) / 2; createUpgradeButton('Speed', startX, 'normalSpeedCost', 'normalSpeed', 50, 'ball', null); createUpgradeButton('Power', startX + (buttonWidth + spacing), 'normalPowerCost', 'normalPower', 75, 'ball', null); createUpgradeButton('Speed', startX + 2 * (buttonWidth + spacing), 'splashSpeedCost', 'splashSpeed', 50, 'splashBall', 'normal'); createUpgradeButton('Power', startX + 3 * (buttonWidth + spacing), 'splashPowerCost', 'splashPower', 75, 'splashBall', 'normal'); createUpgradeButton('Speed', startX + 4 * (buttonWidth + spacing), 'sniperSpeedCost', 'sniperSpeed', 75, 'sniperBall', 'splash'); createUpgradeButton('Power', startX + 5 * (buttonWidth + spacing), 'sniperPowerCost', 'sniperPower', 100, 'sniperBall', 'splash'); createUpgradeButton('Speed', startX + 6 * (buttonWidth + spacing), 'scatterSpeedCost', 'scatterSpeed', 50, 'scatterBall', 'sniper'); createUpgradeButton('Power', startX + 7 * (buttonWidth + spacing), 'scatterPowerCost', 'scatterPower', 75, 'scatterBall', 'sniper'); createUpgradeButton('Click', startX + 8 * (buttonWidth + spacing), 'clickCost', 'clickDamage', 25, null, null); var upgradeButton = LK.getAsset('upgrade', { anchorX: 0.5, anchorY: 0.5, x: GAME_WIDTH / 2, y: GAME_HEIGHT - 100 }); var upgradeText = new Text2('UPGRADE', { size: 50, fill: 0x000000 }); upgradeText.anchor.set(0.5, 0.5); upgradeButton.addChild(upgradeText); upgradeButton.down = function () { powerupContainer.visible = !powerupContainer.visible; }; game.addChild(upgradeButton); // HUD Setup var hud = new Container(); LK.gui.top.addChild(hud); var scoreTxt = new Text2('0', { size: 60, fill: 0x000000 }); scoreTxt.anchor.set(0.3, 0); scoreTxt.x += 450; hud.addChild(scoreTxt); var levelTxt = new Text2('Level: ' + level, { size: 60, fill: 0x000000 }); levelTxt.anchor.set(1, 0); levelTxt.x = scoreTxt.x + 100; levelTxt.y = scoreTxt.height + 10; hud.addChild(levelTxt); // Helper Functions function updateButtonStates() { for (var type in ballButtons) { ballButtons[type].updateState(); } for (var key in upgradeButtons) { upgradeButtons[key].updateState(); } } function handleBallBrickCollision(ball, brick) { var relativeX = (ball.x - brick.x) / (brick.width / 2); var relativeY = (ball.y - brick.y) / (brick.height / 2); if (Math.abs(relativeX) > Math.abs(relativeY)) { ball.direction.x = -ball.direction.x + relativeX * 0.5; ball.x = brick.x + (relativeX > 0 ? brick.width / 2 + BALL_RADIUS : -brick.width / 2 - BALL_RADIUS); } else { ball.direction.y = -ball.direction.y; ball.y = brick.y + (relativeY > 0 ? brick.height / 2 + BALL_RADIUS : -brick.height / 2 - BALL_RADIUS); } ball.direction.x += (Math.random() - 0.5) * 0.1; var magnitude = Math.sqrt(ball.direction.x * ball.direction.x + ball.direction.y * ball.direction.y); ball.direction.x /= magnitude; ball.direction.y /= magnitude; } function applySplashDamage(brick, gridSize) { var gridX = Math.floor(brick.x / gridSize); var gridY = Math.floor(brick.y / gridSize); var adjacentKeys = ["".concat(gridX - 1, ",").concat(gridY), "".concat(gridX + 1, ",").concat(gridY), "".concat(gridX, ",").concat(gridY - 1), "".concat(gridX, ",").concat(gridY + 1)]; adjacentKeys.forEach(function (key) { if (brickGrid[key]) { brickGrid[key].forEach(function (adjBrick) { if (adjBrick && adjBrick.health > 0) { adjBrick.hit(Math.floor(upgrades.splashPower * 0.25)); } }); } }); } function scatterOnImpact(ball) { for (var i = 0; i < 4; i++) { var smallBall = new Ball('smallScatter'); smallBall.x = ball.x; smallBall.y = ball.y; var angle = i / 4 * 2 * Math.PI; smallBall.direction.x = Math.cos(angle); smallBall.direction.y = Math.sin(angle); balls.push(smallBall); game.addChild(smallBall); } } function findNearestBrick(x, y) { if (bricks.length === 0) { return null; } return bricks.reduce(function (closest, brick) { var dx = brick.x - x; var dy = brick.y - y; var distance = Math.sqrt(dx * dx + dy * dy); return !closest || distance < closest.distance ? { brick: brick, distance: distance } : closest; }, null).brick; } function isNearBricks(x, y) { if (!brickGridBounds) { return true; } var buffer = BALL_RADIUS * 2; return x >= brickGridBounds.minX - buffer && x <= brickGridBounds.maxX + buffer && y >= brickGridBounds.minY - buffer && y <= brickGridBounds.maxY + buffer; } function createBricks() { var config = levelConfig[level] || {}; var totalBricks = config.totalBricks || 50; var hitpoints = config.hitpoints || 1; var gridSize = config.gridSize || 200; var pattern = config.pattern || 'grid'; var spacingX = 2; var spacingY = 2; brickGrid = {}; bricks = []; var cols = Math.floor(GAME_WIDTH / (BRICK_WIDTH + spacingX)); var rows = Math.ceil(totalBricks / cols); var totalWidth = cols * BRICK_WIDTH + (cols - 1) * spacingX; var totalHeight = rows * BRICK_HEIGHT + (rows - 1) * spacingY; var startX = (GAME_WIDTH - totalWidth) / 2 + BRICK_WIDTH / 2; var startY = (GAME_HEIGHT - totalHeight) / 3 + BRICK_HEIGHT / 2; var brickCount = 0; if (pattern === 'grid') { for (var i = 0; i < rows && brickCount < totalBricks; i++) { for (var j = 0; j < cols && brickCount < totalBricks; j++) { addBrick(startX + j * (BRICK_WIDTH + spacingX), startY + i * (BRICK_HEIGHT + spacingY), hitpoints, gridSize); brickCount++; } } } else if (pattern === 'staggered') { for (var i = 0; i < rows && brickCount < totalBricks; i++) { var offsetX = i % 2 === 0 ? 0 : BRICK_WIDTH / 2; for (var j = 0; j < cols && brickCount < totalBricks; j++) { addBrick(startX + offsetX + j * (BRICK_WIDTH + spacingX), startY + i * (BRICK_HEIGHT + spacingY), hitpoints, gridSize); brickCount++; } } } else if (pattern === 'clustered') { var clusterCols = Math.floor(cols / 2); var clusterRows = Math.floor(rows / 2); var clusterStartX = GAME_WIDTH / 2 - clusterCols * BRICK_WIDTH / 2; var clusterStartY = GAME_HEIGHT / 3 - clusterRows * BRICK_HEIGHT / 2; for (var i = 0; i < clusterRows && brickCount < totalBricks; i++) { for (var j = 0; j < clusterCols && brickCount < totalBricks; j++) { addBrick(clusterStartX + j * (BRICK_WIDTH + spacingX), clusterStartY + i * (BRICK_HEIGHT + spacingY), hitpoints, gridSize); brickCount++; } } } else if (pattern === 'diagonal') { var stepX = (GAME_WIDTH - BRICK_WIDTH) / (totalBricks - 1); var stepY = GAME_HEIGHT / 3 / (totalBricks - 1); for (var i = 0; i < totalBricks; i++) { addBrick(startX + i * stepX, startY + i * stepY, hitpoints, gridSize); brickCount++; } } else if (pattern === 'sparse') { while (brickCount < totalBricks) { var x = startX + Math.floor(Math.random() * cols) * (BRICK_WIDTH + spacingX); var y = startY + Math.floor(Math.random() * rows) * (BRICK_HEIGHT + spacingY); if (!bricks.some(function (b) { return b.x === x && b.y === y; })) { addBrick(x, y, hitpoints, gridSize); brickCount++; } } } brickGridBounds = { minX: Math.min.apply(Math, _toConsumableArray2(bricks.map(function (b) { return b.x - BRICK_WIDTH / 2; }))), maxX: Math.max.apply(Math, _toConsumableArray2(bricks.map(function (b) { return b.x + BRICK_WIDTH / 2; }))), minY: Math.min.apply(Math, _toConsumableArray2(bricks.map(function (b) { return b.y - BRICK_HEIGHT / 2; }))), maxY: Math.max.apply(Math, _toConsumableArray2(bricks.map(function (b) { return b.y + BRICK_HEIGHT / 2; }))) }; } function addBrick(x, y, hitpoints, gridSize) { var brick = new Brick(); brick.x = x; brick.y = y; brick.health = hitpoints; brick.maxHealth = hitpoints; brick.healthText.setText(brick.health.toString()); brick.updateTint(); bricks.push(brick); game.addChild(brick); var gridX = Math.floor(brick.x / gridSize); var gridY = Math.floor(brick.y / gridSize); var gridKey = "".concat(gridX, ",").concat(gridY); if (!brickGrid[gridKey]) { brickGrid[gridKey] = []; } brickGrid[gridKey].push(brick); } function createBall() { var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'normal'; var ball = new Ball(type); var gridBottom = brickGridBounds ? brickGridBounds.maxY + 150 : GAME_HEIGHT * 0.7; ball.x = GAME_WIDTH / 2 + (Math.random() * 200 - 100); ball.y = Math.min(gridBottom + 100, GAME_HEIGHT - BALL_RADIUS * 2); var angle = (Math.random() * 0.5 + 0.25) * Math.PI; ball.direction.x = Math.cos(angle); ball.direction.y = -Math.sin(angle); var magnitude = Math.sqrt(ball.direction.x * ball.direction.x + ball.direction.y * ball.direction.y); ball.direction.x /= magnitude; ball.direction.y /= magnitude; for (var i = 0; i < bricks.length; i++) { if (ball.intersects(bricks[i])) { ball.y = brickGridBounds.maxY + BALL_RADIUS + 10; break; } } balls.push(ball); game.addChild(ball); } game.update = function () { for (var i = balls.length - 1; i >= 0; i--) { var ball = balls[i]; ball.update(); if (ball.y > GAME_HEIGHT + BALL_RADIUS) { ball.destroy(); balls.splice(i, 1); } } if (bricks.length === 0) { if (level === Object.keys(levelConfig).length) { LK.showGameOver(); } else { level += 1; storage.level = level; levelTxt.setText('Level: ' + level); createBricks(); } } updateButtonStates(); }; game.down = function (x, y, obj) { if (!bricks || !Array.isArray(bricks)) { return; } x = Number(x); y = Number(y); for (var i = 0; i < bricks.length; i++) { var brick = bricks[i]; if (!brick.x || !brick.y || !brick.width || !brick.height) { continue; } if (x >= brick.x - brick.width / 2 && x <= brick.x + brick.width / 2 && y >= brick.y - brick.height / 2 && y <= brick.y + brick.height / 2) { brick.hit(upgrades.clickDamage); score += upgrades.clickDamage; scoreTxt.setText('$' + score.toString()); storage.score = score; return; } } }; // Initialize game elements createBricks(); updateButtonStates();
===================================================================
--- original.js
+++ change.js