User prompt
JJB asset spinning is too slow
User prompt
Speed up JJB asset spinning animation by making it 1.2x faster
User prompt
Speed up JJB asset spinning animation by making it 1.3x faster
User prompt
Speed up JJB asset spinning animation by making it 1.5x faster
User prompt
Speed up jjb spinning 2x faster
User prompt
If godmode is active and mario hit jjb asset then stop this jjb asset moving at here, spin 360 degress by horizontally for two times before dissapear it βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
If godmode is active and mario hit jjb asset then stop this jjb asset movement at here, spin horizontally 360 degress for two times before dissapear it βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
If godmode is active and mario hit jjb asset then spin jjb asset verticaly 360 degress for two times and before dissapear it βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Don't play the jjbe sound while godmode is active
User prompt
Remove duplicated JJBE PLAYING
User prompt
Play JJBE song if jjb asset hitted Mario
User prompt
Play JJBE song if jjb asset hurts Mario
User prompt
The enemy counter should always count one by one!
User prompt
Change the enemy2 spinning animation to a flashing fireflame animation βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Change the spinning animation to a flashing fireflame animation βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'lifePercentText.style.fill = 0x7FFF00; // Original green color' Line Number: 938
User prompt
Change life counter number color to orange if less than 51% live left
User prompt
Scale up the godmode counter number by a little
User prompt
Ensure enemies counter also count by one if godmode is active
User prompt
Ensure enemies counter count by one
User prompt
Ensure display player win animation if no more enemy left
User prompt
Ensure if no loading more enemies than play the player win animation.
User prompt
Reduce watermark size to the half
User prompt
Add a grey '@jzubora' watermark to the right bottom corner of the screen.
User prompt
Could you change the god mode animation to a shiny flashing fireflame
/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Define a class for enemies
var Enemy = Container.expand(function (enemyType) {
	var self = Container.call(this);
	var enemyGraphics = self.attachAsset(enemyType, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 5;
	self.enemyType = enemyType;
	// Apply spinning animation to 'ls' enemy type
	if (enemyType === 'ls') {
		// Start spinning animation in left (counter-clockwise) direction
		tween(enemyGraphics, {
			rotation: Math.PI * 2 * -1 // Negative for left/counter-clockwise direction
		}, {
			duration: 2000,
			// 2 seconds for a full rotation
			easing: tween.linear,
			repeat: Infinity,
			// Use Infinity instead of loop: true for continuous spinning
			loop: true // Continuous spinning
		});
	}
	self.update = function () {
		// Special behavior for ls asset - bounce down from top right
		if (self.enemyType === 'ls') {
			// Add vertical movement properties first time
			if (self.verticalSpeed === undefined) {
				self.verticalSpeed = 3; // Initial downward speed
				self.gravity = 0.1; // Gravity effect
				self.bounceStrength = 2; // How strong the bounce is
				// Start from top-right corner
				self.y = 100; // Near top
				self.x = 2048 + 100; // Off right edge
			}
			// Track if this asset is in the spinning out state
			if (self.spinningOut) {
				// Move toward right top corner
				var targetX = 2048 + 200;
				var targetY = -200;
				// Calculate direction vector
				var dirX = targetX - self.x;
				var dirY = targetY - self.y;
				// Normalize and apply speed
				var length = Math.sqrt(dirX * dirX + dirY * dirY);
				if (length > 0) {
					dirX = dirX / length * (self.spinSpeed || 15);
					dirY = dirY / length * (self.spinSpeed || 15);
				}
				// Move toward target
				self.x += dirX;
				self.y += dirY;
				// Increase rotation speed
				self.children[0].rotation += 0.2;
			} else {
				// Normal behavior when not spinning out
				// Apply gravity to vertical speed
				self.verticalSpeed += self.gravity;
				self.y += self.verticalSpeed;
				// Bounce when hitting bottom at 3/4 of the screen height instead of center
				if (self.y > 2732 * 0.75) {
					// Bounce at 3/4 screen height
					self.y = 2732 * 0.75;
					self.verticalSpeed = -self.verticalSpeed * (self.bounceStrength * 0.3); // Even lower bounce power
					// Reduce bounce strength much more quickly
					self.bounceStrength *= 0.5;
				}
				// Horizontal movement
				self.x -= self.speed;
			}
		} else if (self.enemyType === 'enemy3') {
			// Special behavior for enemy3 - attack from right bottom corner
			if (self.initialPosition === undefined) {
				// Set initial position at right bottom corner
				self.x = 2048 + 100; // Off right edge
				self.y = 2732 - 550; // Bottom of screen with small margin, moved up by 450 units
				self.initialPosition = true;
			}
			// Move diagonally up-left (towards Mario)
			self.x -= self.speed * 1.2;
			self.y -= self.speed * 0.6;
		} else {
			// Original behavior for other enemy types
			self.x -= self.speed;
		}
		// Destroy when off screen
		if (self.x < -50) {
			self.destroy();
		}
	};
	return self; // Return self to make the class inheritable
});
// Define a class for displaying the God Mode text
var GodModeText = Container.expand(function () {
	var self = Container.call(this);
	// Create the text
	var godModeText = new Text2('GOD MODE', {
		size: 80,
		fill: 0xFF8C00 // Orange color
	});
	godModeText.anchor.set(0.5, 0.5);
	self.addChild(godModeText);
	// Initialize with invisible state
	godModeText.alpha = 0;
	// Create timer text
	var timerText = new Text2('', {
		size: 80,
		fill: 0xFF8C00 // Orange color for timer
	});
	timerText.anchor.set(0.5, 0.5);
	timerText.y = 80; // Position below the GOD MODE text
	self.addChild(timerText);
	// Initialize timer value
	self.timerValue = 5; // 5 seconds duration
	self.timerInterval = null;
	// Method to show the animation
	self.showAnimation = function () {
		// Play god mode sound
		LK.getSound('godmode').play();
		// Stop any existing animations
		tween.stop(godModeText);
		// Reset and start the timer
		self.timerValue = 5;
		timerText.setText(self.timerValue);
		timerText.alpha = 1;
		// Clear any existing timer
		if (self.timerInterval) {
			LK.clearInterval(self.timerInterval);
		}
		// Start countdown timer
		self.timerInterval = LK.setInterval(function () {
			self.timerValue -= 1;
			timerText.setText(self.timerValue);
			if (self.timerValue < 0) {
				LK.clearInterval(self.timerInterval);
				self.timerInterval = null;
			}
		}, 1000);
		// Animate in with fireflame effect
		godModeText.tint = 0xFF5500; // Orange-red fire color
		tween(godModeText, {
			alpha: 1,
			scaleX: 1.2,
			scaleY: 1.2
		}, {
			duration: 300,
			easing: tween.elasticOut,
			onFinish: function onFinish() {
				// Create flickering flame animation
				function fireflameFlicker() {
					// Random fire colors between orange-red and yellow
					var fireColors = [0xFF5500, 0xFF8800, 0xFFAA00, 0xFFFF00];
					var randomColor = fireColors[Math.floor(Math.random() * fireColors.length)];
					// Random scale for fire flicker effect
					var randomScale = 1.0 + Math.random() * 0.3;
					// Apply the flame effect
					tween(godModeText, {
						tint: randomColor,
						scaleX: randomScale,
						scaleY: randomScale,
						alpha: 0.7 + Math.random() * 0.3
					}, {
						duration: 100 + Math.random() * 150,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							// Continue the flame effect if still visible
							if (godModeText.alpha > 0) {
								fireflameFlicker();
							}
						}
					});
				}
				// Start the flame flicker effect
				fireflameFlicker();
				// Hide after 3 seconds
				LK.setTimeout(function () {
					// Stop the pulse animation
					tween.stop(godModeText);
					// Stop and hide the timer
					if (self.timerInterval) {
						LK.clearInterval(self.timerInterval);
						self.timerInterval = null;
					}
					tween(timerText, {
						alpha: 0
					}, {
						duration: 300,
						easing: tween.easeIn
					});
					// Animate out
					tween(godModeText, {
						alpha: 0,
						scaleX: 0.8,
						scaleY: 0.8
					}, {
						duration: 500,
						easing: tween.easeIn
					});
				}, 3000);
			}
		});
	};
	return self;
});
// Define a class for the life counter
var LifeCounter = Container.expand(function () {
	var self = Container.call(this);
	// Create a simple white line instead of using an asset
	var lineGraphics = LK.getAsset('enemy2', {
		anchorX: 0.0,
		anchorY: 0.0,
		scaleX: 2048,
		scaleY: 10,
		tint: 0xFFFFFF // White color
	});
	self.addChild(lineGraphics);
	self.width = 2048; // Full width
	self.update = function () {
		// Update the width of the line based on Mario's life
		lineGraphics.scale.x = 2048 * Mario.life;
	};
});
// Define a class for the dragon ball lightning effect
var LightningEffect = Container.expand(function () {
	var self = Container.call(this);
	// Set active status flag
	self.isActive = false;
	// Create lightning bolts
	self.bolts = [];
	var colors = [0xFFFF00, 0xFFFF00, 0xFFFF00, 0xFFFF00];
	// Create multiple lightning bolts around Mario
	for (var i = 0; i < 5; i++) {
		var bolt = self.attachAsset('enemy2', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 25 + Math.random() * 10,
			scaleY: 25 + Math.random() * 10
		});
		bolt.tint = colors[Math.floor(Math.random() * colors.length)];
		bolt.alpha = 0; // Start with invisible bolts
		bolt.rotation = Math.random() * Math.PI * 2;
		bolt.distance = 80 + Math.random() * 40;
		bolt.speed = 0.1 + Math.random() * 0.1;
		bolt.originalScale = {
			x: bolt.scale.x,
			y: bolt.scale.y
		};
		self.bolts.push(bolt);
	}
	// Animate the lightning
	self.animate = function () {
		// Stop any existing animations
		for (var i = 0; i < self.bolts.length; i++) {
			tween.stop(self.bolts[i]);
		}
		// Start new animations
		for (var i = 0; i < self.bolts.length; i++) {
			var bolt = self.bolts[i];
			// Randomize the bolt appearance
			bolt.rotation = Math.random() * Math.PI * 2;
			bolt.scale.x = bolt.originalScale.x * (0.8 + Math.random() * 0.4);
			bolt.scale.y = bolt.originalScale.y * (0.8 + Math.random() * 0.4);
			// Animate the bolt with pulse effect
			tween(bolt, {
				alpha: 0.2 + Math.random() * 0.5,
				scaleX: bolt.originalScale.x * (0.7 + Math.random() * 0.6),
				scaleY: bolt.originalScale.y * (0.7 + Math.random() * 0.6)
			}, {
				duration: 300 + Math.random() * 400,
				easing: tween.easeOut,
				onFinish: function () {
					// Create a callback closure to maintain the correct bolt reference
					var currentBolt = bolt;
					return function () {
						// Animate back
						tween(currentBolt, {
							alpha: 0.6 + Math.random() * 0.4,
							scaleX: currentBolt.originalScale.x * (0.9 + Math.random() * 0.3),
							scaleY: currentBolt.originalScale.y * (0.9 + Math.random() * 0.3)
						}, {
							duration: 300 + Math.random() * 400,
							easing: tween.easeIn
						});
					};
				}()
			});
		}
	};
	self.update = function () {
		// Position the lightning bolts around Mario
		for (var i = 0; i < self.bolts.length; i++) {
			var bolt = self.bolts[i];
			var angle = bolt.rotation + self.parent.rotation + bolt.speed * LK.ticks;
			bolt.x = Math.cos(angle) * bolt.distance;
			bolt.y = Math.sin(angle) * bolt.distance;
			// Make bolts invisible when effect is not active
			if (!self.isActive) {
				bolt.alpha = 0;
			}
			// Ensure bolts remain visible when effect is active
			else if (self.isActive && bolt.alpha < 0.7) {
				bolt.alpha = 0.7 + Math.random() * 0.3;
			}
		}
		// Periodically refresh animations only when not in active state
		if (LK.ticks % 30 === 0 && self.isActive) {
			self.animate();
		}
	};
	return self;
});
//<Assets used in the game will automatically appear here>
// Define a class for the player character
var Player = Container.expand(function () {
	var self = Container.call(this);
	var MarioGraphics = self.attachAsset('Mario', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 5;
	// Add the lightning effect
	self.lightning = self.addChild(new LightningEffect());
	self.jumpHeight = 40;
	self.isJumping = false;
	self.velocityY = 0;
	self.update = function () {
		if (self.isJumping) {
			self.y += self.velocityY;
			self.velocityY += 0.7; // Decreased gravity effect by 30%
			if (self.y >= 2732 / 2) {
				// Ground level
				self.y = 2732 / 2;
				self.isJumping = false;
				self.velocityY = 0;
			}
		}
		// Update the lightning effect
		if (self.lightning) {
			self.lightning.update();
		}
	};
	self.jump = function () {
		if (!self.isJumping) {
			self.isJumping = true;
			self.velocityY = -self.jumpHeight;
			// Play jump sound
			LK.getSound('jump').play();
			// Activate lightning effect animation with a more intense glow when jumping, but only if lightning is already active
			if (self.lightning && self.lightning.isActive) {
				// Intensify the lightning effect
				for (var i = 0; i < self.lightning.bolts.length; i++) {
					var bolt = self.lightning.bolts[i];
					tween(bolt, {
						alpha: 0.9,
						scaleX: bolt.originalScale.x * 1.5,
						scaleY: bolt.originalScale.y * 1.5
					}, {
						duration: 300,
						easing: tween.elasticOut
					});
				}
				// Reset to normal after a short time
				LK.setTimeout(function () {
					self.lightning.animate();
				}, 500);
			}
		}
	};
});
// Define a class for power-ups
var PowerUp = Container.expand(function () {
	var self = Container.call(this);
	var powerGraphics = self.attachAsset('powerup', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 3;
	self.floatOffset = 0;
	self.collected = false;
	// Make power-up glow with tween animation and add shiny flashing effect
	tween(powerGraphics, {
		alpha: 0.7,
		tint: 0xffffff
	}, {
		duration: 1000,
		easing: tween.sinusoidalInOut,
		loop: true,
		yoyo: true
	});
	// Add shiny flashing effect
	function createShinyEffect() {
		// Tween to bright yellow-white (shiny effect)
		tween(powerGraphics, {
			tint: 0xffffff,
			alpha: 1,
			scaleX: 1.2,
			scaleY: 1.2
		}, {
			duration: 150,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Tween back to normal gold
				tween(powerGraphics, {
					tint: 0xffd700,
					alpha: 0.8,
					scaleX: 1.0,
					scaleY: 1.0
				}, {
					duration: 250,
					easing: tween.easeIn,
					onFinish: function onFinish() {
						// Schedule next flash after a shorter random delay
						LK.setTimeout(createShinyEffect, 300 + Math.random() * 400);
					}
				});
			}
		});
	}
	// Start the shiny effect sequence
	LK.setTimeout(createShinyEffect, 200 + Math.random() * 300);
	self.update = function () {
		// Move power-up from right to left
		self.x -= self.speed;
		// Floating up and down motion
		self.floatOffset += 0.05;
		self.y = self.originalY + Math.sin(self.floatOffset) * 20;
		// Remove if off screen
		if (self.x < -100) {
			self.destroy();
		}
	};
	return self;
});
// Define a class for displaying the SHARKNADO title
var SharknadoTitle = Container.expand(function () {
	var self = Container.call(this);
	// Create the text with chrome-silver-black styling
	var sharknadoText = new Text2('SHARKNADO!', {
		size: 240,
		fill: 0xDDDDDD,
		// Silver base color
		dropShadow: true,
		dropShadowColor: 0x333333,
		// Dark shadow for 3D effect
		dropShadowDistance: 3
	});
	// Set anchor to center horizontally
	sharknadoText.anchor.set(0.5, 0.5);
	self.addChild(sharknadoText);
	// Initialize as invisible
	self.visible = false;
	// Method to show the title
	self.show = function () {
		if (self.visible) return; // Already visible
		self.visible = true;
		// Clear any existing animations
		tween.stop(sharknadoText);
		// Reset and animate in
		sharknadoText.alpha = 0;
		sharknadoText.scale.set(0.5, 0.5);
		// Track original position for shake effect
		self.originalX = self.x;
		self.originalY = self.y;
		// Animate in with chrome shine effect
		tween(sharknadoText, {
			alpha: 1,
			scaleX: 1.1,
			scaleY: 1.1
		}, {
			duration: 500,
			easing: tween.elasticOut,
			onFinish: function onFinish() {
				// Add pulsing animation
				tween(sharknadoText, {
					scaleX: 1.0,
					scaleY: 1.0
				}, {
					duration: 800,
					easing: tween.sinusoidalInOut,
					yoyo: true,
					loop: true
				});
				// Start shaking animation
				self.startShaking();
			}
		});
	};
	// Method to hide the title
	self.hide = function () {
		if (!self.visible) return; // Already hidden
		// Stop any existing animations
		tween.stop(sharknadoText);
		// Stop shaking
		self.stopShaking();
		// Animate out
		tween(sharknadoText, {
			alpha: 0,
			scaleX: 0.8,
			scaleY: 0.8
		}, {
			duration: 300,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.visible = false;
			}
		});
	};
	// Start shaking animation for SHARKNADO title
	self.startShaking = function () {
		// Clear any existing shake interval
		self.stopShaking();
		// Create new shake interval
		self.shakeInterval = LK.setInterval(function () {
			// Random offset for shake effect (more horizontal than vertical)
			var offsetX = (Math.random() - 0.5) * 20; // -10 to +10 pixels
			var offsetY = (Math.random() - 0.5) * 10; // -5 to +5 pixels
			// Apply shake
			self.x = self.originalX + offsetX;
			self.y = self.originalY + offsetY;
			// Apply slight rotation for more dramatic effect
			sharknadoText.rotation = (Math.random() - 0.5) * 0.05; // Small random rotation
		}, 50); // Shake every 50ms for realistic earthquake effect
	};
	// Stop shaking animation
	self.stopShaking = function () {
		if (self.shakeInterval) {
			LK.clearInterval(self.shakeInterval);
			self.shakeInterval = null;
			// Reset position and rotation
			if (self.originalX !== undefined) {
				self.x = self.originalX;
				self.y = self.originalY;
				sharknadoText.rotation = 0;
			}
		}
	};
	return self;
});
// Define a class for the TB popup
var TbPopup = Container.expand(function () {
	var self = Container.call(this);
	// Get TB asset
	var tbGraphics = self.attachAsset('tb', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Initialize as invisible
	self.alpha = 0;
	self.visible = false;
	// Method to show the popup
	self.show = function () {
		if (self.visible) return; // Already visible
		// Stop any existing animations
		tween.stop(self);
		// Reset and make visible
		self.visible = true;
		self.scale.set(0.2, 0.2);
		// Animate in
		tween(self, {
			alpha: 1,
			scaleX: 1.0,
			scaleY: 1.0
		}, {
			duration: 500,
			easing: tween.elasticOut
		});
	};
	// Method to hide the popup
	self.hide = function () {
		if (!self.visible) return; // Already hidden
		// Animate out
		tween(self, {
			alpha: 0,
			scaleX: 0.2,
			scaleY: 0.2
		}, {
			duration: 300,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				self.visible = false;
			}
		});
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x87CEEB // Sky blue background
});
/**** 
* Game Code
****/ 
// Track time of last wave spawn to ensure no more than 4 seconds of idle time
game.lastSpawnTime = 0;
var background = game.addChild(LK.getAsset('background', {
	anchorX: 0,
	anchorY: 0
}));
background.x = 0;
background.y = 0;
// Play background music
LK.playMusic('music1', {
	loop: true
});
// Initialize player
var Mario = game.addChild(new Player());
Mario.x = 2048 / 2 - 200; // Position Mario 200 units to the left of center
Mario.y = 2732 / 2;
Mario.life = 1; // Initialize Mario's life to 1 (100%)
// Initialize the life counter and add it to the game
var lifeCounter = game.addChild(new LifeCounter());
lifeCounter.y = 0; // Position it at the top of the screen
// Create TB popup for enemy3
var tbPopup = game.addChild(new TbPopup());
tbPopup.x = 160; // Position on the left side, moved left by 40 units
tbPopup.y = 2732 / 2 - 777; // Center vertically, then move up by 777 units
// Create life percentage text
var lifePercentText = new Text2('100%', {
	size: 40,
	fill: 0x7FFF00 // Bright neon green to match the life bar
});
// Add the life percentage text to the GUI
LK.gui.topRight.addChild(lifePercentText);
// Position the text
lifePercentText.anchor.set(1, 0); // Right align
lifePercentText.x = -20; // Add right margin
lifePercentText.y = 20; // Add top margin
// Initialize enemies
var enemies = [];
var enemySpawnInterval = 100;
var enemySpawnCounter = 0;
// Initialize power-ups
var powerups = [];
var powerupSpawnInterval = 300;
var powerupSpawnCounter = 0;
// Create GodModeText instance
var godModeText = game.addChild(new GodModeText());
godModeText.x = 2048 / 2; // Center horizontally
godModeText.y = 2732 / 2 - 1050; // Position above the center (moved up by 650 units)
// Create a new Text2 object to display the score
var scoreLabelText = new Text2('Defeated enemies: ', {
	size: 40,
	fill: 0xFFFFFF
});
var scoreText = new Text2('0', {
	size: 50,
	fill: 0xFFFFFF
});
// Create the SHARKNADO title
var sharknadoTitle = game.addChild(new SharknadoTitle());
sharknadoTitle.x = 2048 / 2; // Center horizontally
sharknadoTitle.y = scoreText.y + 200; // Position further below the score text (moved down by 100 units)
// Add the score label and text to the game GUI at the top center of the screen
LK.gui.top.addChild(scoreLabelText);
LK.gui.top.addChild(scoreText);
// Position the label and score text
scoreLabelText.anchor.set(1, 0); // Right align the label
scoreText.anchor.set(0, 0); // Left align the score
scoreLabelText.x = 2048 / 2 - 880; // Position to the left of center, moved 880 units left
scoreLabelText.y = 20; // Add a small top margin
scoreText.x = 2048 / 2 - 840; // Position to the right of center, moved 840 units left
scoreText.y = 10; // Add a small top margin
// Set up a regular interval to check and ensure enemy spawning
var enemyWaveScheduler = LK.setInterval(function () {
	// If there are no enemies on screen for more than 3 seconds, spawn a new wave
	if (enemies.length === 0 && LK.ticks - game.lastSpawnTime > 180) {
		// 3 seconds at 60fps
		// Reset spawn counter to trigger spawn on next update
		enemySpawnCounter = enemySpawnInterval;
	}
}, 1000); // Check every second
// Handle game updates
game.update = function () {
	Mario.update();
	// Spawn enemies
	enemySpawnCounter++;
	// Define maximum number of active enemies allowed at once
	var maxEnemies = Math.min(40, LK.getScore() + 5); // Scales with score up to 40 enemies
	// Track time since last enemy spawn
	if (!game.lastSpawnTime) {
		game.lastSpawnTime = LK.ticks;
	}
	// Calculate time passed since last spawn (in frames, 60fps means 240 frames = 4 seconds)
	var framesSinceLastSpawn = LK.ticks - game.lastSpawnTime;
	// Force spawn if more than 4 seconds have passed without enemies
	var forceSpawn = framesSinceLastSpawn > 240;
	if (enemySpawnCounter >= enemySpawnInterval && enemies.length < maxEnemies || forceSpawn && enemies.length === 0) {
		// Define enemy types
		var enemyTypes = ['enemy', 'enemy1', 'enemy2', 'enemy3', 'jjb', 'ls'];
		// Keep track of the last enemy type to avoid repetition
		if (!game.lastEnemyTypeIndex) {
			game.lastEnemyTypeIndex = -1;
		}
		// Reset last spawn time
		game.lastSpawnTime = LK.ticks;
		// Only spawn one enemy at a time
		var _spawnEnemy = function spawnEnemy() {
			// Check if we reached the maximum number of enemies
			if (enemies.length >= maxEnemies) {
				// Check if we've reached a permanent limit (meaning we can't spawn more enemies)
				if (maxEnemies >= 40 && LK.getScore() >= 35) {
					// If all current enemies are defeated, show win message
					if (enemies.length === 0) {
						LK.showYouWin();
					}
				}
				return; // Don't spawn more enemies if we reached the limit
			}
			// Check if we're already in process of spawning (avoid duplicate calls)
			if (game.isSpawningEnemy) {
				return; // Prevent multiple simultaneous spawns
			}
			game.isSpawningEnemy = true;
			// Get a new enemy type that is different from the last one
			var availableTypes = [];
			for (var t = 0; t < enemyTypes.length; t++) {
				// Skip enemy2 type which is too small to be visible (4x4)
				if (t !== game.lastEnemyTypeIndex && enemyTypes[t] !== 'enemy2') {
					availableTypes.push({
						index: t,
						type: enemyTypes[t]
					});
				}
			}
			// Randomly select from available types
			var selectedType = availableTypes[Math.floor(Math.random() * availableTypes.length)];
			game.lastEnemyTypeIndex = selectedType.index;
			var enemy = new Enemy(selectedType.type);
			enemy.x = 2048 + 100; // Fixed distance from edge of screen
			enemy.y = 2732 / 2;
			enemies.push(enemy);
			game.addChild(enemy);
			// Schedule the next enemy spawn with a fixed 1 second delay to ensure sequential spawning
			if (enemies.length < maxEnemies) {
				game.nextEnemyTimeout = LK.setTimeout(function () {
					// Force an enemy spawn by setting the spawn counter to threshold
					enemySpawnCounter = enemySpawnInterval;
					// Update last spawn time to now
					game.lastSpawnTime = LK.ticks;
					// Reset spawning flag to allow next enemy spawn
					game.isSpawningEnemy = false;
				}, 1000); // Exactly 1 second delay between spawns
			} else {
				// Reset spawning flag if we're not spawning more
				game.isSpawningEnemy = false;
			}
		};
		_spawnEnemy();
		// Randomize the spawn interval for the next enemy, but ensure it's not too long
		enemySpawnInterval = Math.floor(Math.random() * 120) + 30; // Reduced max interval
		enemySpawnCounter = 0;
	}
	// Spawn power-ups
	powerupSpawnCounter++;
	if (powerupSpawnCounter >= powerupSpawnInterval) {
		var powerup = new PowerUp();
		powerup.x = 2048 + 200; // Start a bit off screen
		powerup.y = 2732 / 2 - 200; // Above the players level
		powerup.originalY = powerup.y; // Store original Y for floating animation
		powerup.lastWasIntersecting = false; // For tracking intersection
		powerups.push(powerup);
		game.addChild(powerup);
		// Randomize the spawn interval for the next power-up
		powerupSpawnInterval = Math.floor(Math.random() * 400) + 300;
		powerupSpawnCounter = 0;
	}
	// Update enemies
	for (var j = enemies.length - 1; j >= 0; j--) {
		enemies[j].update();
		if (Mario.intersects(enemies[j])) {
			// Check if enemy is jjb type and play JJBE sound
			if (enemies[j].enemyType === 'jjb' && !enemies[j].jjbeSoundPlayed && !(Mario.lightning && Mario.lightning.isActive)) {
				// Play JJBE sound when Mario hits jjb asset and mark it as played
				// Only play if not in godmode
				LK.getSound('JJBE').play();
				enemies[j].jjbeSoundPlayed = true;
			}
			// Special handling for JJB assets during God mode - spin horizontally and disappear
			if (enemies[j].enemyType === 'jjb' && Mario.lightning && Mario.lightning.isActive) {
				// Start the spinning animation if not already spinning
				if (!enemies[j].spinningOut) {
					enemies[j].spinningOut = true;
					// Stop movement
					enemies[j].speed = 0;
					// Get the JJB asset graphic
					var jjbGraphic = enemies[j].children[0];
					// First horizontal 360 spin
					tween(jjbGraphic, {
						scaleX: -1 // Flip horizontally
					}, {
						duration: 150,
						// 0.15 second for first half spin
						easing: tween.linear,
						onFinish: function onFinish() {
							// Continue to full 360
							tween(jjbGraphic, {
								scaleX: 1 // Back to original
							}, {
								duration: 150,
								// 0.15 second for second half spin
								easing: tween.linear,
								onFinish: function onFinish() {
									// Second 360 spin
									tween(jjbGraphic, {
										scaleX: -1 // Flip horizontally again
									}, {
										duration: 150,
										// 0.15 second for third half spin
										easing: tween.linear,
										onFinish: function onFinish() {
											// Complete second 360
											tween(jjbGraphic, {
												scaleX: 1,
												// Back to original
												alpha: 0 // Fade out
											}, {
												duration: 150,
												// 0.15 second for final half spin and fade
												easing: tween.linear,
												onFinish: function onFinish() {
													// Remove the enemy after spinning
													enemies[j].destroy();
													enemies.splice(j, 1);
													// Add points for defeating enemy
													LK.setScore(LK.getScore() + 1);
													scoreText.setText(LK.getScore());
												}
											});
										}
									});
								}
							});
						}
					});
					// Mark as being handled to prevent other collision effects
					return;
				}
			}
			// Special handling for 'ls' or 'enemy3' assets during God mode
			if ((enemies[j].enemyType === 'ls' || enemies[j].enemyType === 'enemy3') && Mario.lightning && Mario.lightning.isActive) {
				// Start the spinning out animation if not already spinning
				if (!enemies[j].spinningOut) {
					enemies[j].spinningOut = true;
					enemies[j].spinSpeed = 15; // Speed at which it flies out
					// Play dog sound when ls or enemy3 starts spinning out
					LK.getSound('dog').play();
					// Increase rotation animation
					tween(enemies[j].children[0], {
						rotation: Math.PI * 10
					}, {
						duration: 2000,
						easing: tween.linear
					});
					// Add points for special effect
					LK.setScore(LK.getScore() + 1); // Count by one to match other defeat methods
					scoreText.setText(LK.getScore());
				}
				// Don't remove from array yet - let it spin out of screen
			} else if (Mario.isJumping || Mario.lightning && Mario.lightning.isActive) {
				// Mario jumped on top of the enemy or has active lightning shield, destroy the enemy
				enemies[j].destroy();
				enemies.splice(j, 1);
				// Add points for defeating enemy
				if (Mario.lightning && Mario.lightning.isActive) {
					// Add 1 point when defeating with lightning shield - changed from 2 to 1 to count consistently
					LK.setScore(LK.getScore() + 1);
					scoreText.setText(LK.getScore());
				} else if (Mario.isJumping) {
					// Add 1 point when jumping on enemy
					LK.setScore(LK.getScore() + 1);
					scoreText.setText(LK.getScore());
				}
			} else {
				Mario.life -= 0.005; // Decrease Mario's life by 0.5%
				if (Mario.life <= 0) {
					LK.effects.flashScreen(0xff0000, 1000);
					LK.showGameOver();
				}
			}
		}
	}
	// Update power-ups
	for (var k = powerups.length - 1; k >= 0; k--) {
		var powerup = powerups[k];
		powerup.update();
		// Check for collision with Mario
		var currentIntersecting = Mario.intersects(powerup);
		if (!powerup.lastWasIntersecting && currentIntersecting) {
			// Power-up collected - apply effect
			powerup.collected = true;
			// Apply power-up effect
			Mario.life = Math.min(1, Mario.life + 0.3); // Restore 30% of life
			// Flash effect when collecting power-up
			LK.effects.flashObject(Mario, 0xFFD700, 500);
			// Show God mode text animation for 3 seconds
			godModeText.showAnimation();
			// Play god mode sound
			LK.getSound('godmode').play();
			// Enhance lightning effect for 5 seconds
			if (Mario.lightning) {
				// Set effect active flag
				Mario.lightning.isActive = true;
				for (var i = 0; i < Mario.lightning.bolts.length; i++) {
					var bolt = Mario.lightning.bolts[i];
					tween(bolt, {
						alpha: 1,
						scaleX: bolt.originalScale.x * 2,
						scaleY: bolt.originalScale.y * 2
					}, {
						duration: 500,
						easing: tween.elasticOut
					});
				}
				// Update timer with the godmode duration (5 seconds)
				godModeText.timerValue = 5;
				// Reset to normal after 5 seconds (5000ms)
				LK.setTimeout(function () {
					Mario.lightning.isActive = false;
					Mario.lightning.animate();
				}, 5000);
			}
			// Remove the power-up
			powerup.destroy();
			powerups.splice(k, 1);
		}
		// Update tracking state
		if (powerup) {
			powerup.lastWasIntersecting = currentIntersecting;
		}
	}
	// Sort enemies by their x position to ensure they never cover each other in display order
	enemies.sort(function (a, b) {
		return a.x - b.x;
	});
	// Check if there's any active ls asset in the map to show/hide SHARKNADO title
	var hasActiveLS = false;
	var hasEnemy3 = false;
	for (var i = 0; i < enemies.length; i++) {
		if (enemies[i].enemyType === 'ls' && enemies[i].x > -50 && enemies[i].x < 2048 + 50) {
			hasActiveLS = true;
		}
		if (enemies[i].enemyType === 'enemy3' && enemies[i].x > -50 && enemies[i].x < 2048 + 50) {
			hasEnemy3 = true;
		}
	}
	// Show or hide SHARKNADO title based on ls asset presence
	if (hasActiveLS) {
		sharknadoTitle.show();
	} else {
		sharknadoTitle.hide();
	}
	// Show or hide TB popup based on enemy3 presence
	if (hasEnemy3) {
		tbPopup.show();
	} else {
		tbPopup.hide();
	}
	// Update the life counter
	lifeCounter.update();
	// Update life percentage text
	lifePercentText.setText(Math.round(Mario.life * 100) + '%');
};
// Create watermark text
var watermarkText = new Text2('@jzubora', {
	size: 20,
	fill: 0x888888 // Grey color
});
// Position at bottom right
watermarkText.anchor.set(1, 1); // Bottom right anchor
LK.gui.bottomRight.addChild(watermarkText);
watermarkText.x = -20; // 20px margin from right
watermarkText.y = -20; // 20px margin from bottom
// Handle player jump
game.down = function (x, y, obj) {
	Mario.jump();
}; ===================================================================
--- original.js
+++ change.js
@@ -799,36 +799,36 @@
 					// First horizontal 360 spin
 					tween(jjbGraphic, {
 						scaleX: -1 // Flip horizontally
 					}, {
-						duration: 417,
-						// 0.417 second for first half spin (1.2x faster)
+						duration: 150,
+						// 0.15 second for first half spin
 						easing: tween.linear,
 						onFinish: function onFinish() {
 							// Continue to full 360
 							tween(jjbGraphic, {
 								scaleX: 1 // Back to original
 							}, {
-								duration: 417,
-								// 0.417 second for second half spin (1.2x faster)
+								duration: 150,
+								// 0.15 second for second half spin
 								easing: tween.linear,
 								onFinish: function onFinish() {
 									// Second 360 spin
 									tween(jjbGraphic, {
 										scaleX: -1 // Flip horizontally again
 									}, {
-										duration: 417,
-										// 0.417 second for third half spin (1.2x faster)
+										duration: 150,
+										// 0.15 second for third half spin
 										easing: tween.linear,
 										onFinish: function onFinish() {
 											// Complete second 360
 											tween(jjbGraphic, {
 												scaleX: 1,
 												// Back to original
 												alpha: 0 // Fade out
 											}, {
-												duration: 417,
-												// 0.417 second for final half spin and fade (1.2x faster)
+												duration: 150,
+												// 0.15 second for final half spin and fade
 												easing: tween.linear,
 												onFinish: function onFinish() {
 													// Remove the enemy after spinning
 													enemies[j].destroy();
:quality(85)/https://cdn.frvr.ai/6823b95ea2d18ea6277bca09.png%3F3) 
 Ghiblis style
:quality(85)/https://cdn.frvr.ai/6823bb746ed58f7e61b44e0d.png%3F3) 
 Ghibli style but more realistic
:quality(85)/https://cdn.frvr.ai/6823d60ade022c3fe2bcc9e2.png%3F3) 
 Ghibli style
:quality(85)/https://cdn.frvr.ai/68244e78d85c9d9ada4b9443.png%3F3) 
 NeonYellow powerup logo. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6825863b1da3c9774cee15af.png%3F3) 
 Running Sith jar-jar binks in ghibli style. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/6825965d1da3c9774cee1624.png%3F3) 
 Shark with lasergun on his head, sideview, ghibli style. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68260c5b71206ab9e088036a.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/68260e6a71206ab9e08803af.png%3F3) 
 White textbubble with thin black frame. 'Run away! A killer rabbit!' text in bubble. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/68420c0e059e6944a2ece248.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/68420e37059e6944a2ece25f.png%3F3) 
 Remove 3. Stripe from the shoe and the kit
:quality(85)/https://cdn.frvr.ai/6875f9b6c15ee306f69ef97b.png%3F3) 
 Orange framed rectangle with transparent middle. The rectangle A side is much longer than the B side.