User prompt
Make level announcement larger and last longer also add effects
User prompt
Make the level announcements to last more time and be more visible
User prompt
Make the level change announcement to last 2 seconds
User prompt
Remove the color transitions on levels
User prompt
Make the level color overlay more transparent on all levels ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Back to first main level after 600 points
User prompt
600 points bring you back to main level
User prompt
You win at 1000 points
User prompt
New level after 600, no overlay
User prompt
Back to main level at 600 and win at 1000 points
User prompt
Back to level 1 at 500 points
User prompt
Back to main level at 500 points
User prompt
After 500 points back to main level and you win at 700 points
User prompt
Make flying dinos to appear just on the upper portion of the screen and make fix the asset to be flying enemy asset
User prompt
Remove dinos info from instructions
User prompt
Make a new flying enemy with a new asset called flying dinosaur, you could jump over it and defeat them or shoot them
User prompt
Fix the final score to reflect the points score counter on screen
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'self.swapChildren(trailContainer, starGraphics);' Line Number: 200
User prompt
Add a gradient on each star that gets shot as an extra animation that fades
User prompt
Add an animation for star shooting ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add a zero to final score counter it beeds to reflect the point counter
User prompt
Final score have to be the same number than points counter
User prompt
Final score is not correct
User prompt
Final score is not correct
User prompt
Fix final score to reflect points counter on screen
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Define a class for enemies var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5; self.update = function () { self.x -= self.speed; if (self.x < -50) { self.destroy(); } }; }); // Define a class for collectible hearts var Heart = Container.expand(function () { var self = Container.call(this); var heartGraphics = self.attachAsset('heart', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1 }); self.speed = 5; self.lastY = self.y; self.lastX = self.x; // Add some floating animation self.floatOffset = Math.random() * Math.PI * 2; self.floatSpeed = 0.05; self.baseY = 0; self.update = function () { // Store last position for collision detection self.lastY = self.y; self.lastX = self.x; // Move the heart self.x -= self.speed; // Floating animation self.y = self.baseY + Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * 20; // Remove if offscreen if (self.x < -50) { self.destroy(); } }; 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 playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5; self.jumpHeight = 40; self.isJumping = false; self.canDoubleJump = false; // Track if player can perform double jump self.velocityY = 0; self.update = function () { // No need for physics-based jump calculation anymore // Animation is handled by tweens in jump method }; self.jump = function () { // First jump if (!self.isJumping) { self.isJumping = true; self.canDoubleJump = true; // Enable double jump after first jump // Use tween for smoother jump animation var initialY = self.y; var peakY = initialY - 500; // Jump peak height - increased from 300 to 500 // Store current X position to prevent horizontal movement during jump var currentX = self.x; tween(self, { y: peakY }, { duration: 500, easing: tween.easeOutQuad, onFinish: function onFinish() { // Fall back down with easing tween(self, { y: 2732 / 2 // Ground level }, { duration: 600, easing: tween.easeInQuad, onFinish: function onFinish() { self.isJumping = false; self.canDoubleJump = false; // Reset double jump ability self.velocityY = 0; } }); } }); } // Second jump (double jump) else if (self.canDoubleJump) { self.canDoubleJump = false; // Used double jump // Cancel any existing tweens on player tween.cancelAll(self); // Current Y position becomes the new starting point var currentY = self.y; var doubleJumpPeakY = currentY - 400; // Slightly lower second jump // Store current X position to prevent horizontal movement during double jump var currentX = self.x; // Perform double jump animation tween(self, { y: doubleJumpPeakY }, { duration: 400, easing: tween.easeOutQuad, onFinish: function onFinish() { // Fall back down with easing tween(self, { y: 2732 / 2 // Ground level }, { duration: 500, easing: tween.easeInQuad, onFinish: function onFinish() { self.isJumping = false; self.velocityY = 0; } }); } }); } }; }); // Define a class for collectible power-up stars var PowerStar = Container.expand(function () { var self = Container.call(this); var starGraphics = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2 }); self.speed = 4; self.lastY = self.y; self.lastX = self.x; // Add floating animation self.floatOffset = Math.random() * Math.PI * 2; self.floatSpeed = 0.07; self.baseY = 0; // Add spinning animation self.rotation = 0; self.rotationSpeed = 0.05; self.update = function () { // Store last position for collision detection self.lastY = self.y; self.lastX = self.x; // Move the star self.x -= self.speed; // Floating animation self.y = self.baseY + Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * 25; // Spinning animation self.rotation += self.rotationSpeed; // Remove if offscreen if (self.x < -50) { self.destroy(); } }; return self; }); // Define a class for star bullets var Star = Container.expand(function () { var self = Container.call(this); // Create a yellow star shape using the built-in shape feature var starGraphics = self.attachAsset('star', { width: 50, height: 50, color: 0xffff00, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); self.speed = 10; self.speedX = 10; // Horizontal speed self.speedY = 0; // Vertical speed (default to 0 for straight shots) self.rotation = 0; // Current rotation self.rotationSpeed = 0.1; // Rotation speed for spinning stars // Store the last position for collision detection self.lastY = self.y; self.lastX = self.x; // Add a pulsing effect self.scaleDirection = 1; self.scaleSpeed = 0.02; self.minScale = 0.8; self.maxScale = 1.2; self.update = function () { // Store last position before update self.lastY = self.y; self.lastX = self.x; // Move the star according to its speed components self.x += self.speedX; self.y += self.speedY; // Rotate the star for visual effect self.rotation += self.rotationSpeed; starGraphics.rotation = self.rotation; // Pulse scaling effect if (self.scaleDirection > 0) { starGraphics.scale.x += self.scaleSpeed; starGraphics.scale.y += self.scaleSpeed; if (starGraphics.scale.x >= self.maxScale) { self.scaleDirection = -1; } } else { starGraphics.scale.x -= self.scaleSpeed; starGraphics.scale.y -= self.scaleSpeed; if (starGraphics.scale.x <= self.minScale) { self.scaleDirection = 1; } } // Remove if it goes off-screen if (self.x > 2048 + 50 || self.y < -50 || self.y > 2732 + 50) { self.destroy(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB // Sky blue background }); /**** * Game Code ****/ // Ensure tween.cancelAll is available if (!tween.cancelAll) { tween.cancelAll = function (target) { // Find all active tweens affecting this target and cancel them var allTweens = []; // Get all tweens if (tween.getAll && typeof tween.getAll === 'function') { allTweens = tween.getAll(); } else { // Fallback implementation if getAll is not available if (tween._tweens && Array.isArray(tween._tweens)) { allTweens = tween._tweens; } } // Cancel tweens for target if (allTweens.length > 0) { allTweens.forEach(function (t) { if (t && t._target === target && typeof t.cancel === 'function') { t.cancel(); } }); } // If no direct way to access tweens, cancel by calling tween with duration 0 tween(target, {}, { duration: 0 }); }; } var background = game.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 0 })); background.x = 0; background.y = 0; game.desertLevelActive = false; game.nightmareLevelActive = false; game.infernoLevelActive = false; // Initialize player var player = game.addChild(new Player()); player.x = 2048 / 2; player.y = 2732 / 2; player.lives = 3; player.invulnerable = false; player.invulnerableTime = 0; player.hasPowerStar = false; player.powerStarTime = 0; player.originalTint = 0xFFFFFF; // Initialize enemies var enemies = []; var enemySpawnInterval = 100; var enemySpawnCounter = 0; // Initialize collectible hearts var collectibleHearts = []; var heartSpawnInterval = 300; // Less frequent than enemies var heartSpawnCounter = 0; // Initialize power stars var powerStars = []; var powerStarSpawnInterval = 600; // Even less frequent than hearts var powerStarSpawnCounter = 0; // Create life display with proper heart images var maxHearts = 5; // Maximum number of hearts var heartsContainer = new Container(); LK.gui.top.addChild(heartsContainer); heartsContainer.x = 0; // Will be centered heartsContainer.y = 150; // Offset from top edge // Create heart icons array - we'll display both filled and empty hearts var heartIcons = []; // Function to update heart display function updateHeartDisplay() { // Remove existing hearts while (heartsContainer.children.length > 0) { heartsContainer.removeChildAt(0); } // Add heart icons for (var i = 0; i < player.lives; i++) { var heart = heartsContainer.addChild(LK.getAsset('heart', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1 })); // Position hearts in a row, centered var heartSpacing = 130; var totalWidth = (player.lives - 1) * heartSpacing; heart.x = -totalWidth / 2 + i * heartSpacing; heartIcons[i] = heart; } } // Initialize heart display updateHeartDisplay(); // Create a new Text2 object to display the score var scoreText = new Text2('0', { size: 100, fill: 0xFFFFFF }); // Add the score text to the game GUI at the top center of the screen LK.gui.top.addChild(scoreText); scoreText.x = 2048 / 2; scoreText.y = 0; // Create points counter and display var points = 0; var pointsText = new Text2('Points: 0', { size: 80, fill: 0xFFFFFF }); LK.gui.topRight.addChild(pointsText); pointsText.anchor.set(1, 0); pointsText.x = -20; pointsText.y = 0; // Create instruction text with black background var instructionContainer = new Container(); LK.gui.center.addChild(instructionContainer); instructionContainer.y = 300; // Create black background for instructions var instructionBg = new Container(); instructionBg.width = 1000; instructionBg.height = 350; instructionContainer.addChild(instructionBg); // Create a black rectangle background var blackBg = instructionBg.attachAsset('rect', { width: 1000, height: 350, color: 0x000000, shape: 'box', anchorX: 0.5, anchorY: 0.5, alpha: 0.9 }); // Create instruction text with more detailed controls var instructionText = new Text2('TAP to JUMP\nHOLD to continuously SHOOT', { size: 60, fill: 0xFFFFFF, align: 'center' }); instructionText.anchor.set(0.5, 0.5); instructionContainer.addChild(instructionText); // Create a timeout to hide instructions after 6 seconds (reduced by 2 seconds) LK.setTimeout(function () { // Fade out instructions var alpha = 1; var fadeInterval = LK.setInterval(function () { alpha -= 0.05; // Slower fade for better readability instructionContainer.alpha = alpha; // Fade the entire container including background if (alpha <= 0) { LK.clearInterval(fadeInterval); instructionContainer.visible = false; } }, 100); }, 6000); // Handle game updates // Array to store bullets var stars = []; var shootTimer = 0; game.update = function () { player.update(); // Handle player invulnerability from damage if (player.invulnerable && !player.hasPowerStar) { // Make player flash to indicate invulnerability player.alpha = Math.sin(Date.now() * 0.01) * 0.5 + 0.5; // End invulnerability after 2 seconds if (Date.now() - player.invulnerableTime > 2000) { player.invulnerable = false; player.alpha = 1; } } // Handle power star invincibility if (player.hasPowerStar) { // Make player glow with neon colors var elapsed = Date.now() - player.powerStarTime; var colorIndex = Math.floor(elapsed / 300 % 4); var neonColors = [0x00FFFF, 0xFF00FF, 0xFFFF00, 0x00FF00]; player.children[0].tint = neonColors[colorIndex]; // Player is invulnerable during power star effect player.invulnerable = true; player.alpha = 1; // End power star effect after 10 seconds instead of 20 if (elapsed > 10000) { player.hasPowerStar = false; player.invulnerable = false; // Restore original appearance player.children[0].tint = player.originalTint; // Show power star end indicator showActionIndicator("POWER LOST", 1000); } } // Removed auto-shooting to only allow double tap shooting // Update stars for (var i = stars.length - 1; i >= 0; i--) { stars[i].update(); // Remove stars that are destroyed if (!stars[i].parent) { stars.splice(i, 1); continue; } // Check for star-enemy collisions for (var j = enemies.length - 1; j >= 0; j--) { if (stars[i] && enemies[j] && stars[i].intersects(enemies[j])) { // Remove the enemy and the star enemies[j].destroy(); enemies.splice(j, 1); stars[i].destroy(); stars.splice(i, 1); // Increase score LK.setScore(LK.getScore() + 1); scoreText.setText(LK.getScore()); // Update points points += 10; pointsText.setText('Points: ' + points); // Check if player reached 500 points to win if (points >= 500) { LK.showYouWin(); } // Check if we just passed 150 points for the enemy increase announcement if (points - 10 < 150 && points >= 150) { showActionIndicator("MORE ENEMIES!", 2000); } // Check if we need to change level if (points >= 300 && game.nightmareLevelActive && !game.infernoLevelActive) { game.infernoLevelActive = true; game.nightmareLevelActive = true; game.desertLevelActive = true; background.tint = 0xFF3300; // Bright orange-red for inferno level showActionIndicator("INFERNO LEVEL!", 2000); } else if (points >= 200 && game.desertLevelActive && !game.nightmareLevelActive) { game.nightmareLevelActive = true; game.desertLevelActive = true; background.tint = 0x800080; // Purple for nightmare level showActionIndicator("NIGHTMARE LEVEL!", 2000); } else if (points >= 100 && !game.desertLevelActive) { game.desertLevelActive = true; background.tint = 0xE8B06A; // Desert sandy orange-brown color showActionIndicator("DESERT LEVEL!", 2000); } break; } } } // Hearts are now managed by updateHeartDisplay function // Update collectible hearts for (var i = collectibleHearts.length - 1; i >= 0; i--) { collectibleHearts[i].update(); // Remove hearts that are destroyed if (!collectibleHearts[i].parent) { collectibleHearts.splice(i, 1); continue; } // Check for player-heart collisions if (player.intersects(collectibleHearts[i])) { // Player collected a heart collectibleHearts[i].destroy(); collectibleHearts.splice(i, 1); // Add a life if not at maximum if (player.lives < 5) { player.lives++; // Show heart collection indicator showActionIndicator("+1 LIFE!", 1000); // Update heart display updateHeartDisplay(); // Show special indicator when approaching win condition if (points >= 450 && points < 500) { showActionIndicator("ALMOST THERE! " + (500 - points) + " TO WIN!", 1000); } // Get the newest heart for animation var newHeartIndex = player.lives - 1; var heart = heartIcons[newHeartIndex]; // Show animation effect tween(heart, { scaleX: 1.5, scaleY: 1.5 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(heart, { scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeIn }); } }); } } } // Spawn enemies enemySpawnCounter++; if (enemySpawnCounter >= enemySpawnInterval) { var enemy = new Enemy(); enemy.x = 2048; enemy.y = 2732 / 2; // Make enemies faster and with different colors based on level if (game.infernoLevelActive) { enemy.speed = 12; // Even faster enemies in inferno level enemy.tint = 0xFF3300; // Orange-red tint for inferno enemies // Occasionally spawn a second enemy in inferno level if (Math.random() < 0.4) { var extraEnemy = new Enemy(); extraEnemy.x = 2048; extraEnemy.y = 2732 / 2 + (Math.random() > 0.5 ? 200 : -200); // Above or below main path extraEnemy.speed = 10; extraEnemy.tint = 0xFF6600; enemies.push(extraEnemy); game.addChild(extraEnemy); } } else if (game.nightmareLevelActive) { enemy.speed = 8; // Faster enemies in nightmare level enemy.tint = 0xFF0000; // Red tint for nightmare enemies } else if (points >= 150 && game.desertLevelActive) { // More enemies after 150 points in desert level enemy.speed = 6; enemy.tint = 0xCC9900; // Darker desert tint // Occasionally spawn a second enemy after 150 points if (Math.random() < 0.3) { var extraEnemy = new Enemy(); extraEnemy.x = 2048; extraEnemy.y = 2732 / 2 + (Math.random() > 0.5 ? 150 : -150); // Above or below main path extraEnemy.speed = 5; extraEnemy.tint = 0xCCAA00; enemies.push(extraEnemy); game.addChild(extraEnemy); } } enemies.push(enemy); game.addChild(enemy); // Randomize the spawn interval for the next enemy based on level var interval, minInterval; if (game.infernoLevelActive) { interval = 80; // Even more frequent spawns in inferno minInterval = 20; } else if (game.nightmareLevelActive) { interval = 100; minInterval = 30; } else if (points >= 150) { interval = 120; // More frequent after 150 points minInterval = 40; } else { interval = 150; minInterval = 50; } enemySpawnInterval = Math.floor(Math.random() * interval) + minInterval; enemySpawnCounter = 0; } // Spawn collectible hearts heartSpawnCounter++; if (heartSpawnCounter >= heartSpawnInterval) { var heart = new Heart(); heart.x = 2048; heart.y = Math.random() * 600 + 200; // Only spawn in upper third of screen heart.baseY = heart.y; collectibleHearts.push(heart); game.addChild(heart); // Randomize the spawn interval for the next heart (less frequent than enemies) heartSpawnInterval = Math.floor(Math.random() * 300) + 300; heartSpawnCounter = 0; } // Spawn power stars powerStarSpawnCounter++; if (powerStarSpawnCounter >= powerStarSpawnInterval) { var powerStar = new PowerStar(); powerStar.x = 2048; powerStar.y = Math.random() * 600 + 200; // Only spawn in upper third of screen powerStar.baseY = powerStar.y; powerStars.push(powerStar); game.addChild(powerStar); // Randomize the spawn interval for the next power star (less frequent than hearts) powerStarSpawnInterval = Math.floor(Math.random() * 400) + 600; powerStarSpawnCounter = 0; } // Update power stars for (var i = powerStars.length - 1; i >= 0; i--) { powerStars[i].update(); // Remove power stars that are destroyed if (!powerStars[i].parent) { powerStars.splice(i, 1); continue; } // Check for player-power star collisions if (player.intersects(powerStars[i])) { // Player collected a power star powerStars[i].destroy(); powerStars.splice(i, 1); // Activate power star effect player.hasPowerStar = true; player.powerStarTime = Date.now(); // Show power star collection indicator showActionIndicator("STAR POWER!", 1500); // Apply neon glow effect to player var neonColors = [0x00FFFF, 0xFF00FF, 0xFFFF00, 0x00FF00]; player.originalTint = player.children[0].tint; tween(player.children[0], { tint: neonColors[0] }, { duration: 500 }); } } // Update enemies for (var j = enemies.length - 1; j >= 0; j--) { enemies[j].update(); if (player.intersects(enemies[j])) { if (player.hasPowerStar) { // With power star, destroy enemies on contact enemies[j].destroy(); enemies.splice(j, 1); // Increase score LK.setScore(LK.getScore() + 4); // Double points from 2 to 4 during power star scoreText.setText(LK.getScore()); // Increase points - doubled from 10 to 20 points += 20; pointsText.setText('Points: ' + points); // Check if player reached 500 points to win if (points >= 500) { // Set the final score to match the points counter before showing win LK.setScore(points); scoreText.setText(points.toString()); // Make sure the score display is updated before showing win screen pointsText.setText('Points: ' + points); LK.showYouWin(); } // Check if we need to change level // We already handled win condition above, no need for duplicate check // Check if we need to change level if (points >= 300 && game.nightmareLevelActive && !game.infernoLevelActive) { game.infernoLevelActive = true; game.nightmareLevelActive = true; game.desertLevelActive = true; background.tint = 0xFF3300; // Bright orange-red for inferno level showActionIndicator("INFERNO LEVEL!", 2000); } else if (points >= 200 && game.desertLevelActive && !game.nightmareLevelActive) { game.nightmareLevelActive = true; game.desertLevelActive = true; background.tint = 0x800080; // Purple for nightmare level showActionIndicator("NIGHTMARE LEVEL!", 2000); } else if (points >= 100 && !game.desertLevelActive) { game.desertLevelActive = true; background.tint = 0xE8C66A; // Desert sandy color showActionIndicator("DESERT LEVEL!", 2000); } // Show power star effect indicator if (Math.random() > 0.7) { // Only show occasionally to avoid spam showActionIndicator("STAR POWER!", 500); } } else if (!player.invulnerable) { // Player was hit, lose a life player.lives--; // Play hit sound LK.getSound('hit').play(); // Flash screen to indicate damage LK.effects.flashScreen(0xff0000, 500); // Show damage indicator showActionIndicator("-1 LIFE!", 1000); // Make player temporarily invulnerable player.invulnerable = true; player.invulnerableTime = Date.now(); // Update hearts display updateHeartDisplay(); // Check if player is out of lives if (player.lives <= 0) { LK.showGameOver(); } else { // Destroy the enemy that hit the player enemies[j].destroy(); enemies.splice(j, 1); } } } else if (player.x > enemies[j].x && !enemies[j].passed) { enemies[j].passed = true; LK.setScore(LK.getScore() + 1); scoreText.setText(LK.getScore()); } } }; // Handle player interaction var dragNode = null; var actionIndicator = null; // Create visual indicators for player actions function showActionIndicator(text, duration) { // Remove any existing indicator if (actionIndicator && actionIndicator.parent) { actionIndicator.parent.removeChild(actionIndicator); } // Create new indicator actionIndicator = new Container(); game.addChild(actionIndicator); // Check if this is a level announcement var isLevelAnnouncement = text.includes("LEVEL"); // Set size and position based on type of announcement var bgWidth = isLevelAnnouncement ? 800 : 300; var bgHeight = isLevelAnnouncement ? 160 : 80; var textSize = isLevelAnnouncement ? 120 : 50; // Add background with lower alpha for better transparency var bg = actionIndicator.attachAsset('rect', { width: bgWidth, height: bgHeight, color: 0x000000, shape: 'box', anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); // Add text var txt = new Text2(text, { size: textSize, fill: 0xFFFFFF, align: 'center' }); txt.anchor.set(0.5, 0.5); actionIndicator.addChild(txt); // Position differently based on type if (isLevelAnnouncement) { // Position at the bottom of the screen for level announcements actionIndicator.x = 2048 / 2; // Center horizontally actionIndicator.y = 2732 - 400; // Near bottom of screen } else { // Position above player for regular announcements actionIndicator.x = player.x; actionIndicator.y = player.y - 150; } // Fade out after duration actionIndicator.alpha = 1; tween(actionIndicator, { alpha: 0, y: isLevelAnnouncement ? actionIndicator.y - 100 : actionIndicator.y - 50 }, { duration: duration, easing: tween.easeOut, onFinish: function onFinish() { if (actionIndicator && actionIndicator.parent) { actionIndicator.parent.removeChild(actionIndicator); } } }); } // Function to handle movement and shooting while holding function handleMove(x, y, obj) { if (dragNode) { // Only move player horizontally when dragging // Limit movement to keep player on screen var minX = 100; // Minimum x-coordinate var maxX = 2048 - 100; // Maximum x-coordinate dragNode.x = Math.max(minX, Math.min(x, maxX)); // Keep the player at the same vertical position if not jumping // (but don't override the tween animation when jumping) if (!player.isJumping) { dragNode.y = 2732 / 2; } // If holding finger on screen, continuously shoot if (shootTimer > 0) { // Reduced fire interval based on power star status var fireInterval = player.hasPowerStar ? 5 : 10; // Only shoot every interval ticks to control fire rate if (LK.ticks % fireInterval === 0) { // Create main star var star = new Star(); star.x = player.x + 100; star.y = player.y; stars.push(star); game.addChild(star); // If player has power star, create spread shots if (player.hasPowerStar) { // Add two additional stars with slight angle variations for (var i = -1; i <= 1; i += 2) { var spreadStar = new Star(); spreadStar.x = player.x + 100; spreadStar.y = player.y; // Apply small angular deviation var angle = i * 0.2; // ~11 degrees up/down spreadStar.speedY = Math.sin(angle) * 5; spreadStar.speedX = Math.cos(angle) * spreadStar.speed; // Override default update method for angled stars spreadStar.update = function () { this.lastY = this.y; this.lastX = this.x; this.x += this.speedX; this.y += this.speedY; if (this.x > 2048 + 50) { this.destroy(); } }; stars.push(spreadStar); game.addChild(spreadStar); } // Show visual effect for powerful shots if (LK.ticks % 20 === 0) { showActionIndicator("POWER SHOTS!", 500); } } // Play shooting sound LK.getSound('shoot').play(); } } } } // shootTimer already declared earlier in the code // Start tracking player movement on touch down and shoot on hold game.down = function (x, y, obj) { // Always make the player jump on tap var jumpMessage = "JUMP!"; // Show different message for double jump if (player.isJumping && player.canDoubleJump) { jumpMessage = "DOUBLE JUMP!"; } player.jump(); // Show jump indicator with appropriate message showActionIndicator(jumpMessage, 800); // Start shooting - fire immediately when pressing shootTimer = Date.now(); // Fire initial shot burst var initialStar = new Star(); initialStar.x = player.x + 100; initialStar.y = player.y; stars.push(initialStar); game.addChild(initialStar); LK.getSound('shoot').play(); // If player has power star, add enhanced initial burst if (player.hasPowerStar) { // Create a burst of 3 stars in a spread pattern for (var angle = -0.3; angle <= 0.3; angle += 0.3) { if (angle === 0) { continue; } // Skip center (already created) var spreadStar = new Star(); spreadStar.x = player.x + 100; spreadStar.y = player.y; spreadStar.speedY = Math.sin(angle) * 8; spreadStar.speedX = Math.cos(angle) * spreadStar.speed; spreadStar.rotationSpeed = 0.15; // Faster rotation stars.push(spreadStar); game.addChild(spreadStar); } showActionIndicator("POWER BURST!", 500); } // Handle regular movement without repositioning the player at tap position dragNode = player; }; // Update player position during movement game.move = handleMove; // Stop tracking player movement and shooting on touch up game.up = function (x, y, obj) { dragNode = null; shootTimer = 0; // Reset shoot timer };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Define a class for enemies
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.update = function () {
self.x -= self.speed;
if (self.x < -50) {
self.destroy();
}
};
});
// Define a class for collectible hearts
var Heart = Container.expand(function () {
var self = Container.call(this);
var heartGraphics = self.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1
});
self.speed = 5;
self.lastY = self.y;
self.lastX = self.x;
// Add some floating animation
self.floatOffset = Math.random() * Math.PI * 2;
self.floatSpeed = 0.05;
self.baseY = 0;
self.update = function () {
// Store last position for collision detection
self.lastY = self.y;
self.lastX = self.x;
// Move the heart
self.x -= self.speed;
// Floating animation
self.y = self.baseY + Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * 20;
// Remove if offscreen
if (self.x < -50) {
self.destroy();
}
};
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 playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.jumpHeight = 40;
self.isJumping = false;
self.canDoubleJump = false; // Track if player can perform double jump
self.velocityY = 0;
self.update = function () {
// No need for physics-based jump calculation anymore
// Animation is handled by tweens in jump method
};
self.jump = function () {
// First jump
if (!self.isJumping) {
self.isJumping = true;
self.canDoubleJump = true; // Enable double jump after first jump
// Use tween for smoother jump animation
var initialY = self.y;
var peakY = initialY - 500; // Jump peak height - increased from 300 to 500
// Store current X position to prevent horizontal movement during jump
var currentX = self.x;
tween(self, {
y: peakY
}, {
duration: 500,
easing: tween.easeOutQuad,
onFinish: function onFinish() {
// Fall back down with easing
tween(self, {
y: 2732 / 2 // Ground level
}, {
duration: 600,
easing: tween.easeInQuad,
onFinish: function onFinish() {
self.isJumping = false;
self.canDoubleJump = false; // Reset double jump ability
self.velocityY = 0;
}
});
}
});
}
// Second jump (double jump)
else if (self.canDoubleJump) {
self.canDoubleJump = false; // Used double jump
// Cancel any existing tweens on player
tween.cancelAll(self);
// Current Y position becomes the new starting point
var currentY = self.y;
var doubleJumpPeakY = currentY - 400; // Slightly lower second jump
// Store current X position to prevent horizontal movement during double jump
var currentX = self.x;
// Perform double jump animation
tween(self, {
y: doubleJumpPeakY
}, {
duration: 400,
easing: tween.easeOutQuad,
onFinish: function onFinish() {
// Fall back down with easing
tween(self, {
y: 2732 / 2 // Ground level
}, {
duration: 500,
easing: tween.easeInQuad,
onFinish: function onFinish() {
self.isJumping = false;
self.velocityY = 0;
}
});
}
});
}
};
});
// Define a class for collectible power-up stars
var PowerStar = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2
});
self.speed = 4;
self.lastY = self.y;
self.lastX = self.x;
// Add floating animation
self.floatOffset = Math.random() * Math.PI * 2;
self.floatSpeed = 0.07;
self.baseY = 0;
// Add spinning animation
self.rotation = 0;
self.rotationSpeed = 0.05;
self.update = function () {
// Store last position for collision detection
self.lastY = self.y;
self.lastX = self.x;
// Move the star
self.x -= self.speed;
// Floating animation
self.y = self.baseY + Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * 25;
// Spinning animation
self.rotation += self.rotationSpeed;
// Remove if offscreen
if (self.x < -50) {
self.destroy();
}
};
return self;
});
// Define a class for star bullets
var Star = Container.expand(function () {
var self = Container.call(this);
// Create a yellow star shape using the built-in shape feature
var starGraphics = self.attachAsset('star', {
width: 50,
height: 50,
color: 0xffff00,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.speedX = 10; // Horizontal speed
self.speedY = 0; // Vertical speed (default to 0 for straight shots)
self.rotation = 0; // Current rotation
self.rotationSpeed = 0.1; // Rotation speed for spinning stars
// Store the last position for collision detection
self.lastY = self.y;
self.lastX = self.x;
// Add a pulsing effect
self.scaleDirection = 1;
self.scaleSpeed = 0.02;
self.minScale = 0.8;
self.maxScale = 1.2;
self.update = function () {
// Store last position before update
self.lastY = self.y;
self.lastX = self.x;
// Move the star according to its speed components
self.x += self.speedX;
self.y += self.speedY;
// Rotate the star for visual effect
self.rotation += self.rotationSpeed;
starGraphics.rotation = self.rotation;
// Pulse scaling effect
if (self.scaleDirection > 0) {
starGraphics.scale.x += self.scaleSpeed;
starGraphics.scale.y += self.scaleSpeed;
if (starGraphics.scale.x >= self.maxScale) {
self.scaleDirection = -1;
}
} else {
starGraphics.scale.x -= self.scaleSpeed;
starGraphics.scale.y -= self.scaleSpeed;
if (starGraphics.scale.x <= self.minScale) {
self.scaleDirection = 1;
}
}
// Remove if it goes off-screen
if (self.x > 2048 + 50 || self.y < -50 || self.y > 2732 + 50) {
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// Ensure tween.cancelAll is available
if (!tween.cancelAll) {
tween.cancelAll = function (target) {
// Find all active tweens affecting this target and cancel them
var allTweens = [];
// Get all tweens
if (tween.getAll && typeof tween.getAll === 'function') {
allTweens = tween.getAll();
} else {
// Fallback implementation if getAll is not available
if (tween._tweens && Array.isArray(tween._tweens)) {
allTweens = tween._tweens;
}
}
// Cancel tweens for target
if (allTweens.length > 0) {
allTweens.forEach(function (t) {
if (t && t._target === target && typeof t.cancel === 'function') {
t.cancel();
}
});
}
// If no direct way to access tweens, cancel by calling tween with duration 0
tween(target, {}, {
duration: 0
});
};
}
var background = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0
}));
background.x = 0;
background.y = 0;
game.desertLevelActive = false;
game.nightmareLevelActive = false;
game.infernoLevelActive = false;
// Initialize player
var player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 / 2;
player.lives = 3;
player.invulnerable = false;
player.invulnerableTime = 0;
player.hasPowerStar = false;
player.powerStarTime = 0;
player.originalTint = 0xFFFFFF;
// Initialize enemies
var enemies = [];
var enemySpawnInterval = 100;
var enemySpawnCounter = 0;
// Initialize collectible hearts
var collectibleHearts = [];
var heartSpawnInterval = 300; // Less frequent than enemies
var heartSpawnCounter = 0;
// Initialize power stars
var powerStars = [];
var powerStarSpawnInterval = 600; // Even less frequent than hearts
var powerStarSpawnCounter = 0;
// Create life display with proper heart images
var maxHearts = 5; // Maximum number of hearts
var heartsContainer = new Container();
LK.gui.top.addChild(heartsContainer);
heartsContainer.x = 0; // Will be centered
heartsContainer.y = 150; // Offset from top edge
// Create heart icons array - we'll display both filled and empty hearts
var heartIcons = [];
// Function to update heart display
function updateHeartDisplay() {
// Remove existing hearts
while (heartsContainer.children.length > 0) {
heartsContainer.removeChildAt(0);
}
// Add heart icons
for (var i = 0; i < player.lives; i++) {
var heart = heartsContainer.addChild(LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1
}));
// Position hearts in a row, centered
var heartSpacing = 130;
var totalWidth = (player.lives - 1) * heartSpacing;
heart.x = -totalWidth / 2 + i * heartSpacing;
heartIcons[i] = heart;
}
}
// Initialize heart display
updateHeartDisplay();
// Create a new Text2 object to display the score
var scoreText = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
// Add the score text to the game GUI at the top center of the screen
LK.gui.top.addChild(scoreText);
scoreText.x = 2048 / 2;
scoreText.y = 0;
// Create points counter and display
var points = 0;
var pointsText = new Text2('Points: 0', {
size: 80,
fill: 0xFFFFFF
});
LK.gui.topRight.addChild(pointsText);
pointsText.anchor.set(1, 0);
pointsText.x = -20;
pointsText.y = 0;
// Create instruction text with black background
var instructionContainer = new Container();
LK.gui.center.addChild(instructionContainer);
instructionContainer.y = 300;
// Create black background for instructions
var instructionBg = new Container();
instructionBg.width = 1000;
instructionBg.height = 350;
instructionContainer.addChild(instructionBg);
// Create a black rectangle background
var blackBg = instructionBg.attachAsset('rect', {
width: 1000,
height: 350,
color: 0x000000,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9
});
// Create instruction text with more detailed controls
var instructionText = new Text2('TAP to JUMP\nHOLD to continuously SHOOT', {
size: 60,
fill: 0xFFFFFF,
align: 'center'
});
instructionText.anchor.set(0.5, 0.5);
instructionContainer.addChild(instructionText);
// Create a timeout to hide instructions after 6 seconds (reduced by 2 seconds)
LK.setTimeout(function () {
// Fade out instructions
var alpha = 1;
var fadeInterval = LK.setInterval(function () {
alpha -= 0.05; // Slower fade for better readability
instructionContainer.alpha = alpha; // Fade the entire container including background
if (alpha <= 0) {
LK.clearInterval(fadeInterval);
instructionContainer.visible = false;
}
}, 100);
}, 6000);
// Handle game updates
// Array to store bullets
var stars = [];
var shootTimer = 0;
game.update = function () {
player.update();
// Handle player invulnerability from damage
if (player.invulnerable && !player.hasPowerStar) {
// Make player flash to indicate invulnerability
player.alpha = Math.sin(Date.now() * 0.01) * 0.5 + 0.5;
// End invulnerability after 2 seconds
if (Date.now() - player.invulnerableTime > 2000) {
player.invulnerable = false;
player.alpha = 1;
}
}
// Handle power star invincibility
if (player.hasPowerStar) {
// Make player glow with neon colors
var elapsed = Date.now() - player.powerStarTime;
var colorIndex = Math.floor(elapsed / 300 % 4);
var neonColors = [0x00FFFF, 0xFF00FF, 0xFFFF00, 0x00FF00];
player.children[0].tint = neonColors[colorIndex];
// Player is invulnerable during power star effect
player.invulnerable = true;
player.alpha = 1;
// End power star effect after 10 seconds instead of 20
if (elapsed > 10000) {
player.hasPowerStar = false;
player.invulnerable = false;
// Restore original appearance
player.children[0].tint = player.originalTint;
// Show power star end indicator
showActionIndicator("POWER LOST", 1000);
}
}
// Removed auto-shooting to only allow double tap shooting
// Update stars
for (var i = stars.length - 1; i >= 0; i--) {
stars[i].update();
// Remove stars that are destroyed
if (!stars[i].parent) {
stars.splice(i, 1);
continue;
}
// Check for star-enemy collisions
for (var j = enemies.length - 1; j >= 0; j--) {
if (stars[i] && enemies[j] && stars[i].intersects(enemies[j])) {
// Remove the enemy and the star
enemies[j].destroy();
enemies.splice(j, 1);
stars[i].destroy();
stars.splice(i, 1);
// Increase score
LK.setScore(LK.getScore() + 1);
scoreText.setText(LK.getScore());
// Update points
points += 10;
pointsText.setText('Points: ' + points);
// Check if player reached 500 points to win
if (points >= 500) {
LK.showYouWin();
}
// Check if we just passed 150 points for the enemy increase announcement
if (points - 10 < 150 && points >= 150) {
showActionIndicator("MORE ENEMIES!", 2000);
}
// Check if we need to change level
if (points >= 300 && game.nightmareLevelActive && !game.infernoLevelActive) {
game.infernoLevelActive = true;
game.nightmareLevelActive = true;
game.desertLevelActive = true;
background.tint = 0xFF3300; // Bright orange-red for inferno level
showActionIndicator("INFERNO LEVEL!", 2000);
} else if (points >= 200 && game.desertLevelActive && !game.nightmareLevelActive) {
game.nightmareLevelActive = true;
game.desertLevelActive = true;
background.tint = 0x800080; // Purple for nightmare level
showActionIndicator("NIGHTMARE LEVEL!", 2000);
} else if (points >= 100 && !game.desertLevelActive) {
game.desertLevelActive = true;
background.tint = 0xE8B06A; // Desert sandy orange-brown color
showActionIndicator("DESERT LEVEL!", 2000);
}
break;
}
}
}
// Hearts are now managed by updateHeartDisplay function
// Update collectible hearts
for (var i = collectibleHearts.length - 1; i >= 0; i--) {
collectibleHearts[i].update();
// Remove hearts that are destroyed
if (!collectibleHearts[i].parent) {
collectibleHearts.splice(i, 1);
continue;
}
// Check for player-heart collisions
if (player.intersects(collectibleHearts[i])) {
// Player collected a heart
collectibleHearts[i].destroy();
collectibleHearts.splice(i, 1);
// Add a life if not at maximum
if (player.lives < 5) {
player.lives++;
// Show heart collection indicator
showActionIndicator("+1 LIFE!", 1000);
// Update heart display
updateHeartDisplay();
// Show special indicator when approaching win condition
if (points >= 450 && points < 500) {
showActionIndicator("ALMOST THERE! " + (500 - points) + " TO WIN!", 1000);
}
// Get the newest heart for animation
var newHeartIndex = player.lives - 1;
var heart = heartIcons[newHeartIndex];
// Show animation effect
tween(heart, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(heart, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeIn
});
}
});
}
}
}
// Spawn enemies
enemySpawnCounter++;
if (enemySpawnCounter >= enemySpawnInterval) {
var enemy = new Enemy();
enemy.x = 2048;
enemy.y = 2732 / 2;
// Make enemies faster and with different colors based on level
if (game.infernoLevelActive) {
enemy.speed = 12; // Even faster enemies in inferno level
enemy.tint = 0xFF3300; // Orange-red tint for inferno enemies
// Occasionally spawn a second enemy in inferno level
if (Math.random() < 0.4) {
var extraEnemy = new Enemy();
extraEnemy.x = 2048;
extraEnemy.y = 2732 / 2 + (Math.random() > 0.5 ? 200 : -200); // Above or below main path
extraEnemy.speed = 10;
extraEnemy.tint = 0xFF6600;
enemies.push(extraEnemy);
game.addChild(extraEnemy);
}
} else if (game.nightmareLevelActive) {
enemy.speed = 8; // Faster enemies in nightmare level
enemy.tint = 0xFF0000; // Red tint for nightmare enemies
} else if (points >= 150 && game.desertLevelActive) {
// More enemies after 150 points in desert level
enemy.speed = 6;
enemy.tint = 0xCC9900; // Darker desert tint
// Occasionally spawn a second enemy after 150 points
if (Math.random() < 0.3) {
var extraEnemy = new Enemy();
extraEnemy.x = 2048;
extraEnemy.y = 2732 / 2 + (Math.random() > 0.5 ? 150 : -150); // Above or below main path
extraEnemy.speed = 5;
extraEnemy.tint = 0xCCAA00;
enemies.push(extraEnemy);
game.addChild(extraEnemy);
}
}
enemies.push(enemy);
game.addChild(enemy);
// Randomize the spawn interval for the next enemy based on level
var interval, minInterval;
if (game.infernoLevelActive) {
interval = 80; // Even more frequent spawns in inferno
minInterval = 20;
} else if (game.nightmareLevelActive) {
interval = 100;
minInterval = 30;
} else if (points >= 150) {
interval = 120; // More frequent after 150 points
minInterval = 40;
} else {
interval = 150;
minInterval = 50;
}
enemySpawnInterval = Math.floor(Math.random() * interval) + minInterval;
enemySpawnCounter = 0;
}
// Spawn collectible hearts
heartSpawnCounter++;
if (heartSpawnCounter >= heartSpawnInterval) {
var heart = new Heart();
heart.x = 2048;
heart.y = Math.random() * 600 + 200; // Only spawn in upper third of screen
heart.baseY = heart.y;
collectibleHearts.push(heart);
game.addChild(heart);
// Randomize the spawn interval for the next heart (less frequent than enemies)
heartSpawnInterval = Math.floor(Math.random() * 300) + 300;
heartSpawnCounter = 0;
}
// Spawn power stars
powerStarSpawnCounter++;
if (powerStarSpawnCounter >= powerStarSpawnInterval) {
var powerStar = new PowerStar();
powerStar.x = 2048;
powerStar.y = Math.random() * 600 + 200; // Only spawn in upper third of screen
powerStar.baseY = powerStar.y;
powerStars.push(powerStar);
game.addChild(powerStar);
// Randomize the spawn interval for the next power star (less frequent than hearts)
powerStarSpawnInterval = Math.floor(Math.random() * 400) + 600;
powerStarSpawnCounter = 0;
}
// Update power stars
for (var i = powerStars.length - 1; i >= 0; i--) {
powerStars[i].update();
// Remove power stars that are destroyed
if (!powerStars[i].parent) {
powerStars.splice(i, 1);
continue;
}
// Check for player-power star collisions
if (player.intersects(powerStars[i])) {
// Player collected a power star
powerStars[i].destroy();
powerStars.splice(i, 1);
// Activate power star effect
player.hasPowerStar = true;
player.powerStarTime = Date.now();
// Show power star collection indicator
showActionIndicator("STAR POWER!", 1500);
// Apply neon glow effect to player
var neonColors = [0x00FFFF, 0xFF00FF, 0xFFFF00, 0x00FF00];
player.originalTint = player.children[0].tint;
tween(player.children[0], {
tint: neonColors[0]
}, {
duration: 500
});
}
}
// Update enemies
for (var j = enemies.length - 1; j >= 0; j--) {
enemies[j].update();
if (player.intersects(enemies[j])) {
if (player.hasPowerStar) {
// With power star, destroy enemies on contact
enemies[j].destroy();
enemies.splice(j, 1);
// Increase score
LK.setScore(LK.getScore() + 4); // Double points from 2 to 4 during power star
scoreText.setText(LK.getScore());
// Increase points - doubled from 10 to 20
points += 20;
pointsText.setText('Points: ' + points);
// Check if player reached 500 points to win
if (points >= 500) {
// Set the final score to match the points counter before showing win
LK.setScore(points);
scoreText.setText(points.toString());
// Make sure the score display is updated before showing win screen
pointsText.setText('Points: ' + points);
LK.showYouWin();
}
// Check if we need to change level
// We already handled win condition above, no need for duplicate check
// Check if we need to change level
if (points >= 300 && game.nightmareLevelActive && !game.infernoLevelActive) {
game.infernoLevelActive = true;
game.nightmareLevelActive = true;
game.desertLevelActive = true;
background.tint = 0xFF3300; // Bright orange-red for inferno level
showActionIndicator("INFERNO LEVEL!", 2000);
} else if (points >= 200 && game.desertLevelActive && !game.nightmareLevelActive) {
game.nightmareLevelActive = true;
game.desertLevelActive = true;
background.tint = 0x800080; // Purple for nightmare level
showActionIndicator("NIGHTMARE LEVEL!", 2000);
} else if (points >= 100 && !game.desertLevelActive) {
game.desertLevelActive = true;
background.tint = 0xE8C66A; // Desert sandy color
showActionIndicator("DESERT LEVEL!", 2000);
}
// Show power star effect indicator
if (Math.random() > 0.7) {
// Only show occasionally to avoid spam
showActionIndicator("STAR POWER!", 500);
}
} else if (!player.invulnerable) {
// Player was hit, lose a life
player.lives--;
// Play hit sound
LK.getSound('hit').play();
// Flash screen to indicate damage
LK.effects.flashScreen(0xff0000, 500);
// Show damage indicator
showActionIndicator("-1 LIFE!", 1000);
// Make player temporarily invulnerable
player.invulnerable = true;
player.invulnerableTime = Date.now();
// Update hearts display
updateHeartDisplay();
// Check if player is out of lives
if (player.lives <= 0) {
LK.showGameOver();
} else {
// Destroy the enemy that hit the player
enemies[j].destroy();
enemies.splice(j, 1);
}
}
} else if (player.x > enemies[j].x && !enemies[j].passed) {
enemies[j].passed = true;
LK.setScore(LK.getScore() + 1);
scoreText.setText(LK.getScore());
}
}
};
// Handle player interaction
var dragNode = null;
var actionIndicator = null;
// Create visual indicators for player actions
function showActionIndicator(text, duration) {
// Remove any existing indicator
if (actionIndicator && actionIndicator.parent) {
actionIndicator.parent.removeChild(actionIndicator);
}
// Create new indicator
actionIndicator = new Container();
game.addChild(actionIndicator);
// Check if this is a level announcement
var isLevelAnnouncement = text.includes("LEVEL");
// Set size and position based on type of announcement
var bgWidth = isLevelAnnouncement ? 800 : 300;
var bgHeight = isLevelAnnouncement ? 160 : 80;
var textSize = isLevelAnnouncement ? 120 : 50;
// Add background with lower alpha for better transparency
var bg = actionIndicator.attachAsset('rect', {
width: bgWidth,
height: bgHeight,
color: 0x000000,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
// Add text
var txt = new Text2(text, {
size: textSize,
fill: 0xFFFFFF,
align: 'center'
});
txt.anchor.set(0.5, 0.5);
actionIndicator.addChild(txt);
// Position differently based on type
if (isLevelAnnouncement) {
// Position at the bottom of the screen for level announcements
actionIndicator.x = 2048 / 2; // Center horizontally
actionIndicator.y = 2732 - 400; // Near bottom of screen
} else {
// Position above player for regular announcements
actionIndicator.x = player.x;
actionIndicator.y = player.y - 150;
}
// Fade out after duration
actionIndicator.alpha = 1;
tween(actionIndicator, {
alpha: 0,
y: isLevelAnnouncement ? actionIndicator.y - 100 : actionIndicator.y - 50
}, {
duration: duration,
easing: tween.easeOut,
onFinish: function onFinish() {
if (actionIndicator && actionIndicator.parent) {
actionIndicator.parent.removeChild(actionIndicator);
}
}
});
}
// Function to handle movement and shooting while holding
function handleMove(x, y, obj) {
if (dragNode) {
// Only move player horizontally when dragging
// Limit movement to keep player on screen
var minX = 100; // Minimum x-coordinate
var maxX = 2048 - 100; // Maximum x-coordinate
dragNode.x = Math.max(minX, Math.min(x, maxX));
// Keep the player at the same vertical position if not jumping
// (but don't override the tween animation when jumping)
if (!player.isJumping) {
dragNode.y = 2732 / 2;
}
// If holding finger on screen, continuously shoot
if (shootTimer > 0) {
// Reduced fire interval based on power star status
var fireInterval = player.hasPowerStar ? 5 : 10;
// Only shoot every interval ticks to control fire rate
if (LK.ticks % fireInterval === 0) {
// Create main star
var star = new Star();
star.x = player.x + 100;
star.y = player.y;
stars.push(star);
game.addChild(star);
// If player has power star, create spread shots
if (player.hasPowerStar) {
// Add two additional stars with slight angle variations
for (var i = -1; i <= 1; i += 2) {
var spreadStar = new Star();
spreadStar.x = player.x + 100;
spreadStar.y = player.y;
// Apply small angular deviation
var angle = i * 0.2; // ~11 degrees up/down
spreadStar.speedY = Math.sin(angle) * 5;
spreadStar.speedX = Math.cos(angle) * spreadStar.speed;
// Override default update method for angled stars
spreadStar.update = function () {
this.lastY = this.y;
this.lastX = this.x;
this.x += this.speedX;
this.y += this.speedY;
if (this.x > 2048 + 50) {
this.destroy();
}
};
stars.push(spreadStar);
game.addChild(spreadStar);
}
// Show visual effect for powerful shots
if (LK.ticks % 20 === 0) {
showActionIndicator("POWER SHOTS!", 500);
}
}
// Play shooting sound
LK.getSound('shoot').play();
}
}
}
}
// shootTimer already declared earlier in the code
// Start tracking player movement on touch down and shoot on hold
game.down = function (x, y, obj) {
// Always make the player jump on tap
var jumpMessage = "JUMP!";
// Show different message for double jump
if (player.isJumping && player.canDoubleJump) {
jumpMessage = "DOUBLE JUMP!";
}
player.jump();
// Show jump indicator with appropriate message
showActionIndicator(jumpMessage, 800);
// Start shooting - fire immediately when pressing
shootTimer = Date.now();
// Fire initial shot burst
var initialStar = new Star();
initialStar.x = player.x + 100;
initialStar.y = player.y;
stars.push(initialStar);
game.addChild(initialStar);
LK.getSound('shoot').play();
// If player has power star, add enhanced initial burst
if (player.hasPowerStar) {
// Create a burst of 3 stars in a spread pattern
for (var angle = -0.3; angle <= 0.3; angle += 0.3) {
if (angle === 0) {
continue;
} // Skip center (already created)
var spreadStar = new Star();
spreadStar.x = player.x + 100;
spreadStar.y = player.y;
spreadStar.speedY = Math.sin(angle) * 8;
spreadStar.speedX = Math.cos(angle) * spreadStar.speed;
spreadStar.rotationSpeed = 0.15; // Faster rotation
stars.push(spreadStar);
game.addChild(spreadStar);
}
showActionIndicator("POWER BURST!", 500);
}
// Handle regular movement without repositioning the player at tap position
dragNode = player;
};
// Update player position during movement
game.move = handleMove;
// Stop tracking player movement and shooting on touch up
game.up = function (x, y, obj) {
dragNode = null;
shootTimer = 0; // Reset shoot timer
};
I need an octopus that looks like bowser. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Heart illustration red shinny. Single Game Texture. 2d. Blank background. High contrast. No shadows
Star illustration shinny. Single Game Texture. Blank background. High contrast. No shadows
Make it more detailed and add flying dinosaurs
Flying dinosaur with spikes. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows