User prompt
ahora en el golem empieza a aprecer despues del enemigo 30
User prompt
crea un nuevo enemigo el golem
User prompt
crea una hitbox invisible en los enemigos del doble de su tamaño
User prompt
Quita los puntos amarillos en el menú principal
User prompt
Quita todo lo verde del menú principal
User prompt
Quita los puntos que aparecen en la pantalla de inicio
User prompt
Cambia el menú de inicio y hazlo parecido a la portada de un libro ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Cambia el fondo celeste y pon uno morado
User prompt
Cambia todo el menú de inicio y hazlo parecido a la portada de un libro ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Aplica todas estas mejoras ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Quita la imagen del mago del menú principal
User prompt
Crea un menú de juego más bonito
User prompt
Pon más bonito el camino
User prompt
Crea un nuevo enemigo que sale después del enemigo 30 que se llame golem
User prompt
Que la segunda fase del menú de mejora sea después del enemigo 40
User prompt
Crea una segunda aparición del menú de mejora después del enemigo 30
User prompt
Has más grande la hitbox invisible
User prompt
Has la hitbox invisible más grande
User prompt
Ahora crea una hitbox en los enemigos más grande e invisible
User prompt
Ahora has los caminos de piedad más grandes
User prompt
Ahora has la hitbox de los enemigos más grande
User prompt
Vuelve a poner el camino de piedras
User prompt
los enemigos que se encuentren en pantalla cuando se muestre el menu dejan de existir
User prompt
pon un cooldown de 2 segundos al menu de mejoras ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
despues del enemigo 12 no aparecen mas enemigos
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Coin = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); self.bobOffset = Math.random() * Math.PI * 2; self.initialY = 0; self.update = function () { if (self.initialY === 0) { self.initialY = self.y; } // Only do bobbing animation and collection if not animating to coin counter if (!self.isAnimating) { // Bobbing animation self.y = self.initialY + Math.sin(LK.ticks * 0.1 + self.bobOffset) * 10; // Check collection by knight if (knight && self.intersects(knight)) { self.collect(); } } }; self.collect = function () { LK.getSound('coinCollect').play(); LK.setScore(LK.getScore() + 5); coinCounter++; coinText.setText('Coins: ' + coinCounter); // Remove from coins array for (var i = coins.length - 1; i >= 0; i--) { if (coins[i] === self) { coins.splice(i, 1); break; } } self.destroy(); }; return self; }); // Game arrays to track objects var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.5, scaleY: 1.5 }); // Create invisible larger hitbox for better collision detection var enemyHitbox = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 1.0, scaleX: 5.0, // Much larger than visible enemy scaleY: 5.0 }); enemyHitbox.alpha = 0; // Make hitbox invisible enemyHitbox.tint = 0xFF0000; // Red tint (invisible anyway) self.health = 100; self.maxHealth = 100; self.speed = 7; // Note: health, maxHealth and speed will be overridden by difficulty system self.lastX = 0; self.update = function () { // Progressive speed increase - increase speed by 50% over 10 seconds if (!self.speedTweenStarted) { self.speedTweenStarted = true; var targetSpeed = self.speed * 2.5; // Increase speed by 150% tween(self, { speed: targetSpeed }, { duration: 10000, // 10 seconds easing: tween.easeOut }); } // Move along the assigned path toward the wizard if (wizard && self.pathAngle !== undefined) { // Move along the path direction toward the wizard var moveX = -Math.cos(self.pathAngle) * self.speed; var moveY = -Math.sin(self.pathAngle) * self.speed; self.x += moveX; self.y += moveY; } else if (wizard) { // Fallback: move directly toward the wizard if no path assigned var dx = wizard.x - self.x; var dy = wizard.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { // Normalize direction and apply speed self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } } else { // Fallback: move down if knight doesn't exist self.y += self.speed; } }; self.takeDamage = function (damage) { self.health -= damage; // Flash red when hit LK.effects.flashObject(self, 0xFF0000, 200); // Enemies die from any projectile hit self.die(); }; self.down = function (x, y, obj) { // Create projectile from wizard to enemy when enemy is tapped if (wizard && projectiles.length < 10) { // Limit projectiles to prevent spam var projectile = game.addChild(new Projectile()); projectile.x = wizard.x; projectile.y = wizard.y; // Calculate direction from wizard to enemy var dx = self.x - wizard.x; var dy = self.y - wizard.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { projectile.direction.x = dx / distance; projectile.direction.y = dy / distance; } projectiles.push(projectile); LK.getSound('spellCast').play(); } }; self.die = function () { // Play pain sound when enemy dies LK.getSound('painSound').play(); // Drop coin var coin = game.addChild(new Coin()); coin.x = self.x; coin.y = self.y - 50; coin.isAnimating = true; coins.push(coin); // Animate coin moving toward coin counter var coinTargetX = 120 + coinText.width / 2; var coinTargetY = 90 + coinText.height / 2; tween(coin, { x: coinTargetX, y: coinTargetY, scaleX: 0.5, scaleY: 0.5 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { // Increment coin counter after animation coinCounter++; coinText.setText('Coins: ' + coinCounter); // Remove coin from array and destroy for (var i = coins.length - 1; i >= 0; i--) { if (coins[i] === coin) { coins.splice(i, 1); break; } } coin.destroy(); } }); // Increment enemy kill counter enemyKillCounter++; killCountText.setText('Puntuacion: ' + enemyKillCounter); // Add experience to wizard wizard.gainExperience(25); // Remove from enemies array for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i] === self) { enemies.splice(i, 1); break; } } self.destroy(); LK.setScore(LK.getScore() + 10); }; return self; }); var GameMenu = Container.expand(function () { var self = Container.call(this); // Create parchment-style book background var bookBackground = self.attachAsset('pathSelector', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 32, scaleY: 42 }); bookBackground.alpha = 0.98; bookBackground.tint = 0xF5DEB3; // Wheat color for parchment // Create ornate book border frame var outerBorder = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 34, scaleY: 44 }); outerBorder.alpha = 1.0; outerBorder.tint = 0x8B4513; // Dark brown leather binding // Inner decorative border var innerBorder = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 30, scaleY: 40 }); innerBorder.alpha = 0.8; innerBorder.tint = 0xDAA520; // Goldenrod border // Create corner decorations (ornate book corners) var cornerPositions = [{ x: 400, y: 400 }, // Top left { x: 1648, y: 400 }, // Top right { x: 400, y: 2332 }, // Bottom left { x: 1648, y: 2332 } // Bottom right ]; for (var i = 0; i < cornerPositions.length; i++) { var corner = self.attachAsset('spell', { anchorX: 0.5, anchorY: 0.5, x: cornerPositions[i].x, y: cornerPositions[i].y, scaleX: 3, scaleY: 3 }); corner.alpha = 0.7; corner.tint = 0xFFD700; // Gold corner decorations corner.rotation = Math.PI / 2 * i; // Rotate each corner // Gentle glow animation for corners tween(corner, { scaleX: 3.5, scaleY: 3.5, alpha: 0.9 }, { duration: 3000, loop: true, yoyo: true, easing: tween.easeInOut }); } // Create book spine decoration on left side for (var i = 0; i < 12; i++) { var spineDecor = self.attachAsset('stonePath', { anchorX: 0.5, anchorY: 0.5, x: 200, y: 600 + i * 150, scaleX: 0.8, scaleY: 2.5 }); spineDecor.tint = 0x654321; // Dark brown spine details spineDecor.alpha = 0.6; spineDecor.rotation = Math.PI / 2; } // Add vintage paper texture with subtle aged spots for (var i = 0; i < 25; i++) { var ageSpot = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5, x: 400 + Math.random() * 1248, y: 500 + Math.random() * 1732, scaleX: 0.3 + Math.random() * 0.8, scaleY: 0.3 + Math.random() * 0.8 }); ageSpot.alpha = 0.1 + Math.random() * 0.15; ageSpot.tint = 0x8B7355; // Brown aging spots } // Create illuminated manuscript-style title var titleContainer = new Container(); titleContainer.x = 2048 / 2; titleContainer.y = 700; self.addChild(titleContainer); // Main title with ornate medieval styling var mainTitle = new Text2('WIZARD', { size: 200, fill: 0x8B0000, font: "monospace" }); mainTitle.anchor.set(0.5, 0.5); mainTitle.y = -50; titleContainer.addChild(mainTitle); // Title shadow for depth var titleShadow = new Text2('WIZARD', { size: 200, fill: 0x000000, font: "monospace" }); titleShadow.anchor.set(0.5, 0.5); titleShadow.x = 5; titleShadow.y = -45; titleShadow.alpha = 0.3; titleContainer.addChildAt(titleShadow, 0); var subTitle = new Text2('DEFENDER', { size: 180, fill: 0x8B0000, font: "monospace" }); subTitle.anchor.set(0.5, 0.5); subTitle.y = 120; titleContainer.addChild(subTitle); // Subtitle shadow var subTitleShadow = new Text2('DEFENDER', { size: 180, fill: 0x000000, font: "monospace" }); subTitleShadow.anchor.set(0.5, 0.5); subTitleShadow.x = 5; subTitleShadow.y = 125; subTitleShadow.alpha = 0.3; titleContainer.addChildAt(subTitleShadow, 0); // Add decorative flourishes around title var leftFlourish = self.attachAsset('spell', { anchorX: 0.5, anchorY: 0.5, x: 600, y: 700, scaleX: 4, scaleY: 1.5 }); leftFlourish.alpha = 0.5; leftFlourish.tint = 0xDAA520; var rightFlourish = self.attachAsset('spell', { anchorX: 0.5, anchorY: 0.5, x: 1448, y: 700, scaleX: 4, scaleY: 1.5 }); rightFlourish.alpha = 0.5; rightFlourish.tint = 0xDAA520; rightFlourish.scaleX = -4; // Mirror the flourish // Animate title entrance with book opening effect titleContainer.scaleX = 0; titleContainer.scaleY = 0; tween(titleContainer, { scaleX: 1, scaleY: 1 }, { duration: 1200, delay: 500, easing: tween.elasticOut }); // Add subtitle describing the tome var bookSubtitle = new Text2('~ A MAGICAL TOME OF DEFENSE ~', { size: 70, fill: 0x654321, font: "monospace" }); bookSubtitle.anchor.set(0.5, 0.5); bookSubtitle.x = 2048 / 2; bookSubtitle.y = 1000; bookSubtitle.alpha = 0; self.addChild(bookSubtitle); // Fade in book subtitle tween(bookSubtitle, { alpha: 1 }, { duration: 1500, delay: 800, easing: tween.easeOut }); // Create author attribution like a real book var authorText = new Text2('By the Ancient Order of Wizards', { size: 50, fill: 0x556B2F, font: "monospace" }); authorText.anchor.set(0.5, 0.5); authorText.x = 2048 / 2; authorText.y = 1150; authorText.alpha = 0; self.addChild(authorText); tween(authorText, { alpha: 0.8 }, { duration: 1500, delay: 1200, easing: tween.easeOut }); // Add medieval instructions in book style var instructionsText = new Text2('~ Touch the Ancient Paths to Cast Spells ~\n~ Defend the Sacred Castle ~', { size: 60, fill: 0x2F4F4F, font: "monospace" }); instructionsText.anchor.set(0.5, 0.5); instructionsText.x = 2048 / 2; instructionsText.y = 1350; instructionsText.alpha = 0; self.addChild(instructionsText); // Fade in instructions tween(instructionsText, { alpha: 1 }, { duration: 1500, delay: 1000, easing: tween.easeOut }); // Create ornate start button like a book clasp var buttonContainer = new Container(); buttonContainer.x = 2048 / 2; buttonContainer.y = 1800; self.addChild(buttonContainer); // Button ornate background (book clasp design) var buttonFrame = buttonContainer.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, scaleX: 5, scaleY: 3 }); buttonFrame.tint = 0x8B4513; // Dark brown frame var buttonInner = buttonContainer.attachAsset('healthBar', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, scaleX: 4.5, scaleY: 2.5 }); buttonInner.tint = 0xDAA520; // Gold inner // Decorative wizard seal in center var wizardSeal = buttonContainer.attachAsset('wizard', { anchorX: 0.5, anchorY: 0.5, x: -100, y: 0, scaleX: 2, scaleY: 2 }); wizardSeal.tint = 0x4B0082; // Dark purple wizard // Start text in medieval style var startButtonText = new Text2('OPEN TOME', { size: 80, fill: 0xF5DEB3, font: "monospace" }); startButtonText.anchor.set(0.5, 0.5); startButtonText.x = 60; startButtonText.y = 0; buttonContainer.addChild(startButtonText); // Button entrance animation (book clasp opening) buttonContainer.scaleX = 0; buttonContainer.scaleY = 0; tween(buttonContainer, { scaleX: 1, scaleY: 1 }, { duration: 800, delay: 1500, easing: tween.elasticOut }); // Add magical runes around the border like a medieval manuscript var runePositions = [{ x: 300, y: 300 }, { x: 1024, y: 250 }, { x: 1748, y: 300 }, { x: 1800, y: 1366 }, { x: 1748, y: 2432 }, { x: 1024, y: 2482 }, { x: 300, y: 2432 }, { x: 248, y: 1366 }]; for (var i = 0; i < runePositions.length; i++) { var rune = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5, x: runePositions[i].x, y: runePositions[i].y, scaleX: 1.5, scaleY: 1.5 }); rune.alpha = 0.4; rune.tint = 0x8B0000; // Dark red runes rune.rotation = Math.PI / 4 * i; // Different rotation for each // Slow mystical rotation tween(rune, { rotation: rune.rotation + Math.PI * 2 }, { duration: 15000 + i * 1000, loop: true, easing: tween.linear }); } // Add medieval page decoration elements for (var i = 0; i < 6; i++) { var pageDecor = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5, x: 500 + i * 200, y: 2200, scaleX: 1.2, scaleY: 1.8 }); pageDecor.alpha = 0.3; pageDecor.tint = 0x8B4513; // Brown decorative elements // Gentle bob animation tween(pageDecor, { y: pageDecor.y - 20, rotation: 0.1 }, { duration: 4000 + i * 300, loop: true, yoyo: true, easing: tween.easeInOut }); } // Button interaction with book opening effects self.down = function (x, y, obj) { // Check if start button area was clicked if (x >= 724 && x <= 1324 && y >= 1650 && y <= 1950) { // Create page turning effect var pageFlip = self.attachAsset('pathSelector', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 32, scaleY: 42 }); pageFlip.alpha = 0.8; pageFlip.tint = 0xFFFFFF; // White page turning // Animate page turning tween(pageFlip, { scaleX: 0, alpha: 0 }, { duration: 600, easing: tween.easeInOut, onFinish: function onFinish() { pageFlip.destroy(); } }); // Button press animation tween(buttonContainer, { scaleX: 0.95, scaleY: 0.95 }, { duration: 150, yoyo: true, onFinish: function onFinish() { self.startGame(); } }); } }; // No update method needed for static book design self.update = function () { // Static book design - minimal animations only }; self.startGame = function () { // Create magical sparkles when opening the tome for (var i = 0; i < 20; i++) { var sparkle = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + (Math.random() - 0.5) * 400, y: 1800 + (Math.random() - 0.5) * 200, scaleX: 0.3, scaleY: 0.3 }); sparkle.alpha = 1; sparkle.tint = [0xFFD700, 0xFFFFFF, 0xDAA520][i % 3]; var angle = Math.PI * 2 / 20 * i; var speed = 5 + Math.random() * 10; tween(sparkle, { x: sparkle.x + Math.cos(angle) * speed * 30, y: sparkle.y + Math.sin(angle) * speed * 30, scaleX: 0, scaleY: 0, alpha: 0, rotation: Math.PI * 2 }, { duration: 1200, easing: tween.easeOut, onFinish: function onFinish() { sparkle.destroy(); } }); } // Fade out menu like closing a book tween(self, { alpha: 0, scaleY: 0.1 // Collapse like closing book }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { self.visible = false; self.alpha = 1; self.scaleY = 1; } }); gameStarted = true; // Show all game elements with fade in castle.visible = true; castle.alpha = 0; tween(castle, { alpha: 1 }, { duration: 1000, easing: tween.easeOut }); wizard.visible = true; wizard.alpha = 0; tween(wizard, { alpha: 1 }, { duration: 1000, delay: 300, easing: tween.easeOut }); for (var i = 0; i < paths.length; i++) { paths[i].visible = true; } // Show all stone path segments with staggered animation for (var i = 0; i < game.children.length; i++) { var child = game.children[i]; if (child.pathIndex !== undefined && child !== paths[child.pathIndex]) { child.visible = true; var originalAlpha = child.alpha; child.alpha = 0; tween(child, { alpha: originalAlpha }, { duration: 500, delay: Math.random() * 500, easing: tween.easeOut }); } } coinText.visible = true; killCountText.visible = true; tapText.visible = true; healthBarBg.visible = true; healthBar.visible = true; healthText.visible = true; // Start medieval music LK.playMusic('medievalTheme'); }; return self; }); var Golem = Container.expand(function () { var self = Container.call(this); var golemGraphics = self.attachAsset('golem', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.8, scaleY: 1.8 }); // Create invisible larger hitbox for better collision detection var golemHitbox = self.attachAsset('golem', { anchorX: 0.5, anchorY: 1.0, scaleX: 5.0, // Much larger than visible golem scaleY: 5.0 }); golemHitbox.alpha = 0; // Make hitbox invisible golemHitbox.tint = 0xFF0000; // Red tint (invisible anyway) self.health = 200; self.maxHealth = 200; self.speed = 4; self.hitsToKill = 4; self.hitsTaken = 0; // Note: health, maxHealth and speed will be overridden by difficulty system self.lastX = 0; self.update = function () { // Progressive speed increase - increase speed by 150% over 10 seconds if (!self.speedTweenStarted) { self.speedTweenStarted = true; var targetSpeed = self.speed * 2.0; // Increase speed by 100% tween(self, { speed: targetSpeed }, { duration: 12000, // 12 seconds easing: tween.easeOut }); } // Move along the assigned path toward the wizard if (wizard && self.pathAngle !== undefined) { // Move along the path direction toward the wizard var moveX = -Math.cos(self.pathAngle) * self.speed; var moveY = -Math.sin(self.pathAngle) * self.speed; self.x += moveX; self.y += moveY; } else if (wizard) { // Fallback: move directly toward the wizard if no path assigned var dx = wizard.x - self.x; var dy = wizard.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { // Normalize direction and apply speed self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } } else { // Fallback: move down if knight doesn't exist self.y += self.speed; } }; self.takeDamage = function (damage) { self.health -= damage; self.hitsTaken++; // Flash red when hit LK.effects.flashObject(self, 0xFF0000, 200); // Golems need 4 hits to die if (self.hitsTaken >= self.hitsToKill) { self.die(); } }; self.down = function (x, y, obj) { // Create projectile from wizard to golem when golem is tapped if (wizard && projectiles.length < 10) { // Limit projectiles to prevent spam var projectile = game.addChild(new Projectile()); projectile.x = wizard.x; projectile.y = wizard.y; // Calculate direction from wizard to golem var dx = self.x - wizard.x; var dy = self.y - wizard.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { projectile.direction.x = dx / distance; projectile.direction.y = dy / distance; } projectiles.push(projectile); LK.getSound('spellCast').play(); } }; self.die = function () { // Play pain sound when golem dies LK.getSound('painSound').play(); // Drop coin var coin = game.addChild(new Coin()); coin.x = self.x; coin.y = self.y - 50; coin.isAnimating = true; coins.push(coin); // Animate coin moving toward coin counter var coinTargetX = 120 + coinText.width / 2; var coinTargetY = 90 + coinText.height / 2; tween(coin, { x: coinTargetX, y: coinTargetY, scaleX: 0.5, scaleY: 0.5 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { // Increment coin counter after animation coinCounter++; coinText.setText('Coins: ' + coinCounter); // Remove coin from array and destroy for (var i = coins.length - 1; i >= 0; i--) { if (coins[i] === coin) { coins.splice(i, 1); break; } } coin.destroy(); } }); // Increment enemy kill counter enemyKillCounter++; killCountText.setText('Puntuacion: ' + enemyKillCounter); // Add experience to wizard wizard.gainExperience(25); // Remove from golems array for (var i = golems.length - 1; i >= 0; i--) { if (golems[i] === self) { golems.splice(i, 1); break; } } self.destroy(); LK.setScore(LK.getScore() + 20); }; return self; }); var Ogre = Container.expand(function () { var self = Container.call(this); var ogreGraphics = self.attachAsset('ogre', { anchorX: 0.5, anchorY: 1.0, scaleX: 1.5, scaleY: 1.5 }); // Create invisible larger hitbox for better collision detection var ogreHitbox = self.attachAsset('ogre', { anchorX: 0.5, anchorY: 1.0, scaleX: 5.0, // Much larger than visible ogre scaleY: 5.0 }); ogreHitbox.alpha = 0; // Make hitbox invisible ogreHitbox.tint = 0xFF0000; // Red tint (invisible anyway) self.health = 100; self.maxHealth = 100; self.speed = 7; self.hitsToKill = 2; self.hitsTaken = 0; // Note: health, maxHealth and speed will be overridden by difficulty system self.lastX = 0; self.update = function () { // Progressive speed increase - increase speed by 150% over 10 seconds if (!self.speedTweenStarted) { self.speedTweenStarted = true; var targetSpeed = self.speed * 2.5; // Increase speed by 150% tween(self, { speed: targetSpeed }, { duration: 10000, // 10 seconds easing: tween.easeOut }); } // Move along the assigned path toward the wizard if (wizard && self.pathAngle !== undefined) { // Move along the path direction toward the wizard var moveX = -Math.cos(self.pathAngle) * self.speed; var moveY = -Math.sin(self.pathAngle) * self.speed; self.x += moveX; self.y += moveY; } else if (wizard) { // Fallback: move directly toward the wizard if no path assigned var dx = wizard.x - self.x; var dy = wizard.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { // Normalize direction and apply speed self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } } else { // Fallback: move down if knight doesn't exist self.y += self.speed; } }; self.takeDamage = function (damage) { self.health -= damage; self.hitsTaken++; // Flash red when hit LK.effects.flashObject(self, 0xFF0000, 200); // Ogres need 2 hits to die if (self.hitsTaken >= self.hitsToKill) { self.die(); } }; self.down = function (x, y, obj) { // Create projectile from wizard to ogre when ogre is tapped if (wizard && projectiles.length < 10) { // Limit projectiles to prevent spam var projectile = game.addChild(new Projectile()); projectile.x = wizard.x; projectile.y = wizard.y; // Calculate direction from wizard to ogre var dx = self.x - wizard.x; var dy = self.y - wizard.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { projectile.direction.x = dx / distance; projectile.direction.y = dy / distance; } projectiles.push(projectile); LK.getSound('spellCast').play(); } }; self.die = function () { // Play pain sound when ogre dies LK.getSound('painSound').play(); // Drop coin var coin = game.addChild(new Coin()); coin.x = self.x; coin.y = self.y - 50; coin.isAnimating = true; coins.push(coin); // Animate coin moving toward coin counter var coinTargetX = 120 + coinText.width / 2; var coinTargetY = 90 + coinText.height / 2; tween(coin, { x: coinTargetX, y: coinTargetY, scaleX: 0.5, scaleY: 0.5 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { // Increment coin counter after animation coinCounter++; coinText.setText('Coins: ' + coinCounter); // Remove coin from array and destroy for (var i = coins.length - 1; i >= 0; i--) { if (coins[i] === coin) { coins.splice(i, 1); break; } } coin.destroy(); } }); // Increment enemy kill counter enemyKillCounter++; killCountText.setText('Puntuacion: ' + enemyKillCounter); // Add experience to wizard wizard.gainExperience(25); // Remove from ogres array for (var i = ogres.length - 1; i >= 0; i--) { if (ogres[i] === self) { ogres.splice(i, 1); break; } } self.destroy(); LK.setScore(LK.getScore() + 15); }; return self; }); var Projectile = Container.expand(function () { var self = Container.call(this); var projectileGraphics = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 50; self.direction = { x: 0, y: 0 }; self.lastIntersecting = {}; self.update = function () { // Move projectile self.x += self.direction.x * self.speed; self.y += self.direction.y * self.speed; // Remove if off screen if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { self.removeFromGame(); return; } // Check collision with enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (!self.lastIntersecting[i]) { self.lastIntersecting[i] = false; } var currentIntersecting = self.intersects(enemy); if (!self.lastIntersecting[i] && currentIntersecting) { // Hit enemy enemy.takeDamage(50); self.removeFromGame(); return; } self.lastIntersecting[i] = currentIntersecting; } // Check collision with ogres for (var i = ogres.length - 1; i >= 0; i--) { var ogre = ogres[i]; var ogreKey = 'ogre_' + i; if (!self.lastIntersecting[ogreKey]) { self.lastIntersecting[ogreKey] = false; } var currentOgreIntersecting = self.intersects(ogre); if (!self.lastIntersecting[ogreKey] && currentOgreIntersecting) { // Hit ogre ogre.takeDamage(50); self.removeFromGame(); return; } self.lastIntersecting[ogreKey] = currentOgreIntersecting; } // Check collision with golems for (var i = golems.length - 1; i >= 0; i--) { var golem = golems[i]; var golemKey = 'golem_' + i; if (!self.lastIntersecting[golemKey]) { self.lastIntersecting[golemKey] = false; } var currentGolemIntersecting = self.intersects(golem); if (!self.lastIntersecting[golemKey] && currentGolemIntersecting) { // Hit golem golem.takeDamage(50); self.removeFromGame(); return; } self.lastIntersecting[golemKey] = currentGolemIntersecting; } }; self.removeFromGame = function () { // Remove from projectiles array for (var i = projectiles.length - 1; i >= 0; i--) { if (projectiles[i] === self) { projectiles.splice(i, 1); break; } } self.destroy(); }; return self; }); var UpgradeMenu = Container.expand(function () { var self = Container.call(this); // Set high z-index to ensure menu appears above all game elements self.zIndex = 1000; // Cooldown system for upgrade menu self.cooldownDuration = 120; // 2 seconds at 60fps self.cooldownTimer = 0; // Semi-transparent background overlay var menuBg = self.attachAsset('pathSelector', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 30, scaleY: 40 }); menuBg.alpha = 0.8; menuBg.tint = 0x4A4A4A; // Dark gray background // Title text var titleText = new Text2('UPGRADES', { size: 120, fill: 0xFFD700, font: "monospace" }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 600; self.addChild(titleText); // Upgrade options var upgradeOptions = [{ name: 'ATTACK SPEED', description: 'Faster spells' }, { name: 'SPELL POWER', description: 'More damage' }, { name: 'HEALTH BOOST', description: 'More health' }]; // Create upgrade buttons for (var i = 0; i < upgradeOptions.length; i++) { var upgrade = upgradeOptions[i]; var yPos = 1000 + i * 300; // Upgrade button background var upgradeBtn = self.attachAsset('wizard', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: yPos, scaleX: 3, scaleY: 1.5 }); upgradeBtn.upgradeIndex = i; upgradeBtn.tint = 0x8B008B; // Upgrade text var upgradeText = new Text2(upgrade.name + '\n' + upgrade.description + '\nCost: 10 coins', { size: 60, fill: 0xFFFFFF, font: "monospace" }); upgradeText.anchor.set(0.5, 0.5); upgradeText.x = 2048 / 2; upgradeText.y = yPos; self.addChild(upgradeText); } // Close button var closeBtn = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2200, scaleX: 2, scaleY: 2 }); closeBtn.tint = 0xFF0000; var closeText = new Text2('CLOSE', { size: 80, fill: 0xFFFFFF, font: "monospace" }); closeText.anchor.set(0.5, 0.5); closeText.x = 2048 / 2; closeText.y = 2200; self.addChild(closeText); // Update method for cooldown timer self.update = function () { if (self.cooldownTimer > 0) { self.cooldownTimer--; // Apply visual feedback during cooldown var cooldownAlpha = 0.3 + self.cooldownTimer / self.cooldownDuration * 0.7; self.alpha = cooldownAlpha; } else { self.alpha = 1.0; // Full opacity when cooldown is over } }; // Handle upgrade purchases self.down = function (x, y, obj) { // Check if cooldown is active if (self.cooldownTimer > 0) { // Flash red to indicate cooldown is active LK.effects.flashScreen(0xFF0000, 200); return; // Exit early if cooldown is active } // Determine which upgrade was clicked based on Y position var upgradeIndex = -1; if (y >= 850 && y <= 1150) { upgradeIndex = 0; // Attack Speed } else if (y >= 1150 && y <= 1450) { upgradeIndex = 1; // Spell Power } else if (y >= 1450 && y <= 1750) { upgradeIndex = 2; // Health Boost } // Check if upgrade button was clicked if (upgradeIndex !== -1) { if (coinCounter >= 10) { coinCounter -= 10; coinText.setText('Coins: ' + coinCounter); // Apply upgrade based on index switch (upgradeIndex) { case 0: // Attack Speed - reduce cooldown wizard.attackCooldown = Math.max(5, wizard.attackCooldown - 5); break; case 1: // Spell Power - increase damage multiplier if (!wizard.spellPowerLevel) wizard.spellPowerLevel = 0; wizard.spellPowerLevel++; break; case 2: // Health Boost wizard.maxHealth += 25; wizard.health = Math.min(wizard.health + 25, wizard.maxHealth); updateHealthBar(); break; } // Visual feedback - flash the upgrade area green LK.effects.flashScreen(0x00FF00, 300); // Close menu and resume game after successful purchase self.closeMenu(); } else { // Not enough coins - flash red LK.effects.flashScreen(0xFF0000, 300); // Close menu even when not enough coins self.closeMenu(); } } else if (y >= 2050 && y <= 2350) { // Close button area clicked self.closeMenu(); } }; self.closeMenu = function () { self.visible = false; gameStarted = true; // Resume game time LK.playMusic('medievalTheme'); }; return self; }); var Wizard = Container.expand(function () { var self = Container.call(this); var wizardGraphics = self.attachAsset('wizard', { anchorX: 0.5, anchorY: 1.0 }); self.attackCooldown = 0; self.level = 1; self.experience = 0; self.health = 100; self.maxHealth = 100; self.spellPowerLevel = 0; // Track spell power upgrades self.update = function () { if (self.attackCooldown > 0) { self.attackCooldown--; } }; self.attack = function (direction) { if (self.attackCooldown <= 0) { // Default direction if none specified if (direction === undefined) { direction = 0; // Default to center path } // Get attack angle based on path direction var attackAngle = pathAngles[direction]; var attackDistance = 100; // Calculate spell position based on attack direction var spellX = self.x + Math.cos(attackAngle) * attackDistance; var spellY = self.y + Math.sin(attackAngle) * attackDistance; // Create spell effect var spell = game.addChild(LK.getAsset('spell', { anchorX: 0.5, anchorY: 0.5, x: spellX, y: spellY, scaleX: 0.5, scaleY: 0.5 })); // Animate spell with magical effects tween(spell, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { spell.destroy(); } }); // Add rotation animation to spell tween(spell, { rotation: Math.PI * 2 }, { duration: 500, easing: tween.linear }); self.attackCooldown = 30; // 0.5 seconds at 60fps LK.getSound('spellCast').play(); // Calculate damage based on spell power upgrades var baseDamage = 50; var spellPowerMultiplier = 1 + (self.spellPowerLevel || 0) * 0.5; // 50% more damage per upgrade var totalDamage = Math.floor(baseDamage * spellPowerMultiplier); // Attack enemies in the specified direction/path for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.pathIndex === direction) { // Check if enemy is within attack range along this path var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 150) { // Attack range enemy.takeDamage(totalDamage); } } } // Attack ogres in the specified direction/path for (var i = ogres.length - 1; i >= 0; i--) { var ogre = ogres[i]; if (ogre.pathIndex === direction) { // Check if ogre is within attack range along this path var dx = ogre.x - self.x; var dy = ogre.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 150) { // Attack range ogre.takeDamage(totalDamage); } } } // Attack golems in the specified direction/path for (var i = golems.length - 1; i >= 0; i--) { var golem = golems[i]; if (golem.pathIndex === direction) { // Check if golem is within attack range along this path var dx = golem.x - self.x; var dy = golem.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 150) { // Attack range golem.takeDamage(totalDamage); } } } return true; } return false; }; self.gainExperience = function (amount) { self.experience += amount; var expNeeded = self.level * 100; if (self.experience >= expNeeded) { self.levelUp(); } }; self.levelUp = function () { self.level++; self.experience = 0; // Visual level up effect LK.effects.flashObject(self, 0xFFD700, 500); }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { self.health = 0; // Game over when health reaches 0 LK.effects.flashScreen(0xFF0000, 1000); LK.showGameOver(); } // Update health bar updateHealthBar(); // Flash red when hit LK.effects.flashObject(self, 0xFF0000, 200); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB // Celeste (sky blue) background }); /**** * Game Code ****/ // Game state variables var gameStarted = false; var gameMenu; var upgradeMenu; var upgradeMenuShown = false; var secondUpgradeMenuShown = false; // Game arrays to track objects var enemies = []; var ogres = []; var golems = []; var coins = []; var projectiles = []; // Create and show game menu gameMenu = game.addChild(new GameMenu()); // Create upgrade menu (initially hidden) upgradeMenu = game.addChild(new UpgradeMenu()); upgradeMenu.visible = false; // Create castle background var castle = game.addChild(LK.getAsset('castle', { anchorX: 0.5, anchorY: 1.0, x: 2048 / 2, y: 2732 - 200 })); castle.visible = false; // Create 5 stone paths leading toward the wizard position var paths = []; var knightX = 2048 / 2; var knightY = 2732 - 250; // Create paths: center, two diagonal, and two side paths var pathAngles = [-Math.PI / 2, // Center (straight down) -Math.PI / 4, // Diagonal right -3 * Math.PI / 4, // Diagonal left 0, // Right side (horizontal) Math.PI // Left side (horizontal) ]; // 5 paths: center, two diagonal, two sides // Create multiple stone segments for each path to form visible stone roads for (var p = 0; p < 5; p++) { var angle = pathAngles[p]; // Calculate path length - make center path longer var pathLength = p === 0 ? 3000 : 1800; // Center path is longer var segmentSize = 120; // Size of each stone segment var numSegments = Math.floor(pathLength / segmentSize); // Path-specific colors for visual distinction var pathColors = [0x8B7355, // Center path - warm brown 0x696969, // Diagonal right - dark gray 0x708090, // Diagonal left - slate gray 0x778899, // Right side - light slate gray 0x556B2F // Left side - dark olive green ]; // Create individual stone segments along the path for (var s = 0; s < numSegments; s++) { var segmentDistance = s * segmentSize + segmentSize / 2; var segmentX = knightX + Math.cos(angle) * segmentDistance; var segmentY = knightY + Math.sin(angle) * segmentDistance; // Create main stone path segment var stoneSegment = game.addChild(LK.getAsset('stonePath', { anchorX: 0.5, anchorY: 0.5, x: segmentX, y: segmentY, scaleX: 2.0 + Math.random() * 0.4, // Slight size variation scaleY: 2.0 + Math.random() * 0.4, rotation: angle + Math.PI / 2 + (Math.random() - 0.5) * 0.3 // Slight rotation variety })); // Apply path-specific coloring and transparency stoneSegment.tint = pathColors[p]; stoneSegment.alpha = 0.7 + Math.random() * 0.25; // Better transparency range stoneSegment.visible = false; stoneSegment.pathIndex = p; // Add decorative border stones for center path if (p === 0 && s % 3 === 0) { // Every 3rd segment on center path // Left border stone var leftBorder = game.addChild(LK.getAsset('stonePath', { anchorX: 0.5, anchorY: 0.5, x: segmentX + Math.cos(angle + Math.PI / 2) * 80, y: segmentY + Math.sin(angle + Math.PI / 2) * 80, scaleX: 1.2, scaleY: 1.2, rotation: angle + Math.PI / 2 })); leftBorder.tint = 0x654321; // Darker brown leftBorder.alpha = 0.8; leftBorder.visible = false; leftBorder.pathIndex = p; // Right border stone var rightBorder = game.addChild(LK.getAsset('stonePath', { anchorX: 0.5, anchorY: 0.5, x: segmentX + Math.cos(angle - Math.PI / 2) * 80, y: segmentY + Math.sin(angle - Math.PI / 2) * 80, scaleX: 1.2, scaleY: 1.2, rotation: angle + Math.PI / 2 })); rightBorder.tint = 0x654321; // Darker brown rightBorder.alpha = 0.8; rightBorder.visible = false; rightBorder.pathIndex = p; } // Add small decorative stones around main paths if (s % 4 === 1 && Math.random() > 0.6) { // Random decorative stones var decorX = segmentX + (Math.random() - 0.5) * 200; var decorY = segmentY + (Math.random() - 0.5) * 200; var decorStone = game.addChild(LK.getAsset('stonePath', { anchorX: 0.5, anchorY: 0.5, x: decorX, y: decorY, scaleX: 0.8 + Math.random() * 0.6, scaleY: 0.8 + Math.random() * 0.6, rotation: Math.random() * Math.PI * 2 })); decorStone.tint = 0x2F4F4F; // Dark slate gray decorStone.alpha = 0.4 + Math.random() * 0.3; decorStone.visible = false; decorStone.pathIndex = p; } } } // Create invisible path collision areas for touch detection for (var p = 0; p < 5; p++) { var angle = pathAngles[p]; var pathLength = p === 0 ? 3000 : 1800; var centerX = knightX + Math.cos(angle) * (pathLength / 2); var centerY = knightY + Math.sin(angle) * (pathLength / 2); // Create invisible collision path var path = game.addChild(LK.getAsset('pathSelector', { anchorX: 0.5, anchorY: 0.5, x: centerX, y: centerY, scaleX: 2, scaleY: pathLength / 60, rotation: angle + Math.PI / 2 })); // Make collision path completely invisible path.alpha = 0; path.visible = false; path.pathIndex = p; // Add touch handler for directional attacks path.down = function (x, y, obj) { // Attack in this path's direction wizard.attack(obj.pathIndex); // Visual feedback - flash all stone segments on this path for (var i = 0; i < game.children.length; i++) { var child = game.children[i]; if (child.pathIndex === obj.pathIndex && child !== obj) { LK.effects.flashObject(child, 0xFFFFFF, 300); } } }; paths.push(path); } // Create wizard var wizard = game.addChild(new Wizard()); wizard.x = knightX; wizard.y = knightY; wizard.visible = false; // UI Elements // Removed scoreText and levelText to eliminate stray characters in top right var coinCounter = 0; var enemyKillCounter = 0; var coinText = new Text2('Coins: 0', { size: 60, fill: 0xFFD700, font: "monospace" }); coinText.anchor.set(0, 0); LK.gui.topLeft.addChild(coinText); coinText.x = 120; coinText.y = 90; coinText.visible = false; var killCountText = new Text2('Puntuacion: 0', { size: 60, fill: 0xFF6B6B, font: "monospace" }); killCountText.anchor.set(0, 0); LK.gui.topLeft.addChild(killCountText); killCountText.x = 120; killCountText.y = 150; killCountText.visible = false; var tapText = new Text2('TAP TO CAST SPELLS!', { size: 100, fill: 0xFF6B6B, font: "monospace" }); tapText.anchor.set(0.5, 0.5); LK.gui.center.addChild(tapText); tapText.y = -200; tapText.visible = false; // Health bar UI var healthBarBg = LK.getAsset('healthBarBg', { anchorX: 0, anchorY: 0 }); LK.gui.topLeft.addChild(healthBarBg); healthBarBg.x = 120; healthBarBg.y = 20; healthBarBg.visible = false; var healthBar = LK.getAsset('healthBar', { anchorX: 0, anchorY: 0 }); LK.gui.topLeft.addChild(healthBar); healthBar.x = 120; healthBar.y = 20; healthBar.visible = false; var healthText = new Text2('Health: 100/100', { size: 50, fill: 0xFFFFFF, font: "monospace" }); healthText.anchor.set(0, 0); LK.gui.topLeft.addChild(healthText); healthText.x = 120; healthText.y = 50; healthText.visible = false; function updateHealthBar() { var healthPercent = wizard.health / wizard.maxHealth; healthBar.scaleX = healthPercent; healthText.setText('Health: ' + wizard.health + '/' + wizard.maxHealth); // Change color based on health if (healthPercent > 0.6) { healthBar.tint = 0x00ff00; // Green } else if (healthPercent > 0.3) { healthBar.tint = 0xffff00; // Yellow } else { healthBar.tint = 0xff0000; // Red } } // Enemy spawning variables var enemySpawnTimer = 0; var lastSpawnedPath = -1; // Track the last spawned path var consecutiveSpawns = 0; // Track consecutive spawns from same path // Cooldown system variables var pathLastSpawnTime = [-1, -1, -1, -1, -1]; // Track last spawn time for each path var pathConsecutiveSpawns = [0, 0, 0, 0, 0]; // Track consecutive spawns per path var pathCooldownDuration = 300; // 5 seconds at 60fps // Game input handling game.down = function (x, y, obj) { // Check if a path was tapped for directional attack var pathTapped = false; for (var p = 0; p < paths.length; p++) { var path = paths[p]; // Convert tap position to path's local coordinates var localPos = path.toLocal({ x: x, y: y }); // Check if tap is within path bounds if (Math.abs(localPos.x) < path.width / 2 && Math.abs(localPos.y) < path.height / 2) { // Attack in this path's direction wizard.attack(path.pathIndex); pathTapped = true; break; } } // No default attack - player must tap a path to attack }; // Main game update loop game.update = function () { // Sort children by z-index to ensure proper rendering order game.children.sort(function (a, b) { return (a.zIndex || 0) - (b.zIndex || 0); }); // Only update game logic if game has started if (!gameStarted) { return; } // Show upgrade menu after 12 enemies are killed if (enemyKillCounter >= 12 && !upgradeMenuShown) { upgradeMenuShown = true; upgradeMenu.visible = true; upgradeMenu.cooldownTimer = upgradeMenu.cooldownDuration; // Start 2-second cooldown gameStarted = false; // Pause game while menu is open LK.stopMusic(); // Pause music // Clear all enemies on screen when upgrade menu is shown for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; enemies.splice(i, 1); enemy.destroy(); } // Clear all ogres on screen when upgrade menu is shown for (var i = ogres.length - 1; i >= 0; i--) { var ogre = ogres[i]; ogres.splice(i, 1); ogre.destroy(); } // Clear all golems on screen when upgrade menu is shown for (var i = golems.length - 1; i >= 0; i--) { var golem = golems[i]; golems.splice(i, 1); golem.destroy(); } } // Show second upgrade menu after 40 enemies are killed if (enemyKillCounter >= 40 && !secondUpgradeMenuShown) { secondUpgradeMenuShown = true; upgradeMenu.visible = true; upgradeMenu.cooldownTimer = upgradeMenu.cooldownDuration; // Start 2-second cooldown gameStarted = false; // Pause game while menu is open LK.stopMusic(); // Pause music // Clear all enemies on screen when upgrade menu is shown for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; enemies.splice(i, 1); enemy.destroy(); } // Clear all ogres on screen when upgrade menu is shown for (var i = ogres.length - 1; i >= 0; i--) { var ogre = ogres[i]; ogres.splice(i, 1); ogre.destroy(); } // Clear all golems on screen when upgrade menu is shown for (var i = golems.length - 1; i >= 0; i--) { var golem = golems[i]; golems.splice(i, 1); golem.destroy(); } } // Reset consecutive spawns for paths that have cooled down (runs every frame) for (var pathIdx = 0; pathIdx < 5; pathIdx++) { // Check if enough time has passed since last spawn (cooldown expired) if (pathLastSpawnTime[pathIdx] !== -1 && LK.ticks - pathLastSpawnTime[pathIdx] > pathCooldownDuration) { // Reset consecutive spawns for this path due to cooldown pathConsecutiveSpawns[pathIdx] = 0; } } // Progressive difficulty system based on kills var difficultyLevel = Math.floor(enemyKillCounter / 10); // Every 10 kills increases difficulty var currentSpawnRate = Math.max(30, 90 - difficultyLevel * 8); // Faster spawning over time var enemyHealthMultiplier = 1 + difficultyLevel * 0.3; // 30% more health per difficulty level var enemySpeedMultiplier = 1 + difficultyLevel * 0.35; // 35% faster per difficulty level // Spawn enemies enemySpawnTimer++; if (enemySpawnTimer >= currentSpawnRate) { enemySpawnTimer = 0; var enemy = game.addChild(new Enemy()); // Apply difficulty scaling to enemy stats enemy.health = Math.floor(100 * enemyHealthMultiplier); enemy.maxHealth = enemy.health; enemy.speed = 3 * enemySpeedMultiplier; // Spawn enemy at a random path entrance var randomPathIndex; if (enemyKillCounter < 5) { // First 5 enemies spawn from center path only randomPathIndex = 0; // Center path } else { // After 5 enemies, spawn from any path but limit consecutive spawns with cooldown system // Build available paths list var availablePaths = []; for (var pathIdx = 0; pathIdx < 5; pathIdx++) { // If path has spawned less than 2 consecutive times, it's available if (pathConsecutiveSpawns[pathIdx] < 2) { availablePaths.push(pathIdx); } } // If no paths available, reset ALL paths to ensure balanced distribution if (availablePaths.length === 0) { // Reset all paths' consecutive spawn counters for (var pathIdx = 0; pathIdx < 5; pathIdx++) { pathConsecutiveSpawns[pathIdx] = 0; availablePaths.push(pathIdx); } } randomPathIndex = availablePaths[Math.floor(Math.random() * availablePaths.length)]; } // Update path-specific spawn tracking // Always increment consecutive spawns for the selected path pathConsecutiveSpawns[randomPathIndex]++; // Update path spawn time and global tracking pathLastSpawnTime[randomPathIndex] = LK.ticks; lastSpawnedPath = randomPathIndex; consecutiveSpawns = pathConsecutiveSpawns[randomPathIndex]; var pathAngle = pathAngles[randomPathIndex]; // Store the path information on the enemy enemy.pathIndex = randomPathIndex; enemy.pathAngle = pathAngle; // Calculate spawn position at the far end of the path (screen edge) var pathLength = randomPathIndex === 0 ? 3000 : 1800; // Match path lengths var spawnDistance = pathLength * 0.8; // Spawn farther away - 80% of path length enemy.x = knightX + Math.cos(pathAngle) * spawnDistance; enemy.y = knightY + Math.sin(pathAngle) * spawnDistance; // Make sure enemies spawn within screen bounds enemy.x = Math.max(50, Math.min(1998, enemy.x)); enemy.y = Math.max(-200, Math.min(2732 + 100, enemy.y)); enemy.lastX = enemy.x; enemies.push(enemy); } // Spawn ogres after 15 seconds (900 ticks at 60fps) if (LK.ticks >= 900 && LK.ticks % 180 === 0) { // Every 3 seconds after 15 seconds var ogre = game.addChild(new Ogre()); // Apply difficulty scaling to ogre stats ogre.health = Math.floor(150 * enemyHealthMultiplier); // Ogres have more base health ogre.maxHealth = ogre.health; ogre.speed = 2.5 * enemySpeedMultiplier; // Ogres are slightly slower // Spawn ogre at a random path entrance var ogrePathIndex = Math.floor(Math.random() * 5); var ogrePathAngle = pathAngles[ogrePathIndex]; // Store the path information on the ogre ogre.pathIndex = ogrePathIndex; ogre.pathAngle = ogrePathAngle; // Calculate spawn position at the far end of the path (screen edge) var ogrePathLength = ogrePathIndex === 0 ? 3000 : 1800; var ogreSpawnDistance = ogrePathLength * 0.8; ogre.x = knightX + Math.cos(ogrePathAngle) * ogreSpawnDistance; ogre.y = knightY + Math.sin(ogrePathAngle) * ogreSpawnDistance; // Make sure ogres spawn within screen bounds ogre.x = Math.max(50, Math.min(1998, ogre.x)); ogre.y = Math.max(-200, Math.min(2732 + 100, ogre.y)); ogre.lastX = ogre.x; ogres.push(ogre); } // Spawn golems after 30 enemies killed if (enemyKillCounter >= 30 && LK.ticks % 240 === 0) { // Every 4 seconds after 30 enemies killed var golem = game.addChild(new Golem()); // Apply difficulty scaling to golem stats golem.health = Math.floor(200 * enemyHealthMultiplier); // Golems have most base health golem.maxHealth = golem.health; golem.speed = 2 * enemySpeedMultiplier; // Golems are slowest // Spawn golem at a random path entrance var golemPathIndex = Math.floor(Math.random() * 5); var golemPathAngle = pathAngles[golemPathIndex]; // Store the path information on the golem golem.pathIndex = golemPathIndex; golem.pathAngle = golemPathAngle; // Calculate spawn position at the far end of the path (screen edge) var golemPathLength = golemPathIndex === 0 ? 3000 : 1800; var golemSpawnDistance = golemPathLength * 0.8; golem.x = knightX + Math.cos(golemPathAngle) * golemSpawnDistance; golem.y = knightY + Math.sin(golemPathAngle) * golemSpawnDistance; // Make sure golems spawn within screen bounds golem.x = Math.max(50, Math.min(1998, golem.x)); golem.y = Math.max(-200, Math.min(2732 + 100, golem.y)); golem.lastX = golem.x; golems.push(golem); } // Check enemy-knight collisions and cleanup off-screen enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; // Remove enemies that went off-screen at bottom if (enemy.y > 2732 + 100) { enemies.splice(i, 1); enemy.destroy(); continue; } // Initialize lastIntersecting if not set if (enemy.lastIntersecting === undefined) { enemy.lastIntersecting = false; } // Check for collision transition var currentIntersecting = enemy.intersects(wizard); if (!enemy.lastIntersecting && currentIntersecting) { // Damage wizard when enemy touches for the first time wizard.takeDamage(20); // Remove enemy after dealing damage enemies.splice(i, 1); enemy.destroy(); continue; } // Update last intersecting state enemy.lastIntersecting = currentIntersecting; } // Check ogre-wizard collisions and cleanup off-screen ogres for (var i = ogres.length - 1; i >= 0; i--) { var ogre = ogres[i]; // Remove ogres that went off-screen at bottom if (ogre.y > 2732 + 100) { ogres.splice(i, 1); ogre.destroy(); continue; } // Initialize lastIntersecting if not set if (ogre.lastIntersecting === undefined) { ogre.lastIntersecting = false; } // Check for collision transition var currentOgreIntersecting = ogre.intersects(wizard); if (!ogre.lastIntersecting && currentOgreIntersecting) { // Damage wizard when ogre touches for the first time wizard.takeDamage(30); // Ogres deal 30 damage // Remove ogre after dealing damage ogres.splice(i, 1); ogre.destroy(); continue; } // Update last intersecting state ogre.lastIntersecting = currentOgreIntersecting; } // Check golem-wizard collisions and cleanup off-screen golems for (var i = golems.length - 1; i >= 0; i--) { var golem = golems[i]; // Remove golems that went off-screen at bottom if (golem.y > 2732 + 100) { golems.splice(i, 1); golem.destroy(); continue; } // Initialize lastIntersecting if not set if (golem.lastIntersecting === undefined) { golem.lastIntersecting = false; } // Check for collision transition var currentGolemIntersecting = golem.intersects(wizard); if (!golem.lastIntersecting && currentGolemIntersecting) { // Damage wizard when golem touches for the first time wizard.takeDamage(40); // Golems deal 40 damage // Remove golem after dealing damage golems.splice(i, 1); golem.destroy(); continue; } // Update last intersecting state golem.lastIntersecting = currentGolemIntersecting; } // Make tap text pulse var pulse = 1 + Math.sin(LK.ticks * 0.1) * 0.2; tapText.scale.set(pulse, pulse); }; // Remove tap text after 5 seconds tween({}, {}, { duration: 5000, onFinish: function onFinish() { if (tapText && tapText.parent) { tapText.destroy(); } } });
===================================================================
--- original.js
+++ change.js
@@ -182,339 +182,455 @@
return self;
});
var GameMenu = Container.expand(function () {
var self = Container.call(this);
- // Create book background
- var bookBg = self.attachAsset('healthBarBg', {
+ // Create parchment-style book background
+ var bookBackground = self.attachAsset('pathSelector', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
- scaleX: 25,
- scaleY: 35
+ scaleX: 32,
+ scaleY: 42
});
- bookBg.tint = 0x1a0e0a; // Very dark brown background
- bookBg.alpha = 1;
- // Book cover main panel
- var bookCover = self.attachAsset('healthBarBg', {
+ bookBackground.alpha = 0.98;
+ bookBackground.tint = 0xF5DEB3; // Wheat color for parchment
+ // Create ornate book border frame
+ var outerBorder = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
- scaleX: 22,
- scaleY: 32
+ scaleX: 34,
+ scaleY: 44
});
- bookCover.tint = 0x3d2914; // Rich brown leather color
- bookCover.alpha = 1;
- // Book spine effect (center line)
- var bookSpine = self.attachAsset('healthBarBg', {
+ outerBorder.alpha = 1.0;
+ outerBorder.tint = 0x8B4513; // Dark brown leather binding
+ // Inner decorative border
+ var innerBorder = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
- scaleX: 0.5,
- scaleY: 32
+ scaleX: 30,
+ scaleY: 40
});
- bookSpine.tint = 0x2a1a0a; // Darker brown for spine
- bookSpine.alpha = 0.8;
- // Add book corner decorations
+ innerBorder.alpha = 0.8;
+ innerBorder.tint = 0xDAA520; // Goldenrod border
+ // Create corner decorations (ornate book corners)
var cornerPositions = [{
- x: 300,
- y: 300
- }, {
- x: 1748,
- y: 300
- }, {
- x: 300,
- y: 2432
- }, {
- x: 1748,
- y: 2432
- }];
+ x: 400,
+ y: 400
+ },
+ // Top left
+ {
+ x: 1648,
+ y: 400
+ },
+ // Top right
+ {
+ x: 400,
+ y: 2332
+ },
+ // Bottom left
+ {
+ x: 1648,
+ y: 2332
+ } // Bottom right
+ ];
for (var i = 0; i < cornerPositions.length; i++) {
- // Gold corner piece
- var corner = self.attachAsset('coin', {
+ var corner = self.attachAsset('spell', {
anchorX: 0.5,
anchorY: 0.5,
x: cornerPositions[i].x,
y: cornerPositions[i].y,
scaleX: 3,
scaleY: 3
});
- corner.tint = 0xD4AF37; // Antique gold
- corner.alpha = 0.9;
- // Corner ornament rotation
- var rotation = 0;
- if (i === 1) rotation = Math.PI / 2;else if (i === 2) rotation = -Math.PI / 2;else if (i === 3) rotation = Math.PI;
- corner.rotation = rotation;
+ corner.alpha = 0.7;
+ corner.tint = 0xFFD700; // Gold corner decorations
+ corner.rotation = Math.PI / 2 * i; // Rotate each corner
+ // Gentle glow animation for corners
+ tween(corner, {
+ scaleX: 3.5,
+ scaleY: 3.5,
+ alpha: 0.9
+ }, {
+ duration: 3000,
+ loop: true,
+ yoyo: true,
+ easing: tween.easeInOut
+ });
}
- // Create ornate border frame
- var borderTop = self.attachAsset('healthBar', {
- anchorX: 0.5,
- anchorY: 0.5,
- x: 2048 / 2,
- y: 400,
- scaleX: 20,
- scaleY: 0.3
+ // Create book spine decoration on left side
+ for (var i = 0; i < 12; i++) {
+ var spineDecor = self.attachAsset('stonePath', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 200,
+ y: 600 + i * 150,
+ scaleX: 0.8,
+ scaleY: 2.5
+ });
+ spineDecor.tint = 0x654321; // Dark brown spine details
+ spineDecor.alpha = 0.6;
+ spineDecor.rotation = Math.PI / 2;
+ }
+ // Add vintage paper texture with subtle aged spots
+ for (var i = 0; i < 25; i++) {
+ var ageSpot = self.attachAsset('coin', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 400 + Math.random() * 1248,
+ y: 500 + Math.random() * 1732,
+ scaleX: 0.3 + Math.random() * 0.8,
+ scaleY: 0.3 + Math.random() * 0.8
+ });
+ ageSpot.alpha = 0.1 + Math.random() * 0.15;
+ ageSpot.tint = 0x8B7355; // Brown aging spots
+ }
+ // Create illuminated manuscript-style title
+ var titleContainer = new Container();
+ titleContainer.x = 2048 / 2;
+ titleContainer.y = 700;
+ self.addChild(titleContainer);
+ // Main title with ornate medieval styling
+ var mainTitle = new Text2('WIZARD', {
+ size: 200,
+ fill: 0x8B0000,
+ font: "monospace"
});
- borderTop.tint = 0xD4AF37;
- borderTop.alpha = 0.7;
- var borderBottom = self.attachAsset('healthBar', {
- anchorX: 0.5,
- anchorY: 0.5,
- x: 2048 / 2,
- y: 2332,
- scaleX: 20,
- scaleY: 0.3
- });
- borderBottom.tint = 0xD4AF37;
- borderBottom.alpha = 0.7;
- var borderLeft = self.attachAsset('healthBar', {
- anchorX: 0.5,
- anchorY: 0.5,
- x: 400,
- y: 2732 / 2,
- scaleX: 0.3,
- scaleY: 28
- });
- borderLeft.tint = 0xD4AF37;
- borderLeft.alpha = 0.7;
- var borderRight = self.attachAsset('healthBar', {
- anchorX: 0.5,
- anchorY: 0.5,
- x: 1648,
- y: 2732 / 2,
- scaleX: 0.3,
- scaleY: 28
- });
- borderRight.tint = 0xD4AF37;
- borderRight.alpha = 0.7;
- // Create embossed title effect with gold lettering
- var titleShadow = new Text2('WIZARD\nDEFENDER', {
- size: 180,
- fill: 0x1a0e0a,
+ mainTitle.anchor.set(0.5, 0.5);
+ mainTitle.y = -50;
+ titleContainer.addChild(mainTitle);
+ // Title shadow for depth
+ var titleShadow = new Text2('WIZARD', {
+ size: 200,
+ fill: 0x000000,
font: "monospace"
});
titleShadow.anchor.set(0.5, 0.5);
- titleShadow.x = 2048 / 2 + 8;
- titleShadow.y = 808;
- self.addChild(titleShadow);
- var titleText = new Text2('WIZARD\nDEFENDER', {
+ titleShadow.x = 5;
+ titleShadow.y = -45;
+ titleShadow.alpha = 0.3;
+ titleContainer.addChildAt(titleShadow, 0);
+ var subTitle = new Text2('DEFENDER', {
size: 180,
- fill: 0xD4AF37,
+ fill: 0x8B0000,
font: "monospace"
});
- titleText.anchor.set(0.5, 0.5);
- titleText.x = 2048 / 2;
- titleText.y = 800;
- self.addChild(titleText);
- // Add subtle title animation
- tween(titleText, {
- scaleX: 1.02,
- scaleY: 1.02
- }, {
- duration: 4000,
- loop: true,
- yoyo: true,
- easing: tween.easeInOut
- });
- // Subtitle in elegant script
- var subtitle = new Text2('A Tale of Magic & Defense', {
- size: 70,
- fill: 0xC9A961,
+ subTitle.anchor.set(0.5, 0.5);
+ subTitle.y = 120;
+ titleContainer.addChild(subTitle);
+ // Subtitle shadow
+ var subTitleShadow = new Text2('DEFENDER', {
+ size: 180,
+ fill: 0x000000,
font: "monospace"
});
- subtitle.anchor.set(0.5, 0.5);
- subtitle.x = 2048 / 2;
- subtitle.y = 1050;
- subtitle.alpha = 0.9;
- self.addChild(subtitle);
- // Add wizard emblem in center
- var wizardEmblem = self.attachAsset('wizard', {
+ subTitleShadow.anchor.set(0.5, 0.5);
+ subTitleShadow.x = 5;
+ subTitleShadow.y = 125;
+ subTitleShadow.alpha = 0.3;
+ titleContainer.addChildAt(subTitleShadow, 0);
+ // Add decorative flourishes around title
+ var leftFlourish = self.attachAsset('spell', {
anchorX: 0.5,
anchorY: 0.5,
- x: 2048 / 2,
- y: 1400,
+ x: 600,
+ y: 700,
scaleX: 4,
- scaleY: 4
+ scaleY: 1.5
});
- wizardEmblem.tint = 0xD4AF37;
- wizardEmblem.alpha = 0.3;
- // Add circular frame around wizard
- var emblemFrame = self.attachAsset('pathSelector', {
+ leftFlourish.alpha = 0.5;
+ leftFlourish.tint = 0xDAA520;
+ var rightFlourish = self.attachAsset('spell', {
anchorX: 0.5,
anchorY: 0.5,
- x: 2048 / 2,
- y: 1400,
- scaleX: 5,
- scaleY: 5
+ x: 1448,
+ y: 700,
+ scaleX: 4,
+ scaleY: 1.5
});
- emblemFrame.tint = 0xD4AF37;
- emblemFrame.alpha = 0.2;
- // Rotate emblem frame slowly
- tween(emblemFrame, {
- rotation: Math.PI * 2
+ rightFlourish.alpha = 0.5;
+ rightFlourish.tint = 0xDAA520;
+ rightFlourish.scaleX = -4; // Mirror the flourish
+ // Animate title entrance with book opening effect
+ titleContainer.scaleX = 0;
+ titleContainer.scaleY = 0;
+ tween(titleContainer, {
+ scaleX: 1,
+ scaleY: 1
}, {
- duration: 20000,
- loop: true,
- easing: tween.linear
+ duration: 1200,
+ delay: 500,
+ easing: tween.elasticOut
});
- // Author text at bottom
- var authorText = new Text2('By the Archmages of FRVR', {
- size: 60,
- fill: 0xC9A961,
+ // Add subtitle describing the tome
+ var bookSubtitle = new Text2('~ A MAGICAL TOME OF DEFENSE ~', {
+ size: 70,
+ fill: 0x654321,
font: "monospace"
});
+ bookSubtitle.anchor.set(0.5, 0.5);
+ bookSubtitle.x = 2048 / 2;
+ bookSubtitle.y = 1000;
+ bookSubtitle.alpha = 0;
+ self.addChild(bookSubtitle);
+ // Fade in book subtitle
+ tween(bookSubtitle, {
+ alpha: 1
+ }, {
+ duration: 1500,
+ delay: 800,
+ easing: tween.easeOut
+ });
+ // Create author attribution like a real book
+ var authorText = new Text2('By the Ancient Order of Wizards', {
+ size: 50,
+ fill: 0x556B2F,
+ font: "monospace"
+ });
authorText.anchor.set(0.5, 0.5);
authorText.x = 2048 / 2;
- authorText.y = 1800;
- authorText.alpha = 0.8;
+ authorText.y = 1150;
+ authorText.alpha = 0;
self.addChild(authorText);
- // Start reading button styled as book clasp
- var claspBg = self.attachAsset('healthBarBg', {
+ tween(authorText, {
+ alpha: 0.8
+ }, {
+ duration: 1500,
+ delay: 1200,
+ easing: tween.easeOut
+ });
+ // Add medieval instructions in book style
+ var instructionsText = new Text2('~ Touch the Ancient Paths to Cast Spells ~\n~ Defend the Sacred Castle ~', {
+ size: 60,
+ fill: 0x2F4F4F,
+ font: "monospace"
+ });
+ instructionsText.anchor.set(0.5, 0.5);
+ instructionsText.x = 2048 / 2;
+ instructionsText.y = 1350;
+ instructionsText.alpha = 0;
+ self.addChild(instructionsText);
+ // Fade in instructions
+ tween(instructionsText, {
+ alpha: 1
+ }, {
+ duration: 1500,
+ delay: 1000,
+ easing: tween.easeOut
+ });
+ // Create ornate start button like a book clasp
+ var buttonContainer = new Container();
+ buttonContainer.x = 2048 / 2;
+ buttonContainer.y = 1800;
+ self.addChild(buttonContainer);
+ // Button ornate background (book clasp design)
+ var buttonFrame = buttonContainer.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5,
- x: 2048 / 2,
- y: 2100,
- scaleX: 4,
- scaleY: 1.5
+ x: 0,
+ y: 0,
+ scaleX: 5,
+ scaleY: 3
});
- claspBg.tint = 0x8B4513; // Saddle brown
- var claspMetal = self.attachAsset('coin', {
+ buttonFrame.tint = 0x8B4513; // Dark brown frame
+ var buttonInner = buttonContainer.attachAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5,
- x: 2048 / 2,
- y: 2100,
- scaleX: 2.5,
- scaleY: 1.2
+ x: 0,
+ y: 0,
+ scaleX: 4.5,
+ scaleY: 2.5
});
- claspMetal.tint = 0xD4AF37;
- var startText = new Text2('OPEN BOOK', {
+ buttonInner.tint = 0xDAA520; // Gold inner
+ // Decorative wizard seal in center
+ var wizardSeal = buttonContainer.attachAsset('wizard', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: -100,
+ y: 0,
+ scaleX: 2,
+ scaleY: 2
+ });
+ wizardSeal.tint = 0x4B0082; // Dark purple wizard
+ // Start text in medieval style
+ var startButtonText = new Text2('OPEN TOME', {
size: 80,
- fill: 0x1a0e0a,
+ fill: 0xF5DEB3,
font: "monospace"
});
- startText.anchor.set(0.5, 0.5);
- startText.x = 2048 / 2;
- startText.y = 2100;
- self.addChild(startText);
- // Add hover effect for clasp
- tween(claspMetal, {
- scaleX: 2.7,
- scaleY: 1.4
+ startButtonText.anchor.set(0.5, 0.5);
+ startButtonText.x = 60;
+ startButtonText.y = 0;
+ buttonContainer.addChild(startButtonText);
+ // Button entrance animation (book clasp opening)
+ buttonContainer.scaleX = 0;
+ buttonContainer.scaleY = 0;
+ tween(buttonContainer, {
+ scaleX: 1,
+ scaleY: 1
}, {
- duration: 1500,
- loop: true,
- yoyo: true,
- easing: tween.easeInOut
+ duration: 800,
+ delay: 1500,
+ easing: tween.elasticOut
});
- // Add magical sparkles around the book
- self.sparkles = [];
- for (var i = 0; i < 15; i++) {
- var sparkle = self.attachAsset('spell', {
+ // Add magical runes around the border like a medieval manuscript
+ var runePositions = [{
+ x: 300,
+ y: 300
+ }, {
+ x: 1024,
+ y: 250
+ }, {
+ x: 1748,
+ y: 300
+ }, {
+ x: 1800,
+ y: 1366
+ }, {
+ x: 1748,
+ y: 2432
+ }, {
+ x: 1024,
+ y: 2482
+ }, {
+ x: 300,
+ y: 2432
+ }, {
+ x: 248,
+ y: 1366
+ }];
+ for (var i = 0; i < runePositions.length; i++) {
+ var rune = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5,
- x: 300 + Math.random() * 1448,
- y: 300 + Math.random() * 2132,
- scaleX: 0.2,
- scaleY: 0.2
+ x: runePositions[i].x,
+ y: runePositions[i].y,
+ scaleX: 1.5,
+ scaleY: 1.5
});
- sparkle.tint = 0xFFD700;
- sparkle.alpha = 0;
- sparkle.delay = Math.random() * 3000;
- self.sparkles.push(sparkle);
- // Animate sparkle
- tween(sparkle, {
- alpha: 0.8,
- scaleX: 0.5,
- scaleY: 0.5
+ rune.alpha = 0.4;
+ rune.tint = 0x8B0000; // Dark red runes
+ rune.rotation = Math.PI / 4 * i; // Different rotation for each
+ // Slow mystical rotation
+ tween(rune, {
+ rotation: rune.rotation + Math.PI * 2
}, {
- duration: 1000,
- delay: sparkle.delay,
- yoyo: true,
+ duration: 15000 + i * 1000,
loop: true,
+ easing: tween.linear
+ });
+ }
+ // Add medieval page decoration elements
+ for (var i = 0; i < 6; i++) {
+ var pageDecor = self.attachAsset('coin', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 500 + i * 200,
+ y: 2200,
+ scaleX: 1.2,
+ scaleY: 1.8
+ });
+ pageDecor.alpha = 0.3;
+ pageDecor.tint = 0x8B4513; // Brown decorative elements
+ // Gentle bob animation
+ tween(pageDecor, {
+ y: pageDecor.y - 20,
+ rotation: 0.1
+ }, {
+ duration: 4000 + i * 300,
+ loop: true,
+ yoyo: true,
easing: tween.easeInOut
});
}
- // Page edge effect (worn edges)
- var leftEdge = self.attachAsset('healthBarBg', {
- anchorX: 0,
- anchorY: 0.5,
- x: 380,
- y: 2732 / 2,
- scaleX: 0.1,
- scaleY: 30
- });
- leftEdge.tint = 0xF5DEB3; // Wheat color for pages
- leftEdge.alpha = 0.3;
- var rightEdge = self.attachAsset('healthBarBg', {
- anchorX: 1,
- anchorY: 0.5,
- x: 1668,
- y: 2732 / 2,
- scaleX: 0.1,
- scaleY: 30
- });
- rightEdge.tint = 0xF5DEB3;
- rightEdge.alpha = 0.3;
- // Button interaction
+ // Button interaction with book opening effects
self.down = function (x, y, obj) {
- // Check if clasp/button area was clicked
- if (x >= 824 && x <= 1224 && y >= 2000 && y <= 2200) {
- // Book opening effect
- tween(bookCover, {
- scaleX: 0.1,
+ // Check if start button area was clicked
+ if (x >= 724 && x <= 1324 && y >= 1650 && y <= 1950) {
+ // Create page turning effect
+ var pageFlip = self.attachAsset('pathSelector', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 2048 / 2,
+ y: 2732 / 2,
+ scaleX: 32,
+ scaleY: 42
+ });
+ pageFlip.alpha = 0.8;
+ pageFlip.tint = 0xFFFFFF; // White page turning
+ // Animate page turning
+ tween(pageFlip, {
+ scaleX: 0,
alpha: 0
}, {
- duration: 800,
- easing: tween.easeIn
+ duration: 600,
+ easing: tween.easeInOut,
+ onFinish: function onFinish() {
+ pageFlip.destroy();
+ }
});
- tween(self, {
- rotation: 0.1
+ // Button press animation
+ tween(buttonContainer, {
+ scaleX: 0.95,
+ scaleY: 0.95
}, {
- duration: 400,
+ duration: 150,
yoyo: true,
onFinish: function onFinish() {
self.startGame();
}
});
}
};
- // Update method for sparkles
+ // No update method needed for static book design
self.update = function () {
- // Sparkles are animated via tweens, no update needed
+ // Static book design - minimal animations only
};
self.startGame = function () {
- // Page turn effect
- var pageTurn = self.attachAsset('healthBarBg', {
- anchorX: 0,
- anchorY: 0.5,
- x: 2048 / 2,
- y: 2732 / 2,
- scaleX: 0,
- scaleY: 32
- });
- pageTurn.tint = 0xF5DEB3;
- tween(pageTurn, {
- scaleX: 25,
- x: 2048
- }, {
- duration: 500,
- easing: tween.easeOut,
- onFinish: function onFinish() {
- pageTurn.destroy();
- }
- });
- // Fade out menu
+ // Create magical sparkles when opening the tome
+ for (var i = 0; i < 20; i++) {
+ var sparkle = self.attachAsset('projectile', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 2048 / 2 + (Math.random() - 0.5) * 400,
+ y: 1800 + (Math.random() - 0.5) * 200,
+ scaleX: 0.3,
+ scaleY: 0.3
+ });
+ sparkle.alpha = 1;
+ sparkle.tint = [0xFFD700, 0xFFFFFF, 0xDAA520][i % 3];
+ var angle = Math.PI * 2 / 20 * i;
+ var speed = 5 + Math.random() * 10;
+ tween(sparkle, {
+ x: sparkle.x + Math.cos(angle) * speed * 30,
+ y: sparkle.y + Math.sin(angle) * speed * 30,
+ scaleX: 0,
+ scaleY: 0,
+ alpha: 0,
+ rotation: Math.PI * 2
+ }, {
+ duration: 1200,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ sparkle.destroy();
+ }
+ });
+ }
+ // Fade out menu like closing a book
tween(self, {
- alpha: 0
+ alpha: 0,
+ scaleY: 0.1 // Collapse like closing book
}, {
- duration: 500,
- delay: 200,
- easing: tween.easeOut,
+ duration: 800,
+ easing: tween.easeInOut,
onFinish: function onFinish() {
self.visible = false;
self.alpha = 1;
+ self.scaleY = 1;
}
});
gameStarted = true;
// Show all game elements with fade in
@@ -1225,9 +1341,9 @@
/****
* Initialize Game
****/
var game = new LK.Game({
- backgroundColor: 0x800080 // Purple background
+ backgroundColor: 0x87CEEB // Celeste (sky blue) background
});
/****
* Game Code