User prompt
start should spawn less often
User prompt
Make sure combos continue and not stop at 2.
User prompt
Yes, implement it
User prompt
star should move from right to left and move up and down, add a tween to make this effect ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Change how the start moves. Initially make it move like the flying koopas
User prompt
star power up, should have a different movement. it should move forward, like the enemies, but also oscilate up and down. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add boroders to score and coins in hud
User prompt
add border tot tap to start
User prompt
add white border to ttitle text
User prompt
title text should be NES red
User prompt
Increase the goombas size over time when they are spawning ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add a red square behind the game title
User prompt
when game speed increases goomba size should also increase
User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'groundY')' in or related to this line: 'tween(automatedPlayer, {' Line Number: 864
User prompt
Fix double paralax in homescreen. only the one with player moving should be happening
User prompt
remoeve double paralax speed in homepage
User prompt
add paralax scrolling also to the main menu background
User prompt
tap to start should be 400 pixxels below
User prompt
tap to start should be belwo the middle of the screen
User prompt
Better, move tap to start move below
User prompt
main menu background should do paralax too
User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'groundY')' in or related to this line: 'tween(automatedPlayer, {' Line Number: 864
Code edit (1 edits merged)
Please save this source code
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { coins: 0 }); /**** * Classes ****/ var AutomatedPlayer = Container.expand(function () { var self = Container.call(this); self.runAnimation = ['player_run1', 'player_run2', 'player_run3']; self.sprites = []; self.runFrame = 0; self.animationCounter = 0; self.animationSpeed = 0.1; // Pre-attach all sprites for (var i = 0; i < self.runAnimation.length; i++) { var sprite = self.attachAsset(self.runAnimation[i], { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); sprite.alpha = i === 0 ? 1 : 0; self.sprites.push(sprite); } self.groundY = 2732 - 400; // 400 pixels from bottom self.y = -200; // Start off-screen at the top self.showFrame = function (index) { // Hide all sprites first for (var i = 0; i < self.sprites.length; i++) { self.sprites[i].alpha = 0; } // Show the appropriate sprite self.sprites[index].alpha = 1; }; self.update = function () { // Running animation self.animationCounter += self.animationSpeed; if (self.animationCounter >= 1) { self.animationCounter = 0; self.runFrame = (self.runFrame + 1) % self.runAnimation.length; self.showFrame(self.runFrame); } // Move right automatically self.x += 5; // Wrap around when reaching edge if (self.x > 2048 + 100) { self.x = -100; } }; return self; }); var Background = Container.expand(function () { var self = Container.call(this); var backgrounds = ['background1', 'background2', 'background3']; var randomBackground = backgrounds[Math.floor(Math.random() * backgrounds.length)]; var backgroundGraphics = self.attachAsset(randomBackground, { anchorX: 0, anchorY: 0 }); self.sprites = [backgroundGraphics]; // Store sprites for access self.speed = 3; self.update = function () { if (!game.playerDead) { // Increase speed over time, up to a reasonable maximum self.speed = 3 + Math.min(8, Math.floor(LK.ticks / 300) * 0.3); self.x -= self.speed; } if (self.x <= -2048) { self.x = 2048; } }; }); var Background2 = Container.expand(function () { var self = Container.call(this); var backgrounds = ['background1', 'background2', 'background3']; var randomBackground = backgrounds[Math.floor(Math.random() * backgrounds.length)]; var backgroundGraphics = self.attachAsset(randomBackground, { anchorX: 0, anchorY: 0 }); self.sprites = [backgroundGraphics]; // Store sprites for access self.speed = 3; self.update = function () { if (!game.playerDead) { // Increase speed over time, up to a reasonable maximum self.speed = 3 + Math.min(8, Math.floor(LK.ticks / 300) * 0.3); // Double speed during star power if (starPowerActive) { self.speed *= 2; } self.x -= self.speed; } if (self.x <= -2048) { self.x = 2048; } }; }); var Coin = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); self.speed = 3; self.collected = false; self.y = 2732 - 600; // Position coins higher than the ground self.update = function () { if (!game.playerDead) { // Increase speed over time, up to a reasonable maximum self.speed = 3 + Math.min(8, Math.floor(LK.ticks / 300) * 0.3); // Double speed during star power if (starPowerActive) { self.speed *= 2; } self.x -= self.speed; // Removed oscillation to keep coins from moving up and down if (!self.oscillating) { self.oscillating = true; // No pulsing animation for coins self.scale.x = 1; self.scale.y = 1; } } if (self.x < -100) { // Cancel any active tweens when destroying tween.stop(self); tween.stop(self.scale); self.destroy(); } }; }); // ComboDisplay handles showing combo text on screen var ComboDisplay = Container.expand(function () { var self = Container.call(this); var comboText = new Text2('', { size: 60, fill: 0xFFD700, // Gold color for combo text font: "'Press Start 2P', monospace" }); comboText.anchor.set(0.5, 0.5); self.addChild(comboText); self.showCombo = function (comboCount, points) { comboText.setText('COMBO x' + comboCount + '!\n+' + points + ' POINTS!'); comboText.alpha = 1; // Animate the combo text with a scale effect comboText.scale.x = 1.2; comboText.scale.y = 1.2; tween(comboText, { alpha: 0, scaleX: 0.8, scaleY: 0.8, y: comboText.y - 60 // Move up as it fades but not as far }, { duration: 800, easing: tween.easeOut }); }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); self.runFrames = ['turtle1', 'turtle2']; self.sprites = []; // Pre-attach all sprites for (var i = 0; i < self.runFrames.length; i++) { var sprite = self.attachAsset(self.runFrames[i], { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); sprite.alpha = i === 0 ? 1 : 0; self.sprites.push(sprite); } self.speed = 6 + Math.random() * 2; self.passed = false; self.isJumping = false; self.velocityY = 0; self.canHarmPlayer = true; // Flag to track if enemy can harm player self.groundY = 2732 - 400; // 400 pixels from bottom self.y = self.groundY; // Set initial position to ground level self.runFrameIndex = 0; self.runFrameCounter = 0; self.runFrameDelay = 15; self.showFrame = function (index) { // Hide all sprites first for (var i = 0; i < self.sprites.length; i++) { self.sprites[i].alpha = 0; } // Show the appropriate sprite self.sprites[index].alpha = 1; }; self.update = function () { // Calculate base speed var currentSpeed = self.speed + Math.floor(LK.ticks / 300) * 0.2; // Increase speed over time faster // Double speed during star power if (starPowerActive) { currentSpeed *= 2; } self.x -= currentSpeed; if (self.isJumping) { self.y += self.velocityY; self.velocityY += 0.5; // Gravity effect if (self.y > 2732) { self.destroy(); } } else { self.runFrameCounter++; if (self.runFrameCounter >= self.runFrameDelay) { self.runFrameIndex = (self.runFrameIndex + 1) % self.runFrames.length; self.showFrame(self.runFrameIndex); self.runFrameCounter = 0; } } if (self.x < -100) { self.destroy(); } }; }); var FlyKoopa = Container.expand(function () { var self = Container.call(this); self.runFrames = ['flykoopa1', 'flykoopa2']; self.sprites = []; // Pre-attach all sprites for (var i = 0; i < self.runFrames.length; i++) { var sprite = self.attachAsset(self.runFrames[i], { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); sprite.alpha = i === 0 ? 1 : 0; self.sprites.push(sprite); } self.speed = 4 + Math.random() * 2; self.runFrameIndex = 0; self.runFrameCounter = 0; self.runFrameDelay = 15; self.isJumping = false; self.velocityY = 0; self.canHarmPlayer = true; // Flag to track if enemy can harm player self.showFrame = function (index) { // Hide all sprites first for (var i = 0; i < self.sprites.length; i++) { self.sprites[i].alpha = 0; } // Show the appropriate sprite self.sprites[index].alpha = 1; }; self.update = function () { // Increase speed over time, up to a reasonable maximum self.speed = 4 + Math.random() * 2 + Math.min(6, Math.floor(LK.ticks / 300) * 0.3); // Double speed during star power if (starPowerActive) { self.speed *= 2; } self.x -= self.speed; if (self.isJumping) { self.y += self.velocityY; self.velocityY += 0.5; // Gravity effect if (self.y > 2732) { self.destroy(); } } else { self.runFrameCounter++; if (self.runFrameCounter >= self.runFrameDelay) { self.runFrameIndex = (self.runFrameIndex + 1) % self.runFrames.length; self.showFrame(self.runFrameIndex); self.runFrameCounter = 0; } } if (self.x < -100) { self.destroy(); } }; }); var Goomba = Container.expand(function () { var self = Container.call(this); self.runFrames = ['goomba1', 'goomba2']; self.sprites = []; // Pre-attach all sprites for (var i = 0; i < self.runFrames.length; i++) { var sprite = self.attachAsset(self.runFrames[i], { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); sprite.alpha = i === 0 ? 1 : 0; self.sprites.push(sprite); } self.speed = 4 + Math.random() * 2; self.passed = false; self.isJumping = false; self.velocityY = 0; self.canHarmPlayer = true; // Flag to track if enemy can harm player self.groundY = 2732 - 400; // 400 pixels from bottom self.y = self.groundY; // Set initial position to ground level self.runFrameIndex = 0; self.runFrameCounter = 0; self.runFrameDelay = 15; self.showFrame = function (index) { // Hide all sprites first for (var i = 0; i < self.sprites.length; i++) { self.sprites[i].alpha = 0; } // Show the appropriate sprite self.sprites[index].alpha = 1; }; self.update = function () { // Increase speed over time, up to a reasonable maximum self.speed = 4 + Math.random() * 2 + Math.min(6, Math.floor(LK.ticks / 300) * 0.3); // Double speed during star power if (starPowerActive) { self.speed *= 2; } self.x -= self.speed; if (self.isJumping) { self.y += self.velocityY; self.velocityY += 0.5; // Gravity effect if (self.y > 2732) { self.destroy(); } } else { self.runFrameCounter++; if (self.runFrameCounter >= self.runFrameDelay) { self.runFrameIndex = (self.runFrameIndex + 1) % self.runFrames.length; self.showFrame(self.runFrameIndex); self.runFrameCounter = 0; } } if (self.x < -100) { self.destroy(); } }; }); var MainMenu = Container.expand(function () { var self = Container.call(this); // Add background image var background = self.attachAsset('background3', { anchorX: 0, anchorY: 0 }); // Title text var titleText = new Text2('OG Mario\nVs\nMonsters', { size: 180, fill: 0x000000, //{3t} // Black color instead of NES Mario brick-red font: "'Press Start 2P', monospace", align: 'center' // Add text alignment directly in the options }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 2732 / 4; // Position higher on screen self.addChild(titleText); // No subtitle text // Play button var playButton = new Text2('TAP TO START', { size: 120, fill: 0xFCA817, // NES Mario gold coin color font: "'Press Start 2P', monospace" }); playButton.anchor.set(0.5, 0.5); playButton.x = 2048 / 2; playButton.y = 2732 / 2; // Centered vertically self.addChild(playButton); // Make the play button "pulse" for attention self.animationCounter = 0; self.update = function () { self.animationCounter += 0.05; playButton.scale.x = 1 + Math.sin(self.animationCounter) * 0.1; playButton.scale.y = 1 + Math.sin(self.animationCounter) * 0.1; // Parallax scrolling effect for the background background.x -= 1; // Move background to the left if (background.x <= -2048) { // Reset position when off-screen background.x = 0; } }; // Handle button clicks self.down = function (x, y, obj) { // Default behavior - start game if (self.onPlayClick) { self.onPlayClick(); } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); self.runAnimation = ['player_run1', 'player_run2', 'player_run3']; self.jumpAnimation = ['player_jump']; self.currentState = 'running'; self.sprites = []; self.runFrame = 0; self.jumpFrame = 0; self.animationCounter = 0; self.animationSpeed = 0.1; // Pre-attach all sprites for (var i = 0; i < self.runAnimation.length; i++) { var sprite = self.attachAsset(self.runAnimation[i], { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); sprite.alpha = i === 0 ? 1 : 0; self.sprites.push(sprite); } for (var j = 0; j < self.jumpAnimation.length; j++) { var jumpSprite = self.attachAsset(self.jumpAnimation[j], { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); jumpSprite.alpha = 0; self.sprites.push(jumpSprite); } self.speed = 5; // Base speed, will increase in update function self.jumpHeight = 25; self.isJumping = false; self.canDoubleJump = false; // Track if double jump is available self.hasDoubleJumped = false; // Track if double jump was used self.isDashing = false; // Track if player is currently dashing self.isInvincible = false; // Track if player is invincible self.dashCooldown = false; // Dash cooldown self.swipeStartX = null; // Track swipe start position self.swipeStartY = null; self.velocityY = 0; self.groundY = 2732 - 400; // 400 pixels from bottom self.y = self.groundY; // Set initial position to ground level self.runFrameDelay = 10; self.showFrame = function (frameType, index) { // Hide all sprites first for (var i = 0; i < self.sprites.length; i++) { self.sprites[i].alpha = 0; } // Show the appropriate sprite based on state and frame index if (frameType === 'run') { self.sprites[index].alpha = 1; } else if (frameType === 'jump') { self.sprites[self.runAnimation.length + index].alpha = 1; } }; // Dash functionality removed // Swipe handling removed self.down = function (x, y, obj) { // Down handler simplified, no swipe tracking }; self.up = function (x, y, obj) { // Up handler simplified, no swipe handling }; self.move = function (x, y, obj) { // Move handler simplified, no swipe detection }; self.update = function () { // Update player speed based on game progress and background speed // Use background speed as base for player speed scaling if available var speedMultiplier = 1; if (game.background && game.background.speed) { speedMultiplier = game.background.speed / 3; } self.speed = 5 + Math.min(5, Math.floor(LK.ticks / 300) * 0.3 * speedMultiplier); // Make player blink fast during star power if (starPowerActive) { // Cancel any existing tween on player tween.stop(self); // Use tween to create a more advanced flashing effect with color changes if (!self.starTweenActive) { var _flashNextColor = function flashNextColor() { // Apply the next color in the sequence tween(self, { tint: colors[colorIndex] }, { duration: 150, // Fast color transitions easing: tween.linear, onFinish: function onFinish() { // Cycle to the next color colorIndex = (colorIndex + 1) % colors.length; // Continue the cycle if star power is still active if (starPowerActive) { _flashNextColor(); } else { self.tint = 0xFFFFFF; // Reset tint when star power ends self.starTweenActive = false; } } }); }; // Start the flash sequence self.starTweenActive = true; // Create rapid color cycling effect var colors = [0xFFFF00, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF00FF]; var colorIndex = 0; _flashNextColor(); } } else { // Ensure player is fully visible when star power ends self.alpha = 1; self.tint = 0xFFFFFF; // Reset tint self.starTweenActive = false; } if (self.isJumping) { self.y += self.velocityY; // Scale gravity based on game speed - faster speed = faster falling var gravityMultiplier = speedMultiplier > 1 ? speedMultiplier * 0.8 : 1; self.velocityY += 0.3 * gravityMultiplier; // Show jump sprite self.showFrame('jump', 0); if (self.y >= self.groundY - 30) { if (self.y < 0) { // Prevent jump from exceeding the top of the screen self.y = 0; self.velocityY = 0; } if (!self.isDead) { self.y = self.groundY - 30; self.isJumping = false; self.hasDoubleJumped = false; // Reset double jump when landing self.velocityY = 0; self.currentState = 'running'; // Reset combo when landing if (comboActive) { comboActive = false; // If we had a combo going, display the final combo if (comboCount > 1) { if (!comboDisplayObj) { comboDisplayObj = game.addChild(new ComboDisplay()); comboDisplayObj.x = 2048 / 2; comboDisplayObj.y = 2732 / 2 - 300; var comboPoints = comboCount * 50 * 2; // Double points for combos comboDisplayObj.showCombo(comboCount, comboPoints); } } // Reset comboDisplayObj to ensure fresh display for next combo comboDisplayObj = null; } } } } else { // Running animation self.animationCounter += self.animationSpeed; if (self.animationCounter >= 1) { self.animationCounter = 0; self.runFrame = (self.runFrame + 1) % self.runAnimation.length; self.showFrame('run', self.runFrame); } } }; self.jump = function () { // Get speed multiplier based on background speed var speedMultiplier = 1; if (game.background && game.background.speed) { speedMultiplier = game.background.speed / 3; } // Increase jump height slightly with game speed to help player clear obstacles var jumpHeightMultiplier = Math.min(1.3, 1 + (speedMultiplier - 1) * 0.3); // Regular jump when not jumping if (!self.isJumping) { self.isJumping = true; LK.getSound('jump').play(); self.velocityY = -self.jumpHeight * jumpHeightMultiplier; self.currentState = 'jumping'; self.showFrame('jump', 0); } // Double jump when already jumping (always available) else if (self.isJumping && !self.hasDoubleJumped) { LK.getSound('jump').play(); self.velocityY = -self.jumpHeight * 0.8 * jumpHeightMultiplier; // Slightly lower second jump self.hasDoubleJumped = true; // No flash effect for double jump to make it distinct from dash } }; }); var Star = Container.expand(function () { var self = Container.call(this); // Use star asset directly instead of recoloring coin var starGraphics = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); // Set star color to bright yellow for emphasis starGraphics.tint = 0xFFFF00; self.speed = 3; self.collected = false; self.y = 2732 - 600; // Position stars higher than the ground // Add animation self.animationCounter = 0; self.update = function () { if (!game.playerDead) { // Increase speed over time, matching background speed self.speed = 3 + Math.min(8, Math.floor(LK.ticks / 300) * 0.3); // Double speed during star power if (starPowerActive) { self.speed *= 2; } self.x -= self.speed; // If we haven't started oscillation animation yet, initialize it if (!self.oscillating) { self.originalY = self.y; // Store original position self.originalX = self.x; // Store original X position self.oscillating = true; // Set up horizontal forward oscillation - star moves forward and backward tween(self, { xOffset: 300 // Move forward by 300px }, { duration: 2000, easing: tween.sineInOut, onUpdate: function onUpdate(obj, progress) { // Apply horizontal oscillation while still allowing normal movement // This creates a zigzag forward motion as the star still moves left overall var oscillationX = Math.sin(progress * Math.PI * 2) * 150; self.x += oscillationX - (self.lastOscillationX || 0); self.lastOscillationX = oscillationX; }, onFinish: function onFinish() { self.lastOscillationX = 0; // Restart horizontal oscillation to create continuous movement self.oscillating = false; } }); // Set up vertical oscillation with tween - full screen height movement tween(self, { y: 100 // Move to the top of the screen }, { duration: 3000, // Slower, smoother movement easing: tween.sineInOut, // Smoother easing onFinish: function onFinish() { // When reaching the top, go all the way down tween(self, { y: 2732 - 100 // Move to the bottom of the screen }, { duration: 3000, // Matching duration for smooth cycle easing: tween.sineInOut, onFinish: function onFinish() { // Reset animation when complete self.oscillating = false; } }); } }); // Setup enhanced pulsing animation with tween - larger size variation tween(self.scale, { x: 1.3, // Increase more (was 1.15) y: 1.3 // Increase more (was 1.15) }, { duration: 900, easing: tween.sineInOut, onFinish: function onFinish() { tween(self.scale, { x: 0.8, // Decrease more (was 0.85) y: 0.8 // Decrease more (was 0.85) }, { duration: 900, easing: tween.sineInOut, onFinish: function onFinish() { // Scale animation will reset when complete if (self.parent) { self.scale.x = 1; self.scale.y = 1; } } }); } }); } } if (self.x < -100) { // Cancel any active tweens when destroying tween.stop(self); tween.stop(self.scale); self.destroy(); } }; return self; }); /**** * Initialize Game ****/ // Helper function to adjust music playback rate as LK.setMusicPlaybackRate is not available /**** *-Seperator- ****/ var game = new LK.Game({ backgroundColor: 0x5C94FC // NES Mario sky blue background color }); /**** * Game Code ****/ // For reference: the font is used with font: "'Press Start 2P', monospace" // The font 'Press Start 2P' is a web font that should be loaded from Google Fonts // Helper function to adjust music playback rate as LK.setMusicPlaybackRate is not available // Game state variables // No additional code needed for font loading in this environment // or being loaded by the LK engine automatically // Instead, we'll rely on the font already being available in the system // We can't use document.createElement in this environment function setMusicPlaybackRate(rate) { // Check if music is playing before trying to adjust it // Use the sound API instead of the non-existent LK.getMusic function var music = LK.getSound('theme'); if (music) { // Set the playback rate if available on the audio element if (music.playbackRate !== undefined) { music.playbackRate = rate; } } } var gameStarted = false; var showingUpgradeMenu = false; var mainMenu; var upgradeMenu; var background; var background2; var player; var enemies = []; var enemySpawnInterval = 80; var enemySpawnCounter = 0; var coinObjects = []; // Renamed from 'coins' to avoid conflict with coin counter var coinSpawnInterval = Math.max(40, 150 - Math.floor(LK.ticks / 300) * 2); // Decrease interval faster, minimum 40 var coinSpawnCounter = 0; var stars = []; // Array to store star power-ups var starSpawnInterval = 500; // Spawn stars less frequently than coins var starSpawnCounter = 0; var starPowerActive = false; // Track if star power is active var starPowerDuration = 10 * 60; // 10 seconds at 60fps var starPowerTimer = 0; // Timer for star power // Combo system variables var comboCount = 0; var comboActive = false; var comboDisplayObj = null; // Score system var score = 0; var coins = storage.coins || 0; // Get persistent coin count var scoreText = new Text2('Score: 0', { size: 60, fill: 0xFCE29F, //{67} // NES light tan/cream color font: "'Press Start 2P', monospace" }); // Speed indicator removed from HUD scoreText.anchor.set(1, 0); scoreText.x = -50; scoreText.y = 50; LK.gui.topRight.addChild(scoreText); // Coin count display var coinText = new Text2('Coins: ' + coins, { size: 50, fill: 0xFCA817, //{6d} // NES Mario gold coin color // Gold color for coins font: "'Press Start 2P', monospace" }); coinText.anchor.set(1, 0); coinText.x = -50; coinText.y = 120; // Position below score LK.gui.topRight.addChild(coinText); // Combo indicator removed from HUD scoreText.alpha = 0; // Hide score initially coinText.alpha = 0; // Hide coin count initially // Always enable double jump, no upgrades needed storage.doubleJumpPurchased = true; // Dash is removed // Create parallax backgrounds for main menu animation background = game.addChild(new Background()); background.x = 0; background.y = 0; background2 = game.addChild(new Background2()); background2.x = 2048; background2.y = 0; // Create automated player for main menu var automatedPlayer = game.addChild(new AutomatedPlayer()); automatedPlayer.x = -100; // Show main menu with elements on top of background mainMenu = game.addChild(new MainMenu()); // Animate title text with tween // First position title off-screen at the top if (mainMenu.children && mainMenu.children[1]) { var titleText = mainMenu.children[1]; // Get the title text titleText.y = -200; // Start from above the screen // Animate title dropping from top tween(titleText, { y: 2732 / 4 // Final position (center) }, { duration: 1000, easing: tween.bounceOut, onFinish: function onFinish() { // Add shake effect after dropping var originalX = titleText.x; var originalY = titleText.y; var shakeCount = 0; var maxShakes = 5; function shakeTitle() { // Shake in random direction var shakeX = originalX + (Math.random() * 40 - 20); var shakeY = originalY + (Math.random() * 20 - 10); tween(titleText, { x: shakeX, y: shakeY }, { duration: 100, easing: tween.linear, onFinish: function onFinish() { shakeCount++; if (shakeCount < maxShakes) { shakeTitle(); // Continue shaking } else { // Return to original position tween(titleText, { x: originalX, y: originalY }, { duration: 100, easing: tween.linear, onFinish: function onFinish() { // Start playing game theme music LK.playMusic('theme'); // Drop the automated player from top tween(automatedPlayer, { y: automatedPlayer.groundY - 30 }, { duration: 1000, easing: tween.bounceOut }); } }); } } }); } shakeTitle(); // Start the shake sequence } }); } mainMenu.onPlayClick = function () { // Start the game gameStarted = true; if (mainMenu) { // Add null check before destroying mainMenu.destroy(); mainMenu = null; } // Initialize game elements - handled in game.down }; game.update = function () { // Handle menu states if (!gameStarted) { // When in menu mode, update backgrounds for parallax effect and menu if (background) { background.update(); } // Update automated player if it exists if (typeof automatedPlayer !== 'undefined' && automatedPlayer) { automatedPlayer.update(); } // Update the menu if (mainMenu) { mainMenu.update(); } return; } // Game hasn't been initialized yet - start it if (!player) { // Initialize game elements // Player and GUI should already be created in game.down // Set background reference for other objects game.background = background; } // Game play update logic background.update(); background2.update(); player.update(); enemySpawnCounter++; coinSpawnCounter++; starSpawnCounter++; // Handle star power-up timer if (starPowerActive) { starPowerTimer--; if (starPowerTimer <= 0) { starPowerActive = false; player.isInvincible = false; // Return background tint to normal background.sprites[0].tint = 0xFFFFFF; background2.sprites[0].tint = 0xFFFFFF; // Switch back to regular theme music LK.stopMusic(); LK.playMusic('theme'); } } if (coinSpawnCounter >= coinSpawnInterval) { var coin = new Coin(); coin.x = 2048 + Math.random() * 200; // Set a reasonable height range for coins (not too low, not too high) coin.y = Math.max(300, Math.min(2732 - 600, Math.random() * (2732 - 800))); coinObjects.push(coin); game.addChild(coin); coinSpawnCounter = 0; } // Spawn star power-ups occasionally, but only if star power is not active if (starSpawnCounter >= starSpawnInterval && !starPowerActive) { var star = new Star(); star.x = 2048 + Math.random() * 200; // Set a reasonable height range for stars (not too low, not too high) star.y = Math.max(300, Math.min(2732 - 600, Math.random() * (2732 - 800))); stars.push(star); game.addChild(star); starSpawnCounter = 0; starSpawnInterval = Math.floor(Math.random() * 300) + 300; // Random interval between 300-600 ticks } if (enemySpawnCounter >= enemySpawnInterval) { var enemyType = Math.random() < 0.33 ? 'Enemy' : Math.random() < 0.5 ? 'Goomba' : 'FlyKoopa'; var enemy; if (enemyType === 'Enemy') { enemy = new Enemy(); } else if (enemyType === 'Goomba') { enemy = new Goomba(); } else { enemy = new FlyKoopa(); // Ensure FlyKoopas spawn in the middle to upper part of the screen, not too low enemy.y = Math.max(300, Math.min(2732 - 600, Math.random() * (2732 - 800))); } enemy.x = 2048 + Math.random() * 200; if (enemyType === 'FlyKoopa') { // Height for FlyKoopa is already set earlier, no need to set it again } else { enemy.y = enemy.groundY; // Use groundY for initial position } enemies.push(enemy); game.addChild(enemy); enemySpawnInterval = Math.max(15, Math.floor(Math.random() * 100) + 60 - Math.floor(LK.ticks / 300) * 2); // Decrease interval faster, minimum 15 enemySpawnCounter = 0; } for (var j = enemies.length - 1; j >= 0; j--) { enemies[j].update(); if (player.intersects(enemies[j])) { if (starPowerActive && enemies[j].canHarmPlayer !== false) { // Star power is active - instantly defeat enemy with special effect enemies[j].velocityY = -15; // Stronger pop up effect for star power enemies[j].isJumping = true; enemies[j].canHarmPlayer = false; LK.getSound('stomp').play(); // Create a sparkle effect LK.effects.flashObject(enemies[j], 0xFFFF00, 300); // Handle combo tracking - activate combo mode if not already active if (!comboActive) { comboActive = true; comboCount = 0; } // Increment combo count comboCount++; // Calculate score with combo bonus var starEnemyPoints = 100 * comboCount; score += starEnemyPoints; // Display flash text for combo count if more than 1 if (comboCount > 1) { if (!comboDisplayObj) { comboDisplayObj = game.addChild(new ComboDisplay()); comboDisplayObj.x = enemies[j].x; comboDisplayObj.y = enemies[j].y - 50; comboDisplayObj.showCombo(comboCount, starEnemyPoints); } } scoreText.setText('Score: ' + score); LK.setScore(score); } else if (!player.isDead && player.isJumping && player.velocityY > 0 && player.y < enemies[j].y) { // Player is falling and lands on enemy enemies[j].velocityY = -10; // Pop up effect for enemy player.velocityY = -15; // Bounce Mario upwards LK.getSound('stomp').play(); // Play stomp sound // Handle combo tracking - activate combo mode if not already active if (!comboActive) { comboActive = true; comboCount = 0; } // Increment combo count comboCount++; // Calculate score with combo bonus var enemyPoints = 50; if (comboCount > 1) { // Apply combo multiplier - each enemy in combo is worth more enemyPoints = 50 * comboCount; } score += enemyPoints; // Display flash text for combo count if more than 1 if (comboCount > 1) { if (!comboDisplayObj) { comboDisplayObj = game.addChild(new ComboDisplay()); comboDisplayObj.x = enemies[j].x; comboDisplayObj.y = enemies[j].y - 50; comboDisplayObj.showCombo(comboCount, enemyPoints); } } scoreText.setText('Score: ' + score); LK.setScore(score); enemies[j].isJumping = true; enemies[j].canHarmPlayer = false; // Enemy can no longer harm player } else if (enemies[j].canHarmPlayer !== false && !player.isInvincible) { if (!player.isDead && enemies[j].canHarmPlayer !== false) { LK.getSound('dead').play(); // Play dead sound player.isDead = true; game.playerDead = true; player.velocityY = -10; // Pop up effect similar to enemy player.isJumping = true; LK.setTimeout(function () { // Save final score before game over LK.setScore(score); LK.showGameOver(); }, 3000); // Delay game over by 3 seconds } } } else if (player.x > enemies[j].x && !enemies[j].passed) { enemies[j].passed = true; } if (enemies[j].x < -100) { enemies.splice(j, 1); } } for (var k = coinObjects.length - 1; k >= 0; k--) { coinObjects[k].update(); if (player.intersects(coinObjects[k])) { if (!coinObjects[k].collected) { coinObjects[k].collected = true; LK.getSound('Coin').play(); // Play coin sound // Increase score when collecting coins score += 10; // Separate coin counter coins++; // Update storage for persistence storage.coins = coins; // Update displays scoreText.setText('Score: ' + score); coinText.setText('Coins: ' + coins); LK.setScore(score); // Create a coin pickup effect // Visual effects for coin collection - similar to star power but smaller LK.effects.flashObject(player, 0xFCA817, 300); // Gold flash // Create a coin burst effect for (var i = 0; i < 8; i++) { var angle = i / 8 * Math.PI * 2; var distance = 60; var particleX = coinObjects[k].x + Math.cos(angle) * distance; var particleY = coinObjects[k].y + Math.sin(angle) * distance; var particle = LK.getAsset('coin', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.4, scaleY: 0.4, x: coinObjects[k].x, y: coinObjects[k].y, alpha: 0.8 }); particle.tint = 0xFCA817; // Gold tint game.addChild(particle); // Animate particles outward tween(particle, { x: particleX, y: particleY, alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 800, easing: tween.easeOut }); // Remove particles after animation LK.setTimeout(function (p) { return function () { if (p && p.parent) { p.parent.removeChild(p); } }; }(particle), 800); } coinObjects[k].destroy(); coinObjects.splice(k, 1); } } } // Update and check star power-ups for (var s = stars.length - 1; s >= 0; s--) { stars[s].update(); if (player.intersects(stars[s])) { if (!stars[s].collected) { stars[s].collected = true; // Switch music to star power theme LK.stopMusic(); LK.playMusic('starman2'); // Activate star power starPowerActive = true; starPowerTimer = starPowerDuration; player.isInvincible = true; // Visual effects for star power LK.effects.flashObject(player, 0xFFFF00, 500); // Yellow flash // Create a star burst effect for (var i = 0; i < 12; i++) { var angle = i / 12 * Math.PI * 2; var distance = 100; var particleX = player.x + Math.cos(angle) * distance; var particleY = player.y + Math.sin(angle) * distance; var particle = LK.getAsset('coin', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5, x: player.x, y: player.y, alpha: 0.8 }); particle.tint = 0xFFFF00; // Yellow tint game.addChild(particle); // Animate particles outward tween(particle, { x: particleX, y: particleY, alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 1000, easing: tween.easeOut }); // Remove particles after animation LK.setTimeout(function (p) { return function () { if (p && p.parent) { p.parent.removeChild(p); } }; }(particle), 1000); } // Change background tint for star power effect if (background.sprites && background.sprites.length > 0) { background.sprites[0].tint = 0xFFFFAA; // Slight yellow tint } if (background2.sprites && background2.sprites.length > 0) { background2.sprites[0].tint = 0xFFFFAA; // Slight yellow tint } // Add extra points for star score += 100; scoreText.setText('Score: ' + score); LK.setScore(score); // Remove the star stars[s].destroy(); stars.splice(s, 1); } } else if (stars[s].x < -100) { stars[s].destroy(); stars.splice(s, 1); } } // Update speed display and music speed if (background && !game.playerDead) { var speedMultiplier = (background.speed / 3).toFixed(1); // Speed text update removed // Combo text update removed // Adjust music playback rate based on game speed var musicPlaybackRate = Math.min(1.5, 0.8 + background.speed / 3 * 0.2); // Increase music speed during star power if (starPowerActive) { musicPlaybackRate = Math.min(2.0, musicPlaybackRate * 1.2); } setMusicPlaybackRate(musicPlaybackRate); } }; game.down = function (x, y, obj) { if (!gameStarted) { // Transition to game on tap gameStarted = true; if (mainMenu && mainMenu.destroy) { mainMenu.destroy(); mainMenu = null; } if (typeof automatedPlayer !== 'undefined' && automatedPlayer) { automatedPlayer.destroy(); automatedPlayer = null; } // Background will be kept and reused for actual gameplay // We don't need to initialize background in the game.update function // since we already have it // Show score and coin count scoreText.alpha = 1; coinText.alpha = 1; // Create player player = game.addChild(new Player()); player.x = 2048 / 4; player.y = player.groundY - 30; return; } else { // Pass event to player player.down(x, y, obj); // In-game tap makes player jump player.jump(); } }; game.up = function (x, y, obj) { if (!gameStarted) { return; } // Pass touch up event to player if (player) { player.up(x, y, obj); } }; game.move = function (x, y, obj) { if (!gameStarted) { return; } // Pass touch move event to player if (player) { player.move(x, y, obj); } };
===================================================================
--- original.js
+++ change.js
@@ -867,11 +867,8 @@
// When in menu mode, update backgrounds for parallax effect and menu
if (background) {
background.update();
}
- if (background2) {
- background2.update();
- }
// Update automated player if it exists
if (typeof automatedPlayer !== 'undefined' && automatedPlayer) {
automatedPlayer.update();
}