/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var DesktopIcon = Container.expand(function (iconName, x, y) { var self = Container.call(this); // Create icon background for selection effect var iconBg = self.attachAsset('desktopIcon', { anchorX: 0.5, anchorY: 0.5, width: 72, height: 88 }); iconBg.alpha = 0; // Initially transparent // Create the actual icon var icon = self.attachAsset('desktopIcon', { anchorX: 0.5, anchorY: 0.5 }); // Set icon color based on type if (iconName === "My Computer") { icon.tint = 0x87CEEB; // Light blue } else if (iconName === "Recycle Bin") { icon.tint = 0x00FF00; // Green } else if (iconName === "Notepad") { icon.tint = 0xFFFFFF; // White } else if (iconName === "Calculator") { icon.tint = 0xDDDDDD; // Light gray } else if (iconName === "Explorer") { icon.tint = 0xFFD700; // Gold } else if (iconName === "Corrupted") { icon.tint = 0xFF0000; } else if (iconName === "CMD") { icon.tint = 0x000000; // Black for command prompt } else if (iconName === "Chrome") { // Use circular icon for Chrome self.removeChild(icon); icon = self.attachAsset('chromeIcon', { anchorX: 0.5, anchorY: 0.5 }); icon.tint = 0x4285F4; // Blue Chrome icon } var label = new Text2(iconName, { size: 24, fill: 0xFFFFFF }); label.anchor.set(0.5, 0); label.y = 40; self.addChild(label); self.x = x; self.y = y; self.name = iconName; self.interactive = true; self.isSelected = false; self.down = function () { // Show blue selection background iconBg.alpha = 0.3; iconBg.tint = 0x0000FF; self.isSelected = true; icon.alpha = 0.7; LK.getSound('click').play(); }; self.up = function () { icon.alpha = 1; // Double-click effect (simplified) if (self.isSelected) { createWindow(iconName); // Reset selection after opening window LK.setTimeout(function () { iconBg.alpha = 0; self.isSelected = false; }, 300); } }; return self; }); var GlitchEffect = Container.expand(function () { var self = Container.call(this); // Particle properties self.particles = []; self.particleCount = 200; self.colors = [0xff00ff, 0x00ffff, 0xffff00, 0xff0000, 0x00ff00, 0x0000ff]; self.active = false; self.virusSongPlaying = false; self.activationTime = 0; self.sinkFactor = 0; self.sinkDirection = 1; // Create glitch particles for (var i = 0; i < self.particleCount; i++) { var particle = self.attachAsset('glitchParticle', { anchorX: 0.5, anchorY: 0.5 }); // Random starting position off-screen particle.x = Math.random() * 2048; particle.y = -50 - Math.random() * 200; // Random size between 5 and 30 var size = 5 + Math.random() * 25; particle.width = size; particle.height = size; // Random color from glitch palette particle.tint = self.colors[Math.floor(Math.random() * self.colors.length)]; // Random alpha particle.alpha = 0.5 + Math.random() * 0.5; // Additional properties for movement particle.speedX = Math.random() * 8 - 4; particle.speedY = 2 + Math.random() * 6; particle.rotation = Math.random() * Math.PI * 2; particle.rotationSpeed = (Math.random() - 0.5) * 0.2; // Hide initially particle.visible = false; self.particles.push(particle); } // Sink effect tracking properties self.lastSinkPhaseTime = 0; self.sinkPhase = 0; // 0 = not started, 1 = sinking, 2 = unsinking // Create background glitch overlay self.background = self.attachAsset('desktop', { anchorX: 0, anchorY: 0, width: 2048, height: 2732 }); self.background.tint = 0xff00ff; self.background.alpha = 0; // Activate glitch effect self.activate = function () { if (self.active) { return; } self.active = true; self.activationTime = LK.ticks; self.virusSongPlaying = false; // Reset particles for (var i = 0; i < self.particles.length; i++) { var particle = self.particles[i]; particle.visible = true; particle.x = Math.random() * 2048; particle.y = -50 - Math.random() * 200; } // Stop any existing virus sounds before starting new ones LK.getSound('virus').stop(); // Play virus sound in loop LK.getSound('virus').play(); // Schedule next virus sound to create loop effect self.soundLoop = LK.setInterval(function () { LK.getSound('virus').play(); }, 1000); // Start sinking effect self.sinkFactor = 0; self.sinkDirection = 1; }; // Update glitch effect self.update = function () { if (!self.active) { return; } // Update background color based on time var time = LK.ticks / 10; var r = Math.sin(time * 0.021) * 127 + 128; var g = Math.sin(time * 0.022 + 2) * 127 + 128; var b = Math.sin(time * 0.023 + 4) * 127 + 128; var color = Math.floor(r) << 16 | Math.floor(g) << 8 | Math.floor(b); self.background.tint = color; self.background.alpha = 0.2 + Math.sin(time * 0.1) * 0.05; // Check if 5 seconds have passed since activation to start virus song if (!self.virusSongPlaying && self.active && (LK.ticks - self.activationTime) / 60 >= 5) { self.virusSongPlaying = true; // Stop the regular virus sound loop LK.clearInterval(self.soundLoop); // Create continuous glitchy jumbled noise self.glitchySoundLoop = LK.setInterval(function () { // Play virus sound at different rates and overlapping for glitchy effect LK.getSound('virus').play(); LK.setTimeout(function () { LK.getSound('virus').play(); }, 100); LK.setTimeout(function () { LK.getSound('virus').play(); }, 200); }, 300); } // Calculate elapsed time in seconds since activation var elapsedTimeSeconds = (LK.ticks - self.activationTime) / 60; // Check if 25 seconds have passed to start rotation effect if (elapsedTimeSeconds >= 25) { // Apply rotation effect - gradually rotate the screen over time var rotationSpeed = 0.001; var rotationAngle = (elapsedTimeSeconds - 25) * rotationSpeed; // Stop the glitchy sound loop if it's active if (self.glitchySoundLoop) { LK.clearInterval(self.glitchySoundLoop); self.glitchySoundLoop = null; // Also stop the playing virus sounds immediately LK.getSound('virus').stop(); } // Apply rotation to game game.rotation = rotationAngle; // Adjust position to keep content centered during rotation var centerX = 2048 / 2; var centerY = 2732 / 2; game.x = centerX; game.y = centerY; // Check if 40 seconds have passed (15 seconds after rotation started) to show restart message if (elapsedTimeSeconds >= 40) { // Check if we haven't already switched to the SystemStart var systemStartExists = false; for (var i = 0; i < game.children.length; i++) { if (game.children[i] instanceof SystemStart) { systemStartExists = true; break; } } if (!systemStartExists) { // Find and store the mouse cursor before cleaning up var cursor = null; for (var i = 0; i < game.children.length; i++) { if (game.children[i] instanceof MouseCursor) { cursor = game.children[i]; game.removeChild(cursor); break; } } // Remove all children from game while (game.children.length > 0) { var child = game.children[0]; game.removeChild(child); } // Reset game transform game.rotation = 0; game.x = 0; game.y = 0; game.scale.y = 1; // Show SystemStart screen var startScreen = new SystemStart(); game.addChild(startScreen); // Restore the mouse cursor if (cursor) { game.addChild(cursor); } startScreen.startSequence(); } } return; // Skip other effects when in rotation mode } // Check if 20 seconds have passed to start sink effect (only until 25 seconds) var timeSinceSinkStart = elapsedTimeSeconds - 20; // Time since the 20 second mark // If we're past 20 seconds but before 25 seconds, handle sink/unsink cycles if (elapsedTimeSeconds >= 20 && elapsedTimeSeconds < 25) { // Determine which 5-second cycle we're in (0 = first sink, 1 = first unsink, etc.) var sinkCycle = Math.floor(timeSinceSinkStart / 5); // If even cycle (0, 2, 4...), we should be sinking, otherwise unsinking if (sinkCycle % 2 === 0) { // Sinking phase - calculate progress within 5-second window var sinkProgress = timeSinceSinkStart % 5 / 5; self.sinkFactor = sinkProgress; } else { // Unsinking phase - calculate progress within 5-second window var unsinkProgress = timeSinceSinkStart % 5 / 5; self.sinkFactor = 1 - unsinkProgress; } // Apply sink effect - stronger than the regular effect game.scale.y = 1 - self.sinkFactor * 0.5; game.y = 2732 * self.sinkFactor * 0.5 / 2; } else { // Regular subtle sink animation before 20 seconds self.sinkFactor += 0.005 * self.sinkDirection; if (self.sinkFactor > 1) { self.sinkDirection = -1; } else if (self.sinkFactor < 0) { self.sinkDirection = 1; } // Apply subtle sink effect game.scale.y = 1 - self.sinkFactor * 0.1; game.y = 2732 * self.sinkFactor * 0.1 / 2; } // Update particles for (var i = 0; i < self.particles.length; i++) { var particle = self.particles[i]; // Move particle particle.x += particle.speedX; particle.y += particle.speedY; // Rotate particle particle.rotation += particle.rotationSpeed; // If particle goes off screen, reset it if (particle.y > 2732) { particle.x = Math.random() * 2048; particle.y = -20; // Randomly change color if (Math.random() < 0.3) { particle.tint = self.colors[Math.floor(Math.random() * self.colors.length)]; } // Randomly change alpha particle.alpha = 0.5 + Math.random() * 0.5; } // If particle goes off sides, bounce or wrap if (particle.x < 0 || particle.x > 2048) { if (Math.random() < 0.5) { particle.speedX *= -1; // Bounce } else { particle.x = particle.x < 0 ? 2048 : 0; // Wrap } } } }; return self; }); var MouseCursor = Container.expand(function () { var self = Container.call(this); // Create arrow pointer shape var cursorContainer = new Container(); self.addChild(cursorContainer); // Create white arrow outline var arrowBody = LK.getAsset('desktopIcon', { anchorX: 0, anchorY: 0, width: 20, height: 24 }); arrowBody.tint = 0xFFFFFF; arrowBody.rotation = Math.PI / 6; // Slight tilt cursorContainer.addChild(arrowBody); // Create black inner arrow (slightly smaller) var arrowInner = LK.getAsset('desktopIcon', { anchorX: 0, anchorY: 0, width: 16, height: 20 }); arrowInner.tint = 0x000000; arrowInner.x = 2; arrowInner.y = 2; arrowInner.rotation = Math.PI / 6; // Same tilt cursorContainer.addChild(arrowInner); // Create left ear var leftEar = LK.getAsset('desktopIcon', { anchorX: 0.5, anchorY: 1, width: 8, height: 12 }); leftEar.tint = 0x888888; leftEar.x = 6; leftEar.y = 0; cursorContainer.addChild(leftEar); // Create right ear var rightEar = LK.getAsset('desktopIcon', { anchorX: 0.5, anchorY: 1, width: 8, height: 12 }); rightEar.tint = 0x888888; rightEar.x = 14; rightEar.y = 0; cursorContainer.addChild(rightEar); // Track if the cursor is over a clickable element self.isOverClickable = false; // Update cursor position self.updatePosition = function (x, y) { self.x = x; self.y = y; }; // Change cursor when over clickable elements self.setPointer = function (isPointer) { self.isOverClickable = isPointer; if (isPointer) { tween(cursorContainer, { rotation: 0, scaleX: 1.1, scaleY: 1.1 }, { duration: 100 }); leftEar.tint = 0xCCCCCC; rightEar.tint = 0xCCCCCC; } else { tween(cursorContainer, { rotation: 0, scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); leftEar.tint = 0x888888; rightEar.tint = 0x888888; } }; return self; }); var StartMenu = Container.expand(function () { var self = Container.call(this); var menu = self.attachAsset('startMenu', { anchorX: 0, anchorY: 1 }); var menuItems = ["Programs", "Documents", "Settings", "Find", "Help", "Run...", "Log Off...", "Shut Down..."]; for (var i = 0; i < menuItems.length; i++) { var itemText = new Text2(menuItems[i], { size: 24, fill: 0x000000 }); itemText.x = 34; itemText.y = 10 + i * 40; self.addChild(itemText); } self.x = 0; self.y = 2732; // Bottom of screen self.visible = false; return self; }); var SystemCrashScreen = Container.expand(function () { var self = Container.call(this); // Create black background var blackBg = self.attachAsset('desktop', { anchorX: 0, anchorY: 0, width: 2048, height: 2732 }); blackBg.tint = 0x000000; // Keep black background // Create error text var errorText = new Text2("FATAL ERROR: System files removed\n\nUnable to locate C:\\WINDOWS\\SYSTEM32\n\nSystem restart failed.\n\nPress any key to continue...", { size: 32, fill: 0xFFFFFF // White text for better visibility on black background }); errorText.anchor.set(0.5, 0.5); errorText.x = 2048 / 2; errorText.y = 2732 / 2; self.addChild(errorText); self.interactive = true; // Make entire screen clickable self.down = function () { LK.getSound('error').play(); }; // Show restart button after 10 seconds LK.setTimeout(function () { // Change error text errorText.setText("FATAL ERROR: System files removed\n\nUnable to locate C:\\WINDOWS\\SYSTEM32\n\nSystem restart failed."); // Add restart button var restartButton = new Container(); restartButton.interactive = true; var buttonBg = LK.getAsset('startButton', { anchorX: 0.5, anchorY: 0.5, width: 220, height: 60 }); buttonBg.tint = 0xFF0000; var buttonText = new Text2("Remove everything and restart Windows 98", { size: 18, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); restartButton.addChild(buttonBg); restartButton.addChild(buttonText); restartButton.x = 2048 / 2; restartButton.y = 2732 / 2 + 200; // Add click functionality to button restartButton.down = function () { buttonBg.tint = 0xAA0000; LK.getSound('error').play(); }; restartButton.up = function () { buttonBg.tint = 0xFF0000; // Play multiple error sounds for (var i = 0; i < 10; i++) { LK.setTimeout(function () { LK.getSound('error').play(); }, i * 100); } // Reset the OS (recreate the game) LK.setTimeout(function () { // Find and store the mouse cursor before clearing var oldCursor = null; for (var i = 0; i < game.children.length; i++) { if (game.children[i] instanceof MouseCursor) { oldCursor = game.children[i]; break; } } if (oldCursor) { game.removeChild(oldCursor); } // Clear everything else while (game.children.length > 0) { game.removeChild(game.children[0]); } // Add "Restarting..." text in a black background var desktop = game.addChild(LK.getAsset('desktop', { anchorX: 0, anchorY: 0, width: 2048, height: 2732 })); desktop.tint = 0x000000; var restartText = new Text2("Restarting Windows 98...", { size: 40, fill: 0xFFFFFF }); restartText.anchor.set(0.5, 0.5); restartText.x = 2048 / 2; restartText.y = 2732 / 2; game.addChild(restartText); // Restore the mouse cursor if (oldCursor) { game.addChild(oldCursor); } // Play startup sound LK.setTimeout(function () { LK.getSound('startup').play(); // Create and start the system startup sequence LK.setTimeout(function () { // Store cursor before clearing var cursor = null; for (var i = 0; i < game.children.length; i++) { if (game.children[i] instanceof MouseCursor) { cursor = game.children[i]; game.removeChild(cursor); break; } } // Remove restart text and black background while (game.children.length > 0) { game.removeChild(game.children[0]); } // Add SystemStart screen var startScreen = new SystemStart(); game.addChild(startScreen); // Restore cursor if (cursor) { game.addChild(cursor); } startScreen.startSequence(); }, 3000); }, 2000); }, 2000); }; self.addChild(restartButton); }, 10000); return self; }); var SystemStart = Container.expand(function () { var self = Container.call(this); // Black background var blackBg = self.attachAsset('desktop', { anchorX: 0, anchorY: 0, width: 2048, height: 2732 }); blackBg.tint = 0xFFFFFF; // Set white background instead of black // Starting Windows 98 setup text var startingText = new Text2("Windows 98 Setup", { size: 40, fill: 0x000000 // Change text color to black for better visibility on white background }); startingText.anchor.set(0.5, 0.5); startingText.x = 2048 / 2; startingText.y = 2732 / 2; self.addChild(startingText); // Progress to different stages self.startSequence = function () { // Stop the virus sound if it's playing LK.getSound('virus').stop(); // Add download button immediately var downloadButton = LK.getAsset('startButton', { anchorX: 0.5, anchorY: 0.5, width: 200, height: 50 }); downloadButton.tint = 0x4CAF50; // Green color downloadButton.x = 2048 / 2; downloadButton.y = 2732 / 2 + 200; downloadButton.interactive = true; self.addChild(downloadButton); var downloadText = new Text2("DOWNLOAD NOW", { size: 24, fill: 0xFFFFFF }); downloadText.anchor.set(0.5, 0.5); downloadText.x = 2048 / 2; downloadText.y = 2732 / 2 + 200; self.addChild(downloadText); // Add download button interactivity downloadButton.down = function () { this.tint = 0x388E3C; // Darker green when pressed this.y += 2; // Small push effect LK.getSound('click').play(); }; downloadButton.up = function () { this.tint = 0x4CAF50; // Back to normal green this.y -= 2; // Reset push effect }; // After 10 seconds, show setup stages LK.setTimeout(function () { startingText.setText("Windows XP Setup - Preparing Installation"); // Add setup message var setupMessage = new Text2("Collecting information about your computer...", { size: 24, fill: 0x000000 }); setupMessage.anchor.set(0.5, 0.5); setupMessage.x = 2048 / 2; setupMessage.y = 2732 / 2 + 100; self.addChild(setupMessage); // After 5 more seconds, show next setup stage LK.setTimeout(function () { startingText.setText("Windows 98 Setup - Installing Windows"); setupMessage.setText("Copying files... (45%)"); // After 5 more seconds, show final setup stage LK.setTimeout(function () { startingText.setText("Windows 98 Setup - Completing Installation"); setupMessage.setText("Setting up your computer for first use..."); // Add setup progress bar var progressBarBg = LK.getAsset('desktopIcon', { anchorX: 0, anchorY: 0.5, width: 400, height: 20 }); progressBarBg.tint = 0xCCCCCC; progressBarBg.x = 2048 / 2 - 200; progressBarBg.y = 2732 / 2 + 150; self.addChild(progressBarBg); var progressBar = LK.getAsset('desktopIcon', { anchorX: 0, anchorY: 0.5, width: 380, height: 16 }); progressBar.tint = 0x0000AA; progressBar.x = 2048 / 2 - 190; progressBar.y = 2732 / 2 + 150; self.addChild(progressBar); // Animate progress bar tween(progressBar, { width: 0 }, { duration: 4000, onFinish: function onFinish() { // Store the current mouse cursor before removing it var oldCursor = null; for (var i = 0; i < game.children.length; i++) { if (game.children[i] instanceof MouseCursor) { oldCursor = game.children[i]; game.removeChild(oldCursor); break; } } // Remove SystemStart screen game.removeChild(self); // Recreate desktop initializeDesktop(); // Restore the original mouse cursor if it exists if (oldCursor) { game.addChild(oldCursor); } } }); }, 5000); }, 5000); }, 10000); }; return self; }); var Window = Container.expand(function (title, width, height) { var self = Container.call(this); self.isActive = true; self.width = width || 800; self.height = height || 600; // Create a white background for the window var windowBg = self.attachAsset('window', { anchorX: 0, anchorY: 0, width: self.width, height: self.height }); windowBg.tint = 0xFFFFFF; // Set white background var titleBar = self.attachAsset('windowTitle', { anchorX: 0, anchorY: 0, width: self.width, height: 28 }); var titleText = new Text2(title, { size: 20, fill: 0xFFFFFF }); titleText.x = 10; titleText.y = 4; self.addChild(titleText); var closeButton = self.attachAsset('closeButton', { anchorX: 0, anchorY: 0 }); closeButton.x = self.width - 28; closeButton.y = 2; closeButton.interactive = true; var minimizeButton = self.attachAsset('minimizeButton', { anchorX: 0, anchorY: 0 }); minimizeButton.x = self.width - 56; minimizeButton.y = 2; minimizeButton.interactive = true; var content = self.attachAsset('programContent', { anchorX: 0, anchorY: 0, width: self.width - 20, height: self.height - 50 }); content.tint = 0xFFFFFF; // Set white background content.x = 10; content.y = 40; // Program specific content self.contentArea = new Container(); self.contentArea.x = 10; self.contentArea.y = 40; self.addChild(self.contentArea); self.isDragging = false; self.dragOffsetX = 0; self.dragOffsetY = 0; titleBar.interactive = true; titleBar.down = function (x, y) { self.isDragging = true; self.dragOffsetX = x; self.dragOffsetY = y; // Bring window to front if (self.parent) { var index = self.parent.children.indexOf(self); if (index >= 0) { // Remove from current position self.parent.children.splice(index, 1); // Add to end (top) self.parent.children.push(self); } } }; titleBar.up = function () { self.isDragging = false; }; closeButton.down = function () { closeButton.alpha = 0.7; LK.getSound('click').play(); }; closeButton.up = function () { closeWindow(self); }; minimizeButton.down = function () { minimizeButton.alpha = 0.7; LK.getSound('click').play(); }; minimizeButton.up = function () { minimizeButton.alpha = 1; minimizeWindow(self); }; return self; }); var NotepadWindow = Window.expand(function () { var self = Window.call(this, "Notepad", 700, 500); var textArea = new Text2("Start typing here...", { size: 24, fill: 0x000000 }); textArea.x = 10; textArea.y = 10; self.contentArea.addChild(textArea); return self; }); var GameWindow = Window.expand(function () { var self = Window.call(this, "Game", 800, 600); // Game area background var gameArea = LK.getAsset('programContent', { anchorX: 0, anchorY: 0, width: self.width - 20, height: self.height - 50 }); gameArea.tint = 0xFFFFFF; // Set white background instead of black self.contentArea.addChild(gameArea); // Create game title var gameTitle = new Text2("DRAG ME!", { size: 48, fill: 0x000000 // Change text color to black for better visibility on white background }); gameTitle.anchor.set(0.5, 0.5); gameTitle.x = (self.width - 20) / 2; gameTitle.y = 80; self.contentArea.addChild(gameTitle); // Create draggable ball var gameBall = new Container(); gameBall.x = (self.width - 20) / 2; gameBall.y = (self.height - 50) / 2 + 50; gameBall.interactive = true; self.contentArea.addChild(gameBall); // Ball background var ballBg = LK.getAsset('desktopIcon', { anchorX: 0.5, anchorY: 0.5, width: 150, height: 150 }); ballBg.tint = 0x4285F4; // Blue color gameBall.addChild(ballBg); // Ball letters var ballText = "GAME!"; var colors = [0x4285F4, 0xEA4335, 0xFBBC05, 0x4285F4, 0x34A853, 0xEA4335]; // Blue, Red, Yellow, Blue, Green, Red var ballLetters = []; for (var i = 0; i < ballText.length; i++) { var letter = new Text2(ballText[i], { size: 36, fill: colors[i % colors.length] }); letter.anchor.set(0.5, 0.5); // Position in a circle var angle = i / ballText.length * Math.PI * 2; var radius = 60; letter.x = Math.cos(angle) * radius; letter.y = Math.sin(angle) * radius; letter.rotation = angle + Math.PI / 2; letter.initialX = letter.x; letter.initialY = letter.y; letter.initialRotation = letter.rotation; gameBall.addChild(letter); ballLetters.push(letter); } // Add instruction text var instructionText = new Text2("Works on all devices!", { size: 18, fill: 0x000000 // Change text color to black for better visibility on white background }); instructionText.anchor.set(0.5, 0.5); instructionText.x = (self.width - 20) / 2; instructionText.y = (self.height - 50) / 2 + 150; self.contentArea.addChild(instructionText); // Track ball state var ballActive = false; var lastX = 0; var lastY = 0; // Make ball interactive gameBall.down = function (x, y, obj) { ballActive = true; var localPos = gameBall.toLocal({ x: x, y: y }); lastX = localPos.x; lastY = localPos.y; // Scale effect on press tween(gameBall, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100 }); // Update instruction text instructionText.setText("Dragging..."); LK.getSound('click').play(); }; gameBall.move = function (x, y, obj) { if (ballActive) { var localPos = gameBall.toLocal({ x: x, y: y }); var dx = localPos.x - lastX; var dy = localPos.y - lastY; // Move the ball letters based on the drag for (var i = 0; i < ballLetters.length; i++) { var letter = ballLetters[i]; // Calculate new position based on drag direction and speed var angle = Math.atan2(dy, dx); var speed = Math.sqrt(dx * dx + dy * dy) * 0.1; // Rotate the letters in the direction of the drag letter.rotation = letter.initialRotation + angle; // Move slightly in drag direction letter.x = letter.initialX + Math.cos(angle) * speed * 2; letter.y = letter.initialY + Math.sin(angle) * speed * 2; } lastX = localPos.x; lastY = localPos.y; } }; gameBall.up = function (x, y, obj) { ballActive = false; // Reset instruction text instructionText.setText("Works on all devices!"); // Return to original size tween(gameBall, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); // Return letters to original positions for (var i = 0; i < ballLetters.length; i++) { var letter = ballLetters[i]; tween(letter, { x: letter.initialX, y: letter.initialY, rotation: letter.initialRotation }, { duration: 500, easing: tween.easeElastic }); } }; // Animate the ball constantly to show it's interactive LK.setInterval(function () { if (!ballActive) { // Gentle rotation animation var time = LK.ticks / 60; for (var i = 0; i < ballLetters.length; i++) { var letter = ballLetters[i]; letter.x = letter.initialX + Math.sin(time + i * 0.5) * 5; letter.y = letter.initialY + Math.cos(time + i * 0.5) * 5; letter.rotation = letter.initialRotation + Math.sin(time * 0.2 + i) * 0.1; } } }, 16); // ~60fps animation return self; }); var ExplorerWindow = Window.expand(function () { var self = Window.call(this, "File Explorer", 800, 600); var folderStructure = ["My Documents", "My Computer", "Network Neighborhood", "Recycle Bin"]; for (var i = 0; i < folderStructure.length; i++) { // Create a container for each folder item to handle interactions var folderItem = new Container(); folderItem.interactive = true; folderItem.x = 10; folderItem.y = i * 60 + 10; var folderIcon = LK.getAsset('desktopIcon', { anchorX: 0, anchorY: 0, width: 48, height: 48 }); folderIcon.tint = 0xFFFF00; folderIcon.x = 0; folderIcon.y = 0; var folderName = new Text2(folderStructure[i], { size: 20, fill: 0x000000 }); folderName.x = 60; folderName.y = 14; folderItem.addChild(folderIcon); folderItem.addChild(folderName); // Add click functionality folderItem.name = folderStructure[i]; folderItem.lastSelected = false; folderItem.down = function () { this.children[0].tint = 0xCCCC00; // Darker yellow when clicked LK.getSound('click').play(); }; folderItem.up = function () { this.children[0].tint = 0xFFFF00; // Back to normal yellow // Open a new Explorer window or perform folder-specific action if (this.name === "My Computer") { createWindow("Explorer"); } else if (this.name === "Recycle Bin") { var emptyBinWindow = new Window("Empty Recycle Bin?", 400, 200); emptyBinWindow.x = (2048 - 400) / 2; emptyBinWindow.y = (2732 - 200) / 2; game.addChild(emptyBinWindow); activeWindows.push(emptyBinWindow); } }; self.contentArea.addChild(folderItem); } return self; }); // Red for corrupted app var CorruptedWindow = Window.expand(function () { var self = Window.call(this, "Error", 500, 300); var errorMessage = new Text2("A fatal exception has occurred.\nThe current application will be terminated.\n\nPress OK to close this window.", { size: 24, fill: 0x000000 }); errorMessage.x = 20; errorMessage.y = 30; self.contentArea.addChild(errorMessage); var okButton = new Container(); okButton.interactive = true; okButton.x = 200; okButton.y = 180; var buttonGraphic = LK.getAsset('startButton', { anchorX: 0.5, anchorY: 0.5, width: 100, height: 40 }); buttonGraphic.tint = 0xDDDDDD; var buttonText = new Text2("OK", { size: 24, fill: 0x000000 }); buttonText.anchor.set(0.5, 0.5); buttonText.x = 0; buttonText.y = 0; okButton.addChild(buttonGraphic); okButton.addChild(buttonText); okButton.down = function () { buttonGraphic.tint = 0xAAAAAA; LK.getSound('click').play(); }; okButton.up = function () { buttonGraphic.tint = 0xDDDDDD; closeWindow(self); }; self.contentArea.addChild(okButton); return self; }); var CommandPromptWindow = Window.expand(function () { var self = Window.call(this, "Command Prompt", 700, 500); // Black background for command prompt var cmdBackground = LK.getAsset('desktopIcon', { anchorX: 0, anchorY: 0, width: self.width - 20, height: self.height - 50 }); cmdBackground.tint = 0xFFFFFF; // Set white background instead of black cmdBackground.x = 0; cmdBackground.y = 0; self.contentArea.addChild(cmdBackground); // Initial command prompt text var promptText = new Text2("C:\\WINDOWS>_", { size: 24, fill: 0x000000 // Change text color to black for better visibility on white background }); promptText.x = 10; promptText.y = 10; self.contentArea.addChild(promptText); // Instructions text var instructionsText = new Text2("Click anywhere to type...", { size: 20, fill: 0x555555 // Darker gray for better visibility on white background }); instructionsText.x = 10; instructionsText.y = 50; self.contentArea.addChild(instructionsText); // Make entire content area interactive cmdBackground.interactive = true; // Flag to track if deleting system32 message is shown self.isDeleting = false; // Function to show error messages self.showErrors = function () { if (self.isDeleting) { return; } // Prevent multiple calls self.isDeleting = true; // Change text to show deleting system32 promptText.setText("C:\\WINDOWS>DEL C:\\WINDOWS\\SYSTEM32\\*.* /F /S /Q\n\nDELETING SYSTEM FILES...\nTHIS ACTION CANNOT BE UNDONE!"); promptText.tint = 0xFF0000; instructionsText.visible = false; // Play multiple error sounds with slight delay between them LK.getSound('error').play(); // Create continuous error flood var errorInterval = LK.setInterval(function () { LK.getSound('error').play(); var errorWindow = new CorruptedWindow(); errorWindow.x = Math.random() * (2048 - 500); errorWindow.y = Math.random() * (2732 - 400); game.addChild(errorWindow); activeWindows.push(errorWindow); }, 1); // Create a new error every millisecond // Initial burst of errors LK.setTimeout(function () { for (var i = 0; i < 20; i++) { LK.setTimeout(function () { LK.getSound('error').play(); var errorWindow = new CorruptedWindow(); errorWindow.x = Math.random() * (2048 - 500); errorWindow.y = Math.random() * (2732 - 400); game.addChild(errorWindow); activeWindows.push(errorWindow); }, i * 50); } }, 100); // After 10 seconds, trigger system crash and restart LK.setTimeout(function () { // Change prompt text to show restart promptText.setText("C:\\WINDOWS>DEL C:\\WINDOWS\\SYSTEM32\\*.* /F /S /Q\n\nDELETING SYSTEM FILES... COMPLETE\n\nFATAL ERROR: Critical system files missing\n\nRESTARTING WINDOWS 98..."); // Clear all error windows LK.clearInterval(errorInterval); for (var i = activeWindows.length - 1; i >= 0; i--) { game.removeChild(activeWindows[i]); } activeWindows = []; // Play multiple error sounds for (var i = 0; i < 5; i++) { LK.setTimeout(function () { LK.getSound('error').play(); }, i * 200); } // Wait 2 more seconds then show crash screen LK.setTimeout(function () { // Find and store the mouse cursor before cleaning up var cursor = null; for (var i = 0; i < game.children.length; i++) { if (game.children[i] instanceof MouseCursor) { cursor = game.children[i]; game.removeChild(cursor); break; } } // Remove all children from game while (game.children.length > 0) { var child = game.children[0]; game.removeChild(child); } // Show crash screen var crashScreen = new SystemCrashScreen(); game.addChild(crashScreen); // Restore the mouse cursor if (cursor) { game.addChild(cursor); } }, 2000); }, 10000); }; // Click handler cmdBackground.down = function () { LK.getSound('error').play(); self.showErrors(); // Add more immediate errors on click for (var i = 0; i < 10; i++) { LK.setTimeout(function () { LK.getSound('error').play(); var errorWindow = new CorruptedWindow(); errorWindow.x = Math.random() * (2048 - 500); errorWindow.y = Math.random() * (2732 - 400); game.addChild(errorWindow); activeWindows.push(errorWindow); }, i * 10); // Very small delay between each error } }; return self; }); var ChromeWindow = Window.expand(function () { var self = Window.call(this, "Google Chrome", 900, 650); // Create toolbar var toolbar = self.attachAsset('desktopIcon', { anchorX: 0, anchorY: 0, width: self.width - 20, height: 40 }); toolbar.tint = 0xF0F0F0; toolbar.x = 0; toolbar.y = 0; self.contentArea.addChild(toolbar); // Create address bar var addressBar = LK.getAsset('desktopIcon', { anchorX: 0, anchorY: 0, width: self.width - 100, height: 30 }); addressBar.tint = 0xFFFFFF; addressBar.x = 80; addressBar.y = 5; toolbar.addChild(addressBar); // URL text var urlText = new Text2("https://www.google.com", { size: 18, fill: 0x000000 }); urlText.x = 10; urlText.y = 5; addressBar.addChild(urlText); // Navigation buttons var backButton = LK.getAsset('desktopIcon', { anchorX: 0.5, anchorY: 0.5, width: 24, height: 24 }); backButton.tint = 0x777777; backButton.x = 25; backButton.y = 20; toolbar.addChild(backButton); var forwardButton = LK.getAsset('desktopIcon', { anchorX: 0.5, anchorY: 0.5, width: 24, height: 24 }); forwardButton.tint = 0x777777; forwardButton.x = 55; forwardButton.y = 20; toolbar.addChild(forwardButton); // Create page content area var pageContent = LK.getAsset('programContent', { anchorX: 0, anchorY: 0, width: self.width - 20, height: self.height - 90 }); pageContent.tint = 0xFFFFFF; // Ensure white background pageContent.x = 0; pageContent.y = 45; self.contentArea.addChild(pageContent); // Google logo var googleLogo = new Container(); googleLogo.x = (self.width - 20) / 2; googleLogo.y = 120; pageContent.addChild(googleLogo); // Create Google interactive text ball var textBall = new Container(); textBall.x = (self.width - 20) / 2; textBall.y = 320; textBall.interactive = true; pageContent.addChild(textBall); // Create Google logo parts (G, o, o, g, l, e) var colors = [0x4285F4, 0xEA4335, 0xFBBC05, 0x4285F4, 0x34A853, 0xEA4335]; // Blue, Red, Yellow, Blue, Green, Red var letters = ["G", "o", "o", "g", "l", "e"]; // Track text ball state var ballActive = false; var lastX = 0; var lastY = 0; var ballLetters = []; for (var i = 0; i < letters.length; i++) { var letter = new Text2(letters[i], { size: 48, fill: colors[i] }); letter.anchor.set(0.5, 0.5); letter.x = i * 30 - 75; letter.y = 0; googleLogo.addChild(letter); // Create copies for the ball var ballLetter = new Text2(letters[i], { size: 36, fill: colors[i] }); ballLetter.anchor.set(0.5, 0.5); // Position in a circle var angle = i / letters.length * Math.PI * 2; var radius = 60; ballLetter.x = Math.cos(angle) * radius; ballLetter.y = Math.sin(angle) * radius; ballLetter.rotation = angle + Math.PI / 2; ballLetter.initialX = ballLetter.x; ballLetter.initialY = ballLetter.y; ballLetter.initialRotation = ballLetter.rotation; textBall.addChild(ballLetter); ballLetters.push(ballLetter); } // Ball background var ballBg = LK.getAsset('desktopIcon', { anchorX: 0.5, anchorY: 0.5, width: 150, height: 150 }); ballBg.tint = 0xF8F8F8; ballBg.alpha = 0.7; textBall.addChildAt(ballBg, 0); // Create search bar var searchBar = LK.getAsset('desktopIcon', { anchorX: 0.5, anchorY: 0.5, width: 450, height: 40 }); searchBar.tint = 0xFFFFFF; searchBar.x = (self.width - 20) / 2; searchBar.y = 200; pageContent.addChild(searchBar); // Add "Interactive" text below ball var interactiveText = new Text2("Drag me! Works on all devices", { size: 18, fill: 0x555555 }); interactiveText.anchor.set(0.5, 0.5); interactiveText.x = 0; interactiveText.y = 90; textBall.addChild(interactiveText); // Magnifying glass icon var searchIcon = LK.getAsset('desktopIcon', { anchorX: 0.5, anchorY: 0.5, width: 20, height: 20 }); searchIcon.tint = 0x777777; searchIcon.x = -200; searchIcon.y = 0; searchBar.addChild(searchIcon); // Search buttons var searchButton = LK.getAsset('desktopIcon', { anchorX: 0.5, anchorY: 0.5, width: 120, height: 36 }); searchButton.tint = 0xF0F0F0; searchButton.x = (self.width - 20) / 2 - 70; searchButton.y = 260; pageContent.addChild(searchButton); var searchButtonText = new Text2("Google Search", { size: 16, fill: 0x555555 }); searchButtonText.anchor.set(0.5, 0.5); searchButtonText.x = 0; searchButtonText.y = 0; searchButton.addChild(searchButtonText); var luckyButton = LK.getAsset('desktopIcon', { anchorX: 0.5, anchorY: 0.5, width: 150, height: 36 }); luckyButton.tint = 0xF0F0F0; luckyButton.x = (self.width - 20) / 2 + 90; luckyButton.y = 260; pageContent.addChild(luckyButton); var luckyButtonText = new Text2("I'm Feeling Lucky", { size: 16, fill: 0x555555 }); luckyButtonText.anchor.set(0.5, 0.5); luckyButtonText.x = 0; luckyButtonText.y = 0; luckyButton.addChild(luckyButtonText); // Add Free Download Button var downloadButton = LK.getAsset('desktopIcon', { anchorX: 0.5, anchorY: 0.5, width: 180, height: 50 }); downloadButton.tint = 0x4CAF50; // Green color downloadButton.x = (self.width - 20) / 2; downloadButton.y = 330; downloadButton.interactive = true; pageContent.addChild(downloadButton); var downloadText = new Text2("FREE DOWNLOAD", { size: 20, fill: 0xFFFFFF }); downloadText.anchor.set(0.5, 0.5); downloadText.x = 0; downloadText.y = 0; downloadButton.addChild(downloadText); // Add download button interactivity downloadButton.down = function () { this.tint = 0x388E3C; // Darker green when pressed this.y += 2; // Small push effect LK.getSound('click').play(); }; downloadButton.up = function () { this.tint = 0x4CAF50; // Back to normal green this.y -= 2; // Reset push effect // Show some feedback when clicked var feedbackText = new Text2("Download Started!", { size: 16, fill: 0xff0000 }); feedbackText.anchor.set(0.5, 0.5); feedbackText.x = (self.width - 20) / 2; feedbackText.y = 390; pageContent.addChild(feedbackText); // Create virus glitch effect if not already exists var glitchEffect = null; for (var i = 0; i < game.children.length; i++) { if (game.children[i] instanceof GlitchEffect) { glitchEffect = game.children[i]; break; } } if (!glitchEffect) { glitchEffect = new GlitchEffect(); game.addChild(glitchEffect); } // Activate glitch effect glitchEffect.activate(); // Change desktop background to glitch color var desktop = null; for (var i = 0; i < game.children.length; i++) { if (game.children[i].width === 2048 && game.children[i].height === 2732 && game.children[i] !== glitchEffect) { desktop = game.children[i]; break; } } if (desktop) { desktop.tint = 0xff00ff; // Set background to glitch color } // Remove feedback after 2 seconds LK.setTimeout(function () { pageContent.removeChild(feedbackText); }, 2000); }; // Make text ball interactive textBall.down = function (x, y, obj) { ballActive = true; var localPos = textBall.toLocal({ x: x, y: y }); lastX = localPos.x; lastY = localPos.y; // Scale effect on press tween(textBall, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100 }); // Update ball text to show it's being pressed interactiveText.setText("Dragging..."); LK.getSound('click').play(); }; textBall.move = function (x, y, obj) { if (ballActive) { var localPos = textBall.toLocal({ x: x, y: y }); var dx = localPos.x - lastX; var dy = localPos.y - lastY; // Move the ball letters based on the drag for (var i = 0; i < ballLetters.length; i++) { var letter = ballLetters[i]; // Calculate new position based on drag direction and speed var angle = Math.atan2(dy, dx); var speed = Math.sqrt(dx * dx + dy * dy) * 0.1; // Rotate the letters in the direction of the drag letter.rotation = letter.initialRotation + angle; // Move slightly in drag direction letter.x = letter.initialX + Math.cos(angle) * speed * 2; letter.y = letter.initialY + Math.sin(angle) * speed * 2; } lastX = localPos.x; lastY = localPos.y; } }; textBall.up = function (x, y, obj) { ballActive = false; // Reset ball text interactiveText.setText("Drag me! Works on all devices"); // Return to original size tween(textBall, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); // Return letters to original positions for (var i = 0; i < ballLetters.length; i++) { var letter = ballLetters[i]; tween(letter, { x: letter.initialX, y: letter.initialY, rotation: letter.initialRotation }, { duration: 500, easing: tween.easeElastic }); } }; // Animate the text ball constantly to show it's interactive LK.setInterval(function () { if (!ballActive) { // Gentle rotation animation var time = LK.ticks / 60; for (var i = 0; i < ballLetters.length; i++) { var letter = ballLetters[i]; letter.x = letter.initialX + Math.sin(time + i * 0.5) * 5; letter.y = letter.initialY + Math.cos(time + i * 0.5) * 5; letter.rotation = letter.initialRotation + Math.sin(time * 0.2 + i) * 0.1; } } }, 16); // ~60fps animation // Make buttons interactive searchButton.interactive = true; searchButton.down = function () { this.tint = 0xE0E0E0; LK.getSound('click').play(); }; searchButton.up = function () { this.tint = 0xF0F0F0; }; luckyButton.interactive = true; luckyButton.down = function () { this.tint = 0xE0E0E0; LK.getSound('click').play(); }; luckyButton.up = function () { this.tint = 0xF0F0F0; }; addressBar.interactive = true; addressBar.down = function () { urlText.tint = 0x4285F4; LK.getSound('click').play(); }; return self; }); var CalculatorWindow = Window.expand(function () { var self = Window.call(this, "Calculator", 300, 400); var currentValue = "0"; var previousValue = ""; var operation = ""; var resetDisplay = false; var display = new Text2("0", { size: 36, fill: 0x000000 }); display.x = 10; display.y = 10; self.contentArea.addChild(display); function updateDisplay() { display.setText(currentValue); } function calculate() { var prev = parseFloat(previousValue); var current = parseFloat(currentValue); var result = 0; switch (operation) { case "+": result = prev + current; break; case "-": result = prev - current; break; case "*": result = prev * current; break; case "/": result = prev / current; break; } return result.toString(); } function handleButtonClick(label) { LK.getSound('click').play(); if (label >= "0" && label <= "9") { if (currentValue === "0" || resetDisplay) { currentValue = label; resetDisplay = false; } else { currentValue += label; } updateDisplay(); } else if (label === ".") { if (!currentValue.includes(".")) { currentValue += "."; updateDisplay(); } } else if (["+", "-", "*", "/"].includes(label)) { previousValue = currentValue; operation = label; resetDisplay = true; } else if (label === "=") { if (previousValue && operation) { currentValue = calculate(); previousValue = ""; operation = ""; resetDisplay = true; updateDisplay(); } } } var buttonLabels = ["7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "0", ".", "=", "+"]; var buttonSize = 60; var padding = 5; var buttonsPerRow = 4; for (var i = 0; i < buttonLabels.length; i++) { var buttonX = i % buttonsPerRow * (buttonSize + padding) + 10; var buttonY = Math.floor(i / buttonsPerRow) * (buttonSize + padding) + 60; var buttonBg = new Container(); buttonBg.interactive = true; buttonBg.x = buttonX; buttonBg.y = buttonY; var buttonGraphic = LK.getAsset('desktopIcon', { anchorX: 0, anchorY: 0, width: buttonSize, height: buttonSize }); buttonGraphic.tint = 0xDDDDDD; var buttonText = new Text2(buttonLabels[i], { size: 30, fill: 0x000000 }); buttonText.anchor.set(0.5, 0.5); buttonText.x = buttonSize / 2; buttonText.y = buttonSize / 2; // Store the button label for the event handlers buttonBg.name = buttonLabels[i]; // Add click handling buttonBg.down = function () { this.children[0].tint = 0xAAAAAA; // Darken on press }; buttonBg.up = function () { this.children[0].tint = 0xDDDDDD; // Restore color handleButtonClick(this.name); }; buttonBg.addChild(buttonGraphic); buttonBg.addChild(buttonText); self.contentArea.addChild(buttonBg); } return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x008080 // Windows 98 teal background }); /**** * Game Code ****/ // Global variables // Windows XP blue var activeWindows = []; var startMenuOpen = false; var dragTarget = null; var savedWindowPositions = {}; // Create the desktop background var desktop = game.addChild(LK.getAsset('desktop', { anchorX: 0, anchorY: 0, width: 2048, height: 2732 })); desktop.tint = 0x008080; // Windows 98 teal // Create the taskbar var taskbar = game.addChild(LK.getAsset('taskbar', { anchorX: 0, anchorY: 1, width: 2048, height: 50 })); taskbar.y = 2732; taskbar.tint = 0xc0c0c0; // Windows 98 gray taskbar // Create the start button var startButton = game.addChild(LK.getAsset('startButton', { anchorX: 0, anchorY: 1, width: 100, height: 40 })); startButton.x = 5; startButton.y = 2732 - 5; startButton.interactive = true; startButton.tint = 0xc0c0c0; // Windows 98 gray start button // Create the start menu var startMenu = game.addChild(new StartMenu()); // Add "Start" text to start button var startText = new Text2("Start", { size: 24, fill: 0x000000 //{dy} // Black text for Win98 start button }); startText.x = 35; startText.y = 2732 - 35; game.addChild(startText); // Create desktop icons var icons = [{ name: "My Computer", x: 100, y: 100 }, { name: "Recycle Bin", x: 100, y: 200 }, { name: "Notepad", x: 100, y: 300 }, { name: "Calculator", x: 100, y: 400 }, { name: "Explorer", x: 100, y: 500 }, { name: "Corrupted", x: 100, y: 600 }, { name: "CMD", x: 100, y: 700 }, { name: "Chrome", x: 100, y: 800 }]; icons.forEach(function (icon) { var desktopIcon = new DesktopIcon(icon.name, icon.x, icon.y); game.addChild(desktopIcon); }); // Create time display in taskbar var timeDisplay = new Text2(getCurrentTime(), { size: 24, fill: 0x000000 }); timeDisplay.anchor.set(1, 0.5); timeDisplay.x = 2048 - 10; timeDisplay.y = 2732 - 25; game.addChild(timeDisplay); // Handle desktop clicks desktop.interactive = true; desktop.down = function () { if (startMenuOpen) { toggleStartMenu(); } }; // Start button handling startButton.down = function () { startButton.alpha = 0.7; LK.getSound('click').play(); }; startButton.up = function () { startButton.alpha = 1; toggleStartMenu(); }; // Game update function game.update = function () { // Update time display every second if (LK.ticks % 60 === 0) { timeDisplay.setText(getCurrentTime()); } // Handle window dragging if (dragTarget && dragTarget.isDragging) { dragTarget.x = lastMoveX - dragTarget.dragOffsetX; dragTarget.y = lastMoveY - dragTarget.dragOffsetY; // Keep windows within screen bounds dragTarget.x = Math.max(0, Math.min(2048 - dragTarget.width, dragTarget.x)); dragTarget.y = Math.max(0, Math.min(2732 - 50 - dragTarget.height, dragTarget.y)); } // Update glitch effect if active for (var i = 0; i < game.children.length; i++) { if (game.children[i] instanceof GlitchEffect) { game.children[i].update(); break; } } }; // Track mouse/touch position var lastMoveX = 0; var lastMoveY = 0; game.move = function (x, y) { lastMoveX = x; lastMoveY = y; }; // Handle global mouse up game.up = function () { if (dragTarget) { dragTarget.isDragging = false; dragTarget = null; } }; // Helper functions function toggleStartMenu() { startMenuOpen = !startMenuOpen; startMenu.visible = startMenuOpen; if (startMenuOpen) { LK.getSound('click').play(); } } function createWindow(type) { var newWindow; switch (type) { case "Notepad": newWindow = new NotepadWindow(); break; case "Calculator": newWindow = new CalculatorWindow(); break; case "Explorer": case "My Computer": newWindow = new ExplorerWindow(); break; case "Corrupted": LK.getSound('error').play(); newWindow = new CorruptedWindow(); break; case "CMD": newWindow = new CommandPromptWindow(); break; case "Chrome": newWindow = new ChromeWindow(); break; default: newWindow = new Window(type, 600, 400); } // Position window - either from saved position or center if (savedWindowPositions[type]) { newWindow.x = savedWindowPositions[type].x; newWindow.y = savedWindowPositions[type].y; } else { newWindow.x = (2048 - newWindow.width) / 2; newWindow.y = (2732 - 50 - newWindow.height) / 2; } // Add Windows 98 style opening animation newWindow.scale.x = 0.1; newWindow.scale.y = 0.1; // Add to active windows and game activeWindows.push(newWindow); game.addChild(newWindow); // Animate window opening tween(newWindow, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeOut }); // Set as drag target dragTarget = newWindow; // Close start menu if open if (startMenuOpen) { toggleStartMenu(); } // Play sound LK.getSound('click').play(); return newWindow; } function closeWindow(window) { // Save position savedWindowPositions[window.children[1].text] = { x: window.x, y: window.y }; // Remove from active windows var index = activeWindows.indexOf(window); if (index > -1) { activeWindows.splice(index, 1); } // Remove from game game.removeChild(window); window.destroy(); // Clear drag target if it was this window if (dragTarget === window) { dragTarget = null; } } function minimizeWindow(window) { // Just hide for now - in a real implementation we'd add a taskbar button window.visible = false; // Remove from active windows but don't destroy var index = activeWindows.indexOf(window); if (index > -1) { activeWindows.splice(index, 1); } } function getCurrentTime() { var date = new Date(); var hours = date.getHours(); var minutes = date.getMinutes(); var ampm = hours >= 12 ? 'PM' : 'AM'; hours = hours % 12; hours = hours ? hours : 12; minutes = minutes < 10 ? '0' + minutes : minutes; return hours + ':' + minutes + ' ' + ampm; } // Create mouse cursor var mouseCursor = new MouseCursor(); game.addChild(mouseCursor); // Check if cursor is over a clickable element function updateCursorStyle() { var isOverClickable = false; // Check if over a desktop icon for (var i = 0; i < game.children.length; i++) { var child = game.children[i]; if (child instanceof DesktopIcon && lastMoveX >= child.x - 32 && lastMoveX <= child.x + 32 && lastMoveY >= child.y - 32 && lastMoveY <= child.y + 32) { isOverClickable = true; break; } } // Check if over explorer items in open windows for (var j = 0; j < activeWindows.length; j++) { var window = activeWindows[j]; if (window instanceof ExplorerWindow) { for (var k = 0; k < window.contentArea.children.length; k++) { var item = window.contentArea.children[k]; if (item.interactive && lastMoveX >= window.x + window.contentArea.x + item.x && lastMoveX <= window.x + window.contentArea.x + item.x + 150 && lastMoveY >= window.y + window.contentArea.y + item.y && lastMoveY <= window.y + window.contentArea.y + item.y + 50) { isOverClickable = true; break; } } } } // Update cursor style mouseCursor.setPointer(isOverClickable); } // Extend game.move to update mouse cursor var originalMove = game.move; game.move = function (x, y) { originalMove(x, y); mouseCursor.updatePosition(x, y); updateCursorStyle(); }; // Function to initialize desktop function initializeDesktop() { // Create the desktop background var desktop = game.addChild(LK.getAsset('desktop', { anchorX: 0, anchorY: 0, width: 2048, height: 2732 })); desktop.tint = 0x008080; // Windows 98 teal background // Create the taskbar var taskbar = game.addChild(LK.getAsset('taskbar', { anchorX: 0, anchorY: 1, width: 2048, height: 50 })); taskbar.y = 2732; taskbar.tint = 0xc0c0c0; // Windows 98 gray taskbar // Create the start button var startButton = game.addChild(LK.getAsset('startButton', { anchorX: 0, anchorY: 1, width: 100, height: 40 })); startButton.x = 5; startButton.y = 2732 - 5; startButton.interactive = true; startButton.tint = 0xc0c0c0; // Windows 98 gray start button // Create the start menu var startMenu = game.addChild(new StartMenu()); // Add "Start" text to start button var startText = new Text2("Start", { size: 24, fill: 0x000000 //{g9} // Black text for Win98 start button }); startText.x = 35; startText.y = 2732 - 35; game.addChild(startText); // Create desktop icons var icons = [{ name: "My Computer", x: 100, y: 100 }, { name: "Recycle Bin", x: 100, y: 200 }, { name: "Notepad", x: 100, y: 300 }, { name: "Calculator", x: 100, y: 400 }, { name: "Explorer", x: 100, y: 500 }, { name: "Corrupted", x: 100, y: 600 }, { name: "CMD", x: 100, y: 700 }, { name: "Chrome", x: 100, y: 800 }]; icons.forEach(function (icon) { var desktopIcon = new DesktopIcon(icon.name, icon.x, icon.y); game.addChild(desktopIcon); }); // Create time display in taskbar var timeDisplay = new Text2(getCurrentTime(), { size: 24, fill: 0x000000 }); timeDisplay.anchor.set(1, 0.5); timeDisplay.x = 2048 - 10; timeDisplay.y = 2732 - 25; game.addChild(timeDisplay); // Create mouse cursor var mouseCursor = new MouseCursor(); game.addChild(mouseCursor); // Attach handlers desktop.interactive = true; desktop.down = function () { if (startMenuOpen) { toggleStartMenu(); } }; startButton.down = function () { startButton.alpha = 0.7; LK.getSound('click').play(); }; startButton.up = function () { startButton.alpha = 1; toggleStartMenu(); }; } // Play startup sound LK.setTimeout(function () { LK.getSound('startup').play(); }, 500); ;
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var DesktopIcon = Container.expand(function (iconName, x, y) {
var self = Container.call(this);
// Create icon background for selection effect
var iconBg = self.attachAsset('desktopIcon', {
anchorX: 0.5,
anchorY: 0.5,
width: 72,
height: 88
});
iconBg.alpha = 0; // Initially transparent
// Create the actual icon
var icon = self.attachAsset('desktopIcon', {
anchorX: 0.5,
anchorY: 0.5
});
// Set icon color based on type
if (iconName === "My Computer") {
icon.tint = 0x87CEEB; // Light blue
} else if (iconName === "Recycle Bin") {
icon.tint = 0x00FF00; // Green
} else if (iconName === "Notepad") {
icon.tint = 0xFFFFFF; // White
} else if (iconName === "Calculator") {
icon.tint = 0xDDDDDD; // Light gray
} else if (iconName === "Explorer") {
icon.tint = 0xFFD700; // Gold
} else if (iconName === "Corrupted") {
icon.tint = 0xFF0000;
} else if (iconName === "CMD") {
icon.tint = 0x000000; // Black for command prompt
} else if (iconName === "Chrome") {
// Use circular icon for Chrome
self.removeChild(icon);
icon = self.attachAsset('chromeIcon', {
anchorX: 0.5,
anchorY: 0.5
});
icon.tint = 0x4285F4; // Blue Chrome icon
}
var label = new Text2(iconName, {
size: 24,
fill: 0xFFFFFF
});
label.anchor.set(0.5, 0);
label.y = 40;
self.addChild(label);
self.x = x;
self.y = y;
self.name = iconName;
self.interactive = true;
self.isSelected = false;
self.down = function () {
// Show blue selection background
iconBg.alpha = 0.3;
iconBg.tint = 0x0000FF;
self.isSelected = true;
icon.alpha = 0.7;
LK.getSound('click').play();
};
self.up = function () {
icon.alpha = 1;
// Double-click effect (simplified)
if (self.isSelected) {
createWindow(iconName);
// Reset selection after opening window
LK.setTimeout(function () {
iconBg.alpha = 0;
self.isSelected = false;
}, 300);
}
};
return self;
});
var GlitchEffect = Container.expand(function () {
var self = Container.call(this);
// Particle properties
self.particles = [];
self.particleCount = 200;
self.colors = [0xff00ff, 0x00ffff, 0xffff00, 0xff0000, 0x00ff00, 0x0000ff];
self.active = false;
self.virusSongPlaying = false;
self.activationTime = 0;
self.sinkFactor = 0;
self.sinkDirection = 1;
// Create glitch particles
for (var i = 0; i < self.particleCount; i++) {
var particle = self.attachAsset('glitchParticle', {
anchorX: 0.5,
anchorY: 0.5
});
// Random starting position off-screen
particle.x = Math.random() * 2048;
particle.y = -50 - Math.random() * 200;
// Random size between 5 and 30
var size = 5 + Math.random() * 25;
particle.width = size;
particle.height = size;
// Random color from glitch palette
particle.tint = self.colors[Math.floor(Math.random() * self.colors.length)];
// Random alpha
particle.alpha = 0.5 + Math.random() * 0.5;
// Additional properties for movement
particle.speedX = Math.random() * 8 - 4;
particle.speedY = 2 + Math.random() * 6;
particle.rotation = Math.random() * Math.PI * 2;
particle.rotationSpeed = (Math.random() - 0.5) * 0.2;
// Hide initially
particle.visible = false;
self.particles.push(particle);
}
// Sink effect tracking properties
self.lastSinkPhaseTime = 0;
self.sinkPhase = 0; // 0 = not started, 1 = sinking, 2 = unsinking
// Create background glitch overlay
self.background = self.attachAsset('desktop', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
});
self.background.tint = 0xff00ff;
self.background.alpha = 0;
// Activate glitch effect
self.activate = function () {
if (self.active) {
return;
}
self.active = true;
self.activationTime = LK.ticks;
self.virusSongPlaying = false;
// Reset particles
for (var i = 0; i < self.particles.length; i++) {
var particle = self.particles[i];
particle.visible = true;
particle.x = Math.random() * 2048;
particle.y = -50 - Math.random() * 200;
}
// Stop any existing virus sounds before starting new ones
LK.getSound('virus').stop();
// Play virus sound in loop
LK.getSound('virus').play();
// Schedule next virus sound to create loop effect
self.soundLoop = LK.setInterval(function () {
LK.getSound('virus').play();
}, 1000);
// Start sinking effect
self.sinkFactor = 0;
self.sinkDirection = 1;
};
// Update glitch effect
self.update = function () {
if (!self.active) {
return;
}
// Update background color based on time
var time = LK.ticks / 10;
var r = Math.sin(time * 0.021) * 127 + 128;
var g = Math.sin(time * 0.022 + 2) * 127 + 128;
var b = Math.sin(time * 0.023 + 4) * 127 + 128;
var color = Math.floor(r) << 16 | Math.floor(g) << 8 | Math.floor(b);
self.background.tint = color;
self.background.alpha = 0.2 + Math.sin(time * 0.1) * 0.05;
// Check if 5 seconds have passed since activation to start virus song
if (!self.virusSongPlaying && self.active && (LK.ticks - self.activationTime) / 60 >= 5) {
self.virusSongPlaying = true;
// Stop the regular virus sound loop
LK.clearInterval(self.soundLoop);
// Create continuous glitchy jumbled noise
self.glitchySoundLoop = LK.setInterval(function () {
// Play virus sound at different rates and overlapping for glitchy effect
LK.getSound('virus').play();
LK.setTimeout(function () {
LK.getSound('virus').play();
}, 100);
LK.setTimeout(function () {
LK.getSound('virus').play();
}, 200);
}, 300);
}
// Calculate elapsed time in seconds since activation
var elapsedTimeSeconds = (LK.ticks - self.activationTime) / 60;
// Check if 25 seconds have passed to start rotation effect
if (elapsedTimeSeconds >= 25) {
// Apply rotation effect - gradually rotate the screen over time
var rotationSpeed = 0.001;
var rotationAngle = (elapsedTimeSeconds - 25) * rotationSpeed;
// Stop the glitchy sound loop if it's active
if (self.glitchySoundLoop) {
LK.clearInterval(self.glitchySoundLoop);
self.glitchySoundLoop = null;
// Also stop the playing virus sounds immediately
LK.getSound('virus').stop();
}
// Apply rotation to game
game.rotation = rotationAngle;
// Adjust position to keep content centered during rotation
var centerX = 2048 / 2;
var centerY = 2732 / 2;
game.x = centerX;
game.y = centerY;
// Check if 40 seconds have passed (15 seconds after rotation started) to show restart message
if (elapsedTimeSeconds >= 40) {
// Check if we haven't already switched to the SystemStart
var systemStartExists = false;
for (var i = 0; i < game.children.length; i++) {
if (game.children[i] instanceof SystemStart) {
systemStartExists = true;
break;
}
}
if (!systemStartExists) {
// Find and store the mouse cursor before cleaning up
var cursor = null;
for (var i = 0; i < game.children.length; i++) {
if (game.children[i] instanceof MouseCursor) {
cursor = game.children[i];
game.removeChild(cursor);
break;
}
}
// Remove all children from game
while (game.children.length > 0) {
var child = game.children[0];
game.removeChild(child);
}
// Reset game transform
game.rotation = 0;
game.x = 0;
game.y = 0;
game.scale.y = 1;
// Show SystemStart screen
var startScreen = new SystemStart();
game.addChild(startScreen);
// Restore the mouse cursor
if (cursor) {
game.addChild(cursor);
}
startScreen.startSequence();
}
}
return; // Skip other effects when in rotation mode
}
// Check if 20 seconds have passed to start sink effect (only until 25 seconds)
var timeSinceSinkStart = elapsedTimeSeconds - 20; // Time since the 20 second mark
// If we're past 20 seconds but before 25 seconds, handle sink/unsink cycles
if (elapsedTimeSeconds >= 20 && elapsedTimeSeconds < 25) {
// Determine which 5-second cycle we're in (0 = first sink, 1 = first unsink, etc.)
var sinkCycle = Math.floor(timeSinceSinkStart / 5);
// If even cycle (0, 2, 4...), we should be sinking, otherwise unsinking
if (sinkCycle % 2 === 0) {
// Sinking phase - calculate progress within 5-second window
var sinkProgress = timeSinceSinkStart % 5 / 5;
self.sinkFactor = sinkProgress;
} else {
// Unsinking phase - calculate progress within 5-second window
var unsinkProgress = timeSinceSinkStart % 5 / 5;
self.sinkFactor = 1 - unsinkProgress;
}
// Apply sink effect - stronger than the regular effect
game.scale.y = 1 - self.sinkFactor * 0.5;
game.y = 2732 * self.sinkFactor * 0.5 / 2;
} else {
// Regular subtle sink animation before 20 seconds
self.sinkFactor += 0.005 * self.sinkDirection;
if (self.sinkFactor > 1) {
self.sinkDirection = -1;
} else if (self.sinkFactor < 0) {
self.sinkDirection = 1;
}
// Apply subtle sink effect
game.scale.y = 1 - self.sinkFactor * 0.1;
game.y = 2732 * self.sinkFactor * 0.1 / 2;
}
// Update particles
for (var i = 0; i < self.particles.length; i++) {
var particle = self.particles[i];
// Move particle
particle.x += particle.speedX;
particle.y += particle.speedY;
// Rotate particle
particle.rotation += particle.rotationSpeed;
// If particle goes off screen, reset it
if (particle.y > 2732) {
particle.x = Math.random() * 2048;
particle.y = -20;
// Randomly change color
if (Math.random() < 0.3) {
particle.tint = self.colors[Math.floor(Math.random() * self.colors.length)];
}
// Randomly change alpha
particle.alpha = 0.5 + Math.random() * 0.5;
}
// If particle goes off sides, bounce or wrap
if (particle.x < 0 || particle.x > 2048) {
if (Math.random() < 0.5) {
particle.speedX *= -1; // Bounce
} else {
particle.x = particle.x < 0 ? 2048 : 0; // Wrap
}
}
}
};
return self;
});
var MouseCursor = Container.expand(function () {
var self = Container.call(this);
// Create arrow pointer shape
var cursorContainer = new Container();
self.addChild(cursorContainer);
// Create white arrow outline
var arrowBody = LK.getAsset('desktopIcon', {
anchorX: 0,
anchorY: 0,
width: 20,
height: 24
});
arrowBody.tint = 0xFFFFFF;
arrowBody.rotation = Math.PI / 6; // Slight tilt
cursorContainer.addChild(arrowBody);
// Create black inner arrow (slightly smaller)
var arrowInner = LK.getAsset('desktopIcon', {
anchorX: 0,
anchorY: 0,
width: 16,
height: 20
});
arrowInner.tint = 0x000000;
arrowInner.x = 2;
arrowInner.y = 2;
arrowInner.rotation = Math.PI / 6; // Same tilt
cursorContainer.addChild(arrowInner);
// Create left ear
var leftEar = LK.getAsset('desktopIcon', {
anchorX: 0.5,
anchorY: 1,
width: 8,
height: 12
});
leftEar.tint = 0x888888;
leftEar.x = 6;
leftEar.y = 0;
cursorContainer.addChild(leftEar);
// Create right ear
var rightEar = LK.getAsset('desktopIcon', {
anchorX: 0.5,
anchorY: 1,
width: 8,
height: 12
});
rightEar.tint = 0x888888;
rightEar.x = 14;
rightEar.y = 0;
cursorContainer.addChild(rightEar);
// Track if the cursor is over a clickable element
self.isOverClickable = false;
// Update cursor position
self.updatePosition = function (x, y) {
self.x = x;
self.y = y;
};
// Change cursor when over clickable elements
self.setPointer = function (isPointer) {
self.isOverClickable = isPointer;
if (isPointer) {
tween(cursorContainer, {
rotation: 0,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100
});
leftEar.tint = 0xCCCCCC;
rightEar.tint = 0xCCCCCC;
} else {
tween(cursorContainer, {
rotation: 0,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
leftEar.tint = 0x888888;
rightEar.tint = 0x888888;
}
};
return self;
});
var StartMenu = Container.expand(function () {
var self = Container.call(this);
var menu = self.attachAsset('startMenu', {
anchorX: 0,
anchorY: 1
});
var menuItems = ["Programs", "Documents", "Settings", "Find", "Help", "Run...", "Log Off...", "Shut Down..."];
for (var i = 0; i < menuItems.length; i++) {
var itemText = new Text2(menuItems[i], {
size: 24,
fill: 0x000000
});
itemText.x = 34;
itemText.y = 10 + i * 40;
self.addChild(itemText);
}
self.x = 0;
self.y = 2732; // Bottom of screen
self.visible = false;
return self;
});
var SystemCrashScreen = Container.expand(function () {
var self = Container.call(this);
// Create black background
var blackBg = self.attachAsset('desktop', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
});
blackBg.tint = 0x000000; // Keep black background
// Create error text
var errorText = new Text2("FATAL ERROR: System files removed\n\nUnable to locate C:\\WINDOWS\\SYSTEM32\n\nSystem restart failed.\n\nPress any key to continue...", {
size: 32,
fill: 0xFFFFFF // White text for better visibility on black background
});
errorText.anchor.set(0.5, 0.5);
errorText.x = 2048 / 2;
errorText.y = 2732 / 2;
self.addChild(errorText);
self.interactive = true;
// Make entire screen clickable
self.down = function () {
LK.getSound('error').play();
};
// Show restart button after 10 seconds
LK.setTimeout(function () {
// Change error text
errorText.setText("FATAL ERROR: System files removed\n\nUnable to locate C:\\WINDOWS\\SYSTEM32\n\nSystem restart failed.");
// Add restart button
var restartButton = new Container();
restartButton.interactive = true;
var buttonBg = LK.getAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5,
width: 220,
height: 60
});
buttonBg.tint = 0xFF0000;
var buttonText = new Text2("Remove everything and restart Windows 98", {
size: 18,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
restartButton.addChild(buttonBg);
restartButton.addChild(buttonText);
restartButton.x = 2048 / 2;
restartButton.y = 2732 / 2 + 200;
// Add click functionality to button
restartButton.down = function () {
buttonBg.tint = 0xAA0000;
LK.getSound('error').play();
};
restartButton.up = function () {
buttonBg.tint = 0xFF0000;
// Play multiple error sounds
for (var i = 0; i < 10; i++) {
LK.setTimeout(function () {
LK.getSound('error').play();
}, i * 100);
}
// Reset the OS (recreate the game)
LK.setTimeout(function () {
// Find and store the mouse cursor before clearing
var oldCursor = null;
for (var i = 0; i < game.children.length; i++) {
if (game.children[i] instanceof MouseCursor) {
oldCursor = game.children[i];
break;
}
}
if (oldCursor) {
game.removeChild(oldCursor);
}
// Clear everything else
while (game.children.length > 0) {
game.removeChild(game.children[0]);
}
// Add "Restarting..." text in a black background
var desktop = game.addChild(LK.getAsset('desktop', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
}));
desktop.tint = 0x000000;
var restartText = new Text2("Restarting Windows 98...", {
size: 40,
fill: 0xFFFFFF
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 2048 / 2;
restartText.y = 2732 / 2;
game.addChild(restartText);
// Restore the mouse cursor
if (oldCursor) {
game.addChild(oldCursor);
}
// Play startup sound
LK.setTimeout(function () {
LK.getSound('startup').play();
// Create and start the system startup sequence
LK.setTimeout(function () {
// Store cursor before clearing
var cursor = null;
for (var i = 0; i < game.children.length; i++) {
if (game.children[i] instanceof MouseCursor) {
cursor = game.children[i];
game.removeChild(cursor);
break;
}
}
// Remove restart text and black background
while (game.children.length > 0) {
game.removeChild(game.children[0]);
}
// Add SystemStart screen
var startScreen = new SystemStart();
game.addChild(startScreen);
// Restore cursor
if (cursor) {
game.addChild(cursor);
}
startScreen.startSequence();
}, 3000);
}, 2000);
}, 2000);
};
self.addChild(restartButton);
}, 10000);
return self;
});
var SystemStart = Container.expand(function () {
var self = Container.call(this);
// Black background
var blackBg = self.attachAsset('desktop', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
});
blackBg.tint = 0xFFFFFF; // Set white background instead of black
// Starting Windows 98 setup text
var startingText = new Text2("Windows 98 Setup", {
size: 40,
fill: 0x000000 // Change text color to black for better visibility on white background
});
startingText.anchor.set(0.5, 0.5);
startingText.x = 2048 / 2;
startingText.y = 2732 / 2;
self.addChild(startingText);
// Progress to different stages
self.startSequence = function () {
// Stop the virus sound if it's playing
LK.getSound('virus').stop();
// Add download button immediately
var downloadButton = LK.getAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 50
});
downloadButton.tint = 0x4CAF50; // Green color
downloadButton.x = 2048 / 2;
downloadButton.y = 2732 / 2 + 200;
downloadButton.interactive = true;
self.addChild(downloadButton);
var downloadText = new Text2("DOWNLOAD NOW", {
size: 24,
fill: 0xFFFFFF
});
downloadText.anchor.set(0.5, 0.5);
downloadText.x = 2048 / 2;
downloadText.y = 2732 / 2 + 200;
self.addChild(downloadText);
// Add download button interactivity
downloadButton.down = function () {
this.tint = 0x388E3C; // Darker green when pressed
this.y += 2; // Small push effect
LK.getSound('click').play();
};
downloadButton.up = function () {
this.tint = 0x4CAF50; // Back to normal green
this.y -= 2; // Reset push effect
};
// After 10 seconds, show setup stages
LK.setTimeout(function () {
startingText.setText("Windows XP Setup - Preparing Installation");
// Add setup message
var setupMessage = new Text2("Collecting information about your computer...", {
size: 24,
fill: 0x000000
});
setupMessage.anchor.set(0.5, 0.5);
setupMessage.x = 2048 / 2;
setupMessage.y = 2732 / 2 + 100;
self.addChild(setupMessage);
// After 5 more seconds, show next setup stage
LK.setTimeout(function () {
startingText.setText("Windows 98 Setup - Installing Windows");
setupMessage.setText("Copying files... (45%)");
// After 5 more seconds, show final setup stage
LK.setTimeout(function () {
startingText.setText("Windows 98 Setup - Completing Installation");
setupMessage.setText("Setting up your computer for first use...");
// Add setup progress bar
var progressBarBg = LK.getAsset('desktopIcon', {
anchorX: 0,
anchorY: 0.5,
width: 400,
height: 20
});
progressBarBg.tint = 0xCCCCCC;
progressBarBg.x = 2048 / 2 - 200;
progressBarBg.y = 2732 / 2 + 150;
self.addChild(progressBarBg);
var progressBar = LK.getAsset('desktopIcon', {
anchorX: 0,
anchorY: 0.5,
width: 380,
height: 16
});
progressBar.tint = 0x0000AA;
progressBar.x = 2048 / 2 - 190;
progressBar.y = 2732 / 2 + 150;
self.addChild(progressBar);
// Animate progress bar
tween(progressBar, {
width: 0
}, {
duration: 4000,
onFinish: function onFinish() {
// Store the current mouse cursor before removing it
var oldCursor = null;
for (var i = 0; i < game.children.length; i++) {
if (game.children[i] instanceof MouseCursor) {
oldCursor = game.children[i];
game.removeChild(oldCursor);
break;
}
}
// Remove SystemStart screen
game.removeChild(self);
// Recreate desktop
initializeDesktop();
// Restore the original mouse cursor if it exists
if (oldCursor) {
game.addChild(oldCursor);
}
}
});
}, 5000);
}, 5000);
}, 10000);
};
return self;
});
var Window = Container.expand(function (title, width, height) {
var self = Container.call(this);
self.isActive = true;
self.width = width || 800;
self.height = height || 600;
// Create a white background for the window
var windowBg = self.attachAsset('window', {
anchorX: 0,
anchorY: 0,
width: self.width,
height: self.height
});
windowBg.tint = 0xFFFFFF; // Set white background
var titleBar = self.attachAsset('windowTitle', {
anchorX: 0,
anchorY: 0,
width: self.width,
height: 28
});
var titleText = new Text2(title, {
size: 20,
fill: 0xFFFFFF
});
titleText.x = 10;
titleText.y = 4;
self.addChild(titleText);
var closeButton = self.attachAsset('closeButton', {
anchorX: 0,
anchorY: 0
});
closeButton.x = self.width - 28;
closeButton.y = 2;
closeButton.interactive = true;
var minimizeButton = self.attachAsset('minimizeButton', {
anchorX: 0,
anchorY: 0
});
minimizeButton.x = self.width - 56;
minimizeButton.y = 2;
minimizeButton.interactive = true;
var content = self.attachAsset('programContent', {
anchorX: 0,
anchorY: 0,
width: self.width - 20,
height: self.height - 50
});
content.tint = 0xFFFFFF; // Set white background
content.x = 10;
content.y = 40;
// Program specific content
self.contentArea = new Container();
self.contentArea.x = 10;
self.contentArea.y = 40;
self.addChild(self.contentArea);
self.isDragging = false;
self.dragOffsetX = 0;
self.dragOffsetY = 0;
titleBar.interactive = true;
titleBar.down = function (x, y) {
self.isDragging = true;
self.dragOffsetX = x;
self.dragOffsetY = y;
// Bring window to front
if (self.parent) {
var index = self.parent.children.indexOf(self);
if (index >= 0) {
// Remove from current position
self.parent.children.splice(index, 1);
// Add to end (top)
self.parent.children.push(self);
}
}
};
titleBar.up = function () {
self.isDragging = false;
};
closeButton.down = function () {
closeButton.alpha = 0.7;
LK.getSound('click').play();
};
closeButton.up = function () {
closeWindow(self);
};
minimizeButton.down = function () {
minimizeButton.alpha = 0.7;
LK.getSound('click').play();
};
minimizeButton.up = function () {
minimizeButton.alpha = 1;
minimizeWindow(self);
};
return self;
});
var NotepadWindow = Window.expand(function () {
var self = Window.call(this, "Notepad", 700, 500);
var textArea = new Text2("Start typing here...", {
size: 24,
fill: 0x000000
});
textArea.x = 10;
textArea.y = 10;
self.contentArea.addChild(textArea);
return self;
});
var GameWindow = Window.expand(function () {
var self = Window.call(this, "Game", 800, 600);
// Game area background
var gameArea = LK.getAsset('programContent', {
anchorX: 0,
anchorY: 0,
width: self.width - 20,
height: self.height - 50
});
gameArea.tint = 0xFFFFFF; // Set white background instead of black
self.contentArea.addChild(gameArea);
// Create game title
var gameTitle = new Text2("DRAG ME!", {
size: 48,
fill: 0x000000 // Change text color to black for better visibility on white background
});
gameTitle.anchor.set(0.5, 0.5);
gameTitle.x = (self.width - 20) / 2;
gameTitle.y = 80;
self.contentArea.addChild(gameTitle);
// Create draggable ball
var gameBall = new Container();
gameBall.x = (self.width - 20) / 2;
gameBall.y = (self.height - 50) / 2 + 50;
gameBall.interactive = true;
self.contentArea.addChild(gameBall);
// Ball background
var ballBg = LK.getAsset('desktopIcon', {
anchorX: 0.5,
anchorY: 0.5,
width: 150,
height: 150
});
ballBg.tint = 0x4285F4; // Blue color
gameBall.addChild(ballBg);
// Ball letters
var ballText = "GAME!";
var colors = [0x4285F4, 0xEA4335, 0xFBBC05, 0x4285F4, 0x34A853, 0xEA4335]; // Blue, Red, Yellow, Blue, Green, Red
var ballLetters = [];
for (var i = 0; i < ballText.length; i++) {
var letter = new Text2(ballText[i], {
size: 36,
fill: colors[i % colors.length]
});
letter.anchor.set(0.5, 0.5);
// Position in a circle
var angle = i / ballText.length * Math.PI * 2;
var radius = 60;
letter.x = Math.cos(angle) * radius;
letter.y = Math.sin(angle) * radius;
letter.rotation = angle + Math.PI / 2;
letter.initialX = letter.x;
letter.initialY = letter.y;
letter.initialRotation = letter.rotation;
gameBall.addChild(letter);
ballLetters.push(letter);
}
// Add instruction text
var instructionText = new Text2("Works on all devices!", {
size: 18,
fill: 0x000000 // Change text color to black for better visibility on white background
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = (self.width - 20) / 2;
instructionText.y = (self.height - 50) / 2 + 150;
self.contentArea.addChild(instructionText);
// Track ball state
var ballActive = false;
var lastX = 0;
var lastY = 0;
// Make ball interactive
gameBall.down = function (x, y, obj) {
ballActive = true;
var localPos = gameBall.toLocal({
x: x,
y: y
});
lastX = localPos.x;
lastY = localPos.y;
// Scale effect on press
tween(gameBall, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
// Update instruction text
instructionText.setText("Dragging...");
LK.getSound('click').play();
};
gameBall.move = function (x, y, obj) {
if (ballActive) {
var localPos = gameBall.toLocal({
x: x,
y: y
});
var dx = localPos.x - lastX;
var dy = localPos.y - lastY;
// Move the ball letters based on the drag
for (var i = 0; i < ballLetters.length; i++) {
var letter = ballLetters[i];
// Calculate new position based on drag direction and speed
var angle = Math.atan2(dy, dx);
var speed = Math.sqrt(dx * dx + dy * dy) * 0.1;
// Rotate the letters in the direction of the drag
letter.rotation = letter.initialRotation + angle;
// Move slightly in drag direction
letter.x = letter.initialX + Math.cos(angle) * speed * 2;
letter.y = letter.initialY + Math.sin(angle) * speed * 2;
}
lastX = localPos.x;
lastY = localPos.y;
}
};
gameBall.up = function (x, y, obj) {
ballActive = false;
// Reset instruction text
instructionText.setText("Works on all devices!");
// Return to original size
tween(gameBall, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
// Return letters to original positions
for (var i = 0; i < ballLetters.length; i++) {
var letter = ballLetters[i];
tween(letter, {
x: letter.initialX,
y: letter.initialY,
rotation: letter.initialRotation
}, {
duration: 500,
easing: tween.easeElastic
});
}
};
// Animate the ball constantly to show it's interactive
LK.setInterval(function () {
if (!ballActive) {
// Gentle rotation animation
var time = LK.ticks / 60;
for (var i = 0; i < ballLetters.length; i++) {
var letter = ballLetters[i];
letter.x = letter.initialX + Math.sin(time + i * 0.5) * 5;
letter.y = letter.initialY + Math.cos(time + i * 0.5) * 5;
letter.rotation = letter.initialRotation + Math.sin(time * 0.2 + i) * 0.1;
}
}
}, 16); // ~60fps animation
return self;
});
var ExplorerWindow = Window.expand(function () {
var self = Window.call(this, "File Explorer", 800, 600);
var folderStructure = ["My Documents", "My Computer", "Network Neighborhood", "Recycle Bin"];
for (var i = 0; i < folderStructure.length; i++) {
// Create a container for each folder item to handle interactions
var folderItem = new Container();
folderItem.interactive = true;
folderItem.x = 10;
folderItem.y = i * 60 + 10;
var folderIcon = LK.getAsset('desktopIcon', {
anchorX: 0,
anchorY: 0,
width: 48,
height: 48
});
folderIcon.tint = 0xFFFF00;
folderIcon.x = 0;
folderIcon.y = 0;
var folderName = new Text2(folderStructure[i], {
size: 20,
fill: 0x000000
});
folderName.x = 60;
folderName.y = 14;
folderItem.addChild(folderIcon);
folderItem.addChild(folderName);
// Add click functionality
folderItem.name = folderStructure[i];
folderItem.lastSelected = false;
folderItem.down = function () {
this.children[0].tint = 0xCCCC00; // Darker yellow when clicked
LK.getSound('click').play();
};
folderItem.up = function () {
this.children[0].tint = 0xFFFF00; // Back to normal yellow
// Open a new Explorer window or perform folder-specific action
if (this.name === "My Computer") {
createWindow("Explorer");
} else if (this.name === "Recycle Bin") {
var emptyBinWindow = new Window("Empty Recycle Bin?", 400, 200);
emptyBinWindow.x = (2048 - 400) / 2;
emptyBinWindow.y = (2732 - 200) / 2;
game.addChild(emptyBinWindow);
activeWindows.push(emptyBinWindow);
}
};
self.contentArea.addChild(folderItem);
}
return self;
});
// Red for corrupted app
var CorruptedWindow = Window.expand(function () {
var self = Window.call(this, "Error", 500, 300);
var errorMessage = new Text2("A fatal exception has occurred.\nThe current application will be terminated.\n\nPress OK to close this window.", {
size: 24,
fill: 0x000000
});
errorMessage.x = 20;
errorMessage.y = 30;
self.contentArea.addChild(errorMessage);
var okButton = new Container();
okButton.interactive = true;
okButton.x = 200;
okButton.y = 180;
var buttonGraphic = LK.getAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5,
width: 100,
height: 40
});
buttonGraphic.tint = 0xDDDDDD;
var buttonText = new Text2("OK", {
size: 24,
fill: 0x000000
});
buttonText.anchor.set(0.5, 0.5);
buttonText.x = 0;
buttonText.y = 0;
okButton.addChild(buttonGraphic);
okButton.addChild(buttonText);
okButton.down = function () {
buttonGraphic.tint = 0xAAAAAA;
LK.getSound('click').play();
};
okButton.up = function () {
buttonGraphic.tint = 0xDDDDDD;
closeWindow(self);
};
self.contentArea.addChild(okButton);
return self;
});
var CommandPromptWindow = Window.expand(function () {
var self = Window.call(this, "Command Prompt", 700, 500);
// Black background for command prompt
var cmdBackground = LK.getAsset('desktopIcon', {
anchorX: 0,
anchorY: 0,
width: self.width - 20,
height: self.height - 50
});
cmdBackground.tint = 0xFFFFFF; // Set white background instead of black
cmdBackground.x = 0;
cmdBackground.y = 0;
self.contentArea.addChild(cmdBackground);
// Initial command prompt text
var promptText = new Text2("C:\\WINDOWS>_", {
size: 24,
fill: 0x000000 // Change text color to black for better visibility on white background
});
promptText.x = 10;
promptText.y = 10;
self.contentArea.addChild(promptText);
// Instructions text
var instructionsText = new Text2("Click anywhere to type...", {
size: 20,
fill: 0x555555 // Darker gray for better visibility on white background
});
instructionsText.x = 10;
instructionsText.y = 50;
self.contentArea.addChild(instructionsText);
// Make entire content area interactive
cmdBackground.interactive = true;
// Flag to track if deleting system32 message is shown
self.isDeleting = false;
// Function to show error messages
self.showErrors = function () {
if (self.isDeleting) {
return;
} // Prevent multiple calls
self.isDeleting = true;
// Change text to show deleting system32
promptText.setText("C:\\WINDOWS>DEL C:\\WINDOWS\\SYSTEM32\\*.* /F /S /Q\n\nDELETING SYSTEM FILES...\nTHIS ACTION CANNOT BE UNDONE!");
promptText.tint = 0xFF0000;
instructionsText.visible = false;
// Play multiple error sounds with slight delay between them
LK.getSound('error').play();
// Create continuous error flood
var errorInterval = LK.setInterval(function () {
LK.getSound('error').play();
var errorWindow = new CorruptedWindow();
errorWindow.x = Math.random() * (2048 - 500);
errorWindow.y = Math.random() * (2732 - 400);
game.addChild(errorWindow);
activeWindows.push(errorWindow);
}, 1); // Create a new error every millisecond
// Initial burst of errors
LK.setTimeout(function () {
for (var i = 0; i < 20; i++) {
LK.setTimeout(function () {
LK.getSound('error').play();
var errorWindow = new CorruptedWindow();
errorWindow.x = Math.random() * (2048 - 500);
errorWindow.y = Math.random() * (2732 - 400);
game.addChild(errorWindow);
activeWindows.push(errorWindow);
}, i * 50);
}
}, 100);
// After 10 seconds, trigger system crash and restart
LK.setTimeout(function () {
// Change prompt text to show restart
promptText.setText("C:\\WINDOWS>DEL C:\\WINDOWS\\SYSTEM32\\*.* /F /S /Q\n\nDELETING SYSTEM FILES... COMPLETE\n\nFATAL ERROR: Critical system files missing\n\nRESTARTING WINDOWS 98...");
// Clear all error windows
LK.clearInterval(errorInterval);
for (var i = activeWindows.length - 1; i >= 0; i--) {
game.removeChild(activeWindows[i]);
}
activeWindows = [];
// Play multiple error sounds
for (var i = 0; i < 5; i++) {
LK.setTimeout(function () {
LK.getSound('error').play();
}, i * 200);
}
// Wait 2 more seconds then show crash screen
LK.setTimeout(function () {
// Find and store the mouse cursor before cleaning up
var cursor = null;
for (var i = 0; i < game.children.length; i++) {
if (game.children[i] instanceof MouseCursor) {
cursor = game.children[i];
game.removeChild(cursor);
break;
}
}
// Remove all children from game
while (game.children.length > 0) {
var child = game.children[0];
game.removeChild(child);
}
// Show crash screen
var crashScreen = new SystemCrashScreen();
game.addChild(crashScreen);
// Restore the mouse cursor
if (cursor) {
game.addChild(cursor);
}
}, 2000);
}, 10000);
};
// Click handler
cmdBackground.down = function () {
LK.getSound('error').play();
self.showErrors();
// Add more immediate errors on click
for (var i = 0; i < 10; i++) {
LK.setTimeout(function () {
LK.getSound('error').play();
var errorWindow = new CorruptedWindow();
errorWindow.x = Math.random() * (2048 - 500);
errorWindow.y = Math.random() * (2732 - 400);
game.addChild(errorWindow);
activeWindows.push(errorWindow);
}, i * 10); // Very small delay between each error
}
};
return self;
});
var ChromeWindow = Window.expand(function () {
var self = Window.call(this, "Google Chrome", 900, 650);
// Create toolbar
var toolbar = self.attachAsset('desktopIcon', {
anchorX: 0,
anchorY: 0,
width: self.width - 20,
height: 40
});
toolbar.tint = 0xF0F0F0;
toolbar.x = 0;
toolbar.y = 0;
self.contentArea.addChild(toolbar);
// Create address bar
var addressBar = LK.getAsset('desktopIcon', {
anchorX: 0,
anchorY: 0,
width: self.width - 100,
height: 30
});
addressBar.tint = 0xFFFFFF;
addressBar.x = 80;
addressBar.y = 5;
toolbar.addChild(addressBar);
// URL text
var urlText = new Text2("https://www.google.com", {
size: 18,
fill: 0x000000
});
urlText.x = 10;
urlText.y = 5;
addressBar.addChild(urlText);
// Navigation buttons
var backButton = LK.getAsset('desktopIcon', {
anchorX: 0.5,
anchorY: 0.5,
width: 24,
height: 24
});
backButton.tint = 0x777777;
backButton.x = 25;
backButton.y = 20;
toolbar.addChild(backButton);
var forwardButton = LK.getAsset('desktopIcon', {
anchorX: 0.5,
anchorY: 0.5,
width: 24,
height: 24
});
forwardButton.tint = 0x777777;
forwardButton.x = 55;
forwardButton.y = 20;
toolbar.addChild(forwardButton);
// Create page content area
var pageContent = LK.getAsset('programContent', {
anchorX: 0,
anchorY: 0,
width: self.width - 20,
height: self.height - 90
});
pageContent.tint = 0xFFFFFF; // Ensure white background
pageContent.x = 0;
pageContent.y = 45;
self.contentArea.addChild(pageContent);
// Google logo
var googleLogo = new Container();
googleLogo.x = (self.width - 20) / 2;
googleLogo.y = 120;
pageContent.addChild(googleLogo);
// Create Google interactive text ball
var textBall = new Container();
textBall.x = (self.width - 20) / 2;
textBall.y = 320;
textBall.interactive = true;
pageContent.addChild(textBall);
// Create Google logo parts (G, o, o, g, l, e)
var colors = [0x4285F4, 0xEA4335, 0xFBBC05, 0x4285F4, 0x34A853, 0xEA4335]; // Blue, Red, Yellow, Blue, Green, Red
var letters = ["G", "o", "o", "g", "l", "e"];
// Track text ball state
var ballActive = false;
var lastX = 0;
var lastY = 0;
var ballLetters = [];
for (var i = 0; i < letters.length; i++) {
var letter = new Text2(letters[i], {
size: 48,
fill: colors[i]
});
letter.anchor.set(0.5, 0.5);
letter.x = i * 30 - 75;
letter.y = 0;
googleLogo.addChild(letter);
// Create copies for the ball
var ballLetter = new Text2(letters[i], {
size: 36,
fill: colors[i]
});
ballLetter.anchor.set(0.5, 0.5);
// Position in a circle
var angle = i / letters.length * Math.PI * 2;
var radius = 60;
ballLetter.x = Math.cos(angle) * radius;
ballLetter.y = Math.sin(angle) * radius;
ballLetter.rotation = angle + Math.PI / 2;
ballLetter.initialX = ballLetter.x;
ballLetter.initialY = ballLetter.y;
ballLetter.initialRotation = ballLetter.rotation;
textBall.addChild(ballLetter);
ballLetters.push(ballLetter);
}
// Ball background
var ballBg = LK.getAsset('desktopIcon', {
anchorX: 0.5,
anchorY: 0.5,
width: 150,
height: 150
});
ballBg.tint = 0xF8F8F8;
ballBg.alpha = 0.7;
textBall.addChildAt(ballBg, 0);
// Create search bar
var searchBar = LK.getAsset('desktopIcon', {
anchorX: 0.5,
anchorY: 0.5,
width: 450,
height: 40
});
searchBar.tint = 0xFFFFFF;
searchBar.x = (self.width - 20) / 2;
searchBar.y = 200;
pageContent.addChild(searchBar);
// Add "Interactive" text below ball
var interactiveText = new Text2("Drag me! Works on all devices", {
size: 18,
fill: 0x555555
});
interactiveText.anchor.set(0.5, 0.5);
interactiveText.x = 0;
interactiveText.y = 90;
textBall.addChild(interactiveText);
// Magnifying glass icon
var searchIcon = LK.getAsset('desktopIcon', {
anchorX: 0.5,
anchorY: 0.5,
width: 20,
height: 20
});
searchIcon.tint = 0x777777;
searchIcon.x = -200;
searchIcon.y = 0;
searchBar.addChild(searchIcon);
// Search buttons
var searchButton = LK.getAsset('desktopIcon', {
anchorX: 0.5,
anchorY: 0.5,
width: 120,
height: 36
});
searchButton.tint = 0xF0F0F0;
searchButton.x = (self.width - 20) / 2 - 70;
searchButton.y = 260;
pageContent.addChild(searchButton);
var searchButtonText = new Text2("Google Search", {
size: 16,
fill: 0x555555
});
searchButtonText.anchor.set(0.5, 0.5);
searchButtonText.x = 0;
searchButtonText.y = 0;
searchButton.addChild(searchButtonText);
var luckyButton = LK.getAsset('desktopIcon', {
anchorX: 0.5,
anchorY: 0.5,
width: 150,
height: 36
});
luckyButton.tint = 0xF0F0F0;
luckyButton.x = (self.width - 20) / 2 + 90;
luckyButton.y = 260;
pageContent.addChild(luckyButton);
var luckyButtonText = new Text2("I'm Feeling Lucky", {
size: 16,
fill: 0x555555
});
luckyButtonText.anchor.set(0.5, 0.5);
luckyButtonText.x = 0;
luckyButtonText.y = 0;
luckyButton.addChild(luckyButtonText);
// Add Free Download Button
var downloadButton = LK.getAsset('desktopIcon', {
anchorX: 0.5,
anchorY: 0.5,
width: 180,
height: 50
});
downloadButton.tint = 0x4CAF50; // Green color
downloadButton.x = (self.width - 20) / 2;
downloadButton.y = 330;
downloadButton.interactive = true;
pageContent.addChild(downloadButton);
var downloadText = new Text2("FREE DOWNLOAD", {
size: 20,
fill: 0xFFFFFF
});
downloadText.anchor.set(0.5, 0.5);
downloadText.x = 0;
downloadText.y = 0;
downloadButton.addChild(downloadText);
// Add download button interactivity
downloadButton.down = function () {
this.tint = 0x388E3C; // Darker green when pressed
this.y += 2; // Small push effect
LK.getSound('click').play();
};
downloadButton.up = function () {
this.tint = 0x4CAF50; // Back to normal green
this.y -= 2; // Reset push effect
// Show some feedback when clicked
var feedbackText = new Text2("Download Started!", {
size: 16,
fill: 0xff0000
});
feedbackText.anchor.set(0.5, 0.5);
feedbackText.x = (self.width - 20) / 2;
feedbackText.y = 390;
pageContent.addChild(feedbackText);
// Create virus glitch effect if not already exists
var glitchEffect = null;
for (var i = 0; i < game.children.length; i++) {
if (game.children[i] instanceof GlitchEffect) {
glitchEffect = game.children[i];
break;
}
}
if (!glitchEffect) {
glitchEffect = new GlitchEffect();
game.addChild(glitchEffect);
}
// Activate glitch effect
glitchEffect.activate();
// Change desktop background to glitch color
var desktop = null;
for (var i = 0; i < game.children.length; i++) {
if (game.children[i].width === 2048 && game.children[i].height === 2732 && game.children[i] !== glitchEffect) {
desktop = game.children[i];
break;
}
}
if (desktop) {
desktop.tint = 0xff00ff; // Set background to glitch color
}
// Remove feedback after 2 seconds
LK.setTimeout(function () {
pageContent.removeChild(feedbackText);
}, 2000);
};
// Make text ball interactive
textBall.down = function (x, y, obj) {
ballActive = true;
var localPos = textBall.toLocal({
x: x,
y: y
});
lastX = localPos.x;
lastY = localPos.y;
// Scale effect on press
tween(textBall, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
// Update ball text to show it's being pressed
interactiveText.setText("Dragging...");
LK.getSound('click').play();
};
textBall.move = function (x, y, obj) {
if (ballActive) {
var localPos = textBall.toLocal({
x: x,
y: y
});
var dx = localPos.x - lastX;
var dy = localPos.y - lastY;
// Move the ball letters based on the drag
for (var i = 0; i < ballLetters.length; i++) {
var letter = ballLetters[i];
// Calculate new position based on drag direction and speed
var angle = Math.atan2(dy, dx);
var speed = Math.sqrt(dx * dx + dy * dy) * 0.1;
// Rotate the letters in the direction of the drag
letter.rotation = letter.initialRotation + angle;
// Move slightly in drag direction
letter.x = letter.initialX + Math.cos(angle) * speed * 2;
letter.y = letter.initialY + Math.sin(angle) * speed * 2;
}
lastX = localPos.x;
lastY = localPos.y;
}
};
textBall.up = function (x, y, obj) {
ballActive = false;
// Reset ball text
interactiveText.setText("Drag me! Works on all devices");
// Return to original size
tween(textBall, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
// Return letters to original positions
for (var i = 0; i < ballLetters.length; i++) {
var letter = ballLetters[i];
tween(letter, {
x: letter.initialX,
y: letter.initialY,
rotation: letter.initialRotation
}, {
duration: 500,
easing: tween.easeElastic
});
}
};
// Animate the text ball constantly to show it's interactive
LK.setInterval(function () {
if (!ballActive) {
// Gentle rotation animation
var time = LK.ticks / 60;
for (var i = 0; i < ballLetters.length; i++) {
var letter = ballLetters[i];
letter.x = letter.initialX + Math.sin(time + i * 0.5) * 5;
letter.y = letter.initialY + Math.cos(time + i * 0.5) * 5;
letter.rotation = letter.initialRotation + Math.sin(time * 0.2 + i) * 0.1;
}
}
}, 16); // ~60fps animation
// Make buttons interactive
searchButton.interactive = true;
searchButton.down = function () {
this.tint = 0xE0E0E0;
LK.getSound('click').play();
};
searchButton.up = function () {
this.tint = 0xF0F0F0;
};
luckyButton.interactive = true;
luckyButton.down = function () {
this.tint = 0xE0E0E0;
LK.getSound('click').play();
};
luckyButton.up = function () {
this.tint = 0xF0F0F0;
};
addressBar.interactive = true;
addressBar.down = function () {
urlText.tint = 0x4285F4;
LK.getSound('click').play();
};
return self;
});
var CalculatorWindow = Window.expand(function () {
var self = Window.call(this, "Calculator", 300, 400);
var currentValue = "0";
var previousValue = "";
var operation = "";
var resetDisplay = false;
var display = new Text2("0", {
size: 36,
fill: 0x000000
});
display.x = 10;
display.y = 10;
self.contentArea.addChild(display);
function updateDisplay() {
display.setText(currentValue);
}
function calculate() {
var prev = parseFloat(previousValue);
var current = parseFloat(currentValue);
var result = 0;
switch (operation) {
case "+":
result = prev + current;
break;
case "-":
result = prev - current;
break;
case "*":
result = prev * current;
break;
case "/":
result = prev / current;
break;
}
return result.toString();
}
function handleButtonClick(label) {
LK.getSound('click').play();
if (label >= "0" && label <= "9") {
if (currentValue === "0" || resetDisplay) {
currentValue = label;
resetDisplay = false;
} else {
currentValue += label;
}
updateDisplay();
} else if (label === ".") {
if (!currentValue.includes(".")) {
currentValue += ".";
updateDisplay();
}
} else if (["+", "-", "*", "/"].includes(label)) {
previousValue = currentValue;
operation = label;
resetDisplay = true;
} else if (label === "=") {
if (previousValue && operation) {
currentValue = calculate();
previousValue = "";
operation = "";
resetDisplay = true;
updateDisplay();
}
}
}
var buttonLabels = ["7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "0", ".", "=", "+"];
var buttonSize = 60;
var padding = 5;
var buttonsPerRow = 4;
for (var i = 0; i < buttonLabels.length; i++) {
var buttonX = i % buttonsPerRow * (buttonSize + padding) + 10;
var buttonY = Math.floor(i / buttonsPerRow) * (buttonSize + padding) + 60;
var buttonBg = new Container();
buttonBg.interactive = true;
buttonBg.x = buttonX;
buttonBg.y = buttonY;
var buttonGraphic = LK.getAsset('desktopIcon', {
anchorX: 0,
anchorY: 0,
width: buttonSize,
height: buttonSize
});
buttonGraphic.tint = 0xDDDDDD;
var buttonText = new Text2(buttonLabels[i], {
size: 30,
fill: 0x000000
});
buttonText.anchor.set(0.5, 0.5);
buttonText.x = buttonSize / 2;
buttonText.y = buttonSize / 2;
// Store the button label for the event handlers
buttonBg.name = buttonLabels[i];
// Add click handling
buttonBg.down = function () {
this.children[0].tint = 0xAAAAAA; // Darken on press
};
buttonBg.up = function () {
this.children[0].tint = 0xDDDDDD; // Restore color
handleButtonClick(this.name);
};
buttonBg.addChild(buttonGraphic);
buttonBg.addChild(buttonText);
self.contentArea.addChild(buttonBg);
}
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x008080 // Windows 98 teal background
});
/****
* Game Code
****/
// Global variables
// Windows XP blue
var activeWindows = [];
var startMenuOpen = false;
var dragTarget = null;
var savedWindowPositions = {};
// Create the desktop background
var desktop = game.addChild(LK.getAsset('desktop', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
}));
desktop.tint = 0x008080; // Windows 98 teal
// Create the taskbar
var taskbar = game.addChild(LK.getAsset('taskbar', {
anchorX: 0,
anchorY: 1,
width: 2048,
height: 50
}));
taskbar.y = 2732;
taskbar.tint = 0xc0c0c0; // Windows 98 gray taskbar
// Create the start button
var startButton = game.addChild(LK.getAsset('startButton', {
anchorX: 0,
anchorY: 1,
width: 100,
height: 40
}));
startButton.x = 5;
startButton.y = 2732 - 5;
startButton.interactive = true;
startButton.tint = 0xc0c0c0; // Windows 98 gray start button
// Create the start menu
var startMenu = game.addChild(new StartMenu());
// Add "Start" text to start button
var startText = new Text2("Start", {
size: 24,
fill: 0x000000 //{dy} // Black text for Win98 start button
});
startText.x = 35;
startText.y = 2732 - 35;
game.addChild(startText);
// Create desktop icons
var icons = [{
name: "My Computer",
x: 100,
y: 100
}, {
name: "Recycle Bin",
x: 100,
y: 200
}, {
name: "Notepad",
x: 100,
y: 300
}, {
name: "Calculator",
x: 100,
y: 400
}, {
name: "Explorer",
x: 100,
y: 500
}, {
name: "Corrupted",
x: 100,
y: 600
}, {
name: "CMD",
x: 100,
y: 700
}, {
name: "Chrome",
x: 100,
y: 800
}];
icons.forEach(function (icon) {
var desktopIcon = new DesktopIcon(icon.name, icon.x, icon.y);
game.addChild(desktopIcon);
});
// Create time display in taskbar
var timeDisplay = new Text2(getCurrentTime(), {
size: 24,
fill: 0x000000
});
timeDisplay.anchor.set(1, 0.5);
timeDisplay.x = 2048 - 10;
timeDisplay.y = 2732 - 25;
game.addChild(timeDisplay);
// Handle desktop clicks
desktop.interactive = true;
desktop.down = function () {
if (startMenuOpen) {
toggleStartMenu();
}
};
// Start button handling
startButton.down = function () {
startButton.alpha = 0.7;
LK.getSound('click').play();
};
startButton.up = function () {
startButton.alpha = 1;
toggleStartMenu();
};
// Game update function
game.update = function () {
// Update time display every second
if (LK.ticks % 60 === 0) {
timeDisplay.setText(getCurrentTime());
}
// Handle window dragging
if (dragTarget && dragTarget.isDragging) {
dragTarget.x = lastMoveX - dragTarget.dragOffsetX;
dragTarget.y = lastMoveY - dragTarget.dragOffsetY;
// Keep windows within screen bounds
dragTarget.x = Math.max(0, Math.min(2048 - dragTarget.width, dragTarget.x));
dragTarget.y = Math.max(0, Math.min(2732 - 50 - dragTarget.height, dragTarget.y));
}
// Update glitch effect if active
for (var i = 0; i < game.children.length; i++) {
if (game.children[i] instanceof GlitchEffect) {
game.children[i].update();
break;
}
}
};
// Track mouse/touch position
var lastMoveX = 0;
var lastMoveY = 0;
game.move = function (x, y) {
lastMoveX = x;
lastMoveY = y;
};
// Handle global mouse up
game.up = function () {
if (dragTarget) {
dragTarget.isDragging = false;
dragTarget = null;
}
};
// Helper functions
function toggleStartMenu() {
startMenuOpen = !startMenuOpen;
startMenu.visible = startMenuOpen;
if (startMenuOpen) {
LK.getSound('click').play();
}
}
function createWindow(type) {
var newWindow;
switch (type) {
case "Notepad":
newWindow = new NotepadWindow();
break;
case "Calculator":
newWindow = new CalculatorWindow();
break;
case "Explorer":
case "My Computer":
newWindow = new ExplorerWindow();
break;
case "Corrupted":
LK.getSound('error').play();
newWindow = new CorruptedWindow();
break;
case "CMD":
newWindow = new CommandPromptWindow();
break;
case "Chrome":
newWindow = new ChromeWindow();
break;
default:
newWindow = new Window(type, 600, 400);
}
// Position window - either from saved position or center
if (savedWindowPositions[type]) {
newWindow.x = savedWindowPositions[type].x;
newWindow.y = savedWindowPositions[type].y;
} else {
newWindow.x = (2048 - newWindow.width) / 2;
newWindow.y = (2732 - 50 - newWindow.height) / 2;
}
// Add Windows 98 style opening animation
newWindow.scale.x = 0.1;
newWindow.scale.y = 0.1;
// Add to active windows and game
activeWindows.push(newWindow);
game.addChild(newWindow);
// Animate window opening
tween(newWindow, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
// Set as drag target
dragTarget = newWindow;
// Close start menu if open
if (startMenuOpen) {
toggleStartMenu();
}
// Play sound
LK.getSound('click').play();
return newWindow;
}
function closeWindow(window) {
// Save position
savedWindowPositions[window.children[1].text] = {
x: window.x,
y: window.y
};
// Remove from active windows
var index = activeWindows.indexOf(window);
if (index > -1) {
activeWindows.splice(index, 1);
}
// Remove from game
game.removeChild(window);
window.destroy();
// Clear drag target if it was this window
if (dragTarget === window) {
dragTarget = null;
}
}
function minimizeWindow(window) {
// Just hide for now - in a real implementation we'd add a taskbar button
window.visible = false;
// Remove from active windows but don't destroy
var index = activeWindows.indexOf(window);
if (index > -1) {
activeWindows.splice(index, 1);
}
}
function getCurrentTime() {
var date = new Date();
var hours = date.getHours();
var minutes = date.getMinutes();
var ampm = hours >= 12 ? 'PM' : 'AM';
hours = hours % 12;
hours = hours ? hours : 12;
minutes = minutes < 10 ? '0' + minutes : minutes;
return hours + ':' + minutes + ' ' + ampm;
}
// Create mouse cursor
var mouseCursor = new MouseCursor();
game.addChild(mouseCursor);
// Check if cursor is over a clickable element
function updateCursorStyle() {
var isOverClickable = false;
// Check if over a desktop icon
for (var i = 0; i < game.children.length; i++) {
var child = game.children[i];
if (child instanceof DesktopIcon && lastMoveX >= child.x - 32 && lastMoveX <= child.x + 32 && lastMoveY >= child.y - 32 && lastMoveY <= child.y + 32) {
isOverClickable = true;
break;
}
}
// Check if over explorer items in open windows
for (var j = 0; j < activeWindows.length; j++) {
var window = activeWindows[j];
if (window instanceof ExplorerWindow) {
for (var k = 0; k < window.contentArea.children.length; k++) {
var item = window.contentArea.children[k];
if (item.interactive && lastMoveX >= window.x + window.contentArea.x + item.x && lastMoveX <= window.x + window.contentArea.x + item.x + 150 && lastMoveY >= window.y + window.contentArea.y + item.y && lastMoveY <= window.y + window.contentArea.y + item.y + 50) {
isOverClickable = true;
break;
}
}
}
}
// Update cursor style
mouseCursor.setPointer(isOverClickable);
}
// Extend game.move to update mouse cursor
var originalMove = game.move;
game.move = function (x, y) {
originalMove(x, y);
mouseCursor.updatePosition(x, y);
updateCursorStyle();
};
// Function to initialize desktop
function initializeDesktop() {
// Create the desktop background
var desktop = game.addChild(LK.getAsset('desktop', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732
}));
desktop.tint = 0x008080; // Windows 98 teal background
// Create the taskbar
var taskbar = game.addChild(LK.getAsset('taskbar', {
anchorX: 0,
anchorY: 1,
width: 2048,
height: 50
}));
taskbar.y = 2732;
taskbar.tint = 0xc0c0c0; // Windows 98 gray taskbar
// Create the start button
var startButton = game.addChild(LK.getAsset('startButton', {
anchorX: 0,
anchorY: 1,
width: 100,
height: 40
}));
startButton.x = 5;
startButton.y = 2732 - 5;
startButton.interactive = true;
startButton.tint = 0xc0c0c0; // Windows 98 gray start button
// Create the start menu
var startMenu = game.addChild(new StartMenu());
// Add "Start" text to start button
var startText = new Text2("Start", {
size: 24,
fill: 0x000000 //{g9} // Black text for Win98 start button
});
startText.x = 35;
startText.y = 2732 - 35;
game.addChild(startText);
// Create desktop icons
var icons = [{
name: "My Computer",
x: 100,
y: 100
}, {
name: "Recycle Bin",
x: 100,
y: 200
}, {
name: "Notepad",
x: 100,
y: 300
}, {
name: "Calculator",
x: 100,
y: 400
}, {
name: "Explorer",
x: 100,
y: 500
}, {
name: "Corrupted",
x: 100,
y: 600
}, {
name: "CMD",
x: 100,
y: 700
}, {
name: "Chrome",
x: 100,
y: 800
}];
icons.forEach(function (icon) {
var desktopIcon = new DesktopIcon(icon.name, icon.x, icon.y);
game.addChild(desktopIcon);
});
// Create time display in taskbar
var timeDisplay = new Text2(getCurrentTime(), {
size: 24,
fill: 0x000000
});
timeDisplay.anchor.set(1, 0.5);
timeDisplay.x = 2048 - 10;
timeDisplay.y = 2732 - 25;
game.addChild(timeDisplay);
// Create mouse cursor
var mouseCursor = new MouseCursor();
game.addChild(mouseCursor);
// Attach handlers
desktop.interactive = true;
desktop.down = function () {
if (startMenuOpen) {
toggleStartMenu();
}
};
startButton.down = function () {
startButton.alpha = 0.7;
LK.getSound('click').play();
};
startButton.up = function () {
startButton.alpha = 1;
toggleStartMenu();
};
}
// Play startup sound
LK.setTimeout(function () {
LK.getSound('startup').play();
}, 500);
;