Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
Update with: // Rotation tracking - CORRECTED VERSION if (facekit.leftEye && facekit.rightEye) { targetTilt = calculateFaceTilt() * tiltScaleFactor; // Limit rotation to ±15 degrees - DON'T convert to radians here targetTilt = Math.max(-15, Math.min(15, targetTilt)); self.rotation += (targetTilt - self.rotation) * tiltSmoothingFactor; }
User prompt
Update with: var DragonHead = Container.expand(function () { var self = Container.call(this); // Dragon sprites var head = self.attachAsset('dragonHead', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2 }); var headOpen = self.attachAsset('dragonHeadOpen', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2, alpha: 0 }); // Position tracking variables var targetX = 2048 / 2; var targetY = 2732 * 0.2; var smoothingFactor = 0.12; var prevX = null; var prevY = null; // Rotation variables var targetTilt = 0; var tiltSmoothingFactor = 0.11; var tiltScaleFactor = 0.09; // Scale tracking var scaleHistory = new Array(5).fill(2); // Start with default scale of 2 var scaleIndex = 0; self.update = function () { // Position tracking if (facekit.noseTip) { targetX = facekit.noseTip.x; targetY = facekit.noseTip.y; // Initialize previous positions if not set if (prevX === null) { prevX = targetX; prevY = targetY; } // Weighted average between previous and target position var newX = prevX * (1 - smoothingFactor) + targetX * smoothingFactor; var newY = prevY * (1 - smoothingFactor) + targetY * smoothingFactor; self.x = newX; self.y = newY; // Update previous positions prevX = newX; prevY = newY; } // Rotation tracking if (facekit.leftEye && facekit.rightEye) { targetTilt = calculateFaceTilt() * tiltScaleFactor; // Limit rotation to ±15 degrees (converting to radians) targetTilt = Math.max(-15, Math.min(15, targetTilt)) * (Math.PI / 180); self.rotation += (targetTilt - self.rotation) * tiltSmoothingFactor; } // Scale adjustment based on face size if (facekit.leftEye && facekit.rightEye) { var eyeDistance = Math.abs(facekit.rightEye.x - facekit.leftEye.x); var newScale = eyeDistance / 250; // Adjusted divisor for dragon head // Update rolling average scaleHistory[scaleIndex] = newScale; scaleIndex = (scaleIndex + 1) % scaleHistory.length; // Calculate average scale var avgScale = scaleHistory.reduce(function (a, b) { return a + b; }, 0) / scaleHistory.length; // Apply with gentle smoothing (limited range) var targetScale = Math.max(1.5, Math.min(2.5, avgScale)); head.scaleX = head.scaleX * 0.85 + targetScale * 0.15; head.scaleY = head.scaleY * 0.85 + targetScale * 0.15; headOpen.scaleX = head.scaleX; headOpen.scaleY = head.scaleY; } // Toggle dragon head assets based on mouth open state if (facekit && facekit.mouthOpen) { head.alpha = 0; headOpen.alpha = 1; } else { head.alpha = 1; headOpen.alpha = 0; } }; function calculateFaceTilt() { if (facekit.leftEye && facekit.rightEye && facekit.mouthCenter) { // Calculate midpoint between eyes var eyeMidX = (facekit.leftEye.x + facekit.rightEye.x) / 2; var eyeMidY = (facekit.leftEye.y + facekit.rightEye.y) / 2; // Calculate angle between eye midpoint and mouth, negated to fix direction var dx = facekit.mouthCenter.x - eyeMidX; var dy = facekit.mouthCenter.y - eyeMidY; var angle = -(Math.atan2(dx, dy) * (180 / Math.PI)); // Reduced angle impact return Math.max(-15, Math.min(15, angle * 0.15)); } return 0; // Default to straight when face points aren't available } return self; }); ↪💡 Consider importing and using the following plugins: @upit/facekit.v1
User prompt
Update as needed with: // First add these variables at the top of the DragonHead constructor: self.targetTilt = 0; self.tiltSmoothingFactor = 0.08; // Slightly slower than reference for extra stability self.tiltScaleFactor = 0.07; // Less extreme tilt // Then replace the existing rotation code in update() with: // Rotation tracking using eye-to-mouth relationship if (facekit.leftEye && facekit.rightEye && facekit.mouthCenter) { // Calculate midpoint between eyes var eyeMidX = (facekit.leftEye.x + facekit.rightEye.x) / 2; var eyeMidY = (facekit.leftEye.y + facekit.rightEye.y) / 2; // Calculate angle between eye midpoint and mouth var dx = facekit.mouthCenter.x - eyeMidX; var dy = facekit.mouthCenter.y - eyeMidY; var angle = -(Math.atan2(dx, dy)); // Convert to degrees for easier understanding, then scale down var angleDegrees = angle * (180 / Math.PI); self.targetTilt = (angleDegrees * self.tiltScaleFactor) * (Math.PI / 180); // Back to radians // Limit rotation (10 degrees = ~0.175 radians) self.targetTilt = Math.max(-0.175, Math.min(0.175, self.targetTilt)); // Apply rotation with smoothing self.rotation += (self.targetTilt - self.rotation) * self.tiltSmoothingFactor; } else { // Gradually return to vertical when face tracking is lost self.rotation += (0 - self.rotation) * 0.1; ↪💡 Consider importing and using the following plugins: @upit/facekit.v1
User prompt
Update with: // Completely revamped rotation handling if (facekit.leftEye && facekit.rightEye) { // Calculate angle between eyes var dx = facekit.rightEye.x - facekit.leftEye.x; var dy = facekit.rightEye.y - facekit.leftEye.y; // Get raw angle in radians var rawAngle = -Math.atan2(dy, dx); // Apply substantial deadzone - default to vertical var deadzone = 0.12; // About 7 degrees if (Math.abs(rawAngle) < deadzone) { self.targetRotation = 0; // Force vertical } else { // Apply non-linear scaling to reduce sensitivity while preserving direction var direction = Math.sign(rawAngle); var magnitude = Math.abs(rawAngle) - deadzone; var scaledMagnitude = magnitude * 0.3; // Very reduced sensitivity // Combined result with limits self.targetRotation = direction * Math.min(scaledMagnitude, 0.2); } // Apply very strong damping for stability self.rotationSmoothing = 0.05; // Slower response self.rotation += (self.targetRotation - self.rotation) * self.rotationSmoothing; } ↪💡 Consider importing and using the following plugins: @upit/facekit.v1
User prompt
Update with: // In the DragonHead class, replace the rotation calculation section with this: if (facekit.leftEye && facekit.rightEye) { // Calculate angle between eyes var dx = facekit.rightEye.x - facekit.leftEye.x; var dy = facekit.rightEye.y - facekit.leftEye.y; // Get angle in radians var rawAngle = -Math.atan2(dy, dx); // Apply deadzone for small movements (keep vertical by default) var deadzone = 0.05; // About 3 degrees if (Math.abs(rawAngle) < deadzone) { rawAngle = 0; } // Further reduce rotation sensitivity using a scale factor var scaleFactor = 0.5; // Reduce rotation amount rawAngle *= scaleFactor; // Limit rotation range self.targetRotation = Math.max(-0.25, Math.min(0.25, rawAngle)); // Apply stronger rotation damping for smoother transitions self.rotation += (self.targetRotation - self.rotation) * 0.08; } ↪💡 Consider importing and using the following plugins: @upit/facekit.v1
User prompt
Increase the speed of the field scroll by double
User prompt
Replace flyingbackground with: var FlyingBackground = Container.expand(function () { var self = Container.call(this); // Create a bottom container for field elements (will be rendered first/behind) self.bottomContainer = new Container(); self.addChild(self.bottomContainer); // Store the horizon line self.horizonY = 2732 / 2; // Create field background panels for scrolling self.fieldPanels = []; for (var i = 0; i < 3; i++) { var fieldPanel = self.bottomContainer.attachAsset('fieldBackground', { anchorX: 0.5, anchorY: 0, x: 2048 / 2, y: self.horizonY + (i * 1696) }); self.fieldPanels.push(fieldPanel); } // Create a top container (will be rendered last/in front) self.topContainer = new Container(); self.addChild(self.topContainer); // Create sky background in top container var sky = self.topContainer.attachAsset('skyBackground', { anchorX: 0.5, anchorY: 1.0, x: 2048 / 2, y: self.horizonY }); // Field scroll speed self.scrollSpeed = 2; // Create clouds self.clouds = []; for (var i = 0; i < 8; i++) { // Start clouds with larger scale farther from horizon var startY = self.horizonY - 400 - Math.random() * 600; var distanceFromHorizon = Math.abs(startY - self.horizonY); var startScale = 0.5 + distanceFromHorizon / 800; var cloud = self.topContainer.attachAsset('cloudShape', { anchorX: 0.5, anchorY: 0.5, x: Math.random() * 2048, y: startY, alpha: 0.8, scaleX: startScale, scaleY: startScale * 0.8 }); // Store with motion properties self.clouds.push({ sprite: cloud, speedY: 1 + Math.random() * 2, speedX: (Math.random() - 0.5) * 1.5, // Slight side-to-side drift targetY: self.horizonY }); } // Create field elements self.fieldElements = []; for (var j = 0; j < 12; j++) { // Start field elements with larger scale farther from horizon var fieldStartY = self.horizonY + 400 + Math.random() * 800; var fieldDistanceFromHorizon = Math.abs(fieldStartY - self.horizonY); var fieldStartScale = 0.5 + fieldDistanceFromHorizon / 1000; var fieldElement = self.bottomContainer.attachAsset('fieldElement', { anchorX: 0.5, anchorY: 0.5, x: Math.random() * 2048, y: fieldStartY, scaleX: fieldStartScale, scaleY: fieldStartScale * 0.8 }); // Store with motion properties self.fieldElements.push({ sprite: fieldElement, speedY: 2 + Math.random() * 3, speedX: (Math.random() - 0.5) * 3, // More side-to-side movement for field elements targetY: self.horizonY }); } self.update = function () { // Scroll field panels for (var p = 0; p < self.fieldPanels.length; p++) { var panel = self.fieldPanels[p]; panel.y -= self.scrollSpeed; // If a panel scrolls completely above the horizon, reset it to the bottom if (panel.y + 1696 < self.horizonY) { // Find the lowest panel var lowestY = self.horizonY; for (var k = 0; k < self.fieldPanels.length; k++) { if (self.fieldPanels[k].y > lowestY) { lowestY = self.fieldPanels[k].y; } } // Place this panel below the lowest one panel.y = lowestY + 1696; } } // Update clouds for (var i = 0; i < self.clouds.length; i++) { var cloud = self.clouds[i]; // Move cloud toward horizon cloud.sprite.y += cloud.speedY; cloud.sprite.x += cloud.speedX; // Calculate scale based on distance from horizon var distanceFactor = Math.max(0.05, (cloud.sprite.y - self.horizonY) / -500); cloud.sprite.scaleX = distanceFactor; cloud.sprite.scaleY = distanceFactor * 0.8; // Adjust alpha for fade effect near horizon cloud.sprite.alpha = Math.min(0.9, distanceFactor); // Reset cloud if it reaches horizon or gets too small if (cloud.sprite.y >= self.horizonY - 10 || cloud.sprite.scaleX < 0.1) { cloud.sprite.y = self.horizonY - 800 - Math.random() * 400; cloud.sprite.x = Math.random() * 2048; var newDistanceFactor = (cloud.sprite.y - self.horizonY) / -500; cloud.sprite.scaleX = newDistanceFactor; cloud.sprite.scaleY = newDistanceFactor * 0.8; cloud.sprite.alpha = 0.8; } } // Update field elements for (var j = 0; j < self.fieldElements.length; j++) { var element = self.fieldElements[j]; // Move field element toward horizon element.sprite.y -= element.speedY; element.sprite.x += element.speedX; // Calculate scale based on distance from horizon var fieldDistanceFactor = Math.max(0.05, (element.sprite.y - self.horizonY) / 500); element.sprite.scaleX = fieldDistanceFactor; element.sprite.scaleY = fieldDistanceFactor * 0.8; // Adjust alpha for fade effect near horizon element.sprite.alpha = Math.min(0.9, fieldDistanceFactor); // Reset field element if it reaches horizon or goes off screen if (element.sprite.y <= self.horizonY + 10 || element.sprite.scaleX < 0.1 || element.sprite.x < -50 || element.sprite.x > 2048 + 50) { element.sprite.y = self.horizonY + 800 + Math.random() * 400; element.sprite.x = Math.random() * 2048; var newFieldDistanceFactor = (element.sprite.y - self.horizonY) / 500; element.sprite.scaleX = newFieldDistanceFactor; element.sprite.scaleY = newFieldDistanceFactor * 0.8; element.sprite.alpha = 0.9; } } }; return self; });
User prompt
Update the existing flyingbackground class as needed with: var FlyingBackground = Container.expand(function () { var self = Container.call(this); // Create a bottom container for field elements (will be rendered first/behind) self.bottomContainer = new Container(); self.addChild(self.bottomContainer); // Store the horizon line self.horizonY = 2732 / 2; // Create field background panels for scrolling self.fieldPanels = []; for (var i = 0; i < 3; i++) { var fieldPanel = self.bottomContainer.attachAsset('fieldBackground', { anchorX: 0.5, anchorY: 0, x: 2048 / 2, y: self.horizonY + (i * 1696) }); self.fieldPanels.push(fieldPanel); } // Create a top container (will be rendered last/in front) self.topContainer = new Container(); self.addChild(self.topContainer); // Create sky background in top container var sky = self.topContainer.attachAsset('skyBackground', { anchorX: 0.5, anchorY: 1.0, x: 2048 / 2, y: self.horizonY }); // Field scroll speed self.scrollSpeed = 2; // [Rest of implementation for clouds and field elements...] self.update = function () { // Scroll field panels for (var p = 0; p < self.fieldPanels.length; p++) { var panel = self.fieldPanels[p]; panel.y -= self.scrollSpeed; // If a panel scrolls completely above the horizon, reset it to the bottom if (panel.y + 1696 < self.horizonY) { // Find the lowest panel var lowestY = self.horizonY; for (var k = 0; k < self.fieldPanels.length; k++) { if (self.fieldPanels[k].y > lowestY) { lowestY = self.fieldPanels[k].y; } } // Place this panel below the lowest one panel.y = lowestY + 1696; } } // [Rest of update code for clouds and field elements...] }; return self; });
User prompt
Update with: // In Enemy class, modify the activate function: self.activate = function (x, y, type) { self.type = type || 1; self.visible = true; self.toDestroy = false; // Set position from parameters self.x = x; self.y = y; // Reset scale to maximum when activated self.scaleX = 2.0; // Match maxScale from update method self.scaleY = 2.0; // Update the enemy graphic based on type var assetId = 'enemy1'; if (self.type === 2) { assetId = 'enemy2'; } else if (self.type === 3) { assetId = 'enemy3'; } // Update the existing enemy graphic or create a new one if (enemyGraphic) { enemyGraphic.destroy(); } enemyGraphic = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); // Set type-specific properties switch (self.type) { case 1: self.speed = 2; self.health = 1; break; case 2: self.speed = 1.5; self.health = 2; break; case 3: self.speed = 3; self.health = 1; break; } };
User prompt
Update with: // In the Fireball class, modify the update method: self.update = function () { if (!self.active) { return; } self.y += self.speed; // Create fire trail particles if (Math.random() < 0.3) { particlePool.spawn(self.x + (Math.random() * 40 - 20), self.y + 20); } // NEW CODE: Recycle when off screen if (self.y > 2732) { // Screen height fireballPool.recycle(self); } };
User prompt
Remove firepower and allow player to continually create fireballs
User prompt
Please fix the bug: 'ReferenceError: Can't find variable: firepower' in or related to this line: 'if (!gameActive || firepower < 10) {' Line Number: 523
User prompt
Remove the power bar and associated logic
User prompt
Update with: self.activate = function (x, y, type) { self.type = type || 1; self.visible = true; self.toDestroy = false; // Set position from parameters self.x = x; self.y = y; // Update the enemy graphic based on type var assetId = 'enemy1'; if (self.type === 2) { assetId = 'enemy2'; } else if (self.type === 3) { assetId = 'enemy3'; } // Update the existing enemy graphic or create a new one if (enemyGraphic) { enemyGraphic.destroy(); } enemyGraphic = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); // Set type-specific properties switch (self.type) { case 1: self.speed = 2; self.health = 1; break; case 2: self.speed = 1.5; self.health = 2; break; case 3: self.speed = 3; self.health = 1; break; } };
User prompt
Please fix the bug: 'TypeError: target is not an Object. (evaluating 'key in target')' in or related to this line: 'tween(enemyGraphic, {' Line Number: 195
User prompt
Please fix the bug: 'TypeError: undefined is not an object (evaluating 'e.__colorFlash_current_tick')' in or related to this line: 'LK.effects.flashObject(enemyGraphic, 0xff0000, 200);' Line Number: 173
User prompt
Update with: var Enemy = Container.expand(function (type) { var self = Container.call(this); var enemyGraphic; self.activate = function (x, y, type) { self.type = type || 1; self.visible = true; // Update graphic based on type if (enemyGraphic) { self.removeChild(enemyGraphic); } var assetId = 'enemy' + self.type; enemyGraphic = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); // Set position self.x = x; self.y = y; // Set type-specific properties switch (self.type) { case 1: self.speed = 2; self.health = 1; break; case 2: self.speed = 1.5; self.health = 2; break; case 3: self.speed = 3; self.health = 1; break; } };
User prompt
Enemy 2 and 3 are not spawning visible. Propose fix.
User prompt
Please fix the bug: 'TypeError: undefined is not an object (evaluating 'params.type')' in or related to this line: 'obj.activate(x, y, params.type);' Line Number: 421
User prompt
Analyze enemy class and object pool and fix enemy 2 and 3 not being visible.
User prompt
Only enemy 1 is being set to visible. Fix spawning.
User prompt
Analyze enemy spawning and fix
User prompt
Update with: var FireParticle = Container.expand(function () { var self = Container.call(this); var particle = self.attachAsset('fireParticle', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { self.x += self.vx; self.y += self.vy; self.age++; // Update alpha var lifePercent = self.age / self.lifespan; particle.alpha = 1 - lifePercent; // Recycle if lifetime is over OR particle is off screen if (lifePercent >= 1 || self.y < 0 || self.y > 2732 || // Screen height self.x < 0 || self.x > 2048) { // Screen width particlePool.recycle(self); } }; // Rest of the class remains the same
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); var facekit = LK.import("@upit/facekit.v1"); /**** * Classes ****/ var DragonHead = Container.expand(function () { var self = Container.call(this); var head = self.attachAsset('dragonHead', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2 }); var headOpen = self.attachAsset('dragonHeadOpen', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2, alpha: 0 }); // Position smoothing variables self.targetX = 2048 / 2; self.targetY = 2732 * 0.2; self.smoothingFactor = 0.15; // Simplified rotation variables self.currentRotation = 0; self.targetRotation = 0; self.rotationSmoothing = 0.1; self.update = function () { // Position tracking if (facekit.noseTip) { self.targetX = facekit.noseTip.x; self.targetY = facekit.noseTip.y; } // Apply position smoothing self.x += (self.targetX - self.x) * self.smoothingFactor; self.y += (self.targetY - self.y) * self.smoothingFactor; // Simplified rotation calculation directly from eye positions if (facekit.leftEye && facekit.rightEye) { // Calculate angle between eyes (simpler approach) var dx = facekit.rightEye.x - facekit.leftEye.x; var dy = facekit.rightEye.y - facekit.leftEye.y; // Get the raw angle in radians and negate it to reverse the direction var rawAngle = -Math.atan2(dy, dx); // Limit the rotation to prevent extreme angles (±0.3 radians ≈ ±17 degrees) self.targetRotation = Math.max(-0.3, Math.min(0.3, rawAngle)); // Apply rotation smoothing self.rotation += (self.targetRotation - self.rotation) * self.rotationSmoothing; // Debug output - uncomment if you have console logging // console.log("Eyes dx/dy:", dx, dy, "Target rotation:", self.targetRotation, "Current rotation:", self.rotation); } // Toggle dragon head assets based on mouth open state if (facekit && facekit.mouthOpen) { head.alpha = 0; headOpen.alpha = 1; } else { head.alpha = 1; headOpen.alpha = 0; } }; return self; }); var Enemy = Container.expand(function (type) { var self = Container.call(this); var assetId = 'enemy1'; if (type === 2) { assetId = 'enemy2'; } if (type === 3) { assetId = 'enemy3'; } self.type = type || 1; var enemyGraphic = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); // Different enemy types have different speeds and health switch (self.type) { case 1: self.speed = 2; self.health = 1; break; case 2: self.speed = 1.5; self.health = 2; break; case 3: self.speed = 3; self.health = 1; break; } self.activate = function (x, y, type) { self.type = type || 1; self.visible = true; self.toDestroy = false; // Set position from parameters self.x = x; self.y = y; // Set type-specific properties switch (self.type) { case 1: self.speed = 2; self.health = 1; break; case 2: self.speed = 1.5; self.health = 2; break; case 3: self.speed = 3; self.health = 1; break; } }; self.update = function () { self.y -= self.speed; // Enemies move up the screen toward the player // Only start scaling when actually on screen var maxDistance = 2732; // Screen height var minScale = 0.3; // Smallest size var maxScale = 2.0; // Largest size // Keep full scale until enemy is actually on screen if (self.y <= maxDistance) { var distancePercent = self.y / maxDistance; var newScale = Math.max(0.3, minScale + distancePercent * (maxScale - minScale)); // Ensure minimum scale // Apply scaling self.scaleX = newScale; self.scaleY = newScale; } else { // Keep maximum scale while off-screen self.scaleX = maxScale; self.scaleY = maxScale; } // Also ensure visibility is maintained self.visible = true; }; self.hit = function () { self.health--; if (self.health <= 0) { // Immediate visual feedback LK.effects.flashObject(enemyGraphic, 0xff0000, 200); // Play death effect and IMMEDIATELY recycle if (self.type === 1) { tween(enemyGraphic, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 500, easing: tween.easeOut }); } else if (self.type === 2) { tween(enemyGraphic, { rotation: Math.PI * 4, y: self.y + 300 }, { duration: 700, easing: tween.easeIn }); } else if (self.type === 3) { tween(enemyGraphic, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 300, easing: tween.easeOut }); } // Immediately recycle - no waiting for animation enemyPool.recycle(self); return true; } return false; }; self.deactivate = function () { self.visible = false; self.toDestroy = false; }; return self; }); var FireParticle = Container.expand(function () { var self = Container.call(this); var particle = self.attachAsset('fireParticle', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { self.x += self.vx; self.y += self.vy; self.age++; // Update alpha var lifePercent = self.age / self.lifespan; particle.alpha = 1 - lifePercent; // Recycle if lifetime is over OR particle is off screen if (lifePercent >= 1 || self.y < 0 || self.y > 2732 || // Screen height self.x < 0 || self.x > 2048) { // Screen width particlePool.recycle(self); } }; self.activate = function (x, y) { self.x = x; self.y = y; self.visible = true; self.vx = Math.random() * 4 - 2; self.vy = Math.random() * 2 + 1; self.lifespan = 20 + Math.random() * 20; self.age = 0; particle.alpha = 1; }; self.deactivate = function () { self.visible = false; }; return self; }); var Fireball = Container.expand(function () { var self = Container.call(this); var fireballGraphic = self.attachAsset('fireball', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 15; self.update = function () { if (!self.active) { return; } self.y += self.speed; // Create fire trail particles if (Math.random() < 0.3) { particlePool.spawn(self.x + (Math.random() * 40 - 20), self.y + 20); } }; self.activate = function (x, y) { self.x = x; self.y = y; self.visible = true; self.active = true; }; self.deactivate = function () { self.visible = false; self.active = false; // Remove array manipulation from here }; return self; }); var FlyingBackground = Container.expand(function () { var self = Container.call(this); // Create sky background (top half) var sky = self.attachAsset('skyBackground', { anchorX: 0.5, anchorY: 1.0, // Anchor to bottom x: 2048 / 2, y: 2732 / 2 // Place at middle of screen (horizon line) }); // Create field background (bottom half) var field = self.attachAsset('fieldBackground', { anchorX: 0.5, anchorY: 0, // Anchor to top x: 2048 / 2, y: 2732 / 2 // Place at middle of screen (horizon line) }); // Horizon line is at y = 2732/2 self.horizonY = 2732 / 2; // Create clouds self.clouds = []; for (var i = 0; i < 8; i++) { // Start clouds with larger scale farther from horizon var startY = self.horizonY - 400 - Math.random() * 600; var distanceFromHorizon = Math.abs(startY - self.horizonY); var startScale = 0.5 + distanceFromHorizon / 800; var cloud = self.attachAsset('cloudShape', { anchorX: 0.5, anchorY: 0.5, x: Math.random() * 2048, y: startY, alpha: 0.8, scaleX: startScale, scaleY: startScale * 0.8 }); // Store with motion properties self.clouds.push({ sprite: cloud, speedY: 1 + Math.random() * 2, speedX: (Math.random() - 0.5) * 1.5, // Slight side-to-side drift targetY: self.horizonY }); } // Create field elements self.fieldElements = []; for (var j = 0; j < 12; j++) { // Start field elements with larger scale farther from horizon var fieldStartY = self.horizonY + 400 + Math.random() * 800; var fieldDistanceFromHorizon = Math.abs(fieldStartY - self.horizonY); var fieldStartScale = 0.5 + fieldDistanceFromHorizon / 1000; var fieldElement = self.attachAsset('fieldElement', { anchorX: 0.5, anchorY: 0.5, x: Math.random() * 2048, y: fieldStartY, scaleX: fieldStartScale, scaleY: fieldStartScale * 0.8 }); // Store with motion properties self.fieldElements.push({ sprite: fieldElement, speedY: 2 + Math.random() * 3, speedX: (Math.random() - 0.5) * 3, // More side-to-side movement for field elements targetY: self.horizonY }); } self.update = function () { // Update clouds for (var i = 0; i < self.clouds.length; i++) { var cloud = self.clouds[i]; // Move cloud toward horizon cloud.sprite.y += cloud.speedY; cloud.sprite.x += cloud.speedX; // Calculate scale based on distance from horizon var distanceFactor = Math.max(0.05, (cloud.sprite.y - self.horizonY) / -500); cloud.sprite.scaleX = distanceFactor; cloud.sprite.scaleY = distanceFactor * 0.8; // Adjust alpha for fade effect near horizon cloud.sprite.alpha = Math.min(0.9, distanceFactor); // Reset cloud if it reaches horizon or gets too small if (cloud.sprite.y >= self.horizonY - 10 || cloud.sprite.scaleX < 0.1) { cloud.sprite.y = self.horizonY - 800 - Math.random() * 400; cloud.sprite.x = Math.random() * 2048; var newDistanceFactor = (cloud.sprite.y - self.horizonY) / -500; cloud.sprite.scaleX = newDistanceFactor; cloud.sprite.scaleY = newDistanceFactor * 0.8; cloud.sprite.alpha = 0.8; } } // Update field elements for (var j = 0; j < self.fieldElements.length; j++) { var element = self.fieldElements[j]; // Move field element toward horizon element.sprite.y -= element.speedY; element.sprite.x += element.speedX; // Calculate scale based on distance from horizon var fieldDistanceFactor = Math.max(0.05, (element.sprite.y - self.horizonY) / 500); element.sprite.scaleX = fieldDistanceFactor; element.sprite.scaleY = fieldDistanceFactor * 0.8; // Adjust alpha for fade effect near horizon element.sprite.alpha = Math.min(0.9, fieldDistanceFactor); // Reset field element if it reaches horizon or goes off screen if (element.sprite.y <= self.horizonY + 10 || element.sprite.scaleX < 0.1 || element.sprite.x < -50 || element.sprite.x > 2048 + 50) { element.sprite.y = self.horizonY + 800 + Math.random() * 400; element.sprite.x = Math.random() * 2048; var newFieldDistanceFactor = (element.sprite.y - self.horizonY) / 500; element.sprite.scaleX = newFieldDistanceFactor; element.sprite.scaleY = newFieldDistanceFactor * 0.8; element.sprite.alpha = 0.9; } } }; return self; }); var ObjectPool = Container.expand(function (ObjectClass, size) { var self = Container.call(this); var objects = []; var activeCount = 0; for (var i = 0; i < size; i++) { var obj = new ObjectClass(); obj.visible = false; obj._poolIndex = i; objects.push(obj); self.addChild(obj); } self.spawn = function (x, y, params) { if (activeCount >= objects.length) { return null; } var obj = objects[activeCount]; activeCount++; // Increment AFTER getting object obj.visible = true; obj.activate(x, y, params); return obj; }; self.recycle = function (obj) { if (!obj || obj._poolIndex >= activeCount) { return; } // Already recycled activeCount--; // Decrement count // Swap with last active object if needed if (obj._poolIndex < activeCount) { var temp = objects[activeCount]; objects[activeCount] = obj; objects[obj._poolIndex] = temp; // Update indices temp._poolIndex = obj._poolIndex; obj._poolIndex = activeCount; } obj.deactivate(); obj.visible = false; }; self.update = function () { for (var i = 0; i < activeCount; i++) { objects[i].update(); } }; self.getActiveObjects = function () { return objects.slice(0, activeCount); }; return self; }); var PowerBar = Container.expand(function () { var self = Container.call(this); // Background bar var background = self.attachAsset('powerBarBg', { anchorX: 0.5, anchorY: 0.5 }); // Foreground bar (showing power level) var bar = self.attachAsset('powerBar', { anchorX: 0, anchorY: 0.5, x: -250 }); self.maxWidth = 500; self.setPower = function (percent) { var newWidth = self.maxWidth * percent; bar.width = Math.max(0, Math.min(newWidth, self.maxWidth)); // Change color based on power level if (percent < 0.3) { bar.tint = 0xe74c3c; // Red when low } else if (percent < 0.6) { bar.tint = 0xf39c12; // Orange when medium } else { bar.tint = 0x2ecc71; // Green when high } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ function processCollisions() { var fireballs = fireballPool.getActiveObjects(); var enemies = enemyPool.getActiveObjects(); for (var i = 0; i < fireballs.length; i++) { var fireball = fireballs[i]; for (var j = 0; j < enemies.length; j++) { var enemy = enemies[j]; var dx = fireball.x - enemy.x; var dy = fireball.y - enemy.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 100 * enemy.scaleX) { // Adjusted collision radius if (enemy.hit()) { score += enemy.type * 10; scoreTxt.setText(score); LK.setScore(score); LK.getSound('enemyDefeat').play(); } fireballPool.recycle(fireball); break; } } } } // Set dark blue background for sky effect game.setBackgroundColor(0x2c3e50); // Game state variables var score = 0; var fireballPool = new ObjectPool(Fireball, 100); var particlePool = new ObjectPool(FireParticle, 400); var enemyPool = new ObjectPool(Enemy, 50); var firepower = 100; var maxFirepower = 100; var firepowerRechargeRate = 0.5; var firepowerUseRate = 2; var gameActive = true; var isFiring = false; var lastFireTime = 0; var fireRate = 150; // ms between fireballs var enemySpawnRate = 60; // Frames between enemy spawns var difficultyScaling = 0; var flyingBackground = new FlyingBackground(); game.addChild(flyingBackground); // Create dragon head (player character) var dragon = game.addChild(new DragonHead()); dragon.x = 2048 / 2; dragon.y = 2732 * 0.2; // Place dragon at top fifth of screen game.addChild(fireballPool); game.addChild(particlePool); game.addChild(enemyPool); // Create power bar var powerBar = new PowerBar(); powerBar.x = 2048 / 2; powerBar.y = 150; LK.gui.top.addChild(powerBar); // Score display var scoreTxt = new Text2('0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); scoreTxt.y = 50; LK.gui.top.addChild(scoreTxt); // Create a function to add fire particles function createFireParticle(x, y) { particlePool.spawn(x, y); } // Function to spawn a fireball function spawnFireball() { if (!gameActive || firepower < 10) { return; } var now = Date.now(); if (now - lastFireTime < fireRate) { return; } lastFireTime = now; // Use the new pool's spawn method var fireball = fireballPool.spawn(dragon.x, dragon.y + 50); // Use firepower firepower -= firepowerUseRate; powerBar.setPower(firepower / maxFirepower); // Play sound LK.getSound('firebreathSound').play(); } // Function to spawn enemies function spawnEnemy() { if (!gameActive) { return; } var type = Math.floor(Math.random() * 3) + 1; var enemy = enemyPool.spawn(Math.random() * (2048 - 200) + 100, // x position 2732 + 100, // y position type // additional parameter (enemy type) ); // Add this check if (enemy) { enemy.visible = true; // Force visibility } } // Game update logic game.update = function () { if (!gameActive) { return; } // Check if mouth is open for fire breathing if (facekit && facekit.mouthOpen) { isFiring = true; spawnFireball(); } else { isFiring = false; } // Recharge firepower when not firing if (!isFiring && firepower < maxFirepower) { firepower += firepowerRechargeRate; powerBar.setPower(firepower / maxFirepower); } // Spawn enemies at a constant rate if (LK.ticks % enemySpawnRate === 0) { spawnEnemy(); } // Update all pools fireballPool.update(); enemyPool.update(); particlePool.update(); // Process collisions processCollisions(); }; // Start background music LK.playMusic('gameMusic', { fade: { start: 0, end: 0.3, duration: 1000 } });
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
var DragonHead = Container.expand(function () {
var self = Container.call(this);
var head = self.attachAsset('dragonHead', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2
});
var headOpen = self.attachAsset('dragonHeadOpen', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2,
alpha: 0
});
// Position smoothing variables
self.targetX = 2048 / 2;
self.targetY = 2732 * 0.2;
self.smoothingFactor = 0.15;
// Simplified rotation variables
self.currentRotation = 0;
self.targetRotation = 0;
self.rotationSmoothing = 0.1;
self.update = function () {
// Position tracking
if (facekit.noseTip) {
self.targetX = facekit.noseTip.x;
self.targetY = facekit.noseTip.y;
}
// Apply position smoothing
self.x += (self.targetX - self.x) * self.smoothingFactor;
self.y += (self.targetY - self.y) * self.smoothingFactor;
// Simplified rotation calculation directly from eye positions
if (facekit.leftEye && facekit.rightEye) {
// Calculate angle between eyes (simpler approach)
var dx = facekit.rightEye.x - facekit.leftEye.x;
var dy = facekit.rightEye.y - facekit.leftEye.y;
// Get the raw angle in radians and negate it to reverse the direction
var rawAngle = -Math.atan2(dy, dx);
// Limit the rotation to prevent extreme angles (±0.3 radians ≈ ±17 degrees)
self.targetRotation = Math.max(-0.3, Math.min(0.3, rawAngle));
// Apply rotation smoothing
self.rotation += (self.targetRotation - self.rotation) * self.rotationSmoothing;
// Debug output - uncomment if you have console logging
// console.log("Eyes dx/dy:", dx, dy, "Target rotation:", self.targetRotation, "Current rotation:", self.rotation);
}
// Toggle dragon head assets based on mouth open state
if (facekit && facekit.mouthOpen) {
head.alpha = 0;
headOpen.alpha = 1;
} else {
head.alpha = 1;
headOpen.alpha = 0;
}
};
return self;
});
var Enemy = Container.expand(function (type) {
var self = Container.call(this);
var assetId = 'enemy1';
if (type === 2) {
assetId = 'enemy2';
}
if (type === 3) {
assetId = 'enemy3';
}
self.type = type || 1;
var enemyGraphic = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Different enemy types have different speeds and health
switch (self.type) {
case 1:
self.speed = 2;
self.health = 1;
break;
case 2:
self.speed = 1.5;
self.health = 2;
break;
case 3:
self.speed = 3;
self.health = 1;
break;
}
self.activate = function (x, y, type) {
self.type = type || 1;
self.visible = true;
self.toDestroy = false;
// Set position from parameters
self.x = x;
self.y = y;
// Set type-specific properties
switch (self.type) {
case 1:
self.speed = 2;
self.health = 1;
break;
case 2:
self.speed = 1.5;
self.health = 2;
break;
case 3:
self.speed = 3;
self.health = 1;
break;
}
};
self.update = function () {
self.y -= self.speed; // Enemies move up the screen toward the player
// Only start scaling when actually on screen
var maxDistance = 2732; // Screen height
var minScale = 0.3; // Smallest size
var maxScale = 2.0; // Largest size
// Keep full scale until enemy is actually on screen
if (self.y <= maxDistance) {
var distancePercent = self.y / maxDistance;
var newScale = Math.max(0.3, minScale + distancePercent * (maxScale - minScale)); // Ensure minimum scale
// Apply scaling
self.scaleX = newScale;
self.scaleY = newScale;
} else {
// Keep maximum scale while off-screen
self.scaleX = maxScale;
self.scaleY = maxScale;
}
// Also ensure visibility is maintained
self.visible = true;
};
self.hit = function () {
self.health--;
if (self.health <= 0) {
// Immediate visual feedback
LK.effects.flashObject(enemyGraphic, 0xff0000, 200);
// Play death effect and IMMEDIATELY recycle
if (self.type === 1) {
tween(enemyGraphic, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 500,
easing: tween.easeOut
});
} else if (self.type === 2) {
tween(enemyGraphic, {
rotation: Math.PI * 4,
y: self.y + 300
}, {
duration: 700,
easing: tween.easeIn
});
} else if (self.type === 3) {
tween(enemyGraphic, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
easing: tween.easeOut
});
}
// Immediately recycle - no waiting for animation
enemyPool.recycle(self);
return true;
}
return false;
};
self.deactivate = function () {
self.visible = false;
self.toDestroy = false;
};
return self;
});
var FireParticle = Container.expand(function () {
var self = Container.call(this);
var particle = self.attachAsset('fireParticle', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
self.x += self.vx;
self.y += self.vy;
self.age++;
// Update alpha
var lifePercent = self.age / self.lifespan;
particle.alpha = 1 - lifePercent;
// Recycle if lifetime is over OR particle is off screen
if (lifePercent >= 1 || self.y < 0 || self.y > 2732 ||
// Screen height
self.x < 0 || self.x > 2048) {
// Screen width
particlePool.recycle(self);
}
};
self.activate = function (x, y) {
self.x = x;
self.y = y;
self.visible = true;
self.vx = Math.random() * 4 - 2;
self.vy = Math.random() * 2 + 1;
self.lifespan = 20 + Math.random() * 20;
self.age = 0;
particle.alpha = 1;
};
self.deactivate = function () {
self.visible = false;
};
return self;
});
var Fireball = Container.expand(function () {
var self = Container.call(this);
var fireballGraphic = self.attachAsset('fireball', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.update = function () {
if (!self.active) {
return;
}
self.y += self.speed;
// Create fire trail particles
if (Math.random() < 0.3) {
particlePool.spawn(self.x + (Math.random() * 40 - 20), self.y + 20);
}
};
self.activate = function (x, y) {
self.x = x;
self.y = y;
self.visible = true;
self.active = true;
};
self.deactivate = function () {
self.visible = false;
self.active = false;
// Remove array manipulation from here
};
return self;
});
var FlyingBackground = Container.expand(function () {
var self = Container.call(this);
// Create sky background (top half)
var sky = self.attachAsset('skyBackground', {
anchorX: 0.5,
anchorY: 1.0,
// Anchor to bottom
x: 2048 / 2,
y: 2732 / 2 // Place at middle of screen (horizon line)
});
// Create field background (bottom half)
var field = self.attachAsset('fieldBackground', {
anchorX: 0.5,
anchorY: 0,
// Anchor to top
x: 2048 / 2,
y: 2732 / 2 // Place at middle of screen (horizon line)
});
// Horizon line is at y = 2732/2
self.horizonY = 2732 / 2;
// Create clouds
self.clouds = [];
for (var i = 0; i < 8; i++) {
// Start clouds with larger scale farther from horizon
var startY = self.horizonY - 400 - Math.random() * 600;
var distanceFromHorizon = Math.abs(startY - self.horizonY);
var startScale = 0.5 + distanceFromHorizon / 800;
var cloud = self.attachAsset('cloudShape', {
anchorX: 0.5,
anchorY: 0.5,
x: Math.random() * 2048,
y: startY,
alpha: 0.8,
scaleX: startScale,
scaleY: startScale * 0.8
});
// Store with motion properties
self.clouds.push({
sprite: cloud,
speedY: 1 + Math.random() * 2,
speedX: (Math.random() - 0.5) * 1.5,
// Slight side-to-side drift
targetY: self.horizonY
});
}
// Create field elements
self.fieldElements = [];
for (var j = 0; j < 12; j++) {
// Start field elements with larger scale farther from horizon
var fieldStartY = self.horizonY + 400 + Math.random() * 800;
var fieldDistanceFromHorizon = Math.abs(fieldStartY - self.horizonY);
var fieldStartScale = 0.5 + fieldDistanceFromHorizon / 1000;
var fieldElement = self.attachAsset('fieldElement', {
anchorX: 0.5,
anchorY: 0.5,
x: Math.random() * 2048,
y: fieldStartY,
scaleX: fieldStartScale,
scaleY: fieldStartScale * 0.8
});
// Store with motion properties
self.fieldElements.push({
sprite: fieldElement,
speedY: 2 + Math.random() * 3,
speedX: (Math.random() - 0.5) * 3,
// More side-to-side movement for field elements
targetY: self.horizonY
});
}
self.update = function () {
// Update clouds
for (var i = 0; i < self.clouds.length; i++) {
var cloud = self.clouds[i];
// Move cloud toward horizon
cloud.sprite.y += cloud.speedY;
cloud.sprite.x += cloud.speedX;
// Calculate scale based on distance from horizon
var distanceFactor = Math.max(0.05, (cloud.sprite.y - self.horizonY) / -500);
cloud.sprite.scaleX = distanceFactor;
cloud.sprite.scaleY = distanceFactor * 0.8;
// Adjust alpha for fade effect near horizon
cloud.sprite.alpha = Math.min(0.9, distanceFactor);
// Reset cloud if it reaches horizon or gets too small
if (cloud.sprite.y >= self.horizonY - 10 || cloud.sprite.scaleX < 0.1) {
cloud.sprite.y = self.horizonY - 800 - Math.random() * 400;
cloud.sprite.x = Math.random() * 2048;
var newDistanceFactor = (cloud.sprite.y - self.horizonY) / -500;
cloud.sprite.scaleX = newDistanceFactor;
cloud.sprite.scaleY = newDistanceFactor * 0.8;
cloud.sprite.alpha = 0.8;
}
}
// Update field elements
for (var j = 0; j < self.fieldElements.length; j++) {
var element = self.fieldElements[j];
// Move field element toward horizon
element.sprite.y -= element.speedY;
element.sprite.x += element.speedX;
// Calculate scale based on distance from horizon
var fieldDistanceFactor = Math.max(0.05, (element.sprite.y - self.horizonY) / 500);
element.sprite.scaleX = fieldDistanceFactor;
element.sprite.scaleY = fieldDistanceFactor * 0.8;
// Adjust alpha for fade effect near horizon
element.sprite.alpha = Math.min(0.9, fieldDistanceFactor);
// Reset field element if it reaches horizon or goes off screen
if (element.sprite.y <= self.horizonY + 10 || element.sprite.scaleX < 0.1 || element.sprite.x < -50 || element.sprite.x > 2048 + 50) {
element.sprite.y = self.horizonY + 800 + Math.random() * 400;
element.sprite.x = Math.random() * 2048;
var newFieldDistanceFactor = (element.sprite.y - self.horizonY) / 500;
element.sprite.scaleX = newFieldDistanceFactor;
element.sprite.scaleY = newFieldDistanceFactor * 0.8;
element.sprite.alpha = 0.9;
}
}
};
return self;
});
var ObjectPool = Container.expand(function (ObjectClass, size) {
var self = Container.call(this);
var objects = [];
var activeCount = 0;
for (var i = 0; i < size; i++) {
var obj = new ObjectClass();
obj.visible = false;
obj._poolIndex = i;
objects.push(obj);
self.addChild(obj);
}
self.spawn = function (x, y, params) {
if (activeCount >= objects.length) {
return null;
}
var obj = objects[activeCount];
activeCount++; // Increment AFTER getting object
obj.visible = true;
obj.activate(x, y, params);
return obj;
};
self.recycle = function (obj) {
if (!obj || obj._poolIndex >= activeCount) {
return;
} // Already recycled
activeCount--; // Decrement count
// Swap with last active object if needed
if (obj._poolIndex < activeCount) {
var temp = objects[activeCount];
objects[activeCount] = obj;
objects[obj._poolIndex] = temp;
// Update indices
temp._poolIndex = obj._poolIndex;
obj._poolIndex = activeCount;
}
obj.deactivate();
obj.visible = false;
};
self.update = function () {
for (var i = 0; i < activeCount; i++) {
objects[i].update();
}
};
self.getActiveObjects = function () {
return objects.slice(0, activeCount);
};
return self;
});
var PowerBar = Container.expand(function () {
var self = Container.call(this);
// Background bar
var background = self.attachAsset('powerBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
// Foreground bar (showing power level)
var bar = self.attachAsset('powerBar', {
anchorX: 0,
anchorY: 0.5,
x: -250
});
self.maxWidth = 500;
self.setPower = function (percent) {
var newWidth = self.maxWidth * percent;
bar.width = Math.max(0, Math.min(newWidth, self.maxWidth));
// Change color based on power level
if (percent < 0.3) {
bar.tint = 0xe74c3c; // Red when low
} else if (percent < 0.6) {
bar.tint = 0xf39c12; // Orange when medium
} else {
bar.tint = 0x2ecc71; // Green when high
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
function processCollisions() {
var fireballs = fireballPool.getActiveObjects();
var enemies = enemyPool.getActiveObjects();
for (var i = 0; i < fireballs.length; i++) {
var fireball = fireballs[i];
for (var j = 0; j < enemies.length; j++) {
var enemy = enemies[j];
var dx = fireball.x - enemy.x;
var dy = fireball.y - enemy.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100 * enemy.scaleX) {
// Adjusted collision radius
if (enemy.hit()) {
score += enemy.type * 10;
scoreTxt.setText(score);
LK.setScore(score);
LK.getSound('enemyDefeat').play();
}
fireballPool.recycle(fireball);
break;
}
}
}
}
// Set dark blue background for sky effect
game.setBackgroundColor(0x2c3e50);
// Game state variables
var score = 0;
var fireballPool = new ObjectPool(Fireball, 100);
var particlePool = new ObjectPool(FireParticle, 400);
var enemyPool = new ObjectPool(Enemy, 50);
var firepower = 100;
var maxFirepower = 100;
var firepowerRechargeRate = 0.5;
var firepowerUseRate = 2;
var gameActive = true;
var isFiring = false;
var lastFireTime = 0;
var fireRate = 150; // ms between fireballs
var enemySpawnRate = 60; // Frames between enemy spawns
var difficultyScaling = 0;
var flyingBackground = new FlyingBackground();
game.addChild(flyingBackground);
// Create dragon head (player character)
var dragon = game.addChild(new DragonHead());
dragon.x = 2048 / 2;
dragon.y = 2732 * 0.2; // Place dragon at top fifth of screen
game.addChild(fireballPool);
game.addChild(particlePool);
game.addChild(enemyPool);
// Create power bar
var powerBar = new PowerBar();
powerBar.x = 2048 / 2;
powerBar.y = 150;
LK.gui.top.addChild(powerBar);
// Score display
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.y = 50;
LK.gui.top.addChild(scoreTxt);
// Create a function to add fire particles
function createFireParticle(x, y) {
particlePool.spawn(x, y);
}
// Function to spawn a fireball
function spawnFireball() {
if (!gameActive || firepower < 10) {
return;
}
var now = Date.now();
if (now - lastFireTime < fireRate) {
return;
}
lastFireTime = now;
// Use the new pool's spawn method
var fireball = fireballPool.spawn(dragon.x, dragon.y + 50);
// Use firepower
firepower -= firepowerUseRate;
powerBar.setPower(firepower / maxFirepower);
// Play sound
LK.getSound('firebreathSound').play();
}
// Function to spawn enemies
function spawnEnemy() {
if (!gameActive) {
return;
}
var type = Math.floor(Math.random() * 3) + 1;
var enemy = enemyPool.spawn(Math.random() * (2048 - 200) + 100,
// x position
2732 + 100,
// y position
type // additional parameter (enemy type)
);
// Add this check
if (enemy) {
enemy.visible = true; // Force visibility
}
}
// Game update logic
game.update = function () {
if (!gameActive) {
return;
}
// Check if mouth is open for fire breathing
if (facekit && facekit.mouthOpen) {
isFiring = true;
spawnFireball();
} else {
isFiring = false;
}
// Recharge firepower when not firing
if (!isFiring && firepower < maxFirepower) {
firepower += firepowerRechargeRate;
powerBar.setPower(firepower / maxFirepower);
}
// Spawn enemies at a constant rate
if (LK.ticks % enemySpawnRate === 0) {
spawnEnemy();
}
// Update all pools
fireballPool.update();
enemyPool.update();
particlePool.update();
// Process collisions
processCollisions();
};
// Start background music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.3,
duration: 1000
}
});
A clear blue sky background with no clouds.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
a small bush. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
a wooden arrow with red feathers and a metal arrow head. Completely vertical orientation. Cartoon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A small vertical flame. Cartoon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
a black scorch mark on the ground left by a meteor impact. cartoon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A bright spark. Cartoon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
a red heart. cartoon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
An SVG of the word **BOSS** in sharp red font.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
An SVG of the word “Start” written in fire. Cartoon.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows