/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { level: 1, experience: 0, experienceToNext: 3, health: 50, maxHealth: 50, elementalStones: {}, score: 0, nonanoDefeatCount: 0, defenseCount: 0 }); /**** * Classes ****/ var AdultDragon = Container.expand(function (type, level) { var self = Container.call(this); // Map dragon types to their specific assets var assetMap = { 'Nilisty': 'nilisty', 'Mistina': 'mistina', 'Nokan': 'nokan', 'Oragana': 'oragana', 'Farocha': 'farocha', 'Nonano': 'nonano', 'Jarare': 'jarare', 'Eriza': 'eriza', 'Katoza': 'katoza', 'Ultete': 'ultete' }; var assetName = assetMap[type] || 'nilisty'; var dragonGraphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5 }); self.dragonType = type || 'Nilisty'; self.level = level || 1; self.nonanoDefeatCount = storage.nonanoDefeatCount || 0; // Calculate health based on dragon type and level self.calculateHealth = function () { var playerLevel = self.level; var baseHealthRanges = { 'Nilisty': { min: 25, max: 100, perLevel: 36 }, 'Mistina': { min: 30, max: 110, perLevel: 40 }, 'Nokan': { min: 30, max: 100, perLevel: 50 }, 'Oragana': { min: 40, max: 120, perLevel: 50 }, 'Farocha': { min: 50, max: 130, perLevel: 70 }, 'Nonano': { min: 80, max: 150, perLevel: 30 }, 'Jarare': { min: 90, max: 170, perLevel: 0 }, // Special case - 80% increase 'Eriza': { min: 20, max: 80, perLevel: 0 }, // Special case - can increase during combat 'Katoza': { min: 10, max: 50, perLevel: 0 }, // Fixed range 'Ultete': { min: 20, max: 60, perLevel: 20 } }; var range = baseHealthRanges[self.dragonType]; if (!range) range = baseHealthRanges['Nilisty']; var baseHealth = Math.floor(Math.random() * (range.max - range.min + 1)) + range.min; // Apply level scaling if (self.dragonType === 'Jarare') { // Jarare increases by 80% per level var levelBonus = Math.floor(baseHealth * 0.8 * (playerLevel - 1)); baseHealth += levelBonus; } else if (self.dragonType === 'Nonano') { // Nonano adapts based on previous defeats var adaptationBonus = self.nonanoDefeatCount * 30; baseHealth += adaptationBonus + range.perLevel * (playerLevel - 1); } else if (range.perLevel > 0) { baseHealth += range.perLevel * (playerLevel - 1); } return baseHealth; }; // Define elements for each dragon type self.getElements = function () { var elementMap = { 'Nilisty': ['Shadow', 'Fire'], 'Mistina': ['Light', 'Plant'], 'Nokan': ['Energy', 'Void'], 'Oragana': ['Wind', 'Earth'], 'Farocha': ['Water', 'Void'], 'Nonano': ['Water', 'Wind'], 'Jarare': ['Energy', 'Plant'], 'Eriza': ['Light', 'Fire'], 'Katoza': ['Shadow', 'Wind'], 'Ultete': ['Void', 'Plant'] }; return elementMap[self.dragonType] || ['Fire']; }; self.originalMaxHealth = self.calculateHealth(); self.maxHealth = self.originalMaxHealth; self.health = self.maxHealth; self.elements = self.getElements(); self.canHeal = ['Mistina', 'Oragana', 'Katoza', 'Ultete'].includes(self.dragonType); self.isHealing = false; self.healingTimer = 0; self.hasUsedSpecialAbility = false; self.canUseSword = ['Mistina', 'Ultete'].includes(self.dragonType); self.hasSword = false; // Determine if this dragon will use a sword (45% chance for Mistina and Ultete) if (self.canUseSword && Math.random() < 0.45) { self.hasSword = true; } // Store original colors for healing effects var originalColors = { 'Nilisty': 0x8b0000, 'Mistina': 0x00ff7f, 'Nokan': 0x4b0082, 'Oragana': 0x8b4513, 'Farocha': 0x191970, 'Nonano': 0x00bfff, 'Jarare': 0x32cd32, 'Eriza': 0xffd700, 'Katoza': 0x2f4f4f, 'Ultete': 0x556b2f }; self.startHealing = function () { if (self.canHeal && !self.isHealing) { self.isHealing = true; self.healingTimer = 5000; // 5 seconds dragonGraphics.tint = 0x00ff00; // Green tint when healing } }; self.interruptHealing = function () { if (self.isHealing) { self.isHealing = false; self.healingTimer = 0; dragonGraphics.tint = originalColors[self.dragonType] || 0x8b0000; return true; } return false; }; self.completeHealing = function () { if (self.isHealing) { var healAmount = 0; if (self.dragonType === 'Mistina') { healAmount = Math.floor(self.maxHealth * 0.25); } else if (self.dragonType === 'Oragana') { healAmount = Math.floor(self.originalMaxHealth * 0.4); } else if (self.dragonType === 'Katoza' && !self.hasUsedSpecialAbility) { // Katoza full heal and max health boost self.health = self.maxHealth; self.maxHealth = Math.min(150, Math.floor(Math.random() * (150 - self.maxHealth + 1)) + self.maxHealth); self.health = self.maxHealth; self.hasUsedSpecialAbility = true; self.isHealing = false; self.healingTimer = 0; dragonGraphics.tint = originalColors[self.dragonType] || 0x8b0000; return; } else if (self.dragonType === 'Ultete') { healAmount = Math.floor(self.maxHealth * 0.1); } self.health = Math.min(self.health + healAmount, self.maxHealth); self.isHealing = false; self.healingTimer = 0; dragonGraphics.tint = originalColors[self.dragonType] || 0x8b0000; } }; // Special abilities for specific dragon types self.trySpecialAbility = function () { if (self.dragonType === 'Eriza' && Math.random() < 0.3) { // Eriza can randomly increase health during combat var healthIncrease = Math.floor(Math.random() * 21) + 10; // 10-30 increase var newMaxHealth = Math.min(100, self.maxHealth + healthIncrease); self.maxHealth = newMaxHealth; self.health = Math.min(self.health + healthIncrease, self.maxHealth); return true; } else if (self.dragonType === 'Katoza' && self.health <= 10 && !self.hasUsedSpecialAbility) { // Katoza special transformation when health drops below 10 self.startHealing(); return true; } return false; }; self.useSwordAttack = function (targetPlayer) { if (self.hasSword && targetPlayer) { // Reduce baby dragon's max health by 30% var healthReduction = Math.floor(targetPlayer.maxHealth * 0.3); targetPlayer.maxHealth = Math.max(1, targetPlayer.maxHealth - healthReduction); // Also reduce current health if it exceeds new max health if (targetPlayer.health > targetPlayer.maxHealth) { targetPlayer.health = targetPlayer.maxHealth; } self.hasSword = false; // Sword can only be used once per combat return healthReduction; } return 0; }; self.update = function () { if (self.isHealing) { self.healingTimer -= 16.67; // ~60fps if (self.healingTimer <= 0) { self.completeHealing(); } } // Try special abilities randomly during combat if (Math.random() < 0.1) { // 10% chance per frame self.trySpecialAbility(); } }; return self; }); var BabyDragon = Container.expand(function () { var self = Container.call(this); var dragonGraphics = self.attachAsset('babyDragon', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 50; self.health = self.maxHealth; self.level = 1; self.experience = 0; self.experienceToNext = 3; self.targetY = 0; self.jumpSpeed = 0; self.isJumping = false; self.elementalStones = {}; self.defenseCount = 0; self.isDefending = false; self.takeDamage = function (damage) { if (self.isDefending) { // Defense blocks all damage self.isDefending = false; LK.effects.flashObject(self, 0x0000ff, 500); // Blue flash for successful defense return; } self.health = Math.max(0, self.health - damage); LK.effects.flashObject(self, 0xff0000, 500); }; self.useDefense = function () { if (self.defenseCount < self.level * 5) { self.isDefending = true; self.defenseCount++; return true; } return false; }; self.resetDefenseCount = function () { self.defenseCount = 0; }; self.gainExperience = function () { self.experience++; if (self.experience >= self.experienceToNext) { self.levelUp(); } }; self.levelUp = function () { self.level++; self.experience = 0; self.experienceToNext *= 2; // Health bonus and full regeneration var healthBonus = Math.floor(self.maxHealth * 0.1); self.maxHealth += healthBonus; self.health = self.maxHealth; // Reset defense count on level up self.resetDefenseCount(); LK.effects.flashObject(self, 0xffd700, 1000); // Save progress immediately on level up storage.level = self.level; storage.experience = self.experience; storage.experienceToNext = self.experienceToNext; storage.health = self.health; storage.maxHealth = self.maxHealth; storage.elementalStones = self.elementalStones; storage.defenseCount = self.defenseCount; storage.score = LK.getScore(); }; self.jumpTo = function (targetY) { if (!self.isJumping) { self.isJumping = true; self.targetY = targetY; self.jumpSpeed = -8; LK.getSound('jump').play(); } }; self.update = function () { if (self.isJumping) { self.jumpSpeed += 0.5; // gravity self.y += self.jumpSpeed; if (self.y >= self.targetY) { self.y = self.targetY; self.isJumping = false; self.jumpSpeed = 0; } } }; return self; }); var Combat = Container.expand(function (player, enemy) { var self = Container.call(this); self.player = player; self.enemy = enemy; self.isPlayerTurn = true; self.turnTimer = 0; self.ui = new CombatUI(); self.addChild(self.ui); self.playerAttack = function () { if (!self.isPlayerTurn) return; var damage = 15 + Math.floor(Math.random() * 10); self.enemy.health = Math.max(0, self.enemy.health - damage); self.ui.showAction('You deal ' + damage + ' damage!'); LK.getSound('attack').play(); if (self.enemy.health <= 0) { self.victory(); } else { self.isPlayerTurn = false; self.turnTimer = 1000; } }; self.playerDefend = function () { if (!self.isPlayerTurn) return; if (self.player.useDefense()) { self.ui.showAction('Defense ready! Next attack will be blocked!'); self.isPlayerTurn = false; self.turnTimer = 1000; } else { var maxDefenses = self.player.level * 5; self.ui.showAction('No defenses left! (' + self.player.defenseCount + '/' + maxDefenses + ')'); } }; self.enemyTurn = function () { // Check for healing conditions based on dragon type var shouldHeal = false; if (self.enemy.dragonType === 'Mistina' && self.enemy.health < 20) { shouldHeal = true; // Mistina heals when below 20 HP } else if (self.enemy.dragonType === 'Oragana' && self.enemy.health < self.enemy.maxHealth * 0.5) { shouldHeal = true; // Oragana heals when below 50% } else if (self.enemy.dragonType === 'Katoza' && self.enemy.health <= 10 && !self.enemy.hasUsedSpecialAbility) { shouldHeal = true; // Katoza special heal when below 10 HP } else if (self.enemy.dragonType === 'Ultete' && Math.random() < 0.4) { shouldHeal = true; // Ultete can heal anytime with 40% chance } if (shouldHeal && self.enemy.canHeal && !self.enemy.isHealing) { self.enemy.startHealing(); self.ui.showAction(self.enemy.dragonType + ' is healing! Tap to interrupt!'); } else if (self.enemy.hasSword && Math.random() < 0.5) { // 50% chance to use sword if available (in addition to the 45% chance to have one) var healthReduction = self.enemy.useSwordAttack(self.player); if (healthReduction > 0) { self.ui.showAction(self.enemy.dragonType + ' uses sword! -' + healthReduction + ' Max HP!'); LK.effects.flashObject(self.player, 0x800080, 1000); // Purple flash for sword attack } else { var damage = 10 + Math.floor(Math.random() * 8); self.player.takeDamage(damage); self.ui.showAction(self.enemy.dragonType + ' deals ' + damage + ' damage!'); } if (self.player.health <= 0) { self.defeat(); return; } } else { var damage = 10 + Math.floor(Math.random() * 8); self.player.takeDamage(damage); self.ui.showAction(self.enemy.dragonType + ' deals ' + damage + ' damage!'); if (self.player.health <= 0) { self.defeat(); return; } } self.isPlayerTurn = true; self.turnTimer = 0; }; self.victory = function () { // Ensure we only count this victory once if (self.victoryProcessed) return; self.victoryProcessed = true; self.player.gainExperience(); // Calculate health gain based on defeated dragon type var healthGain = 0; var enemyMaxHealth = self.enemy.maxHealth; if (self.enemy.dragonType === 'Nilisty') { healthGain = Math.floor(enemyMaxHealth * 0.2); // 20% } else if (self.enemy.dragonType === 'Mistina') { healthGain = Math.floor(enemyMaxHealth * 0.4); // 40% } else if (self.enemy.dragonType === 'Nokan') { healthGain = Math.floor(enemyMaxHealth * 0.25); // 25% } else if (self.enemy.dragonType === 'Oragana') { healthGain = 60; // Fixed 60 points } else if (self.enemy.dragonType === 'Farocha') { healthGain = 65; // Fixed 65 points } else if (self.enemy.dragonType === 'Nonano') { healthGain = 50; // Fixed 50 points // Increment Nonano defeat count for adaptation storage.nonanoDefeatCount = (storage.nonanoDefeatCount || 0) + 1; } else if (self.enemy.dragonType === 'Jarare') { healthGain = self.player.maxHealth; // Double current max health } else if (self.enemy.dragonType === 'Eriza') { healthGain = Math.floor(enemyMaxHealth * 0.7); // 70% } else if (self.enemy.dragonType === 'Katoza') { healthGain = 20; // Fixed 20 points } else if (self.enemy.dragonType === 'Ultete') { healthGain = 40; // Fixed 40 points } // Apply health gain to baby dragon self.player.maxHealth += healthGain; self.player.health = Math.min(self.player.health + healthGain, self.player.maxHealth); // Grant elemental stones for each element the dragon has for (var i = 0; i < self.enemy.elements.length; i++) { var element = self.enemy.elements[i]; if (!self.player.elementalStones[element]) { self.player.elementalStones[element] = 0; } self.player.elementalStones[element]++; } LK.setScore(LK.getScore() + 100); LK.getSound('victory').play(); var victoryMessage = 'Victory! +' + healthGain + ' Max HP! '; victoryMessage += 'Gained ' + self.enemy.elements.join(' & ') + ' Stone(s)! '; victoryMessage += 'Level: ' + self.player.level + ' XP: ' + self.player.experience + '/' + self.player.experienceToNext; self.ui.showAction(victoryMessage); // Save progress storage.level = self.player.level; storage.experience = self.player.experience; storage.experienceToNext = self.player.experienceToNext; storage.health = self.player.health; storage.maxHealth = self.player.maxHealth; storage.elementalStones = self.player.elementalStones; storage.score = LK.getScore(); LK.setTimeout(function () { inCombat = false; currentCombat = null; self.destroy(); }, 2000); }; self.defeat = function () { LK.getSound('defeat').play(); self.ui.showAction('Defeat! Game Over'); LK.setTimeout(function () { LK.showGameOver(); }, 2000); }; self.update = function () { self.ui.updateHealthBars(self.player.health, self.player.maxHealth, self.enemy.health, self.enemy.maxHealth, self.player.level, self.player.defenseCount); if (self.turnTimer > 0) { self.turnTimer -= 16.67; if (self.turnTimer <= 0) { self.enemyTurn(); } } }; return self; }); var CombatUI = Container.expand(function () { var self = Container.call(this); var background = self.attachAsset('healthBarBg', { width: 2048, height: 2732, anchorX: 0, anchorY: 0, alpha: 0.8 }); background.tint = 0x000000; var playerHealthBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2200 }); var playerHealthBar = self.attachAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2200 }); var enemyHealthBg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 400 }); var enemyHealthBar = self.attachAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 400 }); var attackButton = self.attachAsset('combatButton', { anchorX: 0.5, anchorY: 0.5, x: 800, y: 2400 }); var defendButton = self.attachAsset('combatButton', { anchorX: 0.5, anchorY: 0.5, x: 1248, y: 2400 }); defendButton.tint = 0x0000ff; // Blue color for defend button self.playerHealthBar = playerHealthBar; self.enemyHealthBar = enemyHealthBar; self.attackButton = attackButton; self.defendButton = defendButton; var playerInfoText = new Text2('', { size: 40, fill: '#000000' }); playerInfoText.anchor.set(0.5, 0.5); playerInfoText.x = 1024; playerInfoText.y = 2300; self.addChild(playerInfoText); self.playerInfoText = playerInfoText; var enemyInfoText = new Text2('', { size: 40, fill: '#000000' }); enemyInfoText.anchor.set(0.5, 0.5); enemyInfoText.x = 1024; enemyInfoText.y = 500; self.addChild(enemyInfoText); self.enemyInfoText = enemyInfoText; var actionText = new Text2('', { size: 50, fill: '#ffff00' }); actionText.anchor.set(0.5, 0.5); actionText.x = 1024; actionText.y = 1300; self.addChild(actionText); self.actionText = actionText; var attackButtonText = new Text2('Attack', { size: 35, fill: '#ffffff' }); attackButtonText.anchor.set(0.5, 0.5); attackButtonText.x = 800; attackButtonText.y = 2400; self.addChild(attackButtonText); var defendButtonText = new Text2('Defend', { size: 35, fill: '#ffffff' }); defendButtonText.anchor.set(0.5, 0.5); defendButtonText.x = 1248; defendButtonText.y = 2400; self.addChild(defendButtonText); var defenseCountText = new Text2('', { size: 30, fill: '#000000' }); defenseCountText.anchor.set(0.5, 0.5); defenseCountText.x = 1248; defenseCountText.y = 2500; self.addChild(defenseCountText); self.defenseCountText = defenseCountText; self.updateHealthBars = function (playerHealth, playerMaxHealth, enemyHealth, enemyMaxHealth, playerLevel, defenseCount) { var playerRatio = playerHealth / playerMaxHealth; var enemyRatio = enemyHealth / enemyMaxHealth; self.playerHealthBar.scaleX = playerRatio; self.enemyHealthBar.scaleX = enemyRatio; self.playerInfoText.setText('HP: ' + playerHealth + '/' + playerMaxHealth); self.enemyInfoText.setText('HP: ' + enemyHealth + '/' + enemyMaxHealth); if (self.defenseCountText && playerLevel) { var maxDefenses = playerLevel * 5; self.defenseCountText.setText(defenseCount + '/' + maxDefenses); } }; self.showAction = function (text) { self.actionText.setText(text); tween(self.actionText, { alpha: 1 }, { duration: 0 }); tween(self.actionText, { alpha: 0 }, { duration: 2000 }); }; self.down = function (x, y, obj) { // Check if obj and obj.parent exist before calling toGlobal if (obj && obj.parent && obj.parent.toGlobal) { var localPos = self.toLocal(obj.parent.toGlobal(obj.position)); } if (currentCombat && currentCombat.enemy.isHealing) { if (currentCombat.enemy.interruptHealing()) { self.showAction('Healing Interrupted!'); currentCombat.playerAttack(); } } else if (currentCombat && currentCombat.isPlayerTurn) { // Check if defend button was clicked var defendButtonBounds = { left: 1248 - 75, right: 1248 + 75, top: 2400 - 30, bottom: 2400 + 30 }; if (x >= defendButtonBounds.left && x <= defendButtonBounds.right && y >= defendButtonBounds.top && y <= defendButtonBounds.bottom) { currentCombat.playerDefend(); } else { // Otherwise attack currentCombat.playerAttack(); } } }; return self; }); var Platform = Container.expand(function () { var self = Container.call(this); var platformGraphics = self.attachAsset('platform', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -2; self.update = function () { self.x += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Dragon type specific assets // Shadow & Fire - dark red // Light & Plant - light green // Energy & Void - indigo // Wind & Earth - saddle brown // Water & Void - midnight blue // Water & Wind - deep sky blue // Energy & Plant - lime green (rare) // Light & Fire - gold // Shadow & Wind - dark slate gray // Void & Plant - dark olive green var platforms = []; var adultDragons = []; var babyDragon = new BabyDragon(); var inCombat = false; var currentCombat = null; var platformSpawnTimer = 0; var dragonSpawnTimer = 0; var scrollSpeed = 2; // Dragon types var dragonTypes = ['Nilisty', 'Mistina', 'Nokan', 'Oragana', 'Farocha', 'Nonano', 'Jarare', 'Eriza', 'Katoza', 'Ultete']; // Add custom background var customBackground = game.attachAsset('customBackground', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732 }); // Initialize baby dragon with saved data babyDragon.x = 300; babyDragon.y = 1800; babyDragon.level = storage.level || 1; babyDragon.experience = storage.experience || 0; babyDragon.experienceToNext = storage.experienceToNext || 3; babyDragon.maxHealth = storage.maxHealth || 50; // Always regenerate health to full after game over - this ensures health is always restored babyDragon.health = babyDragon.maxHealth; babyDragon.elementalStones = storage.elementalStones || {}; babyDragon.defenseCount = storage.defenseCount || 0; LK.setScore(storage.score || 0); // Save the regenerated health immediately to storage storage.health = babyDragon.maxHealth; storage.maxHealth = babyDragon.maxHealth; game.addChild(babyDragon); // Start background music LK.playMusic('backgroundMusic'); // Create initial platforms for (var i = 0; i < 5; i++) { var platform = new Platform(); platform.x = 400 + i * 400; platform.y = 1800 + (Math.random() * 400 - 200); platforms.push(platform); game.addChild(platform); } // UI Elements var levelText = new Text2('Level: 1', { size: 60, fill: '#000000' }); levelText.anchor.set(0, 0); levelText.x = 150; levelText.y = 100; LK.gui.topLeft.addChild(levelText); // Elemental stones display below level var elementalStonesDisplay = new Text2('', { size: 35, fill: '#ffd700' }); elementalStonesDisplay.anchor.set(0, 0); elementalStonesDisplay.x = 150; elementalStonesDisplay.y = 170; LK.gui.topLeft.addChild(elementalStonesDisplay); // Remaining dragons display below stones var remainingDragonsDisplay = new Text2('', { size: 35, fill: '#000000' }); remainingDragonsDisplay.anchor.set(0, 0); remainingDragonsDisplay.x = 150; remainingDragonsDisplay.y = 210; LK.gui.topLeft.addChild(remainingDragonsDisplay); var healthText = new Text2('HP: 50/50', { size: 60, fill: '#000000' }); healthText.anchor.set(1, 0); healthText.x = 1900; healthText.y = 100; LK.gui.topRight.addChild(healthText); var scoreText = new Text2('Score: 0', { size: 60, fill: '#000000' }); scoreText.anchor.set(0.5, 0); scoreText.x = 1024; scoreText.y = 100; LK.gui.top.addChild(scoreText); var stonesText = new Text2('Stones: 0', { size: 70, fill: '#ffd700' }); stonesText.anchor.set(0.5, 0); stonesText.x = 1024; stonesText.y = 200; LK.gui.top.addChild(stonesText); // Individual stone counters display var stoneCountersText = new Text2('', { size: 45, fill: '#000000' }); stoneCountersText.anchor.set(0.5, 0); stoneCountersText.x = 1024; stoneCountersText.y = 280; LK.gui.top.addChild(stoneCountersText); game.down = function (x, y, obj) { if (inCombat) return; // Find nearest platform to jump to var nearestPlatform = null; var minDistance = Infinity; for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; var distance = Math.abs(platform.x - babyDragon.x); if (distance < minDistance && platform.x > babyDragon.x - 100) { minDistance = distance; nearestPlatform = platform; } } if (nearestPlatform) { babyDragon.jumpTo(nearestPlatform.y); } }; function spawnPlatform() { var platform = new Platform(); platform.x = 2200; platform.y = 1400 + Math.random() * 800; platforms.push(platform); game.addChild(platform); } function spawnDragon() { if (platforms.length > 0) { var randomPlatform = platforms[Math.floor(Math.random() * platforms.length)]; // Create weighted dragon type selection (Jarare is 50% less likely) var weightedDragonTypes = []; for (var i = 0; i < dragonTypes.length; i++) { var type = dragonTypes[i]; if (type === 'Jarare') { // Jarare has 50% less chance (add once instead of twice) weightedDragonTypes.push(type); } else { // All other dragons have normal chance (add twice) weightedDragonTypes.push(type); weightedDragonTypes.push(type); } } var dragonType = weightedDragonTypes[Math.floor(Math.random() * weightedDragonTypes.length)]; var dragon = new AdultDragon(dragonType, babyDragon.level); dragon.x = randomPlatform.x; dragon.y = randomPlatform.y - 80; adultDragons.push(dragon); game.addChild(dragon); } } function startCombat(dragon) { inCombat = true; currentCombat = new Combat(babyDragon, dragon); game.addChild(currentCombat); // Remove dragon from world var index = adultDragons.indexOf(dragon); if (index > -1) { adultDragons.splice(index, 1); } } game.update = function () { if (inCombat) { return; } // Update platforms for (var i = platforms.length - 1; i >= 0; i--) { var platform = platforms[i]; if (platform.x < -200) { platform.destroy(); platforms.splice(i, 1); } } // Update adult dragons for (var i = adultDragons.length - 1; i >= 0; i--) { var dragon = adultDragons[i]; dragon.x -= scrollSpeed; if (dragon.x < -200) { dragon.destroy(); adultDragons.splice(i, 1); continue; } // Check collision with baby dragon if (dragon.intersects(babyDragon)) { startCombat(dragon); dragon.destroy(); break; } } // Spawn platforms platformSpawnTimer += 16.67; if (platformSpawnTimer >= 2000) { spawnPlatform(); platformSpawnTimer = 0; } // Spawn dragons dragonSpawnTimer += 16.67; if (dragonSpawnTimer >= 5000) { spawnDragon(); dragonSpawnTimer = 0; } // Update UI levelText.setText('Level: ' + babyDragon.level); healthText.setText('HP: ' + babyDragon.health + '/' + babyDragon.maxHealth); scoreText.setText('Score: ' + LK.getScore()); // Count total elemental stones and create detailed display var totalStones = 0; var stoneDetails = []; var elementOrder = ['Fire', 'Water', 'Earth', 'Dark', 'Ice', 'Lightning', 'Light', 'Shadow', 'Plant', 'Void', 'Energy', 'Wind']; for (var i = 0; i < elementOrder.length; i++) { var element = elementOrder[i]; if (babyDragon.elementalStones[element] && babyDragon.elementalStones[element] > 0) { var count = babyDragon.elementalStones[element]; totalStones += count; stoneDetails.push(element + ': ' + count); } } stonesText.setText('Total Stones: ' + totalStones); // Update individual stone counters if (stoneDetails.length > 0) { stoneCountersText.setText(stoneDetails.join(' | ')); } else { stoneCountersText.setText('No elemental stones collected'); } // Update elemental stones display below level if (stoneDetails.length > 0) { elementalStonesDisplay.setText('Stones: ' + stoneDetails.slice(0, 3).join(', ')); } else { elementalStonesDisplay.setText('Stones: None collected'); } // Calculate remaining dragons to defeat for next level var remainingDragons = babyDragon.experienceToNext - babyDragon.experience; remainingDragonsDisplay.setText('Dragons to next level: ' + remainingDragons); // Save progress periodically (every 5 seconds) if (LK.ticks % 300 === 0) { storage.level = babyDragon.level; storage.experience = babyDragon.experience; storage.experienceToNext = babyDragon.experienceToNext; storage.health = babyDragon.health; storage.maxHealth = babyDragon.maxHealth; storage.elementalStones = babyDragon.elementalStones; storage.defenseCount = babyDragon.defenseCount; storage.score = LK.getScore(); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
level: 1,
experience: 0,
experienceToNext: 3,
health: 50,
maxHealth: 50,
elementalStones: {},
score: 0,
nonanoDefeatCount: 0,
defenseCount: 0
});
/****
* Classes
****/
var AdultDragon = Container.expand(function (type, level) {
var self = Container.call(this);
// Map dragon types to their specific assets
var assetMap = {
'Nilisty': 'nilisty',
'Mistina': 'mistina',
'Nokan': 'nokan',
'Oragana': 'oragana',
'Farocha': 'farocha',
'Nonano': 'nonano',
'Jarare': 'jarare',
'Eriza': 'eriza',
'Katoza': 'katoza',
'Ultete': 'ultete'
};
var assetName = assetMap[type] || 'nilisty';
var dragonGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.dragonType = type || 'Nilisty';
self.level = level || 1;
self.nonanoDefeatCount = storage.nonanoDefeatCount || 0;
// Calculate health based on dragon type and level
self.calculateHealth = function () {
var playerLevel = self.level;
var baseHealthRanges = {
'Nilisty': {
min: 25,
max: 100,
perLevel: 36
},
'Mistina': {
min: 30,
max: 110,
perLevel: 40
},
'Nokan': {
min: 30,
max: 100,
perLevel: 50
},
'Oragana': {
min: 40,
max: 120,
perLevel: 50
},
'Farocha': {
min: 50,
max: 130,
perLevel: 70
},
'Nonano': {
min: 80,
max: 150,
perLevel: 30
},
'Jarare': {
min: 90,
max: 170,
perLevel: 0
},
// Special case - 80% increase
'Eriza': {
min: 20,
max: 80,
perLevel: 0
},
// Special case - can increase during combat
'Katoza': {
min: 10,
max: 50,
perLevel: 0
},
// Fixed range
'Ultete': {
min: 20,
max: 60,
perLevel: 20
}
};
var range = baseHealthRanges[self.dragonType];
if (!range) range = baseHealthRanges['Nilisty'];
var baseHealth = Math.floor(Math.random() * (range.max - range.min + 1)) + range.min;
// Apply level scaling
if (self.dragonType === 'Jarare') {
// Jarare increases by 80% per level
var levelBonus = Math.floor(baseHealth * 0.8 * (playerLevel - 1));
baseHealth += levelBonus;
} else if (self.dragonType === 'Nonano') {
// Nonano adapts based on previous defeats
var adaptationBonus = self.nonanoDefeatCount * 30;
baseHealth += adaptationBonus + range.perLevel * (playerLevel - 1);
} else if (range.perLevel > 0) {
baseHealth += range.perLevel * (playerLevel - 1);
}
return baseHealth;
};
// Define elements for each dragon type
self.getElements = function () {
var elementMap = {
'Nilisty': ['Shadow', 'Fire'],
'Mistina': ['Light', 'Plant'],
'Nokan': ['Energy', 'Void'],
'Oragana': ['Wind', 'Earth'],
'Farocha': ['Water', 'Void'],
'Nonano': ['Water', 'Wind'],
'Jarare': ['Energy', 'Plant'],
'Eriza': ['Light', 'Fire'],
'Katoza': ['Shadow', 'Wind'],
'Ultete': ['Void', 'Plant']
};
return elementMap[self.dragonType] || ['Fire'];
};
self.originalMaxHealth = self.calculateHealth();
self.maxHealth = self.originalMaxHealth;
self.health = self.maxHealth;
self.elements = self.getElements();
self.canHeal = ['Mistina', 'Oragana', 'Katoza', 'Ultete'].includes(self.dragonType);
self.isHealing = false;
self.healingTimer = 0;
self.hasUsedSpecialAbility = false;
self.canUseSword = ['Mistina', 'Ultete'].includes(self.dragonType);
self.hasSword = false;
// Determine if this dragon will use a sword (45% chance for Mistina and Ultete)
if (self.canUseSword && Math.random() < 0.45) {
self.hasSword = true;
}
// Store original colors for healing effects
var originalColors = {
'Nilisty': 0x8b0000,
'Mistina': 0x00ff7f,
'Nokan': 0x4b0082,
'Oragana': 0x8b4513,
'Farocha': 0x191970,
'Nonano': 0x00bfff,
'Jarare': 0x32cd32,
'Eriza': 0xffd700,
'Katoza': 0x2f4f4f,
'Ultete': 0x556b2f
};
self.startHealing = function () {
if (self.canHeal && !self.isHealing) {
self.isHealing = true;
self.healingTimer = 5000; // 5 seconds
dragonGraphics.tint = 0x00ff00; // Green tint when healing
}
};
self.interruptHealing = function () {
if (self.isHealing) {
self.isHealing = false;
self.healingTimer = 0;
dragonGraphics.tint = originalColors[self.dragonType] || 0x8b0000;
return true;
}
return false;
};
self.completeHealing = function () {
if (self.isHealing) {
var healAmount = 0;
if (self.dragonType === 'Mistina') {
healAmount = Math.floor(self.maxHealth * 0.25);
} else if (self.dragonType === 'Oragana') {
healAmount = Math.floor(self.originalMaxHealth * 0.4);
} else if (self.dragonType === 'Katoza' && !self.hasUsedSpecialAbility) {
// Katoza full heal and max health boost
self.health = self.maxHealth;
self.maxHealth = Math.min(150, Math.floor(Math.random() * (150 - self.maxHealth + 1)) + self.maxHealth);
self.health = self.maxHealth;
self.hasUsedSpecialAbility = true;
self.isHealing = false;
self.healingTimer = 0;
dragonGraphics.tint = originalColors[self.dragonType] || 0x8b0000;
return;
} else if (self.dragonType === 'Ultete') {
healAmount = Math.floor(self.maxHealth * 0.1);
}
self.health = Math.min(self.health + healAmount, self.maxHealth);
self.isHealing = false;
self.healingTimer = 0;
dragonGraphics.tint = originalColors[self.dragonType] || 0x8b0000;
}
};
// Special abilities for specific dragon types
self.trySpecialAbility = function () {
if (self.dragonType === 'Eriza' && Math.random() < 0.3) {
// Eriza can randomly increase health during combat
var healthIncrease = Math.floor(Math.random() * 21) + 10; // 10-30 increase
var newMaxHealth = Math.min(100, self.maxHealth + healthIncrease);
self.maxHealth = newMaxHealth;
self.health = Math.min(self.health + healthIncrease, self.maxHealth);
return true;
} else if (self.dragonType === 'Katoza' && self.health <= 10 && !self.hasUsedSpecialAbility) {
// Katoza special transformation when health drops below 10
self.startHealing();
return true;
}
return false;
};
self.useSwordAttack = function (targetPlayer) {
if (self.hasSword && targetPlayer) {
// Reduce baby dragon's max health by 30%
var healthReduction = Math.floor(targetPlayer.maxHealth * 0.3);
targetPlayer.maxHealth = Math.max(1, targetPlayer.maxHealth - healthReduction);
// Also reduce current health if it exceeds new max health
if (targetPlayer.health > targetPlayer.maxHealth) {
targetPlayer.health = targetPlayer.maxHealth;
}
self.hasSword = false; // Sword can only be used once per combat
return healthReduction;
}
return 0;
};
self.update = function () {
if (self.isHealing) {
self.healingTimer -= 16.67; // ~60fps
if (self.healingTimer <= 0) {
self.completeHealing();
}
}
// Try special abilities randomly during combat
if (Math.random() < 0.1) {
// 10% chance per frame
self.trySpecialAbility();
}
};
return self;
});
var BabyDragon = Container.expand(function () {
var self = Container.call(this);
var dragonGraphics = self.attachAsset('babyDragon', {
anchorX: 0.5,
anchorY: 0.5
});
self.maxHealth = 50;
self.health = self.maxHealth;
self.level = 1;
self.experience = 0;
self.experienceToNext = 3;
self.targetY = 0;
self.jumpSpeed = 0;
self.isJumping = false;
self.elementalStones = {};
self.defenseCount = 0;
self.isDefending = false;
self.takeDamage = function (damage) {
if (self.isDefending) {
// Defense blocks all damage
self.isDefending = false;
LK.effects.flashObject(self, 0x0000ff, 500); // Blue flash for successful defense
return;
}
self.health = Math.max(0, self.health - damage);
LK.effects.flashObject(self, 0xff0000, 500);
};
self.useDefense = function () {
if (self.defenseCount < self.level * 5) {
self.isDefending = true;
self.defenseCount++;
return true;
}
return false;
};
self.resetDefenseCount = function () {
self.defenseCount = 0;
};
self.gainExperience = function () {
self.experience++;
if (self.experience >= self.experienceToNext) {
self.levelUp();
}
};
self.levelUp = function () {
self.level++;
self.experience = 0;
self.experienceToNext *= 2;
// Health bonus and full regeneration
var healthBonus = Math.floor(self.maxHealth * 0.1);
self.maxHealth += healthBonus;
self.health = self.maxHealth;
// Reset defense count on level up
self.resetDefenseCount();
LK.effects.flashObject(self, 0xffd700, 1000);
// Save progress immediately on level up
storage.level = self.level;
storage.experience = self.experience;
storage.experienceToNext = self.experienceToNext;
storage.health = self.health;
storage.maxHealth = self.maxHealth;
storage.elementalStones = self.elementalStones;
storage.defenseCount = self.defenseCount;
storage.score = LK.getScore();
};
self.jumpTo = function (targetY) {
if (!self.isJumping) {
self.isJumping = true;
self.targetY = targetY;
self.jumpSpeed = -8;
LK.getSound('jump').play();
}
};
self.update = function () {
if (self.isJumping) {
self.jumpSpeed += 0.5; // gravity
self.y += self.jumpSpeed;
if (self.y >= self.targetY) {
self.y = self.targetY;
self.isJumping = false;
self.jumpSpeed = 0;
}
}
};
return self;
});
var Combat = Container.expand(function (player, enemy) {
var self = Container.call(this);
self.player = player;
self.enemy = enemy;
self.isPlayerTurn = true;
self.turnTimer = 0;
self.ui = new CombatUI();
self.addChild(self.ui);
self.playerAttack = function () {
if (!self.isPlayerTurn) return;
var damage = 15 + Math.floor(Math.random() * 10);
self.enemy.health = Math.max(0, self.enemy.health - damage);
self.ui.showAction('You deal ' + damage + ' damage!');
LK.getSound('attack').play();
if (self.enemy.health <= 0) {
self.victory();
} else {
self.isPlayerTurn = false;
self.turnTimer = 1000;
}
};
self.playerDefend = function () {
if (!self.isPlayerTurn) return;
if (self.player.useDefense()) {
self.ui.showAction('Defense ready! Next attack will be blocked!');
self.isPlayerTurn = false;
self.turnTimer = 1000;
} else {
var maxDefenses = self.player.level * 5;
self.ui.showAction('No defenses left! (' + self.player.defenseCount + '/' + maxDefenses + ')');
}
};
self.enemyTurn = function () {
// Check for healing conditions based on dragon type
var shouldHeal = false;
if (self.enemy.dragonType === 'Mistina' && self.enemy.health < 20) {
shouldHeal = true; // Mistina heals when below 20 HP
} else if (self.enemy.dragonType === 'Oragana' && self.enemy.health < self.enemy.maxHealth * 0.5) {
shouldHeal = true; // Oragana heals when below 50%
} else if (self.enemy.dragonType === 'Katoza' && self.enemy.health <= 10 && !self.enemy.hasUsedSpecialAbility) {
shouldHeal = true; // Katoza special heal when below 10 HP
} else if (self.enemy.dragonType === 'Ultete' && Math.random() < 0.4) {
shouldHeal = true; // Ultete can heal anytime with 40% chance
}
if (shouldHeal && self.enemy.canHeal && !self.enemy.isHealing) {
self.enemy.startHealing();
self.ui.showAction(self.enemy.dragonType + ' is healing! Tap to interrupt!');
} else if (self.enemy.hasSword && Math.random() < 0.5) {
// 50% chance to use sword if available (in addition to the 45% chance to have one)
var healthReduction = self.enemy.useSwordAttack(self.player);
if (healthReduction > 0) {
self.ui.showAction(self.enemy.dragonType + ' uses sword! -' + healthReduction + ' Max HP!');
LK.effects.flashObject(self.player, 0x800080, 1000); // Purple flash for sword attack
} else {
var damage = 10 + Math.floor(Math.random() * 8);
self.player.takeDamage(damage);
self.ui.showAction(self.enemy.dragonType + ' deals ' + damage + ' damage!');
}
if (self.player.health <= 0) {
self.defeat();
return;
}
} else {
var damage = 10 + Math.floor(Math.random() * 8);
self.player.takeDamage(damage);
self.ui.showAction(self.enemy.dragonType + ' deals ' + damage + ' damage!');
if (self.player.health <= 0) {
self.defeat();
return;
}
}
self.isPlayerTurn = true;
self.turnTimer = 0;
};
self.victory = function () {
// Ensure we only count this victory once
if (self.victoryProcessed) return;
self.victoryProcessed = true;
self.player.gainExperience();
// Calculate health gain based on defeated dragon type
var healthGain = 0;
var enemyMaxHealth = self.enemy.maxHealth;
if (self.enemy.dragonType === 'Nilisty') {
healthGain = Math.floor(enemyMaxHealth * 0.2); // 20%
} else if (self.enemy.dragonType === 'Mistina') {
healthGain = Math.floor(enemyMaxHealth * 0.4); // 40%
} else if (self.enemy.dragonType === 'Nokan') {
healthGain = Math.floor(enemyMaxHealth * 0.25); // 25%
} else if (self.enemy.dragonType === 'Oragana') {
healthGain = 60; // Fixed 60 points
} else if (self.enemy.dragonType === 'Farocha') {
healthGain = 65; // Fixed 65 points
} else if (self.enemy.dragonType === 'Nonano') {
healthGain = 50; // Fixed 50 points
// Increment Nonano defeat count for adaptation
storage.nonanoDefeatCount = (storage.nonanoDefeatCount || 0) + 1;
} else if (self.enemy.dragonType === 'Jarare') {
healthGain = self.player.maxHealth; // Double current max health
} else if (self.enemy.dragonType === 'Eriza') {
healthGain = Math.floor(enemyMaxHealth * 0.7); // 70%
} else if (self.enemy.dragonType === 'Katoza') {
healthGain = 20; // Fixed 20 points
} else if (self.enemy.dragonType === 'Ultete') {
healthGain = 40; // Fixed 40 points
}
// Apply health gain to baby dragon
self.player.maxHealth += healthGain;
self.player.health = Math.min(self.player.health + healthGain, self.player.maxHealth);
// Grant elemental stones for each element the dragon has
for (var i = 0; i < self.enemy.elements.length; i++) {
var element = self.enemy.elements[i];
if (!self.player.elementalStones[element]) {
self.player.elementalStones[element] = 0;
}
self.player.elementalStones[element]++;
}
LK.setScore(LK.getScore() + 100);
LK.getSound('victory').play();
var victoryMessage = 'Victory! +' + healthGain + ' Max HP! ';
victoryMessage += 'Gained ' + self.enemy.elements.join(' & ') + ' Stone(s)! ';
victoryMessage += 'Level: ' + self.player.level + ' XP: ' + self.player.experience + '/' + self.player.experienceToNext;
self.ui.showAction(victoryMessage);
// Save progress
storage.level = self.player.level;
storage.experience = self.player.experience;
storage.experienceToNext = self.player.experienceToNext;
storage.health = self.player.health;
storage.maxHealth = self.player.maxHealth;
storage.elementalStones = self.player.elementalStones;
storage.score = LK.getScore();
LK.setTimeout(function () {
inCombat = false;
currentCombat = null;
self.destroy();
}, 2000);
};
self.defeat = function () {
LK.getSound('defeat').play();
self.ui.showAction('Defeat! Game Over');
LK.setTimeout(function () {
LK.showGameOver();
}, 2000);
};
self.update = function () {
self.ui.updateHealthBars(self.player.health, self.player.maxHealth, self.enemy.health, self.enemy.maxHealth, self.player.level, self.player.defenseCount);
if (self.turnTimer > 0) {
self.turnTimer -= 16.67;
if (self.turnTimer <= 0) {
self.enemyTurn();
}
}
};
return self;
});
var CombatUI = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('healthBarBg', {
width: 2048,
height: 2732,
anchorX: 0,
anchorY: 0,
alpha: 0.8
});
background.tint = 0x000000;
var playerHealthBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2200
});
var playerHealthBar = self.attachAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2200
});
var enemyHealthBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 400
});
var enemyHealthBar = self.attachAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 400
});
var attackButton = self.attachAsset('combatButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: 2400
});
var defendButton = self.attachAsset('combatButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1248,
y: 2400
});
defendButton.tint = 0x0000ff; // Blue color for defend button
self.playerHealthBar = playerHealthBar;
self.enemyHealthBar = enemyHealthBar;
self.attackButton = attackButton;
self.defendButton = defendButton;
var playerInfoText = new Text2('', {
size: 40,
fill: '#000000'
});
playerInfoText.anchor.set(0.5, 0.5);
playerInfoText.x = 1024;
playerInfoText.y = 2300;
self.addChild(playerInfoText);
self.playerInfoText = playerInfoText;
var enemyInfoText = new Text2('', {
size: 40,
fill: '#000000'
});
enemyInfoText.anchor.set(0.5, 0.5);
enemyInfoText.x = 1024;
enemyInfoText.y = 500;
self.addChild(enemyInfoText);
self.enemyInfoText = enemyInfoText;
var actionText = new Text2('', {
size: 50,
fill: '#ffff00'
});
actionText.anchor.set(0.5, 0.5);
actionText.x = 1024;
actionText.y = 1300;
self.addChild(actionText);
self.actionText = actionText;
var attackButtonText = new Text2('Attack', {
size: 35,
fill: '#ffffff'
});
attackButtonText.anchor.set(0.5, 0.5);
attackButtonText.x = 800;
attackButtonText.y = 2400;
self.addChild(attackButtonText);
var defendButtonText = new Text2('Defend', {
size: 35,
fill: '#ffffff'
});
defendButtonText.anchor.set(0.5, 0.5);
defendButtonText.x = 1248;
defendButtonText.y = 2400;
self.addChild(defendButtonText);
var defenseCountText = new Text2('', {
size: 30,
fill: '#000000'
});
defenseCountText.anchor.set(0.5, 0.5);
defenseCountText.x = 1248;
defenseCountText.y = 2500;
self.addChild(defenseCountText);
self.defenseCountText = defenseCountText;
self.updateHealthBars = function (playerHealth, playerMaxHealth, enemyHealth, enemyMaxHealth, playerLevel, defenseCount) {
var playerRatio = playerHealth / playerMaxHealth;
var enemyRatio = enemyHealth / enemyMaxHealth;
self.playerHealthBar.scaleX = playerRatio;
self.enemyHealthBar.scaleX = enemyRatio;
self.playerInfoText.setText('HP: ' + playerHealth + '/' + playerMaxHealth);
self.enemyInfoText.setText('HP: ' + enemyHealth + '/' + enemyMaxHealth);
if (self.defenseCountText && playerLevel) {
var maxDefenses = playerLevel * 5;
self.defenseCountText.setText(defenseCount + '/' + maxDefenses);
}
};
self.showAction = function (text) {
self.actionText.setText(text);
tween(self.actionText, {
alpha: 1
}, {
duration: 0
});
tween(self.actionText, {
alpha: 0
}, {
duration: 2000
});
};
self.down = function (x, y, obj) {
// Check if obj and obj.parent exist before calling toGlobal
if (obj && obj.parent && obj.parent.toGlobal) {
var localPos = self.toLocal(obj.parent.toGlobal(obj.position));
}
if (currentCombat && currentCombat.enemy.isHealing) {
if (currentCombat.enemy.interruptHealing()) {
self.showAction('Healing Interrupted!');
currentCombat.playerAttack();
}
} else if (currentCombat && currentCombat.isPlayerTurn) {
// Check if defend button was clicked
var defendButtonBounds = {
left: 1248 - 75,
right: 1248 + 75,
top: 2400 - 30,
bottom: 2400 + 30
};
if (x >= defendButtonBounds.left && x <= defendButtonBounds.right && y >= defendButtonBounds.top && y <= defendButtonBounds.bottom) {
currentCombat.playerDefend();
} else {
// Otherwise attack
currentCombat.playerAttack();
}
}
};
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -2;
self.update = function () {
self.x += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Dragon type specific assets
// Shadow & Fire - dark red
// Light & Plant - light green
// Energy & Void - indigo
// Wind & Earth - saddle brown
// Water & Void - midnight blue
// Water & Wind - deep sky blue
// Energy & Plant - lime green (rare)
// Light & Fire - gold
// Shadow & Wind - dark slate gray
// Void & Plant - dark olive green
var platforms = [];
var adultDragons = [];
var babyDragon = new BabyDragon();
var inCombat = false;
var currentCombat = null;
var platformSpawnTimer = 0;
var dragonSpawnTimer = 0;
var scrollSpeed = 2;
// Dragon types
var dragonTypes = ['Nilisty', 'Mistina', 'Nokan', 'Oragana', 'Farocha', 'Nonano', 'Jarare', 'Eriza', 'Katoza', 'Ultete'];
// Add custom background
var customBackground = game.attachAsset('customBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
// Initialize baby dragon with saved data
babyDragon.x = 300;
babyDragon.y = 1800;
babyDragon.level = storage.level || 1;
babyDragon.experience = storage.experience || 0;
babyDragon.experienceToNext = storage.experienceToNext || 3;
babyDragon.maxHealth = storage.maxHealth || 50;
// Always regenerate health to full after game over - this ensures health is always restored
babyDragon.health = babyDragon.maxHealth;
babyDragon.elementalStones = storage.elementalStones || {};
babyDragon.defenseCount = storage.defenseCount || 0;
LK.setScore(storage.score || 0);
// Save the regenerated health immediately to storage
storage.health = babyDragon.maxHealth;
storage.maxHealth = babyDragon.maxHealth;
game.addChild(babyDragon);
// Start background music
LK.playMusic('backgroundMusic');
// Create initial platforms
for (var i = 0; i < 5; i++) {
var platform = new Platform();
platform.x = 400 + i * 400;
platform.y = 1800 + (Math.random() * 400 - 200);
platforms.push(platform);
game.addChild(platform);
}
// UI Elements
var levelText = new Text2('Level: 1', {
size: 60,
fill: '#000000'
});
levelText.anchor.set(0, 0);
levelText.x = 150;
levelText.y = 100;
LK.gui.topLeft.addChild(levelText);
// Elemental stones display below level
var elementalStonesDisplay = new Text2('', {
size: 35,
fill: '#ffd700'
});
elementalStonesDisplay.anchor.set(0, 0);
elementalStonesDisplay.x = 150;
elementalStonesDisplay.y = 170;
LK.gui.topLeft.addChild(elementalStonesDisplay);
// Remaining dragons display below stones
var remainingDragonsDisplay = new Text2('', {
size: 35,
fill: '#000000'
});
remainingDragonsDisplay.anchor.set(0, 0);
remainingDragonsDisplay.x = 150;
remainingDragonsDisplay.y = 210;
LK.gui.topLeft.addChild(remainingDragonsDisplay);
var healthText = new Text2('HP: 50/50', {
size: 60,
fill: '#000000'
});
healthText.anchor.set(1, 0);
healthText.x = 1900;
healthText.y = 100;
LK.gui.topRight.addChild(healthText);
var scoreText = new Text2('Score: 0', {
size: 60,
fill: '#000000'
});
scoreText.anchor.set(0.5, 0);
scoreText.x = 1024;
scoreText.y = 100;
LK.gui.top.addChild(scoreText);
var stonesText = new Text2('Stones: 0', {
size: 70,
fill: '#ffd700'
});
stonesText.anchor.set(0.5, 0);
stonesText.x = 1024;
stonesText.y = 200;
LK.gui.top.addChild(stonesText);
// Individual stone counters display
var stoneCountersText = new Text2('', {
size: 45,
fill: '#000000'
});
stoneCountersText.anchor.set(0.5, 0);
stoneCountersText.x = 1024;
stoneCountersText.y = 280;
LK.gui.top.addChild(stoneCountersText);
game.down = function (x, y, obj) {
if (inCombat) return;
// Find nearest platform to jump to
var nearestPlatform = null;
var minDistance = Infinity;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var distance = Math.abs(platform.x - babyDragon.x);
if (distance < minDistance && platform.x > babyDragon.x - 100) {
minDistance = distance;
nearestPlatform = platform;
}
}
if (nearestPlatform) {
babyDragon.jumpTo(nearestPlatform.y);
}
};
function spawnPlatform() {
var platform = new Platform();
platform.x = 2200;
platform.y = 1400 + Math.random() * 800;
platforms.push(platform);
game.addChild(platform);
}
function spawnDragon() {
if (platforms.length > 0) {
var randomPlatform = platforms[Math.floor(Math.random() * platforms.length)];
// Create weighted dragon type selection (Jarare is 50% less likely)
var weightedDragonTypes = [];
for (var i = 0; i < dragonTypes.length; i++) {
var type = dragonTypes[i];
if (type === 'Jarare') {
// Jarare has 50% less chance (add once instead of twice)
weightedDragonTypes.push(type);
} else {
// All other dragons have normal chance (add twice)
weightedDragonTypes.push(type);
weightedDragonTypes.push(type);
}
}
var dragonType = weightedDragonTypes[Math.floor(Math.random() * weightedDragonTypes.length)];
var dragon = new AdultDragon(dragonType, babyDragon.level);
dragon.x = randomPlatform.x;
dragon.y = randomPlatform.y - 80;
adultDragons.push(dragon);
game.addChild(dragon);
}
}
function startCombat(dragon) {
inCombat = true;
currentCombat = new Combat(babyDragon, dragon);
game.addChild(currentCombat);
// Remove dragon from world
var index = adultDragons.indexOf(dragon);
if (index > -1) {
adultDragons.splice(index, 1);
}
}
game.update = function () {
if (inCombat) {
return;
}
// Update platforms
for (var i = platforms.length - 1; i >= 0; i--) {
var platform = platforms[i];
if (platform.x < -200) {
platform.destroy();
platforms.splice(i, 1);
}
}
// Update adult dragons
for (var i = adultDragons.length - 1; i >= 0; i--) {
var dragon = adultDragons[i];
dragon.x -= scrollSpeed;
if (dragon.x < -200) {
dragon.destroy();
adultDragons.splice(i, 1);
continue;
}
// Check collision with baby dragon
if (dragon.intersects(babyDragon)) {
startCombat(dragon);
dragon.destroy();
break;
}
}
// Spawn platforms
platformSpawnTimer += 16.67;
if (platformSpawnTimer >= 2000) {
spawnPlatform();
platformSpawnTimer = 0;
}
// Spawn dragons
dragonSpawnTimer += 16.67;
if (dragonSpawnTimer >= 5000) {
spawnDragon();
dragonSpawnTimer = 0;
}
// Update UI
levelText.setText('Level: ' + babyDragon.level);
healthText.setText('HP: ' + babyDragon.health + '/' + babyDragon.maxHealth);
scoreText.setText('Score: ' + LK.getScore());
// Count total elemental stones and create detailed display
var totalStones = 0;
var stoneDetails = [];
var elementOrder = ['Fire', 'Water', 'Earth', 'Dark', 'Ice', 'Lightning', 'Light', 'Shadow', 'Plant', 'Void', 'Energy', 'Wind'];
for (var i = 0; i < elementOrder.length; i++) {
var element = elementOrder[i];
if (babyDragon.elementalStones[element] && babyDragon.elementalStones[element] > 0) {
var count = babyDragon.elementalStones[element];
totalStones += count;
stoneDetails.push(element + ': ' + count);
}
}
stonesText.setText('Total Stones: ' + totalStones);
// Update individual stone counters
if (stoneDetails.length > 0) {
stoneCountersText.setText(stoneDetails.join(' | '));
} else {
stoneCountersText.setText('No elemental stones collected');
}
// Update elemental stones display below level
if (stoneDetails.length > 0) {
elementalStonesDisplay.setText('Stones: ' + stoneDetails.slice(0, 3).join(', '));
} else {
elementalStonesDisplay.setText('Stones: None collected');
}
// Calculate remaining dragons to defeat for next level
var remainingDragons = babyDragon.experienceToNext - babyDragon.experience;
remainingDragonsDisplay.setText('Dragons to next level: ' + remainingDragons);
// Save progress periodically (every 5 seconds)
if (LK.ticks % 300 === 0) {
storage.level = babyDragon.level;
storage.experience = babyDragon.experience;
storage.experienceToNext = babyDragon.experienceToNext;
storage.health = babyDragon.health;
storage.maxHealth = babyDragon.maxHealth;
storage.elementalStones = babyDragon.elementalStones;
storage.defenseCount = babyDragon.defenseCount;
storage.score = LK.getScore();
}
};
Bébé dragon en train de voler. In-Game asset. 2d. High contrast. No shadows
Arbre rouge en feu. In-Game asset. 2d. High contrast. No shadows
Dragonne rose princesse majestueuse. In-Game asset. 2d. High contrast. No shadows
Dragon jaune du tonnerre et du vide. In-Game asset. 2d. High contrast. No shadows
Dragon de l'orage. In-Game asset. 2d. High contrast. No shadows
Dragon légendaire de la nature. In-Game asset. 2d. High contrast. No shadows
Dragon de la lumière. In-Game asset. 2d. High contrast. No shadows
Dragon végétal et du vide. In-Game asset. 2d. High contrast. No shadows
Dragon des glaces. In-Game asset. 2d. High contrast. No shadows
Dragon farouche de l'eau. In-Game asset. 2d. High contrast. No shadows
Dragon de l'ombre. In-Game asset. 2d. High contrast. No shadows
Dragon du feu. In-Game asset. 2d. High contrast. No shadows
Pierre élément feu. In-Game asset. 2d. High contrast. No shadows
Pierre élément eau. In-Game asset. 2d. High contrast. No shadows
Pierre élément terre. In-Game asset. 2d. High contrast. No shadows
Pierre élément ombre. In-Game asset. 2d. High contrast. No shadows
Pierre élément glace. In-Game asset. 2d. High contrast. No shadows
Pierre élément energie. In-Game asset. 2d. High contrast. No shadows
Pierre élément végétal. In-Game asset. 2d. High contrast. No shadows
Pierre element lumière. In-Game asset. 2d. High contrast. No shadows
Pierre élémentaire ombre. In-Game asset. 2d. High contrast. No shadows
Pierre élémentaire vent. In-Game asset. 2d. High contrast. No shadows
Pierre élémentaire vide. In-Game asset. 2d. High contrast. No shadows
Fond d'écran ciel avec nuages. In-Game asset. 2d. High contrast. No shadows