Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: scoreText.setText is not a function' in or related to this line: 'scoreText.setText("Score: " + score);' Line Number: 806
User prompt
in fliprunner, the score is not visible on screen, fix it
User prompt
Please fix the bug: 'TypeError: scoreText.setText is not a function' in or related to this line: 'scoreText.setText("Score: " + score);' Line Number: 806
User prompt
var scoreText = flipRunnerContainer.children[1]; should be visible
User prompt
polarity shift game needs a score visible on the screen
User prompt
Please fix the bug: 'TypeError: scoreText.setText is not a function' in or related to this line: 'scoreText.setText("Score: " + score);' Line Number: 805
User prompt
game #1 should be not doodle jump but it should be an endless sidescroller runner in a tunnel where the goal is to tap the screen to flip polarity ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: catNinjaContainer.children[1].setText is not a function' in or related to this line: 'catNinjaContainer.children[1].setText("Score: " + player.score);' Line Number: 594
User prompt
Please fix the bug: 'Timeout.tick error: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'resultText.style.fill = "#E74C3C";' Line Number: 492
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'call')' in or related to this line: 'Button.prototype.up.call(this);' Line Number: 249
Code edit (1 edits merged)
Please save this source code
User prompt
Meme Arcade Mashup
User prompt
we are making a 3 in 1 game, all three available games are meme based, there will be a splash screen, follow by a game selection screen where there will be 3 game options available on screen each will boot to their own respective meme game
User prompt
i don't like the stonks meme game idea
User prompt
the three games will be meme cultured base
User prompt
Please continue polishing my design document.
Initial prompt
we are making a 3 in 1 game, there will be a splash screen, follow by a game selection screen where there will be 3 options available on screen each will boot to their own respective game
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore1: 0, highScore2: 0, highScore3: 0 }); /**** * Classes ****/ var Button = Container.expand(function (text, width, height) { var self = Container.call(this); var buttonShape = self.attachAsset('selectionButton', { anchorX: 0.5, anchorY: 0.5, width: width || 400, height: height || 300 }); // Add gradient and shadow effect to button buttonShape.tint = 0x4287f5; // Create enhanced text with shadow and better styling var buttonText = new Text2(text, { size: 50, fill: 0xFFFFFF, align: 'center', stroke: 0x000000, strokeThickness: 5, dropShadow: true, dropShadowColor: 0x000000, dropShadowAngle: Math.PI / 6, dropShadowDistance: 4 }); buttonText.anchor.set(0.5, 0.5); self.addChild(buttonText); // Enhanced down effect with scale self.down = function () { buttonShape.alpha = 0.8; LK.getSound('buttonClick').play(); // Add scale effect on press tween(self.scale, { x: 0.95, y: 0.95 }, { duration: 100, easing: tween.easeOutQuad }); // Add glow effect LK.effects.flashObject(buttonShape, 0x66ccff, 300); }; // Enhanced up effect self.up = function () { buttonShape.alpha = 1.0; // Return to normal scale with slight bounce tween(self.scale, { x: 1.0, y: 1.0 }, { duration: 200, easing: tween.bounceOut }); }; return self; }); // CoinFlip classes var Coin = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); self.isHeads = true; self.isFlipping = false; self.flip = function () { if (self.isFlipping) { return; } self.isFlipping = true; LK.getSound('flip').play(); var flips = Math.floor(Math.random() * 10) + 5; var flipDuration = 1500; function doFlip(flipsLeft) { if (flipsLeft <= 0) { self.isFlipping = false; self.isHeads = Math.random() >= 0.5; return; } tween(coinGraphics, { scaleX: 0 }, { duration: flipDuration / (flipsLeft * 2), onFinish: function onFinish() { self.isHeads = !self.isHeads; coinGraphics.tint = self.isHeads ? 0xF1C40F : 0xE67E22; tween(coinGraphics, { scaleX: 1 }, { duration: flipDuration / (flipsLeft * 2), onFinish: function onFinish() { doFlip(flipsLeft - 1); } }); } }); } doFlip(flips); }; return self; }); var CryptoCoin = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('crypto', { anchorX: 0.5, anchorY: 0.5, width: 100, height: 100 }); self.speed = Math.random() * 3 + 3; self.rotationSpeed = (Math.random() - 0.5) * 0.1; self.update = function () { self.y += self.speed; self.rotation += self.rotationSpeed; }; return self; }); var CryptoObstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('Trollface', { anchorX: 0.5, anchorY: 0.5, width: 150, height: 150 }); self.speed = Math.random() * 5 + 5; self.rotationSpeed = (Math.random() - 0.5) * 0.2; self.update = function () { self.y += self.speed; self.rotation += self.rotationSpeed; }; return self; }); // Add prototype method for Button so Button.prototype.up can be called // Doge Dodge classes var DogePlayer = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('Doge', { anchorX: 0.5, anchorY: 0.5, width: 200, height: 200 }); self.score = 0; self.lives = 1; self.speedX = 8; // Horizontal bouncing speed self.direction = 1; // 1 for right, -1 for left self.lastX = 0; // Track last X position // Bounce movement logic self.update = function () { // Store last position self.lastX = self.x; // Move in current direction self.x += self.speedX * self.direction; // Bounce off edges if (self.x <= 100 && self.direction < 0) { self.direction = 1; self.x = 100; LK.getSound('jump').play(); LK.effects.flashObject(self, 0x00FFFF, 300); } else if (self.x >= 1948 && self.direction > 0) { self.direction = -1; self.x = 1948; LK.getSound('jump').play(); LK.effects.flashObject(self, 0x00FFFF, 300); } }; // Change direction when clicked self.down = function () { self.direction *= -1; LK.getSound('flip').play(); LK.effects.flashObject(self, 0xFFFFFF, 300); }; self.collect = function (coin) { LK.getSound('cashding').play(); LK.effects.flashObject(coin, 0x00FFFF, 300); // Cyan flash for crypto self.score += 10; return true; }; self.hurt = function (obstacle) { LK.getSound('oof').play(); LK.effects.flashObject(self, 0xFF0000, 300); self.lives -= 1; return self.lives <= 0; }; return self; }); var DoodlePlatform = Container.expand(function (x, y) { var self = Container.call(this); var platformGraphics = self.attachAsset('doodlePlatform', { anchorX: 0.5, anchorY: 0.5 }); }); // DoodleJump classes var DoodlePlayer = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('doodlePlayer', { anchorX: 0.5, anchorY: 0.5 }); self.velocityY = 0; self.gravity = 0.5; self.jumpPower = -15; self.jump = function () { self.velocityY = self.jumpPower; LK.getSound('jump').play(); }; self.update = function () { self.velocityY += self.gravity; self.y += self.velocityY; }; return self; }); var FlipRunnerObstacle = Container.expand(function (yPosition, speed) { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstaclerunner', { anchorX: 0.5, anchorY: 0.5, width: 100, height: 100 }); // Determine if obstacle is on top (–1) or bottom (+1) self.polarity = yPosition > 1366 ? -1 : 1; self.speed = speed || 15; self.x = 2200; // start just off‐screen on the right self.y = yPosition; // Color based on polarity obstacleGraphics.tint = self.polarity > 0 ? 0x27ae60 : 0xe74c3c; // Move left each frame self.update = function () { self.x -= self.speed; }; return self; }); var FlipRunnerPlayer = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('catPlayer', { anchorX: 0.5, anchorY: 0.5 }); self.polarity = 1; // 1 for top, -1 for bottom self.speed = 10; self.score = 0; self.isAlive = true; self.isFlipping = false; // Track if we're in the middle of a flip self.animationActive = false; // Initialize running animation self.startRunningAnimation = function () { if (self.animationActive) { return; } self.animationActive = true; function animateRunCycle() { // Squash and stretch effect for running tween(playerGraphics.scale, { x: playerGraphics.scale.x > 0 ? 1.2 : -1.2, y: 0.8 }, { duration: 150, onFinish: function onFinish() { tween(playerGraphics.scale, { x: playerGraphics.scale.x > 0 ? 0.8 : -0.8, y: 1.2 }, { duration: 150, onFinish: function onFinish() { // Only continue animation if player is alive if (self.isAlive && self.animationActive) { animateRunCycle(); } else { // Reset to normal scale when stopped tween(playerGraphics.scale, { x: self.polarity > 0 ? -1 : 1, y: 1 }, { duration: 100 }); self.animationActive = false; } } }); } }); } // Start the animation cycle animateRunCycle(); }; self.flip = function () { if (!self.isAlive) { return; } // Don't allow flip if we're already in the middle of a flip if (self.isFlipping) { return; } self.isFlipping = true; self.polarity *= -1; LK.getSound('flip').play(); LK.getSound('jump').play(); // Store current position var startY = self.y; var targetY = self.polarity > 0 ? 600 : 2132; var midY = (startY + targetY) / 2; // Add trail effect function createTrailEffect() { var trail = new Container(); var trailGraphics = trail.attachAsset('catPlayer', { anchorX: 0.5, anchorY: 0.5, width: playerGraphics.width, height: playerGraphics.height }); // Match player's current appearance trailGraphics.scale.x = playerGraphics.scale.x; trailGraphics.scale.y = playerGraphics.scale.y; trailGraphics.rotation = playerGraphics.rotation; // Position trail at player position trail.x = self.x; trail.y = self.y; trail.alpha = 0.5; // Add to the same parent as player self.parent.addChild(trail); // Fade out and remove tween(trail, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { self.parent.removeChild(trail); } }); } // Create multiple trails during flip var trailTimer = LK.setInterval(createTrailEffect, 50); // Animate the flip with arc motion tween(self, { y: midY - 200 // Arc up higher than direct path }, { duration: 150, easing: tween.easeOutQuad, onFinish: function onFinish() { // Then down to destination tween(self, { y: targetY }, { duration: 150, easing: tween.bounceOut, onFinish: function onFinish() { // Clear trail timer when animation completes LK.clearInterval(trailTimer); // Set flipping to false to allow flipping again self.isFlipping = false; } }); } }); // Visual effect when flipping - rotate during movement tween(playerGraphics, { rotation: self.polarity > 0 ? 0 : Math.PI, scaleX: self.polarity > 0 ? -1.3 : 1.3, // Stretch a bit during flip scaleY: 0.7 }, { duration: 150, onFinish: function onFinish() { tween(playerGraphics, { scaleX: self.polarity > 0 ? -1 : 1, scaleY: 1 }, { duration: 150, easing: tween.bounceOut }); } }); }; self.update = function () { self.score += 0.1; // Invert player's X when on top side of the screen if (self.polarity > 0) { // Top side - flip X playerGraphics.scale.x = -1; } else { // Bottom side - normal X playerGraphics.scale.x = 1; } // Start running animation if not already started and player is alive if (self.isAlive && !self.animationActive) { self.startRunningAnimation(); } }; self.die = function () { if (!self.isAlive) { return; } self.isAlive = false; self.animationActive = false; LK.getSound('oof').play(); LK.getSound('oof').play(); LK.effects.flashObject(self, 0xFF0000, 500); }; return self; }); var FlipRunnerTunnel = Container.expand(function () { var self = Container.call(this); // Top wall var topWall = self.attachAsset('doodlePlatform', { anchorX: 0, anchorY: 0, width: 2048, height: 400 }); topWall.tint = 0xFF0000; // Start with red for rainbow effect // Create top glow effect var topGlow = self.attachAsset('doodlePlatform', { anchorX: 0, anchorY: 0, width: 2048, height: 450 }); topGlow.alpha = 0.4; topGlow.tint = 0xFF0000; // Bottom wall var bottomWall = self.attachAsset('doodlePlatform', { anchorX: 0, anchorY: 1, width: 2048, height: 400 }); bottomWall.tint = 0x0000FF; // Start with blue for contrast bottomWall.y = 2732; // Create bottom glow effect var bottomGlow = self.attachAsset('doodlePlatform', { anchorX: 0, anchorY: 1, width: 2048, height: 450 }); bottomGlow.y = 2732; bottomGlow.alpha = 0.4; bottomGlow.tint = 0x0000FF; this.topWall = topWall; this.bottomWall = bottomWall; this.topGlow = topGlow; this.bottomGlow = bottomGlow; this.initialGap = bottomWall.y - bottomWall.height - topWall.height; this.gap = this.initialGap; this.shrinkRate = 0.1; // pixels per frame (tweak as desired) this.update = function () { // shrink the gap, but don't go below 400px this.gap = Math.max(400, this.gap - this.shrinkRate); // recalc each wall's height so the total gap is correct var newWallHeight = (2732 - this.gap) / 2; this.topWall.height = newWallHeight; this.bottomWall.height = newWallHeight; this.bottomWall.y = 2732; // anchorY=1 keeps it flush to bottom // Update glow positions and sizes to match walls this.topGlow.height = newWallHeight + 50; this.bottomGlow.height = newWallHeight + 50; this.bottomGlow.y = 2732; // expose gap edges for collision detection this.topY = this.topWall.height; this.bottomY = this.bottomWall.y - this.bottomWall.height; // Apply rainbow effect to glows var colors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x9400D3]; var now = Date.now(); var colorIndex = Math.floor(now / 100 % colors.length); var nextColorIndex = (colorIndex + 1) % colors.length; var progress = now % 100 / 100; // Calculate intermediate color between current and next var currentColor = colors[colorIndex]; var nextColor = colors[nextColorIndex]; // Extract RGB components var r1 = currentColor >> 16 & 0xFF; var g1 = currentColor >> 8 & 0xFF; var b1 = currentColor & 0xFF; var r2 = nextColor >> 16 & 0xFF; var g2 = nextColor >> 8 & 0xFF; var b2 = nextColor & 0xFF; // Interpolate between colors var r = Math.floor(r1 + (r2 - r1) * progress); var g = Math.floor(g1 + (g2 - g1) * progress); var b = Math.floor(b1 + (b2 - b1) * progress); // Create interpolated color var rainbowColor = r << 16 | g << 8 | b; // Apply to both glow effects this.topGlow.tint = rainbowColor; this.bottomGlow.tint = rainbowColor; this.topGlow.alpha = 0.8; // Increase glow visibility this.bottomGlow.alpha = 0.8; // Increase glow visibility // Bottom glow is color-shifted for variety var oppositeIndex = (colorIndex + 3) % colors.length; var oppositeNextIndex = (oppositeIndex + 1) % colors.length; var oppositeColor = colors[oppositeIndex]; var oppositeNextColor = colors[oppositeNextIndex]; // Extract RGB components for opposite var or1 = oppositeColor >> 16 & 0xFF; var og1 = oppositeColor >> 8 & 0xFF; var ob1 = oppositeColor & 0xFF; var or2 = oppositeNextColor >> 16 & 0xFF; var og2 = oppositeNextColor >> 8 & 0xFF; var ob2 = oppositeNextColor & 0xFF; // Interpolate between opposite colors var or = Math.floor(or1 + (or2 - or1) * progress); var og = Math.floor(og1 + (og2 - og1) * progress); var ob = Math.floor(ob1 + (ob2 - ob1) * progress); // Create interpolated opposite color var oppositeRainbowColor = or << 16 | og << 8 | ob; this.bottomGlow.tint = oppositeRainbowColor; }; return self; }); var HomeButton = Container.expand(function () { var self = Container.call(this); // Home button uses text only, no shape var buttonText = new Text2("", { size: 40, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 5 }); buttonText.anchor.set(0.5, 0.5); self.addChild(buttonText); self.down = function () { buttonText.alpha = 0.7; LK.getSound('buttonClick').play(); }; self.up = function () { buttonText.alpha = 1.0; switchToMainMenu(); }; return self; }); var MemeCoin = Container.expand(function () { var self = Container.call(this); // Create both sides of the coin with meme faces var headsSide = self.attachAsset('Doge', { anchorX: 0.5, anchorY: 0.5, width: 200, height: 200 }); var tailsSide = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5, width: 200, height: 200 }); // Only show heads initially tailsSide.alpha = 0; self.isHeads = true; self.isFlipping = false; self.onFlipComplete = null; // Add coin background circle var coinBg = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5, width: 220, height: 220 }); // Place circle behind faces // Implement our own swapChildren since it doesn't exist function swapChildren(parent, child1, child2) { var index1 = parent.children.indexOf(child1); var index2 = parent.children.indexOf(child2); if (index1 !== -1 && index2 !== -1) { // Remove both children parent.removeChild(child1); parent.removeChild(child2); // Add them back in swapped order if (index1 < index2) { parent.addChildAt(child2, index1); parent.addChildAt(child1, index2); } else { parent.addChildAt(child1, index2); parent.addChildAt(child2, index1); } } } swapChildren(self, coinBg, headsSide); swapChildren(self, coinBg, tailsSide); // Enhanced coin flip with meme animations self.flip = function () { if (self.isFlipping) { return; } // Start countdown before flipping var countdownText = new Text2("3", { size: 300, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 16 }); countdownText.anchor.set(0.5, 0.5); self.addChild(countdownText); // Play countdown sound at 50% speed LK.getSound('countdown').play({ speed: 0.5 }); // Countdown animation with accelerated speed function countdown(num) { if (num > 0) { countdownText.setText(num.toString()); // Pulse animation for countdown - faster duration tween(countdownText.scale, { x: 1.5, y: 1.5 }, { duration: 150, // reduced from 300ms yoyo: true, repeat: 1, onFinish: function onFinish() { LK.setTimeout(function () { countdown(num - 1); }, 100); // reduced from 200ms } }); } else { countdownText.setText("FLIP!", { stroke: 0x000000, strokeThickness: 16, fill: 0xFFFFFF, size: 300 }); // Flash and scale animation for "FLIP!" - faster LK.effects.flashObject(countdownText, 0xFFFF00, 150); // reduced from 300ms tween(countdownText.scale, { x: 2, y: 2 }, { duration: 150, // reduced from 300ms onFinish: function onFinish() { LK.setTimeout(function () { self.removeChild(countdownText); self.startFlip(); }, 150); // reduced from 300ms } }); } } countdown(3); }; self.startFlip = function () { self.isFlipping = true; LK.getSound('flip').play(); // Decide the outcome upfront var finalIsHeads = Math.random() >= 0.5; // Random number of flips (more than original for drama) var flips = Math.floor(Math.random() * 10) + 8; var flipDuration = 2000; // Longer flip for more suspense // Shake screen effect LK.effects.shakeScreen(10, 500); // Initial position for bounce effect var originalY = self.y; // Make the coin bounce up first tween(self, { y: originalY - 200 }, { duration: 300, easing: tween.easeOutQuad, onFinish: function onFinish() { // Now start the flipping as coin comes down doFlip(flips); // Return to original position with bounce tween(self, { y: originalY }, { duration: 600, easing: tween.bounceOut }); } }); function doFlip(flipsLeft) { if (flipsLeft <= 0) { self.isFlipping = false; self.isHeads = finalIsHeads; // Use predetermined result // Only show the side that the coin landed on // If heads, show Doge; if tails, show coin headsSide.alpha = self.isHeads ? 1 : 0; tailsSide.alpha = self.isHeads ? 0 : 1; // Final bounce effect tween(self.scale, { x: 1.3, y: 1.3 }, { duration: 200, yoyo: true, repeat: 1, onFinish: function onFinish() { if (typeof self.onFlipComplete === 'function') { self.onFlipComplete(self.isHeads); // Re-enable all buttons after flip completes if (flipButton) { flipButton.interactive = true; } if (headsButton) { headsButton.interactive = true; } if (tailsButton) { tailsButton.interactive = true; } } } }); return; } // Calculate if we need to end on heads or tails // If we're currently showing heads and need to end on heads: need even number of flips // If we're currently showing heads and need to end on tails: need odd number of flips // If we're currently showing tails and need to end on heads: need odd number of flips // If we're currently showing tails and need to end on tails: need even number of flips var needToFlip = self.isHeads !== finalIsHeads; var needToAdjustFlips = flipsLeft % 2 === 0 && needToFlip || flipsLeft % 2 === 1 && !needToFlip; // Adjust the final flip count if needed to end on the correct side if (needToAdjustFlips) { flipsLeft += 1; } // Make coin appear to flip in 3D by scaling in X direction tween(self, { scaleX: 0 }, { duration: flipDuration / (flipsLeft * 2), onFinish: function onFinish() { // Switch sides when flat self.isHeads = !self.isHeads; headsSide.alpha = self.isHeads ? 1 : 0; tailsSide.alpha = self.isHeads ? 0 : 1; // Flip back to full width tween(self, { scaleX: 1 }, { duration: flipDuration / (flipsLeft * 2), onFinish: function onFinish() { doFlip(flipsLeft - 1); } }); } }); } }; return self; }); var MemeReaction = Container.expand(function (memeType, size) { var self = Container.call(this); // Get the appropriate asset based on type var assetId = memeType === 'doge' ? 'Doge' : memeType === 'troll' ? 'Trollface' : 'Pepe'; var memeGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5, width: size || 300, height: size || 300 }); self.alpha = 0; // Start invisible for entrance animation // Animate entrance based on type self.show = function () { // Different animation for each meme type if (memeType === 'doge') { // Doge bounces in happily self.y -= 200; // Start above target position tween(self, { alpha: 1, y: self.y + 200 }, { duration: 500, easing: tween.bounceOut }); // Play appropriate sound LK.getSound('wow').play(); } else if (memeType === 'troll') { // Trollface slides in from side with rotation self.x += 300; // Start to the right self.rotation = Math.PI * 2; // Full rotation tween(self, { alpha: 1, x: self.x - 300, rotation: 0 }, { duration: 600, easing: tween.easeOutQuad }); // Play appropriate sound LK.getSound('bruh').play(); } else { // Pepe // Pepe fades in with a sad wobble tween(self, { alpha: 1 }, { duration: 300, onFinish: function onFinish() { // Sad wobble animation tween(self, { rotation: -0.1 }, { duration: 200, yoyo: true, repeat: 3, easing: tween.easeInOutSine }); } }); // Play appropriate sound LK.getSound('wednesday').play(); } }; // Animate exit self.hide = function (callback) { tween(self, { alpha: 0, y: self.y - 100 }, { duration: 500, easing: tween.easeInQuad, onFinish: function onFinish() { if (callback) { callback(); } self.destroy(); } }); }; return self; }); var Sanic = Container.expand(function () { var self = Container.call(this); var sanicGraphics = self.attachAsset('Sanic', { anchorX: 0.5, anchorY: 0.5 }); // Speed of Sanic's movement self.speed = 12; self.x = -100; // Start off-screen to the left // Update called every frame self.update = function () { // Initialize bobbing variables if not set if (self.bobOffset === undefined) { self.bobOffset = 0; self.bobSpeed = 0.1; self.bobAmount = 30; self.originalY = self.y; } // Update bobbing animation self.bobOffset += self.bobSpeed; self.y = self.originalY + Math.sin(self.bobOffset) * self.bobAmount; // Add slight rotation to match the bobbing movement self.rotation = Math.sin(self.bobOffset) * 0.08; // Move Sanic from left to right self.x += self.speed; // Destroy Sanic when he moves off-screen to the right if (self.x > 2148) { // 2048 + half of Sanic's width self.destroy(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2C3E50 }); /**** * Game Code ****/ // Background music // Sound effects // CatNinja assets // CoinFlip assets // DoodleJump assets // Game state variables // Removed homeButton shape var flipTunnel = null; var flipButton, headsButton, tailsButton; // Button references for coin flip game // Add prototype method for Button so Button.prototype.up can be called Button.prototype.up = function () { this.children[0].alpha = 1.0; }; var currentScene = "mainMenu"; var currentGame = null; var dragNode = null; // Score variables var score = 0; var platformsPassed = 0; // Game-specific variables var platforms = []; var cucumbers = []; var coins = []; var coin = null; var player = null; var gameTimer = null; var coinFlipGuess = null; var coinFlipStreak = 0; var obstacles = []; var tunnelSpeed = 15; var lastObstacleTime = 0; var flipScoreText = null; // Game backgrounds and containers var mainMenuContainer = new Container(); var gameSelectionContainer = new Container(); var doodleJumpContainer = new Container(); var coinFlipContainer = new Container(); var catNinjaContainer = new Container(); var flipRunnerContainer = new Container(); function setupMainMenu() { // Add splash background var splashBackground = mainMenuContainer.attachAsset('SplashBackground', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 + 100 }); // Play and loop splash music LK.playMusic('splashmusic', { loop: true }); // Animate the splash background with a dance effect function animateSplashBackground() { // Move right and down with slight rotation tween(splashBackground, { x: 2048 / 2 + 30, y: 2732 / 2 + 20, rotation: 0.03 }, { duration: 1800, easing: tween.easeInOutQuad, onFinish: function onFinish() { // Move left and up with opposite rotation tween(splashBackground, { x: 2048 / 2 - 30, y: 2732 / 2 - 20, rotation: -0.03 }, { duration: 1800, easing: tween.easeInOutQuad, onFinish: function onFinish() { // Move center and down with slight scale change tween(splashBackground, { x: 2048 / 2, y: 2732 / 2 + 15, rotation: 0, scaleX: 1.02, scaleY: 1.02 }, { duration: 1800, easing: tween.easeInOutSine, onFinish: function onFinish() { // Return to original position and scale tween(splashBackground, { x: 2048 / 2, y: 2732 / 2, scaleX: 1, scaleY: 1 }, { duration: 1800, easing: tween.easeInOutSine, onFinish: function onFinish() { // Repeat the animation animateSplashBackground(); } }); } }); } }); } }); } // Start the background animation animateSplashBackground(); // Create empty title text first var titleText = new Text2("", { size: 200, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 10, fontWeight: 'bold', dropShadow: true, dropShadowColor: 0x000000, dropShadowAngle: Math.PI / 4, dropShadowDistance: 12 }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 400; // Prepare for character-by-character reveal var fullTitleText = "NOX PRESENTS:"; var currentCharIndex = 0; var charRevealInterval = LK.setInterval(function () { if (currentCharIndex <= fullTitleText.length) { titleText.setText(fullTitleText.substring(0, currentCharIndex)); currentCharIndex++; // Add a small scale bounce effect for each new character if (currentCharIndex > 1) { titleText.scale.set(1.1, 1.1); tween(titleText.scale, { x: 1.0, y: 1.0 }, { duration: 200, easing: tween.bounceOut }); } } else { var _bounceTitleContinuously = function bounceTitleContinuously() { // Bounce up tween(titleText, { y: 380 }, { duration: 600, easing: tween.easeInOutQuad, onFinish: function onFinish() { // Bounce down tween(titleText, { y: 400 }, { duration: 600, easing: tween.easeInOutQuad, onFinish: _bounceTitleContinuously // Loop the animation }); } }); }; // Start continuous bouncing // Animation complete, clear interval LK.clearInterval(charRevealInterval); // Start continuous bouncing animation _bounceTitleContinuously(); } }, 150); // Reveal a new character every 150ms var startButton = new Button("START", 600, 220); startButton.x = 2048 / 2; startButton.y = 2732 - 300; // Position at bottom middle of screen // Add stroke to the button text // Make sure style object exists before setting properties if (!startButton.children[1].style) { startButton.children[1].style = {}; } startButton.children[1].style.stroke = 0x000000; startButton.children[1].style.strokeThickness = 10; startButton.children[1].style.fontSize = 70; // Increase text size too startButton.up = function () { Button.prototype.up.call(this); LK.getSound('yahoo').play(); switchToGameSelection(); }; // Add squash and stretch animation to the start button function animateStartButton() { // Squash (wider horizontally, shorter vertically) tween(startButton.scale, { x: 1.2, y: 0.8 }, { duration: 700, easing: tween.easeInOutQuad, onFinish: function onFinish() { // Stretch (taller vertically, narrower horizontally) tween(startButton.scale, { x: 0.9, y: 1.2 }, { duration: 700, easing: tween.easeInOutQuad, onFinish: function onFinish() { // Return to normal scale tween(startButton.scale, { x: 1.0, y: 1.0 }, { duration: 700, easing: tween.easeInOutQuad, onFinish: animateStartButton }); } }); } }); } // Start the button animation animateStartButton(); mainMenuContainer.addChild(titleText); mainMenuContainer.addChild(startButton); } function setupGameSelection() { // Add MenuBackground behind all elements var menuBackground = gameSelectionContainer.attachAsset('MenuBackground', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); // Add Pointguy in front of MenuBackground var pointguy = gameSelectionContainer.attachAsset('Pointguy', { anchorX: 0.5, anchorY: 0.5, x: 465, y: 1366 }); // Add bobbing animation to Pointguy function animatePointguy() { // Bob up with stretch tween(pointguy, { y: 1100, // Move up by 50px (increased from 40px) scaleX: 0.95, // Stretch taller and thinner (reduced from 0.9) scaleY: 1.05 // Reduced from 1.1 }, { duration: 2000, easing: tween.easeInOutQuad, onFinish: function onFinish() { // Bob down with squash tween(pointguy, { y: 1850, // Down by 50px from center (increased from original position) scaleX: 1.05, // Squash wider and shorter (reduced from 1.1) scaleY: 0.95 // Reduced from 0.9 }, { duration: 2000, easing: tween.easeInOutQuad, onFinish: animatePointguy // Continue the loop }); } }); } // Start the bobbing animation animatePointguy(); // Periodically spawn Sanic running across the screen function spawnSanic() { var sanic = new Sanic(); sanic.y = 2500; // Position Sanic at a good height on screen gameSelectionContainer.addChild(sanic); // Schedule next Sanic to appear after this one leaves LK.setTimeout(spawnSanic, 4000 + Math.random() * 2000); } // Start spawning Sanic characters spawnSanic(); // Create animated title with shadow and effects var titleText = new Text2("SELECT A GAME", { size: 200, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 10, fontWeight: 'bold', dropShadow: true, dropShadowColor: 0x000000, dropShadowAngle: Math.PI / 4, dropShadowDistance: 8 }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 300; titleText.alpha = 0; // Animate title entrance tween(titleText, { alpha: 1, y: 250 }, { duration: 800, easing: tween.bounceOut }); // Setup continuous subtle title animation function animateTitle() { tween(titleText, { y: 270 }, { duration: 1500, easing: tween.easeInOutQuad, onFinish: function onFinish() { tween(titleText, { y: 250 }, { duration: 1500, easing: tween.easeInOutQuad, onFinish: animateTitle }); } }); } LK.setTimeout(animateTitle, 1000); // Create game selection buttons with staggered animations - 25% smaller and repositioned var game1Button = new Button("Meme Runner\nPolarity Shift", 375, 262); // 25% smaller (500*0.75=375, 350*0.75=262.5) game1Button.x = 2300; // Start off-screen game1Button.y = 1100; // Moved up slightly game1Button.alpha = 0; var game2Button = new Button("Meme Flip\nChallenge", 375, 262); // 25% smaller game2Button.x = 2300; // Start off-screen game2Button.y = 1425; // Centered vertically in the TV screen game2Button.alpha = 0; var game3Button = new Button("Meme Dodge\nSimulator", 375, 262); // 25% smaller game3Button.x = 2300; // Start off-screen game3Button.y = 1775; // Moved up slightly game3Button.alpha = 0; // Add hover/pulse effects to buttons function setupButtonAnimations(button) { // Create pulsing animation function pulseButton(btn) { tween(btn.scale, { x: 1.05, y: 1.05 }, { duration: 1000, easing: tween.easeInOutQuad, onFinish: function onFinish() { tween(btn.scale, { x: 1.0, y: 1.0 }, { duration: 1000, easing: tween.easeInOutQuad, onFinish: function onFinish() { pulseButton(btn); } }); } }); } // Start pulsing after entrance animation LK.setTimeout(function () { pulseButton(button); }, 1500); } // Animate buttons entering one after another tween(game1Button, { x: 2048 / 2 + 125, alpha: 1 }, { duration: 700, easing: tween.bounceOut, onFinish: function onFinish() { setupButtonAnimations(game1Button); // Animate second button after first tween(game2Button, { x: 2048 / 2 + 125, alpha: 1 }, { duration: 700, easing: tween.bounceOut, onFinish: function onFinish() { setupButtonAnimations(game2Button); // Animate third button after second tween(game3Button, { x: 2048 / 2 + 125, alpha: 1 }, { duration: 700, easing: tween.bounceOut, onFinish: function onFinish() { setupButtonAnimations(game3Button); } }); } }); } }); game1Button.up = function () { Button.prototype.up.call(this); // Flash button and add scale effect before starting game LK.effects.flashObject(this, 0xFFFFFF, 300); tween(this.scale, { x: 1.2, y: 1.2 }, { duration: 200, onFinish: function onFinish() { startFlipRunner(); } }); }; game2Button.up = function () { Button.prototype.up.call(this); // Flash button and add scale effect before starting game LK.effects.flashObject(this, 0xFFFFFF, 300); tween(this.scale, { x: 1.2, y: 1.2 }, { duration: 200, onFinish: function onFinish() { startCoinFlip(); } }); }; game3Button.up = function () { Button.prototype.up.call(this); // Flash button and add scale effect before starting game LK.effects.flashObject(this, 0xFFFFFF, 300); tween(this.scale, { x: 1.2, y: 1.2 }, { duration: 200, onFinish: function onFinish() { startCatNinja(); } }); }; gameSelectionContainer.addChild(titleText); gameSelectionContainer.addChild(game1Button); gameSelectionContainer.addChild(game2Button); gameSelectionContainer.addChild(game3Button); } // DoodleJump game implementation function setupDoodleJump() { var background = doodleJumpContainer.attachAsset('gameBackground', { anchorX: 0, anchorY: 0 }); var homeBtn = new HomeButton(); homeBtn.x = 150; homeBtn.y = 100; doodleJumpContainer.addChild(homeBtn); var scoreText = new Text2("Score: 0", { size: 50, fill: 0x000000 }); scoreText.anchor.set(0.5, 0); scoreText.x = 2048 / 2; scoreText.y = 50; doodleJumpContainer.addChild(scoreText); var highScoreText = new Text2("Best: " + storage.highScore1, { size: 30, fill: 0x000000 }); highScoreText.anchor.set(0.5, 0); highScoreText.x = 2048 / 2; highScoreText.y = 110; doodleJumpContainer.addChild(highScoreText); player = new DoodlePlayer(); player.x = 2048 / 2; player.y = 2000; doodleJumpContainer.addChild(player); // Generate initial platforms platforms = []; for (var i = 0; i < 10; i++) { var platform = new DoodlePlatform(Math.random() * 1800 + 100, 2600 - i * 250); platforms.push(platform); doodleJumpContainer.addChild(platform); } // First platform is directly under player platforms[0].x = player.x; platforms[0].y = player.y + 100; platforms[0].isMoving = false; score = 0; platformsPassed = 0; } function updateDoodleJump() { if (currentScene !== "doodleJump") { return; } player.update(); // Handle platform collision var onPlatform = false; for (var i = 0; i < platforms.length; i++) { var platform = platforms[i]; platform.update(); if (player.velocityY > 0 && player.y < platform.y && player.y + player.velocityY >= platform.y - 70 && Math.abs(player.x - platform.x) < 150) { player.y = platform.y - 70; player.jump(); onPlatform = true; } } // Handle screen wrapping for player if (player.x < 0) { player.x = 2048; } if (player.x > 2048) { player.x = 0; } // Scroll the world when player gets too high if (player.y < 1000) { var diff = 1000 - player.y; player.y = 1000; // Move platforms down for (var i = 0; i < platforms.length; i++) { platforms[i].y += diff; // If platform is off-screen, reposition it at the top if (platforms[i].y > 2732) { platforms[i].y = platforms[i].y - 2732; platforms[i].x = Math.random() * 1800 + 100; platforms[i].isMoving = Math.random() > 0.7; platformsPassed++; score = platformsPassed * 10; } } } // Handle game over if player falls off the bottom if (player.y > 2732) { // Update high score if (score > storage.highScore1) { storage.highScore1 = score; } LK.setScore(score); LK.showGameOver(); } // Update score display var scoreText = doodleJumpContainer.children[2]; scoreText.setText("Score: " + score); } // Add screen shake effect to LK.effects namespace if (!LK.effects.shakeScreen) { LK.effects.shakeScreen = function (intensity, duration) { var originalX = game.x; var originalY = game.y; var shakeInterval = LK.setInterval(function () { game.x = originalX + (Math.random() * 2 - 1) * intensity; game.y = originalY + (Math.random() * 2 - 1) * intensity; }, 16); LK.setTimeout(function () { LK.clearInterval(shakeInterval); game.x = originalX; game.y = originalY; }, duration); }; } // Add rainbow flash effect to LK.effects namespace if (!LK.effects.rainbowFlash) { LK.effects.rainbowFlash = function (obj, duration) { var colors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x9400D3]; var colorIndex = 0; var originalTint = obj.tint; var flashInterval = LK.setInterval(function () { obj.tint = colors[colorIndex]; colorIndex = (colorIndex + 1) % colors.length; }, duration / colors.length); LK.setTimeout(function () { LK.clearInterval(flashInterval); obj.tint = originalTint; }, duration); }; } // CoinFlip game implementation function setupCoinFlip() { // Create animated background with floating emojis var background = coinFlipContainer.attachAsset('gameBackground', { anchorX: 0, anchorY: 0, width: 2048, height: 2732 }); background.tint = 0x3498db; // Blue background // Add animated floating emoji backgrounds function createFloatingEmoji(emoji, size) { var emojiText = new Text2(emoji, { size: size || 40, fill: 0xFFFFFF, alpha: 0.3 }); emojiText.x = Math.random() * 2048; emojiText.y = Math.random() * 2732; // Random movement direction emojiText.vx = (Math.random() - 0.5) * 2; emojiText.vy = (Math.random() - 0.5) * 2; coinFlipContainer.addChild(emojiText); return emojiText; } // Create 20 random emojis in the background var emojis = ['💯', '🔥', '🤣', '👌', '💪', '😂', '✨', '🚀', '🎯', '💰']; var floatingEmojis = []; for (var i = 0; i < 20; i++) { var emoji = emojis[Math.floor(Math.random() * emojis.length)]; var size = Math.random() * 30 + 30; // Random size between 30-60 floatingEmojis.push(createFloatingEmoji(emoji, size)); } // Store emoji update function for game.update coinFlipContainer.updateEmojis = function () { for (var i = 0; i < floatingEmojis.length; i++) { var emoji = floatingEmojis[i]; emoji.x += emoji.vx; emoji.y += emoji.vy; // Bounce off edges if (emoji.x < 0 || emoji.x > 2048) { emoji.vx *= -1; } if (emoji.y < 0 || emoji.y > 2732) { emoji.vy *= -1; } // Slight rotation emoji.rotation += 0.01; } }; // Create enhanced title with meme style font var titleText = new Text2("MEME FLIP CHALLENGE", { size: 80, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 15, dropShadow: true, dropShadowColor: 0x000000, dropShadowDistance: 10, fontWeight: 'bold', fontStyle: 'italic' }); titleText.anchor.set(0.5, 0); titleText.x = 2048 / 2; titleText.y = 150; coinFlipContainer.addChild(titleText); // Make title pulse with rainbow colors LK.setInterval(function () { // Cycle through hues titleText.tint = Math.random() * 0xFFFFFF; }, 1000); var streakText = new Text2("Current Streak: 0", { size: 60, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 8, dropShadow: true }); streakText.anchor.set(0.5, 0); streakText.x = 2048 / 2; streakText.y = 280; coinFlipContainer.addChild(streakText); var highScoreText = new Text2("Best Streak: " + storage.highScore2, { size: 40, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 5, dropShadow: true }); highScoreText.anchor.set(0.5, 0); highScoreText.x = 2048 / 2; highScoreText.y = 350; coinFlipContainer.addChild(highScoreText); // Use the new MemeCoin instead of regular Coin coin = new MemeCoin(); coin.x = 2048 / 2; coin.y = 900; coinFlipContainer.addChild(coin); var instructionText = new Text2("Select your guess before flipping", { size: 50, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 6, dropShadow: true }); instructionText.anchor.set(0.5, 0); instructionText.x = 2048 / 2; instructionText.y = 1200; coinFlipContainer.addChild(instructionText); // Create meme-styled buttons with "HEADZ" and "TAILZ" headsButton = new Button("HEADZ", 350, 180); headsButton.x = 2048 / 2 - 230; headsButton.y = 1400; headsButton.children[0].tint = 0xF1C40F; // Gold color for heads coinFlipContainer.addChild(headsButton); tailsButton = new Button("TAILZ", 350, 180); tailsButton.x = 2048 / 2 + 230; tailsButton.y = 1400; tailsButton.children[0].tint = 0xE74C3C; // Red color for tails coinFlipContainer.addChild(tailsButton); flipButton = new Button("FLIP IT!!1!", 450, 180); flipButton.x = 2048 / 2; flipButton.y = 1600; flipButton.children[0].tint = 0x2ECC71; // Green color for flip coinFlipContainer.addChild(flipButton); var resultText = new Text2("", { size: 80, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 10, dropShadow: true, dropShadowDistance: 8 }); resultText.anchor.set(0.5, 0); resultText.x = 2048 / 2; resultText.y = 1800; coinFlipContainer.addChild(resultText); // Container for meme reactions var memeContainer = new Container(); memeContainer.x = 2048 / 2; memeContainer.y = 650; coinFlipContainer.addChild(memeContainer); // Container for streak bonus effects var streakBonusContainer = new Container(); streakBonusContainer.x = 2048 / 2; streakBonusContainer.y = 500; coinFlipContainer.addChild(streakBonusContainer); headsButton.up = function () { Button.prototype.up.call(this); // Don't do anything if coin is currently flipping if (coin.isFlipping) { return; } coinFlipGuess = true; instructionText.setText("You chose: HEADZ"); // Flash button for selection feedback LK.effects.flashObject(this, 0xF1C40F, 300); }; tailsButton.up = function () { Button.prototype.up.call(this); // Don't do anything if coin is currently flipping if (coin.isFlipping) { return; } coinFlipGuess = false; instructionText.setText("You chose: TAILZ"); // Flash button for selection feedback LK.effects.flashObject(this, 0xE74C3C, 300); }; flipButton.up = function () { Button.prototype.up.call(this); // If already flipping, don't do anything if (coin.isFlipping) { return; } // If no guess selected, show error message if (coinFlipGuess === null) { instructionText.setText("PICK HEADZ OR TAILZ FIRST, BRUH!!"); // Shake text for emphasis tween(instructionText, { x: 2048 / 2 + 10 }, { duration: 50, yoyo: true, repeat: 5 }); return; } // Clear any existing meme reactions memeContainer.removeChildren(); // Flash button when pressed LK.effects.flashObject(this, 0x2ECC71, 300); // Start the enhanced coin flip coin.flip(); // Disable all buttons while flipping flipButton.interactive = false; headsButton.interactive = false; tailsButton.interactive = false; // Use onFlipComplete handler instead of setTimeout coin.onFlipComplete = function (result) { var correct = coinFlipGuess === result; // Clear any previous meme reactions memeContainer.removeChildren(); if (correct) { resultText.setText("CORRECT!"); if (resultText && resultText.style) { resultText.style.fill = "#27AE60"; } coinFlipStreak++; // Always play wow sound when guessing correctly LK.getSound('wow').play(); // Show Pointguy meme reaction var pointguyReaction = memeContainer.attachAsset('Pointguy', { anchorX: 0.5, anchorY: 0.5, width: 400, height: 400 }); // Position Pointguy to the left of the coin pointguyReaction.x = -400; // Position to the left of Doge/Tailz instead of above pointguyReaction.y = 0; // At the same level as the coin pointguyReaction.alpha = 0; // Start invisible tween(pointguyReaction, { alpha: 1 // Fade in }, { duration: 500, easing: tween.bounceOut }); // Add text bubble with meme saying var textBubble = new Text2("CORRECT!! NICE GUESS!", { size: 40, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 4 }); textBubble.anchor.set(0.5, 0); textBubble.x = 0; textBubble.y = -250; pointguyReaction.addChild(textBubble); // Check for streak bonus at 3 correct flips if (coinFlipStreak % 3 === 0 && coinFlipStreak > 0) { // Epic streak celebration LK.setTimeout(function () { // Clear existing bonus effects streakBonusContainer.removeChildren(); // Create rainbow text var epicStreakText = new Text2("EPIC STREAK: " + coinFlipStreak + "!", { size: 100, fill: 0xFFFF00, stroke: 0xFF00FF, strokeThickness: 10 }); epicStreakText.anchor.set(0.5, 0.5); streakBonusContainer.addChild(epicStreakText); // Rainbow color cycle animation var hue = 0; var colorInterval = LK.setInterval(function () { hue = (hue + 0.05) % 1; // Manually interpolate colors since tween doesn't have interpolateColor method var r1 = 0xFF0000 >> 16 & 0xFF; var g1 = 0xFF0000 >> 8 & 0xFF; var b1 = 0xFF0000 & 0xFF; var r2 = 0x00FF00 >> 16 & 0xFF; var g2 = 0x00FF00 >> 8 & 0xFF; var b2 = 0x00FF00 & 0xFF; var r = Math.floor(r1 + (r2 - r1) * hue); var g = Math.floor(g1 + (g2 - g1) * hue); var b = Math.floor(b1 + (b2 - b1) * hue); epicStreakText.tint = r << 16 | g << 8 | b; }, 50); // Make text grow and then shrink tween(epicStreakText.scale, { x: 1.5, y: 1.5 }, { duration: 1000, yoyo: true, repeat: 1, onFinish: function onFinish() { // Fade out and remove after effect completes LK.setTimeout(function () { LK.clearInterval(colorInterval); tween(epicStreakText, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { streakBonusContainer.removeChildren(); } }); }, 1000); } }); // Add dab animation on high streak var dabPepe = new MemeReaction('doge', 200); dabPepe.x = 300; dabPepe.y = 0; streakBonusContainer.addChild(dabPepe); dabPepe.show(); // Shake screen for emphasis LK.effects.shakeScreen(10, 500); }, 1000); } if (coinFlipStreak > storage.highScore2) { storage.highScore2 = coinFlipStreak; highScoreText.setText("Best Streak: " + storage.highScore2); // Flash high score LK.effects.flashObject(highScoreText, 0xFFD700, 1000); } } else { resultText.setText("WRONG! Streak wrecked!"); if (resultText && resultText.style) { resultText.style.fill = "#E74C3C"; } // Play failure sound LK.getSound('bruh').play(); // Show different meme reactions based on streak length if (coinFlipStreak >= 3) { // Show sad Pepe for losing a good streak var pepeReaction = new MemeReaction('pepe', 300); pepeReaction.x = 0; pepeReaction.y = 0; memeContainer.addChild(pepeReaction); pepeReaction.show(); // Add crying text var sadText = new Text2("Streak of " + coinFlipStreak + " gone...", { size: 40, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 4 }); sadText.anchor.set(0, 0); sadText.x = 100; sadText.y = -100; pepeReaction.addChild(sadText); } else { // Show trollface for short streaks var trollReaction = new MemeReaction('troll', 300); trollReaction.x = 0; trollReaction.y = 0; memeContainer.addChild(trollReaction); trollReaction.show(); // Add u mad text var madText = new Text2("U mad?", { size: 50, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 4 }); madText.anchor.set(0, 0); madText.x = 100; madText.y = -100; trollReaction.addChild(madText); } LK.setTimeout(function () { LK.setScore(coinFlipStreak); LK.showGameOver(); }, 2000); coinFlipStreak = 0; // Shake screen on failure LK.effects.shakeScreen(15, 500); } streakText.setText("Current Streak: " + coinFlipStreak); coinFlipGuess = null; instructionText.setText("Select your guess before flipping"); // Auto-hide meme reaction after delay LK.setTimeout(function () { // Clear meme container - works for both MemeReaction instances and Pointguy memeContainer.removeChildren(); }, 3000); }; }; coinFlipStreak = 0; } // CatNinja game implementation function setupDogeDodge() { // Create vaporwave gradient background catNinjaContainer.vaporwaveBackground = new Container(); var vaporwaveBackground = catNinjaContainer.vaporwaveBackground; vaporwaveBackground.y = 0; vaporwaveBackground.x = 0; // Initialize memePhrasesContainer catNinjaContainer.memePhrasesContainer = new Container(); var memePhrasesContainer = catNinjaContainer.memePhrasesContainer; // Create gradient layers with different colors var colors = [0xff71ce, // hot pink 0x01cdfe, // bright blue 0x05ffa1, // bright green 0xb967ff, // purple 0xfffb96 // light yellow ]; // Create multiple gradient rectangles for (var i = 0; i < colors.length; i++) { var gradientLayer = vaporwaveBackground.attachAsset('gameBackground', { anchorX: 0, anchorY: 0, width: 2048, height: 2732 }); gradientLayer.tint = colors[i]; gradientLayer.alpha = 0.0; // Start transparent for animation } // Add background as first child (behind everything) catNinjaContainer.addChildAt(vaporwaveBackground, 0); // Make vaporwaveBackground accessible globally catNinjaContainer.vaporwaveBackground = vaporwaveBackground; // Initialize variables for meme phrases catNinjaContainer.memePhrasesContainer = new Container(); var memePhrasesContainer = catNinjaContainer.memePhrasesContainer; catNinjaContainer.addChild(memePhrasesContainer); var homeBtn = new HomeButton(); homeBtn.x = 150; homeBtn.y = 100; catNinjaContainer.addChild(homeBtn); var scoreText = new Text2("Score: 0", { size: 50, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); scoreText.x = 2048 / 2; scoreText.y = 50; catNinjaContainer.addChild(scoreText); // Store direct reference to score text catNinjaContainer.scoreText = scoreText; // Lives UI removed for increased difficulty var highScoreText = new Text2("Best: " + storage.highScore3, { size: 30, fill: 0xFFFFFF }); highScoreText.anchor.set(0.5, 0); highScoreText.x = 2048 / 2; highScoreText.y = 110; catNinjaContainer.addChild(highScoreText); var instructionText = new Text2("TAP ANYWHERE TO CHANGE DIRECTION. DODGE OBSTACLES, COLLECT COINS!", { size: 40, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0); instructionText.x = 2048 / 2; instructionText.y = 200; catNinjaContainer.addChild(instructionText); // Add vaporwave styling to instructions LK.setTimeout(function () { tween(instructionText, { alpha: 0.7 }, { duration: 1000, easing: tween.easeInOutSine, yoyo: true, repeat: 3 }); }, 1000); player = new DogePlayer(); player.x = 2048 / 2; player.y = 2200; catNinjaContainer.addChild(player); cucumbers = []; coins = []; // Spawn both obstacles and coins gameTimer = LK.setInterval(function () { if (Math.random() < 0.7) { spawnObstacle(); } else { spawnCoin(); } }, 800); } function spawnObstacle() { if (currentScene !== "catNinja") { return; } var obstacle = new CryptoObstacle(); obstacle.x = Math.random() * 1800 + 100; obstacle.y = -200; cucumbers.push(obstacle); catNinjaContainer.addChild(obstacle); } function spawnCoin() { if (currentScene !== "catNinja") { return; } var coin = new CryptoCoin(); coin.x = Math.random() * 1800 + 100; coin.y = -200; coins.push(coin); catNinjaContainer.addChild(coin); } // Function to spawn flying meme phrases function spawnMemePhrase() { if (currentScene !== "catNinja") { return; } // Array of popular meme phrases var phrases = ["WOW!", "SUCH DODGE!", "VERY SKILL!", "MUCH GAME!", "SO AMAZE!", "EPIC WIN!", "YAAAAAS!", "TO THE MOON!", "STONKS!", "BIG MOOD", "NO CAP!", "THIS IS FINE.", "DEAL WITH IT", "YEET!", "DOGE POWER!", "MUCH SPEED!", "VERY CRYPTO!", "POGGERS!", "LOL", "GET REKT!", "SUCH AMAZING", "VIBES"]; // Select random phrase var phrase = phrases[Math.floor(Math.random() * phrases.length)]; // Create text with random styling var textSize = 40 + Math.floor(Math.random() * 60); // Size between 40-100 var colors = [0xFF71CE, 0x01CDFE, 0x05FFA1, 0xB967FF, 0xFFFF00, 0xFF00FF]; var fillColor = colors[Math.floor(Math.random() * colors.length)]; var strokeColor = colors[Math.floor(Math.random() * colors.length)]; var phraseText = new Text2(phrase, { size: textSize, fill: fillColor, stroke: strokeColor, strokeThickness: 4, fontWeight: Math.random() > 0.5 ? 'bold' : 'normal', fontStyle: Math.random() > 0.7 ? 'italic' : 'normal' }); // Set anchor point for rotation phraseText.anchor.set(0.5, 0.5); // Position randomly var startY = 200 + Math.random() * (2732 - 400); phraseText.x = -300; // Start off-screen left phraseText.y = startY; // Add to container catNinjaContainer.memePhrasesContainer.addChild(phraseText); // Random movement parameters var speed = 5 + Math.random() * 10; var rotationSpeed = (Math.random() - 0.5) * 0.05; var updownAmount = Math.random() * 50; var updownSpeed = Math.random() * 0.1; // Initial properties phraseText.speed = speed; phraseText.rotationSpeed = rotationSpeed; phraseText.updownAmount = updownAmount; phraseText.updownSpeed = updownSpeed; phraseText.updownOffset = Math.random() * Math.PI * 2; // Random starting phase phraseText.initialY = startY; // Add update function phraseText.update = function () { this.x += this.speed; this.y = this.initialY + Math.sin(this.updownOffset) * this.updownAmount; this.updownOffset += this.updownSpeed; this.rotation += this.rotationSpeed; // Remove when off-screen if (this.x > 2348) { catNinjaContainer.memePhrasesContainer.removeChild(this); } }; // Animate entrance with flair tween(phraseText.scale, { x: 1.5, y: 1.5 }, { duration: 300, yoyo: true, repeat: 1, easing: tween.bounceOut }); // Add brief flash effect LK.effects.flashObject(phraseText, 0xFFFFFF, 300); // Play wow sound occasionally if (Math.random() < 0.3) { LK.getSound('wow').play(); } } function updateDogeDodge() { if (currentScene !== "catNinja") { return; } // Re-declare memePhrasesContainer at the top of the function var memePhrasesContainer = catNinjaContainer.memePhrasesContainer; // Animate vaporwave background - cycle through gradient colors var vaporwaveBackground = catNinjaContainer.vaporwaveBackground; if (vaporwaveBackground && vaporwaveBackground.children && vaporwaveBackground.children.length > 0) { // Initialize animation data if not already done if (!vaporwaveBackground.lastUpdate) { vaporwaveBackground.lastUpdate = Date.now(); vaporwaveBackground.cycleTime = 8000; // 8 seconds for full cycle // Start color cycling animation for (var i = 0; i < vaporwaveBackground.children.length; i++) { var layer = vaporwaveBackground.children[i]; var delay = i * 300; // Stagger the animations // Cycle through different alphas for each layer tween(layer, { alpha: 0.4 + Math.random() * 0.3 }, { duration: 2000 + i * 500, easing: tween.easeInOutSine, onFinish: function (layerIndex) { return function () { // Create continuous animations with different durations var _cycleAlpha = function cycleAlpha(layer, min, max) { tween(layer, { alpha: min + Math.random() * 0.2 }, { duration: 2000 + Math.random() * 2000, easing: tween.easeInOutSine, onFinish: function onFinish() { tween(layer, { alpha: max - Math.random() * 0.2 }, { duration: 2000 + Math.random() * 2000, easing: tween.easeInOutSine, onFinish: function onFinish() { _cycleAlpha(layer, min, max); } }); } }); }; // Each layer gets a different alpha range _cycleAlpha(vaporwaveBackground.children[layerIndex], 0.2 + layerIndex * 0.05, 0.5 - layerIndex * 0.03); }; }(i) }); } } // Every so often, spawn a meme phrase if (!catNinjaContainer.memePhrasesContainer.lastPhraseTime) { catNinjaContainer.memePhrasesContainer.lastPhraseTime = Date.now(); catNinjaContainer.memePhrasesContainer.phraseInterval = 2000 + Math.random() * 3000; // 2-5 seconds } // Check if it's time to spawn a new phrase if (Date.now() - catNinjaContainer.memePhrasesContainer.lastPhraseTime > catNinjaContainer.memePhrasesContainer.phraseInterval) { spawnMemePhrase(); catNinjaContainer.memePhrasesContainer.lastPhraseTime = Date.now(); catNinjaContainer.memePhrasesContainer.phraseInterval = 2000 + Math.random() * 3000; // 2-5 seconds } } // Update player movement player.update(); // Update and check collisions with obstacles for (var i = cucumbers.length - 1; i >= 0; i--) { var obstacle = cucumbers[i]; obstacle.update(); // Check for collision with player if (player.intersects(obstacle)) { // Player got hit by obstacle catNinjaContainer.removeChild(obstacle); cucumbers.splice(i, 1); var gameOver = player.hurt(obstacle); //catNinjaContainer.children[2].setText("Lives: " + player.lives); if (gameOver) { // Game over LK.clearInterval(gameTimer); if (player.score > storage.highScore3) { storage.highScore3 = player.score; } LK.setScore(player.score); LK.showGameOver(); } continue; } // Remove obstacle if it goes off screen if (obstacle.y > 2900) { catNinjaContainer.removeChild(obstacle); cucumbers.splice(i, 1); } } // Update and check collisions with coins for (var j = coins.length - 1; j >= 0; j--) { var coin = coins[j]; coin.update(); // Check for collision with player if (player.intersects(coin)) { // Player collected coin player.collect(coin); catNinjaContainer.removeChild(coin); coins.splice(j, 1); continue; } // Remove coin if it goes off screen if (coin.y > 2900) { catNinjaContainer.removeChild(coin); coins.splice(j, 1); } } // Update score display var scoreText = catNinjaContainer.scoreText; if (scoreText && typeof scoreText.setText === 'function') { scoreText.setText("Score: " + player.score); } // Update lives display using the proper child reference and checking its type var livesText = catNinjaContainer.children[2]; if (livesText && typeof livesText.setText === 'function') { livesText.setText("Lives: " + player.lives); } // Update all meme phrases if (memePhrasesContainer) { for (var i = memePhrasesContainer.children.length - 1; i >= 0; i--) { var phrase = memePhrasesContainer.children[i]; if (phrase.update) { phrase.update(); } } } } // Scene management functions function switchToMainMenu() { clearCurrentScene(); currentScene = "mainMenu"; game.addChild(mainMenuContainer); LK.playMusic('menuMusic'); } function switchToGameSelection() { clearCurrentScene(); currentScene = "gameSelection"; game.addChild(gameSelectionContainer); // Add a flash effect for transition LK.effects.flashScreen(0xFFFFFF, 500); // Play transition sound LK.getSound('buttonClick').play(); // Don't start menu music - keep splash music playing } function startDoodleJump() { clearCurrentScene(); currentScene = "doodleJump"; setupDoodleJump(); game.addChild(doodleJumpContainer); LK.playMusic('gameMusic'); } function startCoinFlip() { clearCurrentScene(); currentScene = "coinFlip"; setupCoinFlip(); game.addChild(coinFlipContainer); LK.playMusic('gameMusic'); } function startCatNinja() { clearCurrentScene(); currentScene = "catNinja"; setupDogeDodge(); game.addChild(catNinjaContainer); LK.playMusic('gameMusic'); } function scheduleRandomEvent() { // pick a delay between 5 000 and 8 000 ms var delay = 5000 + Math.random() * 3000; LK.setTimeout(function () { triggerEvent(); scheduleRandomEvent(); // loop }, delay); } function triggerEvent() { // Play buzzer sound when random event happens LK.getSound('buzzer').play(); // Pick a random count between 1 and 3 var count = 1 + Math.floor(Math.random() * 3); // Create multiple effects based on count for (var i = 0; i < count; i++) { // create a temporary sprite for each effect with a random meme asset var fx = new Container(); // Use one of three meme assets randomly (Doge, Trollface, or Pepe) var memeAssets = ['Doge', 'Trollface', 'Pepe']; var randomMeme = memeAssets[Math.floor(Math.random() * memeAssets.length)]; // Generate random size between 100 and 300 var randomSize = 100 + Math.floor(Math.random() * 200); var gfx = fx.attachAsset(randomMeme, { anchorX: 0.5, anchorY: 0.5, width: randomSize, height: randomSize }); // Capture the base scale var baseSX = fx.scale.x; var baseSY = fx.scale.y; // Calculate random position with margins for each effect var maxX = 2048; var maxY = 2732; var margin = 100; // half of effect's max dimension fx.x = margin + Math.random() * (maxX - margin * 2); fx.y = margin + Math.random() * (maxY - margin * 2); flipRunnerContainer.addChild(fx); // pick spin or pulse at random if (Math.random() < 0.5) { // spin for 2s tween(fx, { rotation: Math.PI * 2 }, { duration: 2000 }); } else { // Compute a random increase between 1% and 25% var inc = 0.01 + Math.random() * 0.24; // anywhere from 0.01 to 0.25 var scaleFactor = 1 + inc; // final multiplier // grow & shrink for 2s tween(fx.scale, { x: baseSX * scaleFactor, y: baseSY * scaleFactor }, { duration: 1000, yoyo: true, repeat: 1 }); } // remove after 2s using IIFE to properly capture the fx reference (function (fxToRemove) { LK.setTimeout(function () { flipRunnerContainer.removeChild(fxToRemove); }, 2000); })(fx); } } function setupFlipRunner() { var background = flipRunnerContainer.attachAsset('gameBackground', { anchorX: 0, anchorY: 0, width: 2048, height: 2732 }); background.tint = 0x000000; // Black background // Create container for stars var starsContainer = new Container(); flipRunnerContainer.addChild(starsContainer); // Function to create a rainbow star function createStar() { var star = new Container(); // Random star size between 5 and 20 var starSize = 5 + Math.random() * 15; // Random rainbow color var colors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x9400D3]; var randomColor = colors[Math.floor(Math.random() * colors.length)]; // Create star shape var starGfx = star.attachAsset('selectionButton', { anchorX: 0.5, anchorY: 0.5, width: starSize, height: starSize }); starGfx.tint = randomColor; // Set initial position star.x = 2048 + starSize; star.y = Math.random() * 2732; // Set star speed star.speed = 5 + Math.random() * 10; // Add to container starsContainer.addChild(star); return star; } // Initialize stars var stars = []; for (var i = 0; i < 20; i++) { var star = createStar(); // Distribute stars across the screen initially star.x = Math.random() * 2048; stars.push(star); } // Star generation interval var starInterval = LK.setInterval(function () { if (stars.length < 30) { // Limit number of stars var star = createStar(); stars.push(star); } }, 500); // Star update function flipRunnerContainer.updateStars = function () { for (var i = stars.length - 1; i >= 0; i--) { var star = stars[i]; star.x -= star.speed; // Remove stars that go off screen if (star.x < -20) { starsContainer.removeChild(star); stars.splice(i, 1); } // Slight rotation for twinkling effect star.rotation += 0.02; // Cycle through rainbow colors if (Math.random() < 0.02) { var colors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x9400D3]; star.children[0].tint = colors[Math.floor(Math.random() * colors.length)]; } } }; // Add tunnel with rainbow road effect flipTunnel = new FlipRunnerTunnel(); flipRunnerContainer.addChild(flipTunnel); // Add rainbow glow effect to tunnel walls var colorIndices = [0, 1, 2, 3, 4, 5, 6]; var colors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x9400D3]; var colorIndex = 0; var colorInterval = LK.setInterval(function () { // Cycle through colors colorIndex = (colorIndex + 1) % colors.length; // Update top and bottom wall colors tween(flipTunnel.topWall, { tint: colors[colorIndices[colorIndex]] }, { duration: 300 }); // Use a different color for bottom wall for more rainbow effect tween(flipTunnel.bottomWall, { tint: colors[(colorIndices[colorIndex] + 3) % colors.length] }, { duration: 300 }); // Rotate color indices to create flowing rainbow effect colorIndices.push(colorIndices.shift()); }, 200); // Add player player = new FlipRunnerPlayer(); player.x = 500; // Player's y position will be set in updateFlipRunner based on tunnel gap flipRunnerContainer.addChild(player); // HomeButton removed var scoreText = new Text2("Score: 0", { size: 50, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); scoreText.x = 2048 / 2; scoreText.y = 50; flipScoreText = scoreText; var highScoreText = new Text2("Best: " + (storage.highScoreFlipRunner || 0), { size: 30, fill: 0xFFFFFF }); highScoreText.anchor.set(0.5, 0); highScoreText.x = 2048 / 2; highScoreText.y = 110; var instructionText = new Text2("TAP TO FLIP POLARITY!", { size: 40, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0); instructionText.x = 2048 / 2; instructionText.y = 200; flipRunnerContainer.addChild(highScoreText); flipRunnerContainer.addChild(scoreText); flipRunnerContainer.addChild(instructionText); // HomeButton not needed // Initialize obstacles array obstacles = []; tunnelSpeed = 15; lastObstacleTime = 0; // Function to spawn obstacles function spawnObstacle() { if (currentScene !== "flipRunner" || !player || !player.isAlive) { return; } // Initialize last spawn position if not set if (spawnObstacle.lastPosition === undefined) { spawnObstacle.lastPosition = "bottom"; } // Alternate between top and bottom walls var obstacleY; if (spawnObstacle.lastPosition === "bottom") { // Place on top wall obstacleY = flipTunnel.topY + Math.random() * 200 + 50; spawnObstacle.lastPosition = "top"; } else { // Place on bottom wall obstacleY = flipTunnel.bottomY - Math.random() * 200 - 50; spawnObstacle.lastPosition = "bottom"; } // Create a single obstacle 25% bigger than normal var obstacle = new FlipRunnerObstacle(obstacleY, tunnelSpeed); // Make it 25% bigger obstacle.scale.set(1.25, 1.25); obstacles.push(obstacle); flipRunnerContainer.addChild(obstacle); // Play a sound effect for obstacle spawn if (Math.random() < 0.3) {} } // Start the obstacle spawner gameTimer = LK.setInterval(function () { if (tunnelSpeed < 30) { tunnelSpeed += 0.05; // Gradually increase speed } // Random obstacle generation if (Date.now() - lastObstacleTime > 800) { spawnObstacle(); lastObstacleTime = Date.now(); } }, 100); // Start random event scheduler scheduleRandomEvent(); } function startFlipRunner() { clearCurrentScene(); currentScene = "flipRunner"; setupFlipRunner(); game.addChild(flipRunnerContainer); LK.playMusic('gameMusic'); } function updateFlipRunner() { if (currentScene !== "flipRunner") { return; } flipTunnel.update(); // Update rainbow stars if (flipRunnerContainer.updateStars) { flipRunnerContainer.updateStars(); } // reposition player to follow the shrinking tunnel var halfPlayer = 60; // half of your catPlayer height (120/2) player.y = player.polarity > 0 ? flipTunnel.topY + halfPlayer : flipTunnel.bottomY - halfPlayer; // Update player if (player && player.isAlive) { player.update(); // Update score display var score = Math.floor(player.score); // Properly update the score text using global flipScoreText if (flipScoreText) { flipScoreText.setText("Score: " + score); } // Check for collisions for (var i = obstacles.length - 1; i >= 0; i--) { var obstacle = obstacles[i]; obstacle.update(); // Remove obstacles that have gone off-screen if (obstacle.x < -100) { flipRunnerContainer.removeChild(obstacle); obstacles.splice(i, 1); continue; } // Check for collision with player (same polarity) if (player.intersects(obstacle) && player.polarity === obstacle.polarity) { player.die(); // Update high score var score = Math.floor(player.score); if (!storage.highScoreFlipRunner || score > storage.highScoreFlipRunner) { storage.highScoreFlipRunner = score; var highScoreText = flipRunnerContainer.children[2]; if (highScoreText && highScoreText instanceof Text2) { highScoreText.setText("Best: " + storage.highScoreFlipRunner); } } LK.setScore(score); LK.setTimeout(function () { LK.showGameOver(); }, 1000); } } } } function clearCurrentScene() { if (gameTimer) { LK.clearInterval(gameTimer); gameTimer = null; } game.removeChildren(); if (currentScene === "doodleJump") { // Clean up doodleJump specific resources platforms = []; } else if (currentScene === "catNinja") { // Clean up catNinja specific resources cucumbers = []; coins = []; } else if (currentScene === "flipRunner") { // Clean up flipRunner specific resources obstacles = []; // Clear star interval if it exists if (starInterval) { LK.clearInterval(starInterval); starInterval = null; } // Clear rainbow color cycling interval if (colorInterval) { LK.clearInterval(colorInterval); colorInterval = null; } // Remove any references to tunnel flipTunnel = null; } } // Input handling game.down = function (x, y, obj) { if (currentScene === "doodleJump") { dragNode = player; } else if (currentScene === "catNinja") { // Change direction when tapping anywhere on screen if (player) { player.down(); } } else if (currentScene === "flipRunner" && player && player.isAlive) { // Flip player polarity on tap player.flip(); } }; game.up = function (x, y, obj) { if (currentScene === "catNinja" && dragNode) { // We no longer need to check for swipes in Doge Dodge } dragNode = null; }; game.move = function (x, y, obj) { if (currentScene === "doodleJump" && dragNode) { dragNode.x = x; } else if (currentScene === "catNinja") { // We no longer use drag movement } }; // Main game update loop game.update = function () { if (currentScene === "doodleJump") { updateDoodleJump(); } else if (currentScene === "catNinja") { updateDogeDodge(); } else if (currentScene === "flipRunner") { updateFlipRunner(); } else if (currentScene === "coinFlip") { // Update floating emoji backgrounds if (coinFlipContainer.updateEmojis) { coinFlipContainer.updateEmojis(); } } else if (currentScene === "gameSelection" || currentScene === "mainMenu") { // Update all Sanic instances in menu screens for (var i = 0; i < gameSelectionContainer.children.length; i++) { var child = gameSelectionContainer.children[i]; if (child instanceof Sanic) { child.update(); } } } }; // Initialize game setupMainMenu(); setupGameSelection(); switchToMainMenu();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore1: 0,
highScore2: 0,
highScore3: 0
});
/****
* Classes
****/
var Button = Container.expand(function (text, width, height) {
var self = Container.call(this);
var buttonShape = self.attachAsset('selectionButton', {
anchorX: 0.5,
anchorY: 0.5,
width: width || 400,
height: height || 300
});
// Add gradient and shadow effect to button
buttonShape.tint = 0x4287f5;
// Create enhanced text with shadow and better styling
var buttonText = new Text2(text, {
size: 50,
fill: 0xFFFFFF,
align: 'center',
stroke: 0x000000,
strokeThickness: 5,
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 4
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
// Enhanced down effect with scale
self.down = function () {
buttonShape.alpha = 0.8;
LK.getSound('buttonClick').play();
// Add scale effect on press
tween(self.scale, {
x: 0.95,
y: 0.95
}, {
duration: 100,
easing: tween.easeOutQuad
});
// Add glow effect
LK.effects.flashObject(buttonShape, 0x66ccff, 300);
};
// Enhanced up effect
self.up = function () {
buttonShape.alpha = 1.0;
// Return to normal scale with slight bounce
tween(self.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200,
easing: tween.bounceOut
});
};
return self;
});
// CoinFlip classes
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.isHeads = true;
self.isFlipping = false;
self.flip = function () {
if (self.isFlipping) {
return;
}
self.isFlipping = true;
LK.getSound('flip').play();
var flips = Math.floor(Math.random() * 10) + 5;
var flipDuration = 1500;
function doFlip(flipsLeft) {
if (flipsLeft <= 0) {
self.isFlipping = false;
self.isHeads = Math.random() >= 0.5;
return;
}
tween(coinGraphics, {
scaleX: 0
}, {
duration: flipDuration / (flipsLeft * 2),
onFinish: function onFinish() {
self.isHeads = !self.isHeads;
coinGraphics.tint = self.isHeads ? 0xF1C40F : 0xE67E22;
tween(coinGraphics, {
scaleX: 1
}, {
duration: flipDuration / (flipsLeft * 2),
onFinish: function onFinish() {
doFlip(flipsLeft - 1);
}
});
}
});
}
doFlip(flips);
};
return self;
});
var CryptoCoin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('crypto', {
anchorX: 0.5,
anchorY: 0.5,
width: 100,
height: 100
});
self.speed = Math.random() * 3 + 3;
self.rotationSpeed = (Math.random() - 0.5) * 0.1;
self.update = function () {
self.y += self.speed;
self.rotation += self.rotationSpeed;
};
return self;
});
var CryptoObstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('Trollface', {
anchorX: 0.5,
anchorY: 0.5,
width: 150,
height: 150
});
self.speed = Math.random() * 5 + 5;
self.rotationSpeed = (Math.random() - 0.5) * 0.2;
self.update = function () {
self.y += self.speed;
self.rotation += self.rotationSpeed;
};
return self;
});
// Add prototype method for Button so Button.prototype.up can be called
// Doge Dodge classes
var DogePlayer = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('Doge', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 200
});
self.score = 0;
self.lives = 1;
self.speedX = 8; // Horizontal bouncing speed
self.direction = 1; // 1 for right, -1 for left
self.lastX = 0; // Track last X position
// Bounce movement logic
self.update = function () {
// Store last position
self.lastX = self.x;
// Move in current direction
self.x += self.speedX * self.direction;
// Bounce off edges
if (self.x <= 100 && self.direction < 0) {
self.direction = 1;
self.x = 100;
LK.getSound('jump').play();
LK.effects.flashObject(self, 0x00FFFF, 300);
} else if (self.x >= 1948 && self.direction > 0) {
self.direction = -1;
self.x = 1948;
LK.getSound('jump').play();
LK.effects.flashObject(self, 0x00FFFF, 300);
}
};
// Change direction when clicked
self.down = function () {
self.direction *= -1;
LK.getSound('flip').play();
LK.effects.flashObject(self, 0xFFFFFF, 300);
};
self.collect = function (coin) {
LK.getSound('cashding').play();
LK.effects.flashObject(coin, 0x00FFFF, 300); // Cyan flash for crypto
self.score += 10;
return true;
};
self.hurt = function (obstacle) {
LK.getSound('oof').play();
LK.effects.flashObject(self, 0xFF0000, 300);
self.lives -= 1;
return self.lives <= 0;
};
return self;
});
var DoodlePlatform = Container.expand(function (x, y) {
var self = Container.call(this);
var platformGraphics = self.attachAsset('doodlePlatform', {
anchorX: 0.5,
anchorY: 0.5
});
});
// DoodleJump classes
var DoodlePlayer = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('doodlePlayer', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityY = 0;
self.gravity = 0.5;
self.jumpPower = -15;
self.jump = function () {
self.velocityY = self.jumpPower;
LK.getSound('jump').play();
};
self.update = function () {
self.velocityY += self.gravity;
self.y += self.velocityY;
};
return self;
});
var FlipRunnerObstacle = Container.expand(function (yPosition, speed) {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstaclerunner', {
anchorX: 0.5,
anchorY: 0.5,
width: 100,
height: 100
});
// Determine if obstacle is on top (–1) or bottom (+1)
self.polarity = yPosition > 1366 ? -1 : 1;
self.speed = speed || 15;
self.x = 2200; // start just off‐screen on the right
self.y = yPosition;
// Color based on polarity
obstacleGraphics.tint = self.polarity > 0 ? 0x27ae60 : 0xe74c3c;
// Move left each frame
self.update = function () {
self.x -= self.speed;
};
return self;
});
var FlipRunnerPlayer = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('catPlayer', {
anchorX: 0.5,
anchorY: 0.5
});
self.polarity = 1; // 1 for top, -1 for bottom
self.speed = 10;
self.score = 0;
self.isAlive = true;
self.isFlipping = false; // Track if we're in the middle of a flip
self.animationActive = false;
// Initialize running animation
self.startRunningAnimation = function () {
if (self.animationActive) {
return;
}
self.animationActive = true;
function animateRunCycle() {
// Squash and stretch effect for running
tween(playerGraphics.scale, {
x: playerGraphics.scale.x > 0 ? 1.2 : -1.2,
y: 0.8
}, {
duration: 150,
onFinish: function onFinish() {
tween(playerGraphics.scale, {
x: playerGraphics.scale.x > 0 ? 0.8 : -0.8,
y: 1.2
}, {
duration: 150,
onFinish: function onFinish() {
// Only continue animation if player is alive
if (self.isAlive && self.animationActive) {
animateRunCycle();
} else {
// Reset to normal scale when stopped
tween(playerGraphics.scale, {
x: self.polarity > 0 ? -1 : 1,
y: 1
}, {
duration: 100
});
self.animationActive = false;
}
}
});
}
});
}
// Start the animation cycle
animateRunCycle();
};
self.flip = function () {
if (!self.isAlive) {
return;
}
// Don't allow flip if we're already in the middle of a flip
if (self.isFlipping) {
return;
}
self.isFlipping = true;
self.polarity *= -1;
LK.getSound('flip').play();
LK.getSound('jump').play();
// Store current position
var startY = self.y;
var targetY = self.polarity > 0 ? 600 : 2132;
var midY = (startY + targetY) / 2;
// Add trail effect
function createTrailEffect() {
var trail = new Container();
var trailGraphics = trail.attachAsset('catPlayer', {
anchorX: 0.5,
anchorY: 0.5,
width: playerGraphics.width,
height: playerGraphics.height
});
// Match player's current appearance
trailGraphics.scale.x = playerGraphics.scale.x;
trailGraphics.scale.y = playerGraphics.scale.y;
trailGraphics.rotation = playerGraphics.rotation;
// Position trail at player position
trail.x = self.x;
trail.y = self.y;
trail.alpha = 0.5;
// Add to the same parent as player
self.parent.addChild(trail);
// Fade out and remove
tween(trail, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
self.parent.removeChild(trail);
}
});
}
// Create multiple trails during flip
var trailTimer = LK.setInterval(createTrailEffect, 50);
// Animate the flip with arc motion
tween(self, {
y: midY - 200 // Arc up higher than direct path
}, {
duration: 150,
easing: tween.easeOutQuad,
onFinish: function onFinish() {
// Then down to destination
tween(self, {
y: targetY
}, {
duration: 150,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Clear trail timer when animation completes
LK.clearInterval(trailTimer);
// Set flipping to false to allow flipping again
self.isFlipping = false;
}
});
}
});
// Visual effect when flipping - rotate during movement
tween(playerGraphics, {
rotation: self.polarity > 0 ? 0 : Math.PI,
scaleX: self.polarity > 0 ? -1.3 : 1.3,
// Stretch a bit during flip
scaleY: 0.7
}, {
duration: 150,
onFinish: function onFinish() {
tween(playerGraphics, {
scaleX: self.polarity > 0 ? -1 : 1,
scaleY: 1
}, {
duration: 150,
easing: tween.bounceOut
});
}
});
};
self.update = function () {
self.score += 0.1;
// Invert player's X when on top side of the screen
if (self.polarity > 0) {
// Top side - flip X
playerGraphics.scale.x = -1;
} else {
// Bottom side - normal X
playerGraphics.scale.x = 1;
}
// Start running animation if not already started and player is alive
if (self.isAlive && !self.animationActive) {
self.startRunningAnimation();
}
};
self.die = function () {
if (!self.isAlive) {
return;
}
self.isAlive = false;
self.animationActive = false;
LK.getSound('oof').play();
LK.getSound('oof').play();
LK.effects.flashObject(self, 0xFF0000, 500);
};
return self;
});
var FlipRunnerTunnel = Container.expand(function () {
var self = Container.call(this);
// Top wall
var topWall = self.attachAsset('doodlePlatform', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 400
});
topWall.tint = 0xFF0000; // Start with red for rainbow effect
// Create top glow effect
var topGlow = self.attachAsset('doodlePlatform', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 450
});
topGlow.alpha = 0.4;
topGlow.tint = 0xFF0000;
// Bottom wall
var bottomWall = self.attachAsset('doodlePlatform', {
anchorX: 0,
anchorY: 1,
width: 2048,
height: 400
});
bottomWall.tint = 0x0000FF; // Start with blue for contrast
bottomWall.y = 2732;
// Create bottom glow effect
var bottomGlow = self.attachAsset('doodlePlatform', {
anchorX: 0,
anchorY: 1,
width: 2048,
height: 450
});
bottomGlow.y = 2732;
bottomGlow.alpha = 0.4;
bottomGlow.tint = 0x0000FF;
this.topWall = topWall;
this.bottomWall = bottomWall;
this.topGlow = topGlow;
this.bottomGlow = bottomGlow;
this.initialGap = bottomWall.y - bottomWall.height - topWall.height;
this.gap = this.initialGap;
this.shrinkRate = 0.1; // pixels per frame (tweak as desired)
this.update = function () {
// shrink the gap, but don't go below 400px
this.gap = Math.max(400, this.gap - this.shrinkRate);
// recalc each wall's height so the total gap is correct
var newWallHeight = (2732 - this.gap) / 2;
this.topWall.height = newWallHeight;
this.bottomWall.height = newWallHeight;
this.bottomWall.y = 2732; // anchorY=1 keeps it flush to bottom
// Update glow positions and sizes to match walls
this.topGlow.height = newWallHeight + 50;
this.bottomGlow.height = newWallHeight + 50;
this.bottomGlow.y = 2732;
// expose gap edges for collision detection
this.topY = this.topWall.height;
this.bottomY = this.bottomWall.y - this.bottomWall.height;
// Apply rainbow effect to glows
var colors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x9400D3];
var now = Date.now();
var colorIndex = Math.floor(now / 100 % colors.length);
var nextColorIndex = (colorIndex + 1) % colors.length;
var progress = now % 100 / 100;
// Calculate intermediate color between current and next
var currentColor = colors[colorIndex];
var nextColor = colors[nextColorIndex];
// Extract RGB components
var r1 = currentColor >> 16 & 0xFF;
var g1 = currentColor >> 8 & 0xFF;
var b1 = currentColor & 0xFF;
var r2 = nextColor >> 16 & 0xFF;
var g2 = nextColor >> 8 & 0xFF;
var b2 = nextColor & 0xFF;
// Interpolate between colors
var r = Math.floor(r1 + (r2 - r1) * progress);
var g = Math.floor(g1 + (g2 - g1) * progress);
var b = Math.floor(b1 + (b2 - b1) * progress);
// Create interpolated color
var rainbowColor = r << 16 | g << 8 | b;
// Apply to both glow effects
this.topGlow.tint = rainbowColor;
this.bottomGlow.tint = rainbowColor;
this.topGlow.alpha = 0.8; // Increase glow visibility
this.bottomGlow.alpha = 0.8; // Increase glow visibility
// Bottom glow is color-shifted for variety
var oppositeIndex = (colorIndex + 3) % colors.length;
var oppositeNextIndex = (oppositeIndex + 1) % colors.length;
var oppositeColor = colors[oppositeIndex];
var oppositeNextColor = colors[oppositeNextIndex];
// Extract RGB components for opposite
var or1 = oppositeColor >> 16 & 0xFF;
var og1 = oppositeColor >> 8 & 0xFF;
var ob1 = oppositeColor & 0xFF;
var or2 = oppositeNextColor >> 16 & 0xFF;
var og2 = oppositeNextColor >> 8 & 0xFF;
var ob2 = oppositeNextColor & 0xFF;
// Interpolate between opposite colors
var or = Math.floor(or1 + (or2 - or1) * progress);
var og = Math.floor(og1 + (og2 - og1) * progress);
var ob = Math.floor(ob1 + (ob2 - ob1) * progress);
// Create interpolated opposite color
var oppositeRainbowColor = or << 16 | og << 8 | ob;
this.bottomGlow.tint = oppositeRainbowColor;
};
return self;
});
var HomeButton = Container.expand(function () {
var self = Container.call(this);
// Home button uses text only, no shape
var buttonText = new Text2("", {
size: 40,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 5
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.down = function () {
buttonText.alpha = 0.7;
LK.getSound('buttonClick').play();
};
self.up = function () {
buttonText.alpha = 1.0;
switchToMainMenu();
};
return self;
});
var MemeCoin = Container.expand(function () {
var self = Container.call(this);
// Create both sides of the coin with meme faces
var headsSide = self.attachAsset('Doge', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 200
});
var tailsSide = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 200
});
// Only show heads initially
tailsSide.alpha = 0;
self.isHeads = true;
self.isFlipping = false;
self.onFlipComplete = null;
// Add coin background circle
var coinBg = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5,
width: 220,
height: 220
});
// Place circle behind faces
// Implement our own swapChildren since it doesn't exist
function swapChildren(parent, child1, child2) {
var index1 = parent.children.indexOf(child1);
var index2 = parent.children.indexOf(child2);
if (index1 !== -1 && index2 !== -1) {
// Remove both children
parent.removeChild(child1);
parent.removeChild(child2);
// Add them back in swapped order
if (index1 < index2) {
parent.addChildAt(child2, index1);
parent.addChildAt(child1, index2);
} else {
parent.addChildAt(child1, index2);
parent.addChildAt(child2, index1);
}
}
}
swapChildren(self, coinBg, headsSide);
swapChildren(self, coinBg, tailsSide);
// Enhanced coin flip with meme animations
self.flip = function () {
if (self.isFlipping) {
return;
}
// Start countdown before flipping
var countdownText = new Text2("3", {
size: 300,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 16
});
countdownText.anchor.set(0.5, 0.5);
self.addChild(countdownText);
// Play countdown sound at 50% speed
LK.getSound('countdown').play({
speed: 0.5
});
// Countdown animation with accelerated speed
function countdown(num) {
if (num > 0) {
countdownText.setText(num.toString());
// Pulse animation for countdown - faster duration
tween(countdownText.scale, {
x: 1.5,
y: 1.5
}, {
duration: 150,
// reduced from 300ms
yoyo: true,
repeat: 1,
onFinish: function onFinish() {
LK.setTimeout(function () {
countdown(num - 1);
}, 100); // reduced from 200ms
}
});
} else {
countdownText.setText("FLIP!", {
stroke: 0x000000,
strokeThickness: 16,
fill: 0xFFFFFF,
size: 300
});
// Flash and scale animation for "FLIP!" - faster
LK.effects.flashObject(countdownText, 0xFFFF00, 150); // reduced from 300ms
tween(countdownText.scale, {
x: 2,
y: 2
}, {
duration: 150,
// reduced from 300ms
onFinish: function onFinish() {
LK.setTimeout(function () {
self.removeChild(countdownText);
self.startFlip();
}, 150); // reduced from 300ms
}
});
}
}
countdown(3);
};
self.startFlip = function () {
self.isFlipping = true;
LK.getSound('flip').play();
// Decide the outcome upfront
var finalIsHeads = Math.random() >= 0.5;
// Random number of flips (more than original for drama)
var flips = Math.floor(Math.random() * 10) + 8;
var flipDuration = 2000; // Longer flip for more suspense
// Shake screen effect
LK.effects.shakeScreen(10, 500);
// Initial position for bounce effect
var originalY = self.y;
// Make the coin bounce up first
tween(self, {
y: originalY - 200
}, {
duration: 300,
easing: tween.easeOutQuad,
onFinish: function onFinish() {
// Now start the flipping as coin comes down
doFlip(flips);
// Return to original position with bounce
tween(self, {
y: originalY
}, {
duration: 600,
easing: tween.bounceOut
});
}
});
function doFlip(flipsLeft) {
if (flipsLeft <= 0) {
self.isFlipping = false;
self.isHeads = finalIsHeads; // Use predetermined result
// Only show the side that the coin landed on
// If heads, show Doge; if tails, show coin
headsSide.alpha = self.isHeads ? 1 : 0;
tailsSide.alpha = self.isHeads ? 0 : 1;
// Final bounce effect
tween(self.scale, {
x: 1.3,
y: 1.3
}, {
duration: 200,
yoyo: true,
repeat: 1,
onFinish: function onFinish() {
if (typeof self.onFlipComplete === 'function') {
self.onFlipComplete(self.isHeads);
// Re-enable all buttons after flip completes
if (flipButton) {
flipButton.interactive = true;
}
if (headsButton) {
headsButton.interactive = true;
}
if (tailsButton) {
tailsButton.interactive = true;
}
}
}
});
return;
}
// Calculate if we need to end on heads or tails
// If we're currently showing heads and need to end on heads: need even number of flips
// If we're currently showing heads and need to end on tails: need odd number of flips
// If we're currently showing tails and need to end on heads: need odd number of flips
// If we're currently showing tails and need to end on tails: need even number of flips
var needToFlip = self.isHeads !== finalIsHeads;
var needToAdjustFlips = flipsLeft % 2 === 0 && needToFlip || flipsLeft % 2 === 1 && !needToFlip;
// Adjust the final flip count if needed to end on the correct side
if (needToAdjustFlips) {
flipsLeft += 1;
}
// Make coin appear to flip in 3D by scaling in X direction
tween(self, {
scaleX: 0
}, {
duration: flipDuration / (flipsLeft * 2),
onFinish: function onFinish() {
// Switch sides when flat
self.isHeads = !self.isHeads;
headsSide.alpha = self.isHeads ? 1 : 0;
tailsSide.alpha = self.isHeads ? 0 : 1;
// Flip back to full width
tween(self, {
scaleX: 1
}, {
duration: flipDuration / (flipsLeft * 2),
onFinish: function onFinish() {
doFlip(flipsLeft - 1);
}
});
}
});
}
};
return self;
});
var MemeReaction = Container.expand(function (memeType, size) {
var self = Container.call(this);
// Get the appropriate asset based on type
var assetId = memeType === 'doge' ? 'Doge' : memeType === 'troll' ? 'Trollface' : 'Pepe';
var memeGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5,
width: size || 300,
height: size || 300
});
self.alpha = 0; // Start invisible for entrance animation
// Animate entrance based on type
self.show = function () {
// Different animation for each meme type
if (memeType === 'doge') {
// Doge bounces in happily
self.y -= 200; // Start above target position
tween(self, {
alpha: 1,
y: self.y + 200
}, {
duration: 500,
easing: tween.bounceOut
});
// Play appropriate sound
LK.getSound('wow').play();
} else if (memeType === 'troll') {
// Trollface slides in from side with rotation
self.x += 300; // Start to the right
self.rotation = Math.PI * 2; // Full rotation
tween(self, {
alpha: 1,
x: self.x - 300,
rotation: 0
}, {
duration: 600,
easing: tween.easeOutQuad
});
// Play appropriate sound
LK.getSound('bruh').play();
} else {
// Pepe
// Pepe fades in with a sad wobble
tween(self, {
alpha: 1
}, {
duration: 300,
onFinish: function onFinish() {
// Sad wobble animation
tween(self, {
rotation: -0.1
}, {
duration: 200,
yoyo: true,
repeat: 3,
easing: tween.easeInOutSine
});
}
});
// Play appropriate sound
LK.getSound('wednesday').play();
}
};
// Animate exit
self.hide = function (callback) {
tween(self, {
alpha: 0,
y: self.y - 100
}, {
duration: 500,
easing: tween.easeInQuad,
onFinish: function onFinish() {
if (callback) {
callback();
}
self.destroy();
}
});
};
return self;
});
var Sanic = Container.expand(function () {
var self = Container.call(this);
var sanicGraphics = self.attachAsset('Sanic', {
anchorX: 0.5,
anchorY: 0.5
});
// Speed of Sanic's movement
self.speed = 12;
self.x = -100; // Start off-screen to the left
// Update called every frame
self.update = function () {
// Initialize bobbing variables if not set
if (self.bobOffset === undefined) {
self.bobOffset = 0;
self.bobSpeed = 0.1;
self.bobAmount = 30;
self.originalY = self.y;
}
// Update bobbing animation
self.bobOffset += self.bobSpeed;
self.y = self.originalY + Math.sin(self.bobOffset) * self.bobAmount;
// Add slight rotation to match the bobbing movement
self.rotation = Math.sin(self.bobOffset) * 0.08;
// Move Sanic from left to right
self.x += self.speed;
// Destroy Sanic when he moves off-screen to the right
if (self.x > 2148) {
// 2048 + half of Sanic's width
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C3E50
});
/****
* Game Code
****/
// Background music
// Sound effects
// CatNinja assets
// CoinFlip assets
// DoodleJump assets
// Game state variables
// Removed homeButton shape
var flipTunnel = null;
var flipButton, headsButton, tailsButton; // Button references for coin flip game
// Add prototype method for Button so Button.prototype.up can be called
Button.prototype.up = function () {
this.children[0].alpha = 1.0;
};
var currentScene = "mainMenu";
var currentGame = null;
var dragNode = null;
// Score variables
var score = 0;
var platformsPassed = 0;
// Game-specific variables
var platforms = [];
var cucumbers = [];
var coins = [];
var coin = null;
var player = null;
var gameTimer = null;
var coinFlipGuess = null;
var coinFlipStreak = 0;
var obstacles = [];
var tunnelSpeed = 15;
var lastObstacleTime = 0;
var flipScoreText = null;
// Game backgrounds and containers
var mainMenuContainer = new Container();
var gameSelectionContainer = new Container();
var doodleJumpContainer = new Container();
var coinFlipContainer = new Container();
var catNinjaContainer = new Container();
var flipRunnerContainer = new Container();
function setupMainMenu() {
// Add splash background
var splashBackground = mainMenuContainer.attachAsset('SplashBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 100
});
// Play and loop splash music
LK.playMusic('splashmusic', {
loop: true
});
// Animate the splash background with a dance effect
function animateSplashBackground() {
// Move right and down with slight rotation
tween(splashBackground, {
x: 2048 / 2 + 30,
y: 2732 / 2 + 20,
rotation: 0.03
}, {
duration: 1800,
easing: tween.easeInOutQuad,
onFinish: function onFinish() {
// Move left and up with opposite rotation
tween(splashBackground, {
x: 2048 / 2 - 30,
y: 2732 / 2 - 20,
rotation: -0.03
}, {
duration: 1800,
easing: tween.easeInOutQuad,
onFinish: function onFinish() {
// Move center and down with slight scale change
tween(splashBackground, {
x: 2048 / 2,
y: 2732 / 2 + 15,
rotation: 0,
scaleX: 1.02,
scaleY: 1.02
}, {
duration: 1800,
easing: tween.easeInOutSine,
onFinish: function onFinish() {
// Return to original position and scale
tween(splashBackground, {
x: 2048 / 2,
y: 2732 / 2,
scaleX: 1,
scaleY: 1
}, {
duration: 1800,
easing: tween.easeInOutSine,
onFinish: function onFinish() {
// Repeat the animation
animateSplashBackground();
}
});
}
});
}
});
}
});
}
// Start the background animation
animateSplashBackground();
// Create empty title text first
var titleText = new Text2("", {
size: 200,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 10,
fontWeight: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowAngle: Math.PI / 4,
dropShadowDistance: 12
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 400;
// Prepare for character-by-character reveal
var fullTitleText = "NOX PRESENTS:";
var currentCharIndex = 0;
var charRevealInterval = LK.setInterval(function () {
if (currentCharIndex <= fullTitleText.length) {
titleText.setText(fullTitleText.substring(0, currentCharIndex));
currentCharIndex++;
// Add a small scale bounce effect for each new character
if (currentCharIndex > 1) {
titleText.scale.set(1.1, 1.1);
tween(titleText.scale, {
x: 1.0,
y: 1.0
}, {
duration: 200,
easing: tween.bounceOut
});
}
} else {
var _bounceTitleContinuously = function bounceTitleContinuously() {
// Bounce up
tween(titleText, {
y: 380
}, {
duration: 600,
easing: tween.easeInOutQuad,
onFinish: function onFinish() {
// Bounce down
tween(titleText, {
y: 400
}, {
duration: 600,
easing: tween.easeInOutQuad,
onFinish: _bounceTitleContinuously // Loop the animation
});
}
});
}; // Start continuous bouncing
// Animation complete, clear interval
LK.clearInterval(charRevealInterval);
// Start continuous bouncing animation
_bounceTitleContinuously();
}
}, 150); // Reveal a new character every 150ms
var startButton = new Button("START", 600, 220);
startButton.x = 2048 / 2;
startButton.y = 2732 - 300; // Position at bottom middle of screen
// Add stroke to the button text
// Make sure style object exists before setting properties
if (!startButton.children[1].style) {
startButton.children[1].style = {};
}
startButton.children[1].style.stroke = 0x000000;
startButton.children[1].style.strokeThickness = 10;
startButton.children[1].style.fontSize = 70; // Increase text size too
startButton.up = function () {
Button.prototype.up.call(this);
LK.getSound('yahoo').play();
switchToGameSelection();
};
// Add squash and stretch animation to the start button
function animateStartButton() {
// Squash (wider horizontally, shorter vertically)
tween(startButton.scale, {
x: 1.2,
y: 0.8
}, {
duration: 700,
easing: tween.easeInOutQuad,
onFinish: function onFinish() {
// Stretch (taller vertically, narrower horizontally)
tween(startButton.scale, {
x: 0.9,
y: 1.2
}, {
duration: 700,
easing: tween.easeInOutQuad,
onFinish: function onFinish() {
// Return to normal scale
tween(startButton.scale, {
x: 1.0,
y: 1.0
}, {
duration: 700,
easing: tween.easeInOutQuad,
onFinish: animateStartButton
});
}
});
}
});
}
// Start the button animation
animateStartButton();
mainMenuContainer.addChild(titleText);
mainMenuContainer.addChild(startButton);
}
function setupGameSelection() {
// Add MenuBackground behind all elements
var menuBackground = gameSelectionContainer.attachAsset('MenuBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
// Add Pointguy in front of MenuBackground
var pointguy = gameSelectionContainer.attachAsset('Pointguy', {
anchorX: 0.5,
anchorY: 0.5,
x: 465,
y: 1366
});
// Add bobbing animation to Pointguy
function animatePointguy() {
// Bob up with stretch
tween(pointguy, {
y: 1100,
// Move up by 50px (increased from 40px)
scaleX: 0.95,
// Stretch taller and thinner (reduced from 0.9)
scaleY: 1.05
// Reduced from 1.1
}, {
duration: 2000,
easing: tween.easeInOutQuad,
onFinish: function onFinish() {
// Bob down with squash
tween(pointguy, {
y: 1850,
// Down by 50px from center (increased from original position)
scaleX: 1.05,
// Squash wider and shorter (reduced from 1.1)
scaleY: 0.95
// Reduced from 0.9
}, {
duration: 2000,
easing: tween.easeInOutQuad,
onFinish: animatePointguy // Continue the loop
});
}
});
}
// Start the bobbing animation
animatePointguy();
// Periodically spawn Sanic running across the screen
function spawnSanic() {
var sanic = new Sanic();
sanic.y = 2500; // Position Sanic at a good height on screen
gameSelectionContainer.addChild(sanic);
// Schedule next Sanic to appear after this one leaves
LK.setTimeout(spawnSanic, 4000 + Math.random() * 2000);
}
// Start spawning Sanic characters
spawnSanic();
// Create animated title with shadow and effects
var titleText = new Text2("SELECT A GAME", {
size: 200,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 10,
fontWeight: 'bold',
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowAngle: Math.PI / 4,
dropShadowDistance: 8
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 300;
titleText.alpha = 0;
// Animate title entrance
tween(titleText, {
alpha: 1,
y: 250
}, {
duration: 800,
easing: tween.bounceOut
});
// Setup continuous subtle title animation
function animateTitle() {
tween(titleText, {
y: 270
}, {
duration: 1500,
easing: tween.easeInOutQuad,
onFinish: function onFinish() {
tween(titleText, {
y: 250
}, {
duration: 1500,
easing: tween.easeInOutQuad,
onFinish: animateTitle
});
}
});
}
LK.setTimeout(animateTitle, 1000);
// Create game selection buttons with staggered animations - 25% smaller and repositioned
var game1Button = new Button("Meme Runner\nPolarity Shift", 375, 262); // 25% smaller (500*0.75=375, 350*0.75=262.5)
game1Button.x = 2300; // Start off-screen
game1Button.y = 1100; // Moved up slightly
game1Button.alpha = 0;
var game2Button = new Button("Meme Flip\nChallenge", 375, 262); // 25% smaller
game2Button.x = 2300; // Start off-screen
game2Button.y = 1425; // Centered vertically in the TV screen
game2Button.alpha = 0;
var game3Button = new Button("Meme Dodge\nSimulator", 375, 262); // 25% smaller
game3Button.x = 2300; // Start off-screen
game3Button.y = 1775; // Moved up slightly
game3Button.alpha = 0;
// Add hover/pulse effects to buttons
function setupButtonAnimations(button) {
// Create pulsing animation
function pulseButton(btn) {
tween(btn.scale, {
x: 1.05,
y: 1.05
}, {
duration: 1000,
easing: tween.easeInOutQuad,
onFinish: function onFinish() {
tween(btn.scale, {
x: 1.0,
y: 1.0
}, {
duration: 1000,
easing: tween.easeInOutQuad,
onFinish: function onFinish() {
pulseButton(btn);
}
});
}
});
}
// Start pulsing after entrance animation
LK.setTimeout(function () {
pulseButton(button);
}, 1500);
}
// Animate buttons entering one after another
tween(game1Button, {
x: 2048 / 2 + 125,
alpha: 1
}, {
duration: 700,
easing: tween.bounceOut,
onFinish: function onFinish() {
setupButtonAnimations(game1Button);
// Animate second button after first
tween(game2Button, {
x: 2048 / 2 + 125,
alpha: 1
}, {
duration: 700,
easing: tween.bounceOut,
onFinish: function onFinish() {
setupButtonAnimations(game2Button);
// Animate third button after second
tween(game3Button, {
x: 2048 / 2 + 125,
alpha: 1
}, {
duration: 700,
easing: tween.bounceOut,
onFinish: function onFinish() {
setupButtonAnimations(game3Button);
}
});
}
});
}
});
game1Button.up = function () {
Button.prototype.up.call(this);
// Flash button and add scale effect before starting game
LK.effects.flashObject(this, 0xFFFFFF, 300);
tween(this.scale, {
x: 1.2,
y: 1.2
}, {
duration: 200,
onFinish: function onFinish() {
startFlipRunner();
}
});
};
game2Button.up = function () {
Button.prototype.up.call(this);
// Flash button and add scale effect before starting game
LK.effects.flashObject(this, 0xFFFFFF, 300);
tween(this.scale, {
x: 1.2,
y: 1.2
}, {
duration: 200,
onFinish: function onFinish() {
startCoinFlip();
}
});
};
game3Button.up = function () {
Button.prototype.up.call(this);
// Flash button and add scale effect before starting game
LK.effects.flashObject(this, 0xFFFFFF, 300);
tween(this.scale, {
x: 1.2,
y: 1.2
}, {
duration: 200,
onFinish: function onFinish() {
startCatNinja();
}
});
};
gameSelectionContainer.addChild(titleText);
gameSelectionContainer.addChild(game1Button);
gameSelectionContainer.addChild(game2Button);
gameSelectionContainer.addChild(game3Button);
}
// DoodleJump game implementation
function setupDoodleJump() {
var background = doodleJumpContainer.attachAsset('gameBackground', {
anchorX: 0,
anchorY: 0
});
var homeBtn = new HomeButton();
homeBtn.x = 150;
homeBtn.y = 100;
doodleJumpContainer.addChild(homeBtn);
var scoreText = new Text2("Score: 0", {
size: 50,
fill: 0x000000
});
scoreText.anchor.set(0.5, 0);
scoreText.x = 2048 / 2;
scoreText.y = 50;
doodleJumpContainer.addChild(scoreText);
var highScoreText = new Text2("Best: " + storage.highScore1, {
size: 30,
fill: 0x000000
});
highScoreText.anchor.set(0.5, 0);
highScoreText.x = 2048 / 2;
highScoreText.y = 110;
doodleJumpContainer.addChild(highScoreText);
player = new DoodlePlayer();
player.x = 2048 / 2;
player.y = 2000;
doodleJumpContainer.addChild(player);
// Generate initial platforms
platforms = [];
for (var i = 0; i < 10; i++) {
var platform = new DoodlePlatform(Math.random() * 1800 + 100, 2600 - i * 250);
platforms.push(platform);
doodleJumpContainer.addChild(platform);
}
// First platform is directly under player
platforms[0].x = player.x;
platforms[0].y = player.y + 100;
platforms[0].isMoving = false;
score = 0;
platformsPassed = 0;
}
function updateDoodleJump() {
if (currentScene !== "doodleJump") {
return;
}
player.update();
// Handle platform collision
var onPlatform = false;
for (var i = 0; i < platforms.length; i++) {
var platform = platforms[i];
platform.update();
if (player.velocityY > 0 && player.y < platform.y && player.y + player.velocityY >= platform.y - 70 && Math.abs(player.x - platform.x) < 150) {
player.y = platform.y - 70;
player.jump();
onPlatform = true;
}
}
// Handle screen wrapping for player
if (player.x < 0) {
player.x = 2048;
}
if (player.x > 2048) {
player.x = 0;
}
// Scroll the world when player gets too high
if (player.y < 1000) {
var diff = 1000 - player.y;
player.y = 1000;
// Move platforms down
for (var i = 0; i < platforms.length; i++) {
platforms[i].y += diff;
// If platform is off-screen, reposition it at the top
if (platforms[i].y > 2732) {
platforms[i].y = platforms[i].y - 2732;
platforms[i].x = Math.random() * 1800 + 100;
platforms[i].isMoving = Math.random() > 0.7;
platformsPassed++;
score = platformsPassed * 10;
}
}
}
// Handle game over if player falls off the bottom
if (player.y > 2732) {
// Update high score
if (score > storage.highScore1) {
storage.highScore1 = score;
}
LK.setScore(score);
LK.showGameOver();
}
// Update score display
var scoreText = doodleJumpContainer.children[2];
scoreText.setText("Score: " + score);
}
// Add screen shake effect to LK.effects namespace
if (!LK.effects.shakeScreen) {
LK.effects.shakeScreen = function (intensity, duration) {
var originalX = game.x;
var originalY = game.y;
var shakeInterval = LK.setInterval(function () {
game.x = originalX + (Math.random() * 2 - 1) * intensity;
game.y = originalY + (Math.random() * 2 - 1) * intensity;
}, 16);
LK.setTimeout(function () {
LK.clearInterval(shakeInterval);
game.x = originalX;
game.y = originalY;
}, duration);
};
}
// Add rainbow flash effect to LK.effects namespace
if (!LK.effects.rainbowFlash) {
LK.effects.rainbowFlash = function (obj, duration) {
var colors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x9400D3];
var colorIndex = 0;
var originalTint = obj.tint;
var flashInterval = LK.setInterval(function () {
obj.tint = colors[colorIndex];
colorIndex = (colorIndex + 1) % colors.length;
}, duration / colors.length);
LK.setTimeout(function () {
LK.clearInterval(flashInterval);
obj.tint = originalTint;
}, duration);
};
}
// CoinFlip game implementation
function setupCoinFlip() {
// Create animated background with floating emojis
var background = coinFlipContainer.attachAsset('gameBackground', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
});
background.tint = 0x3498db; // Blue background
// Add animated floating emoji backgrounds
function createFloatingEmoji(emoji, size) {
var emojiText = new Text2(emoji, {
size: size || 40,
fill: 0xFFFFFF,
alpha: 0.3
});
emojiText.x = Math.random() * 2048;
emojiText.y = Math.random() * 2732;
// Random movement direction
emojiText.vx = (Math.random() - 0.5) * 2;
emojiText.vy = (Math.random() - 0.5) * 2;
coinFlipContainer.addChild(emojiText);
return emojiText;
}
// Create 20 random emojis in the background
var emojis = ['💯', '🔥', '🤣', '👌', '💪', '😂', '✨', '🚀', '🎯', '💰'];
var floatingEmojis = [];
for (var i = 0; i < 20; i++) {
var emoji = emojis[Math.floor(Math.random() * emojis.length)];
var size = Math.random() * 30 + 30; // Random size between 30-60
floatingEmojis.push(createFloatingEmoji(emoji, size));
}
// Store emoji update function for game.update
coinFlipContainer.updateEmojis = function () {
for (var i = 0; i < floatingEmojis.length; i++) {
var emoji = floatingEmojis[i];
emoji.x += emoji.vx;
emoji.y += emoji.vy;
// Bounce off edges
if (emoji.x < 0 || emoji.x > 2048) {
emoji.vx *= -1;
}
if (emoji.y < 0 || emoji.y > 2732) {
emoji.vy *= -1;
}
// Slight rotation
emoji.rotation += 0.01;
}
};
// Create enhanced title with meme style font
var titleText = new Text2("MEME FLIP CHALLENGE", {
size: 80,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 15,
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowDistance: 10,
fontWeight: 'bold',
fontStyle: 'italic'
});
titleText.anchor.set(0.5, 0);
titleText.x = 2048 / 2;
titleText.y = 150;
coinFlipContainer.addChild(titleText);
// Make title pulse with rainbow colors
LK.setInterval(function () {
// Cycle through hues
titleText.tint = Math.random() * 0xFFFFFF;
}, 1000);
var streakText = new Text2("Current Streak: 0", {
size: 60,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 8,
dropShadow: true
});
streakText.anchor.set(0.5, 0);
streakText.x = 2048 / 2;
streakText.y = 280;
coinFlipContainer.addChild(streakText);
var highScoreText = new Text2("Best Streak: " + storage.highScore2, {
size: 40,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 5,
dropShadow: true
});
highScoreText.anchor.set(0.5, 0);
highScoreText.x = 2048 / 2;
highScoreText.y = 350;
coinFlipContainer.addChild(highScoreText);
// Use the new MemeCoin instead of regular Coin
coin = new MemeCoin();
coin.x = 2048 / 2;
coin.y = 900;
coinFlipContainer.addChild(coin);
var instructionText = new Text2("Select your guess before flipping", {
size: 50,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 6,
dropShadow: true
});
instructionText.anchor.set(0.5, 0);
instructionText.x = 2048 / 2;
instructionText.y = 1200;
coinFlipContainer.addChild(instructionText);
// Create meme-styled buttons with "HEADZ" and "TAILZ"
headsButton = new Button("HEADZ", 350, 180);
headsButton.x = 2048 / 2 - 230;
headsButton.y = 1400;
headsButton.children[0].tint = 0xF1C40F; // Gold color for heads
coinFlipContainer.addChild(headsButton);
tailsButton = new Button("TAILZ", 350, 180);
tailsButton.x = 2048 / 2 + 230;
tailsButton.y = 1400;
tailsButton.children[0].tint = 0xE74C3C; // Red color for tails
coinFlipContainer.addChild(tailsButton);
flipButton = new Button("FLIP IT!!1!", 450, 180);
flipButton.x = 2048 / 2;
flipButton.y = 1600;
flipButton.children[0].tint = 0x2ECC71; // Green color for flip
coinFlipContainer.addChild(flipButton);
var resultText = new Text2("", {
size: 80,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 10,
dropShadow: true,
dropShadowDistance: 8
});
resultText.anchor.set(0.5, 0);
resultText.x = 2048 / 2;
resultText.y = 1800;
coinFlipContainer.addChild(resultText);
// Container for meme reactions
var memeContainer = new Container();
memeContainer.x = 2048 / 2;
memeContainer.y = 650;
coinFlipContainer.addChild(memeContainer);
// Container for streak bonus effects
var streakBonusContainer = new Container();
streakBonusContainer.x = 2048 / 2;
streakBonusContainer.y = 500;
coinFlipContainer.addChild(streakBonusContainer);
headsButton.up = function () {
Button.prototype.up.call(this);
// Don't do anything if coin is currently flipping
if (coin.isFlipping) {
return;
}
coinFlipGuess = true;
instructionText.setText("You chose: HEADZ");
// Flash button for selection feedback
LK.effects.flashObject(this, 0xF1C40F, 300);
};
tailsButton.up = function () {
Button.prototype.up.call(this);
// Don't do anything if coin is currently flipping
if (coin.isFlipping) {
return;
}
coinFlipGuess = false;
instructionText.setText("You chose: TAILZ");
// Flash button for selection feedback
LK.effects.flashObject(this, 0xE74C3C, 300);
};
flipButton.up = function () {
Button.prototype.up.call(this);
// If already flipping, don't do anything
if (coin.isFlipping) {
return;
}
// If no guess selected, show error message
if (coinFlipGuess === null) {
instructionText.setText("PICK HEADZ OR TAILZ FIRST, BRUH!!");
// Shake text for emphasis
tween(instructionText, {
x: 2048 / 2 + 10
}, {
duration: 50,
yoyo: true,
repeat: 5
});
return;
}
// Clear any existing meme reactions
memeContainer.removeChildren();
// Flash button when pressed
LK.effects.flashObject(this, 0x2ECC71, 300);
// Start the enhanced coin flip
coin.flip();
// Disable all buttons while flipping
flipButton.interactive = false;
headsButton.interactive = false;
tailsButton.interactive = false;
// Use onFlipComplete handler instead of setTimeout
coin.onFlipComplete = function (result) {
var correct = coinFlipGuess === result;
// Clear any previous meme reactions
memeContainer.removeChildren();
if (correct) {
resultText.setText("CORRECT!");
if (resultText && resultText.style) {
resultText.style.fill = "#27AE60";
}
coinFlipStreak++;
// Always play wow sound when guessing correctly
LK.getSound('wow').play();
// Show Pointguy meme reaction
var pointguyReaction = memeContainer.attachAsset('Pointguy', {
anchorX: 0.5,
anchorY: 0.5,
width: 400,
height: 400
});
// Position Pointguy to the left of the coin
pointguyReaction.x = -400; // Position to the left of Doge/Tailz instead of above
pointguyReaction.y = 0; // At the same level as the coin
pointguyReaction.alpha = 0; // Start invisible
tween(pointguyReaction, {
alpha: 1 // Fade in
}, {
duration: 500,
easing: tween.bounceOut
});
// Add text bubble with meme saying
var textBubble = new Text2("CORRECT!! NICE GUESS!", {
size: 40,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
textBubble.anchor.set(0.5, 0);
textBubble.x = 0;
textBubble.y = -250;
pointguyReaction.addChild(textBubble);
// Check for streak bonus at 3 correct flips
if (coinFlipStreak % 3 === 0 && coinFlipStreak > 0) {
// Epic streak celebration
LK.setTimeout(function () {
// Clear existing bonus effects
streakBonusContainer.removeChildren();
// Create rainbow text
var epicStreakText = new Text2("EPIC STREAK: " + coinFlipStreak + "!", {
size: 100,
fill: 0xFFFF00,
stroke: 0xFF00FF,
strokeThickness: 10
});
epicStreakText.anchor.set(0.5, 0.5);
streakBonusContainer.addChild(epicStreakText);
// Rainbow color cycle animation
var hue = 0;
var colorInterval = LK.setInterval(function () {
hue = (hue + 0.05) % 1;
// Manually interpolate colors since tween doesn't have interpolateColor method
var r1 = 0xFF0000 >> 16 & 0xFF;
var g1 = 0xFF0000 >> 8 & 0xFF;
var b1 = 0xFF0000 & 0xFF;
var r2 = 0x00FF00 >> 16 & 0xFF;
var g2 = 0x00FF00 >> 8 & 0xFF;
var b2 = 0x00FF00 & 0xFF;
var r = Math.floor(r1 + (r2 - r1) * hue);
var g = Math.floor(g1 + (g2 - g1) * hue);
var b = Math.floor(b1 + (b2 - b1) * hue);
epicStreakText.tint = r << 16 | g << 8 | b;
}, 50);
// Make text grow and then shrink
tween(epicStreakText.scale, {
x: 1.5,
y: 1.5
}, {
duration: 1000,
yoyo: true,
repeat: 1,
onFinish: function onFinish() {
// Fade out and remove after effect completes
LK.setTimeout(function () {
LK.clearInterval(colorInterval);
tween(epicStreakText, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
streakBonusContainer.removeChildren();
}
});
}, 1000);
}
});
// Add dab animation on high streak
var dabPepe = new MemeReaction('doge', 200);
dabPepe.x = 300;
dabPepe.y = 0;
streakBonusContainer.addChild(dabPepe);
dabPepe.show();
// Shake screen for emphasis
LK.effects.shakeScreen(10, 500);
}, 1000);
}
if (coinFlipStreak > storage.highScore2) {
storage.highScore2 = coinFlipStreak;
highScoreText.setText("Best Streak: " + storage.highScore2);
// Flash high score
LK.effects.flashObject(highScoreText, 0xFFD700, 1000);
}
} else {
resultText.setText("WRONG! Streak wrecked!");
if (resultText && resultText.style) {
resultText.style.fill = "#E74C3C";
}
// Play failure sound
LK.getSound('bruh').play();
// Show different meme reactions based on streak length
if (coinFlipStreak >= 3) {
// Show sad Pepe for losing a good streak
var pepeReaction = new MemeReaction('pepe', 300);
pepeReaction.x = 0;
pepeReaction.y = 0;
memeContainer.addChild(pepeReaction);
pepeReaction.show();
// Add crying text
var sadText = new Text2("Streak of " + coinFlipStreak + " gone...", {
size: 40,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
sadText.anchor.set(0, 0);
sadText.x = 100;
sadText.y = -100;
pepeReaction.addChild(sadText);
} else {
// Show trollface for short streaks
var trollReaction = new MemeReaction('troll', 300);
trollReaction.x = 0;
trollReaction.y = 0;
memeContainer.addChild(trollReaction);
trollReaction.show();
// Add u mad text
var madText = new Text2("U mad?", {
size: 50,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
madText.anchor.set(0, 0);
madText.x = 100;
madText.y = -100;
trollReaction.addChild(madText);
}
LK.setTimeout(function () {
LK.setScore(coinFlipStreak);
LK.showGameOver();
}, 2000);
coinFlipStreak = 0;
// Shake screen on failure
LK.effects.shakeScreen(15, 500);
}
streakText.setText("Current Streak: " + coinFlipStreak);
coinFlipGuess = null;
instructionText.setText("Select your guess before flipping");
// Auto-hide meme reaction after delay
LK.setTimeout(function () {
// Clear meme container - works for both MemeReaction instances and Pointguy
memeContainer.removeChildren();
}, 3000);
};
};
coinFlipStreak = 0;
}
// CatNinja game implementation
function setupDogeDodge() {
// Create vaporwave gradient background
catNinjaContainer.vaporwaveBackground = new Container();
var vaporwaveBackground = catNinjaContainer.vaporwaveBackground;
vaporwaveBackground.y = 0;
vaporwaveBackground.x = 0;
// Initialize memePhrasesContainer
catNinjaContainer.memePhrasesContainer = new Container();
var memePhrasesContainer = catNinjaContainer.memePhrasesContainer;
// Create gradient layers with different colors
var colors = [0xff71ce,
// hot pink
0x01cdfe,
// bright blue
0x05ffa1,
// bright green
0xb967ff,
// purple
0xfffb96 // light yellow
];
// Create multiple gradient rectangles
for (var i = 0; i < colors.length; i++) {
var gradientLayer = vaporwaveBackground.attachAsset('gameBackground', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
});
gradientLayer.tint = colors[i];
gradientLayer.alpha = 0.0; // Start transparent for animation
}
// Add background as first child (behind everything)
catNinjaContainer.addChildAt(vaporwaveBackground, 0);
// Make vaporwaveBackground accessible globally
catNinjaContainer.vaporwaveBackground = vaporwaveBackground;
// Initialize variables for meme phrases
catNinjaContainer.memePhrasesContainer = new Container();
var memePhrasesContainer = catNinjaContainer.memePhrasesContainer;
catNinjaContainer.addChild(memePhrasesContainer);
var homeBtn = new HomeButton();
homeBtn.x = 150;
homeBtn.y = 100;
catNinjaContainer.addChild(homeBtn);
var scoreText = new Text2("Score: 0", {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
scoreText.x = 2048 / 2;
scoreText.y = 50;
catNinjaContainer.addChild(scoreText);
// Store direct reference to score text
catNinjaContainer.scoreText = scoreText;
// Lives UI removed for increased difficulty
var highScoreText = new Text2("Best: " + storage.highScore3, {
size: 30,
fill: 0xFFFFFF
});
highScoreText.anchor.set(0.5, 0);
highScoreText.x = 2048 / 2;
highScoreText.y = 110;
catNinjaContainer.addChild(highScoreText);
var instructionText = new Text2("TAP ANYWHERE TO CHANGE DIRECTION. DODGE OBSTACLES, COLLECT COINS!", {
size: 40,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.x = 2048 / 2;
instructionText.y = 200;
catNinjaContainer.addChild(instructionText);
// Add vaporwave styling to instructions
LK.setTimeout(function () {
tween(instructionText, {
alpha: 0.7
}, {
duration: 1000,
easing: tween.easeInOutSine,
yoyo: true,
repeat: 3
});
}, 1000);
player = new DogePlayer();
player.x = 2048 / 2;
player.y = 2200;
catNinjaContainer.addChild(player);
cucumbers = [];
coins = [];
// Spawn both obstacles and coins
gameTimer = LK.setInterval(function () {
if (Math.random() < 0.7) {
spawnObstacle();
} else {
spawnCoin();
}
}, 800);
}
function spawnObstacle() {
if (currentScene !== "catNinja") {
return;
}
var obstacle = new CryptoObstacle();
obstacle.x = Math.random() * 1800 + 100;
obstacle.y = -200;
cucumbers.push(obstacle);
catNinjaContainer.addChild(obstacle);
}
function spawnCoin() {
if (currentScene !== "catNinja") {
return;
}
var coin = new CryptoCoin();
coin.x = Math.random() * 1800 + 100;
coin.y = -200;
coins.push(coin);
catNinjaContainer.addChild(coin);
}
// Function to spawn flying meme phrases
function spawnMemePhrase() {
if (currentScene !== "catNinja") {
return;
}
// Array of popular meme phrases
var phrases = ["WOW!", "SUCH DODGE!", "VERY SKILL!", "MUCH GAME!", "SO AMAZE!", "EPIC WIN!", "YAAAAAS!", "TO THE MOON!", "STONKS!", "BIG MOOD", "NO CAP!", "THIS IS FINE.", "DEAL WITH IT", "YEET!", "DOGE POWER!", "MUCH SPEED!", "VERY CRYPTO!", "POGGERS!", "LOL", "GET REKT!", "SUCH AMAZING", "VIBES"];
// Select random phrase
var phrase = phrases[Math.floor(Math.random() * phrases.length)];
// Create text with random styling
var textSize = 40 + Math.floor(Math.random() * 60); // Size between 40-100
var colors = [0xFF71CE, 0x01CDFE, 0x05FFA1, 0xB967FF, 0xFFFF00, 0xFF00FF];
var fillColor = colors[Math.floor(Math.random() * colors.length)];
var strokeColor = colors[Math.floor(Math.random() * colors.length)];
var phraseText = new Text2(phrase, {
size: textSize,
fill: fillColor,
stroke: strokeColor,
strokeThickness: 4,
fontWeight: Math.random() > 0.5 ? 'bold' : 'normal',
fontStyle: Math.random() > 0.7 ? 'italic' : 'normal'
});
// Set anchor point for rotation
phraseText.anchor.set(0.5, 0.5);
// Position randomly
var startY = 200 + Math.random() * (2732 - 400);
phraseText.x = -300; // Start off-screen left
phraseText.y = startY;
// Add to container
catNinjaContainer.memePhrasesContainer.addChild(phraseText);
// Random movement parameters
var speed = 5 + Math.random() * 10;
var rotationSpeed = (Math.random() - 0.5) * 0.05;
var updownAmount = Math.random() * 50;
var updownSpeed = Math.random() * 0.1;
// Initial properties
phraseText.speed = speed;
phraseText.rotationSpeed = rotationSpeed;
phraseText.updownAmount = updownAmount;
phraseText.updownSpeed = updownSpeed;
phraseText.updownOffset = Math.random() * Math.PI * 2; // Random starting phase
phraseText.initialY = startY;
// Add update function
phraseText.update = function () {
this.x += this.speed;
this.y = this.initialY + Math.sin(this.updownOffset) * this.updownAmount;
this.updownOffset += this.updownSpeed;
this.rotation += this.rotationSpeed;
// Remove when off-screen
if (this.x > 2348) {
catNinjaContainer.memePhrasesContainer.removeChild(this);
}
};
// Animate entrance with flair
tween(phraseText.scale, {
x: 1.5,
y: 1.5
}, {
duration: 300,
yoyo: true,
repeat: 1,
easing: tween.bounceOut
});
// Add brief flash effect
LK.effects.flashObject(phraseText, 0xFFFFFF, 300);
// Play wow sound occasionally
if (Math.random() < 0.3) {
LK.getSound('wow').play();
}
}
function updateDogeDodge() {
if (currentScene !== "catNinja") {
return;
}
// Re-declare memePhrasesContainer at the top of the function
var memePhrasesContainer = catNinjaContainer.memePhrasesContainer;
// Animate vaporwave background - cycle through gradient colors
var vaporwaveBackground = catNinjaContainer.vaporwaveBackground;
if (vaporwaveBackground && vaporwaveBackground.children && vaporwaveBackground.children.length > 0) {
// Initialize animation data if not already done
if (!vaporwaveBackground.lastUpdate) {
vaporwaveBackground.lastUpdate = Date.now();
vaporwaveBackground.cycleTime = 8000; // 8 seconds for full cycle
// Start color cycling animation
for (var i = 0; i < vaporwaveBackground.children.length; i++) {
var layer = vaporwaveBackground.children[i];
var delay = i * 300; // Stagger the animations
// Cycle through different alphas for each layer
tween(layer, {
alpha: 0.4 + Math.random() * 0.3
}, {
duration: 2000 + i * 500,
easing: tween.easeInOutSine,
onFinish: function (layerIndex) {
return function () {
// Create continuous animations with different durations
var _cycleAlpha = function cycleAlpha(layer, min, max) {
tween(layer, {
alpha: min + Math.random() * 0.2
}, {
duration: 2000 + Math.random() * 2000,
easing: tween.easeInOutSine,
onFinish: function onFinish() {
tween(layer, {
alpha: max - Math.random() * 0.2
}, {
duration: 2000 + Math.random() * 2000,
easing: tween.easeInOutSine,
onFinish: function onFinish() {
_cycleAlpha(layer, min, max);
}
});
}
});
};
// Each layer gets a different alpha range
_cycleAlpha(vaporwaveBackground.children[layerIndex], 0.2 + layerIndex * 0.05, 0.5 - layerIndex * 0.03);
};
}(i)
});
}
}
// Every so often, spawn a meme phrase
if (!catNinjaContainer.memePhrasesContainer.lastPhraseTime) {
catNinjaContainer.memePhrasesContainer.lastPhraseTime = Date.now();
catNinjaContainer.memePhrasesContainer.phraseInterval = 2000 + Math.random() * 3000; // 2-5 seconds
}
// Check if it's time to spawn a new phrase
if (Date.now() - catNinjaContainer.memePhrasesContainer.lastPhraseTime > catNinjaContainer.memePhrasesContainer.phraseInterval) {
spawnMemePhrase();
catNinjaContainer.memePhrasesContainer.lastPhraseTime = Date.now();
catNinjaContainer.memePhrasesContainer.phraseInterval = 2000 + Math.random() * 3000; // 2-5 seconds
}
}
// Update player movement
player.update();
// Update and check collisions with obstacles
for (var i = cucumbers.length - 1; i >= 0; i--) {
var obstacle = cucumbers[i];
obstacle.update();
// Check for collision with player
if (player.intersects(obstacle)) {
// Player got hit by obstacle
catNinjaContainer.removeChild(obstacle);
cucumbers.splice(i, 1);
var gameOver = player.hurt(obstacle);
//catNinjaContainer.children[2].setText("Lives: " + player.lives);
if (gameOver) {
// Game over
LK.clearInterval(gameTimer);
if (player.score > storage.highScore3) {
storage.highScore3 = player.score;
}
LK.setScore(player.score);
LK.showGameOver();
}
continue;
}
// Remove obstacle if it goes off screen
if (obstacle.y > 2900) {
catNinjaContainer.removeChild(obstacle);
cucumbers.splice(i, 1);
}
}
// Update and check collisions with coins
for (var j = coins.length - 1; j >= 0; j--) {
var coin = coins[j];
coin.update();
// Check for collision with player
if (player.intersects(coin)) {
// Player collected coin
player.collect(coin);
catNinjaContainer.removeChild(coin);
coins.splice(j, 1);
continue;
}
// Remove coin if it goes off screen
if (coin.y > 2900) {
catNinjaContainer.removeChild(coin);
coins.splice(j, 1);
}
}
// Update score display
var scoreText = catNinjaContainer.scoreText;
if (scoreText && typeof scoreText.setText === 'function') {
scoreText.setText("Score: " + player.score);
}
// Update lives display using the proper child reference and checking its type
var livesText = catNinjaContainer.children[2];
if (livesText && typeof livesText.setText === 'function') {
livesText.setText("Lives: " + player.lives);
}
// Update all meme phrases
if (memePhrasesContainer) {
for (var i = memePhrasesContainer.children.length - 1; i >= 0; i--) {
var phrase = memePhrasesContainer.children[i];
if (phrase.update) {
phrase.update();
}
}
}
}
// Scene management functions
function switchToMainMenu() {
clearCurrentScene();
currentScene = "mainMenu";
game.addChild(mainMenuContainer);
LK.playMusic('menuMusic');
}
function switchToGameSelection() {
clearCurrentScene();
currentScene = "gameSelection";
game.addChild(gameSelectionContainer);
// Add a flash effect for transition
LK.effects.flashScreen(0xFFFFFF, 500);
// Play transition sound
LK.getSound('buttonClick').play();
// Don't start menu music - keep splash music playing
}
function startDoodleJump() {
clearCurrentScene();
currentScene = "doodleJump";
setupDoodleJump();
game.addChild(doodleJumpContainer);
LK.playMusic('gameMusic');
}
function startCoinFlip() {
clearCurrentScene();
currentScene = "coinFlip";
setupCoinFlip();
game.addChild(coinFlipContainer);
LK.playMusic('gameMusic');
}
function startCatNinja() {
clearCurrentScene();
currentScene = "catNinja";
setupDogeDodge();
game.addChild(catNinjaContainer);
LK.playMusic('gameMusic');
}
function scheduleRandomEvent() {
// pick a delay between 5 000 and 8 000 ms
var delay = 5000 + Math.random() * 3000;
LK.setTimeout(function () {
triggerEvent();
scheduleRandomEvent(); // loop
}, delay);
}
function triggerEvent() {
// Play buzzer sound when random event happens
LK.getSound('buzzer').play();
// Pick a random count between 1 and 3
var count = 1 + Math.floor(Math.random() * 3);
// Create multiple effects based on count
for (var i = 0; i < count; i++) {
// create a temporary sprite for each effect with a random meme asset
var fx = new Container();
// Use one of three meme assets randomly (Doge, Trollface, or Pepe)
var memeAssets = ['Doge', 'Trollface', 'Pepe'];
var randomMeme = memeAssets[Math.floor(Math.random() * memeAssets.length)];
// Generate random size between 100 and 300
var randomSize = 100 + Math.floor(Math.random() * 200);
var gfx = fx.attachAsset(randomMeme, {
anchorX: 0.5,
anchorY: 0.5,
width: randomSize,
height: randomSize
});
// Capture the base scale
var baseSX = fx.scale.x;
var baseSY = fx.scale.y;
// Calculate random position with margins for each effect
var maxX = 2048;
var maxY = 2732;
var margin = 100; // half of effect's max dimension
fx.x = margin + Math.random() * (maxX - margin * 2);
fx.y = margin + Math.random() * (maxY - margin * 2);
flipRunnerContainer.addChild(fx);
// pick spin or pulse at random
if (Math.random() < 0.5) {
// spin for 2s
tween(fx, {
rotation: Math.PI * 2
}, {
duration: 2000
});
} else {
// Compute a random increase between 1% and 25%
var inc = 0.01 + Math.random() * 0.24; // anywhere from 0.01 to 0.25
var scaleFactor = 1 + inc; // final multiplier
// grow & shrink for 2s
tween(fx.scale, {
x: baseSX * scaleFactor,
y: baseSY * scaleFactor
}, {
duration: 1000,
yoyo: true,
repeat: 1
});
}
// remove after 2s using IIFE to properly capture the fx reference
(function (fxToRemove) {
LK.setTimeout(function () {
flipRunnerContainer.removeChild(fxToRemove);
}, 2000);
})(fx);
}
}
function setupFlipRunner() {
var background = flipRunnerContainer.attachAsset('gameBackground', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
});
background.tint = 0x000000; // Black background
// Create container for stars
var starsContainer = new Container();
flipRunnerContainer.addChild(starsContainer);
// Function to create a rainbow star
function createStar() {
var star = new Container();
// Random star size between 5 and 20
var starSize = 5 + Math.random() * 15;
// Random rainbow color
var colors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x9400D3];
var randomColor = colors[Math.floor(Math.random() * colors.length)];
// Create star shape
var starGfx = star.attachAsset('selectionButton', {
anchorX: 0.5,
anchorY: 0.5,
width: starSize,
height: starSize
});
starGfx.tint = randomColor;
// Set initial position
star.x = 2048 + starSize;
star.y = Math.random() * 2732;
// Set star speed
star.speed = 5 + Math.random() * 10;
// Add to container
starsContainer.addChild(star);
return star;
}
// Initialize stars
var stars = [];
for (var i = 0; i < 20; i++) {
var star = createStar();
// Distribute stars across the screen initially
star.x = Math.random() * 2048;
stars.push(star);
}
// Star generation interval
var starInterval = LK.setInterval(function () {
if (stars.length < 30) {
// Limit number of stars
var star = createStar();
stars.push(star);
}
}, 500);
// Star update function
flipRunnerContainer.updateStars = function () {
for (var i = stars.length - 1; i >= 0; i--) {
var star = stars[i];
star.x -= star.speed;
// Remove stars that go off screen
if (star.x < -20) {
starsContainer.removeChild(star);
stars.splice(i, 1);
}
// Slight rotation for twinkling effect
star.rotation += 0.02;
// Cycle through rainbow colors
if (Math.random() < 0.02) {
var colors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x9400D3];
star.children[0].tint = colors[Math.floor(Math.random() * colors.length)];
}
}
};
// Add tunnel with rainbow road effect
flipTunnel = new FlipRunnerTunnel();
flipRunnerContainer.addChild(flipTunnel);
// Add rainbow glow effect to tunnel walls
var colorIndices = [0, 1, 2, 3, 4, 5, 6];
var colors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x9400D3];
var colorIndex = 0;
var colorInterval = LK.setInterval(function () {
// Cycle through colors
colorIndex = (colorIndex + 1) % colors.length;
// Update top and bottom wall colors
tween(flipTunnel.topWall, {
tint: colors[colorIndices[colorIndex]]
}, {
duration: 300
});
// Use a different color for bottom wall for more rainbow effect
tween(flipTunnel.bottomWall, {
tint: colors[(colorIndices[colorIndex] + 3) % colors.length]
}, {
duration: 300
});
// Rotate color indices to create flowing rainbow effect
colorIndices.push(colorIndices.shift());
}, 200);
// Add player
player = new FlipRunnerPlayer();
player.x = 500;
// Player's y position will be set in updateFlipRunner based on tunnel gap
flipRunnerContainer.addChild(player);
// HomeButton removed
var scoreText = new Text2("Score: 0", {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
scoreText.x = 2048 / 2;
scoreText.y = 50;
flipScoreText = scoreText;
var highScoreText = new Text2("Best: " + (storage.highScoreFlipRunner || 0), {
size: 30,
fill: 0xFFFFFF
});
highScoreText.anchor.set(0.5, 0);
highScoreText.x = 2048 / 2;
highScoreText.y = 110;
var instructionText = new Text2("TAP TO FLIP POLARITY!", {
size: 40,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.x = 2048 / 2;
instructionText.y = 200;
flipRunnerContainer.addChild(highScoreText);
flipRunnerContainer.addChild(scoreText);
flipRunnerContainer.addChild(instructionText);
// HomeButton not needed
// Initialize obstacles array
obstacles = [];
tunnelSpeed = 15;
lastObstacleTime = 0;
// Function to spawn obstacles
function spawnObstacle() {
if (currentScene !== "flipRunner" || !player || !player.isAlive) {
return;
}
// Initialize last spawn position if not set
if (spawnObstacle.lastPosition === undefined) {
spawnObstacle.lastPosition = "bottom";
}
// Alternate between top and bottom walls
var obstacleY;
if (spawnObstacle.lastPosition === "bottom") {
// Place on top wall
obstacleY = flipTunnel.topY + Math.random() * 200 + 50;
spawnObstacle.lastPosition = "top";
} else {
// Place on bottom wall
obstacleY = flipTunnel.bottomY - Math.random() * 200 - 50;
spawnObstacle.lastPosition = "bottom";
}
// Create a single obstacle 25% bigger than normal
var obstacle = new FlipRunnerObstacle(obstacleY, tunnelSpeed);
// Make it 25% bigger
obstacle.scale.set(1.25, 1.25);
obstacles.push(obstacle);
flipRunnerContainer.addChild(obstacle);
// Play a sound effect for obstacle spawn
if (Math.random() < 0.3) {}
}
// Start the obstacle spawner
gameTimer = LK.setInterval(function () {
if (tunnelSpeed < 30) {
tunnelSpeed += 0.05; // Gradually increase speed
}
// Random obstacle generation
if (Date.now() - lastObstacleTime > 800) {
spawnObstacle();
lastObstacleTime = Date.now();
}
}, 100);
// Start random event scheduler
scheduleRandomEvent();
}
function startFlipRunner() {
clearCurrentScene();
currentScene = "flipRunner";
setupFlipRunner();
game.addChild(flipRunnerContainer);
LK.playMusic('gameMusic');
}
function updateFlipRunner() {
if (currentScene !== "flipRunner") {
return;
}
flipTunnel.update();
// Update rainbow stars
if (flipRunnerContainer.updateStars) {
flipRunnerContainer.updateStars();
}
// reposition player to follow the shrinking tunnel
var halfPlayer = 60; // half of your catPlayer height (120/2)
player.y = player.polarity > 0 ? flipTunnel.topY + halfPlayer : flipTunnel.bottomY - halfPlayer;
// Update player
if (player && player.isAlive) {
player.update();
// Update score display
var score = Math.floor(player.score);
// Properly update the score text using global flipScoreText
if (flipScoreText) {
flipScoreText.setText("Score: " + score);
}
// Check for collisions
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
obstacle.update();
// Remove obstacles that have gone off-screen
if (obstacle.x < -100) {
flipRunnerContainer.removeChild(obstacle);
obstacles.splice(i, 1);
continue;
}
// Check for collision with player (same polarity)
if (player.intersects(obstacle) && player.polarity === obstacle.polarity) {
player.die();
// Update high score
var score = Math.floor(player.score);
if (!storage.highScoreFlipRunner || score > storage.highScoreFlipRunner) {
storage.highScoreFlipRunner = score;
var highScoreText = flipRunnerContainer.children[2];
if (highScoreText && highScoreText instanceof Text2) {
highScoreText.setText("Best: " + storage.highScoreFlipRunner);
}
}
LK.setScore(score);
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
}
}
function clearCurrentScene() {
if (gameTimer) {
LK.clearInterval(gameTimer);
gameTimer = null;
}
game.removeChildren();
if (currentScene === "doodleJump") {
// Clean up doodleJump specific resources
platforms = [];
} else if (currentScene === "catNinja") {
// Clean up catNinja specific resources
cucumbers = [];
coins = [];
} else if (currentScene === "flipRunner") {
// Clean up flipRunner specific resources
obstacles = [];
// Clear star interval if it exists
if (starInterval) {
LK.clearInterval(starInterval);
starInterval = null;
}
// Clear rainbow color cycling interval
if (colorInterval) {
LK.clearInterval(colorInterval);
colorInterval = null;
}
// Remove any references to tunnel
flipTunnel = null;
}
}
// Input handling
game.down = function (x, y, obj) {
if (currentScene === "doodleJump") {
dragNode = player;
} else if (currentScene === "catNinja") {
// Change direction when tapping anywhere on screen
if (player) {
player.down();
}
} else if (currentScene === "flipRunner" && player && player.isAlive) {
// Flip player polarity on tap
player.flip();
}
};
game.up = function (x, y, obj) {
if (currentScene === "catNinja" && dragNode) {
// We no longer need to check for swipes in Doge Dodge
}
dragNode = null;
};
game.move = function (x, y, obj) {
if (currentScene === "doodleJump" && dragNode) {
dragNode.x = x;
} else if (currentScene === "catNinja") {
// We no longer use drag movement
}
};
// Main game update loop
game.update = function () {
if (currentScene === "doodleJump") {
updateDoodleJump();
} else if (currentScene === "catNinja") {
updateDogeDodge();
} else if (currentScene === "flipRunner") {
updateFlipRunner();
} else if (currentScene === "coinFlip") {
// Update floating emoji backgrounds
if (coinFlipContainer.updateEmojis) {
coinFlipContainer.updateEmojis();
}
} else if (currentScene === "gameSelection" || currentScene === "mainMenu") {
// Update all Sanic instances in menu screens
for (var i = 0; i < gameSelectionContainer.children.length; i++) {
var child = gameSelectionContainer.children[i];
if (child instanceof Sanic) {
child.update();
}
}
}
};
// Initialize game
setupMainMenu();
setupGameSelection();
switchToMainMenu();
a ’90s-retro living room: bean-bag, Super Nintendo wired to the tube TV, “3-in-1 Meme Games” written on-screen, while a mix of meme characters crash the couch mashing SNES controllers wired to the super nintendo. In-Game asset. 2d. High contrast. No shadows
retro tube tv with crt scan lines. add a living room background behind the tv, front facing so i can use it as a menu selection screen In-Game asset. 2d. High contrast. No shadows
pointing soyjak meme. In-Game asset. 2d. High contrast. No shadows
hedgehog running fast meme. In-Game asset. 2d. High contrast. No shadows
trollface. In-Game asset. 2d. High contrast. No shadows
doge. In-Game asset. 2d. High contrast. No shadows
fluffy tail. In-Game asset. 2d. High contrast. No shadows
pepe frog. In-Game asset. 2d. High contrast. No shadows
running pepe frog. In-Game asset. 2d. High contrast. No shadows
3d button empty. In-Game asset. 2d. High contrast. No shadows
keyboard cat meme. In-Game asset. 2d. High contrast. No shadows
shiba inu coin. In-Game asset. 2d. High contrast. No shadows