User prompt
MARİO İSE SPAGETTİ ARASIN
User prompt
OYUNA Bİ CANAVAR OLARAK LUİGİYİ EKLE
User prompt
Please fix the bug: 'TypeError: tween.to is not a function' in or related to this line: 'tween.to(self, 0.5, {' Line Number: 75 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'storage.getItem is not a function' in or related to this line: 'if (storage.getItem('achievement_' + achievement.id)) {' Line Number: 297 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
oyunda başarım olsun
User prompt
ejderha daha yavaş olsun
User prompt
ADD 1 MINUTE 20 SECONDS TO THE GAME
User prompt
ADD 1 MINUTE 20 SECONDS TO THE GAME
User prompt
ADD A 250 POINT HEALTH BAR
Code edit (1 edits merged)
Please save this source code
User prompt
Dragon's Treasure Escape
Initial prompt
MAKE ME A GAME ABOUT ESCAPE FROM THE DRAGON AND LET IT BE IN MARAD AND WE WILL BE A TREASURE HUNTER
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Achievement = Container.expand(function (id, title, description, icon) { var self = Container.call(this); self.id = id; self.title = title; self.description = description; self.icon = icon; self.unlocked = false; self.displayTime = 0; // Create achievement notification display var bg = LK.getAsset('achievement_bg', { width: 600, height: 120, color: 0x2C3E50, shape: 'box', anchorX: 0.5, anchorY: 0.5 }); self.addChild(bg); var titleText = new Text2(title, { size: 40, fill: 0xFFD700 }); titleText.anchor.set(0.5, 0); titleText.x = 0; titleText.y = -30; self.addChild(titleText); var descText = new Text2(description, { size: 30, fill: 0xFFFFFF }); descText.anchor.set(0.5, 1); descText.x = 0; descText.y = 30; self.addChild(descText); self.unlock = function () { if (!self.unlocked) { self.unlocked = true; self.show(); // Save to storage storage['achievement_' + self.id] = true; } }; self.show = function () { self.x = 1024; self.y = 200; self.alpha = 0; self.scaleX = 0.5; self.scaleY = 0.5; self.displayTime = 180; // 3 seconds // Animate in tween(self, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 500 }); }; self.update = function () { if (self.displayTime > 0) { self.displayTime--; if (self.displayTime <= 0) { // Animate out tween(self, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 500 }); } } }; return self; }); var Dragon = Container.expand(function () { var self = Container.call(this); var dragonGraphics = self.attachAsset('dragon', { anchorX: 0.5, anchorY: 0.5 }); self.baseSpeed = 1.5; self.currentSpeed = self.baseSpeed; self.fireTimer = 0; self.fireInterval = 120; // 2 seconds initially self.health = 150; self.maxHealth = 150; // Create health bar var dragonHealthBarBg = self.attachAsset('dragon_health_bar_bg', { anchorX: 0.5, anchorY: 0.5 }); dragonHealthBarBg.y = -180; var dragonHealthBarFill = self.attachAsset('dragon_health_bar_fill', { anchorX: 0, anchorY: 0.5 }); dragonHealthBarFill.x = -60; dragonHealthBarFill.y = -180; self.update = function () { // Follow player var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { self.x += dx / distance * self.currentSpeed; self.y += dy / distance * self.currentSpeed; } // Fire breathing timer self.fireTimer++; if (self.fireTimer >= self.fireInterval) { self.breatheFire(); self.fireTimer = 0; } // Adjust difficulty based on score var difficulty = Math.floor(score / 10); self.currentSpeed = self.baseSpeed + difficulty * 0.5; self.fireInterval = Math.max(60, 120 - difficulty * 10); // Update health bar var healthPercent = self.health / self.maxHealth; dragonHealthBarFill.width = 120 * healthPercent; if (healthPercent > 0.6) { dragonHealthBarFill.tint = 0xFF0000; // Red } else if (healthPercent > 0.3) { dragonHealthBarFill.tint = 0xFF4444; // Light Red } else { dragonHealthBarFill.tint = 0xFF8888; // Very Light Red } }; self.breatheFire = function () { var fireball = new Fireball(); fireball.x = self.x; fireball.y = self.y; // Aim towards player var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); fireball.directionX = dx / distance; fireball.directionY = dy / distance; fireballs.push(fireball); game.addChild(fireball); LK.getSound('fire').play(); }; self.takeDamage = function (damage) { self.health = Math.max(0, self.health - damage); LK.effects.flashObject(self, 0xFF0000, 300); if (self.health <= 0) { // Dragon is defeated but doesn't die LK.effects.flashObject(self, 0x000000, 1000); self.baseSpeed = 0.5; // Reduced speed but still moves self.currentSpeed = 0.5; self.fireInterval = 999999; // Stop firing } }; return self; }); var Fireball = Container.expand(function () { var self = Container.call(this); var fireballGraphics = self.attachAsset('fireball', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; self.directionX = 0; self.directionY = 0; self.lifetime = 300; // 5 seconds self.update = function () { self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; fireballGraphics.rotation += 0.2; fireballGraphics.alpha = Math.sin(LK.ticks * 0.5) * 0.3 + 0.7; self.lifetime--; if (self.lifetime <= 0) { self.shouldDestroy = true; } // Check bounds if (self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) { self.shouldDestroy = true; } }; return self; }); var Gem = Container.expand(function () { var self = Container.call(this); var gemGraphics = self.attachAsset('gem', { anchorX: 0.5, anchorY: 0.5 }); self.points = 25; self.floatOffset = Math.random() * Math.PI * 2; self.update = function () { gemGraphics.y = Math.sin(LK.ticks * 0.15 + self.floatOffset) * 3; gemGraphics.rotation += 0.05; gemGraphics.scaleX = Math.sin(LK.ticks * 0.1 + self.floatOffset) * 0.2 + 1; gemGraphics.scaleY = Math.sin(LK.ticks * 0.1 + self.floatOffset) * 0.2 + 1; }; return self; }); var Luigi = Container.expand(function () { var self = Container.call(this); var luigiGraphics = self.attachAsset('luigi', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; self.jumpTimer = 0; self.jumpInterval = 120; // 2 seconds self.isJumping = false; self.jumpHeight = 0; self.maxJumpHeight = 100; self.jumpSpeed = 8; self.direction = 1; // 1 for right, -1 for left self.update = function () { // Move horizontally self.x += self.speed * self.direction; // Bounce off screen edges if (self.x <= 100 || self.x >= 1948) { self.direction *= -1; luigiGraphics.scaleX = self.direction; } // Jump behavior self.jumpTimer++; if (self.jumpTimer >= self.jumpInterval && !self.isJumping) { self.isJumping = true; self.jumpHeight = 0; self.jumpTimer = 0; } if (self.isJumping) { self.jumpHeight += self.jumpSpeed; if (self.jumpHeight >= self.maxJumpHeight) { self.jumpSpeed = -8; } if (self.jumpHeight <= 0 && self.jumpSpeed < 0) { self.jumpHeight = 0; self.jumpSpeed = 8; self.isJumping = false; } luigiGraphics.y = -self.jumpHeight; } // Check if player is close and doesn't have weapon if (!playerWeapon) { var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= 100) { // Give weapon to player playerWeapon = new Weapon(); playerWeapon.x = player.x; playerWeapon.y = player.y - 50; game.addChild(playerWeapon); LK.effects.flashObject(self, 0x00FF00, 500); updateScore(100); // Bonus for getting weapon } } // Animate Luigi luigiGraphics.rotation = Math.sin(LK.ticks * 0.1) * 0.1; }; return self; }); var Mario = Container.expand(function () { var self = Container.call(this); var marioGraphics = self.attachAsset('mario', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; self.targetSpaghetti = null; self.searchTimer = 0; self.searchInterval = 60; // 1 second self.isAngry = false; self.angerTimer = 0; self.angerDuration = 300; // 5 seconds of anger self.attackSpeed = 6; self.health = 100; self.maxHealth = 100; // Create health bar var healthBarBg = self.attachAsset('health_bar_bg', { anchorX: 0.5, anchorY: 0.5 }); healthBarBg.y = -120; var healthBarFill = self.attachAsset('health_bar_fill', { anchorX: 0, anchorY: 0.5 }); healthBarFill.x = -40; healthBarFill.y = -120; self.update = function () { // Search for nearest spaghetti self.searchTimer++; if (self.searchTimer >= self.searchInterval) { self.findNearestSpaghetti(); self.searchTimer = 0; } // Handle anger state if (self.isAngry) { self.angerTimer--; if (self.angerTimer <= 0) { self.isAngry = false; marioGraphics.tint = 0xFFFFFF; // Return to normal color } else { // Attack player when angry var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { self.x += dx / distance * self.attackSpeed; self.y += dy / distance * self.attackSpeed; // Face the direction of movement marioGraphics.scaleX = dx > 0 ? 1 : -1; } } } else { // Move towards target spaghetti if (self.targetSpaghetti && spaghettis.indexOf(self.targetSpaghetti) !== -1) { var dx = self.targetSpaghetti.x - self.x; var dy = self.targetSpaghetti.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; // Face the direction of movement marioGraphics.scaleX = dx > 0 ? 1 : -1; } } else { // Random movement when no spaghetti found self.x += (Math.random() - 0.5) * 2; self.y += (Math.random() - 0.5) * 2; } } // Keep Mario in bounds self.x = Math.max(100, Math.min(1948, self.x)); self.y = Math.max(100, Math.min(2632, self.y)); // Update health bar var healthPercent = self.health / self.maxHealth; healthBarFill.width = 80 * healthPercent; if (healthPercent > 0.6) { healthBarFill.tint = 0x00FF00; // Green } else if (healthPercent > 0.3) { healthBarFill.tint = 0xFFFF00; // Yellow } else { healthBarFill.tint = 0xFF0000; // Red } // Animate Mario marioGraphics.rotation = Math.sin(LK.ticks * 0.1) * 0.05; }; self.findNearestSpaghetti = function () { var nearestDistance = Infinity; var nearestSpaghetti = null; for (var i = 0; i < spaghettis.length; i++) { var spaghetti = spaghettis[i]; var dx = spaghetti.x - self.x; var dy = spaghetti.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance) { nearestDistance = distance; nearestSpaghetti = spaghetti; } } self.targetSpaghetti = nearestSpaghetti; }; self.becomeAngry = function () { self.isAngry = true; self.angerTimer = self.angerDuration; marioGraphics.tint = 0xFF0000; // Turn red when angry LK.effects.flashObject(self, 0xFF0000, 500); }; self.takeDamage = function (damage) { self.health = Math.max(0, self.health - damage); LK.effects.flashObject(self, 0xFF0000, 300); if (self.health <= 0) { // Mario is defeated and disappears LK.effects.flashObject(self, 0x000000, 1000); self.shouldDestroy = true; // Mark Mario for destruction } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.invulnerable = false; self.invulnerabilityTime = 0; self.speedBoost = false; self.speedBoostTime = 0; self.update = function () { if (self.invulnerabilityTime > 0) { self.invulnerabilityTime--; playerGraphics.alpha = Math.sin(LK.ticks * 0.3) * 0.5 + 0.5; if (self.invulnerabilityTime <= 0) { self.invulnerable = false; playerGraphics.alpha = 1; } } if (self.speedBoostTime > 0) { self.speedBoostTime--; if (self.speedBoostTime <= 0) { self.speedBoost = false; playerGraphics.tint = 0xFFFFFF; } } }; self.activateInvulnerability = function () { self.invulnerable = true; self.invulnerabilityTime = 120; // 2 seconds at 60fps }; self.activateSpeedBoost = function () { self.speedBoost = true; self.speedBoostTime = 300; // 5 seconds at 60fps playerGraphics.tint = 0x00FFFF; }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.type = Math.random() < 0.5 ? 'speed' : 'invulnerable'; self.floatOffset = Math.random() * Math.PI * 2; if (self.type === 'invulnerable') { powerupGraphics.tint = 0xFFD700; } self.update = function () { powerupGraphics.y = Math.sin(LK.ticks * 0.2 + self.floatOffset) * 8; powerupGraphics.rotation += 0.1; powerupGraphics.alpha = Math.sin(LK.ticks * 0.3) * 0.3 + 0.7; }; return self; }); var Sonic = Container.expand(function () { var self = Container.call(this); var sonicGraphics = self.attachAsset('sonic', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 4; self.targetMario = null; self.searchTimer = 0; self.searchInterval = 30; // 0.5 seconds self.attackTimer = 0; self.attackInterval = 120; // 2 seconds self.spindashTimer = 0; self.isSpinning = false; self.direction = 1; self.goldTimer = 30 * 60; // 30 seconds at 60fps self.goldCollected = 0; self.goldTarget = 3; self.isAttackingPlayer = false; self.targetPlayer = null; self.health = 80; self.maxHealth = 80; // Create health bar var healthBarBg = self.attachAsset('health_bar_bg', { anchorX: 0.5, anchorY: 0.5 }); healthBarBg.y = -120; var healthBarFill = self.attachAsset('health_bar_fill', { anchorX: 0, anchorY: 0.5 }); healthBarFill.x = -40; healthBarFill.y = -120; self.update = function () { // Update gold collection timer self.goldTimer--; if (self.goldTimer <= 0 && self.goldCollected < self.goldTarget) { self.isAttackingPlayer = true; self.targetPlayer = player; sonicGraphics.tint = 0xFF0000; // Turn red when attacking player } // Behavior based on current state if (self.isAttackingPlayer && self.targetPlayer) { // Attack player mode var dx = self.targetPlayer.x - self.x; var dy = self.targetPlayer.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { self.x += dx / distance * (self.speed * 1.5); // Faster when attacking player self.y += dy / distance * (self.speed * 1.5); sonicGraphics.scaleX = dx > 0 ? 1 : -1; self.direction = dx > 0 ? 1 : -1; } } else if (self.goldCollected < self.goldTarget) { // Gold collection mode - search for gems (gold) self.searchTimer++; if (self.searchTimer >= self.searchInterval) { self.findNearestGem(); self.searchTimer = 0; } // Move towards nearest gem if (self.targetGem && gems.indexOf(self.targetGem) !== -1) { var dx = self.targetGem.x - self.x; var dy = self.targetGem.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; sonicGraphics.scaleX = dx > 0 ? 1 : -1; self.direction = dx > 0 ? 1 : -1; } } else { // Search pattern movement self.x += Math.sin(LK.ticks * 0.02) * 3; self.y += Math.cos(LK.ticks * 0.015) * 2; } } else { // Normal mode (after collecting enough gold) - but only attack Mario if dragon is alive if (!dragon.isDead) { self.searchTimer++; if (self.searchTimer >= self.searchInterval) { self.findMario(); self.searchTimer = 0; } // Move towards Mario for combat if (self.targetMario && marios.indexOf(self.targetMario) !== -1) { var dx = self.targetMario.x - self.x; var dy = self.targetMario.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 80) { // Move towards Mario self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; sonicGraphics.scaleX = dx > 0 ? 1 : -1; self.direction = dx > 0 ? 1 : -1; } else { // Close enough to attack - start spindash self.attackTimer++; if (self.attackTimer >= self.attackInterval && !self.isSpinning) { self.startSpindash(); self.attackTimer = 0; } } } else { // Search pattern movement self.x += Math.sin(LK.ticks * 0.02) * 3; self.y += Math.cos(LK.ticks * 0.015) * 2; } } else { // Dragon is dead - peaceful mode, just wander around self.x += Math.sin(LK.ticks * 0.01) * 2; self.y += Math.cos(LK.ticks * 0.008) * 1.5; } } // Handle spindash attack if (self.isSpinning) { self.spindashTimer++; sonicGraphics.rotation += 0.5; sonicGraphics.scaleX = Math.sin(LK.ticks * 0.3) * 0.2 + 0.8; sonicGraphics.scaleY = Math.sin(LK.ticks * 0.3) * 0.2 + 0.8; if (self.spindashTimer >= 60) { self.isSpinning = false; self.spindashTimer = 0; sonicGraphics.rotation = 0; sonicGraphics.scaleX = self.direction; sonicGraphics.scaleY = 1; } } // Keep Sonic in bounds self.x = Math.max(100, Math.min(1948, self.x)); self.y = Math.max(100, Math.min(2632, self.y)); // Update health bar var healthPercent = self.health / self.maxHealth; healthBarFill.width = 80 * healthPercent; if (healthPercent > 0.6) { healthBarFill.tint = 0x00FF00; // Green } else if (healthPercent > 0.3) { healthBarFill.tint = 0xFFFF00; // Yellow } else { healthBarFill.tint = 0xFF0000; // Red } // Idle animation when not spinning if (!self.isSpinning) { sonicGraphics.y = Math.sin(LK.ticks * 0.15) * 2; } }; self.findMario = function () { var nearestDistance = Infinity; var nearestMario = null; for (var i = 0; i < marios.length; i++) { var mario = marios[i]; var dx = mario.x - self.x; var dy = mario.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance) { nearestDistance = distance; nearestMario = mario; } } self.targetMario = nearestMario; }; self.findNearestGem = function () { var nearestDistance = Infinity; var nearestGem = null; // First check for sonic gold (priority) for (var i = 0; i < sonicGolds.length; i++) { var sonicGold = sonicGolds[i]; var dx = sonicGold.x - self.x; var dy = sonicGold.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance) { nearestDistance = distance; nearestGem = sonicGold; } } // Then check regular gems if no sonic gold found if (!nearestGem) { for (var i = 0; i < gems.length; i++) { var gem = gems[i]; var dx = gem.x - self.x; var dy = gem.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < nearestDistance) { nearestDistance = distance; nearestGem = gem; } } } self.targetGem = nearestGem; }; self.startSpindash = function () { self.isSpinning = true; self.spindashTimer = 0; // Flash blue to indicate attack LK.effects.flashObject(self, 0x0066FF, 200); }; self.takeDamage = function (damage) { self.health = Math.max(0, self.health - damage); LK.effects.flashObject(self, 0xFF0000, 300); if (self.health <= 0) { // Sonic is defeated and disappears LK.effects.flashObject(self, 0x000000, 1000); self.shouldDestroy = true; // Mark Sonic for destruction } }; return self; }); var SonicGold = Container.expand(function () { var self = Container.call(this); var sonicGoldGraphics = self.attachAsset('sonic_gold', { anchorX: 0.5, anchorY: 0.5 }); self.points = 30; self.floatOffset = Math.random() * Math.PI * 2; // Give it a special blue tint to distinguish from regular gems sonicGoldGraphics.tint = 0x0066FF; self.update = function () { sonicGoldGraphics.y = Math.sin(LK.ticks * 0.18 + self.floatOffset) * 4; sonicGoldGraphics.rotation += 0.08; sonicGoldGraphics.scaleX = Math.sin(LK.ticks * 0.12 + self.floatOffset) * 0.25 + 1; sonicGoldGraphics.scaleY = Math.sin(LK.ticks * 0.12 + self.floatOffset) * 0.25 + 1; // Special pulsing effect sonicGoldGraphics.alpha = Math.sin(LK.ticks * 0.2) * 0.3 + 0.7; }; return self; }); var Spaghetti = Container.expand(function () { var self = Container.call(this); var spaghettiGraphics = self.attachAsset('spaghetti', { anchorX: 0.5, anchorY: 0.5 }); self.points = 15; self.floatOffset = Math.random() * Math.PI * 2; self.update = function () { spaghettiGraphics.y = Math.sin(LK.ticks * 0.12 + self.floatOffset) * 4; spaghettiGraphics.rotation += 0.03; spaghettiGraphics.scaleX = Math.sin(LK.ticks * 0.08 + self.floatOffset) * 0.1 + 1; spaghettiGraphics.scaleY = Math.sin(LK.ticks * 0.08 + self.floatOffset) * 0.1 + 1; }; return self; }); var Treasure = Container.expand(function () { var self = Container.call(this); var treasureGraphics = self.attachAsset('treasure', { anchorX: 0.5, anchorY: 0.5 }); self.points = 10; self.floatOffset = Math.random() * Math.PI * 2; self.update = function () { treasureGraphics.y = Math.sin(LK.ticks * 0.1 + self.floatOffset) * 5; treasureGraphics.rotation += 0.02; }; return self; }); var Weapon = Container.expand(function () { var self = Container.call(this); var weaponGraphics = self.attachAsset('weapon', { anchorX: 0.5, anchorY: 0.5 }); self.damage = 25; self.cooldown = 0; self.maxCooldown = 30; // 0.5 seconds self.range = 150; self.isActive = false; self.update = function () { if (self.cooldown > 0) { self.cooldown--; } // Rotate weapon around player weaponGraphics.rotation += 0.2; // Pulse effect when ready to use if (self.cooldown <= 0) { weaponGraphics.alpha = Math.sin(LK.ticks * 0.3) * 0.3 + 0.7; weaponGraphics.scaleX = Math.sin(LK.ticks * 0.2) * 0.2 + 1; weaponGraphics.scaleY = Math.sin(LK.ticks * 0.2) * 0.2 + 1; } else { weaponGraphics.alpha = 0.5; weaponGraphics.scaleX = 0.8; weaponGraphics.scaleY = 0.8; } }; self.attack = function (target) { if (self.cooldown <= 0) { var dx = target.x - self.x; var dy = target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.range) { target.takeDamage(self.damage); self.cooldown = self.maxCooldown; LK.effects.flashObject(self, 0xFFFFFF, 300); LK.getSound('weapon_hit').play(); return true; } } return false; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x8B4513 }); /**** * Game Code ****/ game.setBackgroundColor(0xDEB887); // Game variables var score = 0; var health = 250; var maxHealth = 250; var gameTimer = 80 * 60; // 1 minute 20 seconds (80 seconds) at 60fps var treasures = []; var gems = []; var powerups = []; var fireballs = []; var luigis = []; var marios = []; var spaghettis = []; var sonics = []; var sonicGolds = []; var treasureSpawnTimer = 0; var gemSpawnTimer = 0; var powerupSpawnTimer = 0; var luigiSpawnTimer = 0; var spaghettiSpawnTimer = 0; var sonicGoldSpawnTimer = 0; var sonicGoldSpawnCount = 0; var maxSonicGoldSpawns = 3; var playerWeapon = null; // Achievement system var achievements = []; var activeAchievements = []; var achievementStats = { treasuresCollected: 0, gemsCollected: 0, powerupsCollected: 0, dragonHits: 0, fireballsAvoided: 0, survivalTime: 0, maxScore: 0 }; // Initialize achievements function initializeAchievements() { achievements = [new Achievement('first_treasure', 'First Treasure!', 'Collect your first treasure', '💰'), new Achievement('treasure_hunter', 'Treasure Hunter', 'Collect 10 treasures', '🏆'), new Achievement('gem_collector', 'Gem Collector', 'Collect 5 gems', '💎'), new Achievement('survivor', 'Survivor', 'Survive for 30 seconds', '⏰'), new Achievement('speed_demon', 'Speed Demon', 'Use 3 speed power-ups', '⚡'), new Achievement('invincible', 'Invincible', 'Use 3 invulnerability power-ups', '🛡️'), new Achievement('score_master', 'Score Master', 'Reach 200 points', '🎯'), new Achievement('dragon_dancer', 'Dragon Dancer', 'Get hit by dragon 5 times and survive', '🐉'), new Achievement('high_scorer', 'High Scorer', 'Reach 300 points', '🌟'), new Achievement('ultimate_survivor', 'Ultimate Survivor', 'Survive for 60 seconds', '👑')]; // Load unlocked achievements from storage for (var i = 0; i < achievements.length; i++) { var achievement = achievements[i]; if (storage['achievement_' + achievement.id]) { achievement.unlocked = true; } } } function checkAchievements() { for (var i = 0; i < achievements.length; i++) { var achievement = achievements[i]; if (!achievement.unlocked) { var shouldUnlock = false; switch (achievement.id) { case 'first_treasure': shouldUnlock = achievementStats.treasuresCollected >= 1; break; case 'treasure_hunter': shouldUnlock = achievementStats.treasuresCollected >= 10; break; case 'gem_collector': shouldUnlock = achievementStats.gemsCollected >= 5; break; case 'survivor': shouldUnlock = achievementStats.survivalTime >= 30 * 60; break; case 'speed_demon': shouldUnlock = achievementStats.powerupsCollected >= 3; break; case 'invincible': shouldUnlock = achievementStats.powerupsCollected >= 3; break; case 'score_master': shouldUnlock = score >= 200; break; case 'dragon_dancer': shouldUnlock = achievementStats.dragonHits >= 5; break; case 'high_scorer': shouldUnlock = score >= 300; break; case 'ultimate_survivor': shouldUnlock = achievementStats.survivalTime >= 60 * 60; break; } if (shouldUnlock) { achievement.unlock(); activeAchievements.push(achievement); game.addChild(achievement); } } } } // Initialize achievements initializeAchievements(); // Create player var player = game.addChild(new Player()); player.x = 1024; player.y = 1366; // Create dragon var dragon = game.addChild(new Dragon()); dragon.x = 200; dragon.y = 200; // Create Luigi monster var luigi = game.addChild(new Luigi()); luigi.x = 1500; luigi.y = 1000; luigis.push(luigi); // Create Mario character var mario = game.addChild(new Mario()); mario.x = 300; mario.y = 800; marios.push(mario); // Create Sonic character var sonic = game.addChild(new Sonic()); sonic.x = 1700; sonic.y = 600; sonics.push(sonic); // UI Elements var scoreTxt = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var healthTxt = new Text2('Health: 250/250', { size: 60, fill: 0x00FF00 }); healthTxt.anchor.set(0, 0); healthTxt.x = 120; healthTxt.y = 20; LK.gui.addChild(healthTxt); var timerTxt = new Text2('Time: 1:20', { size: 70, fill: 0xFFFFFF }); timerTxt.anchor.set(1, 0); timerTxt.x = 2048 - 20; timerTxt.y = 20; LK.gui.addChild(timerTxt); var instructionTxt = new Text2('Tap to move! Get close to Luigi for weapon to defeat dragon!', { size: 50, fill: 0xFFFFFF }); instructionTxt.anchor.set(0.5, 1); LK.gui.bottom.addChild(instructionTxt); // Game logic functions function spawnTreasure() { var treasure = new Treasure(); treasure.x = Math.random() * 1800 + 124; treasure.y = Math.random() * 2400 + 166; treasures.push(treasure); game.addChild(treasure); } function spawnGem() { var gem = new Gem(); gem.x = Math.random() * 1800 + 124; gem.y = Math.random() * 2400 + 166; gems.push(gem); game.addChild(gem); } function spawnPowerUp() { var powerup = new PowerUp(); powerup.x = Math.random() * 1800 + 124; powerup.y = Math.random() * 2400 + 166; powerups.push(powerup); game.addChild(powerup); } function spawnSpaghetti() { var spaghetti = new Spaghetti(); spaghetti.x = Math.random() * 1800 + 124; spaghetti.y = Math.random() * 2400 + 166; spaghettis.push(spaghetti); game.addChild(spaghetti); } function spawnSonicGold() { if (sonicGoldSpawnCount < maxSonicGoldSpawns) { var sonicGold = new SonicGold(); sonicGold.x = Math.random() * 1800 + 124; sonicGold.y = Math.random() * 2400 + 166; sonicGolds.push(sonicGold); game.addChild(sonicGold); } } function updateScore(points) { score += points; scoreTxt.setText('Score: ' + score); LK.setScore(score); } function updateHealth(damage) { health = Math.max(0, health - damage); healthTxt.setText('Health: ' + health + '/' + maxHealth); // Change color based on health percentage var healthPercent = health / maxHealth; if (healthPercent > 0.6) { healthTxt.fill = 0x00FF00; // Green } else if (healthPercent > 0.3) { healthTxt.fill = 0xFFFF00; // Yellow } else { healthTxt.fill = 0xFF0000; // Red } if (health <= 0) { LK.effects.flashScreen(0xFF0000, 1000); LK.showGameOver(); } } function updateTimer() { gameTimer = Math.max(0, gameTimer - 1); var totalSeconds = Math.floor(gameTimer / 60); var minutes = Math.floor(totalSeconds / 60); var seconds = totalSeconds % 60; var timeText = minutes + ':' + (seconds < 10 ? '0' : '') + seconds; timerTxt.setText('Time: ' + timeText); // Change color based on remaining time if (gameTimer <= 10 * 60) { // Last 10 seconds timerTxt.fill = 0xFF0000; // Red } else if (gameTimer <= 30 * 60) { // Last 30 seconds timerTxt.fill = 0xFFFF00; // Yellow } else { timerTxt.fill = 0xFFFFFF; // White } if (gameTimer <= 0) { LK.effects.flashScreen(0xFF0000, 1000); LK.showGameOver(); } } // Touch controls var targetX = player.x; var targetY = player.y; game.down = function (x, y, obj) { targetX = x; targetY = y; // Attack dragon with weapon if player has one if (playerWeapon) { playerWeapon.attack(dragon); // Also attack any Mario in range for (var i = 0; i < marios.length; i++) { var mario = marios[i]; if (mario.health > 0) { playerWeapon.attack(mario); } } // Also attack any Sonic in range for (var i = 0; i < sonics.length; i++) { var sonic = sonics[i]; playerWeapon.attack(sonic); } } }; game.move = function (x, y, obj) { targetX = x; targetY = y; }; // Game update loop game.update = function () { // Update timer updateTimer(); // Move player towards target var dx = targetX - player.x; var dy = targetY - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { var speed = player.speedBoost ? player.speed * 1.5 : player.speed; player.x += dx / distance * speed; player.y += dy / distance * speed; } // Keep player in bounds player.x = Math.max(40, Math.min(2008, player.x)); player.y = Math.max(40, Math.min(2692, player.y)); // Update weapon position if player has one if (playerWeapon) { playerWeapon.x = player.x; playerWeapon.y = player.y - 50; // Auto-attack dragon when in range var dx = dragon.x - playerWeapon.x; var dy = dragon.y - playerWeapon.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= playerWeapon.range) { playerWeapon.attack(dragon); } // Auto-attack Mario when in range for (var i = 0; i < marios.length; i++) { var mario = marios[i]; if (mario.health > 0) { var dx = mario.x - playerWeapon.x; var dy = mario.y - playerWeapon.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= playerWeapon.range) { playerWeapon.attack(mario); } } } // Auto-attack Sonic when in range for (var i = 0; i < sonics.length; i++) { var sonic = sonics[i]; var dx = sonic.x - playerWeapon.x; var dy = sonic.y - playerWeapon.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= playerWeapon.range) { playerWeapon.attack(sonic); } } } // Spawn treasures treasureSpawnTimer++; if (treasureSpawnTimer >= 90) { // Every 1.5 seconds spawnTreasure(); treasureSpawnTimer = 0; } // Spawn gems gemSpawnTimer++; if (gemSpawnTimer >= 180) { // Every 3 seconds spawnGem(); gemSpawnTimer = 0; } // Spawn power-ups powerupSpawnTimer++; if (powerupSpawnTimer >= 600) { // Every 10 seconds spawnPowerUp(); powerupSpawnTimer = 0; } // Spawn spaghetti spaghettiSpawnTimer++; if (spaghettiSpawnTimer >= 120) { // Every 2 seconds spawnSpaghetti(); spaghettiSpawnTimer = 0; } // Spawn sonic gold sonicGoldSpawnTimer++; if (sonicGoldSpawnTimer >= 240 && sonicGoldSpawnCount < maxSonicGoldSpawns) { // Every 4 seconds, but only up to maximum allowed spawnSonicGold(); sonicGoldSpawnTimer = 0; sonicGoldSpawnCount++; } // Check treasure collection for (var i = treasures.length - 1; i >= 0; i--) { var treasure = treasures[i]; if (player.intersects(treasure)) { updateScore(treasure.points); achievementStats.treasuresCollected++; LK.effects.flashObject(treasure, 0xFFFFFF, 300); treasure.destroy(); treasures.splice(i, 1); LK.getSound('collect').play(); } } // Check gem collection for (var i = gems.length - 1; i >= 0; i--) { var gem = gems[i]; if (player.intersects(gem)) { updateScore(gem.points); achievementStats.gemsCollected++; LK.effects.flashObject(gem, 0xFFFFFF, 300); gem.destroy(); gems.splice(i, 1); LK.getSound('collect').play(); } } // Check power-up collection for (var i = powerups.length - 1; i >= 0; i--) { var powerup = powerups[i]; if (player.intersects(powerup)) { if (powerup.type === 'speed') { player.activateSpeedBoost(); } else if (powerup.type === 'invulnerable') { player.activateInvulnerability(); } achievementStats.powerupsCollected++; LK.effects.flashObject(powerup, 0xFFFFFF, 300); powerup.destroy(); powerups.splice(i, 1); LK.getSound('powerup').play(); } } // Check Mario spaghetti collection for (var i = marios.length - 1; i >= 0; i--) { var mario = marios[i]; for (var j = spaghettis.length - 1; j >= 0; j--) { var spaghetti = spaghettis[j]; if (mario.intersects(spaghetti)) { updateScore(spaghetti.points); LK.effects.flashObject(spaghetti, 0xFFD700, 300); spaghetti.destroy(); spaghettis.splice(j, 1); LK.getSound('collect').play(); break; } } } // Check player spaghetti collection for (var i = spaghettis.length - 1; i >= 0; i--) { var spaghetti = spaghettis[i]; if (player.intersects(spaghetti)) { updateScore(spaghetti.points); LK.effects.flashObject(spaghetti, 0xFFD700, 300); // Make all Marios angry when player steals spaghetti for (var j = 0; j < marios.length; j++) { var mario = marios[j]; if (!mario.isAngry) { mario.becomeAngry(); } } spaghetti.destroy(); spaghettis.splice(i, 1); LK.getSound('collect').play(); } } // Check if dragon is defeated and should disappear if (dragon.health <= 0 && !dragon.isDead) { dragon.isDead = true; // Make all Marios angry when dragon is defeated for (var j = 0; j < marios.length; j++) { var mario = marios[j]; if (!mario.isAngry) { mario.becomeAngry(); } } // Sonics remain in the game when dragon is defeated - they will no longer attack Mario for (var k = 0; k < sonics.length; k++) { var sonic = sonics[k]; sonic.isAttackingPlayer = false; // Stop attacking player sonic.targetMario = null; // Clear Mario target sonic.targetPlayer = null; // Clear player target sonicGraphics = sonic.children[0]; // Get sonic graphics if (sonicGraphics) { sonicGraphics.tint = 0xFFFFFF; // Return to normal color } } LK.effects.flashScreen(0x00FF00, 1000); // Green flash for dragon defeat updateScore(200); // Bonus points for defeating dragon // Dragon disappears from the game dragon.destroy(); } // Check if any Mario has died and make Sonics attack player for (var i = marios.length - 1; i >= 0; i--) { var mario = marios[i]; if (mario.shouldDestroy) { // Mario is dead, make all Sonics attack player for (var j = 0; j < sonics.length; j++) { var sonic = sonics[j]; sonic.isAttackingPlayer = true; sonic.targetPlayer = player; var sonicGraphics = sonic.children[0]; if (sonicGraphics) { sonicGraphics.tint = 0xFF0000; // Turn red when attacking player } } // Remove Mario from game mario.destroy(); marios.splice(i, 1); } } // Check if any Sonic has died and remove them for (var i = sonics.length - 1; i >= 0; i--) { var sonic = sonics[i]; if (sonic.shouldDestroy) { // Sonic died - game over LK.effects.flashScreen(0xFF0000, 1000); LK.showGameOver(); // Remove Sonic from game sonic.destroy(); sonics.splice(i, 1); } } // Game continues until timer runs out or player dies // Check dragon collision if (!player.invulnerable && player.intersects(dragon)) { if (!player.lastDragonHit) { updateHealth(50); achievementStats.dragonHits++; player.activateInvulnerability(); LK.effects.flashScreen(0xFF0000, 500); player.lastDragonHit = true; } } else { player.lastDragonHit = false; } // Check fireball collisions for (var i = fireballs.length - 1; i >= 0; i--) { var fireball = fireballs[i]; if (fireball.shouldDestroy) { fireball.destroy(); fireballs.splice(i, 1); continue; } if (!player.invulnerable && player.intersects(fireball)) { if (!fireball.hasHit) { updateHealth(25); player.activateInvulnerability(); LK.effects.flashScreen(0xFF0000, 300); fireball.hasHit = true; fireball.shouldDestroy = true; } } } // Check Luigi collisions for (var i = luigis.length - 1; i >= 0; i--) { var luigi = luigis[i]; if (!player.invulnerable && player.intersects(luigi)) { if (!luigi.lastHit) { updateHealth(30); player.activateInvulnerability(); LK.effects.flashScreen(0x00FF00, 400); luigi.lastHit = true; } } else { luigi.lastHit = false; } } // Check angry Mario attacking player for (var i = marios.length - 1; i >= 0; i--) { var mario = marios[i]; if (mario.isAngry && !player.invulnerable && player.intersects(mario)) { if (!mario.lastPlayerHit) { updateHealth(40); player.activateInvulnerability(); LK.effects.flashScreen(0xFF0000, 400); mario.lastPlayerHit = true; } } else { mario.lastPlayerHit = false; } } // Check sonic gold collection (special gold for Sonic) for (var i = sonicGolds.length - 1; i >= 0; i--) { var sonicGold = sonicGolds[i]; if (player.intersects(sonicGold)) { // Check if any Sonic needs gold var goldGivenToSonic = false; for (var j = 0; j < sonics.length; j++) { var sonic = sonics[j]; if (sonic.goldCollected < sonic.goldTarget) { sonic.goldCollected++; goldGivenToSonic = true; LK.effects.flashObject(sonic, 0x0066FF, 500); // Flash Sonic to show he received gold break; } } if (goldGivenToSonic) { updateScore(sonicGold.points); achievementStats.gemsCollected++; LK.effects.flashObject(sonicGold, 0x0066FF, 300); // Blue flash for Sonic gold sonicGold.destroy(); sonicGolds.splice(i, 1); LK.getSound('collect').play(); } else { // Normal collection if no Sonic needs gold updateScore(sonicGold.points); achievementStats.gemsCollected++; LK.effects.flashObject(sonicGold, 0xFFD700, 300); sonicGold.destroy(); sonicGolds.splice(i, 1); LK.getSound('collect').play(); } } } // Check if player collects gems for Sonic for (var i = gems.length - 1; i >= 0; i--) { var gem = gems[i]; if (player.intersects(gem)) { // Check if any Sonic needs gold var goldGivenToSonic = false; for (var j = 0; j < sonics.length; j++) { var sonic = sonics[j]; if (sonic.goldCollected < sonic.goldTarget) { sonic.goldCollected++; goldGivenToSonic = true; LK.effects.flashObject(sonic, 0x0066FF, 300); // Flash Sonic to show he received gold break; } } if (goldGivenToSonic) { updateScore(gem.points); achievementStats.gemsCollected++; LK.effects.flashObject(gem, 0xFFD700, 300); // Gold flash for Sonic collection gem.destroy(); gems.splice(i, 1); LK.getSound('collect').play(); } else { // Normal gem collection if no Sonic needs gold updateScore(gem.points); achievementStats.gemsCollected++; LK.effects.flashObject(gem, 0xFFFFFF, 300); gem.destroy(); gems.splice(i, 1); LK.getSound('collect').play(); } } } // Check Sonic attacking player for (var i = sonics.length - 1; i >= 0; i--) { var sonic = sonics[i]; if (sonic.isAttackingPlayer && !player.invulnerable && player.intersects(sonic)) { if (!sonic.lastPlayerHit) { updateHealth(35); player.activateInvulnerability(); LK.effects.flashScreen(0x0066FF, 400); sonic.lastPlayerHit = true; } } else { sonic.lastPlayerHit = false; } } // Check Sonic vs Mario combat for (var i = sonics.length - 1; i >= 0; i--) { var sonic = sonics[i]; for (var j = marios.length - 1; j >= 0; j--) { var mario = marios[j]; if (sonic.intersects(mario)) { if (!sonic.lastMarioHit && sonic.isSpinning) { // Sonic hits Mario during spindash mario.takeDamage(20); LK.effects.flashObject(mario, 0xFF0000, 500); LK.effects.flashObject(sonic, 0x0066FF, 300); updateScore(50); // Bonus points for combat sonic.lastMarioHit = true; } else if (!mario.lastSonicHit && !sonic.isSpinning) { // Mario hits Sonic when not spinning LK.effects.flashObject(sonic, 0xFF0000, 500); LK.effects.flashObject(mario, 0x00FF00, 300); updateScore(30); // Bonus points for combat mario.lastSonicHit = true; } } else { sonic.lastMarioHit = false; mario.lastSonicHit = false; } } } // Spawn additional Luigis based on score luigiSpawnTimer++; if (luigiSpawnTimer >= 1800 && score >= 100) { // Every 30 seconds after score 100 var newLuigi = new Luigi(); newLuigi.x = Math.random() * 1800 + 124; newLuigi.y = Math.random() * 2000 + 500; luigis.push(newLuigi); game.addChild(newLuigi); luigiSpawnTimer = 0; } // Update achievement stats achievementStats.survivalTime++; if (score > achievementStats.maxScore) { achievementStats.maxScore = score; } // Check for new achievements checkAchievements(); // Update active achievement displays for (var i = activeAchievements.length - 1; i >= 0; i--) { var achievement = activeAchievements[i]; if (achievement.displayTime <= 0 && achievement.alpha <= 0) { achievement.destroy(); activeAchievements.splice(i, 1); } } // Win condition if (score >= 500) { LK.showYouWin(); } }; // Start background music LK.playMusic('desert'); // Initial treasures for (var i = 0; i < 3; i++) { spawnTreasure(); } // Initial spaghetti for (var i = 0; i < 2; i++) { spawnSpaghetti(); } // Initial sonic gold - removed to respect 3 total limit ;
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Achievement = Container.expand(function (id, title, description, icon) {
var self = Container.call(this);
self.id = id;
self.title = title;
self.description = description;
self.icon = icon;
self.unlocked = false;
self.displayTime = 0;
// Create achievement notification display
var bg = LK.getAsset('achievement_bg', {
width: 600,
height: 120,
color: 0x2C3E50,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
self.addChild(bg);
var titleText = new Text2(title, {
size: 40,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0);
titleText.x = 0;
titleText.y = -30;
self.addChild(titleText);
var descText = new Text2(description, {
size: 30,
fill: 0xFFFFFF
});
descText.anchor.set(0.5, 1);
descText.x = 0;
descText.y = 30;
self.addChild(descText);
self.unlock = function () {
if (!self.unlocked) {
self.unlocked = true;
self.show();
// Save to storage
storage['achievement_' + self.id] = true;
}
};
self.show = function () {
self.x = 1024;
self.y = 200;
self.alpha = 0;
self.scaleX = 0.5;
self.scaleY = 0.5;
self.displayTime = 180; // 3 seconds
// Animate in
tween(self, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 500
});
};
self.update = function () {
if (self.displayTime > 0) {
self.displayTime--;
if (self.displayTime <= 0) {
// Animate out
tween(self, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 500
});
}
}
};
return self;
});
var Dragon = Container.expand(function () {
var self = Container.call(this);
var dragonGraphics = self.attachAsset('dragon', {
anchorX: 0.5,
anchorY: 0.5
});
self.baseSpeed = 1.5;
self.currentSpeed = self.baseSpeed;
self.fireTimer = 0;
self.fireInterval = 120; // 2 seconds initially
self.health = 150;
self.maxHealth = 150;
// Create health bar
var dragonHealthBarBg = self.attachAsset('dragon_health_bar_bg', {
anchorX: 0.5,
anchorY: 0.5
});
dragonHealthBarBg.y = -180;
var dragonHealthBarFill = self.attachAsset('dragon_health_bar_fill', {
anchorX: 0,
anchorY: 0.5
});
dragonHealthBarFill.x = -60;
dragonHealthBarFill.y = -180;
self.update = function () {
// Follow player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.currentSpeed;
self.y += dy / distance * self.currentSpeed;
}
// Fire breathing timer
self.fireTimer++;
if (self.fireTimer >= self.fireInterval) {
self.breatheFire();
self.fireTimer = 0;
}
// Adjust difficulty based on score
var difficulty = Math.floor(score / 10);
self.currentSpeed = self.baseSpeed + difficulty * 0.5;
self.fireInterval = Math.max(60, 120 - difficulty * 10);
// Update health bar
var healthPercent = self.health / self.maxHealth;
dragonHealthBarFill.width = 120 * healthPercent;
if (healthPercent > 0.6) {
dragonHealthBarFill.tint = 0xFF0000; // Red
} else if (healthPercent > 0.3) {
dragonHealthBarFill.tint = 0xFF4444; // Light Red
} else {
dragonHealthBarFill.tint = 0xFF8888; // Very Light Red
}
};
self.breatheFire = function () {
var fireball = new Fireball();
fireball.x = self.x;
fireball.y = self.y;
// Aim towards player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
fireball.directionX = dx / distance;
fireball.directionY = dy / distance;
fireballs.push(fireball);
game.addChild(fireball);
LK.getSound('fire').play();
};
self.takeDamage = function (damage) {
self.health = Math.max(0, self.health - damage);
LK.effects.flashObject(self, 0xFF0000, 300);
if (self.health <= 0) {
// Dragon is defeated but doesn't die
LK.effects.flashObject(self, 0x000000, 1000);
self.baseSpeed = 0.5; // Reduced speed but still moves
self.currentSpeed = 0.5;
self.fireInterval = 999999; // Stop firing
}
};
return self;
});
var Fireball = Container.expand(function () {
var self = Container.call(this);
var fireballGraphics = self.attachAsset('fireball', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.directionX = 0;
self.directionY = 0;
self.lifetime = 300; // 5 seconds
self.update = function () {
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
fireballGraphics.rotation += 0.2;
fireballGraphics.alpha = Math.sin(LK.ticks * 0.5) * 0.3 + 0.7;
self.lifetime--;
if (self.lifetime <= 0) {
self.shouldDestroy = true;
}
// Check bounds
if (self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) {
self.shouldDestroy = true;
}
};
return self;
});
var Gem = Container.expand(function () {
var self = Container.call(this);
var gemGraphics = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5
});
self.points = 25;
self.floatOffset = Math.random() * Math.PI * 2;
self.update = function () {
gemGraphics.y = Math.sin(LK.ticks * 0.15 + self.floatOffset) * 3;
gemGraphics.rotation += 0.05;
gemGraphics.scaleX = Math.sin(LK.ticks * 0.1 + self.floatOffset) * 0.2 + 1;
gemGraphics.scaleY = Math.sin(LK.ticks * 0.1 + self.floatOffset) * 0.2 + 1;
};
return self;
});
var Luigi = Container.expand(function () {
var self = Container.call(this);
var luigiGraphics = self.attachAsset('luigi', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.jumpTimer = 0;
self.jumpInterval = 120; // 2 seconds
self.isJumping = false;
self.jumpHeight = 0;
self.maxJumpHeight = 100;
self.jumpSpeed = 8;
self.direction = 1; // 1 for right, -1 for left
self.update = function () {
// Move horizontally
self.x += self.speed * self.direction;
// Bounce off screen edges
if (self.x <= 100 || self.x >= 1948) {
self.direction *= -1;
luigiGraphics.scaleX = self.direction;
}
// Jump behavior
self.jumpTimer++;
if (self.jumpTimer >= self.jumpInterval && !self.isJumping) {
self.isJumping = true;
self.jumpHeight = 0;
self.jumpTimer = 0;
}
if (self.isJumping) {
self.jumpHeight += self.jumpSpeed;
if (self.jumpHeight >= self.maxJumpHeight) {
self.jumpSpeed = -8;
}
if (self.jumpHeight <= 0 && self.jumpSpeed < 0) {
self.jumpHeight = 0;
self.jumpSpeed = 8;
self.isJumping = false;
}
luigiGraphics.y = -self.jumpHeight;
}
// Check if player is close and doesn't have weapon
if (!playerWeapon) {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 100) {
// Give weapon to player
playerWeapon = new Weapon();
playerWeapon.x = player.x;
playerWeapon.y = player.y - 50;
game.addChild(playerWeapon);
LK.effects.flashObject(self, 0x00FF00, 500);
updateScore(100); // Bonus for getting weapon
}
}
// Animate Luigi
luigiGraphics.rotation = Math.sin(LK.ticks * 0.1) * 0.1;
};
return self;
});
var Mario = Container.expand(function () {
var self = Container.call(this);
var marioGraphics = self.attachAsset('mario', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.targetSpaghetti = null;
self.searchTimer = 0;
self.searchInterval = 60; // 1 second
self.isAngry = false;
self.angerTimer = 0;
self.angerDuration = 300; // 5 seconds of anger
self.attackSpeed = 6;
self.health = 100;
self.maxHealth = 100;
// Create health bar
var healthBarBg = self.attachAsset('health_bar_bg', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.y = -120;
var healthBarFill = self.attachAsset('health_bar_fill', {
anchorX: 0,
anchorY: 0.5
});
healthBarFill.x = -40;
healthBarFill.y = -120;
self.update = function () {
// Search for nearest spaghetti
self.searchTimer++;
if (self.searchTimer >= self.searchInterval) {
self.findNearestSpaghetti();
self.searchTimer = 0;
}
// Handle anger state
if (self.isAngry) {
self.angerTimer--;
if (self.angerTimer <= 0) {
self.isAngry = false;
marioGraphics.tint = 0xFFFFFF; // Return to normal color
} else {
// Attack player when angry
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.attackSpeed;
self.y += dy / distance * self.attackSpeed;
// Face the direction of movement
marioGraphics.scaleX = dx > 0 ? 1 : -1;
}
}
} else {
// Move towards target spaghetti
if (self.targetSpaghetti && spaghettis.indexOf(self.targetSpaghetti) !== -1) {
var dx = self.targetSpaghetti.x - self.x;
var dy = self.targetSpaghetti.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
// Face the direction of movement
marioGraphics.scaleX = dx > 0 ? 1 : -1;
}
} else {
// Random movement when no spaghetti found
self.x += (Math.random() - 0.5) * 2;
self.y += (Math.random() - 0.5) * 2;
}
}
// Keep Mario in bounds
self.x = Math.max(100, Math.min(1948, self.x));
self.y = Math.max(100, Math.min(2632, self.y));
// Update health bar
var healthPercent = self.health / self.maxHealth;
healthBarFill.width = 80 * healthPercent;
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00FF00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xFFFF00; // Yellow
} else {
healthBarFill.tint = 0xFF0000; // Red
}
// Animate Mario
marioGraphics.rotation = Math.sin(LK.ticks * 0.1) * 0.05;
};
self.findNearestSpaghetti = function () {
var nearestDistance = Infinity;
var nearestSpaghetti = null;
for (var i = 0; i < spaghettis.length; i++) {
var spaghetti = spaghettis[i];
var dx = spaghetti.x - self.x;
var dy = spaghetti.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestSpaghetti = spaghetti;
}
}
self.targetSpaghetti = nearestSpaghetti;
};
self.becomeAngry = function () {
self.isAngry = true;
self.angerTimer = self.angerDuration;
marioGraphics.tint = 0xFF0000; // Turn red when angry
LK.effects.flashObject(self, 0xFF0000, 500);
};
self.takeDamage = function (damage) {
self.health = Math.max(0, self.health - damage);
LK.effects.flashObject(self, 0xFF0000, 300);
if (self.health <= 0) {
// Mario is defeated and disappears
LK.effects.flashObject(self, 0x000000, 1000);
self.shouldDestroy = true; // Mark Mario for destruction
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.invulnerable = false;
self.invulnerabilityTime = 0;
self.speedBoost = false;
self.speedBoostTime = 0;
self.update = function () {
if (self.invulnerabilityTime > 0) {
self.invulnerabilityTime--;
playerGraphics.alpha = Math.sin(LK.ticks * 0.3) * 0.5 + 0.5;
if (self.invulnerabilityTime <= 0) {
self.invulnerable = false;
playerGraphics.alpha = 1;
}
}
if (self.speedBoostTime > 0) {
self.speedBoostTime--;
if (self.speedBoostTime <= 0) {
self.speedBoost = false;
playerGraphics.tint = 0xFFFFFF;
}
}
};
self.activateInvulnerability = function () {
self.invulnerable = true;
self.invulnerabilityTime = 120; // 2 seconds at 60fps
};
self.activateSpeedBoost = function () {
self.speedBoost = true;
self.speedBoostTime = 300; // 5 seconds at 60fps
playerGraphics.tint = 0x00FFFF;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = Math.random() < 0.5 ? 'speed' : 'invulnerable';
self.floatOffset = Math.random() * Math.PI * 2;
if (self.type === 'invulnerable') {
powerupGraphics.tint = 0xFFD700;
}
self.update = function () {
powerupGraphics.y = Math.sin(LK.ticks * 0.2 + self.floatOffset) * 8;
powerupGraphics.rotation += 0.1;
powerupGraphics.alpha = Math.sin(LK.ticks * 0.3) * 0.3 + 0.7;
};
return self;
});
var Sonic = Container.expand(function () {
var self = Container.call(this);
var sonicGraphics = self.attachAsset('sonic', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.targetMario = null;
self.searchTimer = 0;
self.searchInterval = 30; // 0.5 seconds
self.attackTimer = 0;
self.attackInterval = 120; // 2 seconds
self.spindashTimer = 0;
self.isSpinning = false;
self.direction = 1;
self.goldTimer = 30 * 60; // 30 seconds at 60fps
self.goldCollected = 0;
self.goldTarget = 3;
self.isAttackingPlayer = false;
self.targetPlayer = null;
self.health = 80;
self.maxHealth = 80;
// Create health bar
var healthBarBg = self.attachAsset('health_bar_bg', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.y = -120;
var healthBarFill = self.attachAsset('health_bar_fill', {
anchorX: 0,
anchorY: 0.5
});
healthBarFill.x = -40;
healthBarFill.y = -120;
self.update = function () {
// Update gold collection timer
self.goldTimer--;
if (self.goldTimer <= 0 && self.goldCollected < self.goldTarget) {
self.isAttackingPlayer = true;
self.targetPlayer = player;
sonicGraphics.tint = 0xFF0000; // Turn red when attacking player
}
// Behavior based on current state
if (self.isAttackingPlayer && self.targetPlayer) {
// Attack player mode
var dx = self.targetPlayer.x - self.x;
var dy = self.targetPlayer.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * (self.speed * 1.5); // Faster when attacking player
self.y += dy / distance * (self.speed * 1.5);
sonicGraphics.scaleX = dx > 0 ? 1 : -1;
self.direction = dx > 0 ? 1 : -1;
}
} else if (self.goldCollected < self.goldTarget) {
// Gold collection mode - search for gems (gold)
self.searchTimer++;
if (self.searchTimer >= self.searchInterval) {
self.findNearestGem();
self.searchTimer = 0;
}
// Move towards nearest gem
if (self.targetGem && gems.indexOf(self.targetGem) !== -1) {
var dx = self.targetGem.x - self.x;
var dy = self.targetGem.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
sonicGraphics.scaleX = dx > 0 ? 1 : -1;
self.direction = dx > 0 ? 1 : -1;
}
} else {
// Search pattern movement
self.x += Math.sin(LK.ticks * 0.02) * 3;
self.y += Math.cos(LK.ticks * 0.015) * 2;
}
} else {
// Normal mode (after collecting enough gold) - but only attack Mario if dragon is alive
if (!dragon.isDead) {
self.searchTimer++;
if (self.searchTimer >= self.searchInterval) {
self.findMario();
self.searchTimer = 0;
}
// Move towards Mario for combat
if (self.targetMario && marios.indexOf(self.targetMario) !== -1) {
var dx = self.targetMario.x - self.x;
var dy = self.targetMario.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 80) {
// Move towards Mario
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
sonicGraphics.scaleX = dx > 0 ? 1 : -1;
self.direction = dx > 0 ? 1 : -1;
} else {
// Close enough to attack - start spindash
self.attackTimer++;
if (self.attackTimer >= self.attackInterval && !self.isSpinning) {
self.startSpindash();
self.attackTimer = 0;
}
}
} else {
// Search pattern movement
self.x += Math.sin(LK.ticks * 0.02) * 3;
self.y += Math.cos(LK.ticks * 0.015) * 2;
}
} else {
// Dragon is dead - peaceful mode, just wander around
self.x += Math.sin(LK.ticks * 0.01) * 2;
self.y += Math.cos(LK.ticks * 0.008) * 1.5;
}
}
// Handle spindash attack
if (self.isSpinning) {
self.spindashTimer++;
sonicGraphics.rotation += 0.5;
sonicGraphics.scaleX = Math.sin(LK.ticks * 0.3) * 0.2 + 0.8;
sonicGraphics.scaleY = Math.sin(LK.ticks * 0.3) * 0.2 + 0.8;
if (self.spindashTimer >= 60) {
self.isSpinning = false;
self.spindashTimer = 0;
sonicGraphics.rotation = 0;
sonicGraphics.scaleX = self.direction;
sonicGraphics.scaleY = 1;
}
}
// Keep Sonic in bounds
self.x = Math.max(100, Math.min(1948, self.x));
self.y = Math.max(100, Math.min(2632, self.y));
// Update health bar
var healthPercent = self.health / self.maxHealth;
healthBarFill.width = 80 * healthPercent;
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00FF00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xFFFF00; // Yellow
} else {
healthBarFill.tint = 0xFF0000; // Red
}
// Idle animation when not spinning
if (!self.isSpinning) {
sonicGraphics.y = Math.sin(LK.ticks * 0.15) * 2;
}
};
self.findMario = function () {
var nearestDistance = Infinity;
var nearestMario = null;
for (var i = 0; i < marios.length; i++) {
var mario = marios[i];
var dx = mario.x - self.x;
var dy = mario.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestMario = mario;
}
}
self.targetMario = nearestMario;
};
self.findNearestGem = function () {
var nearestDistance = Infinity;
var nearestGem = null;
// First check for sonic gold (priority)
for (var i = 0; i < sonicGolds.length; i++) {
var sonicGold = sonicGolds[i];
var dx = sonicGold.x - self.x;
var dy = sonicGold.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestGem = sonicGold;
}
}
// Then check regular gems if no sonic gold found
if (!nearestGem) {
for (var i = 0; i < gems.length; i++) {
var gem = gems[i];
var dx = gem.x - self.x;
var dy = gem.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestGem = gem;
}
}
}
self.targetGem = nearestGem;
};
self.startSpindash = function () {
self.isSpinning = true;
self.spindashTimer = 0;
// Flash blue to indicate attack
LK.effects.flashObject(self, 0x0066FF, 200);
};
self.takeDamage = function (damage) {
self.health = Math.max(0, self.health - damage);
LK.effects.flashObject(self, 0xFF0000, 300);
if (self.health <= 0) {
// Sonic is defeated and disappears
LK.effects.flashObject(self, 0x000000, 1000);
self.shouldDestroy = true; // Mark Sonic for destruction
}
};
return self;
});
var SonicGold = Container.expand(function () {
var self = Container.call(this);
var sonicGoldGraphics = self.attachAsset('sonic_gold', {
anchorX: 0.5,
anchorY: 0.5
});
self.points = 30;
self.floatOffset = Math.random() * Math.PI * 2;
// Give it a special blue tint to distinguish from regular gems
sonicGoldGraphics.tint = 0x0066FF;
self.update = function () {
sonicGoldGraphics.y = Math.sin(LK.ticks * 0.18 + self.floatOffset) * 4;
sonicGoldGraphics.rotation += 0.08;
sonicGoldGraphics.scaleX = Math.sin(LK.ticks * 0.12 + self.floatOffset) * 0.25 + 1;
sonicGoldGraphics.scaleY = Math.sin(LK.ticks * 0.12 + self.floatOffset) * 0.25 + 1;
// Special pulsing effect
sonicGoldGraphics.alpha = Math.sin(LK.ticks * 0.2) * 0.3 + 0.7;
};
return self;
});
var Spaghetti = Container.expand(function () {
var self = Container.call(this);
var spaghettiGraphics = self.attachAsset('spaghetti', {
anchorX: 0.5,
anchorY: 0.5
});
self.points = 15;
self.floatOffset = Math.random() * Math.PI * 2;
self.update = function () {
spaghettiGraphics.y = Math.sin(LK.ticks * 0.12 + self.floatOffset) * 4;
spaghettiGraphics.rotation += 0.03;
spaghettiGraphics.scaleX = Math.sin(LK.ticks * 0.08 + self.floatOffset) * 0.1 + 1;
spaghettiGraphics.scaleY = Math.sin(LK.ticks * 0.08 + self.floatOffset) * 0.1 + 1;
};
return self;
});
var Treasure = Container.expand(function () {
var self = Container.call(this);
var treasureGraphics = self.attachAsset('treasure', {
anchorX: 0.5,
anchorY: 0.5
});
self.points = 10;
self.floatOffset = Math.random() * Math.PI * 2;
self.update = function () {
treasureGraphics.y = Math.sin(LK.ticks * 0.1 + self.floatOffset) * 5;
treasureGraphics.rotation += 0.02;
};
return self;
});
var Weapon = Container.expand(function () {
var self = Container.call(this);
var weaponGraphics = self.attachAsset('weapon', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 25;
self.cooldown = 0;
self.maxCooldown = 30; // 0.5 seconds
self.range = 150;
self.isActive = false;
self.update = function () {
if (self.cooldown > 0) {
self.cooldown--;
}
// Rotate weapon around player
weaponGraphics.rotation += 0.2;
// Pulse effect when ready to use
if (self.cooldown <= 0) {
weaponGraphics.alpha = Math.sin(LK.ticks * 0.3) * 0.3 + 0.7;
weaponGraphics.scaleX = Math.sin(LK.ticks * 0.2) * 0.2 + 1;
weaponGraphics.scaleY = Math.sin(LK.ticks * 0.2) * 0.2 + 1;
} else {
weaponGraphics.alpha = 0.5;
weaponGraphics.scaleX = 0.8;
weaponGraphics.scaleY = 0.8;
}
};
self.attack = function (target) {
if (self.cooldown <= 0) {
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
target.takeDamage(self.damage);
self.cooldown = self.maxCooldown;
LK.effects.flashObject(self, 0xFFFFFF, 300);
LK.getSound('weapon_hit').play();
return true;
}
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x8B4513
});
/****
* Game Code
****/
game.setBackgroundColor(0xDEB887);
// Game variables
var score = 0;
var health = 250;
var maxHealth = 250;
var gameTimer = 80 * 60; // 1 minute 20 seconds (80 seconds) at 60fps
var treasures = [];
var gems = [];
var powerups = [];
var fireballs = [];
var luigis = [];
var marios = [];
var spaghettis = [];
var sonics = [];
var sonicGolds = [];
var treasureSpawnTimer = 0;
var gemSpawnTimer = 0;
var powerupSpawnTimer = 0;
var luigiSpawnTimer = 0;
var spaghettiSpawnTimer = 0;
var sonicGoldSpawnTimer = 0;
var sonicGoldSpawnCount = 0;
var maxSonicGoldSpawns = 3;
var playerWeapon = null;
// Achievement system
var achievements = [];
var activeAchievements = [];
var achievementStats = {
treasuresCollected: 0,
gemsCollected: 0,
powerupsCollected: 0,
dragonHits: 0,
fireballsAvoided: 0,
survivalTime: 0,
maxScore: 0
};
// Initialize achievements
function initializeAchievements() {
achievements = [new Achievement('first_treasure', 'First Treasure!', 'Collect your first treasure', '💰'), new Achievement('treasure_hunter', 'Treasure Hunter', 'Collect 10 treasures', '🏆'), new Achievement('gem_collector', 'Gem Collector', 'Collect 5 gems', '💎'), new Achievement('survivor', 'Survivor', 'Survive for 30 seconds', '⏰'), new Achievement('speed_demon', 'Speed Demon', 'Use 3 speed power-ups', '⚡'), new Achievement('invincible', 'Invincible', 'Use 3 invulnerability power-ups', '🛡️'), new Achievement('score_master', 'Score Master', 'Reach 200 points', '🎯'), new Achievement('dragon_dancer', 'Dragon Dancer', 'Get hit by dragon 5 times and survive', '🐉'), new Achievement('high_scorer', 'High Scorer', 'Reach 300 points', '🌟'), new Achievement('ultimate_survivor', 'Ultimate Survivor', 'Survive for 60 seconds', '👑')];
// Load unlocked achievements from storage
for (var i = 0; i < achievements.length; i++) {
var achievement = achievements[i];
if (storage['achievement_' + achievement.id]) {
achievement.unlocked = true;
}
}
}
function checkAchievements() {
for (var i = 0; i < achievements.length; i++) {
var achievement = achievements[i];
if (!achievement.unlocked) {
var shouldUnlock = false;
switch (achievement.id) {
case 'first_treasure':
shouldUnlock = achievementStats.treasuresCollected >= 1;
break;
case 'treasure_hunter':
shouldUnlock = achievementStats.treasuresCollected >= 10;
break;
case 'gem_collector':
shouldUnlock = achievementStats.gemsCollected >= 5;
break;
case 'survivor':
shouldUnlock = achievementStats.survivalTime >= 30 * 60;
break;
case 'speed_demon':
shouldUnlock = achievementStats.powerupsCollected >= 3;
break;
case 'invincible':
shouldUnlock = achievementStats.powerupsCollected >= 3;
break;
case 'score_master':
shouldUnlock = score >= 200;
break;
case 'dragon_dancer':
shouldUnlock = achievementStats.dragonHits >= 5;
break;
case 'high_scorer':
shouldUnlock = score >= 300;
break;
case 'ultimate_survivor':
shouldUnlock = achievementStats.survivalTime >= 60 * 60;
break;
}
if (shouldUnlock) {
achievement.unlock();
activeAchievements.push(achievement);
game.addChild(achievement);
}
}
}
}
// Initialize achievements
initializeAchievements();
// Create player
var player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
// Create dragon
var dragon = game.addChild(new Dragon());
dragon.x = 200;
dragon.y = 200;
// Create Luigi monster
var luigi = game.addChild(new Luigi());
luigi.x = 1500;
luigi.y = 1000;
luigis.push(luigi);
// Create Mario character
var mario = game.addChild(new Mario());
mario.x = 300;
mario.y = 800;
marios.push(mario);
// Create Sonic character
var sonic = game.addChild(new Sonic());
sonic.x = 1700;
sonic.y = 600;
sonics.push(sonic);
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var healthTxt = new Text2('Health: 250/250', {
size: 60,
fill: 0x00FF00
});
healthTxt.anchor.set(0, 0);
healthTxt.x = 120;
healthTxt.y = 20;
LK.gui.addChild(healthTxt);
var timerTxt = new Text2('Time: 1:20', {
size: 70,
fill: 0xFFFFFF
});
timerTxt.anchor.set(1, 0);
timerTxt.x = 2048 - 20;
timerTxt.y = 20;
LK.gui.addChild(timerTxt);
var instructionTxt = new Text2('Tap to move! Get close to Luigi for weapon to defeat dragon!', {
size: 50,
fill: 0xFFFFFF
});
instructionTxt.anchor.set(0.5, 1);
LK.gui.bottom.addChild(instructionTxt);
// Game logic functions
function spawnTreasure() {
var treasure = new Treasure();
treasure.x = Math.random() * 1800 + 124;
treasure.y = Math.random() * 2400 + 166;
treasures.push(treasure);
game.addChild(treasure);
}
function spawnGem() {
var gem = new Gem();
gem.x = Math.random() * 1800 + 124;
gem.y = Math.random() * 2400 + 166;
gems.push(gem);
game.addChild(gem);
}
function spawnPowerUp() {
var powerup = new PowerUp();
powerup.x = Math.random() * 1800 + 124;
powerup.y = Math.random() * 2400 + 166;
powerups.push(powerup);
game.addChild(powerup);
}
function spawnSpaghetti() {
var spaghetti = new Spaghetti();
spaghetti.x = Math.random() * 1800 + 124;
spaghetti.y = Math.random() * 2400 + 166;
spaghettis.push(spaghetti);
game.addChild(spaghetti);
}
function spawnSonicGold() {
if (sonicGoldSpawnCount < maxSonicGoldSpawns) {
var sonicGold = new SonicGold();
sonicGold.x = Math.random() * 1800 + 124;
sonicGold.y = Math.random() * 2400 + 166;
sonicGolds.push(sonicGold);
game.addChild(sonicGold);
}
}
function updateScore(points) {
score += points;
scoreTxt.setText('Score: ' + score);
LK.setScore(score);
}
function updateHealth(damage) {
health = Math.max(0, health - damage);
healthTxt.setText('Health: ' + health + '/' + maxHealth);
// Change color based on health percentage
var healthPercent = health / maxHealth;
if (healthPercent > 0.6) {
healthTxt.fill = 0x00FF00; // Green
} else if (healthPercent > 0.3) {
healthTxt.fill = 0xFFFF00; // Yellow
} else {
healthTxt.fill = 0xFF0000; // Red
}
if (health <= 0) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
}
}
function updateTimer() {
gameTimer = Math.max(0, gameTimer - 1);
var totalSeconds = Math.floor(gameTimer / 60);
var minutes = Math.floor(totalSeconds / 60);
var seconds = totalSeconds % 60;
var timeText = minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
timerTxt.setText('Time: ' + timeText);
// Change color based on remaining time
if (gameTimer <= 10 * 60) {
// Last 10 seconds
timerTxt.fill = 0xFF0000; // Red
} else if (gameTimer <= 30 * 60) {
// Last 30 seconds
timerTxt.fill = 0xFFFF00; // Yellow
} else {
timerTxt.fill = 0xFFFFFF; // White
}
if (gameTimer <= 0) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
}
}
// Touch controls
var targetX = player.x;
var targetY = player.y;
game.down = function (x, y, obj) {
targetX = x;
targetY = y;
// Attack dragon with weapon if player has one
if (playerWeapon) {
playerWeapon.attack(dragon);
// Also attack any Mario in range
for (var i = 0; i < marios.length; i++) {
var mario = marios[i];
if (mario.health > 0) {
playerWeapon.attack(mario);
}
}
// Also attack any Sonic in range
for (var i = 0; i < sonics.length; i++) {
var sonic = sonics[i];
playerWeapon.attack(sonic);
}
}
};
game.move = function (x, y, obj) {
targetX = x;
targetY = y;
};
// Game update loop
game.update = function () {
// Update timer
updateTimer();
// Move player towards target
var dx = targetX - player.x;
var dy = targetY - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
var speed = player.speedBoost ? player.speed * 1.5 : player.speed;
player.x += dx / distance * speed;
player.y += dy / distance * speed;
}
// Keep player in bounds
player.x = Math.max(40, Math.min(2008, player.x));
player.y = Math.max(40, Math.min(2692, player.y));
// Update weapon position if player has one
if (playerWeapon) {
playerWeapon.x = player.x;
playerWeapon.y = player.y - 50;
// Auto-attack dragon when in range
var dx = dragon.x - playerWeapon.x;
var dy = dragon.y - playerWeapon.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= playerWeapon.range) {
playerWeapon.attack(dragon);
}
// Auto-attack Mario when in range
for (var i = 0; i < marios.length; i++) {
var mario = marios[i];
if (mario.health > 0) {
var dx = mario.x - playerWeapon.x;
var dy = mario.y - playerWeapon.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= playerWeapon.range) {
playerWeapon.attack(mario);
}
}
}
// Auto-attack Sonic when in range
for (var i = 0; i < sonics.length; i++) {
var sonic = sonics[i];
var dx = sonic.x - playerWeapon.x;
var dy = sonic.y - playerWeapon.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= playerWeapon.range) {
playerWeapon.attack(sonic);
}
}
}
// Spawn treasures
treasureSpawnTimer++;
if (treasureSpawnTimer >= 90) {
// Every 1.5 seconds
spawnTreasure();
treasureSpawnTimer = 0;
}
// Spawn gems
gemSpawnTimer++;
if (gemSpawnTimer >= 180) {
// Every 3 seconds
spawnGem();
gemSpawnTimer = 0;
}
// Spawn power-ups
powerupSpawnTimer++;
if (powerupSpawnTimer >= 600) {
// Every 10 seconds
spawnPowerUp();
powerupSpawnTimer = 0;
}
// Spawn spaghetti
spaghettiSpawnTimer++;
if (spaghettiSpawnTimer >= 120) {
// Every 2 seconds
spawnSpaghetti();
spaghettiSpawnTimer = 0;
}
// Spawn sonic gold
sonicGoldSpawnTimer++;
if (sonicGoldSpawnTimer >= 240 && sonicGoldSpawnCount < maxSonicGoldSpawns) {
// Every 4 seconds, but only up to maximum allowed
spawnSonicGold();
sonicGoldSpawnTimer = 0;
sonicGoldSpawnCount++;
}
// Check treasure collection
for (var i = treasures.length - 1; i >= 0; i--) {
var treasure = treasures[i];
if (player.intersects(treasure)) {
updateScore(treasure.points);
achievementStats.treasuresCollected++;
LK.effects.flashObject(treasure, 0xFFFFFF, 300);
treasure.destroy();
treasures.splice(i, 1);
LK.getSound('collect').play();
}
}
// Check gem collection
for (var i = gems.length - 1; i >= 0; i--) {
var gem = gems[i];
if (player.intersects(gem)) {
updateScore(gem.points);
achievementStats.gemsCollected++;
LK.effects.flashObject(gem, 0xFFFFFF, 300);
gem.destroy();
gems.splice(i, 1);
LK.getSound('collect').play();
}
}
// Check power-up collection
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (player.intersects(powerup)) {
if (powerup.type === 'speed') {
player.activateSpeedBoost();
} else if (powerup.type === 'invulnerable') {
player.activateInvulnerability();
}
achievementStats.powerupsCollected++;
LK.effects.flashObject(powerup, 0xFFFFFF, 300);
powerup.destroy();
powerups.splice(i, 1);
LK.getSound('powerup').play();
}
}
// Check Mario spaghetti collection
for (var i = marios.length - 1; i >= 0; i--) {
var mario = marios[i];
for (var j = spaghettis.length - 1; j >= 0; j--) {
var spaghetti = spaghettis[j];
if (mario.intersects(spaghetti)) {
updateScore(spaghetti.points);
LK.effects.flashObject(spaghetti, 0xFFD700, 300);
spaghetti.destroy();
spaghettis.splice(j, 1);
LK.getSound('collect').play();
break;
}
}
}
// Check player spaghetti collection
for (var i = spaghettis.length - 1; i >= 0; i--) {
var spaghetti = spaghettis[i];
if (player.intersects(spaghetti)) {
updateScore(spaghetti.points);
LK.effects.flashObject(spaghetti, 0xFFD700, 300);
// Make all Marios angry when player steals spaghetti
for (var j = 0; j < marios.length; j++) {
var mario = marios[j];
if (!mario.isAngry) {
mario.becomeAngry();
}
}
spaghetti.destroy();
spaghettis.splice(i, 1);
LK.getSound('collect').play();
}
}
// Check if dragon is defeated and should disappear
if (dragon.health <= 0 && !dragon.isDead) {
dragon.isDead = true;
// Make all Marios angry when dragon is defeated
for (var j = 0; j < marios.length; j++) {
var mario = marios[j];
if (!mario.isAngry) {
mario.becomeAngry();
}
}
// Sonics remain in the game when dragon is defeated - they will no longer attack Mario
for (var k = 0; k < sonics.length; k++) {
var sonic = sonics[k];
sonic.isAttackingPlayer = false; // Stop attacking player
sonic.targetMario = null; // Clear Mario target
sonic.targetPlayer = null; // Clear player target
sonicGraphics = sonic.children[0]; // Get sonic graphics
if (sonicGraphics) {
sonicGraphics.tint = 0xFFFFFF; // Return to normal color
}
}
LK.effects.flashScreen(0x00FF00, 1000); // Green flash for dragon defeat
updateScore(200); // Bonus points for defeating dragon
// Dragon disappears from the game
dragon.destroy();
}
// Check if any Mario has died and make Sonics attack player
for (var i = marios.length - 1; i >= 0; i--) {
var mario = marios[i];
if (mario.shouldDestroy) {
// Mario is dead, make all Sonics attack player
for (var j = 0; j < sonics.length; j++) {
var sonic = sonics[j];
sonic.isAttackingPlayer = true;
sonic.targetPlayer = player;
var sonicGraphics = sonic.children[0];
if (sonicGraphics) {
sonicGraphics.tint = 0xFF0000; // Turn red when attacking player
}
}
// Remove Mario from game
mario.destroy();
marios.splice(i, 1);
}
}
// Check if any Sonic has died and remove them
for (var i = sonics.length - 1; i >= 0; i--) {
var sonic = sonics[i];
if (sonic.shouldDestroy) {
// Sonic died - game over
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
// Remove Sonic from game
sonic.destroy();
sonics.splice(i, 1);
}
}
// Game continues until timer runs out or player dies
// Check dragon collision
if (!player.invulnerable && player.intersects(dragon)) {
if (!player.lastDragonHit) {
updateHealth(50);
achievementStats.dragonHits++;
player.activateInvulnerability();
LK.effects.flashScreen(0xFF0000, 500);
player.lastDragonHit = true;
}
} else {
player.lastDragonHit = false;
}
// Check fireball collisions
for (var i = fireballs.length - 1; i >= 0; i--) {
var fireball = fireballs[i];
if (fireball.shouldDestroy) {
fireball.destroy();
fireballs.splice(i, 1);
continue;
}
if (!player.invulnerable && player.intersects(fireball)) {
if (!fireball.hasHit) {
updateHealth(25);
player.activateInvulnerability();
LK.effects.flashScreen(0xFF0000, 300);
fireball.hasHit = true;
fireball.shouldDestroy = true;
}
}
}
// Check Luigi collisions
for (var i = luigis.length - 1; i >= 0; i--) {
var luigi = luigis[i];
if (!player.invulnerable && player.intersects(luigi)) {
if (!luigi.lastHit) {
updateHealth(30);
player.activateInvulnerability();
LK.effects.flashScreen(0x00FF00, 400);
luigi.lastHit = true;
}
} else {
luigi.lastHit = false;
}
}
// Check angry Mario attacking player
for (var i = marios.length - 1; i >= 0; i--) {
var mario = marios[i];
if (mario.isAngry && !player.invulnerable && player.intersects(mario)) {
if (!mario.lastPlayerHit) {
updateHealth(40);
player.activateInvulnerability();
LK.effects.flashScreen(0xFF0000, 400);
mario.lastPlayerHit = true;
}
} else {
mario.lastPlayerHit = false;
}
}
// Check sonic gold collection (special gold for Sonic)
for (var i = sonicGolds.length - 1; i >= 0; i--) {
var sonicGold = sonicGolds[i];
if (player.intersects(sonicGold)) {
// Check if any Sonic needs gold
var goldGivenToSonic = false;
for (var j = 0; j < sonics.length; j++) {
var sonic = sonics[j];
if (sonic.goldCollected < sonic.goldTarget) {
sonic.goldCollected++;
goldGivenToSonic = true;
LK.effects.flashObject(sonic, 0x0066FF, 500); // Flash Sonic to show he received gold
break;
}
}
if (goldGivenToSonic) {
updateScore(sonicGold.points);
achievementStats.gemsCollected++;
LK.effects.flashObject(sonicGold, 0x0066FF, 300); // Blue flash for Sonic gold
sonicGold.destroy();
sonicGolds.splice(i, 1);
LK.getSound('collect').play();
} else {
// Normal collection if no Sonic needs gold
updateScore(sonicGold.points);
achievementStats.gemsCollected++;
LK.effects.flashObject(sonicGold, 0xFFD700, 300);
sonicGold.destroy();
sonicGolds.splice(i, 1);
LK.getSound('collect').play();
}
}
}
// Check if player collects gems for Sonic
for (var i = gems.length - 1; i >= 0; i--) {
var gem = gems[i];
if (player.intersects(gem)) {
// Check if any Sonic needs gold
var goldGivenToSonic = false;
for (var j = 0; j < sonics.length; j++) {
var sonic = sonics[j];
if (sonic.goldCollected < sonic.goldTarget) {
sonic.goldCollected++;
goldGivenToSonic = true;
LK.effects.flashObject(sonic, 0x0066FF, 300); // Flash Sonic to show he received gold
break;
}
}
if (goldGivenToSonic) {
updateScore(gem.points);
achievementStats.gemsCollected++;
LK.effects.flashObject(gem, 0xFFD700, 300); // Gold flash for Sonic collection
gem.destroy();
gems.splice(i, 1);
LK.getSound('collect').play();
} else {
// Normal gem collection if no Sonic needs gold
updateScore(gem.points);
achievementStats.gemsCollected++;
LK.effects.flashObject(gem, 0xFFFFFF, 300);
gem.destroy();
gems.splice(i, 1);
LK.getSound('collect').play();
}
}
}
// Check Sonic attacking player
for (var i = sonics.length - 1; i >= 0; i--) {
var sonic = sonics[i];
if (sonic.isAttackingPlayer && !player.invulnerable && player.intersects(sonic)) {
if (!sonic.lastPlayerHit) {
updateHealth(35);
player.activateInvulnerability();
LK.effects.flashScreen(0x0066FF, 400);
sonic.lastPlayerHit = true;
}
} else {
sonic.lastPlayerHit = false;
}
}
// Check Sonic vs Mario combat
for (var i = sonics.length - 1; i >= 0; i--) {
var sonic = sonics[i];
for (var j = marios.length - 1; j >= 0; j--) {
var mario = marios[j];
if (sonic.intersects(mario)) {
if (!sonic.lastMarioHit && sonic.isSpinning) {
// Sonic hits Mario during spindash
mario.takeDamage(20);
LK.effects.flashObject(mario, 0xFF0000, 500);
LK.effects.flashObject(sonic, 0x0066FF, 300);
updateScore(50); // Bonus points for combat
sonic.lastMarioHit = true;
} else if (!mario.lastSonicHit && !sonic.isSpinning) {
// Mario hits Sonic when not spinning
LK.effects.flashObject(sonic, 0xFF0000, 500);
LK.effects.flashObject(mario, 0x00FF00, 300);
updateScore(30); // Bonus points for combat
mario.lastSonicHit = true;
}
} else {
sonic.lastMarioHit = false;
mario.lastSonicHit = false;
}
}
}
// Spawn additional Luigis based on score
luigiSpawnTimer++;
if (luigiSpawnTimer >= 1800 && score >= 100) {
// Every 30 seconds after score 100
var newLuigi = new Luigi();
newLuigi.x = Math.random() * 1800 + 124;
newLuigi.y = Math.random() * 2000 + 500;
luigis.push(newLuigi);
game.addChild(newLuigi);
luigiSpawnTimer = 0;
}
// Update achievement stats
achievementStats.survivalTime++;
if (score > achievementStats.maxScore) {
achievementStats.maxScore = score;
}
// Check for new achievements
checkAchievements();
// Update active achievement displays
for (var i = activeAchievements.length - 1; i >= 0; i--) {
var achievement = activeAchievements[i];
if (achievement.displayTime <= 0 && achievement.alpha <= 0) {
achievement.destroy();
activeAchievements.splice(i, 1);
}
}
// Win condition
if (score >= 500) {
LK.showYouWin();
}
};
// Start background music
LK.playMusic('desert');
// Initial treasures
for (var i = 0; i < 3; i++) {
spawnTreasure();
}
// Initial spaghetti
for (var i = 0; i < 2; i++) {
spawnSpaghetti();
}
// Initial sonic gold - removed to respect 3 total limit
;
CREATE THIS IMAGE. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
MAKE THIS PICTURE LIKE A FIREBALL. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
DESIGN THIS PICTURE AS AN ENERGY DRINK. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
LUİGİ KARAKTERİNİ OLUŞTUR. In-Game asset. 2d. High contrast. No shadows
KORKAK BİR ADAM. In-Game asset. 2d. High contrast. No shadows
BÜYÜK BİR EJDER. In-Game asset. 2d. High contrast. No shadows
MARİO. In-Game asset. 2d. High contrast. No shadows
SPAGHETTİ. In-Game asset. 2d. High contrast. No shadows
sonic. In-Game asset. 2d. High contrast. No shadows
silah. In-Game asset. 2d. High contrast. No shadows
sonic altını. In-Game asset. 2d. High contrast. No shadows