User prompt
Remplaza el contador de vidas por una imagen , que cada número esté representado por una imagen del 0 al 3
User prompt
Cambia la imagen del avatar del jugador 1 a una nueva imagen
User prompt
Cambia la imagen del avatar del jugador 1
User prompt
Arregla la pantalla de victoria, en vez de mostrar puntos, muestre la cantidad de enemigos que el jugador 1 derrotó
User prompt
Mueve el botón de salto a la derecha, arriba del botón de ataque
User prompt
Mueve la imagen y contador de vidas a la parte superior derecha
User prompt
Que solo sea la imagen y el contador de vidas del jugador 1 visible
User prompt
Solo se ven las vidas del jugador 1 y 2 , ajustalo para que se vea también el del jugador 3 y 4
User prompt
Al iniciar solo aparecen las imágenes y las vidas del jugador 1 y 2 , arreglalo para que la imagen y cantidad de vidas de todos los jugadores sea visible
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'player1LivesText.style.fill = player1Lives > 0 ? 0xFFFFFF : 0x888888;' Line Number: 1381
User prompt
Elimina el texto de estado de los jugadores y agrega una imagen individual junto con un contador de vidas para cara jugador
User prompt
Las flores ya no son visibles, arreglalo por favor
User prompt
Las flores aparecen por delante de los jugadores, arreglalo para que este por detrás
User prompt
Cuando termine el modo tormenta, hacer que crezcan flores donde más cayeron gotas ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Aumenta la anchura del spawn de las gotas de lluvia para que cubra todo el borde superior
User prompt
Centra el spawn de las gotas de lluvia a la base principal
User prompt
Vuelve más ancho el spawn de las gotas de lluvia
User prompt
Aumenta la distancia de la aparición de las gotas hacia la derecha por 500
User prompt
Que la aparición de las gotas sigan el movimiento de la camara
User prompt
El tamaño que reduce las gotas a los jugadores se restablece , arreglalo por favor ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Que las gotas reduscan el tamaño del jugador un 10% ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Que el tamaño que reduce las gotas a los jugadores sea permanente a menos que sean eliminados ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Cambia la reducción de tamaño de las gotas al entrar en contacto con un jugador a un 5% ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Mientras más tarde el modo tormenta, más cantidad de gotas caerán cada 5 segundos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Cambia la reducción de tamaño por gotas a un 1.0% ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Fighter = Container.expand(function (playerNumber, color) { var self = Container.call(this); var assetName = 'player1'; if (playerNumber === 2) assetName = 'player2';else if (playerNumber === 3) assetName = 'player3';else if (playerNumber === 4) assetName = 'player4'; var fighterGraphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 1.0 }); self.playerNumber = playerNumber; self.velocityX = 0; self.velocityY = 0; self.onGround = false; self.jumpsRemaining = 2; // Allow double jump self.health = 0; self.maxHealth = 100; self.damage = 0; // New damage accumulation property self.moveSpeed = 8; self.jumpPower = 25; self.knockbackResistance = 1.0; self.lastHitTime = 0; self.invulnerable = false; self.powerupCount = 0; // Track number of powerups collected self.baseMoveSpeed = 8; // Store original move speed self.baseJumpPower = 25; // Store original jump power self.baseDamage = 15; // Store original damage self.baseKnockback = 20; // Store original knockback self.lastVelocityX = 0; // Track last velocity for rotation self.isWheelMode = false; // Track if in wheel mode self.wheelModeTimer = 0; // Timer for wheel mode duration self.wheelGraphics = null; // Reference to wheel graphics // Create damage bar background var damageBarBg = self.addChild(LK.getAsset('platform', { width: 100, height: 12, anchorX: 0.5, anchorY: 1.0, x: 0, y: -130 })); damageBarBg.tint = 0x333333; damageBarBg.scaleX = 0.8; damageBarBg.scaleY = 0.3; // Create damage bar fill self.damageBar = self.addChild(LK.getAsset('platform', { width: 100, height: 12, anchorX: 0, anchorY: 1.0, x: -40, y: -130 })); self.damageBar.tint = 0xff4444; self.damageBar.scaleX = 0; self.damageBar.scaleY = 0.3; // Create damage text self.damageText = self.addChild(new Text2('0%', { size: 30, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 4 })); self.damageText.anchor.set(0.5, 1); self.damageText.x = 0; self.damageText.y = -140; self.takeDamage = function (damage, knockbackX, knockbackY) { if (self.invulnerable) return; self.health += damage; self.damage += damage; // Accumulate damage for knockback scaling // Cap damage at 999% if (self.damage > 999) self.damage = 999; // Update damage display self.damageText.setText(Math.floor(self.damage) + '%'); // Reapply stroke properties to maintain black background texture if (self.damageText.style) { self.damageText.style.stroke = 0x000000; self.damageText.style.strokeThickness = 4; } // Update damage bar scale (0 to 1 based on damage up to 200%) var barScale = Math.min(self.damage / 200, 1); self.damageBar.scaleX = barScale * 0.8; // Change bar color based on damage level if (self.damage < 50) { self.damageBar.tint = 0x44ff44; // Green for low damage } else if (self.damage < 100) { self.damageBar.tint = 0xffff44; // Yellow for medium damage } else if (self.damage < 150) { self.damageBar.tint = 0xff8844; // Orange for high damage } else { self.damageBar.tint = 0xff4444; // Red for very high damage } // Check if player has reached 200 damage - explosion and life loss if (self.damage >= 200) { // Create explosion effect with tween tween(self, { scaleX: 2.0, scaleY: 2.0, alpha: 0 }, { duration: 500, easing: tween.bounceOut, onFinish: function onFinish() { // Reset scale and alpha after explosion self.scaleX = 1.0; self.scaleY = 1.0; self.alpha = 1.0; // Trigger respawn which handles life loss self.respawn(); } }); // Flash screen effect for dramatic explosion LK.effects.flashScreen(0xff8800, 600); // Play explosion sound effect LK.getSound('explosion').play(); // Reset damage to prevent multiple explosions self.damage = 0; return; // Exit early to prevent further processing this frame } // Knockback multiplier based on accumulated damage - exponential scaling for stronger hits at higher damage var knockbackMultiplier = 1.5 + self.damage / 20 + Math.pow(self.damage / 100, 1.5); // Exponential scaling that increases dramatically with damage self.velocityX += knockbackX * knockbackMultiplier / self.knockbackResistance; self.velocityY += knockbackY * knockbackMultiplier / self.knockbackResistance; // Flash effect when hit LK.effects.flashObject(self, 0xff0000, 300); self.invulnerable = true; LK.setTimeout(function () { self.invulnerable = false; }, 500); LK.getSound('hit').play(); }; self.attack = function (targetX, targetY) { var attackRange = 150; var damage = self.baseDamage + self.powerupCount * 8; // Increase damage by 8 per powerup var baseKnockback = self.baseKnockback + self.powerupCount * 10; // Increase knockback by 10 per powerup for (var i = 0; i < fighters.length; i++) { var target = fighters[i]; if (target === self) continue; var distance = Math.sqrt(Math.pow(target.x - self.x, 2) + Math.pow(target.y - self.y, 2)); if (distance <= attackRange) { var angle = Math.atan2(target.y - self.y, target.x - self.x); var knockbackX = Math.cos(angle) * baseKnockback; var knockbackY = Math.sin(angle) * baseKnockback - 5; // Slight upward angle target.takeDamage(damage, knockbackX, knockbackY); } } }; self.update = function () { // Handle wheel mode timer if (self.isWheelMode) { self.wheelModeTimer--; if (self.wheelModeTimer <= 0) { self.deactivateWheelMode(); } } // Update movement stats based on powerups self.moveSpeed = self.baseMoveSpeed + self.powerupCount * 3; // Increase move speed by 3 per powerup self.jumpPower = self.baseJumpPower + self.powerupCount * 5; // Increase jump power by 5 per powerup // Apply wheel mode bonuses if (self.isWheelMode) { self.moveSpeed *= 1.5; self.jumpPower *= 1.3; } // Apply gravity if (!self.onGround) { self.velocityY += 1.2; } // Apply friction self.velocityX *= 0.85; if (self.onGround) { self.velocityX *= 0.75; } // Limit velocities to prevent teleportation var maxVelocityX = 20; var maxVelocityY = 30; if (self.velocityX > maxVelocityX) { self.velocityX = maxVelocityX; } if (self.velocityX < -maxVelocityX) { self.velocityX = -maxVelocityX; } if (self.velocityY > maxVelocityY) { self.velocityY = maxVelocityY; } if (self.velocityY < -maxVelocityY) { self.velocityY = -maxVelocityY; } // Track last position for smoke trail if (self.lastX === undefined) self.lastX = self.x; if (self.lastY === undefined) self.lastY = self.y; // Update position self.x += self.velocityX; self.y += self.velocityY; // Generate smoke trail when moving var movementSpeed = Math.sqrt(Math.pow(self.x - self.lastX, 2) + Math.pow(self.y - self.lastY, 2)); if (movementSpeed > 3 && LK.ticks % 3 === 0) { // Calculate movement direction var movementDirectionX = self.x - self.lastX; var movementDirectionY = self.y - self.lastY; // Normalize the direction var directionLength = Math.sqrt(movementDirectionX * movementDirectionX + movementDirectionY * movementDirectionY); if (directionLength > 0) { movementDirectionX /= directionLength; movementDirectionY /= directionLength; } // Position smoke trail behind the movement direction var smokeDistance = 30; // Distance behind the player var smokeX = self.x - movementDirectionX * smokeDistance; var smokeY = self.y - movementDirectionY * smokeDistance + 20; var smoke = new SmokeTrail(self.playerNumber, smokeX, smokeY); game.addChild(smoke); smokeTrails.push(smoke); } // Update last position self.lastX = self.x; self.lastY = self.y; // Update visual size based on powerup count var targetScale = 1.0 + self.powerupCount * 0.2; // Increase size by 20% per powerup if (Math.abs(fighterGraphics.scaleX) !== targetScale) { var isFlipped = fighterGraphics.scaleX < 0; fighterGraphics.scaleX = isFlipped ? -targetScale : targetScale; fighterGraphics.scaleY = targetScale; } // Handle wheel mode rotation and physics if (self.isWheelMode && self.wheelGraphics) { // Rotate wheel image based on movement direction only if (Math.abs(self.velocityX) > 1) { self.wheelGraphics.rotation += self.velocityX * 0.1; } // Continuous bounce effect when hitting ground - jump every time touching ground if (self.onGround) { self.velocityY = -self.jumpPower; // Jump with same height as normal jump } // Enhanced friction for wheel mode if (self.onGround) { self.velocityX *= 0.95; // More responsive control } } else { // Rotate player based on movement direction (normal mode) if (Math.abs(self.velocityX) > 1) { // Only rotate if moving with significant velocity if (self.velocityX > 0) { // Moving right - face right (normal orientation) fighterGraphics.scaleX = Math.abs(fighterGraphics.scaleX); } else { // Moving left - face left (flip horizontally) fighterGraphics.scaleX = -Math.abs(fighterGraphics.scaleX); } } } // Platform collision var wasOnGround = self.onGround; self.onGround = false; for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; // More precise collision detection with tighter bounds var platformLeft = platform.x - platform.width / 2 + 10; // Add small margin var platformRight = platform.x + platform.width / 2 - 10; // Add small margin var platformTop = platform.y - platform.height / 2; var platformBottom = platform.y + platform.height / 2; // Check if player is within platform horizontal bounds and approaching from above if (self.x >= platformLeft && self.x <= platformRight && self.y >= platformTop - 20 && self.y <= platformBottom + 5 && self.velocityY >= 0) { // Adjust ground position for wheel mode to prevent clipping var groundOffset = self.isWheelMode ? -60 : 0; // Offset wheel players higher to prevent clipping // Snap player to exact platform surface self.y = platformTop + groundOffset; self.velocityY = 0; // Play landing sound if just landed (wasn't on ground before) if (!wasOnGround) { LK.getSound('landing').play(); } self.onGround = true; self.jumpsRemaining = 2; // Reset jumps when landing break; } } // Check if fallen off screen if (self.y > 2900) { // Play fall sound effect LK.getSound('fall').play(); self.respawn(); } // Fighter-to-fighter collision detection and pushing for (var i = 0; i < fighters.length; i++) { var otherFighter = fighters[i]; if (otherFighter === self || otherFighter.destroyed) continue; // Calculate distance between fighters var deltaX = otherFighter.x - self.x; var deltaY = otherFighter.y - self.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); // Check if fighters are colliding (within collision radius) // Use larger radius for wheel mode players var collisionRadius = 80; // Default collision radius if (self.isWheelMode || otherFighter.isWheelMode) { collisionRadius = 120; // Increased radius when either player is in wheel mode } if (distance < collisionRadius && distance > 0) { // Check for wheel mode damage dealing if (self.isWheelMode && !self.lastWheelDamageTime) { self.lastWheelDamageTime = 0; } if (otherFighter.isWheelMode && !otherFighter.lastWheelDamageTime) { otherFighter.lastWheelDamageTime = 0; } // Initialize lastWheelDamageTime if not set if (self.lastWheelDamageTime === undefined) self.lastWheelDamageTime = 0; if (otherFighter.lastWheelDamageTime === undefined) otherFighter.lastWheelDamageTime = 0; // Deal damage if current player is in wheel mode and enough time has passed if (self.isWheelMode && LK.ticks - self.lastWheelDamageTime > 60) { var wheelDamage = 25 + self.powerupCount * 5; // Base wheel damage + powerup bonus var angle = Math.atan2(deltaY, deltaX); var knockbackX = Math.cos(angle) * 15; var knockbackY = Math.sin(angle) * 15 - 3; // Slight upward angle otherFighter.takeDamage(wheelDamage, knockbackX, knockbackY); self.lastWheelDamageTime = LK.ticks; } // Deal damage if other player is in wheel mode and enough time has passed if (otherFighter.isWheelMode && LK.ticks - otherFighter.lastWheelDamageTime > 60) { var wheelDamage = 25 + otherFighter.powerupCount * 5; // Base wheel damage + powerup bonus var angle = Math.atan2(-deltaY, -deltaX); var knockbackX = Math.cos(angle) * 15; var knockbackY = Math.sin(angle) * 15 - 3; // Slight upward angle self.takeDamage(wheelDamage, knockbackX, knockbackY); otherFighter.lastWheelDamageTime = LK.ticks; } // Calculate push force based on overlap var overlap = collisionRadius - distance; var pushStrength = overlap * 0.3; // Adjust push strength // Normalize direction vector var normalX = deltaX / distance; var normalY = deltaY / distance; // Apply push forces to both fighters var pushX = normalX * pushStrength; var pushY = normalY * pushStrength * 0.3; // Reduced vertical push // Push both fighters apart self.velocityX -= pushX; self.velocityY -= pushY; otherFighter.velocityX += pushX; otherFighter.velocityY += pushY; // Separate fighters to prevent overlap var separationX = normalX * (overlap * 0.5); var separationY = normalY * (overlap * 0.3); self.x -= separationX; self.y -= separationY; otherFighter.x += separationX; otherFighter.y += separationY; } } // Screen boundaries (horizontal bouncing) if (self.x < 60) { self.x = 60; if (self.isWheelMode) { self.velocityX = Math.abs(self.velocityX) * 0.8; // Enhanced bounce in wheel mode } else { self.velocityX = Math.abs(self.velocityX) * 0.5; } } if (self.x > 2700) { self.x = 2700; if (self.isWheelMode) { self.velocityX = -Math.abs(self.velocityX) * 0.8; // Enhanced bounce in wheel mode } else { self.velocityX = -Math.abs(self.velocityX) * 0.5; } } }; self.respawn = function () { // Decrease lives for the player who died if (self.playerNumber === 1) { player1Lives--; } else if (self.playerNumber === 2) { player2Lives--; } else if (self.playerNumber === 3) { player3Lives--; } else if (self.playerNumber === 4) { player4Lives--; } updateScoreDisplay(); // Check if player is eliminated (no lives left) var isEliminated = false; if (self.playerNumber === 1 && player1Lives <= 0) { isEliminated = true; } else if (self.playerNumber === 2 && player2Lives <= 0) { isEliminated = true; } else if (self.playerNumber === 3 && player3Lives <= 0) { isEliminated = true; } else if (self.playerNumber === 4 && player4Lives <= 0) { isEliminated = true; } if (isEliminated) { // Track if player 1 defeated an enemy if (self.playerNumber !== 1) { player1EnemiesDefeated++; } // Remove player from the game completely self.destroy(); // Remove from fighters array for (var j = fighters.length - 1; j >= 0; j--) { if (fighters[j] === self) { fighters.splice(j, 1); break; } } activePlayers--; // Check if only one player remains if (activePlayers <= 1) { // Find the winner var winner = ""; if (player1Lives > 0) winner = "Player 1";else if (player2Lives > 0) winner = "Player 2";else if (player3Lives > 0) winner = "Player 3";else if (player4Lives > 0) winner = "Player 4"; LK.setScore(player1EnemiesDefeated); LK.showGameOver(); } } else { // Player still has lives, respawn normally if (self.playerNumber === 1) { self.x = 1048; // Respawn on left platform self.y = 1950; // Just above left platform surface } else if (self.playerNumber === 2) { self.x = 1648; // Respawn on main platform self.y = 2300; // Just above main platform surface } else if (self.playerNumber === 3) { self.x = 1648; // Respawn on top platform self.y = 1600; // Just above top platform surface } else if (self.playerNumber === 4) { self.x = 2248; // Respawn on right platform self.y = 1950; // Just above right platform surface } self.velocityX = 0; self.velocityY = 0; self.health = 0; self.damage = 0; // Reset damage on respawn self.powerupCount = 0; // Reset powerup count on respawn self.damageText.setText('0%'); // Reapply stroke properties to maintain black background texture if (self.damageText.style) { self.damageText.style.stroke = 0x000000; self.damageText.style.strokeThickness = 4; } self.damageBar.scaleX = 0; self.damageBar.tint = 0x44ff44; self.jumpsRemaining = 2; // Reset jumps on respawn } }; self.activateWheelMode = function () { if (self.isWheelMode) return; // Already in wheel mode self.isWheelMode = true; self.wheelModeTimer = 600; // 10 seconds at 60fps // Hide original fighter graphics fighterGraphics.visible = false; // Create wheel graphics based on player number var wheelAsset = 'wheel1'; if (self.playerNumber === 2) wheelAsset = 'wheel2';else if (self.playerNumber === 3) wheelAsset = 'wheel3';else if (self.playerNumber === 4) wheelAsset = 'wheel4'; self.wheelGraphics = self.attachAsset(wheelAsset, { anchorX: 0.5, anchorY: 0.5 }); // Increase move speed and add bounce physics self.moveSpeed *= 1.5; self.jumpPower *= 1.3; }; self.deactivateWheelMode = function () { if (!self.isWheelMode) return; self.isWheelMode = false; self.wheelModeTimer = 0; // Show original fighter graphics fighterGraphics.visible = true; // Remove wheel graphics if (self.wheelGraphics) { self.wheelGraphics.destroy(); self.wheelGraphics = null; } // Reset move speed self.moveSpeed = self.baseMoveSpeed + self.powerupCount * 3; self.jumpPower = self.baseJumpPower + self.powerupCount * 5; }; return self; }); var Firefly = Container.expand(function () { var self = Container.call(this); // Create firefly body var fireflyBody = self.attachAsset('firefly', { anchorX: 0.5, anchorY: 0.5 }); // Create glow effect with 200x200 illumination radius var fireflyGlow = self.attachAsset('fireflyGlow', { anchorX: 0.5, anchorY: 0.5 }); fireflyGlow.alpha = 0.15; // Soft glow effect fireflyGlow.scaleX = 1.0; fireflyGlow.scaleY = 1.0; self.lifeTime = 0; self.maxLifeTime = 2400; // 40 seconds at 60fps - longer than max night cycle self.velocityX = (Math.random() - 0.5) * 2; self.velocityY = (Math.random() - 0.5) * 2; self.glowIntensity = 0.15; self.flickerTimer = 0; self.update = function () { self.lifeTime++; self.flickerTimer++; // Gentle movement pattern self.velocityX += (Math.random() - 0.5) * 0.3; self.velocityY += (Math.random() - 0.5) * 0.3; // Limit velocity for gentle floating if (self.velocityX > 1.5) self.velocityX = 1.5; if (self.velocityX < -1.5) self.velocityX = -1.5; if (self.velocityY > 1.5) self.velocityY = 1.5; if (self.velocityY < -1.5) self.velocityY = -1.5; self.x += self.velocityX; self.y += self.velocityY; // Flicker effect - vary glow intensity var flickerValue = Math.sin(self.flickerTimer * 0.2) * 0.05; fireflyGlow.alpha = self.glowIntensity + flickerValue; fireflyBody.alpha = 0.8 + flickerValue; // Keep within screen bounds if (self.x < 100) { self.x = 100; self.velocityX = Math.abs(self.velocityX); } if (self.x > 1948) { self.x = 1948; self.velocityX = -Math.abs(self.velocityX); } if (self.y < 100) { self.y = 100; self.velocityY = Math.abs(self.velocityY); } if (self.y > 2632) { self.y = 2632; self.velocityY = -Math.abs(self.velocityY); } // Fade out when approaching end of life if (self.lifeTime >= self.maxLifeTime - 180) { // Start fading 3 seconds before end var fadeProgress = (self.lifeTime - (self.maxLifeTime - 180)) / 180; fireflyGlow.alpha = (self.glowIntensity + flickerValue) * (1 - fadeProgress); fireflyBody.alpha = (0.8 + flickerValue) * (1 - fadeProgress); } // Remove when life time is over if (self.lifeTime >= self.maxLifeTime) { self.destroy(); for (var i = fireflies.length - 1; i >= 0; i--) { if (fireflies[i] === self) { fireflies.splice(i, 1); break; } } } }; return self; }); var Flower = Container.expand(function (x, y) { var self = Container.call(this); // Create flower stem var stem = self.attachAsset('flowerStem', { anchorX: 0.5, anchorY: 1.0 }); // Create flower bloom var bloom = self.attachAsset('flower', { anchorX: 0.5, anchorY: 1.0, y: -30 }); self.x = x; self.y = y; self.lifeTime = 0; self.maxLifeTime = 3600; // 60 seconds at 60fps self.growthPhase = 0; // 0=growing, 1=blooming, 2=swaying // Start small and grow stem.scaleX = 0.1; stem.scaleY = 0.1; bloom.scaleX = 0.1; bloom.scaleY = 0.1; bloom.alpha = 0; // Growth animation tween(stem, { scaleX: 1.0, scaleY: 1.0 }, { duration: 1000, easing: tween.easeOut }); // Delayed bloom animation LK.setTimeout(function () { self.growthPhase = 1; tween(bloom, { scaleX: 1.2, scaleY: 1.2, alpha: 1.0 }, { duration: 1500, easing: tween.bounceOut, onFinish: function onFinish() { self.growthPhase = 2; } }); }, 800); self.update = function () { self.lifeTime++; // Gentle swaying motion when fully grown if (self.growthPhase === 2) { var swayAmount = Math.sin(self.lifeTime * 0.05) * 0.1; bloom.rotation = swayAmount; stem.rotation = swayAmount * 0.3; } // Fade out before disappearing if (self.lifeTime >= self.maxLifeTime - 300) { var fadeProgress = (self.lifeTime - (self.maxLifeTime - 300)) / 300; self.alpha = 1 - fadeProgress; } // Remove when life time is over if (self.lifeTime >= self.maxLifeTime) { self.destroy(); for (var i = flowers.length - 1; i >= 0; i--) { if (flowers[i] === self) { flowers.splice(i, 1); break; } } } }; return self; }); var Lightning = Container.expand(function () { var self = Container.call(this); var lightningGraphics = self.attachAsset('lightning', { anchorX: 0.5, anchorY: 0 }); self.lifeTime = 0; self.maxLifeTime = 15; // Very short flash lightningGraphics.alpha = 0.8; self.update = function () { self.lifeTime++; // Flicker effect lightningGraphics.alpha = 0.8 * Math.random(); // Remove after short time if (self.lifeTime >= self.maxLifeTime) { self.destroy(); for (var i = lightningBolts.length - 1; i >= 0; i--) { if (lightningBolts[i] === self) { lightningBolts.splice(i, 1); break; } } } }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.lifeTime = 0; self.maxLifeTime = 600; // 10 seconds at 60fps self.collected = false; self.velocityY = 0; // Falling velocity self.onGround = false; // Track if powerup has landed self.update = function () { self.lifeTime++; self.rotation += 0.05; // Apply gravity if not on ground if (!self.onGround) { self.velocityY += 0.8; // Gravity effect self.y += self.velocityY; // Check platform collision for landing for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; var platformLeft = platform.x - platform.width / 2; var platformRight = platform.x + platform.width / 2; var platformTop = platform.y - platform.height / 2; var platformBottom = platform.y + platform.height / 2; // Check if powerup is within platform bounds and landing on top if (self.x >= platformLeft && self.x <= platformRight && self.y >= platformTop - 30 && self.y <= platformBottom && self.velocityY >= 0) { self.y = platformTop - 30; // Position on top of platform self.velocityY = 0; self.onGround = true; break; } } // Remove if fallen off screen if (self.y > 2800) { self.destroy(); for (var j = powerups.length - 1; j >= 0; j--) { if (powerups[j] === self) { powerups.splice(j, 1); break; } } return; } } else { // Bounce effect when on ground self.y += Math.sin(self.lifeTime * 0.1) * 0.5; } if (self.lifeTime > self.maxLifeTime) { self.destroy(); for (var i = powerups.length - 1; i >= 0; i--) { if (powerups[i] === self) { powerups.splice(i, 1); break; } } } // Check collection by players if (!self.collected) { for (var i = 0; i < fighters.length; i++) { var fighter = fighters[i]; var distance = Math.sqrt(Math.pow(fighter.x - self.x, 2) + Math.pow(fighter.y - self.y, 2)); if (distance < 80) { self.collected = true; // Increase powerup count for stacking effects fighter.powerupCount++; // Visual effects for powerup collection LK.getSound('powerup').play(); LK.effects.flashObject(fighter, 0xffd700, 800); // Create scaling animation effect tween(fighter, { scaleX: 1.3, scaleY: 1.3 }, { duration: 200, easing: tween.bounceOut, onFinish: function onFinish() { // Scale back down slightly tween(fighter, { scaleX: 1.0 + fighter.powerupCount * 0.2, scaleY: 1.0 + fighter.powerupCount * 0.2 }, { duration: 300, easing: tween.easeOut }); } }); // Temporary knockback resistance boost (stacks with permanent effects) var originalResistance = fighter.knockbackResistance; fighter.knockbackResistance *= 0.7; // 30% less knockback temporarily LK.setTimeout(function () { fighter.knockbackResistance = originalResistance; }, 3000); self.destroy(); for (var j = powerups.length - 1; j >= 0; j--) { if (powerups[j] === self) { powerups.splice(j, 1); break; } } break; } } } }; return self; }); var RainDrop = Container.expand(function () { var self = Container.call(this); var rainGraphics = self.attachAsset('rainDrop', { anchorX: 0.5, anchorY: 0.5 }); self.velocityY = 15 + Math.random() * 10; // Fast falling speed self.velocityX = -2 + Math.random() * 4; // Slight horizontal drift self.lifeTime = 0; self.maxLifeTime = 300; // 5 seconds max life self.update = function () { self.lifeTime++; // Move the raindrop self.x += self.velocityX; self.y += self.velocityY; // Check collision with platforms for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; var platformLeft = platform.x - platform.width / 2; var platformRight = platform.x + platform.width / 2; var platformTop = platform.y - platform.height / 2; var platformBottom = platform.y + platform.height / 2; // Check if raindrop hits platform if (self.x >= platformLeft && self.x <= platformRight && self.y >= platformTop && self.y <= platformBottom && self.velocityY > 0) { // Track rain drop location for flower spawning rainDropLocations.push({ x: self.x, y: platformTop - 20, // Position flowers on top of platform time: LK.ticks }); // Rain drop hit platform, destroy it self.destroy(); for (var j = rainDrops.length - 1; j >= 0; j--) { if (rainDrops[j] === self) { rainDrops.splice(j, 1); break; } } return; // Exit early to prevent further processing } } // Check collision with players for (var i = 0; i < fighters.length; i++) { var fighter = fighters[i]; if (!fighter || fighter.destroyed) continue; var distance = Math.sqrt(Math.pow(fighter.x - self.x, 2) + Math.pow(fighter.y - self.y, 2)); if (distance < 60) { // Hit detection radius // Reduce player size by 1.0% var currentScale = Math.abs(fighter.children[0].scaleX); var newScale = currentScale * 0.99; // Reduce by 1.0% // Apply the scale reduction while maintaining orientation var isFlipped = fighter.children[0].scaleX < 0; fighter.children[0].scaleX = isFlipped ? -newScale : newScale; fighter.children[0].scaleY = newScale; // Destroy the rain drop self.destroy(); for (var j = rainDrops.length - 1; j >= 0; j--) { if (rainDrops[j] === self) { rainDrops.splice(j, 1); break; } } return; // Exit early to prevent further processing } } // Remove if off screen or exceeded life time if (self.y > 2800 || self.x < -100 || self.x > 2148 || self.lifeTime >= self.maxLifeTime) { self.destroy(); for (var i = rainDrops.length - 1; i >= 0; i--) { if (rainDrops[i] === self) { rainDrops.splice(i, 1); break; } } } }; return self; }); var SmokeTrail = Container.expand(function (playerNumber, x, y) { var self = Container.call(this); var assetName = 'smokeTrail1'; if (playerNumber === 2) assetName = 'smokeTrail2';else if (playerNumber === 3) assetName = 'smokeTrail3';else if (playerNumber === 4) assetName = 'smokeTrail4'; var smokeGraphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5 }); self.x = x; self.y = y; self.lifeTime = 0; self.maxLifeTime = 30; // 0.5 seconds at 60fps self.startScale = 0.6 + Math.random() * 0.4; self.endScale = 1.2 + Math.random() * 0.8; smokeGraphics.scaleX = self.startScale; smokeGraphics.scaleY = self.startScale; smokeGraphics.alpha = 0.9; self.velocityX = (Math.random() - 0.5) * 2; self.velocityY = -2 - Math.random() * 3; self.update = function () { self.lifeTime++; var progress = self.lifeTime / self.maxLifeTime; // Move the smoke particle self.x += self.velocityX; self.y += self.velocityY; // Fade out and scale up over time smokeGraphics.alpha = 0.9 * (1 - progress); var currentScale = self.startScale + (self.endScale - self.startScale) * progress; smokeGraphics.scaleX = currentScale; smokeGraphics.scaleY = currentScale; // Remove when life time is over if (self.lifeTime >= self.maxLifeTime) { self.destroy(); for (var i = smokeTrails.length - 1; i >= 0; i--) { if (smokeTrails[i] === self) { smokeTrails.splice(i, 1); break; } } } }; return self; }); var WheelPowerUp = Container.expand(function () { var self = Container.call(this); var wheelPowerupGraphics = self.attachAsset('wheelPowerup', { anchorX: 0.5, anchorY: 0.5 }); self.lifeTime = 0; self.maxLifeTime = 600; // 10 seconds at 60fps self.collected = false; self.velocityY = 0; // Falling velocity self.onGround = false; // Track if powerup has landed self.update = function () { self.lifeTime++; self.rotation += 0.05; // Apply gravity if not on ground if (!self.onGround) { self.velocityY += 0.8; // Gravity effect self.y += self.velocityY; // Check platform collision for landing for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; var platformLeft = platform.x - platform.width / 2; var platformRight = platform.x + platform.width / 2; var platformTop = platform.y - platform.height / 2; var platformBottom = platform.y + platform.height / 2; // Check if powerup is within platform bounds and landing on top if (self.x >= platformLeft && self.x <= platformRight && self.y >= platformTop - 30 && self.y <= platformBottom && self.velocityY >= 0) { self.y = platformTop - 30; // Position on top of platform self.velocityY = 0; self.onGround = true; break; } } // Remove if fallen off screen if (self.y > 2800) { self.destroy(); for (var j = wheelPowerups.length - 1; j >= 0; j--) { if (wheelPowerups[j] === self) { wheelPowerups.splice(j, 1); break; } } return; } } else { // Bounce effect when on ground self.y += Math.sin(self.lifeTime * 0.1) * 0.5; } if (self.lifeTime > self.maxLifeTime) { self.destroy(); for (var i = wheelPowerups.length - 1; i >= 0; i--) { if (wheelPowerups[i] === self) { wheelPowerups.splice(i, 1); break; } } } // Check collection by players if (!self.collected) { for (var i = 0; i < fighters.length; i++) { var fighter = fighters[i]; var distance = Math.sqrt(Math.pow(fighter.x - self.x, 2) + Math.pow(fighter.y - self.y, 2)); if (distance < 80) { self.collected = true; // Convert fighter to wheel mode fighter.activateWheelMode(); // Visual effects for powerup collection LK.getSound('powerup').play(); LK.effects.flashObject(fighter, 0x00ff00, 800); self.destroy(); for (var j = wheelPowerups.length - 1; j >= 0; j--) { if (wheelPowerups[j] === self) { wheelPowerups.splice(j, 1); break; } } break; } } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game variables var fighters = []; var platforms = []; var powerups = []; var wheelPowerups = []; var smokeTrails = []; var fireflies = []; var rainDrops = []; var lightningBolts = []; var flowers = []; var rainDropLocations = []; // Track where rain drops have fallen var player1Lives = 3; var player2Lives = 3; var player3Lives = 3; var player4Lives = 3; var activePlayers = 4; var draggedFighter = null; var lastTapTime = 0; var powerupSpawnTimer = 0; var player1EnemiesDefeated = 0; // Track enemies defeated by player 1 // Night mode variables var nightModeTimer = 0; var nightModeDuration = 1200 + Math.random() * 600; // 20-30 seconds at 60fps var isNightMode = false; var nightOverlay = null; // Storm mode variables var stormModeTimer = 0; var stormStartTime = 300 + Math.random() * 2700; // Random time between 5-50 seconds var isStormMode = false; var stormHasTriggered = false; var stormOverlay = null; // Camera variables var cameraX = 1024; // Center of screen var cameraY = 1366; // Center of screen var cameraScale = 1.0; var targetCameraX = 1024; var targetCameraY = 1366; var targetCameraScale = 1.0; var cameraUpdateTimer = 0; // Add background image with parallax tracking var backgroundImage = game.addChild(LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 1648, y: 2400 })); backgroundImage.originalX = 1648; backgroundImage.originalY = 2400; // Add second background image on top of the first with parallax tracking var backgroundOverlay = game.addChild(LK.getAsset('backgroundOverlay', { anchorX: 0.5, anchorY: 0.5, x: 1648, y: 2400 })); backgroundOverlay.originalX = 1648; backgroundOverlay.originalY = 2400; // Add third background image above the previous two with parallax tracking var backgroundTop = game.addChild(LK.getAsset('backgroundTop', { anchorX: 0.5, anchorY: 0.5, x: 1648, y: 3200 })); backgroundTop.originalX = 1648; backgroundTop.originalY = 3200; // Button press states var leftButtonPressed = false; var rightButtonPressed = false; var jumpButtonPressed = false; var attackButtonPressed = false; // Create platforms var mainPlatform = game.addChild(LK.getAsset('mainPlatform', { anchorX: 0.5, anchorY: 0.5, x: 1648, y: 2400 })); platforms.push(mainPlatform); var leftPlatform = game.addChild(LK.getAsset('platform', { anchorX: 0.5, anchorY: 0.5, x: 1048, y: 2050 })); platforms.push(leftPlatform); var rightPlatform = game.addChild(LK.getAsset('platform', { anchorX: 0.5, anchorY: 0.5, x: 2248, y: 2050 })); platforms.push(rightPlatform); var topPlatform = game.addChild(LK.getAsset('platform', { anchorX: 0.5, anchorY: 0.5, x: 1648, y: 1700 })); platforms.push(topPlatform); // Add decorative textured images directly on top of platforms var mainPlatformTexture = game.addChild(LK.getAsset('platformTexture', { anchorX: 0.5, anchorY: 1.0, x: 1648, y: 2250 })); mainPlatformTexture.scaleX = 2.5; // Scale to match main platform width mainPlatformTexture.scaleY = 0.8; var leftPlatformTexture = game.addChild(LK.getAsset('platformTexture', { anchorX: 0.5, anchorY: 1.0, x: 1048, y: 1950 })); leftPlatformTexture.scaleX = 1.25; // Scale to match platform width leftPlatformTexture.scaleY = 0.6; var rightPlatformTexture = game.addChild(LK.getAsset('platformTexture', { anchorX: 0.5, anchorY: 1.0, x: 2248, y: 1950 })); rightPlatformTexture.scaleX = 1.25; // Scale to match platform width rightPlatformTexture.scaleY = 0.6; var topPlatformTexture = game.addChild(LK.getAsset('platformTexture', { anchorX: 0.5, anchorY: 1.0, x: 1648, y: 1600 })); topPlatformTexture.scaleX = 1.25; // Scale to match platform width topPlatformTexture.scaleY = 0.6; // Create night mode overlay nightOverlay = game.addChild(LK.getAsset('platform', { width: 3000, height: 4000, anchorX: 0.5, anchorY: 0.5, x: 1500, y: 2000 })); nightOverlay.tint = 0x000022; // Darker blue tint for stronger night effect nightOverlay.alpha = 0; // Start invisible nightOverlay.scaleX = 2; nightOverlay.scaleY = 2; // Create storm mode overlay stormOverlay = game.addChild(LK.getAsset('platform', { width: 3000, height: 4000, anchorX: 0.5, anchorY: 0.5, x: 1500, y: 2000 })); stormOverlay.tint = 0x444444; // Dark gray tint for storm atmosphere stormOverlay.alpha = 0; // Start invisible stormOverlay.scaleX = 2; stormOverlay.scaleY = 2; // Create fighters var player1 = game.addChild(new Fighter(1)); player1.x = 1048; // Position on left platform player1.y = 1950; // Just above the platform surface fighters.push(player1); var player2 = game.addChild(new Fighter(2)); player2.x = 1648; // Position on main platform player2.y = 2300; // Just above the main platform surface fighters.push(player2); var player3 = game.addChild(new Fighter(3)); player3.x = 1648; // Position on top platform player3.y = 1600; // Just above the top platform surface fighters.push(player3); var player4 = game.addChild(new Fighter(4)); player4.x = 2248; // Position on right platform player4.y = 1950; // Just above the right platform surface fighters.push(player4); // UI Elements - Individual player displays var player1Avatar = LK.getAsset('player1Avatar', { anchorX: 0.5, anchorY: 0.5, x: -200, y: 100, scaleX: 0.8, scaleY: 0.8 }); LK.gui.topRight.addChild(player1Avatar); var player1LivesImage = LK.getAsset('number3', { anchorX: 0.5, anchorY: 0.5, x: -200, y: 180, scaleX: 1.0, scaleY: 1.0 }); LK.gui.topRight.addChild(player1LivesImage); // Player 2, 3, and 4 UI elements are hidden - only Player 1 UI is visible // Create left movement button for player 1 var leftButton = LK.getAsset('leftButtonIcon', { anchorX: 0, anchorY: 1, x: 30, y: -160, scaleX: 3, scaleY: 3 }); LK.gui.bottomLeft.addChild(leftButton); // Create right movement button for player 1 var rightButton = LK.getAsset('rightButtonIcon', { anchorX: 0, anchorY: 1, x: 320, y: -160, scaleX: 3, scaleY: 3 }); LK.gui.bottomLeft.addChild(rightButton); // Create jump button for player 1 var jumpButton = LK.getAsset('jumpButtonIcon', { anchorX: 1, anchorY: 1, x: -100, y: -300, scaleX: 3, scaleY: 3 }); LK.gui.bottomRight.addChild(jumpButton); // Create attack button for player 1 var attackButton = LK.getAsset('attackButtonIcon', { anchorX: 1, anchorY: 1, x: -100, y: -160, scaleX: 3, scaleY: 3 }); LK.gui.bottomRight.addChild(attackButton); function updateScoreDisplay() { // Remove current lives image LK.gui.topRight.removeChild(player1LivesImage); player1LivesImage.destroy(); // Create new lives image based on current lives count var numberAsset = 'number0'; if (player1Lives === 1) numberAsset = 'number1';else if (player1Lives === 2) numberAsset = 'number2';else if (player1Lives === 3) numberAsset = 'number3'; player1LivesImage = LK.getAsset(numberAsset, { anchorX: 0.5, anchorY: 0.5, x: -200, y: 180, scaleX: 1.0, scaleY: 1.0 }); LK.gui.topRight.addChild(player1LivesImage); // Update avatar opacity based on lives remaining player1Avatar.alpha = player1Lives > 0 ? 1.0 : 0.3; // Update lives image opacity based on lives remaining player1LivesImage.alpha = player1Lives > 0 ? 1.0 : 0.5; } // Left button event handler leftButton.down = function (x, y, obj) { leftButtonPressed = true; leftButton.alpha = 0.6; tween(leftButton, { scaleX: 2.7, scaleY: 2.7 }, { duration: 100 }); }; leftButton.up = function (x, y, obj) { leftButtonPressed = false; leftButton.alpha = 1.0; tween(leftButton, { scaleX: 3.0, scaleY: 3.0 }, { duration: 100 }); }; // Right button event handler rightButton.down = function (x, y, obj) { rightButtonPressed = true; rightButton.alpha = 0.6; tween(rightButton, { scaleX: 2.7, scaleY: 2.7 }, { duration: 100 }); }; rightButton.up = function (x, y, obj) { rightButtonPressed = false; rightButton.alpha = 1.0; tween(rightButton, { scaleX: 3.0, scaleY: 3.0 }, { duration: 100 }); }; // Jump button event handler jumpButton.down = function (x, y, obj) { jumpButtonPressed = true; jumpButton.alpha = 0.6; tween(jumpButton, { scaleX: 2.7, scaleY: 2.7 }, { duration: 100 }); }; jumpButton.up = function (x, y, obj) { jumpButtonPressed = false; jumpButton.alpha = 1.0; tween(jumpButton, { scaleX: 3.0, scaleY: 3.0 }, { duration: 100 }); }; // Attack button event handler attackButton.down = function (x, y, obj) { attackButtonPressed = true; attackButton.alpha = 0.6; tween(attackButton, { scaleX: 2.7, scaleY: 2.7 }, { duration: 100 }); }; attackButton.up = function (x, y, obj) { attackButtonPressed = false; attackButton.alpha = 1.0; tween(attackButton, { scaleX: 3.0, scaleY: 3.0 }, { duration: 100 }); }; function updateCamera() { // Only update camera if there are living fighters var aliveFighters = []; for (var i = 0; i < fighters.length; i++) { var fighter = fighters[i]; if (fighter && !fighter.destroyed) { // Check if fighter is alive based on lives var isAlive = false; if (fighter.playerNumber === 1 && player1Lives > 0) isAlive = true;else if (fighter.playerNumber === 2 && player2Lives > 0) isAlive = true;else if (fighter.playerNumber === 3 && player3Lives > 0) isAlive = true;else if (fighter.playerNumber === 4 && player4Lives > 0) isAlive = true; if (isAlive) { aliveFighters.push(fighter); } } } if (aliveFighters.length === 0) return; // Calculate center point of all alive fighters var minX = Infinity; var maxX = -Infinity; var minY = Infinity; var maxY = -Infinity; var totalX = 0; var totalY = 0; for (var i = 0; i < aliveFighters.length; i++) { var fighter = aliveFighters[i]; totalX += fighter.x; totalY += fighter.y; if (fighter.x < minX) minX = fighter.x; if (fighter.x > maxX) maxX = fighter.x; if (fighter.y < minY) minY = fighter.y; if (fighter.y > maxY) maxY = fighter.y; } // Calculate center point targetCameraX = totalX / aliveFighters.length; targetCameraY = totalY / aliveFighters.length; // Calculate required zoom based on spread of players var spreadX = maxX - minX; var spreadY = maxY - minY; // Base zoom calculation - zoom in more for closer view of players var baseScale = 1.2; // Increased base scale for more zoom var maxSpreadX = 400; // Further reduced max spread for tighter framing var maxSpreadY = 300; // Further reduced max spread for tighter framing var scaleX = maxSpreadX / Math.max(spreadX + 100, maxSpreadX); // Reduced padding for closer view var scaleY = maxSpreadY / Math.max(spreadY + 100, maxSpreadY); // Reduced padding for closer view // Use the smaller scale to ensure all players fit targetCameraScale = Math.min(scaleX, scaleY, 1.3); // Increased max zoom to 1.3x for closer view // Minimum zoom to prevent over-zooming - increased minimum for closer gameplay if (targetCameraScale < 0.9) targetCameraScale = 0.9; // Keep camera within reasonable bounds var padding = 200; if (targetCameraX < padding) targetCameraX = padding; if (targetCameraX > 2048 - padding) targetCameraX = 2048 - padding; if (targetCameraY < 400) targetCameraY = 400; if (targetCameraY > 2400) targetCameraY = 2400; } function applyCameraSmoothing() { // Smooth camera movement using tweening var smoothingSpeed = 0.05; // How fast camera follows (0.01 = very slow, 0.1 = fast) // Interpolate camera position cameraX += (targetCameraX - cameraX) * smoothingSpeed; cameraY += (targetCameraY - cameraY) * smoothingSpeed; cameraScale += (targetCameraScale - cameraScale) * smoothingSpeed; // Apply camera transformation to game game.x = (1024 - cameraX) * cameraScale + 1024 * (1 - cameraScale); game.y = (1366 - cameraY) * cameraScale + 1366 * (1 - cameraScale); game.scaleX = cameraScale; game.scaleY = cameraScale; // Apply parallax scrolling to background layers updateParallax(); } function updateParallax() { // Calculate camera movement offset from center var cameraMoveX = cameraX - 1024; // How much camera moved from center horizontally var cameraMoveY = cameraY - 1366; // How much camera moved from center vertically // Background image (furthest back) - moves slowest (20% of camera movement) backgroundImage.x = backgroundImage.originalX - cameraMoveX * 0.2; backgroundImage.y = backgroundImage.originalY - cameraMoveY * 0.15; // Background overlay (middle layer) - moves at medium speed (40% of camera movement) backgroundOverlay.x = backgroundOverlay.originalX - cameraMoveX * 0.4; backgroundOverlay.y = backgroundOverlay.originalY - cameraMoveY * 0.3; // Background top (closest to foreground) - moves faster (60% of camera movement) backgroundTop.x = backgroundTop.originalX - cameraMoveX * 0.6; backgroundTop.y = backgroundTop.originalY - cameraMoveY * 0.45; } function spawnPowerUp() { if (powerups.length + wheelPowerups.length < 2) { // 50% chance for wheel powerup, 50% for regular powerup if (Math.random() < 0.5) { var powerup = game.addChild(new PowerUp()); // Spawn from random position above the screen aligned with new platform positions powerup.x = 1048 + Math.random() * 1200; // Random X within extended platform bounds (left to right platform) powerup.y = -100; // Start above screen powerup.velocityY = 2 + Math.random() * 3; // Initial falling speed powerups.push(powerup); } else { var wheelPowerup = game.addChild(new WheelPowerUp()); // Spawn from random position above the screen aligned with new platform positions wheelPowerup.x = 1048 + Math.random() * 1200; // Random X within extended platform bounds (left to right platform) wheelPowerup.y = -100; // Start above screen wheelPowerup.velocityY = 2 + Math.random() * 3; // Initial falling speed wheelPowerups.push(wheelPowerup); } } } // Game controls game.down = function (x, y, obj) { var currentTime = LK.ticks; var tapSpeed = 20; // frames between taps for double tap // Find closest fighter to touch point (only player 1) var closestFighter = null; var closestDistance = Infinity; for (var i = 0; i < fighters.length; i++) { var fighter = fighters[i]; // Only allow touch control for player 1 if they're still alive if (fighter.playerNumber !== 1 || player1Lives <= 0) continue; var distance = Math.sqrt(Math.pow(fighter.x - x, 2) + Math.pow(fighter.y - y, 2)); if (distance < closestDistance && distance < 200) { closestDistance = distance; closestFighter = fighter; } } if (closestFighter) { // Check for double tap (attack) if (currentTime - lastTapTime < tapSpeed) { closestFighter.attack(x, y); draggedFighter = null; } else { draggedFighter = closestFighter; } lastTapTime = currentTime; } }; game.move = function (x, y, obj) { if (draggedFighter && draggedFighter.playerNumber === 1) { var deltaX = x - draggedFighter.x; var deltaY = y - draggedFighter.y; // Move fighter towards touch point draggedFighter.velocityX += deltaX * 0.3; // Jump if dragging upward and has jumps remaining if (deltaY < -50 && draggedFighter.jumpsRemaining > 0) { draggedFighter.velocityY = -draggedFighter.jumpPower; draggedFighter.jumpsRemaining--; draggedFighter.onGround = false; LK.getSound('jump').play(); } } }; game.up = function (x, y, obj) { draggedFighter = null; }; // Function to determine which platform a fighter is on function getPlayerPlatform(fighter) { for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; var platformLeft = platform.x - platform.width / 2; var platformRight = platform.x + platform.width / 2; var platformTop = platform.y - platform.height / 2; var platformBottom = platform.y + platform.height / 2; // Check if fighter is within platform bounds and close to platform surface if (fighter.x >= platformLeft && fighter.x <= platformRight && fighter.y >= platformTop - 100 && fighter.y <= platformBottom + 50) { return platform; } } return null; } // Function to find closest target for AI with platform priority function findClosestTarget(aiPlayer) { var closestPlayer = null; var closestDistance = Infinity; var closestSamePlatformPlayer = null; var closestSamePlatformDistance = Infinity; var aiPlatform = getPlayerPlatform(aiPlayer); for (var i = 0; i < fighters.length; i++) { var fighter = fighters[i]; // Skip self, dead players, and destroyed fighters if (fighter === aiPlayer) continue; if (fighter.destroyed) continue; if (fighter.playerNumber === 1 && player1Lives <= 0) continue; if (fighter.playerNumber === 2 && player2Lives <= 0) continue; if (fighter.playerNumber === 3 && player3Lives <= 0) continue; if (fighter.playerNumber === 4 && player4Lives <= 0) continue; var distance = Math.sqrt(Math.pow(fighter.x - aiPlayer.x, 2) + Math.pow(fighter.y - aiPlayer.y, 2)); var fighterPlatform = getPlayerPlatform(fighter); var onSamePlatform = aiPlatform && fighterPlatform && aiPlatform === fighterPlatform; // Track closest enemy on same platform if (onSamePlatform && distance < closestSamePlatformDistance) { closestSamePlatformDistance = distance; closestSamePlatformPlayer = fighter; } // Track overall closest enemy if (distance < closestDistance) { closestDistance = distance; closestPlayer = fighter; } } // Prioritize same platform enemy if one exists if (closestSamePlatformPlayer) { return { player: closestSamePlatformPlayer, distance: closestSamePlatformDistance, samePlatform: true }; } return { player: closestPlayer, distance: closestDistance, samePlatform: false }; } // AI variables for player 2 var aiDecisionTimer = 0; var aiAction = 'idle'; var aiTargetX = player2.x; var aiCooldown = 0; // AI variables for player 3 var ai3DecisionTimer = 0; var ai3Action = 'idle'; var ai3TargetX = 1648; var ai3Cooldown = 0; // AI variables for player 4 var ai4DecisionTimer = 0; var ai4Action = 'idle'; var ai4TargetX = 2248; var ai4Cooldown = 0; game.update = function () { // Start background music on first update if (LK.ticks === 1) { LK.playMusic('backgroundMusic'); } // Handle continuous button presses for player 1 (only if alive) if (player1Lives > 0) { if (leftButtonPressed) { player1.velocityX -= player1.moveSpeed * 0.5; } if (rightButtonPressed) { player1.velocityX += player1.moveSpeed * 0.5; } if (jumpButtonPressed && player1.jumpsRemaining > 0) { player1.velocityY = -player1.jumpPower; player1.jumpsRemaining--; player1.onGround = false; LK.getSound('jump').play(); jumpButtonPressed = false; // Prevent continuous jumping } if (attackButtonPressed) { player1.attack(player1.x, player1.y); attackButtonPressed = false; // Prevent continuous attacking } } // Spawn power-ups occasionally powerupSpawnTimer++; if (powerupSpawnTimer > 120) { // Every 2 seconds if (Math.random() < 0.5) { spawnPowerUp(); } powerupSpawnTimer = 0; } // AI for player 2 (only if alive) if (player2Lives > 0) { aiDecisionTimer++; if (aiCooldown > 0) { aiCooldown--; } // Make AI decisions every 30 frames (half second) if (aiDecisionTimer > 30) { aiDecisionTimer = 0; // Check if AI is below main platform and needs to move to center var mainPlatformY = 2400; // Main platform Y position var isBelowMainPlatform = player2.y > mainPlatformY + 200; if (isBelowMainPlatform) { // Force move to center platform to avoid falling aiAction = 'moveToCenter'; aiTargetX = 1648; // Main platform center X } else { // Find closest target var closestTarget = findClosestTarget(player2); var distanceToClosest = closestTarget.distance; // Check for nearby powerups var nearestPowerup = null; var nearestPowerupDistance = Infinity; for (var i = 0; i < powerups.length; i++) { var powerup = powerups[i]; var distance = Math.sqrt(Math.pow(powerup.x - player2.x, 2) + Math.pow(powerup.y - player2.y, 2)); if (distance < nearestPowerupDistance) { nearestPowerupDistance = distance; nearestPowerup = powerup; } } // AI decision making with enhanced platform awareness if (aiCooldown === 0 && closestTarget.player) { if (distanceToClosest < 200 && Math.random() < 0.8) { // Attack if close to closest target aiAction = 'attack'; aiCooldown = 60; // Attack cooldown } else if (nearestPowerup && nearestPowerupDistance < 300 && Math.random() < 0.3) { // Go for powerup if nearby (lower priority) aiAction = 'moveToPowerup'; aiTargetX = nearestPowerup.x; } else if (closestTarget.samePlatform) { // Same platform enemy detected - move towards closest enemy on same platform aiAction = 'moveToPlayer'; aiTargetX = closestTarget.player.x; } else if (!closestTarget.samePlatform && closestTarget.player) { // Different platform - jump towards target aiAction = 'jumpToPlayer'; aiTargetX = closestTarget.player.x; } else { // Random movement (rare) aiAction = 'randomMove'; aiTargetX = 1200 + Math.random() * 900; // Random X within platform area } } else if (!closestTarget.player) { aiAction = 'idle'; } } } // Execute AI actions if (aiAction === 'attack' && closestTarget.player) { player2.attack(closestTarget.player.x, closestTarget.player.y); aiAction = 'idle'; } else if (aiAction === 'moveToPowerup' || aiAction === 'moveToPlayer' || aiAction === 'randomMove' || aiAction === 'jumpToPlayer' || aiAction === 'moveToCenter') { // Move towards target var deltaX = aiTargetX - player2.x; if (Math.abs(deltaX) > 50) { player2.velocityX += deltaX * 0.25; } // Enhanced jumping logic for different platforms if (aiAction === 'jumpToPlayer' && closestTarget && closestTarget.player) { // Jump towards player on different platform if (player2.jumpsRemaining > 0 && player2.onGround) { player2.velocityY = -player2.jumpPower; player2.jumpsRemaining--; player2.onGround = false; LK.getSound('jump').play(); // Add horizontal velocity towards target player2.velocityX += deltaX * 0.15; } } else if (aiAction === 'moveToCenter') { // Jump upward aggressively to get back to main platform if (player2.jumpsRemaining > 0) { player2.velocityY = -player2.jumpPower; player2.jumpsRemaining--; player2.onGround = false; LK.getSound('jump').play(); } } else if (aiAction === 'moveToPlayer' && closestTarget && closestTarget.player && closestTarget.player.y < player2.y - 100) { // Jump if target is above on same platform if (player2.jumpsRemaining > 0) { player2.velocityY = -player2.jumpPower; player2.jumpsRemaining--; player2.onGround = false; LK.getSound('jump').play(); } } else if (Math.abs(player2.velocityX) < 1 && player2.onGround && Math.random() < 0.1) { // Jump if stuck if (player2.jumpsRemaining > 0) { player2.velocityY = -player2.jumpPower; player2.jumpsRemaining--; player2.onGround = false; LK.getSound('jump').play(); } } // Reset action if close enough to target if (Math.abs(deltaX) < 100) { aiAction = 'idle'; } } // AI logic: double jump if can't reach player who is much higher var heightDifference = player2.y - player1.y; var horizontalDistance = Math.abs(player2.x - player1.x); if (heightDifference > 200 && horizontalDistance < 400 && player2.jumpsRemaining > 0) { // Check if AI is below player and perform double jump to reach them player2.velocityY = -player2.jumpPower; player2.jumpsRemaining--; player2.onGround = false; LK.getSound('jump').play(); } // AI emergency jump if falling off platform if (player2.y > 2500 && player2.jumpsRemaining > 0) { player2.velocityY = -player2.jumpPower; player2.jumpsRemaining--; player2.onGround = false; LK.getSound('jump').play(); } } // AI for player 3 (only if alive) if (player3Lives > 0) { ai3DecisionTimer++; if (ai3Cooldown > 0) { ai3Cooldown--; } if (ai3DecisionTimer > 45) { ai3DecisionTimer = 0; // Check if AI is below main platform and needs to move to center var mainPlatformY = 2400; // Main platform Y position var isBelowMainPlatform = player3.y > mainPlatformY + 200; if (isBelowMainPlatform) { // Force move to center platform to avoid falling ai3Action = 'moveToCenter'; ai3TargetX = 1648; // Main platform center X } else { // Find closest target var closestTarget_3 = findClosestTarget(player3); var closestDistance_3 = closestTarget_3.distance; if (ai3Cooldown === 0 && closestTarget_3.player) { if (closestDistance_3 < 200 && Math.random() < 0.7) { ai3Action = 'attack'; ai3Cooldown = 70; } else if (closestTarget_3.samePlatform) { // Same platform enemy detected - move towards closest enemy on same platform ai3Action = 'moveToPlayer'; ai3TargetX = closestTarget_3.player.x; } else if (!closestTarget_3.samePlatform && closestTarget_3.player) { // Different platform - jump towards target ai3Action = 'jumpToPlayer'; ai3TargetX = closestTarget_3.player.x; } else if (Math.random() < 0.3) { ai3Action = 'randomMove'; ai3TargetX = 1200 + Math.random() * 900; } else { ai3Action = 'idle'; } } else if (!closestTarget_3.player) { ai3Action = 'idle'; } } } if (ai3Action === 'attack' && closestTarget_3.player) { player3.attack(closestTarget_3.player.x, closestTarget_3.player.y); ai3Action = 'idle'; } else if (ai3Action === 'moveToPlayer' || ai3Action === 'randomMove' || ai3Action === 'jumpToPlayer' || ai3Action === 'moveToCenter') { var deltaX_3 = ai3TargetX - player3.x; if (Math.abs(deltaX_3) > 50) { player3.velocityX += deltaX_3 * 0.22; } // Enhanced jumping logic for different platforms if (ai3Action === 'jumpToPlayer' && closestTarget_3 && closestTarget_3.player) { // Jump towards player on different platform if (player3.jumpsRemaining > 0 && player3.onGround) { player3.velocityY = -player3.jumpPower; player3.jumpsRemaining--; player3.onGround = false; LK.getSound('jump').play(); // Add horizontal velocity towards target player3.velocityX += deltaX_3 * 0.18; } } else if (ai3Action === 'moveToCenter') { // Jump upward aggressively to get back to main platform if (player3.jumpsRemaining > 0) { player3.velocityY = -player3.jumpPower; player3.jumpsRemaining--; player3.onGround = false; LK.getSound('jump').play(); } } else if (Math.abs(deltaX_3) > 200 && player3.onGround && Math.random() < 0.15) { if (player3.jumpsRemaining > 0) { player3.velocityY = -player3.jumpPower; player3.jumpsRemaining--; player3.onGround = false; LK.getSound('jump').play(); } } if (Math.abs(deltaX_3) < 100) { ai3Action = 'idle'; } } if (player3.y > 2500 && player3.jumpsRemaining > 0) { player3.velocityY = -player3.jumpPower; player3.jumpsRemaining--; player3.onGround = false; LK.getSound('jump').play(); } } // AI for player 4 (only if alive) if (player4Lives > 0) { ai4DecisionTimer++; if (ai4Cooldown > 0) { ai4Cooldown--; } if (ai4DecisionTimer > 35) { ai4DecisionTimer = 0; // Check if AI is below main platform and needs to move to center var mainPlatformY = 2400; // Main platform Y position var isBelowMainPlatform = player4.y > mainPlatformY + 200; if (isBelowMainPlatform) { // Force move to center platform to avoid falling ai4Action = 'moveToCenter'; ai4TargetX = 1648; // Main platform center X } else { // Find closest target var closestTarget_4 = findClosestTarget(player4); var closestDistance_4 = closestTarget_4.distance; if (ai4Cooldown === 0 && closestTarget_4.player) { if (closestDistance_4 < 180 && Math.random() < 0.85) { ai4Action = 'attack'; ai4Cooldown = 50; } else if (closestTarget_4.samePlatform) { // Same platform enemy detected - move towards closest enemy on same platform aggressively ai4Action = 'moveToPlayer'; ai4TargetX = closestTarget_4.player.x; } else if (!closestTarget_4.samePlatform && closestTarget_4.player) { // Different platform - jump towards target ai4Action = 'jumpToPlayer'; ai4TargetX = closestTarget_4.player.x; } else if (Math.random() < 0.4) { ai4Action = 'randomMove'; ai4TargetX = 1200 + Math.random() * 900; } else { ai4Action = 'idle'; } } else if (!closestTarget_4.player) { ai4Action = 'idle'; } } } if (ai4Action === 'attack' && closestTarget_4.player) { player4.attack(closestTarget_4.player.x, closestTarget_4.player.y); ai4Action = 'idle'; } else if (ai4Action === 'moveToPlayer' || ai4Action === 'randomMove' || ai4Action === 'jumpToPlayer' || ai4Action === 'moveToCenter') { var deltaX_4 = ai4TargetX - player4.x; if (Math.abs(deltaX_4) > 50) { player4.velocityX += deltaX_4 * 0.28; } // Enhanced jumping logic for different platforms if (ai4Action === 'jumpToPlayer' && closestTarget_4 && closestTarget_4.player) { // Jump towards player on different platform if (player4.jumpsRemaining > 0 && player4.onGround) { player4.velocityY = -player4.jumpPower; player4.jumpsRemaining--; player4.onGround = false; LK.getSound('jump').play(); // Add horizontal velocity towards target player4.velocityX += deltaX_4 * 0.2; } } else if (ai4Action === 'moveToCenter') { // Jump upward aggressively to get back to main platform if (player4.jumpsRemaining > 0) { player4.velocityY = -player4.jumpPower; player4.jumpsRemaining--; player4.onGround = false; LK.getSound('jump').play(); } } else if (Math.abs(deltaX_4) > 150 && player4.onGround && Math.random() < 0.2) { if (player4.jumpsRemaining > 0) { player4.velocityY = -player4.jumpPower; player4.jumpsRemaining--; player4.onGround = false; LK.getSound('jump').play(); } } if (Math.abs(deltaX_4) < 100) { ai4Action = 'idle'; } } if (player4.y > 2500 && player4.jumpsRemaining > 0) { player4.velocityY = -player4.jumpPower; player4.jumpsRemaining--; player4.onGround = false; LK.getSound('jump').play(); } } // Update all fighters for (var i = fighters.length - 1; i >= 0; i--) { if (fighters[i] && !fighters[i].destroyed) { fighters[i].update(); } } // Update all powerups for (var i = powerups.length - 1; i >= 0; i--) { if (powerups[i] && !powerups[i].destroyed) { powerups[i].update(); } } // Update all wheel powerups for (var i = wheelPowerups.length - 1; i >= 0; i--) { if (wheelPowerups[i] && !wheelPowerups[i].destroyed) { wheelPowerups[i].update(); } } // Update all smoke trails for (var i = smokeTrails.length - 1; i >= 0; i--) { if (smokeTrails[i] && !smokeTrails[i].destroyed) { smokeTrails[i].update(); } } // Update all fireflies for (var i = fireflies.length - 1; i >= 0; i--) { if (fireflies[i] && !fireflies[i].destroyed) { fireflies[i].update(); } } // Update all rain drops for (var i = rainDrops.length - 1; i >= 0; i--) { if (rainDrops[i] && !rainDrops[i].destroyed) { rainDrops[i].update(); } } // Update all lightning bolts for (var i = lightningBolts.length - 1; i >= 0; i--) { if (lightningBolts[i] && !lightningBolts[i].destroyed) { lightningBolts[i].update(); } } // Update all flowers for (var i = flowers.length - 1; i >= 0; i--) { if (flowers[i] && !flowers[i].destroyed) { flowers[i].update(); } } // Update camera every 10 frames for smooth performance cameraUpdateTimer++; if (cameraUpdateTimer >= 10) { cameraUpdateTimer = 0; updateCamera(); } // Storm mode cycle - triggers once at random time if (!stormHasTriggered && !isNightMode) { // Only start storm if night mode is not active stormModeTimer++; // Only increment timer when night mode is not active if (stormModeTimer >= stormStartTime) { stormHasTriggered = true; isStormMode = true; // Start storm mode with dramatic darkening tween(stormOverlay, { alpha: 0.6 }, { duration: 1500, // 1.5 seconds to darken quickly easing: tween.easeInOut }); // Flash screen effect to simulate lightning LK.effects.flashScreen(0xffffff, 300); // End storm mode after 20 seconds LK.setTimeout(function () { isStormMode = false; tween(stormOverlay, { alpha: 0 }, { duration: 2000, // 2 seconds to clear easing: tween.easeOut }); // Spawn flowers where rain drops fell most frequently var flowerSpawnAreas = []; var gridSize = 150; // Size of each grid cell for density calculation // Create density map based on rain drop locations for (var r = 0; r < rainDropLocations.length; r++) { var location = rainDropLocations[r]; var gridX = Math.floor(location.x / gridSize); var gridY = Math.floor(location.y / gridSize); var gridKey = gridX + "," + gridY; if (!flowerSpawnAreas[gridKey]) { flowerSpawnAreas[gridKey] = { count: 0, totalX: 0, totalY: 0, avgX: 0, avgY: 0 }; } flowerSpawnAreas[gridKey].count++; flowerSpawnAreas[gridKey].totalX += location.x; flowerSpawnAreas[gridKey].totalY += location.y; } // Calculate average positions and spawn flowers in high-density areas for (var key in flowerSpawnAreas) { var area = flowerSpawnAreas[key]; if (area.count >= 5) { // Minimum 5 rain drops to spawn a flower area.avgX = area.totalX / area.count; area.avgY = area.totalY / area.count; // Spawn multiple flowers based on density var flowerCount = Math.min(Math.floor(area.count / 3), 4); // 1 flower per 3 rain drops, max 4 for (var f = 0; f < flowerCount; f++) { var flower = game.addChild(new Flower(area.avgX + (Math.random() - 0.5) * 80, // Small random offset area.avgY + (Math.random() - 0.5) * 40)); // Position flower behind players but in front of background elements // Count background elements (background, backgroundOverlay, backgroundTop) = 3 var backgroundElementCount = 3; var platformCount = 4; // mainPlatform, leftPlatform, rightPlatform, topPlatform var textureCount = 4; // platform textures var overlayCount = 2; // nightOverlay, stormOverlay var totalBackgroundElements = backgroundElementCount + platformCount + textureCount + overlayCount; game.setChildIndex(flower, totalBackgroundElements); flowers.push(flower); } } } // Clear rain drop tracking for next storm rainDropLocations = []; // Clear all rain and lightning when storm ends for (var r = rainDrops.length - 1; r >= 0; r--) { if (rainDrops[r]) { rainDrops[r].destroy(); rainDrops.splice(r, 1); } } for (var l = lightningBolts.length - 1; l >= 0; l--) { if (lightningBolts[l]) { lightningBolts[l].destroy(); lightningBolts.splice(l, 1); } } }, 20000); // 20 seconds duration } } // Storm rain and lightning effects if (isStormMode) { // Calculate storm duration in 5-second intervals for progressive intensity var stormDuration = LK.ticks - (stormStartTime + stormModeTimer - stormStartTime); var fiveSecondIntervals = Math.floor(stormDuration / 300); // 300 frames = 5 seconds at 60fps // Base rain frequency starts at every 2 frames, gets more frequent as storm progresses var rainFrequency = Math.max(1, 2 - Math.floor(fiveSecondIntervals / 2)); // Decreases spawn interval // Additional rain drops - spawn extra drops every 5 seconds var extraDrops = Math.min(fiveSecondIntervals, 10); // Cap at 10 extra drops per spawn // Spawn rain drops continuously with increasing intensity if (LK.ticks % rainFrequency === 0) { // Spawn base rain drop plus additional drops based on storm duration for (var dropCount = 0; dropCount <= extraDrops; dropCount++) { var rainDrop = game.addChild(new RainDrop()); // Center rain drop spawn around main platform (1648 is main platform X center) var mainPlatformX = 1648; var spawnRadius = 800; // Spawn radius around main platform // Calculate camera movement to spawn rain ahead of camera direction var cameraDeltaX = targetCameraX - cameraX; var cameraDeltaY = targetCameraY - cameraY; // Base spawn area centered on main platform var baseSpawnX = mainPlatformX - spawnRadius / 2 + Math.random() * spawnRadius; var baseSpawnY = cameraY - 600; // Offset spawn position based on camera movement direction var movementMultiplier = 2.0; // How much to lead the camera movement rainDrop.x = baseSpawnX + cameraDeltaX * movementMultiplier; rainDrop.y = baseSpawnY + cameraDeltaY * movementMultiplier * 0.5; // Ensure rain spawns within bounds centered around main platform var minX = mainPlatformX - spawnRadius; var maxX = mainPlatformX + spawnRadius; if (rainDrop.x < minX) rainDrop.x = minX; if (rainDrop.x > maxX) rainDrop.x = maxX; if (rainDrop.y > -50) rainDrop.y = -50; rainDrops.push(rainDrop); } } // Random lightning strikes if (Math.random() < 0.005) { // 0.5% chance per frame for lightning var lightning = game.addChild(new Lightning()); lightning.x = 200 + Math.random() * 1648; // Random X position lightning.y = 0; // Start at top of screen lightningBolts.push(lightning); // Flash screen white for lightning effect LK.effects.flashScreen(0xffffff, 200); } } // Night mode cycle if (!isStormMode) { // Only increment timer when storm mode is not active nightModeTimer++; } if (nightModeTimer >= nightModeDuration && !isStormMode) { // Only proceed if storm mode is not active nightModeTimer = 0; // Reset duration for next cycle (20-30 seconds) nightModeDuration = 1200 + Math.random() * 600; if (!isNightMode) { // Start night mode - darken slowly isNightMode = true; tween(nightOverlay, { alpha: 0.75 }, { duration: 3000, // 3 seconds to darken easing: tween.easeInOut }); // Spawn fireflies when night mode starts - they appear from outside screen and move in for (var f = 0; f < 5; f++) { var firefly = game.addChild(new Firefly()); // Start fireflies outside the visible screen area var side = Math.floor(Math.random() * 4); // 0=top, 1=right, 2=bottom, 3=left var startX, startY, targetX, targetY; if (side === 0) { // From top startX = Math.random() * 2048; startY = -200; targetX = startX + (Math.random() - 0.5) * 400; // Some horizontal drift targetY = 200 + Math.random() * 1000; } else if (side === 1) { // From right startX = 2248; startY = Math.random() * 2732; targetX = 1400 + Math.random() * 600; targetY = startY + (Math.random() - 0.5) * 400; // Some vertical drift } else if (side === 2) { // From bottom startX = Math.random() * 2048; startY = 2932; targetX = startX + (Math.random() - 0.5) * 400; // Some horizontal drift targetY = 1800 + Math.random() * 800; } else { // From left startX = -200; startY = Math.random() * 2732; targetX = 200 + Math.random() * 600; targetY = startY + (Math.random() - 0.5) * 400; // Some vertical drift } // Ensure target positions are within reasonable scene bounds if (targetX < 100) targetX = 100; if (targetX > 1948) targetX = 1948; if (targetY < 200) targetY = 200; if (targetY > 2500) targetY = 2500; // Set starting position firefly.x = startX; firefly.y = startY; // Animate firefly moving into the scene var duration = 2000 + Math.random() * 3000; // 2-5 seconds to enter tween(firefly, { x: targetX, y: targetY }, { duration: duration, easing: tween.easeOut }); fireflies.push(firefly); } } else { // End night mode - brighten slowly isNightMode = false; tween(nightOverlay, { alpha: 0 }, { duration: 2000, // 2 seconds to brighten easing: tween.easeInOut }); // Fade out all fireflies when night mode ends for (var f = fireflies.length - 1; f >= 0; f--) { if (fireflies[f]) { var firefly = fireflies[f]; tween(firefly, { alpha: 0 }, { duration: 2000, easing: tween.easeOut, onFinish: function onFinish() { firefly.destroy(); // Remove from array for (var i = fireflies.length - 1; i >= 0; i--) { if (fireflies[i] === firefly) { fireflies.splice(i, 1); break; } } } }); } } } } // Apply smooth camera movement applyCameraSmoothing(); };
===================================================================
--- original.js
+++ change.js
@@ -1164,18 +1164,17 @@
scaleX: 0.8,
scaleY: 0.8
});
LK.gui.topRight.addChild(player1Avatar);
-var player1LivesText = new Text2('3', {
- size: 60,
- fill: 0xFFFFFF,
- stroke: 0x000000,
- strokeThickness: 3
+var player1LivesImage = LK.getAsset('number3', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: -200,
+ y: 180,
+ scaleX: 1.0,
+ scaleY: 1.0
});
-player1LivesText.anchor.set(0.5, 0.5);
-player1LivesText.x = -200;
-player1LivesText.y = 180;
-LK.gui.topRight.addChild(player1LivesText);
+LK.gui.topRight.addChild(player1LivesImage);
// Player 2, 3, and 4 UI elements are hidden - only Player 1 UI is visible
// Create left movement button for player 1
var leftButton = LK.getAsset('leftButtonIcon', {
anchorX: 0,
@@ -1216,13 +1215,27 @@
scaleY: 3
});
LK.gui.bottomRight.addChild(attackButton);
function updateScoreDisplay() {
- player1LivesText.setText(player1Lives.toString());
+ // Remove current lives image
+ LK.gui.topRight.removeChild(player1LivesImage);
+ player1LivesImage.destroy();
+ // Create new lives image based on current lives count
+ var numberAsset = 'number0';
+ if (player1Lives === 1) numberAsset = 'number1';else if (player1Lives === 2) numberAsset = 'number2';else if (player1Lives === 3) numberAsset = 'number3';
+ player1LivesImage = LK.getAsset(numberAsset, {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: -200,
+ y: 180,
+ scaleX: 1.0,
+ scaleY: 1.0
+ });
+ LK.gui.topRight.addChild(player1LivesImage);
// Update avatar opacity based on lives remaining
player1Avatar.alpha = player1Lives > 0 ? 1.0 : 0.3;
- // Update lives text color based on lives remaining using tint
- player1LivesText.tint = player1Lives > 0 ? 0xFFFFFF : 0x888888;
+ // Update lives image opacity based on lives remaining
+ player1LivesImage.alpha = player1Lives > 0 ? 1.0 : 0.5;
}
// Left button event handler
leftButton.down = function (x, y, obj) {
leftButtonPressed = true;
Slime azul, pixelart. In-Game asset. 2d. High contrast. No shadows
Slime rojo, pixelart. In-Game asset. 2d. High contrast. No shadows
Slime amarillo, pixelart. In-Game asset. 2d. High contrast. No shadows
Slime verde, pixelart. In-Game asset. 2d. High contrast. No shadows
Montañas en atardecer pixelart. In-Game asset. 2d. High contrast. No shadows
Elimina la montaña
Burbuja azul, una , pixelart. In-Game asset. 2d. High contrast. No shadows
Esfera amarilla con la letra P , pixelart. In-Game asset. 2d. High contrast. No shadows
Flecha azul de Slime , pixelart. In-Game asset. 2d. High contrast. No shadows
Cámbiale el color a rojo , pixelart
Cámbiale el color a amarillo, pixelart
Cámbiale el color a verde, pixelart
Apaga las luces de la ventanas
Luciérnaga, pixelart. In-Game asset. 2d. High contrast. No shadows
Cabeza de girasol, pixelart. In-Game asset. 2d. High contrast. No shadows
Número 1 azul , pixelart. In-Game asset. 2d. High contrast. No shadows
Número 0 azul, pixelart. In-Game asset. 2d. High contrast. No shadows
Número 3 azul, pixelart. In-Game asset. 2d. High contrast. No shadows
Retro, pixelart