User prompt
add a main menu screen with the game title and a game start button. game should not start until game start is touched. main menu should cover the whole screen and the game should not be displayed.
Code edit (1 edits merged)
Please save this source code
User prompt
add local storage module ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
add a button to delete local storage ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
local storage button delete sholuld be next to the points ↪💡 Consider importing and using the following plugins: @upit/storage.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Import of asset
User prompt
lets add somoe particle effect when a block is destroyed
User prompt
use a new asset for particle effect, not splash ball
Code edit (2 edits merged)
Please save this source code
User prompt
move points to 200 pixels to the right
User prompt
move level below points
User prompt
move level 100 pixels to the left
User prompt
sorry I meant to the right
User prompt
move points and level 200 pixles ot the right
User prompt
move points 50 pixels to the right
User prompt
normal ball should start unlocked
Code edit (1 edits merged)
Please save this source code
User prompt
upgrade buttons and text should be the same size as ball purchase buttons, and have the same space between each ther
User prompt
rename buyball50 to button
User prompt
increase the size parameter of the buttons for the upgrades to be the same as the buy balls ones
User prompt
create a new button for powerup buttons
User prompt
Powerup are using an asset for their background button. create a new asset to be used by all of them. should be powerupbutton
User prompt
powerups should use powerup asset
User prompt
upgrade buttons should have a little moroe space between them
===================================================================
--- original.js
+++ change.js
@@ -8,23 +8,33 @@
****/
var Ball = Container.expand(function () {
var self = Container.call(this);
var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'normal';
- var asset = type === 'splash' ? 'splashBall' : 'ball';
+ var asset = type === 'splash' ? 'splashBall' : type === 'sniper' ? 'sniperBall' : type === 'scatter' ? 'scatterBall' : type === 'smallScatter' ? 'smallScatter' : 'ball';
var ballGraphics = self.attachAsset(asset, {
anchorX: 0.5,
anchorY: 0.5
});
self.type = type;
- self.speed = type === 'splash' ? upgrades.splashSpeed : upgrades.normalSpeed;
- self.power = type === 'splash' ? upgrades.splashPower : upgrades.normalPower;
+ 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;
@@ -59,8 +69,14 @@
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);
}
@@ -96,15 +112,13 @@
self.health -= damage;
if (self.health <= 0) {
score += Math.max(1, Math.floor(self.maxHealth * 0.5));
scoreTxt.setText('$' + score.toString());
- storage.score = score; // Persist score to storage
+ storage.score = score;
var brickIndex = bricks.indexOf(self);
if (brickIndex !== -1) {
bricks.splice(brickIndex, 1);
}
- // Create particle effect at the brick's position before destroying
- createParticleEffect(self.x, self.y);
self.destroy();
} else {
self.healthText.setText(self.health.toString());
self.updateTint();
@@ -121,46 +135,10 @@
/****
* Game Code
****/
-function createParticleEffect(x, y) {
- // Create a container for the particle effect
- var particleContainer = new Container();
- game.addChild(particleContainer);
- // Create particles
- for (var i = 0; i < 20; i++) {
- var particle = LK.getAsset('particleEffect', {
- anchorX: 0.5,
- anchorY: 0.5,
- scaleX: 0.2,
- scaleY: 0.2
- });
- particle.x = x;
- particle.y = y;
- particle.direction = {
- x: (Math.random() - 0.5) * 2,
- y: (Math.random() - 0.5) * 2
- };
- particle.speed = Math.random() * 5 + 2;
- particleContainer.addChild(particle);
- }
- // Update particles
- particleContainer.update = function () {
- for (var i = particleContainer.children.length - 1; i >= 0; i--) {
- var p = particleContainer.children[i];
- p.x += p.direction.x * p.speed;
- p.y += p.direction.y * p.speed;
- p.alpha -= 0.02;
- if (p.alpha <= 0) {
- particleContainer.removeChild(p);
- }
- }
- if (particleContainer.children.length === 0) {
- game.removeChild(particleContainer);
- }
- };
-}
// Constants
+var _storage$unlockedTier, _storage$unlockedTier2, _storage$unlockedTier3, _storage$unlockedTier4;
function _toConsumableArray(r) {
return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
}
function _nonIterableSpread() {
@@ -195,78 +173,105 @@
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2632;
var BALL_RADIUS = 50;
var BRICK_WIDTH = 300;
-var BRICK_HEIGHT = 99; // Adjusted to match asset definition
+var BRICK_HEIGHT = 99;
var BALL_COST = 50;
var LEVEL_COLORS = [0xff00ff, 0x00ffcc, 0xccff00, 0xff6600, 0x66ffff, 0xff3366, 0xffcc00, 0x9966ff, 0x33cc33, 0xff0000];
// Game Variables
var levelConfig = {
1: {
totalBricks: 30,
- // Fewer bricks for mobile visibility
hitpoints: 1,
gridSize: 400,
- // Larger grid for simpler collision
- pattern: 'grid' // Standard grid layout
+ pattern: 'grid'
},
2: {
totalBricks: 50,
hitpoints: 2,
gridSize: 360,
- pattern: 'staggered' // Offset rows for a "zigzag" feel
+ pattern: 'staggered'
},
3: {
totalBricks: 70,
hitpoints: 3,
gridSize: 320,
- pattern: 'clustered' // Tighter clusters of bricks
+ pattern: 'clustered'
},
4: {
totalBricks: 90,
hitpoints: 4,
gridSize: 280,
- pattern: 'diagonal' // Diagonal line pattern
+ pattern: 'diagonal'
},
5: {
totalBricks: 110,
hitpoints: 5,
gridSize: 240,
- pattern: 'sparse' // Spread out with gaps
+ 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
+ splashBallCost: 100,
+ sniperBallCost: 150,
+ scatterBallCost: 125
};
var balls = [];
var bricks = [];
var brickGrid = {};
-var score = storage.score || 0; // Retrieve score from storage or set to 0
-var level = storage.level || 1; // Retrieve level from storage or set to 1
+var score = storage.score || 0;
+var level = storage.level || 1;
var brickGridBounds = null;
-// Function to clear local storage
+// Track unlocked ball tiers
+var unlockedTiers = {
+ normal: ((_storage$unlockedTier = storage.unlockedTiers) === null || _storage$unlockedTier === void 0 ? void 0 : _storage$unlockedTier.normal) || true,
+ // Normal is always unlocked
+ splash: ((_storage$unlockedTier2 = storage.unlockedTiers) === null || _storage$unlockedTier2 === void 0 ? void 0 : _storage$unlockedTier2.splash) || false,
+ sniper: ((_storage$unlockedTier3 = storage.unlockedTiers) === null || _storage$unlockedTier3 === void 0 ? void 0 : _storage$unlockedTier3.sniper) || false,
+ scatter: ((_storage$unlockedTier4 = storage.unlockedTiers) === null || _storage$unlockedTier4 === void 0 ? void 0 : _storage$unlockedTier4.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 = {
+ normal: true,
+ splash: false,
+ sniper: false,
+ scatter: false
+ };
scoreTxt.setText('$' + score.toString());
levelTxt.setText('Level: ' + level);
+ updateButtonStates();
}
// HUD Setup
var hud = new Container();
LK.gui.top.addChild(hud);
-// Upper-Left: Score, Level, Ball Purchases
var scoreTxt = new Text2('0', {
size: 60,
fill: 0xFFFFFF
});
@@ -279,67 +284,57 @@
});
levelTxt.anchor.set(1, 0);
levelTxt.x = scoreTxt.width + 20;
hud.addChild(levelTxt);
-var buyNormalButton = LK.getAsset('BuyBall50', {
- size: 80,
- fill: 0xFFFFFF,
- anchorX: 0.5,
- anchorY: 0,
- y: 0,
- x: -400
-});
-var normalCostText = new Text2('$' + BALL_COST.toString(), {
- size: 50,
- fill: 0xFFFFFF
-});
-normalCostText.anchor.set(0.5, 0);
-normalCostText.y = 100;
-buyNormalButton.addChild(normalCostText);
-buyNormalButton.addChild(buyNormalButton.attachAsset('ball', {
- anchorX: 0.5,
- anchorY: -0.5,
- scaleX: 0.5,
- scaleY: 0.5
-}));
-buyNormalButton.down = function () {
- if (score >= BALL_COST) {
- score -= BALL_COST;
+// Ball Purchase Buttons
+var ballButtons = {};
+function createBallButton(type, x, cost, asset, prevTier) {
+ var button = LK.getAsset('BuyBall50', {
+ size: 80,
+ fill: 0xFFFFFF,
+ anchorX: 0.5,
+ anchorY: 0,
+ y: 0,
+ x: x
+ });
+ var costText = new Text2('$' + cost, {
+ size: 50,
+ fill: 0xFFFFFF
+ });
+ costText.anchor.set(0.5, 0);
+ costText.y = 100;
+ button.addChild(costText);
+ button.addChild(button.attachAsset(asset, {
+ anchorX: 0.5,
+ anchorY: -0.5,
+ scaleX: 0.5,
+ scaleY: 0.5
+ }));
+ button.down = function () {
+ if (!unlockedTiers[type] || score < cost) {
+ return;
+ }
+ score -= cost;
scoreTxt.setText('$' + score.toString());
- createBall('normal');
- }
-};
-hud.addChild(buyNormalButton);
-var buySplashButton = LK.getAsset('BuyBall50', {
- size: 80,
- fill: 0xFFFFFF,
- anchorX: 0.5,
- anchorY: 0,
- y: 0,
- x: -280
-});
-var splashCostText = new Text2('$' + upgrades.splashBallCost.toString(), {
- size: 50,
- fill: 0xFFFFFF
-});
-splashCostText.anchor.set(0.5, 0);
-splashCostText.y = 100;
-buySplashButton.addChild(splashCostText);
-buySplashButton.addChild(buySplashButton.attachAsset('splashBall', {
- anchorX: 0.5,
- anchorY: -0.5,
- scaleX: 0.5,
- scaleY: 0.5
-}));
-buySplashButton.down = function () {
- if (score >= upgrades.splashBallCost) {
- score -= upgrades.splashBallCost;
- scoreTxt.setText('$' + score.toString());
- createBall('splash');
- }
-};
-hud.addChild(buySplashButton);
-// Button to clear local storage
+ createBall(type);
+ if (!unlockedTiers[type]) {
+ unlockedTiers[type] = true;
+ storage.unlockedTiers = unlockedTiers;
+ updateButtonStates();
+ }
+ };
+ button.updateState = function () {
+ var isEnabled = (prevTier ? unlockedTiers[prevTier] : true) && score >= cost;
+ button.tint = isEnabled ? 0xFFFFFF : 0x666666; // White if enabled, grey if locked
+ 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('BuyBall50', {
size: 80,
fill: 0xFFFFFF,
anchorX: 0.5,
@@ -353,17 +348,15 @@
});
clearStorageText.anchor.set(0.5, 0);
clearStorageText.y = 100;
clearStorageButton.addChild(clearStorageText);
-clearStorageButton.down = function () {
- clearLocalStorage();
-};
+clearStorageButton.down = clearLocalStorage;
hud.addChild(clearStorageButton);
-// Bottom: Upgrade Buttons
var bottomHud = new Container();
bottomHud.y = GAME_HEIGHT - 150;
game.addChild(bottomHud);
-function createUpgradeButton(labelPrefix, x, costKey, upgradeKey, baseCost, iconType) {
+var upgradeButtons = {};
+function createUpgradeButton(labelPrefix, x, costKey, upgradeKey, baseCost, iconType, prevTier) {
var button = LK.getAsset('BuyBall50', {
size: 80,
fill: 0xFFFFFF,
anchorX: 0.5,
@@ -393,32 +386,55 @@
}));
}
button.down = function () {
var cost = baseCost * upgrades[upgradeKey];
- if (score >= cost) {
- 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];
- }
- });
+ if (!unlockedTiers[upgradeKey.split('Speed')[0].split('Power')[0]] || 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];
+ }
+ });
};
+ button.updateState = function () {
+ var isEnabled = (prevTier ? unlockedTiers[prevTier] : true) && score >= baseCost * upgrades[upgradeKey];
+ button.tint = isEnabled ? 0xFFFFFF : 0x666666;
+ button.interactive = isEnabled;
+ };
bottomHud.addChild(button);
+ upgradeButtons[upgradeKey] = button;
}
-// Upgrade buttons with icons for ball-specific upgrades
-createUpgradeButton('Speed', GAME_WIDTH / 2 - 480, 'normalSpeedCost', 'normalSpeed', 50, 'ball');
-createUpgradeButton('Power', GAME_WIDTH / 2 - 360, 'normalPowerCost', 'normalPower', 75, 'ball');
-createUpgradeButton('Speed', GAME_WIDTH / 2 - 240, 'splashSpeedCost', 'splashSpeed', 50, 'splashBall');
-createUpgradeButton('Power', GAME_WIDTH / 2 - 120, 'splashPowerCost', 'splashPower', 75, 'splashBall');
-createUpgradeButton('Click', GAME_WIDTH / 2, 'clickCost', 'clickDamage', 25, null); // No icon for Click
+// Extended Upgrade Buttons with tiered unlocking
+createUpgradeButton('Speed', GAME_WIDTH / 2 - 600, 'normalSpeedCost', 'normalSpeed', 50, 'ball', null);
+createUpgradeButton('Power', GAME_WIDTH / 2 - 480, 'normalPowerCost', 'normalPower', 75, 'ball', null);
+createUpgradeButton('Speed', GAME_WIDTH / 2 - 360, 'splashSpeedCost', 'splashSpeed', 50, 'splashBall', 'normal');
+createUpgradeButton('Power', GAME_WIDTH / 2 - 240, 'splashPowerCost', 'splashPower', 75, 'splashBall', 'normal');
+createUpgradeButton('Speed', GAME_WIDTH / 2 - 120, 'sniperSpeedCost', 'sniperSpeed', 75, 'sniperBall', 'splash');
+createUpgradeButton('Power', GAME_WIDTH / 2, 'sniperPowerCost', 'sniperPower', 100, 'sniperBall', 'splash');
+createUpgradeButton('Speed', GAME_WIDTH / 2 + 120, 'scatterSpeedCost', 'scatterSpeed', 50, 'scatterBall', 'sniper');
+createUpgradeButton('Power', GAME_WIDTH / 2 + 240, 'scatterPowerCost', 'scatterPower', 75, 'scatterBall', 'sniper');
+createUpgradeButton('Click', GAME_WIDTH / 2 + 360, 'clickCost', 'clickDamage', 25, null, null);
// 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)) {
@@ -446,8 +462,34 @@
});
}
});
}
+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;
}
@@ -568,8 +610,14 @@
}
}
balls.push(ball);
game.addChild(ball);
+ // Unlock the next tier when a ball is bought
+ if (!unlockedTiers[type]) {
+ unlockedTiers[type] = true;
+ storage.unlockedTiers = unlockedTiers;
+ updateButtonStates();
+ }
}
game.update = function () {
for (var i = balls.length - 1; i >= 0; i--) {
var ball = balls[i];
@@ -583,9 +631,9 @@
if (level === Object.keys(levelConfig).length) {
LK.showGameOver();
} else {
level += 1;
- storage.level = level; // Persist level to storage
+ storage.level = level;
levelTxt.setText('Level: ' + level);
createBricks();
}
}
@@ -593,8 +641,9 @@
score -= BALL_COST;
scoreTxt.setText('$' + score.toString());
createBall();
}
+ updateButtonStates(); // Update button states each frame
};
game.down = function (x, y, obj) {
if (!bricks || !Array.isArray(bricks)) {
return;
@@ -613,5 +662,6 @@
}
};
// Initialize game elements
createBricks();
-createBall();
\ No newline at end of file
+createBall();
+updateButtonStates(); // Initial button state update
\ No newline at end of file