/****
* 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);
;