User prompt
Update with: // In the Enemy initialization if (self.type === 'eyeball') { // Eyeball animations self.flyAnimation = ['eyefly1', 'eyefly2', 'eyefly3', 'eyefly4', 'eyefly5', 'eyefly6', 'eyefly7', 'eyefly8']; self.hitAnimation = ['eyedie1', 'eyedie2']; self.dieAnimation = ['eyedie3', 'eyedie4', 'eyedie5']; } else if (self.type === 'goblin') { // Goblin animations self.runAnimation = ['goblinrun1', 'goblinrun2', 'goblinrun3', 'goblinrun4', 'goblinrun5', 'goblinrun6', 'goblinrun7', 'goblinrun8']; self.hitAnimation = ['goblinhit1']; self.dieAnimation = ['goblindie1', 'goblindie2', 'goblindie3', 'goblindie4']; }
User prompt
Update with: // And in the dying animation timing: if (self.deathTimer > 200) { // Increased from 120 // Show falling animation (eyedie3) self.sprites[dieOffset].alpha = 1; } else if (self.deathTimer > 100) { // Increased from 60 // Show first impact frame (eyedie4) self.sprites[dieOffset + 1].alpha = 1; } else if (self.deathTimer > 0) { // Show final death frame (eyedie5) self.sprites[dieOffset + 2].alpha = 1; }
User prompt
Replace this section with: if (self.type === 'eyeball' && (self.isHit || self.isDying)) { // First handle the hit state if (self.isHit) { var hitOffset = self.flyAnimation.length; self.throwBackDistance += Math.abs(self.throwBackSpeed); self.x += self.throwBackSpeed; self.throwBackSpeed *= 0.95; // Alternate between first two frames during pushback var hitFrame = Math.floor(self.hitTimer / 10) % 2; self.sprites[hitOffset + hitFrame].alpha = 1; self.hitTimer--; if (self.hitTimer <= 0) { self.isHit = false; self.isDying = true; self.velocityY = 0; self.throwBackSpeed = 0; self.deathTimer = 180; // 3 seconds for full death sequence } } // Then handle the dying state else if (self.isDying) { var dieOffset = self.flyAnimation.length + self.hitAnimation.length; // Always check for ground collision during fall if (!self.isOnGround) { self.velocityY += 0.7; self.y += self.velocityY; var platformY = self.checkPlatformCollision(); if (platformY !== null) { self.y = platformY - ENEMY_PLATFORM_OFFSET; self.isOnGround = true; } } self.x -= 5; // Always match platform speed // Animation sequence logic - independent of ground detection if (self.deathTimer > 120) { // Show falling animation (eyedie3) self.sprites[dieOffset].alpha = 1; } else if (self.deathTimer > 60) { // Show first impact frame (eyedie4) self.sprites[dieOffset + 1].alpha = 1; } else if (self.deathTimer > 0) { // Show final death frame (eyedie5) self.sprites[dieOffset + 2].alpha = 1; } else { // Only fade after showing all frames self.alpha -= 0.05; } self.deathTimer--; } return; // Skip regular animation updates }
User prompt
Update with: var finalFrameIndex = dieOffset + (self.deathFrame - 3); if (finalFrameIndex < self.sprites.length) { // Safety check self.sprites[finalFrameIndex].alpha = 1; }
User prompt
Update with: if (self.type === 'eyeball') { // First add fly animations (8 frames) for (var i = 0; i < self.flyAnimation.length; i++) { var sprite = self.attachAsset(self.flyAnimation[i], { anchorX: 0.5, anchorY: 0.5 }); sprite.alpha = i === 0 ? 1 : 0; self.sprites.push(sprite); } // Then hit animations (2 frames) for (var i = 0; i < self.hitAnimation.length; i++) { var sprite = self.attachAsset(self.hitAnimation[i], { anchorX: 0.5, anchorY: 0.5 }); sprite.alpha = 0; self.sprites.push(sprite); } // Then die animations (3 frames) for (var i = 0; i < self.dieAnimation.length; i++) { var sprite = self.attachAsset(self.dieAnimation[i], { anchorX: 0.5, anchorY: 0.5 }); sprite.alpha = 0; self.sprites.push(sprite); } }
User prompt
Please fix the bug: 'TypeError: undefined is not an object (evaluating 'self.sprites[dieOffset + (self.deathFrame - 3)].alpha = 1')' in or related to this line: 'self.sprites[dieOffset + (self.deathFrame - 3)].alpha = 1;' Line Number: 346
User prompt
Update with: // When first hitting ground if (platformY !== null) { self.y = platformY - ENEMY_PLATFORM_OFFSET; self.isOnGround = true; self.groundHitTimer = 60; // 1 second for eyedie4 } // For final frame transition if (self.groundHitTimer <= 0) { self.deathFrame = 5; // Switch to eyedie5 self.finalTimer = 60; // 1 second for eyedie5 } // Only start fade after both timers if (self.finalTimer <= 0) { self.alpha -= 0.05; // Slower fade }
Code edit (3 edits merged)
Please save this source code
User prompt
Update with: if (self.type === 'eyeball' && (self.isHit || self.isDying)) { if (self.isHit) { // Handle pushback phase with eyedie1 and eyedie2 var hitOffset = self.flyAnimation.length; self.throwBackDistance += Math.abs(self.throwBackSpeed); self.x += self.throwBackSpeed; self.throwBackSpeed *= 0.95; // Alternate between first two frames during pushback var hitFrame = Math.floor(self.hitTimer / 10) % 2; self.sprites[hitOffset + hitFrame].alpha = 1; self.hitTimer--; if (self.hitTimer <= 0 || self.throwBackDistance >= self.maxThrowBack) { self.isHit = false; self.isDying = true; self.velocityY = 0; // Reset vertical velocity for falling self.throwBackSpeed = 0; // Reset throwback speed when transitioning to death self.deathTimer = 90; // Increased timer for full animation sequence } } else if (self.isDying) { var dieOffset = self.flyAnimation.length + self.hitAnimation.length; if (!self.isOnGround) { // Falling phase - show eyedie3 self.velocityY += 0.7; // Apply gravity self.y += self.velocityY; self.x -= 5; // Match platform speed while falling self.sprites[dieOffset].alpha = 1; // eyedie3 // Check for platform collision or ground level var platformY = self.checkPlatformCollision(); if (platformY !== null) { self.y = platformY - ENEMY_PLATFORM_OFFSET; self.isOnGround = true; self.deathFrame = 3; // Start at eyedie4 } } else { // Final death sequence with eyedie4 and eyedie5 self.x -= 5; // Continue matching platform speed // Slower frame progression - change every 30 frames if (self.deathTimer % 30 === 0 && self.deathFrame < 5) { self.deathFrame++; } self.sprites[dieOffset + (self.deathFrame - 3)].alpha = 1; self.deathTimer--; // Only start fading when we've shown the final frame for enough time if (self.deathTimer <= 0) { self.alpha -= 0.1; if (self.alpha <= 0) { self.destroy(); } } } } return; // Skip regular animation updates }
User prompt
Update with: if (self.type === 'eyeball' && (self.isHit || self.isDying)) { if (self.isHit) { // Handle pushback phase with eyedie1 and eyedie2 var hitOffset = self.flyAnimation.length; self.throwBackDistance += Math.abs(self.throwBackSpeed); self.x += self.throwBackSpeed; self.throwBackSpeed *= 0.95; // Alternate between first two frames during pushback var hitFrame = Math.floor(self.hitTimer / 10) % 2; self.sprites[hitOffset + hitFrame].alpha = 1; self.hitTimer--; if (self.hitTimer <= 0) { self.isHit = false; self.isDying = true; self.velocityY = 0; // Reset vertical velocity for falling self.throwBackSpeed = 0; // Reset throwback speed when transitioning to death } } else if (self.isDying) { var dieOffset = self.flyAnimation.length + self.hitAnimation.length; if (!self.isOnGround) { // Falling phase - show eyedie3 self.velocityY += 0.7; // Apply gravity self.y += self.velocityY; self.x -= 5; // Match platform speed while falling self.sprites[dieOffset].alpha = 1; // eyedie3 // Check for platform collision or ground level var platformY = self.checkPlatformCollision(); if (platformY !== null) { self.y = platformY - ENEMY_PLATFORM_OFFSET; self.isOnGround = true; self.deathTimer = 30; // Start final death sequence self.deathFrame = 3; // Start at eyedie4 } } else { // Final death sequence with eyedie4 and eyedie5 self.x -= 5; // Continue matching platform speed if (self.deathTimer % 15 === 0 && self.deathFrame < 5) { self.deathFrame++; } self.sprites[dieOffset + (self.deathFrame - 3)].alpha = 1; self.deathTimer--; if (self.deathTimer <= 0) { self.alpha -= 0.1; if (self.alpha <= 0) { self.destroy(); } } } } return; // Skip regular animation updates }
User prompt
Update as needed with: if (self.type === 'eyeball') { // Keep existing fly animations self.flyAnimation = ['eyefly1', 'eyefly2', 'eyefly3', 'eyefly4', 'eyefly5', 'eyefly6', 'eyefly7', 'eyefly8']; // Add new death animations self.hitAnimation = ['eyedie1', 'eyedie2']; self.dieAnimation = ['eyedie3', 'eyedie4', 'eyedie5']; // Pre-attach the death animation frames // Hit animation for (var i = 0; i < self.hitAnimation.length; i++) { var sprite = self.attachAsset(self.hitAnimation[i], { anchorX: 0.5, anchorY: 0.5 }); sprite.alpha = 0; self.sprites.push(sprite); } // Die animation for (var i = 0; i < self.dieAnimation.length; i++) { var sprite = self.attachAsset(self.dieAnimation[i], { anchorX: 0.5, anchorY: 0.5 }); sprite.alpha = 0; self.sprites.push(sprite); } } // Modify the update method to handle eyeball death animation if (self.type === 'eyeball' && (self.isHit || self.isDying)) { if (self.isHit) { // Handle pushback phase with eyedie1 and eyedie2 var hitOffset = self.flyAnimation.length; self.throwBackDistance += Math.abs(self.throwBackSpeed); self.x += self.throwBackSpeed; self.throwBackSpeed *= 0.95; // Alternate between first two frames during pushback var hitFrame = Math.floor(self.hitTimer / 10) % 2; self.sprites[hitOffset + hitFrame].alpha = 1; self.hitTimer--; if (self.hitTimer <= 0) { self.isHit = false; self.isDying = true; self.velocityY = 0; // Reset vertical velocity for falling } } else if (self.isDying) { var dieOffset = self.flyAnimation.length + self.hitAnimation.length; if (!self.isOnGround) { // Falling phase - show eyedie3 self.velocityY += 0.7; // Apply gravity self.y += self.velocityY; self.sprites[dieOffset].alpha = 1; // eyedie3 // Check for platform collision or ground level var platformY = self.checkPlatformCollision(); if (platformY !== null) { self.y = platformY - ENEMY_PLATFORM_OFFSET; self.isOnGround = true; self.deathTimer = 30; // Start final death sequence self.deathFrame = 3; // Start at eyedie4 } } else { // Final death sequence with eyedie4 and eyedie5 if (self.deathTimer % 15 === 0 && self.deathFrame < 5) { self.deathFrame++; } self.sprites[dieOffset + (self.deathFrame - 3)].alpha = 1; self.deathTimer--; if (self.deathTimer <= 0) { self.alpha -= 0.1; if (self.alpha <= 0) { self.destroy(); } } } } return; // Skip regular animation updates }
Code edit (8 edits merged)
Please save this source code
User prompt
Replace this section: self.update = function () { // Hide all sprites first for (var i = 0; i < self.sprites.length; i++) { self.sprites[i].alpha = 0; } if (self.type === 'eyeball') { self.x -= self.speed; // Home toward player var deltaY = player.y - self.y; self.velocityY += (deltaY > 0 ? 0.2 : -0.2); self.velocityY = Math.max(-self.maxVerticalSpeed, Math.min(self.maxVerticalSpeed, self.velocityY)); self.y += self.velocityY; // Animate self.animationCounter += self.animationSpeed; if (self.animationCounter >= 1) { self.animationCounter = 0; self.flyFrame = (self.flyFrame + 1) % self.flyAnimation.length; } self.sprites[self.flyFrame].alpha = 1; // Check if off screen if (self.x < -50) { self.destroy(); } } else { // Handle goblin movement and animations if (self.isHit) { // Handle throw back motion self.x += self.throwBackSpeed; self.throwBackDistance += Math.abs(self.throwBackSpeed); self.throwBackSpeed *= 0.95; // Slower decay than 0.9 // Show hit animation var hitOffset = self.runAnimation.length; self.sprites[hitOffset].alpha = 1; // Decrease hit timer self.hitTimer--; // Once hit timer expires, start death animation if (self.hitTimer <= 0) { self.isHit = false; self.isDying = true; self.deathTimer = 60; // Increased to 60 frames self.deathFrame = 0; // Explicitly track which frame we're on } } else if (self.isDying) { // Continue throw back during death self.x += self.throwBackSpeed; // After halfway through death animation, match platform speed if (self.deathFrame >= 2) { // Since we have 4 frames, 2 is halfway self.x -= 5; // Platform speed is defined as 5 } self.throwBackSpeed *= 0.95; // Handle death animation var dieOffset = self.runAnimation.length + self.hitAnimation.length; // Progress frame every 15 frames (60/4 frames = 15) if (self.deathTimer % 15 === 0 && self.deathFrame < self.dieAnimation.length - 1) { self.deathFrame++; } var dieOffset = self.runAnimation.length + self.hitAnimation.length; self.sprites[dieOffset + self.deathFrame].alpha = 1; // Count down death timer self.deathTimer--; // After timer expires, fade out if (self.deathTimer <= 0) { self.alpha -= 0.1; if (self.alpha <= 0) { self.destroy(); } } } else { // Original movement and animation code // Move left self.x -= self.speed; // Original platform and gravity code if (!self.isOnGround) { self.velocityY += 0.7; self.y += self.velocityY; if (!self.checkPlatformCollision()) { // Let them fall if not on platform } } if (self.currentPlatform) { var platformHalfWidth = 500; // Match the existing platform width constant var stillOnPlatform = self.x >= self.currentPlatform.x - platformHalfWidth && self.x <= self.currentPlatform.x + platformHalfWidth; if (!stillOnPlatform) { var foundAnotherPlatform = false; // Check if there's another platform we might have moved to for (var i = 0; i < platforms.length; i++) { var otherPlatform = platforms[i]; if (otherPlatform === self.currentPlatform) { continue; } if (self.x >= otherPlatform.x - platformHalfWidth && self.x <= otherPlatform.x + platformHalfWidth && Math.abs(self.y - (otherPlatform.y - ENEMY_PLATFORM_OFFSET)) < 5) { // Found another platform at the same height self.currentPlatform = otherPlatform; foundAnotherPlatform = true; break; } } // If no other platform found, start falling if (!foundAnotherPlatform) { self.isOnGround = false; self.currentPlatform = null; // Start falling with initial velocity if (self.velocityY === 0) { self.velocityY = 0.1; } } } } // Handle run animation self.animationCounter += self.animationSpeed; if (self.animationCounter >= 1) { self.animationCounter = 0; self.runFrame = (self.runFrame + 1) % self.runAnimation.length; } self.sprites[self.runFrame].alpha = 1; } // Destroy if off screen if (self.x < -50 || self.y > 2732) { self.destroy(); } } };
User prompt
Update as needed with: var Enemy = Container.expand(function (type) { var self = Container.call(this); // Enemy properties self.type = type || 'basic'; self.speed = 7; self.isOnGround = true; self.velocityY = 0; self.currentPlatform = null; self.groundY = 2732 / 1.5; // Add eyeball-specific properties self.isFlying = type === 'eyeball'; self.flyingHeight = 0; self.verticalSpeed = 2; // Speed of vertical adjustment self.maxVerticalSpeed = 4; // Maximum vertical speed // Animation properties - keep existing goblin animations self.runAnimation = []; self.runFrame = 0; self.animationSpeed = 0.08; self.animationCounter = 0; self.sprites = []; // Add eyeball animations self.flyAnimation = ['eyefly1', 'eyefly2', 'eyefly3', 'eyefly4', 'eyefly5', 'eyefly6', 'eyefly7', 'eyefly8']; self.flyFrame = 0; // Initialize sprites based on type if (self.type === 'goblin') { // Existing goblin sprite initialization // [Keep existing goblin animation code] } else if (self.type === 'eyeball') { // Initialize eyeball sprites for (var i = 0; i < self.flyAnimation.length; i++) { var sprite = self.attachAsset(self.flyAnimation[i], { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, // Scale down the 1000x1000 sprites scaleY: 0.3 }); sprite.alpha = i === 0 ? 1 : 0; self.sprites.push(sprite); } // Adjust hitbox for eyeball self.hitboxWidth = 150; self.hitboxHeight = 150; // Flying enemies don't use ground physics self.isOnGround = false; }
User prompt
Add backgroundmusic1 to the game. Fade up from 0 to 0.7
Code edit (1 edits merged)
Please save this source code
User prompt
Update with: var Torch = Container.expand(function() { var self = Container.call(this); // Create base torch sprite self.base = self.attachAsset('torch', { anchorX: 0.5, anchorY: 1 // Anchor at bottom }); // Create flame sprite self.flame = self.attachAsset('torchflame', { anchorX: 0.5, anchorY: 1, // Anchor at bottom to scale from base y: -100 // Position at top of torch }); // Create aura sprite self.aura = self.attachAsset('torchaura', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3, // Start with low opacity y: -100 // Match flame position });
Code edit (12 edits merged)
Please save this source code
User prompt
brighten the tint on the goblin enemy a little more
User prompt
update with: // In the Enemy class, where it creates the sprite animations // Add a lighter tint to all goblin sprites if (self.type === 'goblin') { // Define a light gray/white tint var lightTint = 0xDDDDDD; // This is a light gray, adjust the value to control brightness // Run animation for (var i = 0; i < self.runAnimation.length; i++) { var sprite = self.attachAsset(self.runAnimation[i], { anchorX: 0.5, anchorY: 0.5, tint: lightTint // Add the tint here }); sprite.alpha = i === 0 ? 1 : 0; self.sprites.push(sprite); } // Hit animation for (var i = 0; i < self.hitAnimation.length; i++) { var sprite = self.attachAsset(self.hitAnimation[i], { anchorX: 0.5, anchorY: 0.5, tint: lightTint // Add the tint here }); sprite.alpha = 0; self.sprites.push(sprite); } // Die animation for (var i = 0; i < self.dieAnimation.length; i++) { var sprite = self.attachAsset(self.dieAnimation[i], { anchorX: 0.5, anchorY: 0.5, tint: lightTint // Add the tint here }); sprite.alpha = 0; self.sprites.push(sprite); } }
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: ScorePopup is not defined' in or related to this line: 'var popup = new ScorePopup(self.x, self.y - 30); // Start slightly above the coin' Line Number: 73
Code edit (2 edits merged)
Please save this source code
User prompt
change score popup color to white
Code edit (1 edits merged)
Please save this source code
/**** * Classes ****/ var Coin = Container.expand(function () { var self = Container.call(this); self.sprite = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5, tint: 0xD3D3D3 // Apply lighter grey tint }); self.velocityX = 0; self.velocityY = 0; self.collected = false; self.bounceCount = 0; self.maxBounces = 2; // Replace the existing collect method in the Coin class self.collect = function () { if (!self.collected) { self.collected = true; LK.setScore(LK.getScore() + 1); scoreText.setText(LK.getScore()); // Create and add the score popup at the coin's position var popup = new ScorePopup(self.x, self.y - 30); // Start slightly above the coin game.addChild(popup); self.destroy(); } }; self.update = function () { if (self.collected) { return; } // Apply physics self.velocityY += 0.5; // gravity self.x += self.velocityX; self.y += self.velocityY; // Check for platform collision with bounce // Only bounce if we're moving downward and hit a platform if (self.velocityY > 0 && self.checkPlatformCollision()) { if (self.bounceCount < self.maxBounces) { var impactSpeed = Math.abs(self.velocityY); self.velocityY = -(impactSpeed * 0.5); // Use half of impact speed self.velocityX *= 0.8; self.bounceCount++; } else { self.velocityY = 0; self.velocityX = -5; // Match platform speed } } // Check if off screen if (self.x < -50 || self.x > 2048 + 50 || self.y > 2732) { self.destroy(); } // Player collection detection var playerBounds = player.getBounds(); var coinBounds = { left: self.x - 25, right: self.x + 25, top: self.y - 25, bottom: self.y + 25 }; if (playerBounds.left < coinBounds.right && playerBounds.right > coinBounds.left && playerBounds.top < coinBounds.bottom && playerBounds.bottom > coinBounds.top) { self.collect(); } }; self.checkPlatformCollision = function () { for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; if (Math.abs(self.y - (platform.y - 80)) < 10 && self.x > platform.x - 500 && self.x < platform.x + 500) { self.y = platform.y - 80; return true; } } return false; }; return self; }); var Enemy = Container.expand(function (type) { var self = Container.call(this); // Enemy properties self.type = type || 'basic'; self.speed = 7; self.isOnGround = true; self.velocityY = 0; self.currentPlatform = null; self.groundY = 2732 / 1.5; // Same as player ground Y self.hitAnimation = ['goblinhit1']; self.dieAnimation = ['goblindie1', 'goblindie2', 'goblindie3', 'goblindie4']; self.isHit = false; self.isDying = false; self.deathTimer = 0; self.throwBackSpeed = 15; // Initial backwards throw speed self.throwBackDistance = 0; // Track distance thrown self.maxThrowBack = 200; // Maximum throw back distance // Add bounding box properties self.hitboxWidth = 200; // Smaller than the 150px sprite width self.hitboxHeight = 260; // Adjusted for goblin height // Animation properties for goblin self.runAnimation = []; self.runFrame = 0; self.animationSpeed = 0.08; self.animationCounter = 0; self.sprites = []; // Initialize based on enemy type if (self.type === 'goblin') { // Setup all animations self.runAnimation = ['goblinrun1', 'goblinrun2', 'goblinrun3', 'goblinrun4', 'goblinrun5', 'goblinrun6', 'goblinrun7', 'goblinrun8']; // Pre-attach all animation frames // Run animation for (var i = 0; i < self.runAnimation.length; i++) { var sprite = self.attachAsset(self.runAnimation[i], { anchorX: 0.5, anchorY: 0.5 }); sprite.alpha = i === 0 ? 1 : 0; self.sprites.push(sprite); } // Hit animation for (var i = 0; i < self.hitAnimation.length; i++) { var sprite = self.attachAsset(self.hitAnimation[i], { anchorX: 0.5, anchorY: 0.5 }); sprite.alpha = 0; self.sprites.push(sprite); } // Die animation for (var i = 0; i < self.dieAnimation.length; i++) { var sprite = self.attachAsset(self.dieAnimation[i], { anchorX: 0.5, anchorY: 0.5 }); sprite.alpha = 0; self.sprites.push(sprite); } } else { // Basic enemy (original version) var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); } self.checkPlatformCollision = function () { var onAnyPlatform = false; var platformHalfWidth = 500; for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; var leftEdge = platform.x - platformHalfWidth; var rightEdge = platform.x + platformHalfWidth; // First check if we're on a platform (exact position check) if (self.x >= leftEdge && self.x <= rightEdge) { if (Math.abs(self.y - (platform.y - ENEMY_PLATFORM_OFFSET)) < 5) { onAnyPlatform = true; self.currentPlatform = platform; self.y = platform.y - ENEMY_PLATFORM_OFFSET; self.isOnGround = true; self.velocityY = 0; return true; } // NEW CODE: Check for passing through platform during fall // This detects if the enemy will cross the platform in the next frame if (self.velocityY > 0 && // Must be falling down self.y < platform.y - ENEMY_PLATFORM_OFFSET && self.y + self.velocityY >= platform.y - ENEMY_PLATFORM_OFFSET) { self.y = platform.y - ENEMY_PLATFORM_OFFSET; self.velocityY = 0; self.isOnGround = true; self.currentPlatform = platform; return true; } } } if (!onAnyPlatform) { self.isOnGround = false; self.currentPlatform = null; } return false; }; // Update collision check method self.getBounds = function () { return { left: self.x - self.hitboxWidth / 2, right: self.x + self.hitboxWidth / 2, top: self.y - self.hitboxHeight / 2, bottom: self.y + self.hitboxHeight / 2 }; }; self.hit = function () { if (!self.isHit && !self.isDying) { self.isHit = true; self.throwBackSpeed = 35; // Increased from 25 for more distance self.throwBackDistance = 0; self.hitTimer = 20; // Added hit timer for longer hit frame // Add particle effect here particleSystem.emitFromHit(self.x, self.y, player.x); } }; self.update = function () { // Hide all sprites first for (var i = 0; i < self.sprites.length; i++) { self.sprites[i].alpha = 0; } if (self.isHit) { // Handle throw back motion self.x += self.throwBackSpeed; self.throwBackDistance += Math.abs(self.throwBackSpeed); self.throwBackSpeed *= 0.95; // Slower decay than 0.9 // Show hit animation var hitOffset = self.runAnimation.length; self.sprites[hitOffset].alpha = 1; // Decrease hit timer self.hitTimer--; // Once hit timer expires, start death animation if (self.hitTimer <= 0) { self.isHit = false; self.isDying = true; self.deathTimer = 60; // Increased to 60 frames self.deathFrame = 0; // Explicitly track which frame we're on } } else if (self.isDying) { // Continue throw back during death self.x += self.throwBackSpeed; // After halfway through death animation, match platform speed if (self.deathFrame >= 2) { // Since we have 4 frames, 2 is halfway self.x -= 5; // Platform speed is defined as 5 } self.throwBackSpeed *= 0.95; // Removed vertical movement code // Handle death animation var dieOffset = self.runAnimation.length + self.hitAnimation.length; // Progress frame every 15 frames (60/4 frames = 15) if (self.deathTimer % 15 === 0 && self.deathFrame < self.dieAnimation.length - 1) { self.deathFrame++; } var dieOffset = self.runAnimation.length + self.hitAnimation.length; self.sprites[dieOffset + self.deathFrame].alpha = 1; // Count down death timer self.deathTimer--; // After timer expires, fade out if (self.deathTimer <= 0) { self.alpha -= 0.1; if (self.alpha <= 0) { self.destroy(); } } } else { // Original movement and animation code // Move left self.x -= self.speed; // Original platform and gravity code if (!self.isOnGround) { self.velocityY += 0.7; self.y += self.velocityY; if (!self.checkPlatformCollision()) { // Let them fall if not on platform } } if (self.currentPlatform) { var platformHalfWidth = 500; // Match the existing platform width constant var stillOnPlatform = self.x >= self.currentPlatform.x - platformHalfWidth && self.x <= self.currentPlatform.x + platformHalfWidth; if (!stillOnPlatform) { var foundAnotherPlatform = false; // Check if there's another platform we might have moved to for (var i = 0; i < platforms.length; i++) { var otherPlatform = platforms[i]; if (otherPlatform === self.currentPlatform) { continue; } if (self.x >= otherPlatform.x - platformHalfWidth && self.x <= otherPlatform.x + platformHalfWidth && Math.abs(self.y - (otherPlatform.y - ENEMY_PLATFORM_OFFSET)) < 5) { // Found another platform at the same height self.currentPlatform = otherPlatform; foundAnotherPlatform = true; break; } } // If no other platform found, start falling if (!foundAnotherPlatform) { self.isOnGround = false; self.currentPlatform = null; // Start falling with initial velocity if (self.velocityY === 0) { self.velocityY = 0.1; } } } } // Handle run animation if (self.type === 'goblin') { self.animationCounter += self.animationSpeed; if (self.animationCounter >= 1) { self.animationCounter = 0; self.runFrame = (self.runFrame + 1) % self.runAnimation.length; } self.sprites[self.runFrame].alpha = 1; } } // Destroy if off screen if (self.x < -50 || self.y > 2732) { self.destroy(); } }; }); var Jar = Container.expand(function () { var self = Container.call(this); // Attach jar sprite self.sprite = self.attachAsset('jar', { anchorX: 0.5, anchorY: 0.5, tint: 0xC0C0C0 // Change tint to an even lighter grey }); self.isBreaking = false; self.currentPlatform = null; self["break"] = function () { if (self.isBreaking) { return; } self.isBreaking = true; // Spawn jar pieces (keep existing piece code) for (var i = 1; i <= 4; i++) { var piece = new JarPiece(i); piece.x = self.x; piece.y = self.y; piece.velocityX = Math.random() * 10 - 5; piece.velocityY = -(Math.random() * 10 + 5); piece.rotationSpeed = Math.random() * 0.2 - 0.1; game.addChild(piece); } // Modified coin spawning with more forward motion var coinCount = Math.floor(Math.random() * 8) + 1; for (var i = 0; i < coinCount; i++) { var coin = new Coin(); coin.x = self.x; coin.y = self.y; // More forward motion and higher initial jump coin.velocityX = Math.random() * 8 + 4; // Minimum 4, maximum 12 right velocity coin.velocityY = -(Math.random() * 10 + 12); // Higher jump game.addChild(coin); coins.push(coin); } self.destroy(); }; return self; }); var JarPiece = Container.expand(function (pieceNum) { var self = Container.call(this); self.sprite = self.attachAsset('jarpiece' + pieceNum, { anchorX: 0.5, anchorY: 0.5, tint: 0xC0C0C0 // Apply grey tint }); self.velocityX = 0; self.velocityY = 0; self.rotationSpeed = 0; self.fadeSpeed = 0.02; self.bounceCount = 0; self.maxBounces = 2; // Number of bounces before stopping self.update = function () { // Apply physics self.velocityY += 0.5; // gravity self.x += self.velocityX; self.y += self.velocityY; self.rotation += self.rotationSpeed; // Check for platform collision with bounce if (self.checkPlatformCollision()) { if (self.bounceCount < self.maxBounces) { // Bounce with reduced velocity self.velocityY = -(self.velocityY * 0.4); // 40% of original velocity self.velocityX *= 0.8; // Reduce horizontal speed self.bounceCount++; } else { // Stop moving after max bounces self.velocityY = 0; self.velocityX = -5; // Match platform speed // Start fading self.alpha -= self.fadeSpeed; if (self.alpha <= 0) { self.destroy(); } } } // Destroy if off screen if (self.x < -50 || self.y > 2732) { self.destroy(); } }; self.checkPlatformCollision = function () { for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; if (Math.abs(self.y - (platform.y - 80)) < 10 && self.x > platform.x - 500 && self.x < platform.x + 500) { self.y = platform.y - 80; return true; } } return false; }; return self; }); var ParticlePool = Container.expand(function (maxParticles) { var self = Container.call(this); self.particles = []; self.activeParticles = []; self.redTints = [0xff0000, 0xff3333, 0xcc0000]; for (var i = 0; i < maxParticles; i++) { var particle = self.attachAsset('pixel', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.2, // 4% of original size (4px from 100px) scaleY: 0.2 // 4% of original size (4px from 100px) }); particle.alpha = 0; particle.velocityX = 0; particle.velocityY = 0; particle.lifespan = 0; particle.fadeSpeed = 0; self.particles.push(particle); } self.emitFromHit = function (x, y, playerX) { var directionX = x - playerX; var directionSign = Math.sign(directionX); for (var i = 0; i < 20; i++) { if (self.particles.length === 0) { break; } var particle = self.particles.pop(); self.activeParticles.push(particle); particle.x = x + 300; particle.y = y; particle.alpha = 1; particle.tint = self.redTints[Math.floor(Math.random() * self.redTints.length)]; // Set scale instead of width/height var particleSize = Math.random() * 0.2 + 0.2; // 2-4% of original size particle.scaleX = particleSize; particle.scaleY = particleSize; var angle = Math.random() * Math.PI / 2 - Math.PI / 4; var speed = Math.random() * 5 + 10; particle.velocityX = Math.cos(angle) * speed * directionSign; particle.velocityY = Math.sin(angle) * speed; particle.lifespan = 100; particle.fadeSpeed = 1 / 60; } }; self.update = function () { for (var i = self.activeParticles.length - 1; i >= 0; i--) { var particle = self.activeParticles[i]; particle.x += particle.velocityX; particle.y += particle.velocityY; particle.alpha -= particle.fadeSpeed; particle.lifespan--; if (particle.lifespan <= 0 || particle.alpha <= 0) { particle.alpha = 0; self.activeParticles.splice(i, 1); self.particles.push(particle); } } }; return self; }); var Platform = Container.expand(function () { var self = Container.call(this); var platformGraphics = self.attachAsset('platform', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5; self.passed = false; self.update = function () { self.x -= self.speed; if (self.x < -500) { // Increased value to ensure platforms are fully off-screen self.destroy(); } }; }); //<Assets used in the game will automatically appear here> var Player = Container.expand(function () { var self = Container.call(this); // Animation properties self.runAnimation = ['playerrun1', 'playerrun2', 'playerrun3', 'playerrun4', 'playerrun5', 'playerrun6']; self.jumpAnimation = ['playerjump1', 'playerjump2', 'playerjump3']; self.attackAnimation = ['playerattack1', 'playerattack2', 'playerattack3', 'playerattack4', 'playerattack5']; self.isAttacking = false; self.attackFrame = 0; self.runFrame = 0; self.animationSpeed = 0.08; self.attackAnimationSpeed = 0.15; // Higher number = faster animation self.animationCounter = 0; self.sprites = []; self.groundY = 2732 * 0.9; // Move ground much lower to allow falling from all platforms // Add bounding box properties self.hitboxWidth = 150; // Smaller than the 600px animation frames self.hitboxHeight = 400; // Adjusted for player height // Platform collision properties self.isOnGround = true; self.currentPlatform = null; // Pre-attach all animation frames but make only the first one visible // First add run animation sprites for (var i = 0; i < self.runAnimation.length; i++) { var sprite = self.attachAsset(self.runAnimation[i], { anchorX: 0.5, anchorY: 0.5 }); // Set all frames except the first to be invisible sprite.alpha = i === 0 ? 1 : 0; self.sprites.push(sprite); } // Then add jump animation sprites for (var i = 0; i < self.jumpAnimation.length; i++) { var sprite = self.attachAsset(self.jumpAnimation[i], { anchorX: 0.5, anchorY: 0.5 }); // Set all jump frames to invisible initially sprite.alpha = 0; self.sprites.push(sprite); } for (var i = 0; i < self.attackAnimation.length; i++) { var sprite = self.attachAsset(self.attackAnimation[i], { anchorX: 0.5, anchorY: 0.5 }); sprite.alpha = 0; self.sprites.push(sprite); } // Movement properties self.speed = 5; self.jumpHeight = 40; // Keeping the original jump height self.isJumping = false; self.velocityY = 0; self.jumpState = "none"; // Added to track jump animation phases self.jumpStartTime = 0; // Add method to get actual collision bounds self.getBounds = function () { return { left: self.x - self.hitboxWidth / 2, right: self.x + self.hitboxWidth / 2, top: self.y - self.hitboxHeight / 2, bottom: self.y + self.hitboxHeight / 2 }; }; self.update = function () { // Hide all sprites first for (var i = 0; i < self.sprites.length; i++) { self.sprites[i].alpha = 0; } // Handle platform collision and falling physics first if (!self.isOnGround && !self.isJumping) { self.velocityY += 0.7; self.y += self.velocityY; self.checkPlatformCollision(); } // Handle jumping physics if (self.isJumping) { self.y += self.velocityY; self.velocityY += 0.7; // Get jump frame index offset var jumpOffset = self.runAnimation.length; // Check for landing on platforms while falling during a jump self.checkPlatformCollision(); // End jump if hitting the original ground (for backward compatibility) if (self.y >= self.groundY && !self.currentPlatform) { self.y = self.groundY; self.isJumping = false; self.velocityY = 0; self.jumpState = "none"; self.isOnGround = true; } } // IMPORTANT: Platform collision check - runs EVERY frame var onAnyPlatform = false; var platformHalfWidth = 500; // half of platform width (1000/2) // First, check platform collisions for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; var leftEdge = platform.x - platformHalfWidth; var rightEdge = platform.x + platformHalfWidth; // Check if player is within horizontal bounds of platform if (self.x >= leftEdge && self.x <= rightEdge) { // If we're at platform height and not jumping if (Math.abs(self.y - (platform.y - 250)) < 5 && !self.isJumping) { onAnyPlatform = true; self.currentPlatform = platform; self.y = platform.y - 250; self.isOnGround = true; self.velocityY = 0; break; } } } // Handle falling state if (!onAnyPlatform && !self.isJumping) { self.isOnGround = false; self.currentPlatform = null; // Apply gravity if (self.velocityY === 0) { self.velocityY = 0.1; } self.velocityY += 0.1; self.y += self.velocityY; // Ground collision check comes AFTER falling movement if (self.y >= self.groundY) { // Reached the bottom of the screen - game over LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } } // Now handle animations - attack takes priority if active if (self.isAttacking) { var attackOffset = self.runAnimation.length + self.jumpAnimation.length; self.animationCounter += self.attackAnimationSpeed; if (self.animationCounter >= 1) { self.animationCounter = 0; self.attackFrame++; if (self.attackFrame >= self.attackAnimation.length) { self.isAttacking = false; self.attackFrame = 0; } } self.sprites[attackOffset + self.attackFrame].alpha = 1; } // If not attacking, show jump or run animation else if (self.isJumping || !self.isOnGround) { var jumpOffset = self.runAnimation.length; var currentTime = Date.now(); if (currentTime - self.jumpStartTime < 100) { self.sprites[jumpOffset + 0].alpha = 1; } else if (self.velocityY < 0) { self.sprites[jumpOffset + 1].alpha = 1; } else if (self.velocityY > 0) { self.sprites[jumpOffset + 2].alpha = 1; } } else if (self.isOnGround) { self.animationCounter += self.animationSpeed; if (self.animationCounter >= 1) { self.animationCounter = 0; self.runFrame = (self.runFrame + 1) % self.runAnimation.length; } self.sprites[self.runFrame].alpha = 1; } // If on a platform, check if we're still above it if (self.currentPlatform) { var platformHalfWidth = platformWidth / 2; // Use platformWidth constant var stillOnPlatform = self.x > self.currentPlatform.x - platformHalfWidth && self.x < self.currentPlatform.x + platformHalfWidth; if (!stillOnPlatform) { var foundAnotherPlatform = false; for (var i = 0; i < platforms.length; i++) { var otherPlatform = platforms[i]; if (otherPlatform === self.currentPlatform) { continue; } var otherHalfWidth = platformWidth / 2; if (self.x > otherPlatform.x - otherHalfWidth && self.x < otherPlatform.x + otherHalfWidth) { // We found another platform directly below player self.currentPlatform = otherPlatform; foundAnotherPlatform = true; break; } } // Only fall if we didn't find another platform if (!foundAnotherPlatform) { self.isOnGround = false; self.currentPlatform = null; // Start falling with initial velocity self.velocityY = 0.1; } } } // Check if player has fallen off the bottom of the screen if (self.y > 2732) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } }; self.jump = function () { if (self.isOnGround) { self.isJumping = true; self.isOnGround = false; self.velocityY = -self.jumpHeight; self.jumpState = "start"; self.jumpStartTime = Date.now(); self.currentPlatform = null; } else if (self.isJumping && self.velocityY < 10) { // Allow for a small double-jump to reach higher platforms // Only if not falling too fast self.velocityY = -self.jumpHeight * 0.7; self.jumpStartTime = Date.now(); } }; self.attack = function () { if (!self.isAttacking) { self.isAttacking = true; self.attackFrame = 0; self.animationCounter = 0; } }; self.checkPlatformCollision = function () { for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; var platformHalfWidth = platform.width / 2; // The offset should match exactly how the player aligns with the lower platform initially var playerPlatformOffset = 250; // This is the exact offset between player.y and lowPlatformHeight // Check if player is above the platform and falling if (self.velocityY > 0 && // Must be falling down self.y < platform.y - playerPlatformOffset && self.y + self.velocityY >= platform.y - playerPlatformOffset && self.x > platform.x - platformHalfWidth && self.x < platform.x + platformHalfWidth) { // Land on the platform with the exact same positioning as on the low platform self.y = platform.y - playerPlatformOffset; self.velocityY = 0; self.isJumping = false; self.isOnGround = true; self.currentPlatform = platform; return; } } }; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 // Black background }); /**** * Game Code ****/ var backgroundContainer = game.addChild(new Container()); var midgroundContainer = game.addChild(new Container()); var foregroundContainer = game.addChild(new Container()); var scoreContainer = game.addChild(new Container()); var GAME_WIDTH = 2048; var ENEMY_PLATFORM_OFFSET = 225; // Adjust this value var platforms = []; var platformWidth = 1000; // Define platform width based on asset size var platformSpawnInterval = 60; var platformSpawnCounter = 0; var platformOverlap = 50; var platformSpeed = 5; // Define platform speed globally var platformSpawnInterval = 190; // = (1000 - 50) / 5 = 190 // Define the two fixed platform heights var lowPlatformHeight = 2732 / 1.5 + 250; // Regular height (player.y + 250) var highPlatformHeight = lowPlatformHeight - 600; // High platform (600 pixels higher) var minPlatformsInSequence = 5; // Minimum platforms in a sequence var maxPlatformsInSequence = 10; // Maximum platforms in a sequence var platformsUntilNextChange = 5; // Initial longer ground sequence var currentPlatformHeight = lowPlatformHeight; var lastPlatformHeight = lowPlatformHeight; // Simple toggle for alternating platform heights var useHighPlatform = false; var platformGap = 200; // Gap between platforms var lastPlatformX = 0; // Track the last platform position var touchStartX = 0; var touchStartY = 0; var touchEndX = 0; var touchEndY = 0; var jars = []; var coins = []; var jarSpawnCounter = 0; var jarSpawnInterval = 20; // Adjust as needed var particleSystem; //<Assets used in the game will automatically appear here> // Background layer (slowest) var bg1 = backgroundContainer.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 1 })); var bg2 = backgroundContainer.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 1 })); bg1.y = 2732; // Position at bottom of screen bg2.y = 2732; bg2.x = GAME_WIDTH; // Midground layer var mg1 = midgroundContainer.addChild(LK.getAsset('midground', { anchorX: 0, anchorY: 1 })); var mg2 = midgroundContainer.addChild(LK.getAsset('midground', { anchorX: 0, anchorY: 1 })); mg1.y = 2732; mg2.y = 2732; mg2.x = GAME_WIDTH; // Foreground layer (fastest) var fg1 = foregroundContainer.addChild(LK.getAsset('foreground', { anchorX: 0, anchorY: 1 })); var fg2 = foregroundContainer.addChild(LK.getAsset('foreground', { anchorX: 0, anchorY: 1 })); fg1.y = 2732 * 1.25; fg2.y = 2732 * 1.25; fg1.x = 0; fg2.x = GAME_WIDTH; // Initialize player var player = game.addChild(new Player()); player.x = 2048 / 4.5; player.y = 2732 / 1.5; // Initialize enemies var enemies = []; var enemySpawnInterval = 100; var enemySpawnCounter = 0; // Create a new Text2 object to display the score var scoreText = new Text2('0', { size: 160, fill: 0xFFFFFF, anchorX: 1, // Anchor text to right edge anchorY: 0.5 // Center text vertically }); var coinIcon = LK.getAsset('coin', { anchorX: 0, anchorY: 0.5, scaleX: 2, scaleY: 2 }); scoreContainer.addChild(scoreText); scoreContainer.addChild(coinIcon); // Position container in top right scoreContainer.x = 2048 - 100; // 50 pixels from right edge scoreContainer.y = 100; // 50 pixels from top // Position elements within container scoreText.x = -100; // Offset left from container position scoreText.y = -100; coinIcon.x = 0; // At container position coinIcon.y = 0; // Initialize the game with starting platforms function initializeGame() { // Create initial platforms at the low level for (var i = 0; i < 5; i++) { var platform = new Platform(); if (i === 0) { // First platform centered on player platform.x = player.x; } else { // Position with slight overlap platform.x = lastPlatformX + platformWidth - platformOverlap; } platform.y = lowPlatformHeight; platforms.push(platform); game.addChild(platform); lastPlatformX = platform.x; } lastPlatformHeight = lowPlatformHeight; player.isOnGround = true; player.currentPlatform = platforms[0]; } initializeGame(); particleSystem = new ParticlePool(100); game.addChild(particleSystem); // Handle game updates game.update = function () { // Scroll backgrounds bg1.x -= platformSpeed * 0.3; bg2.x -= platformSpeed * 0.3; if (bg1.x <= -GAME_WIDTH) { bg1.x = bg2.x + GAME_WIDTH; } if (bg2.x <= -GAME_WIDTH) { bg2.x = bg1.x + GAME_WIDTH; } mg1.x -= platformSpeed * 0.6; mg2.x -= platformSpeed * 0.6; if (mg1.x <= -GAME_WIDTH) { mg1.x = mg2.x + GAME_WIDTH; } if (mg2.x <= -GAME_WIDTH) { mg2.x = mg1.x + GAME_WIDTH; } // Scroll foreground (four instances) fg1.x -= platformSpeed; fg2.x -= platformSpeed; if (fg1.x <= -GAME_WIDTH) { fg1.x = fg2.x + GAME_WIDTH; } if (fg2.x <= -GAME_WIDTH) { fg2.x = fg1.x + GAME_WIDTH; } player.update(); if (particleSystem) { particleSystem.update(); } // Check if we need to spawn a new sequence of platforms var lastPlatform = platforms[platforms.length - 1]; if (lastPlatform && lastPlatform.x < GAME_WIDTH + 500) { // Spawn further off-screen to prevent pop-in // Time to spawn a new sequence if (platformsUntilNextChange <= 0) { // Switch height currentPlatformHeight = currentPlatformHeight === lowPlatformHeight ? highPlatformHeight : lowPlatformHeight; // Generate new random sequence length platformsUntilNextChange = Math.floor(Math.random() * (maxPlatformsInSequence - minPlatformsInSequence + 1)) + minPlatformsInSequence; // Make ground sequences longer if (currentPlatformHeight === lowPlatformHeight) { platformsUntilNextChange += 5; } } // Spawn a single platform in the sequence var platform = new Platform(); platform.x = lastPlatform.x + (platformWidth - platformOverlap); platform.y = currentPlatformHeight; platforms.push(platform); game.addChild(platform); // Decrement the counter for each platform added platformsUntilNextChange--; } // Update platforms for (var i = platforms.length - 1; i >= 0; i--) { platforms[i].update(); // Remove platforms that are destroyed if (platforms[i].destroyed) { platforms.splice(i, 1); } } jarSpawnCounter++; if (jarSpawnCounter >= jarSpawnInterval) { var availablePlatforms = platforms.filter(function (p) { return p.x > 2048 && p.x < 2048 + 300; }); if (availablePlatforms.length > 0 && Math.random() < 0.3) { var platform = availablePlatforms[Math.floor(Math.random() * availablePlatforms.length)]; var jar = new Jar(); jar.x = platform.x; jar.y = platform.y - 130; // Increased offset to match ENEMY_PLATFORM_OFFSET jar.currentPlatform = platform; jars.push(jar); game.addChild(jar); } jarSpawnCounter = 0; } // Update jars for (var i = jars.length - 1; i >= 0; i--) { var jar = jars[i]; if (jar.currentPlatform) { jar.x = jar.currentPlatform.x; // Move with platform } // Check for player attack collision if (player.isAttacking) { var attackRange = 200; // Adjust based on player's attack animation var verticalRange = 150; // Adjust based on player and jar heights var distanceX = Math.abs(jar.x - player.x); var distanceY = Math.abs(jar.y - player.y); if (distanceX < attackRange && distanceY < verticalRange) { jar["break"](); jars.splice(i, 1); continue; } } // Remove if off screen if (jar.x < -50) { jar.destroy(); jars.splice(i, 1); } } // Update coins for (var i = coins.length - 1; i >= 0; i--) { coins[i].update(); if (coins[i].destroyed) { coins.splice(i, 1); } } // Enemy handling (keep your existing enemy code) enemySpawnCounter++; if (enemySpawnCounter >= enemySpawnInterval) { // Only spawn enemies if there are valid platforms available var availablePlatforms = platforms.filter(function (p) { // Look for platforms that are just off-screen to the right return p.x > 2048 - 100 && p.x < 2048 + 300; }); // Only spawn an enemy if we have a platform to put it on if (availablePlatforms.length > 0) { var enemy = new Enemy('goblin'); var platform = availablePlatforms[Math.floor(Math.random() * availablePlatforms.length)]; enemy.x = platform.x; // Spawn directly above the platform enemy.y = platform.y - ENEMY_PLATFORM_OFFSET; enemy.currentPlatform = platform; enemies.push(enemy); game.addChild(enemy); enemySpawnInterval = Math.floor(Math.random() * 150) + 100; // Slightly longer intervals enemySpawnCounter = 0; } else { // No valid platforms, just reset counter but don't spawn enemySpawnCounter = Math.max(0, enemySpawnCounter - 20); // Back up a bit to try again soon } } // Update enemies for (var j = enemies.length - 1; j >= 0; j--) { enemies[j].update(); var playerBounds = player.getBounds(); var enemyBounds = enemies[j].getBounds(); if (playerBounds.left < enemyBounds.right && playerBounds.right > enemyBounds.left && playerBounds.top < enemyBounds.bottom && playerBounds.bottom > enemyBounds.top) { if (player.isAttacking) { // Hit the enemy if player is attacking enemies[j].hit(); // Add score if not already passed if (!enemies[j].passed) { enemies[j].passed = true; LK.setScore(LK.getScore() + 1); scoreText.setText(LK.getScore()); } } else if (!enemies[j].isHit && !enemies[j].isDying) { // Only die from enemy touch if enemy isn't already hit/dying LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } } else if (player.x > enemies[j].x && !enemies[j].passed) { enemies[j].passed = true; //LK.setScore(LK.getScore() + 1); //scoreText.setText(LK.getScore()); } } }; // Handle player jump game.down = function (x, y, obj) { touchStartX = x; touchStartY = y; }; game.up = function (x, y, obj) { touchEndX = x; touchEndY = y; // Calculate swipe var deltaY = touchStartY - touchEndY; var deltaX = Math.abs(touchStartX - touchEndX); // If vertical swipe (more vertical than horizontal movement) if (deltaY > 50 && deltaY > deltaX) { player.jump(); } else { // Regular tap/click triggers attack player.attack(); } }; var backgroundContainer = game.addChild(new Container()); var midgroundContainer = game.addChild(new Container()); var foregroundContainer = game.addChild(new Container()); var scoreContainer = game.addChild(new Container()); var GAME_WIDTH = 2048; var ENEMY_PLATFORM_OFFSET = 225; // Adjust this value var platforms = []; var platformWidth = 1000; // Define platform width based on asset size var platformSpawnInterval = 60; var platformSpawnCounter = 0; var platformOverlap = 50; var platformSpeed = 5; // Define platform speed globally var platformSpawnInterval = 190; // = (1000 - 50) / 5 = 190 // Define the two fixed platform heights var lowPlatformHeight = 2732 / 1.5 + 250; // Regular height (player.y + 250) var highPlatformHeight = lowPlatformHeight - 600; // High platform (600 pixels higher) var minPlatformsInSequence = 5; // Minimum platforms in a sequence var maxPlatformsInSequence = 10; // Maximum platforms in a sequence var platformsUntilNextChange = 5; // Initial longer ground sequence var currentPlatformHeight = lowPlatformHeight; var lastPlatformHeight = lowPlatformHeight; // Simple toggle for alternating platform heights var useHighPlatform = false; var platformGap = 200; // Gap between platforms var lastPlatformX = 0; // Track the last platform position var touchStartX = 0; var touchStartY = 0; var touchEndX = 0; var touchEndY = 0; var jars = []; var coins = []; var jarSpawnCounter = 0; var jarSpawnInterval = 20; // Adjust as needed var particleSystem; //<Assets used in the game will automatically appear here> // Background layer (slowest) var bg1 = backgroundContainer.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 1 })); var bg2 = backgroundContainer.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 1 })); bg1.y = 2732; // Position at bottom of screen bg2.y = 2732; bg2.x = GAME_WIDTH; // Midground layer var mg1 = midgroundContainer.addChild(LK.getAsset('midground', { anchorX: 0, anchorY: 1 })); var mg2 = midgroundContainer.addChild(LK.getAsset('midground', { anchorX: 0, anchorY: 1 })); mg1.y = 2732; mg2.y = 2732; mg2.x = GAME_WIDTH; // Foreground layer (fastest) var fg1 = foregroundContainer.addChild(LK.getAsset('foreground', { anchorX: 0, anchorY: 1 })); var fg2 = foregroundContainer.addChild(LK.getAsset('foreground', { anchorX: 0, anchorY: 1 })); fg1.y = 2732 * 1.25; fg2.y = 2732 * 1.25; fg1.x = 0; fg2.x = GAME_WIDTH; // Initialize player var player = game.addChild(new Player()); player.x = 2048 / 4.5; player.y = 2732 / 1.5; // Initialize enemies var enemies = []; var enemySpawnInterval = 100; var enemySpawnCounter = 0; // Create a new Text2 object to display the score var scoreText = new Text2('0', { size: 160, fill: 0xFFFFFF, anchorX: 1, // Anchor text to right edge anchorY: 0.5 // Center text vertically }); var coinIcon = LK.getAsset('coin', { anchorX: 0, anchorY: 0.5, scaleX: 2, scaleY: 2 }); scoreContainer.addChild(scoreText); scoreContainer.addChild(coinIcon); // Position container in top right scoreContainer.x = 2048 - 100; // 50 pixels from right edge scoreContainer.y = 100; // 50 pixels from top // Position elements within container scoreText.x = -100; // Offset left from container position scoreText.y = -100; coinIcon.x = 0; // At container position coinIcon.y = 0; // Initialize the game with starting platforms initializeGame(); particleSystem = new ParticlePool(100); game.addChild(particleSystem); // Handle game updates game.update = function () { // Scroll backgrounds bg1.x -= platformSpeed * 0.3; bg2.x -= platformSpeed * 0.3; if (bg1.x <= -GAME_WIDTH) { bg1.x = bg2.x + GAME_WIDTH; } if (bg2.x <= -GAME_WIDTH) { bg2.x = bg1.x + GAME_WIDTH; } mg1.x -= platformSpeed * 0.6; mg2.x -= platformSpeed * 0.6; if (mg1.x <= -GAME_WIDTH) { mg1.x = mg2.x + GAME_WIDTH; } if (mg2.x <= -GAME_WIDTH) { mg2.x = mg1.x + GAME_WIDTH; } // Scroll foreground (four instances) fg1.x -= platformSpeed; fg2.x -= platformSpeed; if (fg1.x <= -GAME_WIDTH) { fg1.x = fg2.x + GAME_WIDTH; } if (fg2.x <= -GAME_WIDTH) { fg2.x = fg1.x + GAME_WIDTH; } player.update(); if (particleSystem) { particleSystem.update(); } // Check if we need to spawn a new sequence of platforms var lastPlatform = platforms[platforms.length - 1]; if (lastPlatform && lastPlatform.x < GAME_WIDTH + 500) { // Spawn further off-screen to prevent pop-in // Time to spawn a new sequence if (platformsUntilNextChange <= 0) { // Switch height currentPlatformHeight = currentPlatformHeight === lowPlatformHeight ? highPlatformHeight : lowPlatformHeight; // Generate new random sequence length platformsUntilNextChange = Math.floor(Math.random() * (maxPlatformsInSequence - minPlatformsInSequence + 1)) + minPlatformsInSequence; // Make ground sequences longer if (currentPlatformHeight === lowPlatformHeight) { platformsUntilNextChange += 5; } } // Spawn a single platform in the sequence var platform = new Platform(); platform.x = lastPlatform.x + (platformWidth - platformOverlap); platform.y = currentPlatformHeight; platforms.push(platform); game.addChild(platform); // Decrement the counter for each platform added platformsUntilNextChange--; } // Update platforms for (var i = platforms.length - 1; i >= 0; i--) { platforms[i].update(); // Remove platforms that are destroyed if (platforms[i].destroyed) { platforms.splice(i, 1); } } jarSpawnCounter++; if (jarSpawnCounter >= jarSpawnInterval) { var availablePlatforms = platforms.filter(function (p) { return p.x > 2048 && p.x < 2048 + 300; }); if (availablePlatforms.length > 0 && Math.random() < 0.3) { var platform = availablePlatforms[Math.floor(Math.random() * availablePlatforms.length)]; var jar = new Jar(); jar.x = platform.x; jar.y = platform.y - 130; // Increased offset to match ENEMY_PLATFORM_OFFSET jar.currentPlatform = platform; jars.push(jar); game.addChild(jar); } jarSpawnCounter = 0; } // Update jars for (var i = jars.length - 1; i >= 0; i--) { var jar = jars[i]; if (jar.currentPlatform) { jar.x = jar.currentPlatform.x; // Move with platform } // Check for player attack collision if (player.isAttacking) { var attackRange = 200; // Adjust based on player's attack animation var verticalRange = 150; // Adjust based on player and jar heights var distanceX = Math.abs(jar.x - player.x); var distanceY = Math.abs(jar.y - player.y); if (distanceX < attackRange && distanceY < verticalRange) { jar["break"](); jars.splice(i, 1); continue; } } // Remove if off screen if (jar.x < -50) { jar.destroy(); jars.splice(i, 1); } } // Update coins for (var i = coins.length - 1; i >= 0; i--) { coins[i].update(); if (coins[i].destroyed) { coins.splice(i, 1); } } for (var i = game.children.length - 1; i >= 0; i--) { var child = game.children[i]; if (child instanceof ScorePopup) { child.update(); } } // Enemy handling (keep your existing enemy code) enemySpawnCounter++; if (enemySpawnCounter >= enemySpawnInterval) { // Only spawn enemies if there are valid platforms available var availablePlatforms = platforms.filter(function (p) { // Look for platforms that are just off-screen to the right return p.x > 2048 - 100 && p.x < 2048 + 300; }); // Only spawn an enemy if we have a platform to put it on if (availablePlatforms.length > 0) { var enemy = new Enemy('goblin'); var platform = availablePlatforms[Math.floor(Math.random() * availablePlatforms.length)]; enemy.x = platform.x; // Spawn directly above the platform enemy.y = platform.y - ENEMY_PLATFORM_OFFSET; enemy.currentPlatform = platform; enemies.push(enemy); game.addChild(enemy); enemySpawnInterval = Math.floor(Math.random() * 150) + 100; // Slightly longer intervals enemySpawnCounter = 0; } else { // No valid platforms, just reset counter but don't spawn enemySpawnCounter = Math.max(0, enemySpawnCounter - 20); // Back up a bit to try again soon } } // Update enemies for (var j = enemies.length - 1; j >= 0; j--) { enemies[j].update(); var playerBounds = player.getBounds(); var enemyBounds = enemies[j].getBounds(); if (playerBounds.left < enemyBounds.right && playerBounds.right > enemyBounds.left && playerBounds.top < enemyBounds.bottom && playerBounds.bottom > enemyBounds.top) { if (player.isAttacking) { // Hit the enemy if player is attacking enemies[j].hit(); // Add score if not already passed if (!enemies[j].passed) { enemies[j].passed = true; LK.setScore(LK.getScore() + 1); scoreText.setText(LK.getScore()); } } else if (!enemies[j].isHit && !enemies[j].isDying) { // Only die from enemy touch if enemy isn't already hit/dying LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } } else if (player.x > enemies[j].x && !enemies[j].passed) { enemies[j].passed = true; //LK.setScore(LK.getScore() + 1); //scoreText.setText(LK.getScore()); } } }; // Handle player jump game.down = function (x, y, obj) { touchStartX = x; touchStartY = y; }; game.up = function (x, y, obj) { touchEndX = x; touchEndY = y; // Calculate swipe var deltaY = touchStartY - touchEndY; var deltaX = Math.abs(touchStartX - touchEndX); // If vertical swipe (more vertical than horizontal movement) if (deltaY > 50 && deltaY > deltaX) { player.jump(); } else { // Regular tap/click triggers attack player.attack(); } };
/****
* Classes
****/
var Coin = Container.expand(function () {
var self = Container.call(this);
self.sprite = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xD3D3D3 // Apply lighter grey tint
});
self.velocityX = 0;
self.velocityY = 0;
self.collected = false;
self.bounceCount = 0;
self.maxBounces = 2;
// Replace the existing collect method in the Coin class
self.collect = function () {
if (!self.collected) {
self.collected = true;
LK.setScore(LK.getScore() + 1);
scoreText.setText(LK.getScore());
// Create and add the score popup at the coin's position
var popup = new ScorePopup(self.x, self.y - 30); // Start slightly above the coin
game.addChild(popup);
self.destroy();
}
};
self.update = function () {
if (self.collected) {
return;
}
// Apply physics
self.velocityY += 0.5; // gravity
self.x += self.velocityX;
self.y += self.velocityY;
// Check for platform collision with bounce
// Only bounce if we're moving downward and hit a platform
if (self.velocityY > 0 && self.checkPlatformCollision()) {
if (self.bounceCount < self.maxBounces) {
var impactSpeed = Math.abs(self.velocityY);
self.velocityY = -(impactSpeed * 0.5); // Use half of impact speed
self.velocityX *= 0.8;
self.bounceCount++;
} else {
self.velocityY = 0;
self.velocityX = -5; // Match platform speed
}
}
// Check if off screen
if (self.x < -50 || self.x > 2048 + 50 || self.y > 2732) {
self.destroy();
}
// Player collection detection
var playerBounds = player.getBounds();
var coinBounds = {
left: self.x - 25,
right: self.x + 25,
top: self.y - 25,
bottom: self.y + 25
};
if (playerBounds.left < coinBounds.right && playerBounds.right > coinBounds.left && playerBounds.top < coinBounds.bottom && playerBounds.bottom > coinBounds.top) {
self.collect();
}
};
self.checkPlatformCollision = function () {
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
if (Math.abs(self.y - (platform.y - 80)) < 10 && self.x > platform.x - 500 && self.x < platform.x + 500) {
self.y = platform.y - 80;
return true;
}
}
return false;
};
return self;
});
var Enemy = Container.expand(function (type) {
var self = Container.call(this);
// Enemy properties
self.type = type || 'basic';
self.speed = 7;
self.isOnGround = true;
self.velocityY = 0;
self.currentPlatform = null;
self.groundY = 2732 / 1.5; // Same as player ground Y
self.hitAnimation = ['goblinhit1'];
self.dieAnimation = ['goblindie1', 'goblindie2', 'goblindie3', 'goblindie4'];
self.isHit = false;
self.isDying = false;
self.deathTimer = 0;
self.throwBackSpeed = 15; // Initial backwards throw speed
self.throwBackDistance = 0; // Track distance thrown
self.maxThrowBack = 200; // Maximum throw back distance
// Add bounding box properties
self.hitboxWidth = 200; // Smaller than the 150px sprite width
self.hitboxHeight = 260; // Adjusted for goblin height
// Animation properties for goblin
self.runAnimation = [];
self.runFrame = 0;
self.animationSpeed = 0.08;
self.animationCounter = 0;
self.sprites = [];
// Initialize based on enemy type
if (self.type === 'goblin') {
// Setup all animations
self.runAnimation = ['goblinrun1', 'goblinrun2', 'goblinrun3', 'goblinrun4', 'goblinrun5', 'goblinrun6', 'goblinrun7', 'goblinrun8'];
// Pre-attach all animation frames
// Run animation
for (var i = 0; i < self.runAnimation.length; i++) {
var sprite = self.attachAsset(self.runAnimation[i], {
anchorX: 0.5,
anchorY: 0.5
});
sprite.alpha = i === 0 ? 1 : 0;
self.sprites.push(sprite);
}
// Hit animation
for (var i = 0; i < self.hitAnimation.length; i++) {
var sprite = self.attachAsset(self.hitAnimation[i], {
anchorX: 0.5,
anchorY: 0.5
});
sprite.alpha = 0;
self.sprites.push(sprite);
}
// Die animation
for (var i = 0; i < self.dieAnimation.length; i++) {
var sprite = self.attachAsset(self.dieAnimation[i], {
anchorX: 0.5,
anchorY: 0.5
});
sprite.alpha = 0;
self.sprites.push(sprite);
}
} else {
// Basic enemy (original version)
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.checkPlatformCollision = function () {
var onAnyPlatform = false;
var platformHalfWidth = 500;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var leftEdge = platform.x - platformHalfWidth;
var rightEdge = platform.x + platformHalfWidth;
// First check if we're on a platform (exact position check)
if (self.x >= leftEdge && self.x <= rightEdge) {
if (Math.abs(self.y - (platform.y - ENEMY_PLATFORM_OFFSET)) < 5) {
onAnyPlatform = true;
self.currentPlatform = platform;
self.y = platform.y - ENEMY_PLATFORM_OFFSET;
self.isOnGround = true;
self.velocityY = 0;
return true;
}
// NEW CODE: Check for passing through platform during fall
// This detects if the enemy will cross the platform in the next frame
if (self.velocityY > 0 &&
// Must be falling down
self.y < platform.y - ENEMY_PLATFORM_OFFSET && self.y + self.velocityY >= platform.y - ENEMY_PLATFORM_OFFSET) {
self.y = platform.y - ENEMY_PLATFORM_OFFSET;
self.velocityY = 0;
self.isOnGround = true;
self.currentPlatform = platform;
return true;
}
}
}
if (!onAnyPlatform) {
self.isOnGround = false;
self.currentPlatform = null;
}
return false;
};
// Update collision check method
self.getBounds = function () {
return {
left: self.x - self.hitboxWidth / 2,
right: self.x + self.hitboxWidth / 2,
top: self.y - self.hitboxHeight / 2,
bottom: self.y + self.hitboxHeight / 2
};
};
self.hit = function () {
if (!self.isHit && !self.isDying) {
self.isHit = true;
self.throwBackSpeed = 35; // Increased from 25 for more distance
self.throwBackDistance = 0;
self.hitTimer = 20; // Added hit timer for longer hit frame
// Add particle effect here
particleSystem.emitFromHit(self.x, self.y, player.x);
}
};
self.update = function () {
// Hide all sprites first
for (var i = 0; i < self.sprites.length; i++) {
self.sprites[i].alpha = 0;
}
if (self.isHit) {
// Handle throw back motion
self.x += self.throwBackSpeed;
self.throwBackDistance += Math.abs(self.throwBackSpeed);
self.throwBackSpeed *= 0.95; // Slower decay than 0.9
// Show hit animation
var hitOffset = self.runAnimation.length;
self.sprites[hitOffset].alpha = 1;
// Decrease hit timer
self.hitTimer--;
// Once hit timer expires, start death animation
if (self.hitTimer <= 0) {
self.isHit = false;
self.isDying = true;
self.deathTimer = 60; // Increased to 60 frames
self.deathFrame = 0; // Explicitly track which frame we're on
}
} else if (self.isDying) {
// Continue throw back during death
self.x += self.throwBackSpeed;
// After halfway through death animation, match platform speed
if (self.deathFrame >= 2) {
// Since we have 4 frames, 2 is halfway
self.x -= 5; // Platform speed is defined as 5
}
self.throwBackSpeed *= 0.95;
// Removed vertical movement code
// Handle death animation
var dieOffset = self.runAnimation.length + self.hitAnimation.length;
// Progress frame every 15 frames (60/4 frames = 15)
if (self.deathTimer % 15 === 0 && self.deathFrame < self.dieAnimation.length - 1) {
self.deathFrame++;
}
var dieOffset = self.runAnimation.length + self.hitAnimation.length;
self.sprites[dieOffset + self.deathFrame].alpha = 1;
// Count down death timer
self.deathTimer--;
// After timer expires, fade out
if (self.deathTimer <= 0) {
self.alpha -= 0.1;
if (self.alpha <= 0) {
self.destroy();
}
}
} else {
// Original movement and animation code
// Move left
self.x -= self.speed;
// Original platform and gravity code
if (!self.isOnGround) {
self.velocityY += 0.7;
self.y += self.velocityY;
if (!self.checkPlatformCollision()) {
// Let them fall if not on platform
}
}
if (self.currentPlatform) {
var platformHalfWidth = 500; // Match the existing platform width constant
var stillOnPlatform = self.x >= self.currentPlatform.x - platformHalfWidth && self.x <= self.currentPlatform.x + platformHalfWidth;
if (!stillOnPlatform) {
var foundAnotherPlatform = false;
// Check if there's another platform we might have moved to
for (var i = 0; i < platforms.length; i++) {
var otherPlatform = platforms[i];
if (otherPlatform === self.currentPlatform) {
continue;
}
if (self.x >= otherPlatform.x - platformHalfWidth && self.x <= otherPlatform.x + platformHalfWidth && Math.abs(self.y - (otherPlatform.y - ENEMY_PLATFORM_OFFSET)) < 5) {
// Found another platform at the same height
self.currentPlatform = otherPlatform;
foundAnotherPlatform = true;
break;
}
}
// If no other platform found, start falling
if (!foundAnotherPlatform) {
self.isOnGround = false;
self.currentPlatform = null;
// Start falling with initial velocity
if (self.velocityY === 0) {
self.velocityY = 0.1;
}
}
}
}
// Handle run animation
if (self.type === 'goblin') {
self.animationCounter += self.animationSpeed;
if (self.animationCounter >= 1) {
self.animationCounter = 0;
self.runFrame = (self.runFrame + 1) % self.runAnimation.length;
}
self.sprites[self.runFrame].alpha = 1;
}
}
// Destroy if off screen
if (self.x < -50 || self.y > 2732) {
self.destroy();
}
};
});
var Jar = Container.expand(function () {
var self = Container.call(this);
// Attach jar sprite
self.sprite = self.attachAsset('jar', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xC0C0C0 // Change tint to an even lighter grey
});
self.isBreaking = false;
self.currentPlatform = null;
self["break"] = function () {
if (self.isBreaking) {
return;
}
self.isBreaking = true;
// Spawn jar pieces (keep existing piece code)
for (var i = 1; i <= 4; i++) {
var piece = new JarPiece(i);
piece.x = self.x;
piece.y = self.y;
piece.velocityX = Math.random() * 10 - 5;
piece.velocityY = -(Math.random() * 10 + 5);
piece.rotationSpeed = Math.random() * 0.2 - 0.1;
game.addChild(piece);
}
// Modified coin spawning with more forward motion
var coinCount = Math.floor(Math.random() * 8) + 1;
for (var i = 0; i < coinCount; i++) {
var coin = new Coin();
coin.x = self.x;
coin.y = self.y;
// More forward motion and higher initial jump
coin.velocityX = Math.random() * 8 + 4; // Minimum 4, maximum 12 right velocity
coin.velocityY = -(Math.random() * 10 + 12); // Higher jump
game.addChild(coin);
coins.push(coin);
}
self.destroy();
};
return self;
});
var JarPiece = Container.expand(function (pieceNum) {
var self = Container.call(this);
self.sprite = self.attachAsset('jarpiece' + pieceNum, {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xC0C0C0 // Apply grey tint
});
self.velocityX = 0;
self.velocityY = 0;
self.rotationSpeed = 0;
self.fadeSpeed = 0.02;
self.bounceCount = 0;
self.maxBounces = 2; // Number of bounces before stopping
self.update = function () {
// Apply physics
self.velocityY += 0.5; // gravity
self.x += self.velocityX;
self.y += self.velocityY;
self.rotation += self.rotationSpeed;
// Check for platform collision with bounce
if (self.checkPlatformCollision()) {
if (self.bounceCount < self.maxBounces) {
// Bounce with reduced velocity
self.velocityY = -(self.velocityY * 0.4); // 40% of original velocity
self.velocityX *= 0.8; // Reduce horizontal speed
self.bounceCount++;
} else {
// Stop moving after max bounces
self.velocityY = 0;
self.velocityX = -5; // Match platform speed
// Start fading
self.alpha -= self.fadeSpeed;
if (self.alpha <= 0) {
self.destroy();
}
}
}
// Destroy if off screen
if (self.x < -50 || self.y > 2732) {
self.destroy();
}
};
self.checkPlatformCollision = function () {
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
if (Math.abs(self.y - (platform.y - 80)) < 10 && self.x > platform.x - 500 && self.x < platform.x + 500) {
self.y = platform.y - 80;
return true;
}
}
return false;
};
return self;
});
var ParticlePool = Container.expand(function (maxParticles) {
var self = Container.call(this);
self.particles = [];
self.activeParticles = [];
self.redTints = [0xff0000, 0xff3333, 0xcc0000];
for (var i = 0; i < maxParticles; i++) {
var particle = self.attachAsset('pixel', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
// 4% of original size (4px from 100px)
scaleY: 0.2 // 4% of original size (4px from 100px)
});
particle.alpha = 0;
particle.velocityX = 0;
particle.velocityY = 0;
particle.lifespan = 0;
particle.fadeSpeed = 0;
self.particles.push(particle);
}
self.emitFromHit = function (x, y, playerX) {
var directionX = x - playerX;
var directionSign = Math.sign(directionX);
for (var i = 0; i < 20; i++) {
if (self.particles.length === 0) {
break;
}
var particle = self.particles.pop();
self.activeParticles.push(particle);
particle.x = x + 300;
particle.y = y;
particle.alpha = 1;
particle.tint = self.redTints[Math.floor(Math.random() * self.redTints.length)];
// Set scale instead of width/height
var particleSize = Math.random() * 0.2 + 0.2; // 2-4% of original size
particle.scaleX = particleSize;
particle.scaleY = particleSize;
var angle = Math.random() * Math.PI / 2 - Math.PI / 4;
var speed = Math.random() * 5 + 10;
particle.velocityX = Math.cos(angle) * speed * directionSign;
particle.velocityY = Math.sin(angle) * speed;
particle.lifespan = 100;
particle.fadeSpeed = 1 / 60;
}
};
self.update = function () {
for (var i = self.activeParticles.length - 1; i >= 0; i--) {
var particle = self.activeParticles[i];
particle.x += particle.velocityX;
particle.y += particle.velocityY;
particle.alpha -= particle.fadeSpeed;
particle.lifespan--;
if (particle.lifespan <= 0 || particle.alpha <= 0) {
particle.alpha = 0;
self.activeParticles.splice(i, 1);
self.particles.push(particle);
}
}
};
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.passed = false;
self.update = function () {
self.x -= self.speed;
if (self.x < -500) {
// Increased value to ensure platforms are fully off-screen
self.destroy();
}
};
});
//<Assets used in the game will automatically appear here>
var Player = Container.expand(function () {
var self = Container.call(this);
// Animation properties
self.runAnimation = ['playerrun1', 'playerrun2', 'playerrun3', 'playerrun4', 'playerrun5', 'playerrun6'];
self.jumpAnimation = ['playerjump1', 'playerjump2', 'playerjump3'];
self.attackAnimation = ['playerattack1', 'playerattack2', 'playerattack3', 'playerattack4', 'playerattack5'];
self.isAttacking = false;
self.attackFrame = 0;
self.runFrame = 0;
self.animationSpeed = 0.08;
self.attackAnimationSpeed = 0.15; // Higher number = faster animation
self.animationCounter = 0;
self.sprites = [];
self.groundY = 2732 * 0.9; // Move ground much lower to allow falling from all platforms
// Add bounding box properties
self.hitboxWidth = 150; // Smaller than the 600px animation frames
self.hitboxHeight = 400; // Adjusted for player height
// Platform collision properties
self.isOnGround = true;
self.currentPlatform = null;
// Pre-attach all animation frames but make only the first one visible
// First add run animation sprites
for (var i = 0; i < self.runAnimation.length; i++) {
var sprite = self.attachAsset(self.runAnimation[i], {
anchorX: 0.5,
anchorY: 0.5
});
// Set all frames except the first to be invisible
sprite.alpha = i === 0 ? 1 : 0;
self.sprites.push(sprite);
}
// Then add jump animation sprites
for (var i = 0; i < self.jumpAnimation.length; i++) {
var sprite = self.attachAsset(self.jumpAnimation[i], {
anchorX: 0.5,
anchorY: 0.5
});
// Set all jump frames to invisible initially
sprite.alpha = 0;
self.sprites.push(sprite);
}
for (var i = 0; i < self.attackAnimation.length; i++) {
var sprite = self.attachAsset(self.attackAnimation[i], {
anchorX: 0.5,
anchorY: 0.5
});
sprite.alpha = 0;
self.sprites.push(sprite);
}
// Movement properties
self.speed = 5;
self.jumpHeight = 40; // Keeping the original jump height
self.isJumping = false;
self.velocityY = 0;
self.jumpState = "none"; // Added to track jump animation phases
self.jumpStartTime = 0;
// Add method to get actual collision bounds
self.getBounds = function () {
return {
left: self.x - self.hitboxWidth / 2,
right: self.x + self.hitboxWidth / 2,
top: self.y - self.hitboxHeight / 2,
bottom: self.y + self.hitboxHeight / 2
};
};
self.update = function () {
// Hide all sprites first
for (var i = 0; i < self.sprites.length; i++) {
self.sprites[i].alpha = 0;
}
// Handle platform collision and falling physics first
if (!self.isOnGround && !self.isJumping) {
self.velocityY += 0.7;
self.y += self.velocityY;
self.checkPlatformCollision();
}
// Handle jumping physics
if (self.isJumping) {
self.y += self.velocityY;
self.velocityY += 0.7;
// Get jump frame index offset
var jumpOffset = self.runAnimation.length;
// Check for landing on platforms while falling during a jump
self.checkPlatformCollision();
// End jump if hitting the original ground (for backward compatibility)
if (self.y >= self.groundY && !self.currentPlatform) {
self.y = self.groundY;
self.isJumping = false;
self.velocityY = 0;
self.jumpState = "none";
self.isOnGround = true;
}
}
// IMPORTANT: Platform collision check - runs EVERY frame
var onAnyPlatform = false;
var platformHalfWidth = 500; // half of platform width (1000/2)
// First, check platform collisions
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var leftEdge = platform.x - platformHalfWidth;
var rightEdge = platform.x + platformHalfWidth;
// Check if player is within horizontal bounds of platform
if (self.x >= leftEdge && self.x <= rightEdge) {
// If we're at platform height and not jumping
if (Math.abs(self.y - (platform.y - 250)) < 5 && !self.isJumping) {
onAnyPlatform = true;
self.currentPlatform = platform;
self.y = platform.y - 250;
self.isOnGround = true;
self.velocityY = 0;
break;
}
}
}
// Handle falling state
if (!onAnyPlatform && !self.isJumping) {
self.isOnGround = false;
self.currentPlatform = null;
// Apply gravity
if (self.velocityY === 0) {
self.velocityY = 0.1;
}
self.velocityY += 0.1;
self.y += self.velocityY;
// Ground collision check comes AFTER falling movement
if (self.y >= self.groundY) {
// Reached the bottom of the screen - game over
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
}
// Now handle animations - attack takes priority if active
if (self.isAttacking) {
var attackOffset = self.runAnimation.length + self.jumpAnimation.length;
self.animationCounter += self.attackAnimationSpeed;
if (self.animationCounter >= 1) {
self.animationCounter = 0;
self.attackFrame++;
if (self.attackFrame >= self.attackAnimation.length) {
self.isAttacking = false;
self.attackFrame = 0;
}
}
self.sprites[attackOffset + self.attackFrame].alpha = 1;
}
// If not attacking, show jump or run animation
else if (self.isJumping || !self.isOnGround) {
var jumpOffset = self.runAnimation.length;
var currentTime = Date.now();
if (currentTime - self.jumpStartTime < 100) {
self.sprites[jumpOffset + 0].alpha = 1;
} else if (self.velocityY < 0) {
self.sprites[jumpOffset + 1].alpha = 1;
} else if (self.velocityY > 0) {
self.sprites[jumpOffset + 2].alpha = 1;
}
} else if (self.isOnGround) {
self.animationCounter += self.animationSpeed;
if (self.animationCounter >= 1) {
self.animationCounter = 0;
self.runFrame = (self.runFrame + 1) % self.runAnimation.length;
}
self.sprites[self.runFrame].alpha = 1;
}
// If on a platform, check if we're still above it
if (self.currentPlatform) {
var platformHalfWidth = platformWidth / 2; // Use platformWidth constant
var stillOnPlatform = self.x > self.currentPlatform.x - platformHalfWidth && self.x < self.currentPlatform.x + platformHalfWidth;
if (!stillOnPlatform) {
var foundAnotherPlatform = false;
for (var i = 0; i < platforms.length; i++) {
var otherPlatform = platforms[i];
if (otherPlatform === self.currentPlatform) {
continue;
}
var otherHalfWidth = platformWidth / 2;
if (self.x > otherPlatform.x - otherHalfWidth && self.x < otherPlatform.x + otherHalfWidth) {
// We found another platform directly below player
self.currentPlatform = otherPlatform;
foundAnotherPlatform = true;
break;
}
}
// Only fall if we didn't find another platform
if (!foundAnotherPlatform) {
self.isOnGround = false;
self.currentPlatform = null;
// Start falling with initial velocity
self.velocityY = 0.1;
}
}
}
// Check if player has fallen off the bottom of the screen
if (self.y > 2732) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
};
self.jump = function () {
if (self.isOnGround) {
self.isJumping = true;
self.isOnGround = false;
self.velocityY = -self.jumpHeight;
self.jumpState = "start";
self.jumpStartTime = Date.now();
self.currentPlatform = null;
} else if (self.isJumping && self.velocityY < 10) {
// Allow for a small double-jump to reach higher platforms
// Only if not falling too fast
self.velocityY = -self.jumpHeight * 0.7;
self.jumpStartTime = Date.now();
}
};
self.attack = function () {
if (!self.isAttacking) {
self.isAttacking = true;
self.attackFrame = 0;
self.animationCounter = 0;
}
};
self.checkPlatformCollision = function () {
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
var platformHalfWidth = platform.width / 2;
// The offset should match exactly how the player aligns with the lower platform initially
var playerPlatformOffset = 250; // This is the exact offset between player.y and lowPlatformHeight
// Check if player is above the platform and falling
if (self.velocityY > 0 &&
// Must be falling down
self.y < platform.y - playerPlatformOffset && self.y + self.velocityY >= platform.y - playerPlatformOffset && self.x > platform.x - platformHalfWidth && self.x < platform.x + platformHalfWidth) {
// Land on the platform with the exact same positioning as on the low platform
self.y = platform.y - playerPlatformOffset;
self.velocityY = 0;
self.isJumping = false;
self.isOnGround = true;
self.currentPlatform = platform;
return;
}
}
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000 // Black background
});
/****
* Game Code
****/
var backgroundContainer = game.addChild(new Container());
var midgroundContainer = game.addChild(new Container());
var foregroundContainer = game.addChild(new Container());
var scoreContainer = game.addChild(new Container());
var GAME_WIDTH = 2048;
var ENEMY_PLATFORM_OFFSET = 225; // Adjust this value
var platforms = [];
var platformWidth = 1000; // Define platform width based on asset size
var platformSpawnInterval = 60;
var platformSpawnCounter = 0;
var platformOverlap = 50;
var platformSpeed = 5; // Define platform speed globally
var platformSpawnInterval = 190;
// = (1000 - 50) / 5 = 190
// Define the two fixed platform heights
var lowPlatformHeight = 2732 / 1.5 + 250; // Regular height (player.y + 250)
var highPlatformHeight = lowPlatformHeight - 600; // High platform (600 pixels higher)
var minPlatformsInSequence = 5; // Minimum platforms in a sequence
var maxPlatformsInSequence = 10; // Maximum platforms in a sequence
var platformsUntilNextChange = 5; // Initial longer ground sequence
var currentPlatformHeight = lowPlatformHeight;
var lastPlatformHeight = lowPlatformHeight;
// Simple toggle for alternating platform heights
var useHighPlatform = false;
var platformGap = 200; // Gap between platforms
var lastPlatformX = 0; // Track the last platform position
var touchStartX = 0;
var touchStartY = 0;
var touchEndX = 0;
var touchEndY = 0;
var jars = [];
var coins = [];
var jarSpawnCounter = 0;
var jarSpawnInterval = 20; // Adjust as needed
var particleSystem;
//<Assets used in the game will automatically appear here>
// Background layer (slowest)
var bg1 = backgroundContainer.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 1
}));
var bg2 = backgroundContainer.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 1
}));
bg1.y = 2732; // Position at bottom of screen
bg2.y = 2732;
bg2.x = GAME_WIDTH;
// Midground layer
var mg1 = midgroundContainer.addChild(LK.getAsset('midground', {
anchorX: 0,
anchorY: 1
}));
var mg2 = midgroundContainer.addChild(LK.getAsset('midground', {
anchorX: 0,
anchorY: 1
}));
mg1.y = 2732;
mg2.y = 2732;
mg2.x = GAME_WIDTH;
// Foreground layer (fastest)
var fg1 = foregroundContainer.addChild(LK.getAsset('foreground', {
anchorX: 0,
anchorY: 1
}));
var fg2 = foregroundContainer.addChild(LK.getAsset('foreground', {
anchorX: 0,
anchorY: 1
}));
fg1.y = 2732 * 1.25;
fg2.y = 2732 * 1.25;
fg1.x = 0;
fg2.x = GAME_WIDTH;
// Initialize player
var player = game.addChild(new Player());
player.x = 2048 / 4.5;
player.y = 2732 / 1.5;
// Initialize enemies
var enemies = [];
var enemySpawnInterval = 100;
var enemySpawnCounter = 0;
// Create a new Text2 object to display the score
var scoreText = new Text2('0', {
size: 160,
fill: 0xFFFFFF,
anchorX: 1,
// Anchor text to right edge
anchorY: 0.5 // Center text vertically
});
var coinIcon = LK.getAsset('coin', {
anchorX: 0,
anchorY: 0.5,
scaleX: 2,
scaleY: 2
});
scoreContainer.addChild(scoreText);
scoreContainer.addChild(coinIcon);
// Position container in top right
scoreContainer.x = 2048 - 100; // 50 pixels from right edge
scoreContainer.y = 100; // 50 pixels from top
// Position elements within container
scoreText.x = -100; // Offset left from container position
scoreText.y = -100;
coinIcon.x = 0; // At container position
coinIcon.y = 0;
// Initialize the game with starting platforms
function initializeGame() {
// Create initial platforms at the low level
for (var i = 0; i < 5; i++) {
var platform = new Platform();
if (i === 0) {
// First platform centered on player
platform.x = player.x;
} else {
// Position with slight overlap
platform.x = lastPlatformX + platformWidth - platformOverlap;
}
platform.y = lowPlatformHeight;
platforms.push(platform);
game.addChild(platform);
lastPlatformX = platform.x;
}
lastPlatformHeight = lowPlatformHeight;
player.isOnGround = true;
player.currentPlatform = platforms[0];
}
initializeGame();
particleSystem = new ParticlePool(100);
game.addChild(particleSystem);
// Handle game updates
game.update = function () {
// Scroll backgrounds
bg1.x -= platformSpeed * 0.3;
bg2.x -= platformSpeed * 0.3;
if (bg1.x <= -GAME_WIDTH) {
bg1.x = bg2.x + GAME_WIDTH;
}
if (bg2.x <= -GAME_WIDTH) {
bg2.x = bg1.x + GAME_WIDTH;
}
mg1.x -= platformSpeed * 0.6;
mg2.x -= platformSpeed * 0.6;
if (mg1.x <= -GAME_WIDTH) {
mg1.x = mg2.x + GAME_WIDTH;
}
if (mg2.x <= -GAME_WIDTH) {
mg2.x = mg1.x + GAME_WIDTH;
}
// Scroll foreground (four instances)
fg1.x -= platformSpeed;
fg2.x -= platformSpeed;
if (fg1.x <= -GAME_WIDTH) {
fg1.x = fg2.x + GAME_WIDTH;
}
if (fg2.x <= -GAME_WIDTH) {
fg2.x = fg1.x + GAME_WIDTH;
}
player.update();
if (particleSystem) {
particleSystem.update();
}
// Check if we need to spawn a new sequence of platforms
var lastPlatform = platforms[platforms.length - 1];
if (lastPlatform && lastPlatform.x < GAME_WIDTH + 500) {
// Spawn further off-screen to prevent pop-in
// Time to spawn a new sequence
if (platformsUntilNextChange <= 0) {
// Switch height
currentPlatformHeight = currentPlatformHeight === lowPlatformHeight ? highPlatformHeight : lowPlatformHeight;
// Generate new random sequence length
platformsUntilNextChange = Math.floor(Math.random() * (maxPlatformsInSequence - minPlatformsInSequence + 1)) + minPlatformsInSequence;
// Make ground sequences longer
if (currentPlatformHeight === lowPlatformHeight) {
platformsUntilNextChange += 5;
}
}
// Spawn a single platform in the sequence
var platform = new Platform();
platform.x = lastPlatform.x + (platformWidth - platformOverlap);
platform.y = currentPlatformHeight;
platforms.push(platform);
game.addChild(platform);
// Decrement the counter for each platform added
platformsUntilNextChange--;
}
// Update platforms
for (var i = platforms.length - 1; i >= 0; i--) {
platforms[i].update();
// Remove platforms that are destroyed
if (platforms[i].destroyed) {
platforms.splice(i, 1);
}
}
jarSpawnCounter++;
if (jarSpawnCounter >= jarSpawnInterval) {
var availablePlatforms = platforms.filter(function (p) {
return p.x > 2048 && p.x < 2048 + 300;
});
if (availablePlatforms.length > 0 && Math.random() < 0.3) {
var platform = availablePlatforms[Math.floor(Math.random() * availablePlatforms.length)];
var jar = new Jar();
jar.x = platform.x;
jar.y = platform.y - 130; // Increased offset to match ENEMY_PLATFORM_OFFSET
jar.currentPlatform = platform;
jars.push(jar);
game.addChild(jar);
}
jarSpawnCounter = 0;
}
// Update jars
for (var i = jars.length - 1; i >= 0; i--) {
var jar = jars[i];
if (jar.currentPlatform) {
jar.x = jar.currentPlatform.x; // Move with platform
}
// Check for player attack collision
if (player.isAttacking) {
var attackRange = 200; // Adjust based on player's attack animation
var verticalRange = 150; // Adjust based on player and jar heights
var distanceX = Math.abs(jar.x - player.x);
var distanceY = Math.abs(jar.y - player.y);
if (distanceX < attackRange && distanceY < verticalRange) {
jar["break"]();
jars.splice(i, 1);
continue;
}
}
// Remove if off screen
if (jar.x < -50) {
jar.destroy();
jars.splice(i, 1);
}
}
// Update coins
for (var i = coins.length - 1; i >= 0; i--) {
coins[i].update();
if (coins[i].destroyed) {
coins.splice(i, 1);
}
}
// Enemy handling (keep your existing enemy code)
enemySpawnCounter++;
if (enemySpawnCounter >= enemySpawnInterval) {
// Only spawn enemies if there are valid platforms available
var availablePlatforms = platforms.filter(function (p) {
// Look for platforms that are just off-screen to the right
return p.x > 2048 - 100 && p.x < 2048 + 300;
});
// Only spawn an enemy if we have a platform to put it on
if (availablePlatforms.length > 0) {
var enemy = new Enemy('goblin');
var platform = availablePlatforms[Math.floor(Math.random() * availablePlatforms.length)];
enemy.x = platform.x; // Spawn directly above the platform
enemy.y = platform.y - ENEMY_PLATFORM_OFFSET;
enemy.currentPlatform = platform;
enemies.push(enemy);
game.addChild(enemy);
enemySpawnInterval = Math.floor(Math.random() * 150) + 100; // Slightly longer intervals
enemySpawnCounter = 0;
} else {
// No valid platforms, just reset counter but don't spawn
enemySpawnCounter = Math.max(0, enemySpawnCounter - 20); // Back up a bit to try again soon
}
}
// Update enemies
for (var j = enemies.length - 1; j >= 0; j--) {
enemies[j].update();
var playerBounds = player.getBounds();
var enemyBounds = enemies[j].getBounds();
if (playerBounds.left < enemyBounds.right && playerBounds.right > enemyBounds.left && playerBounds.top < enemyBounds.bottom && playerBounds.bottom > enemyBounds.top) {
if (player.isAttacking) {
// Hit the enemy if player is attacking
enemies[j].hit();
// Add score if not already passed
if (!enemies[j].passed) {
enemies[j].passed = true;
LK.setScore(LK.getScore() + 1);
scoreText.setText(LK.getScore());
}
} else if (!enemies[j].isHit && !enemies[j].isDying) {
// Only die from enemy touch if enemy isn't already hit/dying
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
} else if (player.x > enemies[j].x && !enemies[j].passed) {
enemies[j].passed = true;
//LK.setScore(LK.getScore() + 1);
//scoreText.setText(LK.getScore());
}
}
};
// Handle player jump
game.down = function (x, y, obj) {
touchStartX = x;
touchStartY = y;
};
game.up = function (x, y, obj) {
touchEndX = x;
touchEndY = y;
// Calculate swipe
var deltaY = touchStartY - touchEndY;
var deltaX = Math.abs(touchStartX - touchEndX);
// If vertical swipe (more vertical than horizontal movement)
if (deltaY > 50 && deltaY > deltaX) {
player.jump();
} else {
// Regular tap/click triggers attack
player.attack();
}
};
var backgroundContainer = game.addChild(new Container());
var midgroundContainer = game.addChild(new Container());
var foregroundContainer = game.addChild(new Container());
var scoreContainer = game.addChild(new Container());
var GAME_WIDTH = 2048;
var ENEMY_PLATFORM_OFFSET = 225; // Adjust this value
var platforms = [];
var platformWidth = 1000; // Define platform width based on asset size
var platformSpawnInterval = 60;
var platformSpawnCounter = 0;
var platformOverlap = 50;
var platformSpeed = 5; // Define platform speed globally
var platformSpawnInterval = 190;
// = (1000 - 50) / 5 = 190
// Define the two fixed platform heights
var lowPlatformHeight = 2732 / 1.5 + 250; // Regular height (player.y + 250)
var highPlatformHeight = lowPlatformHeight - 600; // High platform (600 pixels higher)
var minPlatformsInSequence = 5; // Minimum platforms in a sequence
var maxPlatformsInSequence = 10; // Maximum platforms in a sequence
var platformsUntilNextChange = 5; // Initial longer ground sequence
var currentPlatformHeight = lowPlatformHeight;
var lastPlatformHeight = lowPlatformHeight;
// Simple toggle for alternating platform heights
var useHighPlatform = false;
var platformGap = 200; // Gap between platforms
var lastPlatformX = 0; // Track the last platform position
var touchStartX = 0;
var touchStartY = 0;
var touchEndX = 0;
var touchEndY = 0;
var jars = [];
var coins = [];
var jarSpawnCounter = 0;
var jarSpawnInterval = 20; // Adjust as needed
var particleSystem;
//<Assets used in the game will automatically appear here>
// Background layer (slowest)
var bg1 = backgroundContainer.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 1
}));
var bg2 = backgroundContainer.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 1
}));
bg1.y = 2732; // Position at bottom of screen
bg2.y = 2732;
bg2.x = GAME_WIDTH;
// Midground layer
var mg1 = midgroundContainer.addChild(LK.getAsset('midground', {
anchorX: 0,
anchorY: 1
}));
var mg2 = midgroundContainer.addChild(LK.getAsset('midground', {
anchorX: 0,
anchorY: 1
}));
mg1.y = 2732;
mg2.y = 2732;
mg2.x = GAME_WIDTH;
// Foreground layer (fastest)
var fg1 = foregroundContainer.addChild(LK.getAsset('foreground', {
anchorX: 0,
anchorY: 1
}));
var fg2 = foregroundContainer.addChild(LK.getAsset('foreground', {
anchorX: 0,
anchorY: 1
}));
fg1.y = 2732 * 1.25;
fg2.y = 2732 * 1.25;
fg1.x = 0;
fg2.x = GAME_WIDTH;
// Initialize player
var player = game.addChild(new Player());
player.x = 2048 / 4.5;
player.y = 2732 / 1.5;
// Initialize enemies
var enemies = [];
var enemySpawnInterval = 100;
var enemySpawnCounter = 0;
// Create a new Text2 object to display the score
var scoreText = new Text2('0', {
size: 160,
fill: 0xFFFFFF,
anchorX: 1,
// Anchor text to right edge
anchorY: 0.5 // Center text vertically
});
var coinIcon = LK.getAsset('coin', {
anchorX: 0,
anchorY: 0.5,
scaleX: 2,
scaleY: 2
});
scoreContainer.addChild(scoreText);
scoreContainer.addChild(coinIcon);
// Position container in top right
scoreContainer.x = 2048 - 100; // 50 pixels from right edge
scoreContainer.y = 100; // 50 pixels from top
// Position elements within container
scoreText.x = -100; // Offset left from container position
scoreText.y = -100;
coinIcon.x = 0; // At container position
coinIcon.y = 0;
// Initialize the game with starting platforms
initializeGame();
particleSystem = new ParticlePool(100);
game.addChild(particleSystem);
// Handle game updates
game.update = function () {
// Scroll backgrounds
bg1.x -= platformSpeed * 0.3;
bg2.x -= platformSpeed * 0.3;
if (bg1.x <= -GAME_WIDTH) {
bg1.x = bg2.x + GAME_WIDTH;
}
if (bg2.x <= -GAME_WIDTH) {
bg2.x = bg1.x + GAME_WIDTH;
}
mg1.x -= platformSpeed * 0.6;
mg2.x -= platformSpeed * 0.6;
if (mg1.x <= -GAME_WIDTH) {
mg1.x = mg2.x + GAME_WIDTH;
}
if (mg2.x <= -GAME_WIDTH) {
mg2.x = mg1.x + GAME_WIDTH;
}
// Scroll foreground (four instances)
fg1.x -= platformSpeed;
fg2.x -= platformSpeed;
if (fg1.x <= -GAME_WIDTH) {
fg1.x = fg2.x + GAME_WIDTH;
}
if (fg2.x <= -GAME_WIDTH) {
fg2.x = fg1.x + GAME_WIDTH;
}
player.update();
if (particleSystem) {
particleSystem.update();
}
// Check if we need to spawn a new sequence of platforms
var lastPlatform = platforms[platforms.length - 1];
if (lastPlatform && lastPlatform.x < GAME_WIDTH + 500) {
// Spawn further off-screen to prevent pop-in
// Time to spawn a new sequence
if (platformsUntilNextChange <= 0) {
// Switch height
currentPlatformHeight = currentPlatformHeight === lowPlatformHeight ? highPlatformHeight : lowPlatformHeight;
// Generate new random sequence length
platformsUntilNextChange = Math.floor(Math.random() * (maxPlatformsInSequence - minPlatformsInSequence + 1)) + minPlatformsInSequence;
// Make ground sequences longer
if (currentPlatformHeight === lowPlatformHeight) {
platformsUntilNextChange += 5;
}
}
// Spawn a single platform in the sequence
var platform = new Platform();
platform.x = lastPlatform.x + (platformWidth - platformOverlap);
platform.y = currentPlatformHeight;
platforms.push(platform);
game.addChild(platform);
// Decrement the counter for each platform added
platformsUntilNextChange--;
}
// Update platforms
for (var i = platforms.length - 1; i >= 0; i--) {
platforms[i].update();
// Remove platforms that are destroyed
if (platforms[i].destroyed) {
platforms.splice(i, 1);
}
}
jarSpawnCounter++;
if (jarSpawnCounter >= jarSpawnInterval) {
var availablePlatforms = platforms.filter(function (p) {
return p.x > 2048 && p.x < 2048 + 300;
});
if (availablePlatforms.length > 0 && Math.random() < 0.3) {
var platform = availablePlatforms[Math.floor(Math.random() * availablePlatforms.length)];
var jar = new Jar();
jar.x = platform.x;
jar.y = platform.y - 130; // Increased offset to match ENEMY_PLATFORM_OFFSET
jar.currentPlatform = platform;
jars.push(jar);
game.addChild(jar);
}
jarSpawnCounter = 0;
}
// Update jars
for (var i = jars.length - 1; i >= 0; i--) {
var jar = jars[i];
if (jar.currentPlatform) {
jar.x = jar.currentPlatform.x; // Move with platform
}
// Check for player attack collision
if (player.isAttacking) {
var attackRange = 200; // Adjust based on player's attack animation
var verticalRange = 150; // Adjust based on player and jar heights
var distanceX = Math.abs(jar.x - player.x);
var distanceY = Math.abs(jar.y - player.y);
if (distanceX < attackRange && distanceY < verticalRange) {
jar["break"]();
jars.splice(i, 1);
continue;
}
}
// Remove if off screen
if (jar.x < -50) {
jar.destroy();
jars.splice(i, 1);
}
}
// Update coins
for (var i = coins.length - 1; i >= 0; i--) {
coins[i].update();
if (coins[i].destroyed) {
coins.splice(i, 1);
}
}
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child instanceof ScorePopup) {
child.update();
}
}
// Enemy handling (keep your existing enemy code)
enemySpawnCounter++;
if (enemySpawnCounter >= enemySpawnInterval) {
// Only spawn enemies if there are valid platforms available
var availablePlatforms = platforms.filter(function (p) {
// Look for platforms that are just off-screen to the right
return p.x > 2048 - 100 && p.x < 2048 + 300;
});
// Only spawn an enemy if we have a platform to put it on
if (availablePlatforms.length > 0) {
var enemy = new Enemy('goblin');
var platform = availablePlatforms[Math.floor(Math.random() * availablePlatforms.length)];
enemy.x = platform.x; // Spawn directly above the platform
enemy.y = platform.y - ENEMY_PLATFORM_OFFSET;
enemy.currentPlatform = platform;
enemies.push(enemy);
game.addChild(enemy);
enemySpawnInterval = Math.floor(Math.random() * 150) + 100; // Slightly longer intervals
enemySpawnCounter = 0;
} else {
// No valid platforms, just reset counter but don't spawn
enemySpawnCounter = Math.max(0, enemySpawnCounter - 20); // Back up a bit to try again soon
}
}
// Update enemies
for (var j = enemies.length - 1; j >= 0; j--) {
enemies[j].update();
var playerBounds = player.getBounds();
var enemyBounds = enemies[j].getBounds();
if (playerBounds.left < enemyBounds.right && playerBounds.right > enemyBounds.left && playerBounds.top < enemyBounds.bottom && playerBounds.bottom > enemyBounds.top) {
if (player.isAttacking) {
// Hit the enemy if player is attacking
enemies[j].hit();
// Add score if not already passed
if (!enemies[j].passed) {
enemies[j].passed = true;
LK.setScore(LK.getScore() + 1);
scoreText.setText(LK.getScore());
}
} else if (!enemies[j].isHit && !enemies[j].isDying) {
// Only die from enemy touch if enemy isn't already hit/dying
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
} else if (player.x > enemies[j].x && !enemies[j].passed) {
enemies[j].passed = true;
//LK.setScore(LK.getScore() + 1);
//scoreText.setText(LK.getScore());
}
}
};
// Handle player jump
game.down = function (x, y, obj) {
touchStartX = x;
touchStartY = y;
};
game.up = function (x, y, obj) {
touchEndX = x;
touchEndY = y;
// Calculate swipe
var deltaY = touchStartY - touchEndY;
var deltaX = Math.abs(touchStartX - touchEndX);
// If vertical swipe (more vertical than horizontal movement)
if (deltaY > 50 && deltaY > deltaX) {
player.jump();
} else {
// Regular tap/click triggers attack
player.attack();
}
};
2D Single Monster. In-Game asset. 2d. Blank background. High contrast. No shadows..
A gold coin. 8 bit pixel art. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Dark and moody dungeon background. Infinite repeatable texture. 8 bit pixel art.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A ruby. Pixel art.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A wooden arrow with white feathers and a steel arrow head. Horizontal. Pixel art. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A thin crude sword, no pommel. 8 bit pixel art.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
An icon of white wings. Pixel art.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
a magnet icon. 8 bit pixel art. In-Game asset. 2d. High contrast. No shadows
An icon of a glowing wooden arrow from a bow trailing pink particles. Pixel art.. In-Game asset. 2d. High contrast. No shadows
backgroundmusic1
Music
playerjump
Sound effect
swordslash
Sound effect
jarbreak
Sound effect
enemyhit
Sound effect
eyeballhit
Sound effect
coincollect
Sound effect
woodbreak
Sound effect
coinbounce
Sound effect
potion
Sound effect
playerouch
Sound effect
bowfiring
Sound effect
arrowfire
Sound effect
arrowpickup
Sound effect
gameover
Sound effect
skeletonhit
Sound effect
gameover2
Sound effect
shopbuy
Sound effect
menuselect
Sound effect
cantbuy
Sound effect
startgame
Sound effect
platformcrumble
Sound effect
rocksfall
Sound effect
airdash
Sound effect
groundimpact
Sound effect
groundsmashfalling
Sound effect
slide
Sound effect
mushroomburst
Sound effect
mushroomhiss
Sound effect
mushroomdie
Sound effect
mushroombounce
Sound effect