User prompt
Make after every level motre boxes spawn
User prompt
More boxes spawn
User prompt
Make slightly more boxes spawn
User prompt
Please fix the bug: 'RangeError: Maximum call stack size exceeded.' in or related to this line: 'var explosion = game.addChild(LK.getAsset('explosion', {' Line Number: 100
User prompt
Make everything huge
User prompt
Make explosive enemies that explode when hit and the explosion destroys all enemies next to it. Explosive enemies are 1 in10enemies
User prompt
Please fix the bug: 'TypeError: null is not an object (evaluating 'enemy.y')' in or related to this line: 'if (enemy.y > gameHeight + 100) {' Line Number: 414
User prompt
Make explosive boxes that exploded when hot ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make powerups rarer
User prompt
Snake the bullets reach further
User prompt
Make it so you always shoot 3 bullets at once and have powerups give you 5 bullets
User prompt
Make less enemies spawn
User prompt
Make more boxes spawn
Code edit (1 edits merged)
Please save this source code
User prompt
CubeBlast Shooter
Initial prompt
Make a box shooter game
/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
	highScore: 0,
	level: 1
});
/**** 
* Classes
****/ 
var Bullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = -25;
	self.power = 1;
	self.active = true;
	self.update = function () {
		if (self.active) {
			self.y += self.speed;
		}
	};
	self.deactivate = function () {
		self.active = false;
		self.visible = false;
	};
	return self;
});
var Enemy = Container.expand(function (type, level) {
	var self = Container.call(this);
	self.type = type || 'normal';
	self.level = level || 1;
	var assetId;
	if (self.type === 'fast') {
		assetId = 'enemyBoxFast';
		self.speed = 3 + level * 0.3;
		self.health = 1;
		self.points = 20;
	} else if (self.type === 'tough') {
		assetId = 'enemyBoxTough';
		self.speed = 1 + level * 0.2;
		self.health = 3;
		self.points = 30;
	} else {
		assetId = 'enemyBox';
		self.speed = 2 + level * 0.2;
		self.health = 1;
		self.points = 10;
	}
	var enemyGraphics = self.attachAsset(assetId, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Add some randomness to movement
	self.moveType = Math.floor(Math.random() * 3);
	self.moveOffset = 0;
	self.moveSpeed = 1 + Math.random() * 2;
	self.startX = 0;
	self.heat = 0;
	self.isHeatingUp = false;
	self.isExploding = false;
	self.neighborChecked = false;
	self.hit = function () {
		LK.getSound('hit').play();
		self.health--;
		if (!self.isHeatingUp && !self.isExploding) {
			self.heatUp();
		}
		if (self.health <= 0) {
			self.explode();
			return true;
		} else {
			// Flash the enemy
			LK.effects.flashObject(self, 0xFFFFFF, 200);
			return false;
		}
	};
	self.heatUp = function () {
		self.isHeatingUp = true;
		self.heat = 0;
		// Start heating with orange color
		tween(enemyGraphics, {
			tint: 0xFF8C00
		}, {
			duration: 1000,
			onFinish: function onFinish() {
				// Transition to red hot
				tween(enemyGraphics, {
					tint: 0xFF0000
				}, {
					duration: 1000,
					onFinish: function onFinish() {
						if (!self.isExploding) {
							self.explode();
						}
					}
				});
			}
		});
	};
	self.explode = function () {
		if (self.isExploding) {
			return;
		}
		self.isExploding = true;
		LK.getSound('explosion').play();
		// Visual explosion effect
		tween(enemyGraphics, {
			alpha: 0.2,
			scaleX: 3,
			scaleY: 3,
			tint: 0xFFFF00
		}, {
			duration: 300,
			onFinish: function onFinish() {
				// Check for chain reaction with nearby enemies
				if (!self.neighborChecked) {
					self.neighborChecked = true;
					self.chainReaction();
				}
				// Sometimes drop a powerup (3% chance - made rarer)
				if (Math.random() < 0.03) {
					var powerUp = new PowerUp();
					powerUp.x = self.x;
					powerUp.y = self.y;
					powerUps.push(powerUp);
					game.addChild(powerUp);
				}
			}
		});
	};
	self.chainReaction = function () {
		// Find nearby enemies to trigger chain explosion
		for (var i = 0; i < enemies.length; i++) {
			var otherEnemy = enemies[i];
			if (otherEnemy !== self && !otherEnemy.isExploding && !otherEnemy.isHeatingUp) {
				// Calculate distance between enemies
				var dx = otherEnemy.x - self.x;
				var dy = otherEnemy.y - self.y;
				var distance = Math.sqrt(dx * dx + dy * dy);
				// If close enough, heat up this enemy too
				if (distance < 200) {
					otherEnemy.heatUp();
				}
			}
		}
	};
	self.update = function () {
		self.y += self.speed;
		// Side-to-side movement based on moveType
		if (self.moveType === 1) {
			// Sine wave
			self.moveOffset += 0.05;
			self.x = self.startX + Math.sin(self.moveOffset) * 150;
		} else if (self.moveType === 2) {
			// Zigzag
			self.moveOffset += self.moveSpeed * 0.05;
			if (self.moveOffset > 1 || self.moveOffset < -1) {
				self.moveSpeed *= -1;
			}
			self.x += self.moveSpeed * 3;
		}
	};
	return self;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	var playerBody = self.attachAsset('playerCharacter', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var playerGun = self.attachAsset('playerGun', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: -30
	});
	self.width = playerBody.width;
	self.height = playerBody.height;
	self.fireCooldown = 0;
	self.fireRate = 10;
	self.powerLevel = 1;
	self.powerUpTimer = 0;
	self.shootBullet = function () {
		if (self.fireCooldown <= 0) {
			LK.getSound('shoot').play();
			// Create center bullet
			var bullet = new Bullet();
			bullet.x = self.x;
			bullet.y = self.y - 40;
			bullets.push(bullet);
			game.addChild(bullet);
			// Always create side bullets for 3-bullet shot
			var bulletLeft = new Bullet();
			bulletLeft.x = self.x - 30;
			bulletLeft.y = self.y - 30;
			bullets.push(bulletLeft);
			game.addChild(bulletLeft);
			var bulletRight = new Bullet();
			bulletRight.x = self.x + 30;
			bulletRight.y = self.y - 30;
			bullets.push(bulletRight);
			game.addChild(bulletRight);
			// Add 2 more outer bullets when powered up (5 total)
			if (self.powerLevel > 1) {
				var bulletFarLeft = new Bullet();
				bulletFarLeft.x = self.x - 60;
				bulletFarLeft.y = self.y - 20;
				bullets.push(bulletFarLeft);
				game.addChild(bulletFarLeft);
				var bulletFarRight = new Bullet();
				bulletFarRight.x = self.x + 60;
				bulletFarRight.y = self.y - 20;
				bullets.push(bulletFarRight);
				game.addChild(bulletFarRight);
			}
			self.fireCooldown = self.fireRate;
		}
	};
	self.activatePowerUp = function () {
		self.powerLevel = 2;
		self.powerUpTimer = 300; // 5 seconds at 60fps
		tween(playerBody, {
			tint: 0x3D9970
		}, {
			duration: 200
		});
	};
	self.update = function () {
		if (self.fireCooldown > 0) {
			self.fireCooldown--;
		}
		// Auto fire
		self.shootBullet();
		// Handle power-up timer
		if (self.powerUpTimer > 0) {
			self.powerUpTimer--;
			if (self.powerUpTimer <= 0) {
				self.powerLevel = 1;
				tween(playerBody, {
					tint: 0xFFFFFF
				}, {
					duration: 200
				});
			}
		}
	};
	return self;
});
var PowerUp = Container.expand(function () {
	var self = Container.call(this);
	var powerUpGraphics = self.attachAsset('powerUp', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 5;
	self.rotation = 0;
	self.update = function () {
		self.y += self.speed;
		self.rotation += 0.1;
		powerUpGraphics.rotation = self.rotation;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x001F3F
});
/**** 
* Game Code
****/ 
// Game variables
var player;
var bullets = [];
var enemies = [];
var powerUps = [];
var level = storage.level || 1;
var spawnCooldown = 60;
var score = 0;
var combo = 0;
var comboTimer = 0;
var gameWidth = 2048;
var gameHeight = 2732;
// Set up the game scene
function setupGame() {
	// Create player
	player = new Player();
	player.x = gameWidth / 2;
	player.y = gameHeight - 150;
	game.addChild(player);
	// Set up UI
	setupUI();
	// Start music
	LK.playMusic('gameMusic', {
		fade: {
			start: 0,
			end: 0.4,
			duration: 1000
		}
	});
}
// Set up UI elements
function setupUI() {
	// Score text
	var scoreText = new Text2('Score: 0', {
		size: 80,
		fill: 0xFFFFFF
	});
	scoreText.anchor.set(0, 0);
	scoreText.x = 120;
	scoreText.y = 30;
	LK.gui.topLeft.addChild(scoreText);
	// Level text
	var levelText = new Text2('Level: ' + level, {
		size: 80,
		fill: 0xFFFFFF
	});
	levelText.anchor.set(1, 0);
	levelText.x = -30;
	levelText.y = 30;
	LK.gui.topRight.addChild(levelText);
	// Combo text
	var comboText = new Text2('', {
		size: 100,
		fill: 0xFFDC00
	});
	comboText.anchor.set(0.5, 0);
	comboText.y = 150;
	LK.gui.top.addChild(comboText);
	// Update function for UI
	LK.setInterval(function () {
		scoreText.setText('Score: ' + score);
		levelText.setText('Level: ' + level);
		if (combo > 1) {
			comboText.setText('Combo x' + combo + '!');
			comboText.alpha = 1;
		} else {
			comboText.alpha *= 0.95;
		}
	}, 33);
}
// Spawn an enemy
function spawnEnemy() {
	var types = ['normal', 'normal', 'normal', 'fast', 'tough']; // Weighted types
	// Determine how many enemies to spawn at once (1-2 based on level, reduced from 1-3)
	var spawnCount = Math.min(2, 1 + Math.floor(level / 5));
	for (var i = 0; i < spawnCount; i++) {
		var type = types[Math.floor(Math.random() * types.length)];
		var enemy = new Enemy(type, level);
		enemy.x = 150 + Math.random() * (gameWidth - 300);
		enemy.y = -100 - i * 80; // Stagger vertical positions
		enemy.startX = enemy.x; // Store initial X for movement patterns
		enemies.push(enemy);
		game.addChild(enemy);
	}
}
// Update game state
game.update = function () {
	// Handle enemies
	if (spawnCooldown <= 0) {
		spawnEnemy();
		// Spawn rate increases with level, but much slower now
		spawnCooldown = Math.max(45, 90 - level * 2);
	} else {
		spawnCooldown--;
	}
	// Update combo timer
	if (comboTimer > 0) {
		comboTimer--;
		if (comboTimer <= 0) {
			combo = 0;
		}
	}
	// Random wave spawning (approximately every 15-20 seconds)
	if (LK.ticks % 900 === 0 || level > 5 && LK.ticks % 600 === 0) {
		// Create a wave of 3-5 enemies (reduced from 5-8)
		var waveSize = 3 + Math.floor(Math.random() * 3);
		for (var w = 0; w < waveSize; w++) {
			var waveEnemy = new Enemy(Math.random() < 0.3 ? 'fast' : 'normal', level);
			waveEnemy.x = 100 + w * (gameWidth - 200) / waveSize;
			waveEnemy.y = -100 - Math.random() * 200;
			waveEnemy.startX = waveEnemy.x;
			enemies.push(waveEnemy);
			game.addChild(waveEnemy);
		}
	}
	// Process enemies
	for (var i = enemies.length - 1; i >= 0; i--) {
		var enemy = enemies[i];
		// Check if enemy is past bottom
		if (enemy.y > gameHeight + 100) {
			// Reduce score
			score = Math.max(0, score - 50);
			// Remove enemy
			enemy.destroy();
			enemies.splice(i, 1);
			// Flash screen
			LK.effects.flashScreen(0xFF0000, 300);
			continue;
		}
		// Check bullet collisions
		for (var j = bullets.length - 1; j >= 0; j--) {
			var bullet = bullets[j];
			if (bullet.active && bullet.intersects(enemy)) {
				// Handle hit
				var destroyed = enemy.hit();
				if (destroyed) {
					// Add score
					var pointsEarned = enemy.points * (1 + combo * 0.1);
					score += Math.floor(pointsEarned);
					// Update combo
					combo++;
					comboTimer = 60; // 1 second
					// Check for level up
					if (score > level * 1000) {
						level++;
						storage.level = level;
						LK.effects.flashScreen(0x00FF00, 500);
					}
					// Update high score
					if (score > storage.highScore) {
						storage.highScore = score;
					}
					// Remove enemy after explosion animation completes
					LK.setTimeout(function () {
						// Only destroy if the enemy still exists in the array
						if (enemies.indexOf(enemy) !== -1) {
							enemy.destroy();
							enemies.splice(enemies.indexOf(enemy), 1);
						}
					}, 300);
					// Mark as destroyed to prevent multiple hits
					enemies[i] = null;
					enemies.splice(i, 1, enemies[i]);
				}
				// Remove bullet
				bullet.deactivate();
				bullets.splice(j, 1);
				break;
			}
		}
	}
	// Process power-ups
	for (var k = powerUps.length - 1; k >= 0; k--) {
		var powerUp = powerUps[k];
		// Check if power-up is past bottom
		if (powerUp.y > gameHeight + 100) {
			powerUp.destroy();
			powerUps.splice(k, 1);
			continue;
		}
		// Check collision with player
		if (powerUp.intersects(player)) {
			LK.getSound('powerup').play();
			player.activatePowerUp();
			powerUp.destroy();
			powerUps.splice(k, 1);
		}
	}
	// Remove bullets that are off-screen
	for (var l = bullets.length - 1; l >= 0; l--) {
		if (bullets[l].y < -100) {
			bullets[l].destroy();
			bullets.splice(l, 1);
		}
	}
	// Limit max number of bullets and enemies for performance
	while (bullets.length > 50) {
		bullets[0].destroy();
		bullets.shift();
	}
	while (enemies.length > 30) {
		enemies[0].destroy();
		enemies.shift();
	}
};
// Handle input
var isDragging = false;
game.down = function (x, y, obj) {
	isDragging = true;
	player.x = x;
};
game.move = function (x, y, obj) {
	if (isDragging) {
		player.x = x;
		// Keep player within screen bounds
		if (player.x < player.width / 2) {
			player.x = player.width / 2;
		} else if (player.x > gameWidth - player.width / 2) {
			player.x = gameWidth - player.width / 2;
		}
	}
};
game.up = function (x, y, obj) {
	isDragging = false;
};
// Initialize the game
setupGame(); ===================================================================
--- original.js
+++ change.js
@@ -59,11 +59,18 @@
 	self.moveType = Math.floor(Math.random() * 3);
 	self.moveOffset = 0;
 	self.moveSpeed = 1 + Math.random() * 2;
 	self.startX = 0;
+	self.heat = 0;
+	self.isHeatingUp = false;
+	self.isExploding = false;
+	self.neighborChecked = false;
 	self.hit = function () {
 		LK.getSound('hit').play();
 		self.health--;
+		if (!self.isHeatingUp && !self.isExploding) {
+			self.heatUp();
+		}
 		if (self.health <= 0) {
 			self.explode();
 			return true;
 		} else {
@@ -71,18 +78,76 @@
 			LK.effects.flashObject(self, 0xFFFFFF, 200);
 			return false;
 		}
 	};
+	self.heatUp = function () {
+		self.isHeatingUp = true;
+		self.heat = 0;
+		// Start heating with orange color
+		tween(enemyGraphics, {
+			tint: 0xFF8C00
+		}, {
+			duration: 1000,
+			onFinish: function onFinish() {
+				// Transition to red hot
+				tween(enemyGraphics, {
+					tint: 0xFF0000
+				}, {
+					duration: 1000,
+					onFinish: function onFinish() {
+						if (!self.isExploding) {
+							self.explode();
+						}
+					}
+				});
+			}
+		});
+	};
 	self.explode = function () {
+		if (self.isExploding) {
+			return;
+		}
+		self.isExploding = true;
 		LK.getSound('explosion').play();
-		LK.effects.flashObject(self, 0xFF0000, 300);
-		// Sometimes drop a powerup (3% chance - made rarer)
-		if (Math.random() < 0.03) {
-			var powerUp = new PowerUp();
-			powerUp.x = self.x;
-			powerUp.y = self.y;
-			powerUps.push(powerUp);
-			game.addChild(powerUp);
+		// Visual explosion effect
+		tween(enemyGraphics, {
+			alpha: 0.2,
+			scaleX: 3,
+			scaleY: 3,
+			tint: 0xFFFF00
+		}, {
+			duration: 300,
+			onFinish: function onFinish() {
+				// Check for chain reaction with nearby enemies
+				if (!self.neighborChecked) {
+					self.neighborChecked = true;
+					self.chainReaction();
+				}
+				// Sometimes drop a powerup (3% chance - made rarer)
+				if (Math.random() < 0.03) {
+					var powerUp = new PowerUp();
+					powerUp.x = self.x;
+					powerUp.y = self.y;
+					powerUps.push(powerUp);
+					game.addChild(powerUp);
+				}
+			}
+		});
+	};
+	self.chainReaction = function () {
+		// Find nearby enemies to trigger chain explosion
+		for (var i = 0; i < enemies.length; i++) {
+			var otherEnemy = enemies[i];
+			if (otherEnemy !== self && !otherEnemy.isExploding && !otherEnemy.isHeatingUp) {
+				// Calculate distance between enemies
+				var dx = otherEnemy.x - self.x;
+				var dy = otherEnemy.y - self.y;
+				var distance = Math.sqrt(dx * dx + dy * dy);
+				// If close enough, heat up this enemy too
+				if (distance < 200) {
+					otherEnemy.heatUp();
+				}
+			}
 		}
 	};
 	self.update = function () {
 		self.y += self.speed;
@@ -362,11 +427,19 @@
 					// Update high score
 					if (score > storage.highScore) {
 						storage.highScore = score;
 					}
-					// Remove enemy
-					enemy.destroy();
-					enemies.splice(i, 1);
+					// Remove enemy after explosion animation completes
+					LK.setTimeout(function () {
+						// Only destroy if the enemy still exists in the array
+						if (enemies.indexOf(enemy) !== -1) {
+							enemy.destroy();
+							enemies.splice(enemies.indexOf(enemy), 1);
+						}
+					}, 300);
+					// Mark as destroyed to prevent multiple hits
+					enemies[i] = null;
+					enemies.splice(i, 1, enemies[i]);
 				}
 				// Remove bullet
 				bullet.deactivate();
 				bullets.splice(j, 1);
:quality(85)/https://cdn.frvr.ai/680c3898fb8b66abf7d08294.png%3F3) 
 Box wooden. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/680c391efb8b66abf7d08298.png%3F3) 
 Military Tank with gun facing up. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/680c3a0efb8b66abf7d082b9.png%3F3) 
 Nothing. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/680c3a46fb8b66abf7d082bf.png%3F3) 
 Wooden box with car on front. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/680c3a74fb8b66abf7d082c7.png%3F3) 
 Steel box. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/680c3aa9fb8b66abf7d082ce.png%3F3) 
 Power up. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/680c3ad2fb8b66abf7d082d5.png%3F3) 
 Explosion. In-Game asset. 2d. High contrast. No shadows